You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2015/11/04 22:27:09 UTC
ambari git commit: AMBARI-13722. Confusing message is shown when
there are service check failures that have been skipped during RU (Dmitro
Lisnichenko via ncole)
Repository: ambari
Updated Branches:
refs/heads/branch-2.1 b90a7e33c -> 36681a57e
AMBARI-13722. Confusing message is shown when there are service check failures that have been skipped during RU (Dmitro Lisnichenko via ncole)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/36681a57
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/36681a57
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/36681a57
Branch: refs/heads/branch-2.1
Commit: 36681a57e8cbda3ce9530e49e90426df6a91e2ef
Parents: b90a7e3
Author: Nate Cole <nc...@hortonworks.com>
Authored: Wed Nov 4 16:26:54 2015 -0500
Committer: Nate Cole <nc...@hortonworks.com>
Committed: Wed Nov 4 16:26:54 2015 -0500
----------------------------------------------------------------------
.../ambari/server/metadata/ActionMetadata.java | 14 +
.../upgrades/AutoSkipFailedSummaryAction.java | 114 +++--
.../AutoSkipFailedSummaryActionTest.java | 455 +++++++++++++++++++
3 files changed, 552 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/36681a57/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java b/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
index f5642a0..db10125 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
@@ -99,6 +99,20 @@ public class ActionMetadata {
return serviceCheckActions.get(serviceName.toLowerCase());
}
+ /**
+ * Get service name by service check action name
+ * @param serviceCheckAction service check action name like ZOOKEEPER_QUORUM_SERVICE_CHECK
+ * @return service name (capitalized) or null if not found
+ */
+ public String getServiceNameByServiceCheckAction(String serviceCheckAction) {
+ for (Map.Entry<String, String> entry : serviceCheckActions.entrySet()) {
+ if (entry.getValue().equals(serviceCheckAction)) {
+ return entry.getKey().toUpperCase();
+ }
+ }
+ return null;
+ }
+
public void addServiceCheckAction(String serviceName) {
String actionName = serviceName + SERVICE_CHECK_POSTFIX;
http://git-wip-us.apache.org/repos/asf/ambari/blob/36681a57/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java
index 9a84e38..80c1611 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryAction.java
@@ -18,25 +18,28 @@
package org.apache.ambari.server.serveraction.upgrades;
import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeSet;
+import java.util.*;
import java.util.concurrent.ConcurrentMap;
import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.Role;
+import org.apache.ambari.server.RoleCommand;
import org.apache.ambari.server.actionmanager.HostRoleCommand;
import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.actionmanager.ServiceComponentHostEventWrapper;
import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.metadata.ActionMetadata;
import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
import org.apache.ambari.server.orm.dao.UpgradeDAO;
import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
import org.apache.ambari.server.orm.entities.UpgradeItemEntity;
import org.apache.ambari.server.serveraction.AbstractServerAction;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.state.ServiceComponentHostEvent;
-import org.apache.commons.lang.StringUtils;
+import org.apache.ambari.server.state.StackId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,6 +70,11 @@ public class AutoSkipFailedSummaryAction extends AbstractServerAction {
*/
private static final String MIDDLE_ELLIPSIZE_MARKER = "\n\u2026\n";
+ private static final String SKIPPED_SERVICE_CHECK = "service_check";
+ private static final String SKIPPED_HOST_COMPONENT = "host_component";
+ private static final String SKIPPED = "skipped";
+ private static final String FAILURES = "failures";
+
/**
* Used to lookup the {@link UpgradeGroupEntity}.
*/
@@ -87,9 +95,21 @@ public class AutoSkipFailedSummaryAction extends AbstractServerAction {
private Gson m_gson;
/**
+ * Used to look up service check name -> service name bindings
+ */
+ @Inject
+ private ActionMetadata actionMetadata;
+
+ @Inject
+ private AmbariMetaInfo ambariMetaInfo;
+
+ @Inject
+ private Clusters clusters;
+
+ /**
* A mapping of host -> Map<key,info> for each failure.
*/
- private Map<String, Map<String, Object>> m_structuredFailures = new HashMap<>();
+ private Map<String, Object> m_structuredFailures = new HashMap<>();
/**
* {@inheritDoc}
@@ -102,6 +122,10 @@ public class AutoSkipFailedSummaryAction extends AbstractServerAction {
long requestId = hostRoleCommand.getRequestId();
long stageId = hostRoleCommand.getStageId();
+ String clusterName = hostRoleCommand.getExecutionCommandWrapper().getExecutionCommand().getClusterName();
+ Cluster cluster = clusters.getCluster(clusterName);
+ StackId stackId = cluster.getDesiredStackVersion();
+
// use the host role command to get to the parent upgrade group
UpgradeItemEntity upgradeItem = m_upgradeDAO.findUpgradeItemByRequestAndStage(requestId,stageId);
UpgradeGroupEntity upgradeGroup = upgradeItem.getGroupEntity();
@@ -131,37 +155,63 @@ public class AutoSkipFailedSummaryAction extends AbstractServerAction {
"There were no skipped failures", null);
}
- StringBuilder buffer = new StringBuilder("The following steps failed and were automatically skipped:\n");
+ StringBuilder buffer = new StringBuilder("The following steps failed but were automatically skipped:\n");
+ Set<String> skippedCategories = new HashSet<>();
+ Map<String, Object> skippedFailures = new HashMap<>();
- for (HostRoleCommandEntity skippedTask : skippedTasks) {
- try{
- ServiceComponentHostEventWrapper eventWrapper = new ServiceComponentHostEventWrapper(
- skippedTask.getEvent());
+ Set<String> skippedServiceChecks = new HashSet<>();
+ Map<String, Object> hostComponents= new HashMap<>();
- ServiceComponentHostEvent event = eventWrapper.getEvent();
+ // Internal representation for failed host components
+ // To avoid duplicates
+ // Format: <hostname, Set<Role>>
+ Map<String, Set<Role>> publishedHostComponents= new HashMap<>();
- String hostName = skippedTask.getHostName();
- if(null != hostName){
- Map<String, Object> failures = m_structuredFailures.get(hostName);
- if( null == failures ){
- failures = new HashMap<>();
- m_structuredFailures.put(hostName, failures);
+ for (HostRoleCommandEntity skippedTask : skippedTasks) {
+ try {
+ String skippedCategory;
+ if (skippedTask.getRoleCommand().equals(RoleCommand.SERVICE_CHECK)) {
+ skippedCategory = SKIPPED_SERVICE_CHECK;
+
+ String serviceCheckActionName = skippedTask.getRole().toString();
+ String service = actionMetadata.getServiceNameByServiceCheckAction(serviceCheckActionName);
+ skippedServiceChecks.add(service);
+
+ skippedFailures.put(SKIPPED_SERVICE_CHECK, skippedServiceChecks);
+ m_structuredFailures.put(FAILURES, skippedFailures);
+ } else {
+ skippedCategory = SKIPPED_HOST_COMPONENT;
+
+ String hostName = skippedTask.getHostName();
+ if (null != hostName) {
+ List<Object> failures = (List<Object>) hostComponents.get(hostName);
+ if (null == failures) {
+ failures = new ArrayList<>();
+ hostComponents.put(hostName, failures);
+
+ publishedHostComponents.put(hostName, new HashSet<Role>());
+ }
+ Set<Role> publishedHostComponentsOnHost = publishedHostComponents.get(hostName);
+ Role role = skippedTask.getRole();
+ if (! publishedHostComponentsOnHost.contains(role)) {
+ HashMap<String, String> details = new HashMap<>();
+ String service = ambariMetaInfo.getComponentToService(
+ stackId.getStackName(), stackId.getStackVersion(), role.toString());
+
+ details.put("service", service);
+ details.put("component", role.toString());
+ failures.add(details);
+ }
}
+ skippedFailures.put(SKIPPED_HOST_COMPONENT, hostComponents);
+ m_structuredFailures.put(FAILURES, skippedFailures);
+ }
+ skippedCategories.add(skippedCategory);
- failures.put("id", skippedTask.getTaskId());
- failures.put("exit_code", skippedTask.getExitcode());
- failures.put("output_log", skippedTask.getOutputLog());
- failures.put("error_log", skippedTask.getErrorLog());
-
- String stdOut = StringUtils.abbreviateMiddle(new String(skippedTask.getStdOut()),
- MIDDLE_ELLIPSIZE_MARKER, 1000);
-
- String stderr = StringUtils.abbreviateMiddle(new String(skippedTask.getStdError()),
- MIDDLE_ELLIPSIZE_MARKER, 1000);
+ ServiceComponentHostEventWrapper eventWrapper = new ServiceComponentHostEventWrapper(
+ skippedTask.getEvent());
- failures.put("stdout", stdOut);
- failures.put("stderr", stderr);
- }
+ ServiceComponentHostEvent event = eventWrapper.getEvent();
buffer.append(event.getServiceComponentName());
if (null != event.getHostName()) {
@@ -179,6 +229,8 @@ public class AutoSkipFailedSummaryAction extends AbstractServerAction {
}
}
+ m_structuredFailures.put(SKIPPED, skippedCategories);
+
String structuredOutput = m_gson.toJson(m_structuredFailures);
String standardOutput = MessageFormat.format(FAILURE_STD_OUT_TEMPLATE, skippedTasks.size());
String standardError = buffer.toString();
http://git-wip-us.apache.org/repos/asf/ambari/blob/36681a57/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryActionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryActionTest.java
new file mode 100644
index 0000000..5e35b301
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/AutoSkipFailedSummaryActionTest.java
@@ -0,0 +1,455 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.serveraction.upgrades;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import com.google.inject.persist.UnitOfWork;
+import com.google.inject.util.Modules;
+import org.apache.ambari.server.*;
+import org.apache.ambari.server.actionmanager.*;
+import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.agent.ExecutionCommand;
+import org.apache.ambari.server.metadata.ActionMetadata;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.dao.*;
+import org.apache.ambari.server.orm.entities.*;
+import org.apache.ambari.server.serveraction.AbstractServerAction;
+import org.apache.ambari.server.state.*;
+import org.apache.ambari.server.state.svccomphost.ServiceComponentHostOpInProgressEvent;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.*;
+
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.junit.Assert.*;
+
+public class AutoSkipFailedSummaryActionTest {
+
+ private Injector m_injector;
+
+ private static final StackId HDP_STACK = new StackId("HDP-2.2.0");
+
+ @Inject
+ private ExecutionCommandDAO executionCommandDAO;
+
+ @Inject
+ private HostDAO hostDAO;
+
+ // Mocked out values
+ private UpgradeDAO upgradeDAOMock;
+ private HostRoleCommandDAO hostRoleCommandDAOMock;
+ private Clusters clustersMock;
+ private Cluster clusterMock;
+
+
+ @Before
+ public void setup() throws Exception {
+ // Create instances of mocks
+ upgradeDAOMock = createNiceMock(UpgradeDAO.class);
+ hostRoleCommandDAOMock = createNiceMock(HostRoleCommandDAO.class);
+ clustersMock = createNiceMock(Clusters.class);
+ clusterMock = createNiceMock(Cluster.class);
+
+ expect(clustersMock.getCluster(anyString())).andReturn(clusterMock).anyTimes();
+ replay(clustersMock);
+
+ expect(clusterMock.getDesiredStackVersion()).andReturn(HDP_STACK).anyTimes();
+ replay(clusterMock);
+
+ // Initialize injector
+ InMemoryDefaultTestModule module = new InMemoryDefaultTestModule();
+ m_injector = Guice.createInjector(Modules.override(module).with(new MockModule()));
+ m_injector.getInstance(GuiceJpaInitializer.class);
+ m_injector.injectMembers(this);
+ m_injector.getInstance(UnitOfWork.class).begin();
+
+ // Normally initialized in runtime when loading stack
+ m_injector.getInstance(ActionMetadata.class).addServiceCheckAction("ZOOKEEPER");
+ }
+
+ @After
+ public void teardown() throws Exception {
+ m_injector.getInstance(UnitOfWork.class).end();
+ m_injector.getInstance(PersistService.class).stop();
+ }
+
+
+ /**
+ * Tests successful workflow
+ */
+ @Test
+ public void testAutoSkipFailedSummaryAction__green() throws Exception {
+ AutoSkipFailedSummaryAction action = new AutoSkipFailedSummaryAction();
+ m_injector.injectMembers(action);
+
+ ServiceComponentHostEvent event = createNiceMock(ServiceComponentHostEvent.class);
+
+ // Set mock for parent's getHostRoleCommand()
+ HostRoleCommand hostRoleCommand = new HostRoleCommand("host1", Role.AMBARI_SERVER_ACTION,
+ event, RoleCommand.EXECUTE, hostDAO, executionCommandDAO);
+ hostRoleCommand.setRequestId(1l);
+ hostRoleCommand.setStageId(1l);
+
+ ExecutionCommand executionCommand = new ExecutionCommand();
+ executionCommand.setClusterName("cc");
+ executionCommand.setRoleCommand(RoleCommand.EXECUTE);
+ executionCommand.setRole("AMBARI_SERVER_ACTION");
+ executionCommand.setServiceName("");
+ executionCommand.setTaskId(1l);
+ ExecutionCommandWrapper wrapper = new ExecutionCommandWrapper(executionCommand);
+ hostRoleCommand.setExecutionCommandWrapper(wrapper);
+
+ Field f = AbstractServerAction.class.getDeclaredField("hostRoleCommand");
+ f.setAccessible(true);
+ f.set(action, hostRoleCommand);
+
+ final UpgradeItemEntity upgradeItem1 = new UpgradeItemEntity();
+ upgradeItem1.setStageId(5l);
+ final UpgradeItemEntity upgradeItem2 = new UpgradeItemEntity();
+ upgradeItem2.setStageId(6l);
+
+ UpgradeGroupEntity upgradeGroupEntity = new UpgradeGroupEntity();
+ upgradeGroupEntity.setId(11l);
+ // List of upgrade items in group
+ List<UpgradeItemEntity> groupUpgradeItems = new ArrayList<UpgradeItemEntity>(){{
+ add(upgradeItem1);
+ add(upgradeItem2);
+ }};
+ upgradeGroupEntity.setItems(groupUpgradeItems);
+
+ UpgradeItemEntity upgradeItemEntity = new UpgradeItemEntity();
+ upgradeItemEntity.setGroupEntity(upgradeGroupEntity);
+
+ expect(upgradeDAOMock.findUpgradeItemByRequestAndStage(anyLong(), anyLong())).andReturn(upgradeItemEntity).anyTimes();
+ expect(upgradeDAOMock.findUpgradeGroup(anyLong())).andReturn(upgradeGroupEntity).anyTimes();
+ replay(upgradeDAOMock);
+
+ List<HostRoleCommandEntity> skippedTasks = new ArrayList<HostRoleCommandEntity>() {{
+ // It's empty - no skipped tasks
+ }};
+ expect(hostRoleCommandDAOMock.findByStatusBetweenStages(anyLong(),
+ anyObject(HostRoleStatus.class), anyLong(), anyLong())).andReturn(skippedTasks).anyTimes();
+ replay(hostRoleCommandDAOMock);
+
+ ConcurrentMap<String, Object> requestSharedDataContext = new ConcurrentHashMap<String, Object>();
+ CommandReport result = action.execute(requestSharedDataContext);
+
+ assertNotNull(result.getStructuredOut());
+ assertEquals(0, result.getExitCode());
+ assertEquals(HostRoleStatus.COMPLETED.toString(), result.getStatus());
+ assertEquals("There were no skipped failures", result.getStdOut());
+ assertEquals("{}", result.getStructuredOut());
+ assertEquals("", result.getStdErr());
+ }
+
+
+ /**
+ * Tests workflow with few skipped tasks
+ */
+ @Test
+ public void testAutoSkipFailedSummaryAction__red() throws Exception {
+ AutoSkipFailedSummaryAction action = new AutoSkipFailedSummaryAction();
+ m_injector.injectMembers(action);
+
+ ServiceComponentHostEvent event = createNiceMock(ServiceComponentHostEvent.class);
+
+ // Set mock for parent's getHostRoleCommand()
+ final HostRoleCommand hostRoleCommand = new HostRoleCommand("host1", Role.AMBARI_SERVER_ACTION,
+ event, RoleCommand.EXECUTE, hostDAO, executionCommandDAO);
+ hostRoleCommand.setRequestId(1l);
+ hostRoleCommand.setStageId(1l);
+
+ ExecutionCommand executionCommand = new ExecutionCommand();
+ executionCommand.setClusterName("cc");
+ executionCommand.setRoleCommand(RoleCommand.EXECUTE);
+ executionCommand.setRole("AMBARI_SERVER_ACTION");
+ executionCommand.setServiceName("");
+ executionCommand.setTaskId(1l);
+ ExecutionCommandWrapper wrapper = new ExecutionCommandWrapper(executionCommand);
+ hostRoleCommand.setExecutionCommandWrapper(wrapper);
+
+ Field f = AbstractServerAction.class.getDeclaredField("hostRoleCommand");
+ f.setAccessible(true);
+ f.set(action, hostRoleCommand);
+
+ final UpgradeItemEntity upgradeItem1 = new UpgradeItemEntity();
+ upgradeItem1.setStageId(5l);
+ final UpgradeItemEntity upgradeItem2 = new UpgradeItemEntity();
+ upgradeItem2.setStageId(6l);
+
+ UpgradeGroupEntity upgradeGroupEntity = new UpgradeGroupEntity();
+ upgradeGroupEntity.setId(11l);
+ // List of upgrade items in group
+ List<UpgradeItemEntity> groupUpgradeItems = new ArrayList<UpgradeItemEntity>(){{
+ add(upgradeItem1);
+ add(upgradeItem2);
+ }};
+ upgradeGroupEntity.setItems(groupUpgradeItems);
+
+ UpgradeItemEntity upgradeItemEntity = new UpgradeItemEntity();
+ upgradeItemEntity.setGroupEntity(upgradeGroupEntity);
+
+ expect(upgradeDAOMock.findUpgradeItemByRequestAndStage(anyLong(), anyLong())).andReturn(upgradeItemEntity).anyTimes();
+ expect(upgradeDAOMock.findUpgradeGroup(anyLong())).andReturn(upgradeGroupEntity).anyTimes();
+ replay(upgradeDAOMock);
+
+ List<HostRoleCommandEntity> skippedTasks = new ArrayList<HostRoleCommandEntity>() {{
+ add(createSkippedTask("DATANODE", "DATANODE", "host1.vm",
+ "RESTART HDFS/DATANODE", RoleCommand.CUSTOM_COMMAND,
+ "RESTART"
+ ));
+ add(createSkippedTask("DATANODE", "DATANODE", "host2.vm",
+ "RESTART HDFS/DATANODE", RoleCommand.CUSTOM_COMMAND,
+ "RESTART"));
+ add(createSkippedTask("ZOOKEEPER_QUORUM_SERVICE_CHECK", "ZOOKEEPER_CLIENT", "host2.vm",
+ "SERVICE_CHECK ZOOKEEPER", RoleCommand.SERVICE_CHECK, null));
+ }};
+ expect(hostRoleCommandDAOMock.findByStatusBetweenStages(anyLong(),
+ anyObject(HostRoleStatus.class), anyLong(), anyLong())).andReturn(skippedTasks).anyTimes();
+ replay(hostRoleCommandDAOMock);
+
+ ConcurrentMap<String, Object> requestSharedDataContext = new ConcurrentHashMap<String, Object>();
+ CommandReport result = action.execute(requestSharedDataContext);
+
+ assertNotNull(result.getStructuredOut());
+ assertEquals(0, result.getExitCode());
+ assertEquals(HostRoleStatus.HOLDING.toString(), result.getStatus());
+ assertEquals("There were 3 skipped failure(s) that must be addressed " +
+ "before you can proceed. Please resolve each failure before continuing with the upgrade.",
+ result.getStdOut());
+ assertEquals("{\"failures\":" +
+ "{\"service_check\":[\"ZOOKEEPER\"]," +
+ "\"host_component\":{" +
+ "\"host1.vm\":[{\"component\":\"DATANODE\",\"service\":\"HDFS\"}]," +
+ "\"host2.vm\":[{\"component\":\"DATANODE\",\"service\":\"HDFS\"}]}}," +
+ "\"skipped\":[\"service_check\",\"host_component\"]}",
+ result.getStructuredOut());
+ assertEquals("The following steps failed but were automatically skipped:\n" +
+ "DATANODE on host1.vm: RESTART HDFS/DATANODE\n" +
+ "DATANODE on host2.vm: RESTART HDFS/DATANODE\n" +
+ "ZOOKEEPER_CLIENT on host2.vm: SERVICE_CHECK ZOOKEEPER\n", result.getStdErr());
+ }
+
+ /**
+ * Tests workflow with failed service check
+ */
+ @Test
+ public void testAutoSkipFailedSummaryAction__red__service_checks_only() throws Exception {
+ AutoSkipFailedSummaryAction action = new AutoSkipFailedSummaryAction();
+ m_injector.injectMembers(action);
+
+ ServiceComponentHostEvent event = createNiceMock(ServiceComponentHostEvent.class);
+
+ // Set mock for parent's getHostRoleCommand()
+ final HostRoleCommand hostRoleCommand = new HostRoleCommand("host1", Role.AMBARI_SERVER_ACTION,
+ event, RoleCommand.EXECUTE, hostDAO, executionCommandDAO);
+ hostRoleCommand.setRequestId(1l);
+ hostRoleCommand.setStageId(1l);
+
+ ExecutionCommand executionCommand = new ExecutionCommand();
+ executionCommand.setClusterName("cc");
+ executionCommand.setRoleCommand(RoleCommand.EXECUTE);
+ executionCommand.setRole("AMBARI_SERVER_ACTION");
+ executionCommand.setServiceName("");
+ executionCommand.setTaskId(1l);
+ ExecutionCommandWrapper wrapper = new ExecutionCommandWrapper(executionCommand);
+ hostRoleCommand.setExecutionCommandWrapper(wrapper);
+
+ Field f = AbstractServerAction.class.getDeclaredField("hostRoleCommand");
+ f.setAccessible(true);
+ f.set(action, hostRoleCommand);
+
+ final UpgradeItemEntity upgradeItem1 = new UpgradeItemEntity();
+ upgradeItem1.setStageId(5l);
+ final UpgradeItemEntity upgradeItem2 = new UpgradeItemEntity();
+ upgradeItem2.setStageId(6l);
+
+ UpgradeGroupEntity upgradeGroupEntity = new UpgradeGroupEntity();
+ upgradeGroupEntity.setId(11l);
+ // List of upgrade items in group
+ List<UpgradeItemEntity> groupUpgradeItems = new ArrayList<UpgradeItemEntity>(){{
+ add(upgradeItem1);
+ add(upgradeItem2);
+ }};
+ upgradeGroupEntity.setItems(groupUpgradeItems);
+
+ UpgradeItemEntity upgradeItemEntity = new UpgradeItemEntity();
+ upgradeItemEntity.setGroupEntity(upgradeGroupEntity);
+
+ expect(upgradeDAOMock.findUpgradeItemByRequestAndStage(anyLong(), anyLong())).andReturn(upgradeItemEntity).anyTimes();
+ expect(upgradeDAOMock.findUpgradeGroup(anyLong())).andReturn(upgradeGroupEntity).anyTimes();
+ replay(upgradeDAOMock);
+
+ List<HostRoleCommandEntity> skippedTasks = new ArrayList<HostRoleCommandEntity>() {{
+ add(createSkippedTask("ZOOKEEPER_QUORUM_SERVICE_CHECK", "ZOOKEEPER_CLIENT", "host2.vm",
+ "SERVICE_CHECK ZOOKEEPER", RoleCommand.SERVICE_CHECK, null));
+ }};
+ expect(hostRoleCommandDAOMock.findByStatusBetweenStages(anyLong(),
+ anyObject(HostRoleStatus.class), anyLong(), anyLong())).andReturn(skippedTasks).anyTimes();
+ replay(hostRoleCommandDAOMock);
+
+ ConcurrentMap<String, Object> requestSharedDataContext = new ConcurrentHashMap<String, Object>();
+ CommandReport result = action.execute(requestSharedDataContext);
+
+ assertNotNull(result.getStructuredOut());
+ assertEquals(0, result.getExitCode());
+ assertEquals(HostRoleStatus.HOLDING.toString(), result.getStatus());
+ assertEquals("There were 1 skipped failure(s) that must be addressed " +
+ "before you can proceed. Please resolve each failure before continuing with the upgrade.",
+ result.getStdOut());
+ assertEquals("{\"failures\":{\"service_check\":[\"ZOOKEEPER\"]},\"skipped\":[\"service_check\"]}",
+ result.getStructuredOut());
+ assertEquals("The following steps failed but were automatically skipped:\n" +
+ "ZOOKEEPER_CLIENT on host2.vm: SERVICE_CHECK ZOOKEEPER\n", result.getStdErr());
+ }
+
+ /**
+ * Tests workflow with failed host component tasks only
+ */
+ @Test
+ public void testAutoSkipFailedSummaryAction__red__host_components_only() throws Exception {
+ AutoSkipFailedSummaryAction action = new AutoSkipFailedSummaryAction();
+ m_injector.injectMembers(action);
+
+ ServiceComponentHostEvent event = createNiceMock(ServiceComponentHostEvent.class);
+
+ // Set mock for parent's getHostRoleCommand()
+ final HostRoleCommand hostRoleCommand = new HostRoleCommand("host1", Role.AMBARI_SERVER_ACTION,
+ event, RoleCommand.EXECUTE, hostDAO, executionCommandDAO);
+ hostRoleCommand.setRequestId(1l);
+ hostRoleCommand.setStageId(1l);
+
+ ExecutionCommand executionCommand = new ExecutionCommand();
+ executionCommand.setClusterName("cc");
+ executionCommand.setRoleCommand(RoleCommand.EXECUTE);
+ executionCommand.setRole("AMBARI_SERVER_ACTION");
+ executionCommand.setServiceName("");
+ executionCommand.setTaskId(1l);
+ ExecutionCommandWrapper wrapper = new ExecutionCommandWrapper(executionCommand);
+ hostRoleCommand.setExecutionCommandWrapper(wrapper);
+
+ Field f = AbstractServerAction.class.getDeclaredField("hostRoleCommand");
+ f.setAccessible(true);
+ f.set(action, hostRoleCommand);
+
+ final UpgradeItemEntity upgradeItem1 = new UpgradeItemEntity();
+ upgradeItem1.setStageId(5l);
+ final UpgradeItemEntity upgradeItem2 = new UpgradeItemEntity();
+ upgradeItem2.setStageId(6l);
+
+ UpgradeGroupEntity upgradeGroupEntity = new UpgradeGroupEntity();
+ upgradeGroupEntity.setId(11l);
+ // List of upgrade items in group
+ List<UpgradeItemEntity> groupUpgradeItems = new ArrayList<UpgradeItemEntity>(){{
+ add(upgradeItem1);
+ add(upgradeItem2);
+ }};
+ upgradeGroupEntity.setItems(groupUpgradeItems);
+
+ UpgradeItemEntity upgradeItemEntity = new UpgradeItemEntity();
+ upgradeItemEntity.setGroupEntity(upgradeGroupEntity);
+
+ expect(upgradeDAOMock.findUpgradeItemByRequestAndStage(anyLong(), anyLong())).andReturn(upgradeItemEntity).anyTimes();
+ expect(upgradeDAOMock.findUpgradeGroup(anyLong())).andReturn(upgradeGroupEntity).anyTimes();
+ replay(upgradeDAOMock);
+
+ List<HostRoleCommandEntity> skippedTasks = new ArrayList<HostRoleCommandEntity>() {{
+ add(createSkippedTask("DATANODE", "DATANODE", "host1.vm",
+ "RESTART HDFS/DATANODE", RoleCommand.CUSTOM_COMMAND,
+ "RESTART"
+ ));
+ add(createSkippedTask("DATANODE", "DATANODE", "host2.vm",
+ "RESTART HDFS/DATANODE", RoleCommand.CUSTOM_COMMAND,
+ "RESTART"));
+ }};
+ expect(hostRoleCommandDAOMock.findByStatusBetweenStages(anyLong(),
+ anyObject(HostRoleStatus.class), anyLong(), anyLong())).andReturn(skippedTasks).anyTimes();
+ replay(hostRoleCommandDAOMock);
+
+ ConcurrentMap<String, Object> requestSharedDataContext = new ConcurrentHashMap<String, Object>();
+ CommandReport result = action.execute(requestSharedDataContext);
+
+ assertNotNull(result.getStructuredOut());
+ assertEquals(0, result.getExitCode());
+ assertEquals(HostRoleStatus.HOLDING.toString(), result.getStatus());
+ assertEquals("There were 2 skipped failure(s) that must be addressed " +
+ "before you can proceed. Please resolve each failure before continuing with the upgrade.",
+ result.getStdOut());
+ assertEquals("{\"failures\":" +
+ "{\"host_component\":" +
+ "{\"host1.vm\":[{\"component\":\"DATANODE\",\"service\":\"HDFS\"}]," +
+ "\"host2.vm\":[{\"component\":\"DATANODE\",\"service\":\"HDFS\"}]}}," +
+ "\"skipped\":[\"host_component\"]}",
+ result.getStructuredOut());
+ assertEquals("The following steps failed but were automatically skipped:\n" +
+ "DATANODE on host1.vm: RESTART HDFS/DATANODE\n" +
+ "DATANODE on host2.vm: RESTART HDFS/DATANODE\n", result.getStdErr());
+ }
+
+
+
+ private HostRoleCommandEntity createSkippedTask(String role, String componentName,
+ String hostname, String commandDetail,
+ RoleCommand roleCommand, String customCommandName) {
+ HostRoleCommandEntity result = new HostRoleCommandEntity();
+
+ ServiceComponentHostEvent event = new ServiceComponentHostOpInProgressEvent(componentName, hostname, 77l);
+ ServiceComponentHostEventWrapper eventWrapper = new ServiceComponentHostEventWrapper(event);
+ result.setEvent(eventWrapper.getEventJson());
+
+ HostEntity hostEntity = new HostEntity();
+ hostEntity.setHostName(hostname);
+ result.setHostEntity(hostEntity);
+
+ result.setTaskId(7l);
+ result.setExitcode(1);
+ result.setOutputLog("/output.log");
+ result.setErrorLog("/error.log");
+ result.setStdOut("Some stdout".getBytes());
+ result.setStdError("Some stderr".getBytes());
+ result.setCommandDetail(commandDetail);
+ result.setRole(Role.valueOf(role));
+ result.setRoleCommand(roleCommand);
+ result.setCustomCommandName(customCommandName);
+ result.setStatus(HostRoleStatus.SKIPPED_FAILED);
+
+ return result;
+ }
+
+
+ public class MockModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(UpgradeDAO.class).toInstance(upgradeDAOMock);
+ bind(HostRoleCommandDAO.class).toInstance(hostRoleCommandDAOMock);
+ bind(Clusters.class).toInstance(clustersMock);
+ }
+ }
+
+}