/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ambari.server.controller.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.RoleCommand;
import org.apache.ambari.server.actionmanager.ActionManager;
import org.apache.ambari.server.actionmanager.HostRoleCommand;
import org.apache.ambari.server.actionmanager.Request;
import org.apache.ambari.server.actionmanager.RequestFactory;
import org.apache.ambari.server.actionmanager.Stage;
import org.apache.ambari.server.controller.ExecuteActionRequest;
import org.apache.ambari.server.controller.RequestStatusResponse;
import org.apache.ambari.server.controller.ShortTaskStatus;
import org.apache.ambari.server.state.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Contains stages associated with a request.
*/
public class RequestStageContainer {
/**
* Request id
*/
private Long id;
/**
* Request stages
*/
private List<Stage> stages;
/**
* Request Factory used to create Request instance
*/
private RequestFactory requestFactory;
/**
* Action Manager
*/
private ActionManager actionManager;
private String requestContext = null;
private ExecuteActionRequest actionRequest = null;
private String clusterHostInfo = null;
/**
* Logger
*/
private final static Logger LOG =
LoggerFactory.getLogger(RequestStageContainer.class);
/**
* Constructor.
*
* @param id request id
* @param stages stages
* @param factory request factory
* @param manager action manager
*/
public RequestStageContainer(Long id, List<Stage> stages, RequestFactory factory, ActionManager manager) {
this(id, stages, factory, manager, null);
}
/**
* Constructor.
*
* @param id request id
* @param stages stages
* @param factory request factory
* @param manager action manager
* @param actionRequest action request
*/
public RequestStageContainer(Long id, List<Stage> stages, RequestFactory factory, ActionManager manager,
ExecuteActionRequest actionRequest) {
this.id = id;
this.stages = stages == null ? new ArrayList<Stage>() : stages;
this.requestFactory = factory;
this.actionManager = manager;
this.actionRequest = actionRequest;
this.clusterHostInfo = "{}";
}
/**
* Get the request id.
*
* @return request id
*/
public Long getId() {
return id;
}
public void setClusterHostInfo(String clusterHostInfo){
this.clusterHostInfo = clusterHostInfo;
}
/**
* Add stages to request.
*
* @param stages stages to add
*/
public void addStages(List<Stage> stages) {
if (stages != null) {
this.stages.addAll(stages);
}
}
/**
* Get request stages.
*
* @return list of stages
*/
public List<Stage> getStages() {
return stages;
}
/**
* Get the stage id of the last stage.
*
* @return stage id of the last stage or -1 if no stages present
*/
public long getLastStageId() {
return stages.isEmpty() ? -1 : stages.get(stages.size() - 1).getStageId();
}
/**
* Sets the context for the request (optional operation)
*
* @param context the new context
*/
public void setRequestContext(String context) {
requestContext = context;
}
/**
* Determine the projected state for a host component from the existing stages.
*
* @param host host name
* @param component component name
*
* @return the projected state of a host component after all stages successfully complete
* or null if the host component state is not modified in the current stages
*/
public State getProjectedState(String host, String component) {
RoleCommand lastCommand = null;
ListIterator<Stage> iterator = stages.listIterator(stages.size());
while (lastCommand == null && iterator.hasPrevious()) {
Stage stage = iterator.previous();
Map<String, Map<String, HostRoleCommand>> stageCommands = stage.getHostRoleCommands();
if (stageCommands != null) {
Map<String, HostRoleCommand> hostCommands = stageCommands.get(host);
if (hostCommands != null) {
HostRoleCommand roleCommand = hostCommands.get(component);
if (roleCommand != null && roleCommand.getRoleCommand() != RoleCommand.SERVICE_CHECK) {
lastCommand = roleCommand.getRoleCommand();
}
}
}
}
State resultingState = null;
if (lastCommand != null) {
switch(lastCommand) {
case INSTALL:
case STOP:
resultingState = State.INSTALLED;
break;
case START:
resultingState = State.STARTED;
break;
case UNINSTALL:
resultingState = State.INIT;
break;
default:
resultingState = State.UNKNOWN;
}
}
return resultingState;
}
/**
* Persist the stages.
*/
public void persist() throws AmbariException {
if (!stages.isEmpty()) {
Request request = (null == actionRequest)
? requestFactory.createNewFromStages(stages, clusterHostInfo)
: requestFactory.createNewFromStages(stages, clusterHostInfo, actionRequest);
if (null != requestContext) {
request.setRequestContext(requestContext);
}
if (request != null && request.getStages()!= null && !request.getStages().isEmpty()) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Triggering Action Manager, request=%s", request));
}
actionManager.sendActions(request, actionRequest);
}
}
}
/**
* Build a request status response.
*
* @return a {@link org.apache.ambari.server.controller.RequestStatusResponse} for the request
*/
public RequestStatusResponse getRequestStatusResponse() {
RequestStatusResponse response = null;
if (! stages.isEmpty()) {
response = new RequestStatusResponse(id);
List<HostRoleCommand> hostRoleCommands =
actionManager.getRequestTasks(id);
response.setRequestContext(actionManager.getRequestContext(id));
List<ShortTaskStatus> tasks = new ArrayList<>();
for (HostRoleCommand hostRoleCommand : hostRoleCommands) {
tasks.add(new ShortTaskStatus(hostRoleCommand));
}
response.setTasks(tasks);
}
return response;
}
}