AMBARI-19381. Heartbeat version transitions must be update Component alongside Cluster (ncole)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/cd245c00 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/cd245c00 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/cd245c00 Branch: refs/heads/trunk Commit: cd245c00abaa5720675324a383e691434eabcf32 Parents: b1bb289 Author: Nate Cole <nc...@hortonworks.com> Authored: Thu Jan 5 05:01:03 2017 -0500 Committer: Nate Cole <nc...@hortonworks.com> Committed: Thu Jan 5 11:49:52 2017 -0500 ---------------------------------------------------------------------- .../server/checks/AbstractCheckDescriptor.java | 2 +- .../controller/ServiceComponentResponse.java | 37 +++-- .../internal/ComponentResourceProvider.java | 11 +- .../internal/UpgradeResourceProvider.java | 2 +- .../listeners/upgrade/StackVersionListener.java | 22 +-- .../server/orm/dao/HostComponentStateDAO.java | 20 +++ .../dao/ServiceComponentDesiredStateDAO.java | 16 ++ .../orm/entities/HostComponentStateEntity.java | 7 +- .../orm/entities/RepositoryVersionEntity.java | 2 - .../ServiceComponentDesiredStateEntity.java | 19 +++ .../entities/ServiceComponentVersionEntity.java | 26 ++- .../ambari/server/state/ServiceComponent.java | 15 ++ .../server/state/ServiceComponentImpl.java | 166 ++++++++++++++++++- .../state/stack/upgrade/ClusterGrouping.java | 3 - .../server/upgrade/UpgradeCatalog300.java | 15 +- .../main/resources/Ambari-DDL-Derby-CREATE.sql | 1 + .../main/resources/Ambari-DDL-MySQL-CREATE.sql | 1 + .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 1 + .../resources/Ambari-DDL-Postgres-CREATE.sql | 1 + .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 1 + .../resources/Ambari-DDL-SQLServer-CREATE.sql | 1 + .../src/main/resources/properties.json | 6 +- .../checks/AbstractCheckDescriptorTest.java | 2 - .../internal/ComponentResourceProviderTest.java | 28 +++- .../controller/internal/RequestImplTest.java | 4 +- .../apache/ambari/server/orm/OrmTestHelper.java | 1 + .../server/state/ServiceComponentTest.java | 72 ++++++++ .../server/upgrade/UpgradeCatalog300Test.java | 48 +++--- 28 files changed, 443 insertions(+), 87 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java index 0046ec6..3a6c45e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/AbstractCheckDescriptor.java @@ -43,8 +43,8 @@ import org.apache.ambari.server.state.stack.PrereqCheckType; import org.apache.ambari.server.state.stack.PrerequisiteCheck; import org.apache.ambari.server.state.stack.UpgradePack; import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper; -import org.apache.commons.collections.CollectionUtils; import org.apache.ambari.server.state.stack.upgrade.UpgradeType; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java index 9dbda20..16f724f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java @@ -21,27 +21,22 @@ package org.apache.ambari.server.controller; import java.util.Map; +import org.apache.ambari.server.state.RepositoryVersionState; + public class ServiceComponentResponse { private Long clusterId; // REF - private String clusterName; // REF - private String serviceName; - private String componentName; - private String displayName; - private String desiredStackVersion; - private String desiredState; - private String category; - - Map<String, Integer> serviceComponentStateCount; - + private Map<String, Integer> serviceComponentStateCount; private boolean recoveryEnabled; + private String desiredVersion; + private RepositoryVersionState repoState; public ServiceComponentResponse(Long clusterId, String clusterName, String serviceName, @@ -50,8 +45,9 @@ public class ServiceComponentResponse { String desiredState, Map<String, Integer> serviceComponentStateCount, boolean recoveryEnabled, - String displayName) { - super(); + String displayName, + String desiredVersion, + RepositoryVersionState repoState) { this.clusterId = clusterId; this.clusterName = clusterName; this.serviceName = serviceName; @@ -61,6 +57,8 @@ public class ServiceComponentResponse { this.desiredState = desiredState; this.serviceComponentStateCount = serviceComponentStateCount; this.recoveryEnabled = recoveryEnabled; + this.desiredVersion = desiredVersion; + this.repoState = repoState; } /** @@ -196,6 +194,21 @@ public class ServiceComponentResponse { this.recoveryEnabled = recoveryEnabled; } + /** + * @return the desired version of the component + */ + public String getDesiredVersion() { + return desiredVersion; + } + + /** + * @return the state of the repository against the desired version + */ + public RepositoryVersionState getRepositoryState() { + return repoState; + } + + @Override public boolean equals(Object o) { if (this == o) return true; http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/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 65cfcaa..ff8d0be 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 @@ -18,7 +18,6 @@ package org.apache.ambari.server.controller.internal; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.EnumSet; import java.util.HashMap; @@ -64,6 +63,7 @@ import org.apache.ambari.server.state.State; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; +import com.google.common.collect.Sets; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; import com.google.inject.persist.Transactional; @@ -89,17 +89,18 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide protected static final String COMPONENT_UNKNOWN_COUNT_PROPERTY_ID = "ServiceComponentInfo/unknown_count"; protected static final String COMPONENT_INSTALL_FAILED_COUNT_PROPERTY_ID = "ServiceComponentInfo/install_failed_count"; protected static final String COMPONENT_RECOVERY_ENABLED_ID = "ServiceComponentInfo/recovery_enabled"; + protected static final String COMPONENT_DESIRED_VERSION = "ServiceComponentInfo/desired_version"; + protected static final String COMPONENT_REPOSITORY_STATE = "ServiceComponentInfo/repository_state"; private static final String TRUE = "true"; //Parameters from the predicate private static final String QUERY_PARAMETERS_RUN_SMOKE_TEST_ID = "params/run_smoke_test"; - private static Set<String> pkPropertyIds = - new HashSet<>(Arrays.asList(new String[]{ + private static Set<String> pkPropertyIds = Sets.newHashSet( COMPONENT_CLUSTER_NAME_PROPERTY_ID, COMPONENT_SERVICE_NAME_PROPERTY_ID, - COMPONENT_COMPONENT_NAME_PROPERTY_ID})); + COMPONENT_COMPONENT_NAME_PROPERTY_ID); private MaintenanceStateHelper maintenanceStateHelper; @@ -188,6 +189,8 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide setResourceProperty(resource, COMPONENT_INIT_COUNT_PROPERTY_ID, response.getServiceComponentStateCount().get("initCount"), requestedIds); setResourceProperty(resource, COMPONENT_UNKNOWN_COUNT_PROPERTY_ID, response.getServiceComponentStateCount().get("unknownCount"), requestedIds); setResourceProperty(resource, COMPONENT_RECOVERY_ENABLED_ID, String.valueOf(response.isRecoveryEnabled()), requestedIds); + setResourceProperty(resource, COMPONENT_DESIRED_VERSION, response.getDesiredVersion(), requestedIds); + setResourceProperty(resource, COMPONENT_REPOSITORY_STATE, response.getRepositoryState(), requestedIds); resources.add(resource); } http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java index 7c90cab..71162e4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java @@ -92,8 +92,8 @@ import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.Config; import org.apache.ambari.server.state.ConfigHelper; import org.apache.ambari.server.state.DesiredConfig; -import org.apache.ambari.server.state.RepositoryType; import org.apache.ambari.server.state.Host; +import org.apache.ambari.server.state.RepositoryType; import org.apache.ambari.server.state.Service; import org.apache.ambari.server.state.ServiceComponent; import org.apache.ambari.server.state.ServiceInfo; http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java index f5a5b0c..a29929d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java @@ -17,9 +17,6 @@ */ package org.apache.ambari.server.events.listeners.upgrade; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.EagerSingleton; import org.apache.ambari.server.api.services.AmbariMetaInfo; @@ -37,7 +34,6 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.eventbus.AllowConcurrentEvents; import com.google.common.eventbus.Subscribe; import com.google.inject.Inject; import com.google.inject.Provider; @@ -58,13 +54,7 @@ public class StackVersionListener { * Logger. */ private final static Logger LOG = LoggerFactory.getLogger(StackVersionListener.class); - private static final String UNKNOWN_VERSION = State.UNKNOWN.toString(); - - /** - * Used to prevent multiple threads from trying to create host alerts - * simultaneously. - */ - private Lock m_stackVersionLock = new ReentrantLock(); + public static final String UNKNOWN_VERSION = State.UNKNOWN.toString(); @Inject private RepositoryVersionDAO repositoryVersionDAO; @@ -83,7 +73,6 @@ public class StackVersionListener { } @Subscribe - @AllowConcurrentEvents public void onAmbariEvent(HostComponentVersionAdvertisedEvent event) { LOG.debug("Received event {}", event); @@ -96,8 +85,6 @@ public class StackVersionListener { return; } - m_stackVersionLock.lock(); - // if the cluster is upgrading, there's no need to update the repo version - // it better be right if (null != event.getRepositoryVersionId() && null == cluster.getUpgradeInProgress()) { @@ -120,6 +107,7 @@ public class StackVersionListener { ComponentInfo componentInfo = metaInfo.getComponent(cluster.getDesiredStackVersion().getStackName(), cluster.getDesiredStackVersion().getStackVersion(), sch.getServiceName(), sch.getServiceComponentName()); ServiceComponent sc = cluster.getService(sch.getServiceName()).getServiceComponent(sch.getServiceComponentName()); + if (componentInfo.isVersionAdvertised() && StringUtils.isNotBlank(newVersion) && !UNKNOWN_VERSION.equalsIgnoreCase(newVersion)) { processComponentAdvertisedVersion(cluster, sch, newVersion, sc); @@ -135,12 +123,11 @@ public class StackVersionListener { processComponentAdvertisedVersion(cluster, sch, newVersion, sc); } } + } catch (Exception e) { LOG.error( "Unable to propagate version for ServiceHostComponent on component: {}, host: {}. Error: {}", sch.getServiceComponentName(), sch.getHostName(), e.getMessage()); - } finally { - m_stackVersionLock.unlock(); } } @@ -158,6 +145,7 @@ public class StackVersionListener { if (StringUtils.isBlank(newVersion)) { return; } + String previousVersion = sch.getVersion(); if (previousVersion == null || UNKNOWN_VERSION.equalsIgnoreCase(previousVersion)) { // value may be "UNKNOWN" when upgrading from older Ambari versions @@ -168,6 +156,8 @@ public class StackVersionListener { } else if (!StringUtils.equals(previousVersion, newVersion)) { processComponentVersionChange(cluster, sc, sch, newVersion); } + + sc.updateRepositoryState(newVersion); } /** http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java index cc7b503..6174912 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostComponentStateDAO.java @@ -207,4 +207,24 @@ public class HostComponentStateDAO { em.clear(); } + + /** + * @param serviceName + * @param componentName + * @param version + * @return a list of host components whose version that does NOT match the give version + */ + @RequiresSession + public List<HostComponentStateEntity> findByServiceAndComponentAndNotVersion(String serviceName, + String componentName, String version) { + + final TypedQuery<HostComponentStateEntity> query = entityManagerProvider.get().createNamedQuery( + "HostComponentStateEntity.findByServiceAndComponentAndNotVersion", HostComponentStateEntity.class); + + query.setParameter("serviceName", serviceName); + query.setParameter("componentName", componentName); + query.setParameter("version", version); + + return daoUtils.selectList(query); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java index 987e44f..11e41b6 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java @@ -199,4 +199,20 @@ public class ServiceComponentDesiredStateDAO { return daoUtils.selectList(query); } + @RequiresSession + public ServiceComponentVersionEntity findVersion(long clusterId, String serviceName, + String componentName, String version) { + + EntityManager entityManager = entityManagerProvider.get(); + TypedQuery<ServiceComponentVersionEntity> query = entityManager.createNamedQuery( + "ServiceComponentVersionEntity.findByComponentAndVersion", ServiceComponentVersionEntity.class); + + query.setParameter("clusterId", clusterId); + query.setParameter("serviceName", serviceName); + query.setParameter("componentName", componentName); + query.setParameter("repoVersion", version); + + return daoUtils.selectSingle(query); + } + } http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java index 9d35e2a..0b3d8ce 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java @@ -67,7 +67,12 @@ import com.google.common.base.Objects; query = "SELECT hcs from HostComponentStateEntity hcs WHERE hcs.serviceName=:serviceName AND hcs.componentName=:componentName AND hcs.hostEntity.hostName=:hostName"), @NamedQuery( name = "HostComponentStateEntity.findByIndex", - query = "SELECT hcs from HostComponentStateEntity hcs WHERE hcs.clusterId=:clusterId AND hcs.serviceName=:serviceName AND hcs.componentName=:componentName AND hcs.hostId=:hostId") }) + query = "SELECT hcs from HostComponentStateEntity hcs WHERE hcs.clusterId=:clusterId AND hcs.serviceName=:serviceName AND hcs.componentName=:componentName AND hcs.hostId=:hostId"), + @NamedQuery( + name = "HostComponentStateEntity.findByServiceAndComponentAndNotVersion", + query = "SELECT hcs from HostComponentStateEntity hcs WHERE hcs.serviceName=:serviceName AND hcs.componentName=:componentName AND hcs.version != :version") +}) + public class HostComponentStateEntity { @Id http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java index 210de62..d3705f3 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java @@ -17,8 +17,6 @@ */ package org.apache.ambari.server.orm.entities; -import static java.util.Arrays.asList; - import java.util.Collections; import java.util.List; import java.util.Set; http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java index 9b93517..17fd323 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java @@ -40,6 +40,7 @@ import javax.persistence.Table; import javax.persistence.TableGenerator; import javax.persistence.UniqueConstraint; +import org.apache.ambari.server.state.RepositoryVersionState; import org.apache.ambari.server.state.State; @Entity @@ -84,6 +85,10 @@ public class ServiceComponentDesiredStateEntity { @Column(name = "recovery_enabled", nullable = false, insertable = true, updatable = true) private Integer recoveryEnabled = 0; + @Column(name = "repo_state", nullable = false, insertable = true, updatable = true) + @Enumerated(EnumType.STRING) + private RepositoryVersionState repoState = RepositoryVersionState.INIT; + /** * Unidirectional one-to-one association to {@link StackEntity} */ @@ -297,4 +302,18 @@ public class ServiceComponentDesiredStateEntity { this.hostComponentDesiredStateEntities = hostComponentDesiredStateEntities; } + /** + * @param state the repository state for {@link #getDesiredVersion()} + */ + public void setRepositoryState(RepositoryVersionState state) { + repoState = state; + } + + /** + * @return the state of the repository for {@link #getDesiredVersion()} + */ + public RepositoryVersionState getRepositoryState() { + return repoState; + } + } http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java index 5085d18..f0b9660 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java @@ -49,9 +49,22 @@ import org.apache.ambari.server.state.RepositoryVersionState; valueColumnName = "sequence_value", pkColumnValue = "servicecomponent_version_id_seq", initialValue = 0) -@NamedQueries({ @NamedQuery( +@NamedQueries({ + @NamedQuery( name = "ServiceComponentVersionEntity.findByComponent", - query = "SELECT version FROM ServiceComponentVersionEntity version WHERE version.m_serviceComponentDesiredStateEntity.clusterId = :clusterId AND version.m_serviceComponentDesiredStateEntity.serviceName = :serviceName AND version.m_serviceComponentDesiredStateEntity.componentName = :componentName") }) + query = "SELECT version FROM ServiceComponentVersionEntity version WHERE " + + "version.m_serviceComponentDesiredStateEntity.clusterId = :clusterId AND " + + "version.m_serviceComponentDesiredStateEntity.serviceName = :serviceName AND " + + "version.m_serviceComponentDesiredStateEntity.componentName = :componentName"), + @NamedQuery( + name = "ServiceComponentVersionEntity.findByComponentAndVersion", + query = "SELECT version FROM ServiceComponentVersionEntity version WHERE " + + "version.m_serviceComponentDesiredStateEntity.clusterId = :clusterId AND " + + "version.m_serviceComponentDesiredStateEntity.serviceName = :serviceName AND " + + "version.m_serviceComponentDesiredStateEntity.componentName = :componentName AND " + + "version.m_repositoryVersion.version = :repoVersion") +}) + public class ServiceComponentVersionEntity { @Id @@ -66,7 +79,7 @@ public class ServiceComponentVersionEntity { private ServiceComponentDesiredStateEntity m_serviceComponentDesiredStateEntity; @ManyToOne - @JoinColumn(name = "repo_version_id", referencedColumnName = "repo_version_id", nullable = false) + @JoinColumn(name = "repo_version_id", referencedColumnName = "repo_version_id", nullable = false) private RepositoryVersionEntity m_repositoryVersion; @Column(name = "state", nullable = false, insertable = true, updatable = true) @@ -99,6 +112,13 @@ public class ServiceComponentVersionEntity { } /** + * @return the repository + */ + public RepositoryVersionEntity getRepositoryVersion() { + return m_repositoryVersion; + } + + /** * @return the id */ public long getId() { http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java index e93ab9a..b5b6821 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponent.java @@ -97,4 +97,19 @@ public interface ServiceComponent { String hostName) throws AmbariException; void delete() throws AmbariException; + + /** + * This method computes the state of the repository that's associated with the desired + * version. It is used, for example, when a host component reports its version and the + * state can be in flux. + * + * @param reportedVersion + * @throws AmbariException + */ + void updateRepositoryState(String reportedVersion) throws AmbariException; + + /** + * @return the repository state for the desired version + */ + RepositoryVersionState getRepositoryState(); } http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java index 236091b..122f57c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java @@ -19,6 +19,7 @@ package org.apache.ambari.server.state; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; @@ -32,21 +33,31 @@ import org.apache.ambari.server.ServiceComponentHostNotFoundException; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.ServiceComponentResponse; import org.apache.ambari.server.events.ServiceComponentRecoveryChangedEvent; +import org.apache.ambari.server.events.listeners.upgrade.StackVersionListener; import org.apache.ambari.server.events.publishers.AmbariEventPublisher; import org.apache.ambari.server.orm.dao.ClusterServiceDAO; import org.apache.ambari.server.orm.dao.HostComponentDesiredStateDAO; +import org.apache.ambari.server.orm.dao.HostComponentStateDAO; +import org.apache.ambari.server.orm.dao.RepositoryVersionDAO; import org.apache.ambari.server.orm.dao.ServiceComponentDesiredStateDAO; import org.apache.ambari.server.orm.dao.StackDAO; import org.apache.ambari.server.orm.entities.ClusterServiceEntity; import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK; import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity; import org.apache.ambari.server.orm.entities.HostComponentStateEntity; +import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity; +import org.apache.ambari.server.orm.entities.ServiceComponentVersionEntity; import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.state.cluster.ClusterImpl; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import com.google.inject.Inject; import com.google.inject.ProvisionException; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; @@ -86,6 +97,12 @@ public class ServiceComponentImpl implements ServiceComponent { */ private final StackDAO stackDAO; + @Inject + private RepositoryVersionDAO repoVersionDAO; + + @Inject + private HostComponentStateDAO hostComponentDAO; + @AssistedInject public ServiceComponentImpl(@Assisted Service service, @Assisted String componentName, AmbariMetaInfo ambariMetaInfo, @@ -121,6 +138,7 @@ public class ServiceComponentImpl implements ServiceComponent { desiredStateEntityId = desiredStateEntity.getId(); } + @Override public void updateComponentInfo() throws AmbariException { StackId stackId = service.getDesiredStackVersion(); try { @@ -427,7 +445,8 @@ public class ServiceComponentImpl implements ServiceComponent { ServiceComponentResponse r = new ServiceComponentResponse(getClusterId(), cluster.getClusterName(), service.getName(), getName(), getDesiredStackVersion().getStackId(), getDesiredState().toString(), - getServiceComponentStateCount(), isRecoveryEnabled(), displayName); + getServiceComponentStateCount(), isRecoveryEnabled(), displayName, + getDesiredVersion(), getRepositoryState()); return r; } @@ -571,6 +590,151 @@ public class ServiceComponentImpl implements ServiceComponent { } + /** + * Follows this version logic: + * <table border="1"> + * <tr> + * <th>DB hostcomponent1</th> + * <th>DB hostcomponentN</th> + * <th>DB desired</th> + * <th>New desired</th> + * <th>Repo State</th> + * </tr> + * <tr> + * <td>v1</td> + * <td>v1</td> + * <td>UNKNOWN</td> + * <td>v1</td> + * <td>CURRENT</td> + * </tr> + * <tr> + * <td>v1</td> + * <td>v2</td> + * <td>UNKNOWN</td> + * <td>UNKNOWN</td> + * <td>OUT_OF_SYNC</td> + * </tr> + * <tr> + * <td>v1</td> + * <td>v2</td> + * <td>v2</td> + * <td>v2 (no change)</td> + * <td>OUT_OF_SYNC</td> + * </tr> + * <tr> + * <td>v2</td> + * <td>v2</td> + * <td>v1</td> + * <td>v1 (no change)</td> + * <td>OUT_OF_SYNC</td> + * </tr> + * <tr> + * <td>v2</td> + * <td>v2</td> + * <td>v2</td> + * <td>v2 (no change)</td> + * <td>CURRENT</td> + * </tr> + * </table> + */ + @Override + @Transactional + public void updateRepositoryState(String reportedVersion) throws AmbariException { + + ServiceComponentDesiredStateEntity component = serviceComponentDesiredStateDAO.findById( + desiredStateEntityId); + + List<ServiceComponentVersionEntity> componentVersions = serviceComponentDesiredStateDAO.findVersions( + getClusterId(), getServiceName(), getName()); + + // per component, this list should be small, so iterating here isn't a big deal + Map<String, ServiceComponentVersionEntity> map = new HashMap<>(Maps.uniqueIndex(componentVersions, + new Function<ServiceComponentVersionEntity, String>() { + @Override + public String apply(ServiceComponentVersionEntity input) { + return input.getRepositoryVersion().getVersion(); + } + })); + + if (LOG.isDebugEnabled()) { + LOG.debug("Existing versions for {}/{}/{}: {}", + getClusterName(), getServiceName(), getName(), map.keySet()); + } + + ServiceComponentVersionEntity componentVersion = map.get(reportedVersion); + + if (null == componentVersion) { + RepositoryVersionEntity repoVersion = repoVersionDAO.findByStackAndVersion( + getDesiredStackVersion(), reportedVersion); + + if (null != repoVersion) { + componentVersion = new ServiceComponentVersionEntity(); + componentVersion.setRepositoryVersion(repoVersion); + componentVersion.setState(RepositoryVersionState.INSTALLED); + componentVersion.setUserName("auto-reported"); + + // since we've never seen this version before, mark the component as CURRENT + component.setRepositoryState(RepositoryVersionState.CURRENT); + component.addVersion(componentVersion); + + component = serviceComponentDesiredStateDAO.merge(component); + + map.put(reportedVersion, componentVersion); + + } else { + LOG.warn("There is no repository available for stack {}, version {}", + getDesiredStackVersion(), reportedVersion); + } + } + + if (MapUtils.isNotEmpty(map)) { + String desiredVersion = component.getDesiredVersion(); + + List<HostComponentStateEntity> hostComponents = hostComponentDAO.findByServiceAndComponentAndNotVersion( + component.getServiceName(), component.getComponentName(), reportedVersion); + + LOG.debug("{}/{} reportedVersion={}, desiredVersion={}, non-matching desired count={}, repo_state={}", + component.getServiceName(), component.getComponentName(), reportedVersion, + desiredVersion, hostComponents.size(), component.getRepositoryState()); + + // !!! if we are unknown, that means it's never been set. Try to determine it. + if (StackVersionListener.UNKNOWN_VERSION.equals(desiredVersion)) { + if (CollectionUtils.isEmpty(hostComponents)) { + // all host components are the same version as reported + component.setDesiredVersion(reportedVersion); + component.setRepositoryState(RepositoryVersionState.CURRENT); + } else { + // desired is UNKNOWN and there's a mix of versions in the host components + component.setRepositoryState(RepositoryVersionState.OUT_OF_SYNC); + } + } else { + if (!reportedVersion.equals(desiredVersion)) { + component.setRepositoryState(RepositoryVersionState.OUT_OF_SYNC); + } else if (CollectionUtils.isEmpty(hostComponents)) { + component.setRepositoryState(RepositoryVersionState.CURRENT); + } + } + + component = serviceComponentDesiredStateDAO.merge(component); + } + } + + @Override + public RepositoryVersionState getRepositoryState() { + ServiceComponentDesiredStateEntity component = serviceComponentDesiredStateDAO.findById( + desiredStateEntityId); + + if (null != component) { + return component.getRepositoryState(); + } else { + LOG.warn("Cannot retrieve repository state on component that may have been deleted: service {}, component {}", + service != null ? service.getName() : null, componentName); + + return null; + } + } + + private int getSCHCountByState(State state) { int count = 0; for (ServiceComponentHost sch : hostComponents.values()) { http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java index 7d35d2e..35c5efb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ClusterGrouping.java @@ -46,9 +46,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Objects; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; /** * Used to represent cluster-based operations. http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java index d6bbbac..3190390 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java @@ -19,8 +19,6 @@ package org.apache.ambari.server.upgrade; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import org.apache.ambari.server.AmbariException; @@ -30,6 +28,7 @@ import org.apache.ambari.server.orm.dao.DaoUtils; 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.RepositoryVersionState; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -87,6 +86,7 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog { */ @Override protected void executeDDLUpdates() throws AmbariException, SQLException { + addServiceComponentColumn(); } /** @@ -125,4 +125,15 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog { } } + + /** + * Updates the {@code servicecomponentdesiredstate} table. + * + * @throws SQLException + */ + protected void addServiceComponentColumn() throws SQLException { + dbAccessor.addColumn(UpgradeCatalog250.COMPONENT_TABLE, + new DBColumnInfo("repo_state", String.class, 255, RepositoryVersionState.INIT.name(), false)); + + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql index b79c945..a64a861 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql @@ -191,6 +191,7 @@ CREATE TABLE servicecomponentdesiredstate ( desired_version VARCHAR(255) NOT NULL DEFAULT 'UNKNOWN', service_name VARCHAR(255) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, + repo_state VARCHAR(255) NOT NULL DEFAULT 'INIT', CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql index 1c502bc..55ec5ed 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -201,6 +201,7 @@ CREATE TABLE servicecomponentdesiredstate ( desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(100) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, + repo_state VARCHAR(255) NOT NULL DEFAULT 'INIT', CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql index c6d4ad0..a4a87aa 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -182,6 +182,7 @@ CREATE TABLE servicecomponentdesiredstate ( desired_version VARCHAR(255) DEFAULT 'UNKNOWN' NOT NULL, service_name VARCHAR2(255) NOT NULL, recovery_enabled SMALLINT DEFAULT 0 NOT NULL, + repo_state VARCHAR2(255) DEFAULT 'INIT' NOT NULL, CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql index 1be87bb..36587c7 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -191,6 +191,7 @@ CREATE TABLE servicecomponentdesiredstate ( desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, + repo_state VARCHAR(255) NOT NULL DEFAULT 'INIT', CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql index abe48e8..5f7d98d 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql @@ -180,6 +180,7 @@ CREATE TABLE servicecomponentdesiredstate ( desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, + repo_state VARCHAR(255) NOT NULL DEFAULT 'INIT', CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql index 169a464..7fbe93b 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql @@ -204,6 +204,7 @@ CREATE TABLE servicecomponentdesiredstate ( desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, recovery_enabled SMALLINT NOT NULL DEFAULT 0, + repo_state VARCHAR(255) NOT NULL DEFAULT 'INIT', CONSTRAINT pk_sc_desiredstate PRIMARY KEY (id), CONSTRAINT UQ_scdesiredstate_name UNIQUE(component_name, service_name, cluster_id), CONSTRAINT FK_scds_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id), http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/main/resources/properties.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json index b7e0988..fc74381 100644 --- a/ambari-server/src/main/resources/properties.json +++ b/ambari-server/src/main/resources/properties.json @@ -59,8 +59,8 @@ "ServiceComponentInfo/cluster_name", "ServiceComponentInfo/display_name", "ServiceComponentInfo/state", - "ServiceComponents/display_name", - "ServiceComponents/description", + "ServiceComponentInfo/display_name", + "ServiceComponentInfo/description", "ServiceComponentInfo/category", "ServiceComponentInfo/total_count", "ServiceComponentInfo/started_count", @@ -69,6 +69,8 @@ "ServiceComponentInfo/init_count", "ServiceComponentInfo/unknown_count", "ServiceComponentInfo/recovery_enabled", + "ServiceComponentInfo/desired_version", + "ServiceComponentInfo/repository_state", "params/run_smoke_test", "_" ], http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/test/java/org/apache/ambari/server/checks/AbstractCheckDescriptorTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/AbstractCheckDescriptorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/AbstractCheckDescriptorTest.java index 7758924..be9ab96 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/checks/AbstractCheckDescriptorTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/AbstractCheckDescriptorTest.java @@ -49,8 +49,6 @@ import org.junit.Test; import com.google.inject.Provider; -import junit.framework.Assert; - /** * Unit tests for AbstractCheckDescriptor */ http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java index 3529bef..3fd38f9 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java @@ -68,6 +68,7 @@ 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.RepositoryVersionState; import org.apache.ambari.server.state.Service; import org.apache.ambari.server.state.ServiceComponent; import org.apache.ambari.server.state.ServiceComponentFactory; @@ -243,13 +244,13 @@ public class ComponentResourceProviderTest { expect(serviceComponent1.convertToResponse()).andReturn( new ServiceComponentResponse(100L, "Cluster100", "Service100", "Component100", null, "", serviceComponentStateCountMap, - true /* recovery enabled */, "Component100 Client")); + true /* recovery enabled */, "Component100 Client", null, null)); expect(serviceComponent2.convertToResponse()).andReturn( new ServiceComponentResponse(100L, "Cluster100", "Service100", "Component101", null, "", serviceComponentStateCountMap, - false /* recovery not enabled */, "Component101 Client")); + false /* recovery not enabled */, "Component101 Client", null, null)); expect(serviceComponent3.convertToResponse()).andReturn( new ServiceComponentResponse(100L, "Cluster100", "Service100", "Component102", null, "", serviceComponentStateCountMap, - true /* recovery enabled */, "Component102 Client")); + true /* recovery enabled */, "Component102 Client", "1.1", RepositoryVersionState.CURRENT)); expect(ambariMetaInfo.getComponent(null, null, null, "Component100")).andReturn(componentInfo1); expect(ambariMetaInfo.getComponent(null, null, null, "Component101")).andReturn(componentInfo2); @@ -282,6 +283,8 @@ public class ComponentResourceProviderTest { propertyIds.add(ComponentResourceProvider.COMPONENT_INIT_COUNT_PROPERTY_ID); propertyIds.add(ComponentResourceProvider.COMPONENT_UNKNOWN_COUNT_PROPERTY_ID); propertyIds.add(ComponentResourceProvider.COMPONENT_RECOVERY_ENABLED_ID); + propertyIds.add(ComponentResourceProvider.COMPONENT_DESIRED_VERSION); + propertyIds.add(ComponentResourceProvider.COMPONENT_REPOSITORY_STATE); Predicate predicate = new PredicateBuilder() .property(ComponentResourceProvider.COMPONENT_CLUSTER_NAME_PROPERTY_ID) @@ -314,6 +317,17 @@ public class ComponentResourceProviderTest { ComponentResourceProvider.COMPONENT_UNKNOWN_COUNT_PROPERTY_ID)); Assert.assertEquals(String.valueOf(true), resource.getPropertyValue( ComponentResourceProvider.COMPONENT_RECOVERY_ENABLED_ID)); + + if (resource.getPropertyValue( + ComponentResourceProvider.COMPONENT_COMPONENT_NAME_PROPERTY_ID).equals("Component102")) { + Assert.assertNotNull(resource.getPropertyValue(ComponentResourceProvider.COMPONENT_REPOSITORY_STATE)); + Assert.assertNotNull(resource.getPropertyValue(ComponentResourceProvider.COMPONENT_DESIRED_VERSION)); + Assert.assertEquals(RepositoryVersionState.CURRENT, resource.getPropertyValue(ComponentResourceProvider.COMPONENT_REPOSITORY_STATE)); + Assert.assertEquals("1.1", resource.getPropertyValue(ComponentResourceProvider.COMPONENT_DESIRED_VERSION)); + } else { + Assert.assertNull(resource.getPropertyValue(ComponentResourceProvider.COMPONENT_REPOSITORY_STATE)); + Assert.assertNull(resource.getPropertyValue(ComponentResourceProvider.COMPONENT_DESIRED_VERSION)); + } } // verify @@ -405,13 +419,13 @@ public class ComponentResourceProviderTest { expect(serviceComponent1.convertToResponse()).andReturn( new ServiceComponentResponse(100L, "Cluster100", "Service100", "Component101", null, "", serviceComponentStateCountMap, - false /* recovery not enabled */, "Component101 Client")); + false /* recovery not enabled */, "Component101 Client", null, null)); expect(serviceComponent2.convertToResponse()).andReturn( new ServiceComponentResponse(100L, "Cluster100", "Service100", "Component102", null, "", serviceComponentStateCountMap, - false /* recovery not enabled */, "Component102 Client")); + false /* recovery not enabled */, "Component102 Client", null, null)); expect(serviceComponent3.convertToResponse()).andReturn( new ServiceComponentResponse(100L, "Cluster100", "Service100", "Component103", null, "", serviceComponentStateCountMap, - false /* recovery not enabled */, "Component103 Client")); + false /* recovery not enabled */, "Component103 Client", null, null)); expect(serviceComponent1.getDesiredState()).andReturn(State.INSTALLED).anyTimes(); expect(serviceComponent2.getDesiredState()).andReturn(State.INSTALLED).anyTimes(); expect(serviceComponent3.getDesiredState()).andReturn(State.INSTALLED).anyTimes(); @@ -721,7 +735,7 @@ public class ComponentResourceProviderTest { expect(serviceComponent1.convertToResponse()).andReturn( new ServiceComponentResponse(100L, "Cluster100", "Service100", "Component101", null, "", serviceComponentStateCountMap, - false /* recovery not enabled */, "Component101 Client")); + false /* recovery not enabled */, "Component101 Client", null, null)); expect(serviceComponent1.getDesiredState()).andReturn(State.INSTALLED).anyTimes(); expect(serviceComponentHost.getState()).andReturn(State.INSTALLED).anyTimes(); http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestImplTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestImplTest.java index fb508ea..4aacf91 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestImplTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestImplTest.java @@ -128,8 +128,8 @@ public class RequestImplTest { Assert.assertTrue(validPropertyIds.contains("ServiceComponentInfo/component_name")); Assert.assertTrue(validPropertyIds.contains("ServiceComponentInfo/cluster_name")); Assert.assertTrue(validPropertyIds.contains("ServiceComponentInfo/state")); - Assert.assertTrue(validPropertyIds.contains("ServiceComponents/display_name")); - Assert.assertTrue(validPropertyIds.contains("ServiceComponents/description")); + Assert.assertTrue(validPropertyIds.contains("ServiceComponentInfo/display_name")); + Assert.assertTrue(validPropertyIds.contains("ServiceComponentInfo/description")); Assert.assertTrue(validPropertyIds.contains("params/run_smoke_test")); request = PropertyHelper.getReadRequest(PropertyHelper.getPropertyIds(Resource.Type.Action)); http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java index ead0a2d..57af8a6 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java @@ -622,6 +622,7 @@ public class OrmTestHelper { repositoryVersion = repositoryVersionDAO.create(stackEntity, version, String.valueOf(System.currentTimeMillis()), ""); } catch (Exception ex) { + ex.printStackTrace(); Assert.fail(MessageFormat.format("Unable to create Repo Version for Stack {0} and version {1}", stackEntity.getStackName() + "-" + stackEntity.getStackVersion(), version)); } http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java index 0f615ee..a7f8ae3 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java @@ -29,6 +29,7 @@ import java.util.Map; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.ServiceComponentResponse; +import org.apache.ambari.server.events.listeners.upgrade.StackVersionListener; import org.apache.ambari.server.orm.GuiceJpaInitializer; import org.apache.ambari.server.orm.InMemoryDefaultTestModule; import org.apache.ambari.server.orm.OrmTestHelper; @@ -634,6 +635,77 @@ public class ServiceComponentTest { assertEquals(0, list.size()); } + + @Test + public void testUpdateStates() throws Exception { + ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO = injector.getInstance( + ServiceComponentDesiredStateDAO.class); + + String componentName = "NAMENODE"; + + ServiceComponent component = serviceComponentFactory.createNew(service, componentName); + component.setDesiredStackVersion(new StackId("HDP-2.2.0")); + service.addServiceComponent(component); + + ServiceComponent sc = service.getServiceComponent(componentName); + Assert.assertNotNull(sc); + + ServiceComponentDesiredStateEntity entity = serviceComponentDesiredStateDAO.findByName(cluster.getClusterId(), serviceName, componentName); + + helper.getOrCreateRepositoryVersion(component.getDesiredStackVersion(), "2.2.0.1"); + helper.getOrCreateRepositoryVersion(component.getDesiredStackVersion(), "2.2.0.2"); + + addHostToCluster("h1", clusterName); + addHostToCluster("h2", clusterName); + + sc.setDesiredState(State.INSTALLED); + Assert.assertEquals(State.INSTALLED, sc.getDesiredState()); + + ServiceComponentHost sch1 = sc.addServiceComponentHost("h1"); + ServiceComponentHost sch2 = sc.addServiceComponentHost("h2"); + + // !!! case 1: component desired is UNKNOWN, mix of h-c versions + sc.setDesiredVersion(StackVersionListener.UNKNOWN_VERSION); + sch1.setVersion("2.2.0.1"); + sch2.setVersion("2.2.0.2"); + sc.updateRepositoryState("2.2.0.2"); + entity = serviceComponentDesiredStateDAO.findByName(cluster.getClusterId(), serviceName, componentName); + assertEquals(RepositoryVersionState.OUT_OF_SYNC, entity.getRepositoryState()); + + // !!! case 2: component desired is UNKNOWN, all h-c same version + sc.setDesiredVersion(StackVersionListener.UNKNOWN_VERSION); + sch1.setVersion("2.2.0.1"); + sch2.setVersion("2.2.0.1"); + sc.updateRepositoryState("2.2.0.1"); + entity = serviceComponentDesiredStateDAO.findByName(cluster.getClusterId(), serviceName, componentName); + assertEquals(RepositoryVersionState.CURRENT, entity.getRepositoryState()); + + // !!! case 3: component desired is known, any component reports different version + sc.setDesiredVersion("2.2.0.1"); + sch1.setVersion("2.2.0.1"); + sch2.setVersion("2.2.0.2"); + sc.updateRepositoryState("2.2.0.2"); + entity = serviceComponentDesiredStateDAO.findByName(cluster.getClusterId(), serviceName, componentName); + assertEquals(RepositoryVersionState.OUT_OF_SYNC, entity.getRepositoryState()); + + // !!! case 4: component desired is known, component reports same as desired, mix of h-c versions + sc.setDesiredVersion("2.2.0.1"); + sch1.setVersion("2.2.0.1"); + sch2.setVersion("2.2.0.2"); + sc.updateRepositoryState("2.2.0.1"); + entity = serviceComponentDesiredStateDAO.findByName(cluster.getClusterId(), serviceName, componentName); + assertEquals(RepositoryVersionState.OUT_OF_SYNC, entity.getRepositoryState()); + + // !!! case 5: component desired is known, component reports same as desired, all h-c the same + sc.setDesiredVersion("2.2.0.1"); + sch1.setVersion("2.2.0.1"); + sch2.setVersion("2.2.0.1"); + sc.updateRepositoryState("2.2.0.1"); + entity = serviceComponentDesiredStateDAO.findByName(cluster.getClusterId(), serviceName, componentName); + assertEquals(RepositoryVersionState.CURRENT, entity.getRepositoryState()); + } + + /** * Creates an upgrade entity, asserting it was created correctly. * http://git-wip-us.apache.org/repos/asf/ambari/blob/cd245c00/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java index 36afa03..f5e0bfe 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java @@ -17,39 +17,13 @@ */ package org.apache.ambari.server.upgrade; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.createMockBuilder; -import static org.easymock.EasyMock.createNiceMock; -import static org.easymock.EasyMock.createStrictMock; -import static org.easymock.EasyMock.eq; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.newCapture; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.Statement; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.persistence.EntityManager; - -import org.apache.ambari.server.configuration.Configuration; -import org.apache.ambari.server.orm.DBAccessor; -import org.apache.ambari.server.state.stack.OsFamily; -import org.easymock.Capture; -import org.junit.Assert; -import org.junit.Test; -import org.springframework.security.crypto.password.PasswordEncoder; -import com.google.inject.Binder; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Module; +import org.junit.Test; public class UpgradeCatalog300Test { @@ -67,7 +41,6 @@ public class UpgradeCatalog300Test { upgradeCatalog300.addNewConfigurationsFromXml(); upgradeCatalog300.showHcatDeletedUserMessage(); - replay(upgradeCatalog300); upgradeCatalog300.executeDMLUpdates(); @@ -75,4 +48,23 @@ public class UpgradeCatalog300Test { verify(upgradeCatalog300); } + @Test + public void testExecuteDDLUpdates() throws Exception { + + Method addServiceComponentColumn = UpgradeCatalog300.class + .getDeclaredMethod("addServiceComponentColumn"); + + UpgradeCatalog300 upgradeCatalog300 = createMockBuilder(UpgradeCatalog300.class) + .addMockedMethod(addServiceComponentColumn) + .createMock(); + + upgradeCatalog300.addServiceComponentColumn(); + + replay(upgradeCatalog300); + + upgradeCatalog300.executeDDLUpdates(); + + verify(upgradeCatalog300); + } + }