|
@@ -18,16 +18,36 @@
|
|
|
package org.apache.ambari.server.controller.internal;
|
|
|
|
|
|
import org.apache.ambari.server.AmbariException;
|
|
|
+import org.apache.ambari.server.ClusterNotFoundException;
|
|
|
+import org.apache.ambari.server.DuplicateResourceException;
|
|
|
+import org.apache.ambari.server.ObjectNotFoundException;
|
|
|
+import org.apache.ambari.server.ParentObjectNotFoundException;
|
|
|
+import org.apache.ambari.server.ServiceComponentNotFoundException;
|
|
|
+import org.apache.ambari.server.ServiceNotFoundException;
|
|
|
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
|
|
|
import org.apache.ambari.server.controller.AmbariManagementController;
|
|
|
import org.apache.ambari.server.controller.RequestStatusResponse;
|
|
|
import org.apache.ambari.server.controller.ServiceComponentRequest;
|
|
|
import org.apache.ambari.server.controller.ServiceComponentResponse;
|
|
|
import org.apache.ambari.server.controller.spi.*;
|
|
|
import org.apache.ambari.server.controller.utilities.PropertyHelper;
|
|
|
-
|
|
|
+import org.apache.ambari.server.state.Cluster;
|
|
|
+import org.apache.ambari.server.state.Clusters;
|
|
|
+import org.apache.ambari.server.state.ComponentInfo;
|
|
|
+import org.apache.ambari.server.state.Config;
|
|
|
+import org.apache.ambari.server.state.Service;
|
|
|
+import org.apache.ambari.server.state.ServiceComponent;
|
|
|
+import org.apache.ambari.server.state.ServiceComponentFactory;
|
|
|
+import org.apache.ambari.server.state.ServiceComponentHost;
|
|
|
+import org.apache.ambari.server.state.StackId;
|
|
|
+import org.apache.ambari.server.state.State;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
+import java.util.Collection;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.HashSet;
|
|
|
+import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
|
|
@@ -40,11 +60,12 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
// ----- Property ID constants ---------------------------------------------
|
|
|
|
|
|
// Components
|
|
|
- protected static final String COMPONENT_CLUSTER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("ServiceComponentInfo", "cluster_name");
|
|
|
- protected static final String COMPONENT_SERVICE_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("ServiceComponentInfo", "service_name");
|
|
|
- protected static final String COMPONENT_COMPONENT_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("ServiceComponentInfo", "component_name");
|
|
|
- protected static final String COMPONENT_STATE_PROPERTY_ID = PropertyHelper.getPropertyId("ServiceComponentInfo", "state");
|
|
|
- protected static final String COMPONENT_DESIRED_CONFIGS_PROPERTY_ID = PropertyHelper.getPropertyId("ServiceComponentInfo", "desired_configs");
|
|
|
+ protected static final String COMPONENT_CLUSTER_NAME_PROPERTY_ID = "ServiceComponentInfo/cluster_name";
|
|
|
+ protected static final String COMPONENT_SERVICE_NAME_PROPERTY_ID = "ServiceComponentInfo/service_name";
|
|
|
+ protected static final String COMPONENT_COMPONENT_NAME_PROPERTY_ID = "ServiceComponentInfo/component_name";
|
|
|
+ protected static final String COMPONENT_STATE_PROPERTY_ID = "ServiceComponentInfo/state";
|
|
|
+ protected static final String COMPONENT_DESIRED_CONFIGS_PROPERTY_ID = "ServiceComponentInfo/desired_configs";
|
|
|
+ protected static final String COMPONENT_CATEGORY_PROPERTY_ID = "ServiceComponentInfo/category";
|
|
|
|
|
|
//Parameters from the predicate
|
|
|
private static final String QUERY_PARAMETERS_RUN_SMOKE_TEST_ID =
|
|
@@ -56,6 +77,7 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
COMPONENT_SERVICE_NAME_PROPERTY_ID,
|
|
|
COMPONENT_COMPONENT_NAME_PROPERTY_ID}));
|
|
|
|
|
|
+
|
|
|
// ----- Constructors ----------------------------------------------------
|
|
|
|
|
|
/**
|
|
@@ -71,6 +93,7 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
super(propertyIds, keyPropertyIds, managementController);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
// ----- ResourceProvider ------------------------------------------------
|
|
|
|
|
|
@Override
|
|
@@ -88,7 +111,7 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
createResources(new Command<Void>() {
|
|
|
@Override
|
|
|
public Void invoke() throws AmbariException {
|
|
|
- getManagementController().createComponents(requests);
|
|
|
+ createComponents(requests);
|
|
|
return null;
|
|
|
}
|
|
|
});
|
|
@@ -111,7 +134,7 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
Set<ServiceComponentResponse> responses = getResources(new Command<Set<ServiceComponentResponse>>() {
|
|
|
@Override
|
|
|
public Set<ServiceComponentResponse> invoke() throws AmbariException {
|
|
|
- return getManagementController().getComponents(requests);
|
|
|
+ return getComponents(requests);
|
|
|
}
|
|
|
});
|
|
|
|
|
@@ -127,6 +150,8 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
response.getDesiredState(), requestedIds);
|
|
|
setResourceProperty(resource, COMPONENT_DESIRED_CONFIGS_PROPERTY_ID,
|
|
|
response.getConfigVersions(), requestedIds);
|
|
|
+ setResourceProperty(resource, COMPONENT_CATEGORY_PROPERTY_ID, response.getCategory(), requestedIds);
|
|
|
+
|
|
|
resources.add(resource);
|
|
|
}
|
|
|
return resources;
|
|
@@ -154,13 +179,13 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
requests.add(compRequest);
|
|
|
}
|
|
|
|
|
|
- final boolean runSmokeTest = "true".equals(getQueryParameterValue(
|
|
|
- QUERY_PARAMETERS_RUN_SMOKE_TEST_ID, predicate)) ? true : false;
|
|
|
+ Object queryParameterValue = getQueryParameterValue(QUERY_PARAMETERS_RUN_SMOKE_TEST_ID, predicate);
|
|
|
+ final boolean runSmokeTest = queryParameterValue != null && queryParameterValue.equals("true");
|
|
|
|
|
|
RequestStatusResponse response = modifyResources(new Command<RequestStatusResponse>() {
|
|
|
@Override
|
|
|
public RequestStatusResponse invoke() throws AmbariException {
|
|
|
- return getManagementController().updateComponents(requests, request.getRequestInfoProperties(), runSmokeTest);
|
|
|
+ return updateComponents(requests, request.getRequestInfoProperties(), runSmokeTest);
|
|
|
}
|
|
|
});
|
|
|
|
|
@@ -173,15 +198,10 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
public RequestStatus deleteResources(Predicate predicate)
|
|
|
throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
|
|
|
|
|
|
- final Set<ServiceComponentRequest> requests = new HashSet<ServiceComponentRequest>();
|
|
|
- for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
|
|
|
- requests.add(getRequest(propertyMap));
|
|
|
- }
|
|
|
-
|
|
|
RequestStatusResponse response = modifyResources(new Command<RequestStatusResponse>() {
|
|
|
@Override
|
|
|
public RequestStatusResponse invoke() throws AmbariException {
|
|
|
- return getManagementController().deleteComponents(requests);
|
|
|
+ return deleteComponents();
|
|
|
}
|
|
|
});
|
|
|
|
|
@@ -189,13 +209,17 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
return getRequestStatus(response);
|
|
|
}
|
|
|
|
|
|
- // ----- utility methods -------------------------------------------------
|
|
|
+
|
|
|
+ // ----- AbstractResourceProvider ------------------------------------------
|
|
|
|
|
|
@Override
|
|
|
protected Set<String> getPKPropertyIds() {
|
|
|
return pkPropertyIds;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ // ----- utility methods ---------------------------------------------------
|
|
|
+
|
|
|
/**
|
|
|
* Get a component request object from a map of property values.
|
|
|
*
|
|
@@ -211,4 +235,605 @@ class ComponentResourceProvider extends AbstractControllerResourceProvider {
|
|
|
null,
|
|
|
(String) properties.get(COMPONENT_STATE_PROPERTY_ID));
|
|
|
}
|
|
|
-}
|
|
|
+
|
|
|
+ // Create the components for the given requests.
|
|
|
+ protected synchronized void createComponents(
|
|
|
+ Set<ServiceComponentRequest> requests) throws AmbariException {
|
|
|
+
|
|
|
+ if (requests.isEmpty()) {
|
|
|
+ LOG.warn("Received an empty requests set");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Clusters clusters = getManagementController().getClusters();
|
|
|
+ AmbariMetaInfo ambariMetaInfo = getManagementController().getAmbariMetaInfo();
|
|
|
+ ServiceComponentFactory serviceComponentFactory = getManagementController().getServiceComponentFactory();
|
|
|
+
|
|
|
+ // do all validation checks
|
|
|
+ Map<String, Map<String, Set<String>>> componentNames =
|
|
|
+ new HashMap<String, Map<String, Set<String>>>();
|
|
|
+ Set<String> duplicates = new HashSet<String>();
|
|
|
+
|
|
|
+ for (ServiceComponentRequest request : requests) {
|
|
|
+ if (request.getClusterName() == null
|
|
|
+ || request.getClusterName().isEmpty()
|
|
|
+ || request.getComponentName() == null
|
|
|
+ || request.getComponentName().isEmpty()) {
|
|
|
+ throw new IllegalArgumentException("Invalid arguments"
|
|
|
+ + ", clustername and componentname should be"
|
|
|
+ + " non-null and non-empty when trying to create a"
|
|
|
+ + " component");
|
|
|
+ }
|
|
|
+
|
|
|
+ Cluster cluster;
|
|
|
+ try {
|
|
|
+ cluster = clusters.getCluster(request.getClusterName());
|
|
|
+ } catch (ClusterNotFoundException e) {
|
|
|
+ throw new ParentObjectNotFoundException(
|
|
|
+ "Attempted to add a component to a cluster which doesn't exist:", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (request.getServiceName() == null
|
|
|
+ || request.getServiceName().isEmpty()) {
|
|
|
+ StackId stackId = cluster.getDesiredStackVersion();
|
|
|
+ String serviceName =
|
|
|
+ ambariMetaInfo.getComponentToService(stackId.getStackName(),
|
|
|
+ stackId.getStackVersion(), request.getComponentName());
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Looking up service name for component"
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", serviceName=" + serviceName);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (serviceName == null
|
|
|
+ || serviceName.isEmpty()) {
|
|
|
+ throw new AmbariException("Could not find service for component"
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", clusterName=" + cluster.getClusterName()
|
|
|
+ + ", stackInfo=" + stackId.getStackId());
|
|
|
+ }
|
|
|
+ request.setServiceName(serviceName);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Received a createComponent request"
|
|
|
+ + ", clusterName=" + request.getClusterName()
|
|
|
+ + ", serviceName=" + request.getServiceName()
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", request=" + request);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!componentNames.containsKey(request.getClusterName())) {
|
|
|
+ componentNames.put(request.getClusterName(),
|
|
|
+ new HashMap<String, Set<String>>());
|
|
|
+ }
|
|
|
+ if (!componentNames.get(request.getClusterName())
|
|
|
+ .containsKey(request.getServiceName())) {
|
|
|
+ componentNames.get(request.getClusterName()).put(
|
|
|
+ request.getServiceName(), new HashSet<String>());
|
|
|
+ }
|
|
|
+ if (componentNames.get(request.getClusterName())
|
|
|
+ .get(request.getServiceName()).contains(request.getComponentName())) {
|
|
|
+ // throw error later for dup
|
|
|
+ duplicates.add("[clusterName=" + request.getClusterName() + ", serviceName=" + request.getServiceName() +
|
|
|
+ ", componentName=" + request.getComponentName() + "]");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ componentNames.get(request.getClusterName())
|
|
|
+ .get(request.getServiceName()).add(request.getComponentName());
|
|
|
+
|
|
|
+ if (request.getDesiredState() != null
|
|
|
+ && !request.getDesiredState().isEmpty()) {
|
|
|
+ State state = State.valueOf(request.getDesiredState());
|
|
|
+ if (!state.isValidDesiredState()
|
|
|
+ || state != State.INIT) {
|
|
|
+ throw new IllegalArgumentException("Invalid desired state"
|
|
|
+ + " only INIT state allowed during creation"
|
|
|
+ + ", providedDesiredState=" + request.getDesiredState());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Service s;
|
|
|
+ try {
|
|
|
+ s = cluster.getService(request.getServiceName());
|
|
|
+ } catch (ServiceNotFoundException e) {
|
|
|
+ throw new ParentObjectNotFoundException(
|
|
|
+ "Attempted to add a component to a service which doesn't exist:", e);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ ServiceComponent sc = s.getServiceComponent(request.getComponentName());
|
|
|
+ if (sc != null) {
|
|
|
+ // throw error later for dup
|
|
|
+ duplicates.add("[clusterName=" + request.getClusterName() + ", serviceName=" + request.getServiceName() +
|
|
|
+ ", componentName=" + request.getComponentName() + "]");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ } catch (AmbariException e) {
|
|
|
+ // Expected
|
|
|
+ }
|
|
|
+
|
|
|
+ StackId stackId = s.getDesiredStackVersion();
|
|
|
+ if (!ambariMetaInfo.isValidServiceComponent(stackId.getStackName(),
|
|
|
+ stackId.getStackVersion(), s.getName(), request.getComponentName())) {
|
|
|
+ throw new IllegalArgumentException("Unsupported or invalid component"
|
|
|
+ + " in stack"
|
|
|
+ + ", clusterName=" + request.getClusterName()
|
|
|
+ + ", serviceName=" + request.getServiceName()
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", stackInfo=" + stackId.getStackId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ensure only a single cluster update
|
|
|
+ if (componentNames.size() != 1) {
|
|
|
+ throw new IllegalArgumentException("Invalid arguments, updates allowed"
|
|
|
+ + "on only one cluster at a time");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Validate dups
|
|
|
+ if (!duplicates.isEmpty()) {
|
|
|
+ StringBuilder names = new StringBuilder();
|
|
|
+ boolean first = true;
|
|
|
+ for (String cName : duplicates) {
|
|
|
+ if (!first) {
|
|
|
+ names.append(",");
|
|
|
+ }
|
|
|
+ first = false;
|
|
|
+ names.append(cName);
|
|
|
+ }
|
|
|
+ String msg;
|
|
|
+ if (duplicates.size() == 1) {
|
|
|
+ msg = "Attempted to create a component which already exists: ";
|
|
|
+ } else {
|
|
|
+ msg = "Attempted to create components which already exist: ";
|
|
|
+ }
|
|
|
+ throw new DuplicateResourceException(msg + names.toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ // now doing actual work
|
|
|
+ for (ServiceComponentRequest request : requests) {
|
|
|
+ Cluster cluster = clusters.getCluster(request.getClusterName());
|
|
|
+ Service s = cluster.getService(request.getServiceName());
|
|
|
+ ServiceComponent sc = serviceComponentFactory.createNew(s,
|
|
|
+ request.getComponentName());
|
|
|
+ sc.setDesiredStackVersion(s.getDesiredStackVersion());
|
|
|
+
|
|
|
+ if (request.getDesiredState() != null
|
|
|
+ && !request.getDesiredState().isEmpty()) {
|
|
|
+ State state = State.valueOf(request.getDesiredState());
|
|
|
+ sc.setDesiredState(state);
|
|
|
+ } else {
|
|
|
+ sc.setDesiredState(s.getDesiredState());
|
|
|
+ }
|
|
|
+
|
|
|
+ // FIXME fix config versions to configs conversion
|
|
|
+ Map<String, Config> configs = new HashMap<String, Config>();
|
|
|
+ if (request.getConfigVersions() != null) {
|
|
|
+ }
|
|
|
+
|
|
|
+ sc.updateDesiredConfigs(configs);
|
|
|
+ s.addServiceComponent(sc);
|
|
|
+ sc.persist();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the components for the given requests.
|
|
|
+ protected Set<ServiceComponentResponse> getComponents(
|
|
|
+ Set<ServiceComponentRequest> requests) throws AmbariException {
|
|
|
+ Set<ServiceComponentResponse> response =
|
|
|
+ new HashSet<ServiceComponentResponse>();
|
|
|
+ for (ServiceComponentRequest request : requests) {
|
|
|
+ try {
|
|
|
+ response.addAll(getComponents(request));
|
|
|
+ } catch (ServiceComponentNotFoundException e) {
|
|
|
+ if (requests.size() == 1) {
|
|
|
+ // only throw exception if 1 request.
|
|
|
+ // there will be > 1 request in case of OR predicate
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the components for the given request.
|
|
|
+ private synchronized Set<ServiceComponentResponse> getComponents(
|
|
|
+ ServiceComponentRequest request) throws AmbariException {
|
|
|
+ if (request.getClusterName() == null
|
|
|
+ || request.getClusterName().isEmpty()) {
|
|
|
+ throw new IllegalArgumentException("Invalid arguments, cluster name"
|
|
|
+ + " should be non-null");
|
|
|
+ }
|
|
|
+
|
|
|
+ Clusters clusters = getManagementController().getClusters();
|
|
|
+ AmbariMetaInfo ambariMetaInfo = getManagementController().getAmbariMetaInfo();
|
|
|
+
|
|
|
+ final Cluster cluster;
|
|
|
+ try {
|
|
|
+ cluster = clusters.getCluster(request.getClusterName());
|
|
|
+ } catch (ObjectNotFoundException e) {
|
|
|
+ throw new ParentObjectNotFoundException("Parent Cluster resource doesn't exist", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ Set<ServiceComponentResponse> response =
|
|
|
+ new HashSet<ServiceComponentResponse>();
|
|
|
+ String category;
|
|
|
+
|
|
|
+ StackId stackId = cluster.getDesiredStackVersion();
|
|
|
+
|
|
|
+ if (request.getComponentName() != null) {
|
|
|
+ if (request.getServiceName() == null) {
|
|
|
+ String serviceName =
|
|
|
+ ambariMetaInfo.getComponentToService(stackId.getStackName(),
|
|
|
+ stackId.getStackVersion(), request.getComponentName());
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Looking up service name for component"
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", serviceName=" + serviceName);
|
|
|
+ }
|
|
|
+ if (serviceName == null
|
|
|
+ || serviceName.isEmpty()) {
|
|
|
+ throw new AmbariException("Could not find service for component"
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", clusterName=" + cluster.getClusterName()
|
|
|
+ + ", stackInfo=" + stackId.getStackId());
|
|
|
+ }
|
|
|
+ request.setServiceName(serviceName);
|
|
|
+ }
|
|
|
+
|
|
|
+ final Service s;
|
|
|
+ try {
|
|
|
+ s = cluster.getService(request.getServiceName());
|
|
|
+ } catch (ObjectNotFoundException e) {
|
|
|
+ throw new ParentObjectNotFoundException("Parent Service resource doesn't exist", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ ServiceComponent sc = s.getServiceComponent(request.getComponentName());
|
|
|
+ ServiceComponentResponse serviceComponentResponse = sc.convertToResponse();
|
|
|
+
|
|
|
+
|
|
|
+ ComponentInfo componentInfo = ambariMetaInfo.getComponentCategory(stackId.getStackName(),
|
|
|
+ stackId.getStackVersion(), s.getName(), request.getComponentName());
|
|
|
+ if (componentInfo != null) {
|
|
|
+ category = componentInfo.getCategory();
|
|
|
+ if (category != null) {
|
|
|
+ serviceComponentResponse.setCategory(category);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ response.add(serviceComponentResponse);
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean checkDesiredState = false;
|
|
|
+ State desiredStateToCheck = null;
|
|
|
+ if (request.getDesiredState() != null
|
|
|
+ && !request.getDesiredState().isEmpty()) {
|
|
|
+ desiredStateToCheck = State.valueOf(request.getDesiredState());
|
|
|
+ if (!desiredStateToCheck.isValidDesiredState()) {
|
|
|
+ throw new IllegalArgumentException("Invalid arguments, invalid desired"
|
|
|
+ + " state, desiredState=" + desiredStateToCheck);
|
|
|
+ }
|
|
|
+ checkDesiredState = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ Set<Service> services = new HashSet<Service>();
|
|
|
+ if (request.getServiceName() != null
|
|
|
+ && !request.getServiceName().isEmpty()) {
|
|
|
+ services.add(cluster.getService(request.getServiceName()));
|
|
|
+ } else {
|
|
|
+ services.addAll(cluster.getServices().values());
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Service s : services) {
|
|
|
+ // filter on request.getDesiredState()
|
|
|
+ for (ServiceComponent sc : s.getServiceComponents().values()) {
|
|
|
+ if (checkDesiredState
|
|
|
+ && (desiredStateToCheck != sc.getDesiredState())) {
|
|
|
+ // skip non matching state
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ ComponentInfo componentInfo = ambariMetaInfo.getComponentCategory(stackId.getStackName(),
|
|
|
+ stackId.getStackVersion(), s.getName(), sc.getName());
|
|
|
+ ServiceComponentResponse serviceComponentResponse = sc.convertToResponse();
|
|
|
+ if (componentInfo != null) {
|
|
|
+ category = componentInfo.getCategory();
|
|
|
+ if (category != null) {
|
|
|
+ serviceComponentResponse.setCategory(category);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ response.add(serviceComponentResponse);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update the components for the given requests.
|
|
|
+ protected synchronized RequestStatusResponse updateComponents(Set<ServiceComponentRequest> requests,
|
|
|
+ Map<String, String> requestProperties, boolean runSmokeTest)
|
|
|
+ throws AmbariException {
|
|
|
+
|
|
|
+ if (requests.isEmpty()) {
|
|
|
+ LOG.warn("Received an empty requests set");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ Clusters clusters = getManagementController().getClusters();
|
|
|
+ AmbariMetaInfo ambariMetaInfo = getManagementController().getAmbariMetaInfo();
|
|
|
+
|
|
|
+ Map<State, List<ServiceComponent>> changedComps =
|
|
|
+ new HashMap<State, List<ServiceComponent>>();
|
|
|
+ Map<String, Map<State, List<ServiceComponentHost>>> changedScHosts =
|
|
|
+ new HashMap<String, Map<State, List<ServiceComponentHost>>>();
|
|
|
+ Collection<ServiceComponentHost> ignoredScHosts =
|
|
|
+ new ArrayList<ServiceComponentHost>();
|
|
|
+
|
|
|
+ Set<String> clusterNames = new HashSet<String>();
|
|
|
+ Map<String, Map<String, Set<String>>> componentNames =
|
|
|
+ new HashMap<String, Map<String,Set<String>>>();
|
|
|
+ Set<State> seenNewStates = new HashSet<State>();
|
|
|
+
|
|
|
+ for (ServiceComponentRequest request : requests) {
|
|
|
+ if (request.getClusterName() == null
|
|
|
+ || request.getClusterName().isEmpty()
|
|
|
+ || request.getComponentName() == null
|
|
|
+ || request.getComponentName().isEmpty()) {
|
|
|
+ throw new IllegalArgumentException("Invalid arguments, cluster name"
|
|
|
+ + ", service name and component name should be provided to"
|
|
|
+ + " update components");
|
|
|
+ }
|
|
|
+
|
|
|
+ LOG.info("Received a updateComponent request"
|
|
|
+ + ", clusterName=" + request.getClusterName()
|
|
|
+ + ", serviceName=" + request.getServiceName()
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", request=" + request.toString());
|
|
|
+
|
|
|
+ Cluster cluster = clusters.getCluster(request.getClusterName());
|
|
|
+
|
|
|
+ if (request.getServiceName() == null
|
|
|
+ || request.getServiceName().isEmpty()) {
|
|
|
+ StackId stackId = cluster.getDesiredStackVersion();
|
|
|
+ String serviceName =
|
|
|
+ ambariMetaInfo.getComponentToService(stackId.getStackName(),
|
|
|
+ stackId.getStackVersion(), request.getComponentName());
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Looking up service name for component"
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", serviceName=" + serviceName);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (serviceName == null
|
|
|
+ || serviceName.isEmpty()) {
|
|
|
+ throw new AmbariException("Could not find service for component"
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", clusterName=" + cluster.getClusterName()
|
|
|
+ + ", stackInfo=" + stackId.getStackId());
|
|
|
+ }
|
|
|
+ request.setServiceName(serviceName);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Received a updateComponent request"
|
|
|
+ + ", clusterName=" + request.getClusterName()
|
|
|
+ + ", serviceName=" + request.getServiceName()
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", request=" + request);
|
|
|
+ }
|
|
|
+
|
|
|
+ clusterNames.add(request.getClusterName());
|
|
|
+
|
|
|
+ if (clusterNames.size() > 1) {
|
|
|
+ // FIXME throw correct error
|
|
|
+ throw new IllegalArgumentException("Updates to multiple clusters is not"
|
|
|
+ + " supported");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!componentNames.containsKey(request.getClusterName())) {
|
|
|
+ componentNames.put(request.getClusterName(),
|
|
|
+ new HashMap<String, Set<String>>());
|
|
|
+ }
|
|
|
+ if (!componentNames.get(request.getClusterName())
|
|
|
+ .containsKey(request.getServiceName())) {
|
|
|
+ componentNames.get(request.getClusterName()).put(
|
|
|
+ request.getServiceName(), new HashSet<String>());
|
|
|
+ }
|
|
|
+ if (componentNames.get(request.getClusterName())
|
|
|
+ .get(request.getServiceName()).contains(request.getComponentName())){
|
|
|
+ // throw error later for dup
|
|
|
+ throw new IllegalArgumentException("Invalid request contains duplicate"
|
|
|
+ + " service components");
|
|
|
+ }
|
|
|
+ componentNames.get(request.getClusterName())
|
|
|
+ .get(request.getServiceName()).add(request.getComponentName());
|
|
|
+
|
|
|
+ Service s = cluster.getService(request.getServiceName());
|
|
|
+ ServiceComponent sc = s.getServiceComponent(
|
|
|
+ request.getComponentName());
|
|
|
+ State newState = null;
|
|
|
+ if (request.getDesiredState() != null) {
|
|
|
+ newState = State.valueOf(request.getDesiredState());
|
|
|
+ if (!newState.isValidDesiredState()) {
|
|
|
+ throw new IllegalArgumentException("Invalid arguments, invalid"
|
|
|
+ + " desired state, desiredState=" + newState.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (request.getConfigVersions() != null) {
|
|
|
+ State.checkUpdateConfiguration(sc, newState);
|
|
|
+
|
|
|
+ for (Map.Entry<String,String> entry :
|
|
|
+ request.getConfigVersions().entrySet()) {
|
|
|
+ Config config = cluster.getConfig(
|
|
|
+ entry.getKey(), entry.getValue());
|
|
|
+ if (null == config) {
|
|
|
+ // throw error for invalid config
|
|
|
+ throw new AmbariException("Trying to update servicecomponent with"
|
|
|
+ + " invalid configs"
|
|
|
+ + ", clusterName=" + cluster.getClusterName()
|
|
|
+ + ", clusterId=" + cluster.getClusterId()
|
|
|
+ + ", serviceName=" + s.getName()
|
|
|
+ + ", componentName=" + sc.getName()
|
|
|
+ + ", invalidConfigType=" + entry.getKey()
|
|
|
+ + ", invalidConfigTag=" + entry.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (newState == null) {
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Nothing to do for new updateServiceComponent request"
|
|
|
+ + ", clusterName=" + request.getClusterName()
|
|
|
+ + ", serviceName=" + request.getServiceName()
|
|
|
+ + ", componentName=" + request.getComponentName()
|
|
|
+ + ", newDesiredState=null");
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sc.isClientComponent() &&
|
|
|
+ !newState.isValidClientComponentState()) {
|
|
|
+ throw new AmbariException("Invalid desired state for a client"
|
|
|
+ + " component");
|
|
|
+ }
|
|
|
+
|
|
|
+ seenNewStates.add(newState);
|
|
|
+
|
|
|
+ State oldScState = sc.getDesiredState();
|
|
|
+ if (newState != oldScState) {
|
|
|
+ if (!State.isValidDesiredStateTransition(oldScState, newState)) {
|
|
|
+ // FIXME throw correct error
|
|
|
+ throw new AmbariException("Invalid transition for"
|
|
|
+ + " servicecomponent"
|
|
|
+ + ", clusterName=" + cluster.getClusterName()
|
|
|
+ + ", clusterId=" + cluster.getClusterId()
|
|
|
+ + ", serviceName=" + sc.getServiceName()
|
|
|
+ + ", componentName=" + sc.getName()
|
|
|
+ + ", currentDesiredState=" + oldScState
|
|
|
+ + ", newDesiredState=" + newState);
|
|
|
+ }
|
|
|
+ if (!changedComps.containsKey(newState)) {
|
|
|
+ changedComps.put(newState, new ArrayList<ServiceComponent>());
|
|
|
+ }
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Handling update to ServiceComponent"
|
|
|
+ + ", clusterName=" + request.getClusterName()
|
|
|
+ + ", serviceName=" + s.getName()
|
|
|
+ + ", componentName=" + sc.getName()
|
|
|
+ + ", currentDesiredState=" + oldScState
|
|
|
+ + ", newDesiredState=" + newState);
|
|
|
+ }
|
|
|
+ changedComps.get(newState).add(sc);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (ServiceComponentHost sch : sc.getServiceComponentHosts().values()) {
|
|
|
+ State oldSchState = sch.getState();
|
|
|
+ if (oldSchState == State.MAINTENANCE || oldSchState == State.UNKNOWN) {
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Ignoring ServiceComponentHost"
|
|
|
+ + ", clusterName=" + request.getClusterName()
|
|
|
+ + ", serviceName=" + s.getName()
|
|
|
+ + ", componentName=" + sc.getName()
|
|
|
+ + ", hostname=" + sch.getHostName()
|
|
|
+ + ", currentState=" + oldSchState
|
|
|
+ + ", newDesiredState=" + newState);
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (newState == oldSchState) {
|
|
|
+ ignoredScHosts.add(sch);
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Ignoring ServiceComponentHost"
|
|
|
+ + ", clusterName=" + request.getClusterName()
|
|
|
+ + ", serviceName=" + s.getName()
|
|
|
+ + ", componentName=" + sc.getName()
|
|
|
+ + ", hostname=" + sch.getHostName()
|
|
|
+ + ", currentState=" + oldSchState
|
|
|
+ + ", newDesiredState=" + newState);
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (!State.isValidStateTransition(oldSchState, newState)) {
|
|
|
+ // FIXME throw correct error
|
|
|
+ throw new AmbariException("Invalid transition for"
|
|
|
+ + " servicecomponenthost"
|
|
|
+ + ", clusterName=" + cluster.getClusterName()
|
|
|
+ + ", clusterId=" + cluster.getClusterId()
|
|
|
+ + ", serviceName=" + sch.getServiceName()
|
|
|
+ + ", componentName=" + sch.getServiceComponentName()
|
|
|
+ + ", hostname=" + sch.getHostName()
|
|
|
+ + ", currentState=" + oldSchState
|
|
|
+ + ", newDesiredState=" + newState);
|
|
|
+ }
|
|
|
+ if (!changedScHosts.containsKey(sc.getName())) {
|
|
|
+ changedScHosts.put(sc.getName(),
|
|
|
+ new HashMap<State, List<ServiceComponentHost>>());
|
|
|
+ }
|
|
|
+ if (!changedScHosts.get(sc.getName()).containsKey(newState)) {
|
|
|
+ changedScHosts.get(sc.getName()).put(newState,
|
|
|
+ new ArrayList<ServiceComponentHost>());
|
|
|
+ }
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("Handling update to ServiceComponentHost"
|
|
|
+ + ", clusterName=" + request.getClusterName()
|
|
|
+ + ", serviceName=" + s.getName()
|
|
|
+ + ", componentName=" + sc.getName()
|
|
|
+ + ", hostname=" + sch.getHostName()
|
|
|
+ + ", currentState=" + oldSchState
|
|
|
+ + ", newDesiredState=" + newState);
|
|
|
+ }
|
|
|
+ changedScHosts.get(sc.getName()).get(newState).add(sch);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (seenNewStates.size() > 1) {
|
|
|
+ // FIXME should we handle this scenario
|
|
|
+ throw new IllegalArgumentException("Cannot handle different desired"
|
|
|
+ + " state changes for a set of service components at the same time");
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO additional validation?
|
|
|
+
|
|
|
+ // TODO if all components reach a common state, should service state be
|
|
|
+ // modified?
|
|
|
+
|
|
|
+ for (ServiceComponentRequest request : requests) {
|
|
|
+ Cluster cluster = clusters.getCluster(request.getClusterName());
|
|
|
+ Service s = cluster.getService(request.getServiceName());
|
|
|
+ ServiceComponent sc = s.getServiceComponent(
|
|
|
+ request.getComponentName());
|
|
|
+ if (request.getConfigVersions() != null) {
|
|
|
+ Map<String, Config> updated = new HashMap<String, Config>();
|
|
|
+
|
|
|
+ for (Map.Entry<String,String> entry :
|
|
|
+ request.getConfigVersions().entrySet()) {
|
|
|
+ Config config = cluster.getConfig(
|
|
|
+ entry.getKey(), entry.getValue());
|
|
|
+ updated.put(config.getType(), config);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!updated.isEmpty()) {
|
|
|
+ sc.updateDesiredConfigs(updated);
|
|
|
+ for (ServiceComponentHost sch :
|
|
|
+ sc.getServiceComponentHosts().values()) {
|
|
|
+ sch.deleteDesiredConfigs(updated.keySet());
|
|
|
+ sch.persist();
|
|
|
+ }
|
|
|
+ sc.persist();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Cluster cluster = clusters.getCluster(clusterNames.iterator().next());
|
|
|
+
|
|
|
+ return getManagementController().createStages(cluster, requestProperties, null, null, changedComps, changedScHosts,
|
|
|
+ ignoredScHosts, runSmokeTest, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Delete the components for the given request.
|
|
|
+ protected RequestStatusResponse deleteComponents() throws AmbariException {
|
|
|
+ throw new AmbariException("Delete components not supported");
|
|
|
+ }
|
|
|
+}
|