AMBARI-21175 - Host Versions Remain on CURRENT During STANDARD (Full) Upgrades (jonathanhurley)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7847e4b6 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7847e4b6 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7847e4b6 Branch: refs/heads/branch-feature-AMBARI-20859 Commit: 7847e4b6cf65b777e516a4806cbf5f45cdd207ee Parents: 4767389 Author: Jonathan Hurley <jhur...@hortonworks.com> Authored: Fri Jun 2 08:28:51 2017 -0400 Committer: Jonathan Hurley <jhur...@hortonworks.com> Committed: Fri Jun 2 10:30:06 2017 -0400 ---------------------------------------------------------------------- .../ambari/server/orm/dao/HostVersionDAO.java | 16 +++ .../server/orm/entities/HostVersionEntity.java | 5 + .../upgrades/FinalizeUpgradeAction.java | 57 ++++++++-- .../upgrades/UpgradeActionTest.java | 109 +++++++++++++++++-- 4 files changed, 164 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/7847e4b6/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java index ad34ec7..7be7691 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java @@ -130,6 +130,22 @@ public class HostVersionDAO extends CrudDAO<HostVersionEntity, Long> { } /** + * Retrieve all of the host versions for the given cluster name, and state. <br/> + * @param clusterName Cluster name + * @param state repository version state + * @return Return all of the host versions that match the criteria. + */ + @RequiresSession + public List<HostVersionEntity> findByClusterAndState(String clusterName, RepositoryVersionState state) { + final TypedQuery<HostVersionEntity> query = entityManagerProvider.get() + .createNamedQuery("findByClusterAndState", HostVersionEntity.class); + query.setParameter("clusterName", clusterName); + query.setParameter("state", state); + + return daoUtils.selectList(query); + } + + /** * Retrieve all of the host versions for the given cluster name, host name, and state. <br/> * @param clusterName Cluster name * @param hostName FQDN of host http://git-wip-us.apache.org/repos/asf/ambari/blob/7847e4b6/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java index dbe4fe0..4a030af 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java @@ -61,6 +61,11 @@ import org.apache.ambari.server.state.RepositoryVersionState; "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host " + "WHERE hostVersion.hostEntity.hostName=:hostName"), + @NamedQuery( + name = "findByClusterAndState", + query = "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host JOIN host.clusterEntities clusters " + + "WHERE clusters.clusterName=:clusterName AND hostVersion.state=:state"), + @NamedQuery(name = "hostVersionByClusterHostnameAndState", query = "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host JOIN host.clusterEntities clusters " + "WHERE clusters.clusterName=:clusterName AND hostVersion.hostEntity.hostName=:hostName AND hostVersion.state=:state"), http://git-wip-us.apache.org/repos/asf/ambari/blob/7847e4b6/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java index 475a8c9..8f206bf 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java @@ -140,8 +140,8 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction { throw new AmbariException(messageBuff.toString()); } - // for all hosts participating in this upgrade, update thei repository - // versions and upgrade state + // find every host version for this upgrade and ensure it has transitioned + // to CURRENT if required List<HostVersionEntity> hostVersions = hostVersionDAO.findHostVersionByClusterAndRepository( cluster.getClusterId(), repositoryVersion); @@ -165,7 +165,8 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction { } } - // throw an exception if there are hosts which are not not fully upgraded + // throw an exception if there are hosts which did not transition the + // repository to CURRENT if (hostsWithoutCorrectVersionState.size() > 0) { message = String.format( "The following %d host(s) have not been upgraded to version %s. " @@ -178,10 +179,11 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction { } outSB.append( - String.format("Finalizing the upgrade state of %d host(s).", + String.format("Finalizing the upgrade state and repository version for %d host(s).", hostVersionsAllowed.size())).append(System.lineSeparator()); - // Reset the upgrade state + // at this point, all host versions are correct - do some cleanup like + // resetting the upgrade state for (HostVersionEntity hostVersion : hostVersionsAllowed) { Collection<HostComponentStateEntity> hostComponentStates = hostComponentStateDAO.findByHost(hostVersion.getHostName()); for (HostComponentStateEntity hostComponentStateEntity: hostComponentStates) { @@ -190,16 +192,16 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction { } } - // Impacts all hosts that have a version - outSB.append( - String.format("Finalizing the version for %d host(s).", - hostVersionsAllowed.size())).append(System.lineSeparator()); - - versionEventPublisher.publish(new StackUpgradeFinishEvent(cluster)); + // move host versions from CURRENT to INSTALLED if their repos are no + // longer used + finalizeHostRepositoryVersions(cluster); // Reset upgrade state cluster.setUpgradeEntity(null); + // the upgrade is done! + versionEventPublisher.publish(new StackUpgradeFinishEvent(cluster)); + message = String.format("The upgrade to %s has completed.", version); outSB.append(message).append(System.lineSeparator()); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outSB.toString(), errSB.toString()); @@ -372,6 +374,39 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction { return errors; } + /** + * Moves any {@link HostVersionEntity}s which are + * {@link RepositoryVersionState#CURRENT} to either + * {@link RepositoryVersionState#INSTALLED} or + * {@link RepositoryVersionState#NOT_REQUIRED} if their assocaited + * repositories are no longer in use. + * + * @param cluster + * @throws AmbariException + */ + private void finalizeHostRepositoryVersions(Cluster cluster) throws AmbariException { + // create a set of all of the repos that the services are on + Set<RepositoryVersionEntity> desiredRepoVersions = new HashSet<>(); + Set<String> serviceNames = cluster.getServices().keySet(); + for (String serviceName : serviceNames) { + Service service = cluster.getService(serviceName); + desiredRepoVersions.add(service.getDesiredRepositoryVersion()); + } + + // if any CURRENT host version is for a repo which is no longer desired by + // ANY service, move it to INSTALLED + List<HostVersionEntity> currentHostVersions = hostVersionDAO.findByClusterAndState( + cluster.getClusterName(), RepositoryVersionState.CURRENT); + + for (HostVersionEntity hostVersion : currentHostVersions) { + RepositoryVersionEntity hostRepoVersion = hostVersion.getRepositoryVersion(); + if (!desiredRepoVersions.contains(hostRepoVersion)) { + hostVersion.setState(RepositoryVersionState.INSTALLED); + hostVersion = hostVersionDAO.merge(hostVersion); + } + } + } + protected static class InfoTuple implements Comparable<InfoTuple> { protected final String serviceName; protected final String componentName; http://git-wip-us.apache.org/repos/asf/ambari/blob/7847e4b6/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java index 35fffda..e3ffae0 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java @@ -100,7 +100,6 @@ public class UpgradeActionTest { private static final String HDP_2_1_1_1 = "2.1.1.1-2"; private static final String HDP_2_2_0_1 = "2.2.0.1-3"; - private static final String HDP_2_2_0_2 = "2.2.0.2-4"; private static final StackId HDP_21_STACK = new StackId("HDP-2.1.1"); private static final StackId HDP_22_STACK = new StackId("HDP-2.2.0"); @@ -147,7 +146,6 @@ public class UpgradeActionTest { private RepositoryVersionEntity repositoryVersion2110; private RepositoryVersionEntity repositoryVersion2111; private RepositoryVersionEntity repositoryVersion2201; - private RepositoryVersionEntity repositoryVersion2202; @Before public void setup() throws Exception { @@ -167,7 +165,6 @@ public class UpgradeActionTest { repositoryVersion2110 = m_helper.getOrCreateRepositoryVersion(HDP_21_STACK, HDP_2_1_1_0); repositoryVersion2111 = m_helper.getOrCreateRepositoryVersion(HDP_21_STACK, HDP_2_1_1_1); repositoryVersion2201 = m_helper.getOrCreateRepositoryVersion(HDP_22_STACK, HDP_2_2_0_1); - repositoryVersion2202 = m_helper.getOrCreateRepositoryVersion(HDP_22_STACK, HDP_2_2_0_2); } @After @@ -199,11 +196,11 @@ public class UpgradeActionTest { hostVersionDAO.create(entity); } - private void createUpgradeCluster( + private Cluster createUpgradeCluster( RepositoryVersionEntity sourceRepoVersion, String hostName) throws Exception { clusters.addCluster(clusterName, sourceRepoVersion.getStackId()); - Cluster c = clusters.getCluster(clusterName); + Cluster cluster = clusters.getCluster(clusterName); // add a host component clusters.addHost(hostName); @@ -222,6 +219,8 @@ public class UpgradeActionTest { sourceRepoVersion, RepositoryVersionState.INSTALLED); hostVersionDAO.create(entity); + + return cluster; } private void createHostVersions(RepositoryVersionEntity targetRepoVersion, @@ -313,13 +312,13 @@ public class UpgradeActionTest { Cluster cluster = clusters.getCluster(clusterName); // Install ZK and HDFS with some components - Service zk = installService(cluster, "ZOOKEEPER"); + Service zk = installService(cluster, "ZOOKEEPER", repositoryVersion2110); addServiceComponent(cluster, zk, "ZOOKEEPER_SERVER"); addServiceComponent(cluster, zk, "ZOOKEEPER_CLIENT"); createNewServiceComponentHost(cluster, "ZOOKEEPER", "ZOOKEEPER_SERVER", "h1"); createNewServiceComponentHost(cluster, "ZOOKEEPER", "ZOOKEEPER_CLIENT", "h1"); - Service hdfs = installService(cluster, "HDFS"); + Service hdfs = installService(cluster, "HDFS", repositoryVersion2110); addServiceComponent(cluster, hdfs, "NAMENODE"); addServiceComponent(cluster, hdfs, "DATANODE"); createNewServiceComponentHost(cluster, "HDFS", "NAMENODE", "h1"); @@ -393,7 +392,7 @@ public class UpgradeActionTest { for (HostVersionEntity entity : hostVersionDAO.findByClusterAndHost(clusterName, "h1")) { if (StringUtils.equals(entity.getRepositoryVersion().getVersion(), repositoryVersion2110.getVersion())) { assertEquals(RepositoryVersionState.CURRENT, entity.getState()); - } else if (StringUtils.equals(entity.getRepositoryVersion().getVersion(), repositoryVersion2111.getVersion())) { + } else { assertEquals(RepositoryVersionState.INSTALLED, entity.getState()); } } @@ -497,10 +496,95 @@ public class UpgradeActionTest { assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus()); } + /** + * Tests that all host versions are correct after upgrade. This test will + * ensure that the prior CURRENT versions are moved to INSTALLED while not + * touching any others. + * + * @throws Exception + */ + @Test + public void testHostVersionsAfterUpgrade() throws Exception { + String hostName = "h1"; + Cluster cluster = createUpgradeCluster(repositoryVersion2110, hostName); + createHostVersions(repositoryVersion2111, hostName); + createHostVersions(repositoryVersion2201, hostName); + + // Install ZK with some components + Service zk = installService(cluster, "ZOOKEEPER", repositoryVersion2110); + addServiceComponent(cluster, zk, "ZOOKEEPER_SERVER"); + addServiceComponent(cluster, zk, "ZOOKEEPER_CLIENT"); + createNewServiceComponentHost(cluster, "ZOOKEEPER", "ZOOKEEPER_SERVER", hostName); + createNewServiceComponentHost(cluster, "ZOOKEEPER", "ZOOKEEPER_CLIENT", hostName); + + List<HostVersionEntity> hostVersions = hostVersionDAO.findAll(); + assertEquals(3, hostVersions.size()); + + // repo 2110 - CURRENT (upgrading from) + // repo 2111 - CURRENT (all hosts reported in during upgrade) + // repo 2201 - NOT_REQUIRED (different stack) + for (HostVersionEntity hostVersion : hostVersions) { + RepositoryVersionEntity hostRepoVersion = hostVersion.getRepositoryVersion(); + if (repositoryVersion2110.equals(hostRepoVersion)) { + hostVersion.setState(RepositoryVersionState.CURRENT); + } else if (repositoryVersion2111.equals(hostRepoVersion)) { + hostVersion.setState(RepositoryVersionState.CURRENT); + } else { + hostVersion.setState(RepositoryVersionState.NOT_REQUIRED); + } + + hostVersionDAO.merge(hostVersion); + } + + // upgrade to 2111 + createUpgrade(cluster, repositoryVersion2111); + + // push all services to the correct repo version for finalize + Map<String, Service> services = cluster.getServices(); + assertTrue(services.size() > 0); + for (Service service : services.values()) { + service.setDesiredRepositoryVersion(repositoryVersion2111); + } + + // push all components to the correct version + List<HostComponentStateEntity> hostComponentStates = hostComponentStateDAO.findByHost(hostName); + for (HostComponentStateEntity hostComponentState : hostComponentStates) { + hostComponentState.setVersion(repositoryVersion2111.getVersion()); + hostComponentStateDAO.merge(hostComponentState); + } + + Map<String, String> commandParams = new HashMap<>(); + ExecutionCommand executionCommand = new ExecutionCommand(); + executionCommand.setCommandParams(commandParams); + executionCommand.setClusterName(clusterName); + + HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(null, null, null, null); + hostRoleCommand.setExecutionCommandWrapper(new ExecutionCommandWrapper(executionCommand)); + + finalizeUpgradeAction.setExecutionCommand(executionCommand); + finalizeUpgradeAction.setHostRoleCommand(hostRoleCommand); + + // finalize + CommandReport report = finalizeUpgradeAction.execute(null); + assertNotNull(report); + assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus()); + + for (HostVersionEntity hostVersion : hostVersions) { + RepositoryVersionEntity hostRepoVersion = hostVersion.getRepositoryVersion(); + if (repositoryVersion2110.equals(hostRepoVersion)) { + assertEquals(RepositoryVersionState.INSTALLED, hostVersion.getState()); + } else if (repositoryVersion2111.equals(hostRepoVersion)) { + assertEquals(RepositoryVersionState.CURRENT, hostVersion.getState()); + } else { + assertEquals(RepositoryVersionState.NOT_REQUIRED, hostVersion.getState()); + } + } + } + private ServiceComponentHost createNewServiceComponentHost(Cluster cluster, String svc, String svcComponent, String hostName) throws AmbariException { Assert.assertNotNull(cluster.getConfigGroups()); - Service s = installService(cluster, svc); + Service s = installService(cluster, svc, sourceRepositoryVersion); ServiceComponent sc = addServiceComponent(cluster, s, svcComponent); ServiceComponentHost sch = serviceComponentHostFactory.createNew(sc, hostName); @@ -511,13 +595,14 @@ public class UpgradeActionTest { return sch; } - private Service installService(Cluster cluster, String serviceName) throws AmbariException { + private Service installService(Cluster cluster, String serviceName, + RepositoryVersionEntity repositoryVersionEntity) throws AmbariException { Service service = null; try { service = cluster.getService(serviceName); } catch (ServiceNotFoundException e) { - service = serviceFactory.createNew(cluster, serviceName, sourceRepositoryVersion); + service = serviceFactory.createNew(cluster, serviceName, repositoryVersionEntity); cluster.addService(service); } @@ -525,7 +610,7 @@ public class UpgradeActionTest { } private ServiceComponent addServiceComponent(Cluster cluster, Service service, - String componentName) throws AmbariException { + String componentName) throws AmbariException { ServiceComponent serviceComponent = null; try { serviceComponent = service.getServiceComponent(componentName);