Repository: ambari Updated Branches: refs/heads/branch-2.1 bbe4c9a1e -> c3348ea1f
AMBARI-14079 - Unable to Finalize Upgrade After Removing Host In Maintenance Mode (jonathanhurley) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c3348ea1 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c3348ea1 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c3348ea1 Branch: refs/heads/branch-2.1 Commit: c3348ea1f9d86b4c7164602ac1fbfa19f476ba54 Parents: bbe4c9a Author: Jonathan Hurley <[email protected]> Authored: Wed Nov 25 18:40:13 2015 -0500 Committer: Jonathan Hurley <[email protected]> Committed: Mon Nov 30 12:33:36 2015 -0500 ---------------------------------------------------------------------- .../ambari/server/orm/entities/HostEntity.java | 13 ++- .../upgrades/FinalizeUpgradeAction.java | 3 +- .../server/state/cluster/ClusterImpl.java | 16 ++-- .../server/state/cluster/ClustersImpl.java | 35 ++++---- .../upgrades/UpgradeActionTest.java | 85 +++++++++++++++++++- 5 files changed, 121 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/c3348ea1/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java index 502c060..2f94e67 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java @@ -278,18 +278,27 @@ public class HostEntity implements Comparable<HostEntity> { if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } HostEntity that = (HostEntity) o; - return hostId == that.hostId && hostName.equals(that.hostName); + return getHostId() == that.getHostId() && hostName.equals(that.hostName); } + /** + * {@inheritDoc} + */ @Override public int hashCode() { - return (null == hostId ? 0 : hostId.hashCode()); + int result = null != getHostId() ? getHostId().hashCode() : 0; + if (null != hostName) { + result = 31 * result + hostName.hashCode(); + } + + return result; } @Override http://git-wip-us.apache.org/repos/asf/ambari/blob/c3348ea1/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 ba4dadc..9331ef0 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 @@ -163,7 +163,8 @@ public class FinalizeUpgradeAction extends AbstractServerAction { boolean hostHasCorrectVersionState = false; RepositoryVersionState hostVersionState = hostVersion.getState(); switch( hostVersionState ){ - case UPGRADED:{ + case UPGRADED: + case CURRENT:{ // if the state is correct, then do nothing hostHasCorrectVersionState = true; break; http://git-wip-us.apache.org/repos/asf/ambari/blob/c3348ea1/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java index 11c1f1b..65149a3 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java @@ -37,8 +37,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.persistence.RollbackException; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.ConfigGroupNotFoundException; import org.apache.ambari.server.DuplicateResourceException; @@ -101,6 +99,7 @@ import org.apache.ambari.server.state.Host; import org.apache.ambari.server.state.HostHealthStatus; import org.apache.ambari.server.state.HostState; import org.apache.ambari.server.state.MaintenanceState; +import org.apache.ambari.server.state.PropertyInfo; import org.apache.ambari.server.state.RepositoryVersionState; import org.apache.ambari.server.state.SecurityType; import org.apache.ambari.server.state.Service; @@ -111,9 +110,8 @@ import org.apache.ambari.server.state.ServiceComponentHostEventType; import org.apache.ambari.server.state.ServiceFactory; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.state.StackId; -import org.apache.ambari.server.state.State; -import org.apache.ambari.server.state.PropertyInfo; import org.apache.ambari.server.state.StackInfo; +import org.apache.ambari.server.state.State; import org.apache.ambari.server.state.configgroup.ConfigGroup; import org.apache.ambari.server.state.configgroup.ConfigGroupFactory; import org.apache.ambari.server.state.fsm.InvalidStateTransitionException; @@ -124,7 +122,9 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Predicate; import com.google.common.collect.HashMultimap; +import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; @@ -1669,8 +1669,7 @@ public class ClusterImpl implements Cluster { if (state == RepositoryVersionState.CURRENT) { for (HostEntity hostEntity : clusterEntity.getHostEntities()) { - if (hostHasReportables(existingClusterVersion.getRepositoryVersion(), - hostEntity)) { + if (hostHasReportables(existingClusterVersion.getRepositoryVersion(), hostEntity)) { continue; } @@ -1827,8 +1826,9 @@ public class ClusterImpl implements Cluster { return null; } for(Map.Entry<String, Config> entry: allConfigs.get(configType).entrySet()) { - if(entry.getValue().getVersion().equals(configVersion)) + if(entry.getValue().getVersion().equals(configVersion)) { return entry.getValue(); + } } return null; } finally { @@ -2989,7 +2989,7 @@ public class ClusterImpl implements Cluster { @Override public Map<PropertyInfo.PropertyType, Set<String>> getConfigPropertiesTypes(String configType){ try { - StackId stackId = this.getCurrentStackVersion(); + StackId stackId = getCurrentStackVersion(); StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(), stackId.getStackVersion()); return stackInfo.getConfigPropertiesTypes(configType); } catch (AmbariException e) { http://git-wip-us.apache.org/repos/asf/ambari/blob/c3348ea1/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java index facef8b..944a24e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java @@ -18,9 +18,20 @@ package org.apache.ambari.server.state.cluster; -import com.google.inject.Inject; -import com.google.inject.Singleton; -import com.google.inject.persist.Transactional; +import java.util.ArrayList; +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.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import javax.persistence.RollbackException; + import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.ClusterNotFoundException; import org.apache.ambari.server.DuplicateResourceException; @@ -56,6 +67,7 @@ import org.apache.ambari.server.orm.entities.ResourceTypeEntity; import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.security.SecurityHelper; import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority; +import org.apache.ambari.server.security.authorization.ResourceType; import org.apache.ambari.server.state.AgentVersion; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; @@ -73,18 +85,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.GrantedAuthority; -import javax.persistence.RollbackException; -import java.util.ArrayList; -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.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.google.inject.persist.Transactional; @Singleton public class ClustersImpl implements Clusters { @@ -780,7 +783,7 @@ public class ClustersImpl implements Clusters { clusterEntity.getHostEntities().remove(hostEntity); hostDAO.merge(hostEntity); - clusterDAO.merge(clusterEntity); + clusterDAO.merge(clusterEntity, true); } @Transactional http://git-wip-us.apache.org/repos/asf/ambari/blob/c3348ea1/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 8533d1d..2e3c623 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 @@ -49,6 +49,7 @@ import org.apache.ambari.server.orm.dao.RepositoryVersionDAO; import org.apache.ambari.server.orm.dao.StackDAO; import org.apache.ambari.server.orm.entities.ClusterVersionEntity; import org.apache.ambari.server.orm.entities.HostVersionEntity; +import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; @@ -205,6 +206,9 @@ public class UpgradeActionTest { host.setHostAttributes(hostAttributes); host.persist(); + // without this, HostEntity will not have a relation to ClusterEntity + clusters.mapHostsToCluster(Collections.singleton(hostName), clusterName); + // Create the starting repo version m_helper.getOrCreateRepositoryVersion(sourceStack, sourceRepo); c.createClusterVersion(sourceStack, sourceRepo, "admin", RepositoryVersionState.UPGRADING); @@ -214,6 +218,7 @@ public class UpgradeActionTest { String urlInfo = "[{'repositories':[" + "{'Repositories/base_url':'http://foo1','Repositories/repo_name':'HDP','Repositories/repo_id':'" + targetStack.getStackId() + "'}" + "], 'OperatingSystems/os_type':'redhat6'}]"; + repoVersionDAO.create(stackEntityTarget, targetRepo, String.valueOf(System.currentTimeMillis()), urlInfo); // Start upgrading the newer repo @@ -226,13 +231,23 @@ public class UpgradeActionTest { c.mapHostVersions(Collections.singleton(hostName), c.getCurrentClusterVersion(), RepositoryVersionState.CURRENT); + // create a single host with the UPGRADED HostVersionEntity HostDAO hostDAO = m_injector.getInstance(HostDAO.class); - HostVersionEntity entity = new HostVersionEntity(); - entity.setHostEntity(hostDAO.findByName(hostName)); - entity.setRepositoryVersion(repoVersionDAO.findByStackAndVersion(targetStack, targetRepo)); - entity.setState(RepositoryVersionState.UPGRADED); + RepositoryVersionEntity repositoryVersionEntity = repoVersionDAO.findByStackAndVersion( + targetStack, targetRepo); + + HostVersionEntity entity = new HostVersionEntity(hostDAO.findByName(hostName), + repositoryVersionEntity, RepositoryVersionState.UPGRADED); + hostVersionDAO.create(entity); + + // verify the UPGRADED host versions were created successfully + List<HostVersionEntity> hostVersions = hostVersionDAO.findByClusterStackAndVersion(clusterName, + targetStack, targetRepo); + + assertEquals(1, hostVersions.size()); + assertEquals(RepositoryVersionState.UPGRADED, hostVersions.get(0).getState()); } private void makeCrossStackUpgradeCluster(StackId sourceStack, String sourceRepo, StackId targetStack, String targetRepo) throws Exception { @@ -383,6 +398,68 @@ public class UpgradeActionTest { verifyBaseRepoURL(helper, cluster, host, "http://foo1"); } + /** + * Tests that finalize still works when there are hosts which are already + * {@link RepositoryVersionState#CURRENT}. + * + * @throws Exception + */ + @Test + public void testFinalizeWithHostsAlreadyCurrent() throws Exception { + StackId sourceStack = HDP_21_STACK; + StackId targetStack = HDP_21_STACK; + String sourceRepo = HDP_2_1_1_0; + String targetRepo = HDP_2_1_1_1; + + makeUpgradeCluster(sourceStack, sourceRepo, targetStack, targetRepo); + + // move the old version from CURRENT to INSTALLED and the new version from + // UPGRADED to CURRENT - this will simulate what happens when a host is + // removed before finalization and all hosts transition to CURRENT + List<HostVersionEntity> hostVersions = hostVersionDAO.findAll(); + for (HostVersionEntity hostVersion : hostVersions) { + if (hostVersion.getState() == RepositoryVersionState.CURRENT) { + hostVersion.setState(RepositoryVersionState.INSTALLED); + } else { + hostVersion.setState(RepositoryVersionState.CURRENT); + } + + hostVersionDAO.merge(hostVersion); + } + + // Verify the repo before calling Finalize + AmbariMetaInfo metaInfo = m_injector.getInstance(AmbariMetaInfo.class); + AmbariCustomCommandExecutionHelper helper = m_injector.getInstance(AmbariCustomCommandExecutionHelper.class); + Clusters clusters = m_injector.getInstance(Clusters.class); + Host host = clusters.getHost("h1"); + Cluster cluster = clusters.getCluster("c1"); + + RepositoryInfo repo = metaInfo.getRepository(sourceStack.getStackName(), + sourceStack.getStackVersion(), "redhat6", sourceStack.getStackId()); + assertEquals(HDP_211_CENTOS6_REPO_URL, repo.getBaseUrl()); + verifyBaseRepoURL(helper, cluster, host, HDP_211_CENTOS6_REPO_URL); + + // Finalize the upgrade + Map<String, String> commandParams = new HashMap<String, String>(); + commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade"); + commandParams.put(FinalizeUpgradeAction.VERSION_KEY, targetRepo); + + ExecutionCommand executionCommand = new ExecutionCommand(); + executionCommand.setCommandParams(commandParams); + executionCommand.setClusterName("c1"); + + HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(null, null, null, null); + hostRoleCommand.setExecutionCommandWrapper(new ExecutionCommandWrapper(executionCommand)); + + FinalizeUpgradeAction action = m_injector.getInstance(FinalizeUpgradeAction.class); + action.setExecutionCommand(executionCommand); + action.setHostRoleCommand(hostRoleCommand); + + CommandReport report = action.execute(null); + assertNotNull(report); + assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus()); + } + private void verifyBaseRepoURL(AmbariCustomCommandExecutionHelper helper, Cluster cluster, Host host, String expectedRepoBaseURL) throws AmbariException { String repoInfo = helper.getRepoInfo(cluster, host); Gson gson = new Gson();
