http://git-wip-us.apache.org/repos/asf/ambari/blob/c9f0dd0b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java index 03acd40..aab5395 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java @@ -30,7 +30,6 @@ import java.util.Set; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.DuplicateResourceException; -import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.controller.spi.NoSuchParentResourceException; import org.apache.ambari.server.controller.spi.NoSuchResourceException; @@ -43,16 +42,16 @@ import org.apache.ambari.server.controller.spi.SystemException; import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; import org.apache.ambari.server.controller.utilities.PropertyHelper; import org.apache.ambari.server.orm.dao.BlueprintDAO; -import org.apache.ambari.server.orm.dao.StackDAO; import org.apache.ambari.server.orm.entities.BlueprintConfigEntity; import org.apache.ambari.server.orm.entities.BlueprintConfiguration; import org.apache.ambari.server.orm.entities.BlueprintEntity; import org.apache.ambari.server.orm.entities.HostGroupComponentEntity; -import org.apache.ambari.server.orm.entities.HostGroupConfigEntity; import org.apache.ambari.server.orm.entities.HostGroupEntity; import org.apache.ambari.server.orm.entities.StackEntity; -import org.apache.ambari.server.state.ComponentInfo; -import org.apache.ambari.server.state.ServiceInfo; +import org.apache.ambari.server.stack.NoSuchStackException; +import org.apache.ambari.server.topology.Blueprint; +import org.apache.ambari.server.topology.BlueprintFactory; +import org.apache.ambari.server.topology.InvalidTopologyException; import com.google.gson.Gson; @@ -60,32 +59,32 @@ import com.google.gson.Gson; /** * Resource Provider for Blueprint resources. */ -public class BlueprintResourceProvider extends BaseBlueprintProcessor { +public class BlueprintResourceProvider extends AbstractControllerResourceProvider { // ----- Property ID constants --------------------------------------------- // Blueprints - protected static final String BLUEPRINT_NAME_PROPERTY_ID = + public static final String BLUEPRINT_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("Blueprints", "blueprint_name"); - protected static final String STACK_NAME_PROPERTY_ID = + public static final String STACK_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("Blueprints", "stack_name"); - protected static final String STACK_VERSION_PROPERTY_ID = + public static final String STACK_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("Blueprints", "stack_version"); // Host Groups - protected static final String HOST_GROUP_PROPERTY_ID = "host_groups"; - protected static final String HOST_GROUP_NAME_PROPERTY_ID = "name"; - protected static final String HOST_GROUP_CARDINALITY_PROPERTY_ID = "cardinality"; + public static final String HOST_GROUP_PROPERTY_ID = "host_groups"; + public static final String HOST_GROUP_NAME_PROPERTY_ID = "name"; + public static final String HOST_GROUP_CARDINALITY_PROPERTY_ID = "cardinality"; // Host Group Components - protected static final String COMPONENT_PROPERTY_ID ="components"; - protected static final String COMPONENT_NAME_PROPERTY_ID ="name"; + public static final String COMPONENT_PROPERTY_ID ="components"; + public static final String COMPONENT_NAME_PROPERTY_ID ="name"; // Configurations - protected static final String CONFIGURATION_PROPERTY_ID = "configurations"; - protected static final String PROPERTIES_PROPERTY_ID = "properties"; - protected static final String PROPERTIES_ATTRIBUTES_PROPERTY_ID = "properties_attributes"; - protected static final String SCHEMA_IS_NOT_SUPPORTED_MESSAGE = + public static final String CONFIGURATION_PROPERTY_ID = "configurations"; + public static final String PROPERTIES_PROPERTY_ID = "properties"; + public static final String PROPERTIES_ATTRIBUTES_PROPERTY_ID = "properties_attributes"; + public static final String SCHEMA_IS_NOT_SUPPORTED_MESSAGE = "Configuration format provided in Blueprint is not supported"; // Primary Key Fields @@ -94,6 +93,16 @@ public class BlueprintResourceProvider extends BaseBlueprintProcessor { BLUEPRINT_NAME_PROPERTY_ID})); /** + * Used to create Blueprint instances + */ + private static BlueprintFactory blueprintFactory; + + /** + * Blueprint Data Access Object + */ + private static BlueprintDAO blueprintDAO; + + /** * Used to serialize to/from json. */ private static Gson jsonSerializer; @@ -118,19 +127,14 @@ public class BlueprintResourceProvider extends BaseBlueprintProcessor { /** * Static initialization. * - * @param dao - * blueprint data access object - * @param gson - * json serializer - * @param metaInfo - * stack related information + * @param factory blueprint factory + * @param dao blueprint data access object + * @param gson json serializer */ - public static void init(BlueprintDAO dao, StackDAO stacks, Gson gson, - AmbariMetaInfo metaInfo) { + public static void init(BlueprintFactory factory, BlueprintDAO dao, Gson gson) { + blueprintFactory = factory; blueprintDAO = dao; - stackDAO = stacks; jsonSerializer = gson; - stackInfo = metaInfo; } // ----- ResourceProvider ------------------------------------------------ @@ -154,6 +158,7 @@ public class BlueprintResourceProvider extends BaseBlueprintProcessor { } @Override + //todo: continue to use dao/entity directly or use blueprint factory? public Set<Resource> getResources(Request request, Predicate predicate) throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { @@ -278,172 +283,6 @@ public class BlueprintResourceProvider extends BaseBlueprintProcessor { } /** - * Convert a map of properties to a blueprint entity. - * - * @param properties property map - * @return new blueprint entity - */ - @SuppressWarnings("unchecked") - protected BlueprintEntity toBlueprintEntity(Map<String, Object> properties) { - String name = (String) properties.get(BLUEPRINT_NAME_PROPERTY_ID); - if (name == null || name.isEmpty()) { - throw new IllegalArgumentException("Blueprint name must be provided"); - } - - String stackName = (String) properties.get(STACK_NAME_PROPERTY_ID); - String stackVersion = (String) properties.get(STACK_VERSION_PROPERTY_ID); - StackEntity stackEntity = stackDAO.find(stackName, stackVersion); - - BlueprintEntity blueprint = new BlueprintEntity(); - blueprint.setBlueprintName(name); - blueprint.setStack(stackEntity); - - createHostGroupEntities(blueprint, - (HashSet<HashMap<String, Object>>) properties.get(HOST_GROUP_PROPERTY_ID)); - - createBlueprintConfigEntities((Collection<Map<String, String>>) - properties.get(CONFIGURATION_PROPERTY_ID), blueprint); - - return blueprint; - } - - /** - * Create host group entities and add to the parent blueprint entity. - * - * @param blueprint parent blueprint entity - * @param setHostGroups set of host group property maps - */ - @SuppressWarnings("unchecked") - private void createHostGroupEntities(BlueprintEntity blueprint, - HashSet<HashMap<String, Object>> setHostGroups) { - - if (setHostGroups == null || setHostGroups.isEmpty()) { - throw new IllegalArgumentException("At least one host group must be specified in a blueprint"); - } - - Collection<HostGroupEntity> entities = new ArrayList<HostGroupEntity>(); - - StackEntity stackEntity = blueprint.getStack(); - - Collection<String> stackComponentNames = getAllStackComponents( - stackEntity.getStackName(), stackEntity.getStackVersion()); - - for (HashMap<String, Object> hostGroupProperties : setHostGroups) { - HostGroupEntity hostGroup = new HostGroupEntity(); - entities.add(hostGroup); - - String hostGroupName = (String) hostGroupProperties.get(HOST_GROUP_NAME_PROPERTY_ID); - if (hostGroupName == null || hostGroupName.isEmpty()) { - throw new IllegalArgumentException("Every host group must include a non-null 'name' property"); - } - - hostGroup.setName(hostGroupName); - hostGroup.setBlueprintEntity(blueprint); - hostGroup.setBlueprintName(blueprint.getBlueprintName()); - hostGroup.setCardinality((String) hostGroupProperties.get(HOST_GROUP_CARDINALITY_PROPERTY_ID)); - - createHostGroupConfigEntities((Collection<Map<String, - String>>) hostGroupProperties.get(CONFIGURATION_PROPERTY_ID), hostGroup); - - createComponentEntities(hostGroup, (HashSet<HashMap<String, String>>) - hostGroupProperties.get(COMPONENT_PROPERTY_ID), stackComponentNames); - } - blueprint.setHostGroups(entities); - } - - /** - * Create component entities and add to parent host group. - * - * @param group parent host group - * @param setComponents set of component property maps - * @param componentNames set of all component names for the associated stack - */ - @SuppressWarnings("unchecked") - private void createComponentEntities(HostGroupEntity group, HashSet<HashMap<String, String>> setComponents, - Collection<String> componentNames) { - - Collection<HostGroupComponentEntity> components = new ArrayList<HostGroupComponentEntity>(); - String groupName = group.getName(); - group.setComponents(components); - - if (setComponents == null || setComponents.isEmpty()) { - throw new IllegalArgumentException("Host group '" + groupName + "' must contain at least one component"); - } - - for (HashMap<String, String> componentProperties : setComponents) { - HostGroupComponentEntity component = new HostGroupComponentEntity(); - components.add(component); - - String componentName = componentProperties.get(COMPONENT_NAME_PROPERTY_ID); - if (componentName == null || componentName.isEmpty()) { - throw new IllegalArgumentException("Host group '" + groupName + - "' contains a component with no 'name' property"); - } - - if (! componentNames.contains(componentName)) { - throw new IllegalArgumentException("The component '" + componentName + "' in host group '" + - groupName + "' is not valid for the specified stack"); - } - - component.setName(componentName); - component.setBlueprintName(group.getBlueprintName()); - component.setHostGroupEntity(group); - component.setHostGroupName(group.getName()); - } - group.setComponents(components); - } - - /** - * Obtain all component names for the specified stack. - * - * @param stackName stack name - * @param stackVersion stack version - * - * @return collection of component names for the specified stack - * @throws IllegalArgumentException if the specified stack doesn't exist - */ - private Collection<String> getAllStackComponents(String stackName, String stackVersion) { - Collection<String> componentNames = new HashSet<String>(); - componentNames.add("AMBARI_SERVER"); - Collection<ComponentInfo> components; - try { - components = getComponents(stackName, stackVersion); - } catch (AmbariException e) { - throw new IllegalArgumentException("The specified stack doesn't exist. Name='" + - stackName + "', Version='" + stackVersion + "'"); - } - if (components != null) { - for (ComponentInfo component : components) { - componentNames.add(component.getName()); - } - } - return componentNames; - } - - /** - * Get all the components for the specified stack. - * - * @param stackName stack name - * @param version stack version - * - * @return all components for the specified stack - * @throws AmbariException if the stack doesn't exist - */ - private Collection<ComponentInfo> getComponents(String stackName, String version) throws AmbariException { - Collection<ComponentInfo> components = new HashSet<ComponentInfo>(); - Map<String, ServiceInfo> services = stackInfo.getServices(stackName, version); - - for (ServiceInfo service : services.values()) { - List<ComponentInfo> serviceComponents = stackInfo.getComponentsByService( - stackName, version, service.getName()); - for (ComponentInfo component : serviceComponents) { - components.add(component); - } - } - return components; - } - - /** * Populate a list of configuration property maps from a collection of configuration entities. * * @param configurations collection of configuration entities @@ -495,28 +334,6 @@ public class BlueprintResourceProvider extends BaseBlueprintProcessor { blueprint.setConfigurations(configurations); } - /** - * Populate host group configurations. - * - * @param propertyMaps collection of configuration property maps - * @param hostGroup host group entity to set configurations on - */ - private void createHostGroupConfigEntities(Collection<Map<String, String>> propertyMaps, - HostGroupEntity hostGroup) { - - Collection<HostGroupConfigEntity> configurations = new ArrayList<HostGroupConfigEntity>(); - if (propertyMaps != null) { - for (Map<String, String> configuration : propertyMaps) { - HostGroupConfigEntity configEntity = new HostGroupConfigEntity(); - configEntity.setHostGroupEntity(hostGroup); - configEntity.setHostGroupName(hostGroup.getName()); - configEntity.setBlueprintName(hostGroup.getBlueprintName()); - populateConfigurationEntity(configuration, configEntity); - configurations.add(configEntity); - } - } - hostGroup.setConfigurations(configurations); - } /** * Populate a configuration entity from properties. @@ -560,31 +377,39 @@ public class BlueprintResourceProvider extends BaseBlueprintProcessor { return new Command<Void>() { @Override public Void invoke() throws AmbariException { - BlueprintEntity blueprint = toBlueprintEntity(properties); + Blueprint blueprint; + try { + blueprint = blueprintFactory.createBlueprint(properties); + } catch (NoSuchStackException e) { + throw new IllegalArgumentException("Specified stack doesn't exist: " + e, e); + } - if (blueprintDAO.findByName(blueprint.getBlueprintName()) != null) { + if (blueprintDAO.findByName(blueprint.getName()) != null) { throw new DuplicateResourceException( "Attempted to create a Blueprint which already exists, blueprint_name=" + - blueprint.getBlueprintName()); + blueprint.getName()); } - Map<String, Map<String, Collection<String>>> missingProperties = blueprint.validateConfigurations( - stackInfo, false); - if (! missingProperties.isEmpty()) { - throw new IllegalArgumentException("Required configurations are missing from the specified host groups: " + - missingProperties); + try { + blueprint.validateRequiredProperties(); + } catch (InvalidTopologyException e) { + throw new IllegalArgumentException("Blueprint configuration validation failed: " + e.getMessage(), e); } String validateTopology = requestInfoProps.get("validate_topology"); if (validateTopology == null || ! validateTopology.equalsIgnoreCase("false")) { - validateTopology(blueprint); + try { + blueprint.validateTopology(); + } catch (InvalidTopologyException e) { + throw new IllegalArgumentException(e.getMessage()); + } } if (LOG.isDebugEnabled()) { - LOG.debug("Creating Blueprint, name=" + blueprint.getBlueprintName()); + LOG.debug("Creating Blueprint, name=" + blueprint.getName()); } try { - blueprintDAO.create(blueprint); + blueprintDAO.create(blueprint.toEntity()); } catch (Exception e) { throw new RuntimeException(e); }
http://git-wip-us.apache.org/repos/asf/ambari/blob/c9f0dd0b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Cardinality.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Cardinality.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Cardinality.java deleted file mode 100644 index 74e594f..0000000 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Cardinality.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * 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; - -/** - * Component cardinality representation. - */ -class Cardinality { - String cardinality; - int min = 0; - int max = Integer.MAX_VALUE; - int exact = -1; - boolean isAll = false; - - public Cardinality(String cardinality) { - this.cardinality = cardinality; - if (cardinality != null && ! cardinality.isEmpty()) { - if (cardinality.contains("+")) { - min = Integer.valueOf(cardinality.split("\\+")[0]); - } else if (cardinality.contains("-")) { - String[] toks = cardinality.split("-"); - min = Integer.parseInt(toks[0]); - max = Integer.parseInt(toks[1]); - } else if (cardinality.equals("ALL")) { - isAll = true; - } else { - exact = Integer.parseInt(cardinality); - } - } - } - - /** - * Determine if component is required for all host groups. - * - * @return true if cardinality is 'ALL', false otherwise - */ - public boolean isAll() { - return isAll; - } - - /** - * Determine if the given count satisfies the required cardinality. - * - * @param count number of host groups containing component - * - * @return true id count satisfies the required cardinality, false otherwise - */ - public boolean isValidCount(int count) { - if (isAll) { - return false; - } else if (exact != -1) { - return count == exact; - } else return count >= min && count <= max; - } - - /** - * Determine if the cardinality count supports auto-deployment. - * This determination is independent of whether the component is configured - * to be auto-deployed. This only indicates whether auto-deployment is - * supported for the current cardinality. - * - * At this time, only cardinalities of ALL or where a count of 1 is valid are - * supported. - * - * @return true if cardinality supports auto-deployment - */ - public boolean supportsAutoDeploy() { - return isValidCount(1) || isAll; - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/c9f0dd0b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java index 2c43e1a..2db2d28 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java @@ -270,7 +270,7 @@ public class ClientConfigResourceProvider extends AbstractControllerResourceProv Map<String, Set<String>> clusterHostInfo = null; ServiceInfo serviceInfo = null; String osFamily = null; - clusterHostInfo = StageUtils.getClusterHostInfo(managementController.getClusters().getHostsForCluster(cluster.getClusterName()), cluster); + clusterHostInfo = StageUtils.getClusterHostInfo(cluster); serviceInfo = managementController.getAmbariMetaInfo().getService(stackId.getStackName(), stackId.getStackVersion(), serviceName); clusterHostInfo = substituteHostIndexes(clusterHostInfo); http://git-wip-us.apache.org/repos/asf/ambari/blob/c9f0dd0b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java index 0b5bb8e..812aa5d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java @@ -18,15 +18,22 @@ package org.apache.ambari.server.controller.internal; import org.apache.ambari.server.AmbariException; -import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.controller.ClusterRequest; import org.apache.ambari.server.controller.ClusterResponse; -import org.apache.ambari.server.controller.ConfigGroupRequest; import org.apache.ambari.server.controller.ConfigurationRequest; import org.apache.ambari.server.controller.RequestStatusResponse; import org.apache.ambari.server.controller.ServiceConfigVersionRequest; import org.apache.ambari.server.controller.ServiceConfigVersionResponse; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.apache.ambari.server.controller.spi.NoSuchParentResourceException; import org.apache.ambari.server.controller.spi.NoSuchResourceException; import org.apache.ambari.server.controller.spi.Predicate; @@ -34,50 +41,32 @@ import org.apache.ambari.server.controller.spi.Request; import org.apache.ambari.server.controller.spi.RequestStatus; import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException; -import org.apache.ambari.server.controller.spi.ResourceProvider; import org.apache.ambari.server.controller.spi.SystemException; import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; import org.apache.ambari.server.controller.utilities.PropertyHelper; -import org.apache.ambari.server.orm.dao.BlueprintDAO; -import org.apache.ambari.server.orm.entities.BlueprintConfigEntity; -import org.apache.ambari.server.orm.entities.BlueprintEntity; -import org.apache.ambari.server.orm.entities.HostGroupEntity; -import org.apache.ambari.server.state.Config; -import org.apache.ambari.server.state.ConfigHelper; -import org.apache.ambari.server.state.ConfigImpl; import org.apache.ambari.server.state.SecurityType; -import org.apache.ambari.server.state.StackId; +import org.apache.ambari.server.topology.*; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; /** * Resource provider for cluster resources. */ -public class ClusterResourceProvider extends BaseBlueprintProcessor { +public class ClusterResourceProvider extends AbstractControllerResourceProvider { // ----- Property ID constants --------------------------------------------- // Clusters public static final String CLUSTER_ID_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "cluster_id"); public static final String CLUSTER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "cluster_name"); - protected static final String CLUSTER_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "version"); - protected static final String CLUSTER_PROVISIONING_STATE_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "provisioning_state"); - protected static final String CLUSTER_SECURITY_TYPE_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "security_type"); - protected static final String CLUSTER_DESIRED_CONFIGS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_configs"); - protected static final String CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_service_config_versions"); - protected static final String CLUSTER_TOTAL_HOSTS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "total_hosts"); - protected static final String CLUSTER_HEALTH_REPORT_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "health_report"); - protected static final String BLUEPRINT_PROPERTY_ID = PropertyHelper.getPropertyId(null, "blueprint"); - protected static final String SESSION_ATTRIBUTES_PROPERTY_ID = "session_attributes"; + public static final String CLUSTER_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "version"); + public static final String CLUSTER_PROVISIONING_STATE_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "provisioning_state"); + public static final String CLUSTER_SECURITY_TYPE_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "security_type"); + public static final String CLUSTER_DESIRED_CONFIGS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_configs"); + public static final String CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_service_config_versions"); + public static final String CLUSTER_TOTAL_HOSTS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "total_hosts"); + public static final String CLUSTER_HEALTH_REPORT_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "health_report"); + public static final String BLUEPRINT_PROPERTY_ID = PropertyHelper.getPropertyId(null, "blueprint"); + public static final String SESSION_ATTRIBUTES_PROPERTY_ID = "session_attributes"; /** * The session attributes property prefix. @@ -90,6 +79,16 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor { public static final String GET_IGNORE_PERMISSIONS_PROPERTY_ID = "get_resource/ignore_permissions"; /** + * topology manager instance + */ + private static TopologyManager topologyManager; + + /** + * factory for creating topology requests which are used to provision a cluster via a blueprint + */ + private static TopologyRequestFactory topologyRequestFactory; + + /** * The cluster primary key properties. */ private static Set<String> pkPropertyIds = @@ -107,6 +106,8 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor { * The property ids for a cluster resource. */ private static Set<String> propertyIds = new HashSet<String>(); + + static { propertyIds.add(CLUSTER_ID_PROPERTY_ID); propertyIds.add(CLUSTER_NAME_PROPERTY_ID); @@ -121,16 +122,6 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor { propertyIds.add(SESSION_ATTRIBUTES_PROPERTY_ID); } - /** - * Maps configuration type (string) to associated properties - */ - private Map<String, Map<String, String>> mapClusterConfigurations = - new HashMap<String, Map<String, String>>(); - /** - * Maps configuration type (string) to property attributes, and their values - */ - private Map<String, Map<String, Map<String, String>>> mapClusterAttributes = - new HashMap<String, Map<String, Map<String, String>>>(); // ----- Constructors ---------------------------------------------------- @@ -336,21 +327,13 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor { /** * Inject the blueprint data access object which is used to obtain blueprint entities. * - * @param dao blueprint data access object + * @param manager topology manager + * @param requestFactory request factory */ - public static void init(BlueprintDAO dao, AmbariMetaInfo metaInfo, ConfigHelper ch) { - blueprintDAO = dao; - stackInfo = metaInfo; - configHelper = ch; - } - - - /** - * Package-level access for cluster config - * @return cluster config map - */ - Map<String, Map<String, String>> getClusterConfigurations() { - return mapClusterConfigurations; + //todo: proper static injection mechanism + public static void init(TopologyManager manager, TopologyRequestFactory requestFactory) { + topologyManager = manager; + topologyRequestFactory = requestFactory; } @@ -477,439 +460,24 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor { throws ResourceAlreadyExistsException, SystemException, UnsupportedPropertyException, NoSuchParentResourceException { - String blueprintName = (String) properties.get(BLUEPRINT_PROPERTY_ID); - LOG.info("Creating Cluster '" + properties.get(CLUSTER_NAME_PROPERTY_ID) + - "' based on blueprint '" + blueprintName + "'."); - - //todo: build up a proper topology object - BlueprintEntity blueprint = getExistingBlueprint(blueprintName); - Stack stack = parseStack(blueprint); - - Map<String, HostGroupImpl> blueprintHostGroups = parseBlueprintHostGroups(blueprint, stack); - applyRequestInfoToHostGroups(properties, blueprintHostGroups); - Collection<Map<String, String>> configOverrides = (Collection<Map<String, String>>)properties.get("configurations"); - - String message = null; - for (BlueprintConfigEntity blueprintConfig: blueprint.getConfigurations()){ - if(blueprintConfig.getType().equals("global")){ - message = "WARNING: Global configurations are deprecated, please use *-env"; - break; - } - } - - processConfigurations(processBlueprintConfigurations(blueprint, configOverrides), - processBlueprintAttributes(blueprint), stack, blueprintHostGroups); - validatePasswordProperties(blueprint, blueprintHostGroups, (String) properties.get("default_password")); - - String clusterName = (String) properties.get(CLUSTER_NAME_PROPERTY_ID); - createClusterResource(buildClusterResourceProperties(stack, clusterName)); - setConfigurationsOnCluster(clusterName, stack, blueprintHostGroups); - - Set<String> services = getServicesToDeploy(stack, blueprintHostGroups); - - createServiceAndComponentResources(blueprintHostGroups, clusterName, services); - createHostAndComponentResources(blueprintHostGroups, clusterName); - - registerConfigGroups(clusterName, blueprintHostGroups, stack); - - persistInstallStateForUI(clusterName); - - RequestStatusResponse request = ((ServiceResourceProvider) getResourceProvider(Resource.Type.Service)). - installAndStart(clusterName); - - request.setMessage(message); - - return request; - } - - /** - * Validate that all required password properties have been set or that 'default_password' is specified. - * - * @param blueprint associated blueprint entity - * @param hostGroups host groups in blueprint - * @param defaultPassword specified default password, may be null - * - * @throws IllegalArgumentException if required password properties are missing and no - * default is specified via 'default_password' - */ - private void validatePasswordProperties(BlueprintEntity blueprint, Map<String, HostGroupImpl> hostGroups, - String defaultPassword) { - - Map<String, Map<String, Collection<String>>> missingPasswords = blueprint.validateConfigurations( - stackInfo, true); - - Iterator<Map.Entry<String, Map<String, Collection<String>>>> iter; - for(iter = missingPasswords.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry<String, Map<String, Collection<String>>> entry = iter.next(); - Map<String, Collection<String>> missingProps = entry.getValue(); - Iterator<Map.Entry<String, Collection<String>>> hostGroupIter; - - for (hostGroupIter = missingProps.entrySet().iterator(); hostGroupIter.hasNext(); ) { - Map.Entry<String, Collection<String>> hgEntry = hostGroupIter.next(); - String configType = hgEntry.getKey(); - Collection<String> propertySet = hgEntry.getValue(); - - for (Iterator<String> propIter = propertySet.iterator(); propIter.hasNext(); ) { - String property = propIter.next(); - if (isPropertyInConfiguration(mapClusterConfigurations.get(configType), property)){ - propIter.remove(); - } else { - HostGroupImpl hg = hostGroups.get(entry.getKey()); - if (hg != null && isPropertyInConfiguration(hg.getConfigurationProperties().get(configType), property)) { - propIter.remove(); - } else if (setDefaultPassword(defaultPassword, configType, property)) { - propIter.remove(); - } - } - } - if (propertySet.isEmpty()) { - hostGroupIter.remove(); - } - } - if (entry.getValue().isEmpty()) { - iter.remove(); - } - } - - if (! missingPasswords.isEmpty()) { - throw new IllegalArgumentException("Missing required password properties. Specify a value for these " + - "properties in the cluster or host group configurations or include 'default_password' field in request. " + - missingPasswords); - } - } - - /** - * Attempt to set the default password in cluster configuration for missing password property. - * - * @param defaultPassword default password specified in request, may be null - * @param configType configuration type - * @param property password property name - * - * @return true if password was set, otherwise false. Currently the password will always be set - * unless it is null - */ - private boolean setDefaultPassword(String defaultPassword, String configType, String property) { - boolean setDefaultPassword = false; - Map<String, String> typeProps = mapClusterConfigurations.get(configType); - if (defaultPassword != null && ! defaultPassword.trim().isEmpty()) { - // set default password in cluster config - if (typeProps == null) { - typeProps = new HashMap<String, String>(); - mapClusterConfigurations.put(configType, typeProps); - } - typeProps.put(property, defaultPassword); - setDefaultPassword = true; - } - return setDefaultPassword; - } - - /** - * Determine if a specific property is in a configuration. - * - * @param props property map to check - * @param property property to check for - * - * @return true if the property is contained in the configuration, otherwise false - */ - private boolean isPropertyInConfiguration(Map<String, String> props, String property) { - boolean foundProperty = false; - if (props != null) { - String val = props.get(property); - foundProperty = (val != null && ! val.trim().isEmpty()); - } - return foundProperty; - } - - /** - * Create service and component resources. - * - * @param blueprintHostGroups host groups contained in blueprint - * @param clusterName cluster name - * @param services services to be deployed - * - * @throws SystemException an unexpected exception occurred - * @throws UnsupportedPropertyException an unsupported property was specified in the request - * @throws ResourceAlreadyExistsException attempted to create a service or component that already exists - * @throws NoSuchParentResourceException a required parent resource is missing - */ - private void createServiceAndComponentResources(Map<String, HostGroupImpl> blueprintHostGroups, - String clusterName, Set<String> services) - throws SystemException, - UnsupportedPropertyException, - ResourceAlreadyExistsException, - NoSuchParentResourceException { - - Set<Map<String, Object>> setServiceRequestProps = new HashSet<Map<String, Object>>(); - for (String service : services) { - Map<String, Object> serviceProperties = new HashMap<String, Object>(); - serviceProperties.put(ServiceResourceProvider.SERVICE_CLUSTER_NAME_PROPERTY_ID, clusterName); - serviceProperties.put(ServiceResourceProvider.SERVICE_SERVICE_NAME_PROPERTY_ID, service); - setServiceRequestProps.add(serviceProperties); - } - - Request serviceRequest = new RequestImpl(null, setServiceRequestProps, null, null); - getResourceProvider(Resource.Type.Service).createResources(serviceRequest); - createComponentResources(blueprintHostGroups, clusterName, services); - } - - /** - * Build the cluster properties necessary for creating a cluster resource. - * - * @param stack associated stack - * @param clusterName cluster name - * @return map of cluster properties used to create a cluster resource - */ - private Map<String, Object> buildClusterResourceProperties(Stack stack, String clusterName) { - Map<String, Object> clusterProperties = new HashMap<String, Object>(); - clusterProperties.put(CLUSTER_NAME_PROPERTY_ID, clusterName); - clusterProperties.put(CLUSTER_VERSION_PROPERTY_ID, stack.getName() + "-" + stack.getVersion()); - return clusterProperties; - } - - /** - * Create component resources. - * - * @param blueprintHostGroups host groups specified in blueprint - * @param clusterName cluster name - * @param services services to be deployed - * - * @throws SystemException an unexpected exception occurred - * @throws UnsupportedPropertyException an invalid property was specified - * @throws ResourceAlreadyExistsException attempt to create a component which already exists - * @throws NoSuchParentResourceException a required parent resource is missing - */ - private void createComponentResources(Map<String, HostGroupImpl> blueprintHostGroups, - String clusterName, Set<String> services) - throws SystemException, - UnsupportedPropertyException, - ResourceAlreadyExistsException, - NoSuchParentResourceException { - for (String service : services) { - Set<String> components = new HashSet<String>(); - for (HostGroupImpl hostGroup : blueprintHostGroups.values()) { - Collection<String> serviceComponents = hostGroup.getComponents(service); - if (serviceComponents != null && !serviceComponents.isEmpty()) { - components.addAll(serviceComponents); - } - } - - Set<Map<String, Object>> setComponentRequestProps = new HashSet<Map<String, Object>>(); - for (String component : components) { - Map<String, Object> componentProperties = new HashMap<String, Object>(); - componentProperties.put("ServiceComponentInfo/cluster_name", clusterName); - componentProperties.put("ServiceComponentInfo/service_name", service); - componentProperties.put("ServiceComponentInfo/component_name", component); - setComponentRequestProps.add(componentProperties); - } - Request componentRequest = new RequestImpl(null, setComponentRequestProps, null, null); - ResourceProvider componentProvider = getResourceProvider(Resource.Type.Component); - componentProvider.createResources(componentRequest); - } - } - - /** - * Set all configurations on the cluster resource. - * - * @param clusterName cluster name - * @param stack Stack definition object used for this cluster - * @param blueprintHostGroups host groups defined in the Blueprint for this cluster - * - * @throws SystemException an unexpected exception occurred - */ - void setConfigurationsOnCluster(String clusterName, Stack stack, Map<String, HostGroupImpl> blueprintHostGroups) throws SystemException { - List<BlueprintServiceConfigRequest> listofConfigRequests = - new LinkedList<BlueprintServiceConfigRequest>(); - - // create a list of config requests on a per-service basis, in order - // to properly support the new service configuration versioning mechanism - // in Ambari - for (String service : getServicesToDeploy(stack, blueprintHostGroups)) { - BlueprintServiceConfigRequest blueprintConfigRequest = - new BlueprintServiceConfigRequest(service); - - for (String serviceConfigType : stack.getConfigurationTypes(service)) { - Set<String> excludedConfigTypes = stack.getExcludedConfigurationTypes(service); - if (excludedConfigTypes == null) { - // if the service does not have excluded config types - // associated, then treat this as an empty set - excludedConfigTypes = Collections.emptySet(); - } - - // only include config types that are not excluded, re-introducing fix from AMBARI-8009 - if (!excludedConfigTypes.contains(serviceConfigType)) { - // skip handling of cluster-env here - if (!serviceConfigType.equals("cluster-env")) { - if (mapClusterConfigurations.containsKey(serviceConfigType)) { - blueprintConfigRequest.addConfigElement(serviceConfigType, - mapClusterConfigurations.get(serviceConfigType), - mapClusterAttributes.get(serviceConfigType)); - } - } - } - } - - listofConfigRequests.add(blueprintConfigRequest); - } - - // since the stack returns "cluster-env" with each service's config - // this code needs to ensure that only one ClusterRequest occurs for - // the global cluster-env configuration - BlueprintServiceConfigRequest globalConfigRequest = - new BlueprintServiceConfigRequest("GLOBAL-CONFIG"); - globalConfigRequest.addConfigElement("cluster-env", - mapClusterConfigurations.get("cluster-env"), - mapClusterAttributes.get("cluster-env")); - listofConfigRequests.add(globalConfigRequest); + "' based on blueprint '" + String.valueOf(properties.get(BLUEPRINT_PROPERTY_ID)) + "'."); + TopologyRequest createClusterRequest; try { - //todo: properly handle non system exceptions - setConfigurationsOnCluster(clusterName, listofConfigRequests); - } catch (AmbariException e) { - throw new SystemException("Unable to set configurations on cluster.", e); - } - - } - - - /** - * Creates a ClusterRequest for each service that - * includes any associated config types and configuration. The Blueprints - * implementation will now create one ClusterRequest per service, in order - * to comply with the ServiceConfigVersioning framework in Ambari. - * - * This method will also send these requests to the management controller. - * - * @param clusterName name of cluster - * @param listOfBlueprintConfigRequests a list of requests to send to the AmbariManagementController. - * - * @throws AmbariException upon any error that occurs during updateClusters - */ - private void setConfigurationsOnCluster(String clusterName, List<BlueprintServiceConfigRequest> listOfBlueprintConfigRequests) throws AmbariException { - // iterate over services to deploy - for (BlueprintServiceConfigRequest blueprintConfigRequest : listOfBlueprintConfigRequests) { - ClusterRequest clusterRequest = null; - // iterate over the config types associated with this service - List<ConfigurationRequest> requestsPerService = new LinkedList<ConfigurationRequest>(); - for (BlueprintServiceConfigElement blueprintElement : blueprintConfigRequest.getConfigElements()) { - Map<String, Object> clusterProperties = new HashMap<String, Object>(); - clusterProperties.put(CLUSTER_NAME_PROPERTY_ID, clusterName); - clusterProperties.put(CLUSTER_DESIRED_CONFIGS_PROPERTY_ID + "/type", blueprintElement.getTypeName()); - clusterProperties.put(CLUSTER_DESIRED_CONFIGS_PROPERTY_ID + "/tag", "1"); - for (Map.Entry<String, String> entry : blueprintElement.getConfiguration().entrySet()) { - clusterProperties.put(CLUSTER_DESIRED_CONFIGS_PROPERTY_ID + - "/properties/" + entry.getKey(), entry.getValue()); - } - if (blueprintElement.getAttributes() != null) { - for (Map.Entry<String, Map<String, String>> attribute : blueprintElement.getAttributes().entrySet()) { - String attributeName = attribute.getKey(); - for (Map.Entry<String, String> attributeOccurrence : attribute.getValue().entrySet()) { - clusterProperties.put(CLUSTER_DESIRED_CONFIGS_PROPERTY_ID + "/properties_attributes/" - + attributeName + "/" + attributeOccurrence.getKey(), attributeOccurrence.getValue()); - } - } - } - - // only create one cluster request per service, which includes - // all the configuration types for that service - if (clusterRequest == null) { - SecurityType securityType; - String requestedSecurityType = (String) clusterProperties.get(CLUSTER_SECURITY_TYPE_PROPERTY_ID); - if(requestedSecurityType == null) - securityType = null; - else { - try { - securityType = SecurityType.valueOf(requestedSecurityType.toUpperCase()); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(String.format("Cannot set cluster security type to invalid value: %s", requestedSecurityType)); - } - } - - clusterRequest = new ClusterRequest( - (Long) clusterProperties.get(CLUSTER_ID_PROPERTY_ID), - (String) clusterProperties.get(CLUSTER_NAME_PROPERTY_ID), - (String) clusterProperties.get(CLUSTER_PROVISIONING_STATE_PROPERTY_ID), - securityType, - (String) clusterProperties.get(CLUSTER_VERSION_PROPERTY_ID), - null); - } - - List<ConfigurationRequest> listOfRequests = - getConfigurationRequests("Clusters", clusterProperties); - requestsPerService.addAll(listOfRequests); - } - - // set total list of config requests, including all config types - // for this service - if (clusterRequest != null) { - clusterRequest.setDesiredConfig(requestsPerService); - - LOG.info("About to send cluster config update request for service = " + blueprintConfigRequest.getServiceName()); - - // send the request update for this service as a whole - getManagementController().updateClusters( - Collections.singleton(clusterRequest), null); - } else { - LOG.error("ClusterRequest should not be null for service = " + blueprintConfigRequest.getServiceName()); - } - - } - } - - /** - * Apply the information contained in the cluster request body such as host an configuration properties to - * the associated blueprint. - * - * @param properties request properties - * @param blueprintHostGroups blueprint host groups - * - * @throws IllegalArgumentException a host_group in the request doesn't match a host-group in the blueprint - */ - @SuppressWarnings("unchecked") - private void applyRequestInfoToHostGroups(Map<String, Object> properties, - Map<String, HostGroupImpl> blueprintHostGroups) - throws IllegalArgumentException { - - @SuppressWarnings("unchecked") - Collection<Map<String, Object>> hostGroups = - (Collection<Map<String, Object>>) properties.get("host_groups"); - - if (hostGroups == null || hostGroups.isEmpty()) { - throw new IllegalArgumentException("'host_groups' element must be included in cluster create body"); + createClusterRequest = topologyRequestFactory.createProvisionClusterRequest(properties); + } catch (InvalidTopologyTemplateException e) { + throw new IllegalArgumentException("Invalid Cluster Creation Template: " + e, e); } - // iterate over host groups provided in request body - for (Map<String, Object> hostGroupProperties : hostGroups) { - String name = (String) hostGroupProperties.get("name"); - if (name == null || name.isEmpty()) { - throw new IllegalArgumentException("Every host_group must include a non-null 'name' property"); - } - HostGroupImpl hostGroup = blueprintHostGroups.get(name); - - if (hostGroup == null) { - throw new IllegalArgumentException("Invalid host_group specified: " + name + - ". All request host groups must have a corresponding host group in the specified blueprint"); - } - - Collection hosts = (Collection) hostGroupProperties.get("hosts"); - if (hosts == null || hosts.isEmpty()) { - throw new IllegalArgumentException("Host group '" + name + "' must contain a 'hosts' element"); - } - for (Object oHost : hosts) { - Map<String, String> mapHostProperties = (Map<String, String>) oHost; - //add host information to host group - String fqdn = mapHostProperties.get("fqdn"); - if (fqdn == null || fqdn.isEmpty()) { - throw new IllegalArgumentException("Host group '" + name + "' hosts element must include at least one fqdn"); - } - hostGroup.addHostInfo(fqdn); - } - Map<String, Map<String, String>> existingConfigurations = hostGroup.getConfigurationProperties(); - overrideExistingProperties(existingConfigurations, (Collection<Map<String, String>>) - hostGroupProperties.get("configurations")); - + try { + return topologyManager.provisionCluster(createClusterRequest); + } catch (InvalidTopologyException e) { + throw new IllegalArgumentException("Topology validation failed: " + e, e); + } catch (AmbariException e) { + e.printStackTrace(); + throw new SystemException("Unknown exception when asking TopologyManager to provision cluster", e); } - validateHostMappings(blueprintHostGroups); } /** @@ -934,317 +502,6 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor { } /** - * Persist cluster state for the ambari UI. Setting this state informs that UI that a cluster has been - * installed and started and that the monitoring screen for the cluster should be displayed to the user. - * - * @param clusterName name of cluster - * - * @throws SystemException if unable to update the cluster with the UI installed flag - */ - private void persistInstallStateForUI(String clusterName) throws SystemException { - Map<String, Object> clusterProperties = new HashMap<String, Object>(); - clusterProperties.put(CLUSTER_PROVISIONING_STATE_PROPERTY_ID, "INSTALLED"); - clusterProperties.put(CLUSTER_NAME_PROPERTY_ID, clusterName); - - try { - getManagementController().updateClusters( - Collections.singleton(getRequest(clusterProperties)), null); - } catch (AmbariException e) { - throw new SystemException("Unable to finalize state of cluster for UI."); - } - } - - /** - * Process cluster configurations. This includes obtaining the default configuration properties - * from the stack,overlaying configuration properties specified in the blueprint and cluster - * create request and updating properties with topology specific information. - * - * @param stack associated stack - * @param blueprintHostGroups host groups contained in the blueprint - */ - private void processConfigurations(Map<String, Map<String, String>> blueprintConfigurations, - Map<String, Map<String, Map<String, String>>> blueprintAttributes, - Stack stack, Map<String, HostGroupImpl> blueprintHostGroups) { - - - for (String service : getServicesToDeploy(stack, blueprintHostGroups)) { - for (String type : stack.getConfigurationTypes(service)) { - Map<String, String> typeProps = mapClusterConfigurations.get(type); - if (typeProps == null) { - typeProps = new HashMap<String, String>(); - mapClusterConfigurations.put(type, typeProps); - } - typeProps.putAll(stack.getConfigurationProperties(service, type)); - Map<String, Map<String, String>> stackTypeAttributes = stack.getConfigurationAttributes(service, type); - if (!stackTypeAttributes.isEmpty()) { - if (!mapClusterAttributes.containsKey(type)) { - mapClusterAttributes.put(type, new HashMap<String, Map<String, String>>()); - } - Map<String, Map<String, String>> typeAttrs = mapClusterAttributes.get(type); - for (Map.Entry<String, Map<String, String>> attribute : stackTypeAttributes.entrySet()) { - String attributeName = attribute.getKey(); - Map<String, String> attributes = typeAttrs.get(attributeName); - if (attributes == null) { - attributes = new HashMap<String, String>(); - typeAttrs.put(attributeName, attributes); - } - attributes.putAll(attribute.getValue()); - } - } - } - } - processBlueprintClusterConfigurations(blueprintConfigurations); - processBlueprintClusterConfigAttributes(blueprintAttributes); - - BlueprintConfigurationProcessor configurationProcessor = new BlueprintConfigurationProcessor(mapClusterConfigurations); - configurationProcessor.doUpdateForClusterCreate(blueprintHostGroups, stack); - setMissingConfigurations(blueprintHostGroups); - } - - /** - * Since global configs are deprecated since 1.7.0, but still supported. - * We should automatically map any globals used, to *-env dictionaries. - * - * @param blueprintConfigurations map of blueprint configurations keyed by type - */ - private void handleGlobalsBackwardsCompability(Stack stack, - Map<String, Map<String, String>> blueprintConfigurations, String clusterName) { - StackId stackId = new StackId(stack.getName(), stack.getVersion()); - configHelper.moveDeprecatedGlobals(stackId, blueprintConfigurations, clusterName); - } - - /** - * Process cluster scoped configurations provided in blueprint. - * - * @param blueprintConfigurations map of blueprint configurations keyed by type - */ - private void processBlueprintClusterConfigurations(Map<String, Map<String, String>> blueprintConfigurations) { - for (Map.Entry<String, Map<String, String>> entry : blueprintConfigurations.entrySet()) { - Map<String, String> properties = entry.getValue(); - if (properties != null && !properties.isEmpty()) { - String type = entry.getKey(); - Map<String, String> typeProps = mapClusterConfigurations.get(type); - if (typeProps == null) { - typeProps = new HashMap<String, String>(); - mapClusterConfigurations.put(type, typeProps); - } - // override default properties - typeProps.putAll(properties); - } - } - } - - /** - * Process cluster scoped configuration attributes provided in blueprint. - * - * @param blueprintAttributes map of configuration type to configuration attributes and their values - */ - private void processBlueprintClusterConfigAttributes(Map<String, Map<String, Map<String, String>>> blueprintAttributes) { - for (Map.Entry<String, Map<String, Map<String, String>>> entry : blueprintAttributes.entrySet()) { - Map<String, Map<String, String>> attributes = entry.getValue(); - if (attributes != null && !attributes.isEmpty()) { - String type = entry.getKey(); - if (!mapClusterAttributes.containsKey(type)) { - mapClusterAttributes.put(type, new HashMap<String, Map<String, String>>()); - } - Map<String, Map<String, String>> typeAttrs = mapClusterAttributes.get(type); - for (Map.Entry<String, Map<String, String>> attribute : attributes.entrySet()) { - String attributeName = attribute.getKey(); - if (!typeAttrs.containsKey(attributeName)) { - typeAttrs.put(attributeName, new HashMap<String, String>()); - } - typeAttrs.get(attributeName).putAll(attribute.getValue()); - } - } - } - } - - /** - * Explicitly set any properties that are required but not currently provided in the stack definition. - */ - void setMissingConfigurations(Map<String, HostGroupImpl> blueprintHostGroups) { - // AMBARI-5206 - final Map<String , String> userProps = new HashMap<String , String>(); - - // only add user properties to the map for - // services actually included in the blueprint definition - if (isServiceIncluded("OOZIE", blueprintHostGroups)) { - userProps.put("oozie_user", "oozie-env"); - } - - if (isServiceIncluded("HIVE", blueprintHostGroups)) { - userProps.put("hive_user", "hive-env"); - userProps.put("hcat_user", "hive-env"); - } - - if (isServiceIncluded("HBASE", blueprintHostGroups)) { - userProps.put("hbase_user", "hbase-env"); - } - - if (isServiceIncluded("FALCON", blueprintHostGroups)) { - userProps.put("falcon_user", "falcon-env"); - } - - - String proxyUserHosts = "hadoop.proxyuser.%s.hosts"; - String proxyUserGroups = "hadoop.proxyuser.%s.groups"; - - for (String property : userProps.keySet()) { - String configType = userProps.get(property); - Map<String, String> configs = mapClusterConfigurations.get(configType); - if (configs != null) { - String user = configs.get(property); - if (user != null && !user.isEmpty()) { - ensureProperty("core-site", String.format(proxyUserHosts, user), "*"); - ensureProperty("core-site", String.format(proxyUserGroups, user), "users"); - } - } else { - LOG.debug("setMissingConfigurations: no user configuration found for type = " + configType + ". This may be caused by an error in the blueprint configuration."); - } - - } - } - - - /** - * Determines if any components in the specified service are - * included in the current blueprint's host group definitions. - * - * @param serviceName the Hadoop service name to query on - * @param blueprintHostGroups the map of Host Groups in the current blueprint - * @return true if the named service is included in the blueprint - * false if the named service it not included in the blueprint - */ - protected boolean isServiceIncluded(String serviceName, Map<String, HostGroupImpl> blueprintHostGroups) { - for (String hostGroupName : blueprintHostGroups.keySet()) { - HostGroupImpl hostGroup = blueprintHostGroups.get(hostGroupName); - if (hostGroup.getServices().contains(serviceName)) { - return true; - } - } - - return false; - } - - /** - * Ensure that the specified property exists. - * If not, set a default value. - * - * @param type config type - * @param property property name - * @param defaultValue default value - */ - private void ensureProperty(String type, String property, String defaultValue) { - Map<String, String> properties = mapClusterConfigurations.get(type); - if (properties == null) { - properties = new HashMap<String, String>(); - mapClusterConfigurations.put(type, properties); - } - - if (! properties.containsKey(property)) { - properties.put(property, defaultValue); - } - } - - /** - * Get set of services which are to be deployed. - * - * @param stack stack information - * @param blueprintHostGroups host groups contained in blueprint - * - * @return set of service names which will be deployed - */ - private Set<String> getServicesToDeploy(Stack stack, Map<String, HostGroupImpl> blueprintHostGroups) { - Set<String> services = new HashSet<String>(); - for (HostGroupImpl group : blueprintHostGroups.values()) { - if (! group.getHostInfo().isEmpty()) { - services.addAll(stack.getServicesForComponents(group.getComponents())); - } - } - //remove entry associated with Ambari Server since this isn't recognized by Ambari - services.remove(null); - - return services; - } - - /** - * Register config groups for host group scoped configuration. - * For each host group with configuration specified in the blueprint, a config group is created - * and the hosts associated with the host group are assigned to the config group. - * - * @param clusterName name of cluster - * @param hostGroups map of host group name to host group - * @param stack associated stack information - * - * @throws ResourceAlreadyExistsException attempt to create a config group that already exists - * @throws SystemException an unexpected exception occurs - * @throws UnsupportedPropertyException an invalid property is provided when creating a config group - * @throws NoSuchParentResourceException attempt to create a config group for a non-existing cluster - */ - private void registerConfigGroups(String clusterName, Map<String, HostGroupImpl> hostGroups, Stack stack) throws - ResourceAlreadyExistsException, SystemException, - UnsupportedPropertyException, NoSuchParentResourceException { - - for (HostGroupImpl group : hostGroups.values()) { - HostGroupEntity entity = group.getEntity(); - Map<String, Map<String, Config>> groupConfigs = new HashMap<String, Map<String, Config>>(); - - handleGlobalsBackwardsCompability(stack, group.getConfigurationProperties(), clusterName); - for (Map.Entry<String, Map<String, String>> entry: group.getConfigurationProperties().entrySet()) { - String type = entry.getKey(); - String service = stack.getServiceForConfigType(type); - Config config = new ConfigImpl(type); - config.setTag(entity.getName()); - config.setProperties(entry.getValue()); - Map<String, Config> serviceConfigs = groupConfigs.get(service); - if (serviceConfigs == null) { - serviceConfigs = new HashMap<String, Config>(); - groupConfigs.put(service, serviceConfigs); - } - serviceConfigs.put(type, config); - } - - for (Map.Entry<String, Map<String, Config>> entry : groupConfigs.entrySet()) { - String service = entry.getKey(); - Map<String, Config> serviceConfigs = entry.getValue(); - String hostGroupName = getConfigurationGroupName(entity.getBlueprintName(), entity.getName()); - ConfigGroupRequest request = new ConfigGroupRequest( - null, clusterName, hostGroupName, service, "Host Group Configuration", - new HashSet<String>(group.getHostInfo()), serviceConfigs); - - ((ConfigGroupResourceProvider) getResourceProvider(Resource.Type.ConfigGroup)). - createResources(Collections.singleton(request)); - } - } - } - - /** - * Validate that a host is only mapped to a single host group. - * - * @param hostGroups map of host group name to host group - */ - private void validateHostMappings(Map<String, HostGroupImpl> hostGroups) { - Collection<String> mappedHosts = new HashSet<String>(); - Collection<String> flaggedHosts = new HashSet<String>(); - - for (HostGroupImpl hostgroup : hostGroups.values()) { - for (String host : hostgroup.getHostInfo()) { - if (mappedHosts.contains(host)) { - flaggedHosts.add(host); - } else { - mappedHosts.add(host); - } - } - } - - if (! flaggedHosts.isEmpty()) { - throw new IllegalArgumentException("A host may only be mapped to a single host group at this time." + - " The following hosts are mapped to more than one host group: " + - flaggedHosts); - } - } - - /** * Determine whether or not the cluster resource identified * by the given cluster name should be included based on the * permissions granted to the current user. @@ -1258,69 +515,5 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor { return getManagementController().getClusters().checkPermission(clusterName, readOnly); } - - /** - * Internal class meant to represent the collection of configuration - * items and configuration attributes that are associated with a given service. - * - * This class is used to support proper configuration versioning when - * Ambari Blueprints is used to deploy a cluster. - */ - private static class BlueprintServiceConfigRequest { - - private final String serviceName; - - private List<BlueprintServiceConfigElement> configElements = - new LinkedList<BlueprintServiceConfigElement>(); - - BlueprintServiceConfigRequest(String serviceName) { - this.serviceName = serviceName; - } - - void addConfigElement(String typeName, Map<String, String> configuration, Map<String, Map<String, String>> attributes) { - configElements.add(new BlueprintServiceConfigElement(typeName, configuration, attributes)); - } - - public String getServiceName() { - return serviceName; - } - - List<BlueprintServiceConfigElement> getConfigElements() { - return configElements; - } - - } - - /** - * Internal class that represents the configuration - * and attributes for a given configuration type. - */ - private static class BlueprintServiceConfigElement { - private final String typeName; - - private final Map<String, String> configuration; - - private final Map<String, Map<String, String>> attributes; - - BlueprintServiceConfigElement(String typeName, Map<String, String> configuration, Map<String, Map<String, String>> attributes) { - this.typeName = typeName; - this.configuration = configuration; - this.attributes = attributes; - } - - public String getTypeName() { - return typeName; - } - - public Map<String, String> getConfiguration() { - return configuration; - } - - public Map<String, Map<String, String>> getAttributes() { - return attributes; - } - - } - } http://git-wip-us.apache.org/repos/asf/ambari/blob/c9f0dd0b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java index dea90f6..147ab8e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java @@ -32,7 +32,6 @@ import org.apache.ambari.server.DuplicateResourceException; import org.apache.ambari.server.ObjectNotFoundException; import org.apache.ambari.server.ParentObjectNotFoundException; import org.apache.ambari.server.ServiceNotFoundException; -import org.apache.ambari.server.StackAccessException; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.controller.MaintenanceStateHelper; @@ -51,7 +50,6 @@ import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; 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.MaintenanceState; import org.apache.ambari.server.state.Service; import org.apache.ambari.server.state.ServiceComponent; import org.apache.ambari.server.state.ServiceComponentFactory; @@ -211,7 +209,6 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) { requests.add(getRequest(propertyMap)); } - final Predicate finalPredicate = predicate; RequestStatusResponse response = modifyResources(new Command<RequestStatusResponse>() { @Override public RequestStatusResponse invoke() throws AmbariException { @@ -251,7 +248,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide } // Create the components for the given requests. - protected synchronized void createComponents( + public synchronized void createComponents( Set<ServiceComponentRequest> requests) throws AmbariException { if (requests.isEmpty()) { http://git-wip-us.apache.org/repos/asf/ambari/blob/c9f0dd0b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationTopologyException.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationTopologyException.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationTopologyException.java new file mode 100644 index 0000000..48b54a3 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationTopologyException.java @@ -0,0 +1,39 @@ +/** + * 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 distribut + * ed 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.Collection; + +/** + * Indicates that there is a problem with the cluster topology configuration. + */ +public class ConfigurationTopologyException extends Exception { + public ConfigurationTopologyException(Collection<String> properties) { + super(String.format("Unable to resolve host names for the following configuration properties %s", properties)); + } + + public ConfigurationTopologyException(String s) { + super(s); + } + + public ConfigurationTopologyException(String s, Throwable throwable) { + super(s, throwable); + } +}