You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by kr...@apache.org on 2018/07/31 13:44:56 UTC
[ambari] branch trunk updated: AMBARI-24283 - DB consistency
warning due to config group without service name (#1915)
This is an automated email from the ASF dual-hosted git repository.
krisztiankasa pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new 048b0d4 AMBARI-24283 - DB consistency warning due to config group without service name (#1915)
048b0d4 is described below
commit 048b0d49b173d02cc0bad89135e3100b6e1df3f1
Author: kasakrisz <33...@users.noreply.github.com>
AuthorDate: Tue Jul 31 15:44:52 2018 +0200
AMBARI-24283 - DB consistency warning due to config group without service name (#1915)
---
.../checks/DatabaseConsistencyCheckHelper.java | 248 ++++++++++++++++++++
.../ambari/server/upgrade/UpgradeCatalog271.java | 44 +++-
.../checks/DatabaseConsistencyCheckHelperTest.java | 257 +++++++++++++++++++++
.../server/upgrade/UpgradeCatalog271Test.java | 5 +
4 files changed, 553 insertions(+), 1 deletion(-)
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
index 669ab81..375bcd9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
@@ -36,6 +36,7 @@ import java.util.Scanner;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.inject.Provider;
@@ -59,14 +60,19 @@ import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
import org.apache.ambari.server.orm.entities.MetainfoEntity;
import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
import org.apache.ambari.server.state.ClientConfigFileDefinition;
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.Host;
+import org.apache.ambari.server.state.Service;
import org.apache.ambari.server.state.ServiceInfo;
import org.apache.ambari.server.state.State;
import org.apache.ambari.server.state.UpgradeState;
+import org.apache.ambari.server.state.configgroup.ConfigGroup;
import org.apache.ambari.server.utils.VersionUtils;
+import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -181,6 +187,9 @@ public class DatabaseConsistencyCheckHelper {
if (fixIssues) {
fixHostComponentStatesCountEqualsHostComponentsDesiredStates();
fixClusterConfigsNotMappedToAnyService();
+ fixConfigGroupServiceNames();
+ fixConfigGroupHostMappings();
+ fixConfigGroupsForDeletedServices();
fixConfigsSelectedMoreThanOnce();
}
checkSchemaName();
@@ -191,6 +200,9 @@ public class DatabaseConsistencyCheckHelper {
checkHostComponentStates();
checkServiceConfigs();
checkForLargeTables();
+ checkConfigGroupsHasServiceName();
+ checkConfigGroupHostMapping(true);
+ checkConfigGroupsForDeletedServices(true);
LOG.info("******************************* Check database completed *******************************");
return checkResult;
}
@@ -1147,6 +1159,242 @@ public class DatabaseConsistencyCheckHelper {
}
+ /**
+ * This method collects the ConfigGroups with empty or null service name field
+ */
+ static Map<Long, ConfigGroup> collectConfigGroupsWithoutServiceName() {
+ Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+ Clusters clusters = injector.getInstance(Clusters.class);
+ Map<String, Cluster> clusterMap = clusters.getClusters();
+
+ if (MapUtils.isEmpty(clusterMap))
+ return configGroupMap;
+
+ for (Cluster cluster : clusterMap.values()) {
+ Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups();
+
+ if (MapUtils.isEmpty(configGroups)) {
+ continue;
+ }
+
+ for (ConfigGroup configGroup : configGroups.values()) {
+ if (StringUtils.isEmpty(configGroup.getServiceName())) {
+ configGroupMap.put(configGroup.getId(), configGroup);
+ }
+ }
+ }
+
+ return configGroupMap;
+ }
+
+ /**
+ * This method checks if there are any ConfigGroup with empty or null service name field
+ */
+ static void checkConfigGroupsHasServiceName() {
+ Map<Long, ConfigGroup> configGroupMap = collectConfigGroupsWithoutServiceName();
+ if (MapUtils.isEmpty(configGroupMap))
+ return;
+
+ String message = String.join(" ), ( ",
+ configGroupMap.values().stream().map(ConfigGroup::getName).collect(Collectors.toList()));
+
+ warning("You have config groups present in the database with no " +
+ "service name, [(ConfigGroup) => ( {} )]. Run --auto-fix-database to fix " +
+ "this automatically. Please backup Ambari Server database before running --auto-fix-database.", message);
+ }
+
+ /**
+ * Fix inconsistencies found by @collectConfigGroupsWithoutServiceName
+ */
+ @Transactional
+ static void fixConfigGroupServiceNames() {
+ Map<Long, ConfigGroup> configGroupMap = collectConfigGroupsWithoutServiceName();
+ if (MapUtils.isEmpty(configGroupMap))
+ return;
+
+ Clusters clusters = injector.getInstance(Clusters.class);
+
+ for (Map.Entry<Long, ConfigGroup> configGroupEntry : configGroupMap.entrySet()) {
+ ConfigGroup configGroup = configGroupEntry.getValue();
+ try {
+ Cluster cluster = clusters.getCluster(configGroup.getClusterName());
+ Map<String, Service> serviceMap = cluster.getServices();
+ if (serviceMap.containsKey(configGroup.getTag())) {
+ LOG.info("Setting service name of config group {} with id {} to {}",
+ configGroup.getName(), configGroupEntry.getKey(), configGroup.getTag());
+ configGroup.setServiceName(configGroup.getTag());
+ }
+ else {
+ LOG.info("Config group {} with id {} contains a tag {} which is not a service name in the cluster {}",
+ configGroup.getName(), configGroupEntry.getKey(), configGroup.getTag(), cluster.getClusterName());
+ }
+ } catch (AmbariException e) {
+ // Ignore if cluster not found
+ }
+ }
+ }
+
+ /**
+ * This method checks if there are any ConfigGroup host mappings with hosts
+ * that are not longer a part of the cluster.
+ */
+ static Map<Long, Set<Long>> checkConfigGroupHostMapping(boolean warnIfFound) {
+ LOG.info("Checking config group host mappings");
+ Map<Long, Set<Long>> nonMappedHostIds = new HashMap<>();
+ Clusters clusters = injector.getInstance(Clusters.class);
+ Map<String, Cluster> clusterMap = clusters.getClusters();
+ StringBuilder output = new StringBuilder("[(ConfigGroup, Service, HostCount) => ");
+
+ if (!MapUtils.isEmpty(clusterMap)) {
+ for (Cluster cluster : clusterMap.values()) {
+ Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups();
+ Map<String, Host> clusterHosts = clusters.getHostsForCluster(cluster.getClusterName());
+
+ if (!MapUtils.isEmpty(configGroups) && !MapUtils.isEmpty(clusterHosts)) {
+ for (ConfigGroup configGroup : configGroups.values()) {
+ // Based on current implementation of ConfigGroupImpl the
+ // host mapping would be loaded only if the host actually exists
+ // in the host table
+ Map<Long, Host> hosts = configGroup.getHosts();
+ boolean addToOutput = false;
+ Set<String> hostnames = new HashSet<>();
+ if (!MapUtils.isEmpty(hosts)) {
+ for (Host host : hosts.values()) {
+ // Lookup by hostname - It does have a unique constraint
+ if (!clusterHosts.containsKey(host.getHostName())) {
+ Set<Long> hostIds = nonMappedHostIds.computeIfAbsent(configGroup.getId(), configGroupId -> new HashSet<>());
+ hostIds.add(host.getHostId());
+ hostnames.add(host.getHostName());
+ addToOutput = true;
+ }
+ }
+ }
+ if (addToOutput) {
+ output.append("( ");
+ output.append(configGroup.getName());
+ output.append(", ");
+ output.append(configGroup.getTag());
+ output.append(", ");
+ output.append(hostnames);
+ output.append(" ), ");
+ }
+ }
+ }
+ }
+ }
+ if (!MapUtils.isEmpty(nonMappedHostIds) && warnIfFound) {
+ output.replace(output.lastIndexOf(","), output.length(), "]");
+ warning("You have config group host mappings with hosts that are no " +
+ "longer associated with the cluster, {}. Run --auto-fix-database to " +
+ "fix this automatically. Alternatively, you can remove this mapping " +
+ "from the UI. Please backup Ambari Server database before running --auto-fix-database.", output.toString());
+ }
+
+ return nonMappedHostIds;
+ }
+
+ static Map<Long, ConfigGroup> checkConfigGroupsForDeletedServices(boolean warnIfFound) {
+ Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+ Clusters clusters = injector.getInstance(Clusters.class);
+ Map<String, Cluster> clusterMap = clusters.getClusters();
+ StringBuilder output = new StringBuilder("[(ConfigGroup, Service) => ");
+
+ if (!MapUtils.isEmpty(clusterMap)) {
+ for (Cluster cluster : clusterMap.values()) {
+ Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups();
+ Map<String, Service> services = cluster.getServices();
+
+ if (!MapUtils.isEmpty(configGroups)) {
+ for (ConfigGroup configGroup : configGroups.values()) {
+ if (!services.containsKey(configGroup.getServiceName())) {
+ configGroupMap.put(configGroup.getId(), configGroup);
+ output.append("( ");
+ output.append(configGroup.getName());
+ output.append(", ");
+ output.append(configGroup.getServiceName());
+ output.append(" ), ");
+ }
+ }
+ }
+ }
+ }
+
+ if (warnIfFound && !configGroupMap.isEmpty()) {
+ output.replace(output.lastIndexOf(","), output.length(), "]");
+ warning("You have config groups present in the database with no " +
+ "corresponding service found, {}. Run --auto-fix-database to fix " +
+ "this automatically. Please backup Ambari Server database before running --auto-fix-database.", output.toString());
+ }
+
+ return configGroupMap;
+ }
+
+ @Transactional
+ static void fixConfigGroupsForDeletedServices() {
+ Map<Long, ConfigGroup> configGroupMap = checkConfigGroupsForDeletedServices(false);
+ Clusters clusters = injector.getInstance(Clusters.class);
+
+ if (!MapUtils.isEmpty(configGroupMap)) {
+ for (Map.Entry<Long, ConfigGroup> configGroupEntry : configGroupMap.entrySet()) {
+ Long id = configGroupEntry.getKey();
+ ConfigGroup configGroup = configGroupEntry.getValue();
+ if (!StringUtils.isEmpty(configGroup.getServiceName())) {
+ LOG.info("Deleting config group {} with id {} for deleted service {}",
+ configGroup.getName(), id, configGroup.getServiceName());
+ try {
+ Cluster cluster = clusters.getCluster(configGroup.getClusterName());
+ cluster.deleteConfigGroup(id);
+ } catch (AuthorizationException e) {
+ // This call does not thrown Authorization Exception
+ } catch (AmbariException e) {
+ // Ignore if cluster not found
+ }
+ }
+ else {
+ warning("The config group {} with id {} can not be fixed automatically because service name is missing.",
+ configGroup.getName(), id);
+ }
+ }
+ }
+ }
+
+ /**
+ * Fix inconsistencies found by @checkConfigGroupHostMapping
+ */
+ @Transactional
+ static void fixConfigGroupHostMappings() {
+ Map<Long, Set<Long>> nonMappedHostIds = checkConfigGroupHostMapping(false);
+ Clusters clusters = injector.getInstance(Clusters.class);
+
+ if (!MapUtils.isEmpty(nonMappedHostIds)) {
+ LOG.info("Fixing {} config groups with inconsistent host mappings", nonMappedHostIds.size());
+
+ for (Map.Entry<Long, Set<Long>> nonMappedHostEntry : nonMappedHostIds.entrySet()) {
+ if (!MapUtils.isEmpty(clusters.getClusters())) {
+ for (Cluster cluster : clusters.getClusters().values()) {
+ Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups();
+ if (!MapUtils.isEmpty(configGroups)) {
+ ConfigGroup configGroup = configGroups.get(nonMappedHostEntry.getKey());
+ if (configGroup != null) {
+ for (Long hostId : nonMappedHostEntry.getValue()) {
+ try {
+ configGroup.removeHost(hostId);
+ } catch (AmbariException e) {
+ LOG.warn("Unable to fix inconsistency by removing host " +
+ "mapping for config group: {}, service: {}, hostId = {}",
+ configGroup.getName(), configGroup.getTag(), hostId);
+ }
+ }
+ } else {
+ LOG.warn("Unable to find config group with id = {}", nonMappedHostEntry.getKey());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
private static void ensureConnection() {
if (connection == null) {
if (dbAccessor == null) {
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog271.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog271.java
index c8a4d99..010ab62 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog271.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog271.java
@@ -17,6 +17,9 @@
*/
package org.apache.ambari.server.upgrade;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_INFRA_NEW_NAME;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_INFRA_OLD_NAME;
+
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
@@ -24,13 +27,17 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.orm.dao.DaoUtils;
+import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.state.Config;
-
+import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -97,6 +104,7 @@ public class UpgradeCatalog271 extends AbstractUpgradeCatalog {
addNewConfigurationsFromXml();
updateRangerLogDirConfigs();
updateRangerKmsDbUrl();
+ renameAmbariInfraInConfigGroups();
}
/**
@@ -195,4 +203,38 @@ public class UpgradeCatalog271 extends AbstractUpgradeCatalog {
}
}
+ protected void renameAmbariInfraInConfigGroups() {
+ LOG.info("Renaming service AMBARI_INFRA to AMBARI_INFRA_SOLR in config group records");
+ AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
+ Clusters clusters = ambariManagementController.getClusters();
+ if (clusters == null)
+ return;
+
+ Map<String, Cluster> clusterMap = clusters.getClusters();
+ if (MapUtils.isEmpty(clusterMap))
+ return;
+
+ EntityManager entityManager = getEntityManagerProvider().get();
+
+ executeInTransaction(() -> {
+ TypedQuery<ServiceConfigEntity> serviceConfigUpdate = entityManager.createQuery(
+ "UPDATE ConfigGroupEntity SET serviceName = :newServiceName WHERE serviceName = :oldServiceName", ServiceConfigEntity.class);
+ serviceConfigUpdate.setParameter("newServiceName", AMBARI_INFRA_NEW_NAME);
+ serviceConfigUpdate.setParameter("oldServiceName", AMBARI_INFRA_OLD_NAME);
+ serviceConfigUpdate.executeUpdate();
+ });
+
+ executeInTransaction(() -> {
+ TypedQuery<ServiceConfigEntity> serviceConfigUpdate = entityManager.createQuery(
+ "UPDATE ConfigGroupEntity SET tag = :newServiceName WHERE tag = :oldServiceName", ServiceConfigEntity.class);
+ serviceConfigUpdate.setParameter("newServiceName", AMBARI_INFRA_NEW_NAME);
+ serviceConfigUpdate.setParameter("oldServiceName", AMBARI_INFRA_OLD_NAME);
+ serviceConfigUpdate.executeUpdate();
+ });
+
+
+ // Force the clusters object to reload to ensure the renamed service is accounted for
+ entityManager.getEntityManagerFactory().getCache().evictAll();
+ clusters.invalidateAllClusters();
+ }
}
\ No newline at end of file
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java
index 91b18e1..e38b24f 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java
@@ -40,6 +40,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
@@ -52,9 +53,13 @@ import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
import org.apache.ambari.server.stack.StackManagerFactory;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.Service;
import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.state.configgroup.ConfigGroup;
import org.apache.ambari.server.state.stack.OsFamily;
import org.apache.ambari.server.testutils.PartialNiceMockBinder;
+import org.apache.commons.collections.MapUtils;
import org.easymock.EasyMockSupport;
import org.junit.Assert;
import org.junit.Test;
@@ -523,6 +528,258 @@ public class DatabaseConsistencyCheckHelperTest {
}
@Test
+ public void testConfigGroupHostMappings() throws Exception {
+ EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+ final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class);
+
+ final StackManagerFactory mockStackManagerFactory = easyMockSupport.createNiceMock(StackManagerFactory.class);
+ final EntityManager mockEntityManager = easyMockSupport.createNiceMock(EntityManager.class);
+ final Clusters mockClusters = easyMockSupport.createNiceMock(Clusters.class);
+ final OsFamily mockOSFamily = easyMockSupport.createNiceMock(OsFamily.class);
+ final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+ bind(EntityManager.class).toInstance(mockEntityManager);
+ bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+ bind(Clusters.class).toInstance(mockClusters);
+ bind(OsFamily.class).toInstance(mockOSFamily);
+ }
+ });
+
+ Map<String, Cluster> clusters = new HashMap<>();
+ Cluster cluster = easyMockSupport.createNiceMock(Cluster.class);
+ clusters.put("c1", cluster);
+ expect(mockClusters.getClusters()).andReturn(clusters).anyTimes();
+
+ Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+ ConfigGroup cg1 = easyMockSupport.createNiceMock(ConfigGroup.class);
+ ConfigGroup cg2 = easyMockSupport.createNiceMock(ConfigGroup.class);
+ configGroupMap.put(1L, cg1);
+ configGroupMap.put(2L, cg2);
+
+ expect(cluster.getConfigGroups()).andReturn(configGroupMap).anyTimes();
+
+ expect(cluster.getClusterName()).andReturn("c1").anyTimes();
+
+ Map<String, Host> hosts = new HashMap<>();
+ Host h1 = easyMockSupport.createNiceMock(Host.class);
+ Host h2 = easyMockSupport.createNiceMock(Host.class);
+ hosts.put("h1", h1);
+ expect(mockClusters.getHostsForCluster("c1")).andReturn(hosts);
+
+ Map<Long, Host> cgHosts = new HashMap<>();
+ cgHosts.put(1L, h1);
+ cgHosts.put(2L, h2);
+
+ expect(cg1.getHosts()).andReturn(cgHosts);
+
+ expect(h1.getHostName()).andReturn("h1").anyTimes();
+ expect(h2.getHostName()).andReturn("h2").anyTimes() ;
+ expect(h1.getHostId()).andReturn(1L).anyTimes();
+ expect(h2.getHostId()).andReturn(2L).anyTimes();
+
+ expect(cg1.getId()).andReturn(1L).anyTimes();
+ expect(cg2.getId()).andReturn(2L).anyTimes();
+ expect(cg1.getName()).andReturn("cg1").anyTimes();
+ expect(cg2.getName()).andReturn("cg2").anyTimes();
+
+ DatabaseConsistencyCheckHelper.setInjector(mockInjector);
+
+ easyMockSupport.replayAll();
+
+ Map<Long, Set<Long>> hostIds = DatabaseConsistencyCheckHelper.checkConfigGroupHostMapping(true);
+
+ easyMockSupport.verifyAll();
+
+ Assert.assertNotNull(hostIds);
+ Assert.assertEquals(1, hostIds.size());
+ Assert.assertEquals(1L, hostIds.keySet().iterator().next().longValue());
+ Assert.assertEquals(2L, hostIds.get(1L).iterator().next().longValue());
+ }
+
+ @Test
+ public void testConfigGroupForDeletedServices() throws Exception {
+ EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+ final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class);
+
+ final StackManagerFactory mockStackManagerFactory = easyMockSupport.createNiceMock(StackManagerFactory.class);
+ final EntityManager mockEntityManager = easyMockSupport.createNiceMock(EntityManager.class);
+ final Clusters mockClusters = easyMockSupport.createNiceMock(Clusters.class);
+ final OsFamily mockOSFamily = easyMockSupport.createNiceMock(OsFamily.class);
+ final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+ bind(EntityManager.class).toInstance(mockEntityManager);
+ bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+ bind(Clusters.class).toInstance(mockClusters);
+ bind(OsFamily.class).toInstance(mockOSFamily);
+ }
+ });
+
+ Map<String, Cluster> clusters = new HashMap<>();
+ Cluster cluster = easyMockSupport.createStrictMock(Cluster.class);
+ clusters.put("c1", cluster);
+ expect(mockClusters.getClusters()).andReturn(clusters).anyTimes();
+
+ Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+ ConfigGroup cg1 = easyMockSupport.createNiceMock(ConfigGroup.class);
+ ConfigGroup cg2 = easyMockSupport.createNiceMock(ConfigGroup.class);
+ ConfigGroup cgWithoutServiceName = easyMockSupport.createNiceMock(ConfigGroup.class);
+ configGroupMap.put(1L, cg1);
+ configGroupMap.put(2L, cg2);
+ configGroupMap.put(3L, cgWithoutServiceName);
+
+ expect(cluster.getConfigGroups()).andStubReturn(configGroupMap);
+ expect(cg1.getName()).andReturn("cg1").anyTimes();
+ expect(cg1.getId()).andReturn(1L).anyTimes();
+ expect(cg1.getServiceName()).andReturn("YARN").anyTimes();
+ expect(cg2.getServiceName()).andReturn("HDFS").anyTimes();
+ expect(cgWithoutServiceName.getName()).andReturn("cg3").anyTimes();
+ expect(cgWithoutServiceName.getId()).andReturn(3L).anyTimes();
+ expect(cgWithoutServiceName.getServiceName()).andReturn(null).anyTimes();
+
+ Service service = easyMockSupport.createNiceMock(Service.class);
+ Map<String, Service> services = new HashMap<>();
+ services.put("HDFS", service);
+ expect(cluster.getServices()).andReturn(services).anyTimes();
+
+ expect(cg1.getClusterName()).andReturn("c1");
+ expect(mockClusters.getCluster("c1")).andReturn(cluster).anyTimes();
+ cluster.deleteConfigGroup(1L);
+ expectLastCall();
+
+ DatabaseConsistencyCheckHelper.setInjector(mockInjector);
+
+ easyMockSupport.replayAll();
+
+ Map<Long, ConfigGroup> configGroups = DatabaseConsistencyCheckHelper.checkConfigGroupsForDeletedServices(true);
+ DatabaseConsistencyCheckHelper.fixConfigGroupsForDeletedServices();
+
+ easyMockSupport.verifyAll();
+
+ Assert.assertFalse(MapUtils.isEmpty(configGroups));
+ Assert.assertEquals(2, configGroups.size());
+ Assert.assertTrue(configGroups.containsKey(1L));
+ Assert.assertFalse(configGroups.containsKey(2L));
+ Assert.assertTrue(configGroups.containsKey(3L));
+ }
+
+ @Test
+ public void testCollectConfigGroupsWithoutServiceName() throws Exception {
+ EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+ final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class);
+
+ final StackManagerFactory mockStackManagerFactory = easyMockSupport.createNiceMock(StackManagerFactory.class);
+ final EntityManager mockEntityManager = easyMockSupport.createNiceMock(EntityManager.class);
+ final Clusters mockClusters = easyMockSupport.createNiceMock(Clusters.class);
+ final OsFamily mockOSFamily = easyMockSupport.createNiceMock(OsFamily.class);
+ final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+ bind(EntityManager.class).toInstance(mockEntityManager);
+ bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+ bind(Clusters.class).toInstance(mockClusters);
+ bind(OsFamily.class).toInstance(mockOSFamily);
+ }
+ });
+
+ Map<String, Cluster> clusters = new HashMap<>();
+ Cluster cluster1 = easyMockSupport.createNiceMock(Cluster.class);
+ clusters.put("c1", cluster1);
+ Cluster cluster2 = easyMockSupport.createNiceMock(Cluster.class);
+ clusters.put("c2", cluster2);
+ expect(cluster2.getConfigGroups()).andReturn(new HashMap<Long, ConfigGroup>(0)).anyTimes();
+ expect(mockClusters.getClusters()).andReturn(clusters).anyTimes();
+ expect(mockClusters.getCluster("c1")).andReturn(cluster1).anyTimes();
+ expect(mockClusters.getCluster("c2")).andReturn(cluster2).anyTimes();
+
+ Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+ ConfigGroup cgWithoutServiceName = easyMockSupport.createNiceMock(ConfigGroup.class);
+ ConfigGroup cgWithServiceName = easyMockSupport.createNiceMock(ConfigGroup.class);
+ ConfigGroup cgForNonExistentService = easyMockSupport.createNiceMock(ConfigGroup.class);
+ configGroupMap.put(1L, cgWithoutServiceName);
+ configGroupMap.put(2L, cgWithServiceName);
+ configGroupMap.put(3L, cgForNonExistentService);
+
+ expect(cluster1.getConfigGroups()).andReturn(configGroupMap).anyTimes();
+ expect(cgWithoutServiceName.getId()).andReturn(1L).anyTimes();
+ expect(cgWithoutServiceName.getClusterName()).andReturn("c1").anyTimes();
+ expect(cgWithoutServiceName.getServiceName()).andReturn(null).anyTimes();
+ expect(cgWithoutServiceName.getTag()).andReturn("YARN").anyTimes();
+ cgWithoutServiceName.setServiceName("YARN"); expectLastCall();
+ expect(cgWithServiceName.getId()).andReturn(2L).anyTimes();
+ expect(cgWithServiceName.getClusterName()).andReturn("c1").anyTimes();
+ expect(cgWithServiceName.getServiceName()).andReturn("HDFS").anyTimes();
+ expect(cgForNonExistentService.getId()).andReturn(3L).anyTimes();
+ expect(cgForNonExistentService.getClusterName()).andReturn("c1").anyTimes();
+ expect(cgForNonExistentService.getServiceName()).andReturn(null).anyTimes();
+ expect(cgForNonExistentService.getTag()).andReturn("NOT_EXISTS").anyTimes();
+
+ Service hdfsService = easyMockSupport.createNiceMock(Service.class);
+ Service yarnService = easyMockSupport.createNiceMock(Service.class);
+ Map<String, Service> services = new HashMap<>();
+ services.put("HDFS", hdfsService);
+ services.put("YARN", yarnService);
+ expect(cluster1.getServices()).andReturn(services).anyTimes();
+
+ DatabaseConsistencyCheckHelper.setInjector(mockInjector);
+
+ easyMockSupport.replayAll();
+
+ Map<Long, ConfigGroup> configGroups = DatabaseConsistencyCheckHelper.collectConfigGroupsWithoutServiceName();
+ DatabaseConsistencyCheckHelper.fixConfigGroupServiceNames();
+
+ easyMockSupport.verifyAll();
+
+ Assert.assertFalse(MapUtils.isEmpty(configGroups));
+ Assert.assertEquals(2, configGroups.size());
+ Assert.assertTrue(configGroups.containsKey(1L));
+ Assert.assertFalse(configGroups.containsKey(2L));
+ Assert.assertTrue(configGroups.containsKey(3L));
+ }
+
+ @Test
+ public void testCollectConfigGroupsWithoutServiceNameReturnsEmptyMapWhenNoClusters() throws Exception {
+ EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+ final DBAccessor mockDBDbAccessor = easyMockSupport.createNiceMock(DBAccessor.class);
+
+ final StackManagerFactory mockStackManagerFactory = easyMockSupport.createNiceMock(StackManagerFactory.class);
+ final EntityManager mockEntityManager = easyMockSupport.createNiceMock(EntityManager.class);
+ final Clusters mockClusters = easyMockSupport.createNiceMock(Clusters.class);
+ final OsFamily mockOSFamily = easyMockSupport.createNiceMock(OsFamily.class);
+ final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+ bind(EntityManager.class).toInstance(mockEntityManager);
+ bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+ bind(Clusters.class).toInstance(mockClusters);
+ bind(OsFamily.class).toInstance(mockOSFamily);
+ }
+ });
+
+ Map<String, Cluster> clusters = new HashMap<>();
+ expect(mockClusters.getClusters()).andReturn(clusters).anyTimes();
+
+ DatabaseConsistencyCheckHelper.setInjector(mockInjector);
+
+ easyMockSupport.replayAll();
+
+ Map<Long, ConfigGroup> configGroups = DatabaseConsistencyCheckHelper.collectConfigGroupsWithoutServiceName();
+
+ easyMockSupport.verifyAll();
+
+ Assert.assertTrue(MapUtils.isEmpty(configGroups));
+ }
+
+ @Test
public void testFixConfigsSelectedMoreThanOnce() throws Exception {
EasyMockSupport easyMockSupport = new EasyMockSupport();
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog271Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog271Test.java
index d7a1069..8d397f0 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog271Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog271Test.java
@@ -55,11 +55,13 @@ public class UpgradeCatalog271Test {
Method addNewConfigurationsFromXml = AbstractUpgradeCatalog.class.getDeclaredMethod("addNewConfigurationsFromXml");
Method updateRangerLogDirConfigs = UpgradeCatalog271.class.getDeclaredMethod("updateRangerLogDirConfigs");
Method updateRangerKmsDbUrl = UpgradeCatalog271.class.getDeclaredMethod("updateRangerKmsDbUrl");
+ Method renameAmbariInfraInConfigGroups = UpgradeCatalog271.class.getDeclaredMethod("renameAmbariInfraInConfigGroups");
UpgradeCatalog271 upgradeCatalog271 = createMockBuilder(UpgradeCatalog271.class)
.addMockedMethod(updateRangerKmsDbUrl)
.addMockedMethod(updateRangerLogDirConfigs)
.addMockedMethod(addNewConfigurationsFromXml)
+ .addMockedMethod(renameAmbariInfraInConfigGroups)
.createMock();
upgradeCatalog271.addNewConfigurationsFromXml();
@@ -71,6 +73,9 @@ public class UpgradeCatalog271Test {
upgradeCatalog271.updateRangerKmsDbUrl();
expectLastCall().once();
+ upgradeCatalog271.renameAmbariInfraInConfigGroups();
+ expectLastCall().once();
+
replay(upgradeCatalog271);
upgradeCatalog271.executeDMLUpdates();
verify(upgradeCatalog271);