AMBARI-10990. Implement topology manager persistence
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/807b3c2d Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/807b3c2d Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/807b3c2d Branch: refs/heads/trunk Commit: 807b3c2df7a9a9fe1d728e75cf80c130848d4756 Parents: 8963501 Author: John Speidel <[email protected]> Authored: Thu May 7 01:17:10 2015 -0400 Committer: John Speidel <[email protected]> Committed: Thu May 7 01:17:10 2015 -0400 ---------------------------------------------------------------------- .../query/render/ClusterBlueprintRenderer.java | 4 +- .../ambari/server/controller/AmbariServer.java | 4 +- .../server/controller/ControllerModule.java | 2 - .../internal/ExportBlueprintRequest.java | 10 + .../internal/HostComponentResourceProvider.java | 34 +- .../internal/HostResourceProvider.java | 4 +- .../internal/ProvisionClusterRequest.java | 14 +- .../internal/ScaleClusterRequest.java | 94 ++- .../server/controller/internal/Stack.java | 30 +- .../server/orm/dao/TopologyHostGroupDAO.java | 12 + .../server/orm/dao/TopologyHostTaskDAO.java | 73 ++ .../server/orm/dao/TopologyLogicalTaskDAO.java | 63 ++ .../server/orm/entities/BlueprintEntity.java | 3 - .../orm/entities/TopologyHostGroupEntity.java | 28 +- .../orm/entities/TopologyHostInfoEntity.java | 6 +- .../orm/entities/TopologyHostRequestEntity.java | 11 +- .../orm/entities/TopologyHostTaskEntity.java | 6 + .../entities/TopologyLogicalRequestEntity.java | 4 - .../ambari/server/topology/AmbariContext.java | 499 +++++++++++++ .../ambari/server/topology/BlueprintImpl.java | 3 +- .../topology/ClusterConfigurationRequest.java | 30 +- .../ambari/server/topology/ClusterTopology.java | 30 + .../server/topology/ClusterTopologyImpl.java | 33 +- .../ambari/server/topology/HostGroupInfo.java | 15 +- .../server/topology/HostOfferResponse.java | 9 +- .../ambari/server/topology/HostRequest.java | 699 +++++++------------ .../ambari/server/topology/LogicalRequest.java | 153 ++-- .../server/topology/LogicalRequestFactory.java | 40 ++ .../ambari/server/topology/PersistedState.java | 69 ++ .../server/topology/PersistedStateImpl.java | 408 +++++++++++ .../topology/PersistedTopologyRequest.java | 41 ++ .../ambari/server/topology/TopologyManager.java | 379 ++++------ .../ambari/server/topology/TopologyRequest.java | 4 + .../ambari/server/topology/TopologyTask.java | 5 + .../server/upgrade/UpgradeCatalog210.java | 15 +- .../main/resources/Ambari-DDL-MySQL-CREATE.sql | 17 +- .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 17 +- .../resources/Ambari-DDL-Postgres-CREATE.sql | 22 +- .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql | 20 +- .../BlueprintConfigurationProcessorTest.java | 142 ++-- .../internal/StageResourceProviderTest.java | 3 + .../orm/dao/TopologyLogicalRequestDAOTest.java | 8 +- .../server/orm/dao/TopologyRequestDAOTest.java | 3 +- .../topology/BlueprintValidatorImplTest.java | 181 +++++ .../topology/ClusterTopologyImplTest.java | 41 +- .../server/topology/TopologyManagerTest.java | 298 ++++++++ 46 files changed, 2595 insertions(+), 991 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java index 351f6b4..cfc9bc0 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java @@ -33,6 +33,7 @@ import org.apache.ambari.server.controller.internal.ExportBlueprintRequest; import org.apache.ambari.server.controller.internal.ResourceImpl; import org.apache.ambari.server.controller.internal.Stack; import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.topology.AmbariContext; import org.apache.ambari.server.topology.ClusterTopology; import org.apache.ambari.server.topology.ClusterTopologyImpl; import org.apache.ambari.server.topology.Configuration; @@ -40,7 +41,6 @@ import org.apache.ambari.server.topology.HostGroup; import org.apache.ambari.server.topology.HostGroupInfo; import org.apache.ambari.server.topology.InvalidTopologyException; import org.apache.ambari.server.topology.InvalidTopologyTemplateException; -import org.apache.ambari.server.topology.NoSuchHostGroupException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -253,7 +253,7 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer { protected ClusterTopology createClusterTopology(TreeNode<Resource> clusterNode) throws InvalidTopologyTemplateException, InvalidTopologyException { - return new ClusterTopologyImpl(new ExportBlueprintRequest(clusterNode)); + return new ClusterTopologyImpl(new AmbariContext(), new ExportBlueprintRequest(clusterNode)); } /** http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java index 84e1623..77f6d2c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java @@ -90,8 +90,8 @@ import org.apache.ambari.server.security.unsecured.rest.CertificateDownload; import org.apache.ambari.server.security.unsecured.rest.CertificateSign; import org.apache.ambari.server.security.unsecured.rest.ConnectionInfo; import org.apache.ambari.server.state.Clusters; +import org.apache.ambari.server.topology.AmbariContext; import org.apache.ambari.server.topology.BlueprintFactory; -import org.apache.ambari.server.topology.HostRequest; import org.apache.ambari.server.topology.TopologyManager; import org.apache.ambari.server.topology.TopologyRequestFactoryImpl; import org.apache.ambari.server.utils.StageUtils; @@ -618,7 +618,7 @@ public class AmbariServer { BlueprintFactory.init(injector.getInstance(BlueprintDAO.class)); ProvisionClusterRequest.init(injector.getInstance(BlueprintFactory.class)); ScaleClusterRequest.init(injector.getInstance(BlueprintFactory.class)); - HostRequest.init(injector.getInstance(HostRoleCommandFactory.class)); + AmbariContext.init(injector.getInstance(HostRoleCommandFactory.class)); PermissionResourceProvider.init(injector.getInstance(PermissionDAO.class)); ViewPermissionResourceProvider.init(injector.getInstance(PermissionDAO.class)); http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java index 3994a7b..08a56d0 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java @@ -111,7 +111,6 @@ import org.apache.ambari.server.state.scheduler.RequestExecutionImpl; import org.apache.ambari.server.state.stack.OsFamily; import org.apache.ambari.server.state.svccomphost.ServiceComponentHostImpl; import org.apache.ambari.server.topology.BlueprintFactory; -import org.apache.ambari.server.topology.TopologyManager; import org.apache.ambari.server.view.ViewInstanceHandlerList; import org.eclipse.jetty.server.SessionIdManager; import org.eclipse.jetty.server.SessionManager; @@ -324,7 +323,6 @@ public class ControllerModule extends AbstractModule { bind(ExecutionScheduler.class).to(ExecutionSchedulerImpl.class); bind(DBAccessor.class).to(DBAccessorImpl.class); bind(ViewInstanceHandlerList.class).to(AmbariHandlerList.class); - bind(TopologyManager.class); requestStaticInjection(ExecutionCommandWrapper.class); requestStaticInjection(DatabaseChecker.class); http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java index e4acea2..9318db9 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java @@ -86,6 +86,11 @@ public class ExportBlueprintRequest implements TopologyRequest { } @Override + public Type getType() { + return Type.EXPORT; + } + + @Override public Blueprint getBlueprint() { return blueprint; } @@ -105,6 +110,11 @@ public class ExportBlueprintRequest implements TopologyRequest { return Collections.emptyList(); } + @Override + public String getCommandDescription() { + return String.format("Export Command For Cluster '%s'", clusterName); + } + // ----- private instance methods ------------------------------------------ http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java index 30627eb..818147b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java @@ -355,13 +355,13 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro installProperties.put(HOST_COMPONENT_DESIRED_STATE_PROPERTY_ID, "INSTALLED"); Map<String, String> requestInfo = new HashMap<String, String>(); - requestInfo.put("context", "Install components on added hosts"); + requestInfo.put("context", String.format("Install components on host %s", hostname)); Request installRequest = PropertyHelper.getUpdateRequest(installProperties, requestInfo); Predicate statePredicate = new EqualsPredicate<String>(HOST_COMPONENT_STATE_PROPERTY_ID, "INIT"); Predicate clusterPredicate = new EqualsPredicate<String>(HOST_COMPONENT_CLUSTER_NAME_PROPERTY_ID, cluster); // single host - Predicate hostPredicate = new EqualsPredicate(HOST_COMPONENT_HOST_NAME_PROPERTY_ID, hostname); + Predicate hostPredicate = new EqualsPredicate<String>(HOST_COMPONENT_HOST_NAME_PROPERTY_ID, hostname); //Predicate hostPredicate = new OrPredicate(hostPredicates.toArray(new Predicate[hostPredicates.size()])); Predicate hostAndStatePredicate = new AndPredicate(statePredicate, hostPredicate); Predicate installPredicate = new AndPredicate(hostAndStatePredicate, clusterPredicate); @@ -387,10 +387,10 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro UnsupportedPropertyException, NoSuchParentResourceException { Map<String, String> requestInfo = new HashMap<String, String>(); - requestInfo.put("context", "Start components on added hosts"); + requestInfo.put("context", String.format("Start components on host %s", hostName)); Predicate clusterPredicate = new EqualsPredicate<String>(HOST_COMPONENT_CLUSTER_NAME_PROPERTY_ID, cluster); - Predicate hostPredicate = new EqualsPredicate(HOST_COMPONENT_HOST_NAME_PROPERTY_ID, hostName); + Predicate hostPredicate = new EqualsPredicate<String>(HOST_COMPONENT_HOST_NAME_PROPERTY_ID, hostName); //Predicate hostPredicate = new OrPredicate(hostPredicates.toArray(new Predicate[hostPredicates.size()])); RequestStageContainer requestStages; @@ -742,12 +742,32 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro RequestStageContainer requestStages = modifyResources(new Command<RequestStageContainer>() { @Override public RequestStageContainer invoke() throws AmbariException { - return updateHostComponents(stages, requests, request.getRequestInfoProperties(), - runSmokeTest); + RequestStageContainer stageContainer = null; + int retriesRemaining = 100; + do { + try { + stageContainer = updateHostComponents(stages, requests, request.getRequestInfoProperties(), + runSmokeTest); + } catch (Exception e) { + LOG.info("Caught an exception while updating host components, retrying : " + e); + if (--retriesRemaining == 0) { + e.printStackTrace(); + throw new RuntimeException("Update Host request submission failed: " + e, e); + } else { + try { + Thread.sleep(250); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Update Host request submission failed: " + e, e); + } + } + } + } while (stageContainer == null); + + return stageContainer; } }); notifyUpdate(Resource.Type.HostComponent, request, predicate); - return requestStages; } http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java index 07c0e58..47a4ce0 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java @@ -538,7 +538,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider { } } - public RequestStatusResponse install(final String hostname, final String cluster) + public RequestStatusResponse install(final String cluster, final String hostname) throws ResourceAlreadyExistsException, SystemException, NoSuchParentResourceException, @@ -549,7 +549,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider { install(cluster, hostname); } - public RequestStatusResponse start(final String hostname, final String cluster) + public RequestStatusResponse start(final String cluster, final String hostname) throws ResourceAlreadyExistsException, SystemException, NoSuchParentResourceException, http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java index 3da92f1..a1a0ac6 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java @@ -21,7 +21,6 @@ package org.apache.ambari.server.controller.internal; import org.apache.ambari.server.api.predicate.InvalidQueryException; -import org.apache.ambari.server.api.predicate.PredicateCompiler; import org.apache.ambari.server.stack.NoSuchStackException; import org.apache.ambari.server.topology.Blueprint; import org.apache.ambari.server.topology.BlueprintFactory; @@ -46,7 +45,6 @@ import java.util.Map; public class ProvisionClusterRequest implements TopologyRequest { private static BlueprintFactory blueprintFactory; - private static PredicateCompiler predicateCompiler = new PredicateCompiler(); private static ConfigurationFactory configurationFactory = new ConfigurationFactory(); private String clusterName; @@ -90,6 +88,11 @@ public class ProvisionClusterRequest implements TopologyRequest { } @Override + public Type getType() { + return Type.PROVISION; + } + + @Override public Blueprint getBlueprint() { return blueprint; } @@ -110,6 +113,11 @@ public class ProvisionClusterRequest implements TopologyRequest { return Collections.<TopologyValidator>singletonList(new RequiredPasswordValidator(defaultPassword)); } + @Override + public String getCommandDescription() { + return String.format("Provision Cluster '%s'", clusterName); + } + private void parseBlueprint(Map<String, Object> properties) throws NoSuchStackException, NoSuchBlueprintException { String blueprintName = String.valueOf(properties.get(ClusterResourceProvider.BLUEPRINT_PROPERTY_ID)); blueprint = blueprintFactory.getBlueprint(blueprintName); @@ -154,7 +162,7 @@ public class ProvisionClusterRequest implements TopologyRequest { String predicate = hostProperties.get("host_predicate"); if (predicate != null && ! predicate.isEmpty()) { try { - hostGroupInfo.setPredicate(predicateCompiler.compile(predicate)); + hostGroupInfo.setPredicate(predicate); } catch (InvalidQueryException e) { throw new InvalidTopologyTemplateException( String.format("Unable to compile host predicate '%s': %s", predicate, e), e); http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java index f3e45aa..1530a3e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java @@ -20,7 +20,6 @@ package org.apache.ambari.server.controller.internal; import org.apache.ambari.server.api.predicate.InvalidQueryException; -import org.apache.ambari.server.api.predicate.PredicateCompiler; import org.apache.ambari.server.controller.spi.Request; import org.apache.ambari.server.stack.NoSuchStackException; import org.apache.ambari.server.topology.Blueprint; @@ -42,10 +41,11 @@ import java.util.Map; public class ScaleClusterRequest implements TopologyRequest { private static BlueprintFactory blueprintFactory; - private static final PredicateCompiler predicateCompiler = new PredicateCompiler(); private String clusterName; + private Blueprint blueprint; + private Map<String, HostGroupInfo> hostGroupInfoMap = new HashMap<String, HostGroupInfo>(); public static void init(BlueprintFactory factory) { @@ -62,15 +62,57 @@ public class ScaleClusterRequest implements TopologyRequest { } } + @Override + public String getClusterName() { + return clusterName; + } + + @Override + public Type getType() { + return Type.SCALE; + } + + @Override + public Blueprint getBlueprint() { + return blueprint; + } + + @Override + public Configuration getConfiguration() { + // currently don't allow cluster scoped configuration in scaling operation + return new Configuration(Collections.<String, Map<String, String>>emptyMap(), + Collections.<String, Map<String, Map<String, String>>>emptyMap()); + } + + @Override + public Map<String, HostGroupInfo> getHostGroupInfo() { + return hostGroupInfoMap; + } + + @Override + public List<TopologyValidator> getTopologyValidators() { + return Collections.emptyList(); + } + + @Override + public String getCommandDescription() { + return String.format("Scale Cluster '%s' (+%s hosts)", clusterName, getTotalRequestedHostCount()); + } + private void parseHostGroup(Map<String, Object> properties) throws InvalidTopologyTemplateException { + String blueprintName = String.valueOf(properties.get(HostResourceProvider.BLUEPRINT_PROPERTY_ID)); + if (blueprint == null) { + blueprint = parseBlueprint(blueprintName); + } else if (! blueprintName.equals(blueprint.getName())) { + throw new InvalidTopologyTemplateException( + "Currently, a scaling request may only refer to a single blueprint"); + } + String hgName = String.valueOf(properties.get(HostResourceProvider.HOSTGROUP_PROPERTY_ID)); //todo: need to use fully qualified host group name. For now, disregard name collisions across BP's HostGroupInfo hostGroupInfo = hostGroupInfoMap.get(hgName); if (hostGroupInfo == null) { - String bpName = String.valueOf(properties.get(HostResourceProvider.BLUEPRINT_PROPERTY_ID)); - Blueprint blueprint = parseBlueprint(bpName); - if (blueprint.getHostGroup(hgName) == null) { throw new InvalidTopologyTemplateException("Invalid host group specified in request: " + hgName); } @@ -78,15 +120,18 @@ public class ScaleClusterRequest implements TopologyRequest { hostGroupInfoMap.put(hgName, hostGroupInfo); } + // specifying configuration is scaling request isn't permitted + hostGroupInfo.setConfiguration(new Configuration(Collections.<String, Map<String, String>>emptyMap(), + Collections.<String, Map<String, Map<String, String>>>emptyMap())); + // process host_name and host_count if (properties.containsKey("host_count")) { - //todo: validate the host_name and host_predicate are not both specified for same group //todo: validate that when predicate is specified that only a single host group entry is specified String predicate = String.valueOf(properties.get("host_predicate")); if (predicate != null && ! predicate.isEmpty()) { try { - hostGroupInfo.setPredicate(predicateCompiler.compile(predicate)); + hostGroupInfo.setPredicate(predicate); } catch (InvalidQueryException e) { throw new InvalidTopologyTemplateException( String.format("Unable to compile host predicate '%s': %s", predicate, e), e); @@ -105,33 +150,6 @@ public class ScaleClusterRequest implements TopologyRequest { } } - @Override - public String getClusterName() { - return clusterName; - } - - @Override - public Blueprint getBlueprint() { - // bp is only set at HG level from scaling operations - return null; - } - - @Override - public Configuration getConfiguration() { - // currently don't allow cluster scoped configuration in scaling operation - return null; - } - - @Override - public Map<String, HostGroupInfo> getHostGroupInfo() { - return hostGroupInfoMap; - } - - @Override - public List<TopologyValidator> getTopologyValidators() { - return Collections.emptyList(); - } - private Blueprint parseBlueprint(String blueprintName) throws InvalidTopologyTemplateException { Blueprint blueprint; try { @@ -153,4 +171,12 @@ public class ScaleClusterRequest implements TopologyRequest { return hostname != null ? hostname : String.valueOf(properties.get(HostResourceProvider.HOST_NAME_NO_CATEGORY_PROPERTY_ID)); } + + private int getTotalRequestedHostCount() { + int count = 0; + for (HostGroupInfo groupInfo : getHostGroupInfo().values()) { + count += groupInfo.getRequestedHostCount(); + } + return count; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java index 7167449..38b5a3c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java @@ -36,6 +36,7 @@ import org.apache.ambari.server.controller.StackServiceRequest; import org.apache.ambari.server.controller.StackServiceResponse; import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.state.AutoDeployInfo; +import org.apache.ambari.server.state.ComponentInfo; import org.apache.ambari.server.state.DependencyInfo; import org.apache.ambari.server.state.PropertyInfo; import org.apache.ambari.server.topology.Cardinality; @@ -140,11 +141,8 @@ public class Stack { * the management controller (not {@code null}). * @throws AmbariException */ - public Stack(StackEntity stack, - AmbariManagementController ambariManagementController) - throws AmbariException { - this(stack.getStackName(), stack.getStackVersion(), - ambariManagementController); + public Stack(StackEntity stack, AmbariManagementController ambariManagementController) throws AmbariException { + this(stack.getStackName(), stack.getStackVersion(), ambariManagementController); } /** @@ -236,6 +234,28 @@ public class Stack { } /** + * Get info for the specified component. + * + * @param component component name + * + * @return component information for the requested component + * or null if the component doesn't exist in the stack + */ + public ComponentInfo getComponentInfo(String component) { + ComponentInfo componentInfo = null; + String service = getServiceForComponent(component); + if (service != null) { + try { + componentInfo = controller.getAmbariMetaInfo().getComponent( + getName(), getVersion(), service, component); + } catch (AmbariException e) { + // just return null if component doesn't exist + } + } + return componentInfo; + } + + /** * Get all configuration types, including excluded types for the specified service. * * @param service service name http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java index a11ec33..1457f3c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java @@ -25,6 +25,7 @@ import org.apache.ambari.server.orm.RequiresSession; import org.apache.ambari.server.orm.entities.TopologyHostGroupEntity; import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; import java.util.List; @Singleton @@ -41,6 +42,17 @@ public class TopologyHostGroupDAO { } @RequiresSession + public TopologyHostGroupEntity findByRequestIdAndName(long topologyRequestId, String name) { + TypedQuery<TopologyHostGroupEntity> query = entityManagerProvider.get().createNamedQuery( + "TopologyHostGroupEntity.findByRequestIdAndName", TopologyHostGroupEntity.class); + + query.setParameter("requestId", topologyRequestId); + query.setParameter("name", name); + + return query.getSingleResult(); + } + + @RequiresSession public List<TopologyHostGroupEntity> findAll() { return daoUtils.selectAll(entityManagerProvider.get(), TopologyHostGroupEntity.class); } http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostTaskDAO.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostTaskDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostTaskDAO.java new file mode 100644 index 0000000..031601a --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostTaskDAO.java @@ -0,0 +1,73 @@ +/** + * 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.orm.dao; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import com.google.inject.persist.Transactional; +import org.apache.ambari.server.orm.RequiresSession; +import org.apache.ambari.server.orm.entities.TopologyHostTaskEntity; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import java.util.Collection; +import java.util.List; + +@Singleton +public class TopologyHostTaskDAO { + @Inject + Provider<EntityManager> entityManagerProvider; + + @Inject + DaoUtils daoUtils; + + @RequiresSession + public TopologyHostTaskEntity findById(Long id) { + return entityManagerProvider.get().find(TopologyHostTaskEntity.class, id); + } + + public Collection<TopologyHostTaskEntity> findByHostRequest(Long id) { + TypedQuery<TopologyHostTaskEntity> query = entityManagerProvider.get() + .createNamedQuery("TopologyHostTaskEntity.findByHostRequest", TopologyHostTaskEntity.class); + + query.setParameter("hostRequestId", id); + return daoUtils.selectList(query); + } + + @RequiresSession + public List<TopologyHostTaskEntity> findAll() { + return daoUtils.selectAll(entityManagerProvider.get(), TopologyHostTaskEntity.class); + } + + @Transactional + public void create(TopologyHostTaskEntity requestEntity) { + entityManagerProvider.get().persist(requestEntity); + } + + @Transactional + public TopologyHostTaskEntity merge(TopologyHostTaskEntity requestEntity) { + return entityManagerProvider.get().merge(requestEntity); + } + + @Transactional + public void remove(TopologyHostTaskEntity requestEntity) { + entityManagerProvider.get().remove(requestEntity); + } +} + http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyLogicalTaskDAO.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyLogicalTaskDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyLogicalTaskDAO.java new file mode 100644 index 0000000..f0331cc --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyLogicalTaskDAO.java @@ -0,0 +1,63 @@ +/** + * 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.orm.dao; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import com.google.inject.persist.Transactional; +import org.apache.ambari.server.orm.RequiresSession; +import org.apache.ambari.server.orm.entities.TopologyLogicalTaskEntity; + +import javax.persistence.EntityManager; +import java.util.List; + +@Singleton +public class TopologyLogicalTaskDAO { + @Inject + Provider<EntityManager> entityManagerProvider; + + @Inject + DaoUtils daoUtils; + + @RequiresSession + public TopologyLogicalTaskEntity findById(Long id) { + return entityManagerProvider.get().find(TopologyLogicalTaskEntity.class, id); + } + + @RequiresSession + public List<TopologyLogicalTaskEntity> findAll() { + return daoUtils.selectAll(entityManagerProvider.get(), TopologyLogicalTaskEntity.class); + } + + @Transactional + public void create(TopologyLogicalTaskEntity logicalTaskEntity) { + entityManagerProvider.get().persist(logicalTaskEntity); + } + + @Transactional + public TopologyLogicalTaskEntity merge(TopologyLogicalTaskEntity logicalTaskEntity) { + return entityManagerProvider.get().merge(logicalTaskEntity); + } + + @Transactional + public void remove(TopologyLogicalTaskEntity logicalTaskEntity) { + entityManagerProvider.get().remove(logicalTaskEntity); + } +} + http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java index 21813ba..ada924a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java @@ -63,9 +63,6 @@ public class BlueprintEntity { @OneToMany(cascade = CascadeType.ALL, mappedBy = "blueprint") private Collection<BlueprintConfigEntity> configurations; - @Transient - private static Gson jsonSerializer = new Gson(); - /** * Get the blueprint name. http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java index 3448b65..0a81286 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java @@ -22,19 +22,37 @@ import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.Lob; import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Table; +import javax.persistence.TableGenerator; import java.util.Collection; @Entity @Table(name = "topology_hostgroup") +@NamedQueries({ + @NamedQuery(name = "TopologyHostGroupEntity.findByRequestIdAndName", + query = "SELECT req FROM TopologyHostGroupEntity req WHERE req.topologyRequestEntity.id = :requestId AND req.name = :name") +}) +@TableGenerator(name = "topology_host_group_id_generator", table = "ambari_sequences", + pkColumnName = "sequence_name", valueColumnName = "sequence_value", + pkColumnValue = "topology_host_group_id_seq", initialValue = 0) public class TopologyHostGroupEntity { @Id - @Column(name = "name", length = 255, nullable = false) + @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_host_group_id_generator") + @Column(name = "id", nullable = false, updatable = false) + private Long id; + + @Column(name = "name", nullable = false, updatable = false) + @Basic(fetch = FetchType.LAZY) + @Lob private String name; @Column(name = "group_properties") @@ -57,6 +75,14 @@ public class TopologyHostGroupEntity { @OneToMany(mappedBy = "topologyHostGroupEntity", cascade = CascadeType.ALL) private Collection<TopologyHostRequestEntity> topologyHostRequestEntities; + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public String getName() { return name; } http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java index 36c2782..8ae8aa6 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java @@ -48,7 +48,7 @@ public class TopologyHostInfoEntity { private String predicate; @ManyToOne - @JoinColumn(name = "group_name", referencedColumnName = "name", nullable = false) + @JoinColumn(name = "group_id", referencedColumnName = "id", nullable = false) private TopologyHostGroupEntity topologyHostGroupEntity; public Long getId() { @@ -59,8 +59,8 @@ public class TopologyHostInfoEntity { this.id = id; } - public String getGroupName() { - return topologyHostGroupEntity != null ? topologyHostGroupEntity.getName() : null; + public Long getGroupId() { + return topologyHostGroupEntity.getId(); } public String getFqdn() { http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java index 2f42d80..4e05ea1 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java @@ -32,12 +32,9 @@ import java.util.Collection; @Entity @Table(name = "topology_host_request") -@TableGenerator(name = "topology_host_request_id_generator", table = "ambari_sequences", - pkColumnName = "sequence_name", valueColumnName = "sequence_value", - pkColumnValue = "topology_host_request_id_seq", initialValue = 0) public class TopologyHostRequestEntity { @Id - @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_request_id_generator") +// @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_host_request_id_generator") @Column(name = "id", nullable = false, updatable = false) private Long id; @@ -52,7 +49,7 @@ public class TopologyHostRequestEntity { private TopologyLogicalRequestEntity topologyLogicalRequestEntity; @ManyToOne - @JoinColumn(name = "group_name", referencedColumnName = "name", nullable = false) + @JoinColumn(name = "group_id", referencedColumnName = "id", nullable = false) private TopologyHostGroupEntity topologyHostGroupEntity; @OneToMany(mappedBy = "topologyHostRequestEntity", cascade = CascadeType.ALL, orphanRemoval = true) @@ -70,8 +67,8 @@ public class TopologyHostRequestEntity { return topologyLogicalRequestEntity != null ? topologyLogicalRequestEntity.getTopologyRequestId() : null; } - public String getHostGroupName() { - return topologyHostGroupEntity != null ? topologyHostGroupEntity.getName() : null; + public Long getHostGroupId() { + return topologyHostGroupEntity.getId(); } public Long getStageId() { http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java index 2c31bb5..49d3a97 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java @@ -25,6 +25,8 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Table; @@ -36,6 +38,10 @@ import java.util.Collection; @TableGenerator(name = "topology_host_task_id_generator", table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value", pkColumnValue = "topology_host_task_id_seq", initialValue = 0) +@NamedQueries({ + @NamedQuery(name = "TopologyHostTaskEntity.findByHostRequest", + query = "SELECT req FROM TopologyHostTaskEntity req WHERE req.topologyHostRequestEntity.id = :hostRequestId") +}) public class TopologyHostTaskEntity { @Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_host_task_id_generator") http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java index 023a058..4d255b2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java @@ -33,12 +33,8 @@ import java.util.Collection; @Entity @Table(name = "topology_logical_request") -@TableGenerator(name = "topology_logical_request_id_generator", table = "ambari_sequences", - pkColumnName = "sequence_name", valueColumnName = "sequence_value", - pkColumnValue = "topology_logical_request_id_seq", initialValue = 0) public class TopologyLogicalRequestEntity { @Id - @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_logical_request_id_generator") @Column(name = "id", nullable = false, updatable = false) private Long id; http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java new file mode 100644 index 0000000..e6c43ef --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java @@ -0,0 +1,499 @@ +/** + * 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 + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * 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.topology; + +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 java.util.concurrent.atomic.AtomicLong; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.ClusterNotFoundException; +import org.apache.ambari.server.Role; +import org.apache.ambari.server.RoleCommand; +import org.apache.ambari.server.actionmanager.HostRoleCommand; +import org.apache.ambari.server.actionmanager.HostRoleCommandFactory; +import org.apache.ambari.server.actionmanager.HostRoleStatus; +import org.apache.ambari.server.controller.AmbariManagementController; +import org.apache.ambari.server.controller.AmbariServer; +import org.apache.ambari.server.controller.ClusterRequest; +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.ServiceComponentHostRequest; +import org.apache.ambari.server.controller.ServiceComponentRequest; +import org.apache.ambari.server.controller.ServiceRequest; +import org.apache.ambari.server.controller.internal.AbstractResourceProvider; +import org.apache.ambari.server.controller.internal.ComponentResourceProvider; +import org.apache.ambari.server.controller.internal.ConfigGroupResourceProvider; +import org.apache.ambari.server.controller.internal.HostComponentResourceProvider; +import org.apache.ambari.server.controller.internal.HostResourceProvider; +import org.apache.ambari.server.controller.internal.RequestImpl; +import org.apache.ambari.server.controller.internal.ServiceResourceProvider; +import org.apache.ambari.server.controller.internal.Stack; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.ClusterControllerHelper; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.Clusters; +import org.apache.ambari.server.state.Config; +import org.apache.ambari.server.state.ConfigImpl; +import org.apache.ambari.server.state.DesiredConfig; +import org.apache.ambari.server.state.Host; +import org.apache.ambari.server.state.SecurityType; +import org.apache.ambari.server.state.StackId; +import org.apache.ambari.server.state.configgroup.ConfigGroup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides topology related information as well as access to the core Ambari functionality. + */ +public class AmbariContext { + + public enum TaskType {INSTALL, START} + + private static PersistedState persistedState = new PersistedStateImpl(); + private static AmbariManagementController controller; + //todo: task id's. Use existing mechanism for getting next task id sequence + private final static AtomicLong nextTaskId = new AtomicLong(10000); + + private static HostRoleCommandFactory hostRoleCommandFactory; + private static HostResourceProvider hostResourceProvider; + private static ServiceResourceProvider serviceResourceProvider; + private static ComponentResourceProvider componentResourceProvider; + private HostComponentResourceProvider hostComponentResourceProvider; + + private final static Logger LOG = LoggerFactory.getLogger(TopologyManager.class); + + public boolean isClusterKerberosEnabled(String clusterName) { + Cluster cluster; + try { + cluster = getController().getClusters().getCluster(clusterName); + } catch (AmbariException e) { + throw new RuntimeException("Parent Cluster resource doesn't exist. clusterName= " + clusterName); + } + return cluster.getSecurityType() == SecurityType.KERBEROS; + } + + //todo: change return type to a topology abstraction + public HostRoleCommand createAmbariTask(long requestId, long stageId, String component, String host, TaskType type) { + HostRoleCommand task = hostRoleCommandFactory.create(host, Role.valueOf(component), null, RoleCommand.valueOf(type.name())); + task.setStatus(HostRoleStatus.PENDING); + task.setCommandDetail(String.format("Logical Task: %s component %s on host %s", type.name(), component, host)); + task.setTaskId(nextTaskId.getAndIncrement()); + task.setRequestId(requestId); + task.setStageId(stageId); + + return task; + } + + //todo: change return type to a topology abstraction + public HostRoleCommand createAmbariTask(long taskId, long requestId, long stageId, + String component, String host, TaskType type) { + synchronized (nextTaskId) { + if (nextTaskId.get() <= taskId) { + nextTaskId.set(taskId + 1); + } + } + + HostRoleCommand task = hostRoleCommandFactory.create( + host, Role.valueOf(component), null, RoleCommand.valueOf(type.name())); + task.setStatus(HostRoleStatus.PENDING); + task.setCommandDetail(String.format("Logical Task: %s component %s on host %s", + type.name(), component, host)); + task.setTaskId(taskId); + task.setRequestId(requestId); + task.setStageId(stageId); + + return task; + } + + public HostRoleCommand getPhysicalTask(long id) { + return getController().getActionManager().getTaskById(id); + } + + public void createAmbariResources(ClusterTopology topology) { + String clusterName = topology.getClusterName(); + Stack stack = topology.getBlueprint().getStack(); + createAmbariClusterResource(clusterName, stack.getName(), stack.getVersion()); + createAmbariServiceAndComponentResources(topology); + } + + public void createAmbariClusterResource(String clusterName, String stackName, String stackVersion) { + String stackInfo = String.format("%s-%s", stackName, stackVersion); + ClusterRequest clusterRequest = new ClusterRequest(null, clusterName, stackInfo, null); + try { + getController().createCluster(clusterRequest); + } catch (AmbariException e) { + e.printStackTrace(); + throw new RuntimeException("Failed to create Cluster resource: " + e, e); + } + } + + public void createAmbariServiceAndComponentResources(ClusterTopology topology) { + String clusterName = topology.getClusterName(); + Collection<String> services = topology.getBlueprint().getServices(); + + try { + Cluster cluster = getController().getClusters().getCluster(clusterName); + services.removeAll(cluster.getServices().keySet()); + } catch (AmbariException e) { + e.printStackTrace(); + throw new RuntimeException("Failed to persist service and component resources: " + e, e); + } + Set<ServiceRequest> serviceRequests = new HashSet<ServiceRequest>(); + Set<ServiceComponentRequest> componentRequests = new HashSet<ServiceComponentRequest>(); + for (String service : services) { + serviceRequests.add(new ServiceRequest(clusterName, service, null)); + for (String component : topology.getBlueprint().getComponents(service)) { + componentRequests.add(new ServiceComponentRequest(clusterName, service, component, null)); + } + } + try { + getServiceResourceProvider().createServices(serviceRequests); + getComponentResourceProvider().createComponents(componentRequests); + } catch (AmbariException e) { + e.printStackTrace(); + throw new RuntimeException("Failed to persist service and component resources: " + e, e); + } + } + + public void createAmbariHostResources(String clusterName, String hostName, Map<String, Collection<String>> components) { + Host host; + try { + host = getController().getClusters().getHost(hostName); + } catch (AmbariException e) { + // system exception, shouldn't occur + throw new RuntimeException(String.format( + "Unable to obtain host instance '%s' when persisting host resources", hostName)); + } + + Map<String, Object> properties = new HashMap<String, Object>(); + properties.put(HostResourceProvider.HOST_CLUSTER_NAME_PROPERTY_ID, clusterName); + properties.put(HostResourceProvider.HOST_NAME_PROPERTY_ID, hostName); + properties.put(HostResourceProvider.HOST_RACK_INFO_PROPERTY_ID, host.getRackInfo()); + + try { + getHostResourceProvider().createHosts(new RequestImpl(null, Collections.singleton(properties), null, null)); + } catch (AmbariException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Unable to create host resource for host '%s': %s", + hostName, e.toString()), e); + } + + Set<ServiceComponentHostRequest> requests = new HashSet<ServiceComponentHostRequest>(); + for (Map.Entry<String, Collection<String>> entry : components.entrySet()) { + String service = entry.getKey(); + for (String component : entry.getValue()) { + //todo: handle this in a generic manner. These checks are all over the code + if (!component.equals("AMBARI_SERVER")) { + requests.add(new ServiceComponentHostRequest(clusterName, service, component, hostName, null)); + } + } + } + try { + getController().createHostComponents(requests); + } catch (AmbariException e) { + e.printStackTrace(); + throw new RuntimeException(String.format("Unable to create host component resource for host '%s': %s", + hostName, e.toString()), e); + } + } + + /** + * 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 + */ + //todo: do once for all configs + public void convertGlobalProperties(ClusterTopology topology, + Map<String, Map<String, String>> blueprintConfigurations) { + + Stack stack = topology.getBlueprint().getStack(); + StackId stackId = new StackId(stack.getName(), stack.getVersion()); + getController().getConfigHelper().moveDeprecatedGlobals( + stackId, blueprintConfigurations, topology.getClusterName()); + } + + public Long getNextRequestId() { + return getController().getActionManager().getNextRequestId(); + } + + public synchronized AmbariManagementController getController() { + if (controller == null) { + controller = AmbariServer.getController(); + } + return controller; + } + + public static void init(HostRoleCommandFactory factory) { + hostRoleCommandFactory = factory; + } + + public void registerHostWithConfigGroup(String hostName, ClusterTopology topology, String groupName) { + try { + if (!addHostToExistingConfigGroups(hostName, topology, groupName)) { + createConfigGroupsAndRegisterHost(topology, groupName); + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Unable to register config group for host: " + hostName); + } + } + + public RequestStatusResponse installHost(String hostName, String clusterName) { + try { + return getHostResourceProvider().install(clusterName, hostName); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("INSTALL Host request submission failed: " + e, e); + } + } + + public RequestStatusResponse startHost(String hostName, String clusterName) { + try { + return getHostComponentResourceProvider().start(clusterName, hostName); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("START Host request submission failed: " + e, e); + } + } + + /** + * 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 cluster name + * @param stackName stack name + * @param stackVersion stack version + */ + public void persistInstallStateForUI(String clusterName, String stackName, String stackVersion) { + String stackInfo = String.format("%s-%s", stackName, stackVersion); + ClusterRequest clusterRequest = new ClusterRequest(null, clusterName, "INSTALLED", null, stackInfo, null); + + try { + getController().updateClusters(Collections.singleton(clusterRequest), null); + } catch (AmbariException e) { + LOG.error("Unable to set install state for UI", e); + } + } + + //todo: non topology type shouldn't be returned + public List<ConfigurationRequest> createConfigurationRequests(Map<String, Object> clusterProperties) { + return AbstractResourceProvider.getConfigurationRequests("Clusters", clusterProperties); + } + + public void setConfigurationOnCluster(ClusterRequest clusterRequest) { + try { + getController().updateClusters(Collections.singleton(clusterRequest), null); + } catch (AmbariException e) { + e.printStackTrace(); + throw new RuntimeException("Failed to set configurations on cluster: " + e, e); + } + } + + public boolean doesConfigurationWithTagExist(String clusterName, String tag) { + boolean isTopologyResolved = false; + try { + Cluster cluster = getController().getClusters().getCluster(clusterName); + Collection<DesiredConfig> desiredConfigs = cluster.getDesiredConfigs().values(); + for (DesiredConfig config : desiredConfigs) { + if (config.getTag().equals(tag)) { + isTopologyResolved = true; + break; + } + } + } catch (ClusterNotFoundException e) { + LOG.info("Attempted to determine if configuration is topology resolved for a non-existent cluster: {}", + clusterName); + } catch (AmbariException e) { + throw new RuntimeException( + "Unable to determine if cluster config is topology resolved due to unknown error: " + e, e); + } + + return isTopologyResolved; + } + + public PersistedState getPersistedTopologyState() { + return persistedState; + } + + public boolean isHostRegisteredWithCluster(String cluster, String host) { + boolean found = false; + try { + Collection<Host> hosts = getController().getClusters().getCluster(cluster).getHosts(); + for (Host h : hosts) { + if (h.getHostName().equals(host)) { + found = true; + break; + } + } + } catch (AmbariException e) { + throw new RuntimeException(String.format("Unable to get hosts for cluster '%s': %s", cluster, e), e); + } + return found; + } + + /** + * Add the new host to an existing config group. + */ + private boolean addHostToExistingConfigGroups(String hostName, ClusterTopology topology, String groupName) { + boolean addedHost = false; + Clusters clusters; + Cluster cluster; + try { + clusters = getController().getClusters(); + cluster = clusters.getCluster(topology.getClusterName()); + } catch (AmbariException e) { + throw new RuntimeException(String.format( + "Attempt to add hosts to a non-existent cluster: '%s'", topology.getClusterName())); + } + // I don't know of a method to get config group by name + //todo: add a method to get config group by name + Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups(); + String qualifiedGroupName = getConfigurationGroupName(topology.getBlueprint().getName(), groupName); + for (ConfigGroup group : configGroups.values()) { + if (group.getName().equals(qualifiedGroupName)) { + try { + group.addHost(clusters.getHost(hostName)); + group.persist(); + addedHost = true; + } catch (AmbariException e) { + // shouldn't occur, this host was just added to the cluster + throw new RuntimeException(String.format( + "Unable to obtain newly created host '%s' from cluster '%s'", hostName, topology.getClusterName())); + } + } + } + return addedHost; + } + + /** + * 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. + */ + private void createConfigGroupsAndRegisterHost(ClusterTopology topology, String groupName) { + + //HostGroupEntity entity = hostGroup.getEntity(); + Map<String, Map<String, Config>> groupConfigs = new HashMap<String, Map<String, Config>>(); + + Stack stack = topology.getBlueprint().getHostGroup(groupName).getStack(); + + // get the host-group config with cluster creation template overrides + Configuration topologyHostGroupConfig = topology. + getHostGroupInfo().get(groupName).getConfiguration(); + + //handling backwards compatibility for group configs + //todo: doesn't belong here + convertGlobalProperties(topology, topologyHostGroupConfig.getProperties()); + + // iterate over topo host group configs which were defined in CCT/HG and BP/HG only, no parent configs + for (Map.Entry<String, Map<String, String>> entry : topologyHostGroupConfig.getProperties().entrySet()) { + String type = entry.getKey(); + String service = stack.getServiceForConfigType(type); + Config config = new ConfigImpl(type); + config.setTag(groupName); + config.setProperties(entry.getValue()); + //todo: attributes + Map<String, Config> serviceConfigs = groupConfigs.get(service); + if (serviceConfigs == null) { + serviceConfigs = new HashMap<String, Config>(); + groupConfigs.put(service, serviceConfigs); + } + serviceConfigs.put(type, config); + } + + String bpName = topology.getBlueprint().getName(); + for (Map.Entry<String, Map<String, Config>> entry : groupConfigs.entrySet()) { + String service = entry.getKey(); + Map<String, Config> serviceConfigs = entry.getValue(); + String absoluteGroupName = getConfigurationGroupName(bpName, groupName); + Collection<String> groupHosts; + + groupHosts = topology.getHostGroupInfo(). + get(groupName).getHostNames(); + + ConfigGroupRequest request = new ConfigGroupRequest( + null, topology.getClusterName(), absoluteGroupName, service, "Host Group Configuration", + new HashSet<String>(groupHosts), serviceConfigs); + + // get the config group provider and create config group resource + ConfigGroupResourceProvider configGroupProvider = (ConfigGroupResourceProvider) + ClusterControllerHelper.getClusterController().ensureResourceProvider(Resource.Type.ConfigGroup); + + try { + configGroupProvider.createResources(Collections.singleton(request)); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to create new configuration group: " + e, e); + } + } + } + + /** + * Get a config group name based on a bp and host group. + * + * @param bpName blueprint name + * @param hostGroupName host group name + * @return config group name + */ + private String getConfigurationGroupName(String bpName, String hostGroupName) { + return String.format("%s:%s", bpName, hostGroupName); + } + + private synchronized HostResourceProvider getHostResourceProvider() { + if (hostResourceProvider == null) { + hostResourceProvider = (HostResourceProvider) + ClusterControllerHelper.getClusterController().ensureResourceProvider(Resource.Type.Host); + + } + return hostResourceProvider; + } + + private synchronized HostComponentResourceProvider getHostComponentResourceProvider() { + if (hostComponentResourceProvider == null) { + hostComponentResourceProvider = (HostComponentResourceProvider) + ClusterControllerHelper.getClusterController().ensureResourceProvider(Resource.Type.HostComponent); + + } + return hostComponentResourceProvider; + } + + private synchronized ServiceResourceProvider getServiceResourceProvider() { + if (serviceResourceProvider == null) { + serviceResourceProvider = (ServiceResourceProvider) ClusterControllerHelper. + getClusterController().ensureResourceProvider(Resource.Type.Service); + } + return serviceResourceProvider; + } + + private synchronized ComponentResourceProvider getComponentResourceProvider() { + if (componentResourceProvider == null) { + componentResourceProvider = (ComponentResourceProvider) ClusterControllerHelper. + getClusterController().ensureResourceProvider(Resource.Type.Component); + } + return componentResourceProvider; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java index f27d4ab..481d217 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java @@ -229,8 +229,7 @@ public class BlueprintImpl implements Blueprint { } /** - * Process blueprint configurations. This includes obtaining the default configuration properties - * from the stack and overlaying configuration properties specified in the blueprint. + * Process blueprint configurations. */ private void processConfiguration(Collection<BlueprintConfigEntity> configs) { // not setting stack configuration as parent until after host groups are parsed in constructor http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java index 07ea50b..a8c2ff3 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java @@ -19,11 +19,8 @@ package org.apache.ambari.server.topology; import org.apache.ambari.server.AmbariException; -import org.apache.ambari.server.controller.AmbariManagementController; -import org.apache.ambari.server.controller.AmbariServer; import org.apache.ambari.server.controller.ClusterRequest; import org.apache.ambari.server.controller.ConfigurationRequest; -import org.apache.ambari.server.controller.internal.AbstractResourceProvider; import org.apache.ambari.server.controller.internal.BlueprintConfigurationProcessor; import org.apache.ambari.server.controller.internal.ClusterResourceProvider; import org.apache.ambari.server.controller.internal.ConfigurationTopologyException; @@ -47,18 +44,21 @@ public class ClusterConfigurationRequest { protected final static Logger LOG = LoggerFactory.getLogger(ClusterConfigurationRequest.class); + private AmbariContext ambariContext; private ClusterTopology clusterTopology; private BlueprintConfigurationProcessor configurationProcessor; - private AmbariManagementController controller = AmbariServer.getController(); private Stack stack; - public ClusterConfigurationRequest(ClusterTopology clusterTopology) throws AmbariException { + public ClusterConfigurationRequest(AmbariContext ambariContext, ClusterTopology clusterTopology, boolean setInitial) { + this.ambariContext = ambariContext; + this.clusterTopology = clusterTopology; Blueprint blueprint = clusterTopology.getBlueprint(); this.stack = blueprint.getStack(); - this.clusterTopology = clusterTopology; // set initial configuration (not topology resolved) this.configurationProcessor = new BlueprintConfigurationProcessor(clusterTopology); - setConfigurationsOnCluster(clusterTopology, "INITIAL"); + if (setInitial) { + setConfigurationsOnCluster(clusterTopology, TopologyManager.INITIAL_CONFIG_TAG); + } } // get names of required host groups @@ -74,17 +74,15 @@ public class ClusterConfigurationRequest { //log and continue to set configs on cluster to make progress LOG.error("An exception occurred while doing configuration topology update: " + e, e); } - setConfigurationsOnCluster(clusterTopology, "TOPOLOGY_RESOLVED"); + setConfigurationsOnCluster(clusterTopology, TopologyManager.TOPOLOGY_RESOLVED_TAG); } /** * Set all configurations on the cluster resource. * @param clusterTopology cluster topology * @param tag config tag - * - * @throws AmbariException unable to set config on cluster */ - public void setConfigurationsOnCluster(ClusterTopology clusterTopology, String tag) throws AmbariException { + public void setConfigurationsOnCluster(ClusterTopology clusterTopology, String tag) { //todo: also handle setting of host group scoped configuration which is updated by config processor List<BlueprintServiceConfigRequest> listofConfigRequests = new LinkedList<BlueprintServiceConfigRequest>(); @@ -134,11 +132,9 @@ public class ClusterConfigurationRequest { * This method will also send these requests to the management controller. * * @param listOfBlueprintConfigRequests a list of requests to send to the AmbariManagementController. - * - * @throws AmbariException upon any error that occurs during updateClusters */ private void setConfigurationsOnCluster(List<BlueprintServiceConfigRequest> listOfBlueprintConfigRequests, - String tag) throws AmbariException { + String tag) { // iterate over services to deploy for (BlueprintServiceConfigRequest blueprintConfigRequest : listOfBlueprintConfigRequests) { ClusterRequest clusterRequest = null; @@ -189,9 +185,7 @@ public class ClusterConfigurationRequest { null); } - //todo: made getConfigurationRequests static so that I could access from here, where does it belong? - List<ConfigurationRequest> listOfRequests = - AbstractResourceProvider.getConfigurationRequests("Clusters", clusterProperties); + List<ConfigurationRequest> listOfRequests = ambariContext.createConfigurationRequests(clusterProperties); requestsPerService.addAll(listOfRequests); } @@ -199,7 +193,7 @@ public class ClusterConfigurationRequest { if (clusterRequest != null) { clusterRequest.setDesiredConfig(requestsPerService); LOG.info("Sending cluster config update request for service = " + blueprintConfigRequest.getServiceName()); - controller.updateClusters(Collections.singleton(clusterRequest), null); + ambariContext.setConfigurationOnCluster(clusterRequest); } else { LOG.error("ClusterRequest should not be null for service = " + blueprintConfigRequest.getServiceName()); } http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java index e924653..6a7a79b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java @@ -18,6 +18,9 @@ package org.apache.ambari.server.topology; +import org.apache.ambari.server.controller.RequestStatusResponse; +import org.apache.ambari.server.state.SecurityType; + import java.util.Collection; import java.util.Map; @@ -113,4 +116,31 @@ public interface ClusterTopology { * @return true if NameNode HA is enabled; false otherwise */ public boolean isNameNodeHAEnabled(); + + /** + * Determine if the cluster is kerberos enabled. + * + * @return true if the cluster is kerberos enabled; false otherwise + */ + public boolean isClusterKerberosEnabled(); + + /** + * Install the specified host. + * + * @param hostName host name + * @return install response + */ + public RequestStatusResponse installHost(String hostName); + + /** + * Start the specified host. + * + * @param hostName host name + * @return start response + */ + public RequestStatusResponse startHost(String hostName); + + //todo: don't expose ambari context from this class + public AmbariContext getAmbariContext(); + } http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java index 84e90bf..e0e79b3 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java @@ -19,6 +19,8 @@ package org.apache.ambari.server.topology; +import org.apache.ambari.server.controller.RequestStatusResponse; + import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -39,13 +41,13 @@ public class ClusterTopologyImpl implements ClusterTopology { //todo: for example: provision using bp1 and scale using bp2 private Blueprint blueprint; private Configuration configuration; - private final Map<String, HostGroupInfo> hostGroupInfoMap = - new HashMap<String, HostGroupInfo>(); + private final Map<String, HostGroupInfo> hostGroupInfoMap = new HashMap<String, HostGroupInfo>(); + private final AmbariContext ambariContext; //todo: will need to convert all usages of hostgroup name to use fully qualified name (BP/HG) //todo: for now, restrict scaling to the same BP - public ClusterTopologyImpl(TopologyRequest topologyRequest) throws InvalidTopologyException { + public ClusterTopologyImpl(AmbariContext ambariContext, TopologyRequest topologyRequest) throws InvalidTopologyException { this.clusterName = topologyRequest.getClusterName(); // provision cluster currently requires that all hostgroups have same BP so it is ok to use root level BP here this.blueprint = topologyRequest.getBlueprint(); @@ -54,10 +56,12 @@ public class ClusterTopologyImpl implements ClusterTopology { registerHostGroupInfo(topologyRequest.getHostGroupInfo()); validateTopology(topologyRequest.getTopologyValidators()); + this.ambariContext = ambariContext; } //todo: only used in tests, remove. Validators not invoked when this constructor is used. - public ClusterTopologyImpl(String clusterName, + public ClusterTopologyImpl(AmbariContext ambariContext, + String clusterName, Blueprint blueprint, Configuration configuration, Map<String, HostGroupInfo> hostGroupInfo) @@ -68,6 +72,7 @@ public class ClusterTopologyImpl implements ClusterTopology { this.configuration = configuration; registerHostGroupInfo(hostGroupInfo); + this.ambariContext = ambariContext; } @Override @@ -174,6 +179,26 @@ public class ClusterTopologyImpl implements ClusterTopology { } } + @Override + public boolean isClusterKerberosEnabled() { + return ambariContext.isClusterKerberosEnabled(getClusterName()); + } + + @Override + public RequestStatusResponse installHost(String hostName) { + return ambariContext.installHost(hostName, getClusterName()); + } + + @Override + public RequestStatusResponse startHost(String hostName) { + return ambariContext.startHost(hostName, getClusterName()); + } + + @Override + public AmbariContext getAmbariContext() { + return ambariContext; + } + private void registerHostGroupInfo(Map<String, HostGroupInfo> groupInfoMap) throws InvalidTopologyException { checkForDuplicateHosts(groupInfoMap); for (HostGroupInfo hostGroupInfo : groupInfoMap.values() ) { http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java index 07cc1b2..a48f331 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java @@ -18,6 +18,8 @@ package org.apache.ambari.server.topology; +import org.apache.ambari.server.api.predicate.InvalidQueryException; +import org.apache.ambari.server.api.predicate.PredicateCompiler; import org.apache.ambari.server.controller.spi.Predicate; import java.util.Collection; @@ -28,6 +30,8 @@ import java.util.HashSet; */ public class HostGroupInfo { + private static PredicateCompiler predicateCompiler = new PredicateCompiler(); + private String hostGroupName; /** * Hosts contained associated with the host group @@ -38,7 +42,7 @@ public class HostGroupInfo { Configuration configuration; - + String predicateString; Predicate predicate; @@ -81,11 +85,16 @@ public class HostGroupInfo { return configuration; } - public void setPredicate(Predicate predicate) { - this.predicate = predicate; + public void setPredicate(String predicateString) throws InvalidQueryException { + this.predicate = predicateCompiler.compile(predicateString); + this.predicateString = predicateString; } public Predicate getPredicate() { return predicate; } + + public String getPredicateString() { + return predicateString; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java index ce636e2..2932581 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java @@ -29,6 +29,7 @@ public class HostOfferResponse { private final Answer answer; private final String hostGroupName; + private final long hostRequestId; private final List<TopologyTask> tasks; public HostOfferResponse(Answer answer) { @@ -36,12 +37,14 @@ public class HostOfferResponse { throw new IllegalArgumentException("For accepted response, hostgroup name and tasks must be set"); } this.answer = answer; + this.hostRequestId = -1; this.hostGroupName = null; this.tasks = null; } - public HostOfferResponse(Answer answer, String hostGroupName, List<TopologyTask> tasks) { + public HostOfferResponse(Answer answer, long hostRequestId, String hostGroupName, List<TopologyTask> tasks) { this.answer = answer; + this.hostRequestId = hostRequestId; this.hostGroupName = hostGroupName; this.tasks = tasks; } @@ -50,6 +53,10 @@ public class HostOfferResponse { return answer; } + public long getHostRequestId() { + return hostRequestId; + } + //todo: for now assumes a host was added //todo: perhaps a topology modification object that modifies a passed in topology structure? public String getHostGroupName() {
