/**
* 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.agent;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.DATANODE;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.DummyCluster;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.DummyCurrentPingPort;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.DummyHostStatus;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.DummyHostname1;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.DummyOSRelease;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.DummyOs;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.DummyOsType;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.DummyStackId;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.HDFS;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.HDFS_CLIENT;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.NAMENODE;
import static org.apache.ambari.server.agent.DummyHeartbeatConstants.SECONDARY_NAMENODE;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBException;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.H2DatabaseCleaner;
import org.apache.ambari.server.Role;
import org.apache.ambari.server.RoleCommand;
import org.apache.ambari.server.actionmanager.ActionDBAccessor;
import org.apache.ambari.server.actionmanager.ActionManager;
import org.apache.ambari.server.actionmanager.ActionManagerTestHelper;
import org.apache.ambari.server.actionmanager.HostRoleCommand;
import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.actionmanager.Request;
import org.apache.ambari.server.actionmanager.Stage;
import org.apache.ambari.server.actionmanager.StageFactory;
import org.apache.ambari.server.agent.HostStatus.Status;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.audit.AuditLogger;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
import org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileWriter;
import org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileWriterFactory;
import org.apache.ambari.server.serveraction.kerberos.KerberosServerAction;
import org.apache.ambari.server.state.Alert;
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.HostHealthStatus;
import org.apache.ambari.server.state.HostState;
import org.apache.ambari.server.state.MaintenanceState;
import org.apache.ambari.server.state.SecurityState;
import org.apache.ambari.server.state.Service;
import org.apache.ambari.server.state.ServiceComponentHost;
import org.apache.ambari.server.state.StackId;
import org.apache.ambari.server.state.State;
import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
import org.apache.ambari.server.state.svccomphost.ServiceComponentHostInstallEvent;
import org.apache.ambari.server.utils.StageUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.codehaus.jackson.JsonGenerationException;
import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import junit.framework.Assert;
public class TestHeartbeatHandler {
private static final Logger log = LoggerFactory.getLogger(TestHeartbeatHandler.class);
private Injector injector;
private Clusters clusters;
long requestId = 23;
long stageId = 31;
@Inject
AmbariMetaInfo metaInfo;
@Inject
Configuration config;
@Inject
ActionDBAccessor actionDBAccessor;
@Inject
StageFactory stageFactory;
@Inject
HostRoleCommandFactory hostRoleCommandFactory;
@Inject
HeartbeatTestHelper heartbeatTestHelper;
@Inject
ActionManagerTestHelper actionManagerTestHelper;
@Inject
AuditLogger auditLogger;
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private InMemoryDefaultTestModule module;
@Before
public void setup() throws Exception {
module = HeartbeatTestHelper.getTestModule();
injector = Guice.createInjector(module);
injector.getInstance(GuiceJpaInitializer.class);
clusters = injector.getInstance(Clusters.class);
injector.injectMembers(this);
EasyMock.replay(auditLogger);
}
@After
public void teardown() throws Exception {
H2DatabaseCleaner.clearDatabaseAndStopPersistenceService(injector);
EasyMock.reset(auditLogger);
}
@Test
@SuppressWarnings("unchecked")
public void testHeartbeat() throws Exception {
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(new ArrayList<HostRoleCommand>());
replay(am);
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE);
hdfs.addServiceComponent(NAMENODE);
hdfs.addServiceComponent(SECONDARY_NAMENODE);
Collection<Host> hosts = cluster.getHosts();
assertEquals(hosts.size(), 1);
Clusters fsm = clusters;
Host hostObject = hosts.iterator().next();
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
hostObject.setOsType(DummyOsType);
String hostname = hostObject.getHostName();
ActionQueue aq = new ActionQueue();
HeartBeatHandler handler = new HeartBeatHandler(fsm, aq, am, injector);
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(hostname);
hi.setOS(DummyOs);
hi.setOSRelease(DummyOSRelease);
reg.setHostname(hostname);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
handler.handleRegistration(reg);
hostObject.setState(HostState.UNHEALTHY);
ExecutionCommand execCmd = new ExecutionCommand();
execCmd.setRequestAndStage(2, 34);
execCmd.setHostname(hostname);
execCmd.setClusterName(cluster.getClusterName());
execCmd.setServiceName(HDFS);
aq.enqueue(hostname, execCmd);
HeartBeat hb = new HeartBeat();
hb.setResponseId(0);
HostStatus hs = new HostStatus(Status.HEALTHY, DummyHostStatus);
List<Alert> al = new ArrayList<>();
al.add(new Alert());
hb.setNodeStatus(hs);
hb.setHostname(hostname);
handler.handleHeartBeat(hb);
assertEquals(HostState.HEALTHY, hostObject.getState());
assertEquals(0, aq.dequeueAll(hostname).size());
}
@Test
@SuppressWarnings("unchecked")
public void testStatusHeartbeatWithAnnotation() throws Exception {
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE);
hdfs.addServiceComponent(NAMENODE);
hdfs.addServiceComponent(SECONDARY_NAMENODE);
ActionQueue aq = new ActionQueue();
HeartBeat hb = new HeartBeat();
hb.setTimestamp(System.currentTimeMillis());
hb.setResponseId(0);
hb.setHostname(DummyHostname1);
hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb.setReports(new ArrayList<CommandReport>());
ArrayList<ComponentStatus> componentStatuses = new ArrayList<>();
hb.setComponentStatus(componentStatuses);
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1,
Role.DATANODE, null, null);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
}}).anyTimes();
replay(am);
HeartBeatHandler handler = heartbeatTestHelper.getHeartBeatHandler(am, aq);
HeartBeatResponse resp = handler.handleHeartBeat(hb);
Assert.assertFalse(resp.hasMappedComponents());
hdfs.getServiceComponent(DATANODE).addServiceComponentHost(DummyHostname1);
ServiceComponentHost serviceComponentHost1 = clusters.getCluster(DummyCluster).getService(HDFS).
getServiceComponent(DATANODE).getServiceComponentHost(DummyHostname1);
serviceComponentHost1.setState(State.INIT);
hb = new HeartBeat();
hb.setTimestamp(System.currentTimeMillis());
hb.setResponseId(1);
hb.setHostname(DummyHostname1);
hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb.setReports(new ArrayList<CommandReport>());
hb.setComponentStatus(componentStatuses);
resp = handler.handleHeartBeat(hb);
Assert.assertTrue(resp.hasMappedComponents());
}
@Test
@SuppressWarnings("unchecked")
public void testLiveStatusUpdateAfterStopFailed() throws Exception {
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE);
hdfs.getServiceComponent(DATANODE).
addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(NAMENODE);
hdfs.getServiceComponent(NAMENODE).
addServiceComponentHost(DummyHostname1);
ActionQueue aq = new ActionQueue();
ServiceComponentHost serviceComponentHost1 = clusters.
getCluster(DummyCluster).getService(HDFS).
getServiceComponent(DATANODE).
getServiceComponentHost(DummyHostname1);
ServiceComponentHost serviceComponentHost2 = clusters.
getCluster(DummyCluster).getService(HDFS).
getServiceComponent(NAMENODE).
getServiceComponentHost(DummyHostname1);
serviceComponentHost1.setState(State.STARTED);
serviceComponentHost2.setState(State.STARTED);
HeartBeat hb = new HeartBeat();
hb.setTimestamp(System.currentTimeMillis());
hb.setResponseId(0);
hb.setHostname(DummyHostname1);
hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb.setReports(new ArrayList<CommandReport>());
ArrayList<ComponentStatus> componentStatuses = new ArrayList<>();
ComponentStatus componentStatus1 = new ComponentStatus();
componentStatus1.setClusterName(DummyCluster);
componentStatus1.setServiceName(HDFS);
componentStatus1.setMessage(DummyHostStatus);
componentStatus1.setStatus(State.STARTED.name());
componentStatus1.setComponentName(DATANODE);
componentStatuses.add(componentStatus1);
ComponentStatus componentStatus2 = new ComponentStatus();
componentStatus2.setClusterName(DummyCluster);
componentStatus2.setServiceName(HDFS);
componentStatus2.setMessage(DummyHostStatus);
componentStatus2.setStatus(State.INSTALLED.name());
componentStatus2.setComponentName(NAMENODE);
componentStatuses.add(componentStatus2);
hb.setComponentStatus(componentStatuses);
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1,
Role.DATANODE, null, null);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
add(command);
}});
replay(am);
HeartBeatHandler handler = heartbeatTestHelper.getHeartBeatHandler(am, aq);
HeartbeatProcessor heartbeatProcessor = handler.getHeartbeatProcessor();
heartbeatProcessor.processHeartbeat(hb);
State componentState1 = serviceComponentHost1.getState();
State componentState2 = serviceComponentHost2.getState();
assertEquals(State.STARTED, componentState1);
assertEquals(State.INSTALLED, componentState2);
}
@Test
public void testRegistration() throws Exception,
InvalidStateTransitionException {
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
HeartBeatHandler handler = new HeartBeatHandler(fsm, new ActionQueue(), am,
injector);
clusters.addHost(DummyHostname1);
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOsType);
reg.setHostname(DummyHostname1);
reg.setCurrentPingPort(DummyCurrentPingPort);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
reg.setPrefix(Configuration.PREFIX_DIR);
handler.handleRegistration(reg);
assertEquals(hostObject.getState(), HostState.HEALTHY);
assertEquals(DummyOsType, hostObject.getOsType());
assertEquals(DummyCurrentPingPort, hostObject.getCurrentPingPort());
assertTrue(hostObject.getLastRegistrationTime() != 0);
assertEquals(hostObject.getLastHeartbeatTime(),
hostObject.getLastRegistrationTime());
}
@Test
public void testRegistrationRecoveryConfig() throws Exception {
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE).setRecoveryEnabled(true);
hdfs.getServiceComponent(DATANODE);
hdfs.getServiceComponent(DATANODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(NAMENODE).setRecoveryEnabled(true);
hdfs.getServiceComponent(NAMENODE);
hdfs.getServiceComponent(NAMENODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(HDFS_CLIENT);
hdfs.getServiceComponent(HDFS_CLIENT).addServiceComponentHost(DummyHostname1);
// Create helper after creating service to avoid race condition caused by asynchronous recovery configs
// timestamp invalidation (RecoveryConfigHelper.handleServiceComponentInstalledEvent())
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
HeartBeatHandler handler = new HeartBeatHandler(fsm, new ActionQueue(), am,
injector);
handler.start();
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOsType);
reg.setHostname(DummyHostname1);
reg.setCurrentPingPort(DummyCurrentPingPort);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
reg.setPrefix(Configuration.PREFIX_DIR);
RegistrationResponse rr = handler.handleRegistration(reg);
RecoveryConfig rc = rr.getRecoveryConfig();
assertEquals(rc.getMaxCount(), "4");
assertEquals(rc.getType(), "AUTO_START");
assertEquals(rc.getMaxLifetimeCount(), "10");
assertEquals(rc.getRetryGap(), "2");
assertEquals(rc.getWindowInMinutes(), "23");
assertEquals(rc.getEnabledComponents(), "DATANODE,NAMENODE");
// Send a heart beat with the recovery timestamp set to the
// recovery timestamp from registration. The heart beat
// response should not contain a recovery config since
// nothing changed between the registration and heart beat.
HeartBeat hb = new HeartBeat();
hb.setTimestamp(System.currentTimeMillis());
hb.setResponseId(0);
hb.setHostname(DummyHostname1);
hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb.setRecoveryTimestamp(rc.getRecoveryTimestamp());
HeartBeatResponse hbr = handler.handleHeartBeat(hb);
assertNull(hbr.getRecoveryConfig());
handler.stop();
}
//
// Same as testRegistrationRecoveryConfig but will test
// maintenance mode set to ON for a service component host
//
@Test
public void testRegistrationRecoveryConfigMaintenanceMode()
throws Exception, InvalidStateTransitionException {
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
HeartBeatHandler handler = new HeartBeatHandler(fsm, new ActionQueue(), am,
injector);
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Service hdfs = cluster.addService(HDFS);
/**
* Add three service components enabled for auto start.
*/
hdfs.addServiceComponent(DATANODE).setRecoveryEnabled(true);
hdfs.getServiceComponent(DATANODE);
hdfs.getServiceComponent(DATANODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(NAMENODE).setRecoveryEnabled(true);
hdfs.getServiceComponent(NAMENODE);
hdfs.getServiceComponent(NAMENODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(HDFS_CLIENT).setRecoveryEnabled(true);
hdfs.getServiceComponent(HDFS_CLIENT);
hdfs.getServiceComponent(HDFS_CLIENT).addServiceComponentHost(DummyHostname1);
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
// set maintenance mode on HDFS_CLIENT on host1 to true
ServiceComponentHost schHdfsClient = hdfs.getServiceComponent(HDFS_CLIENT).getServiceComponentHost(DummyHostname1);
schHdfsClient.setMaintenanceState(MaintenanceState.ON);
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOsType);
reg.setHostname(DummyHostname1);
reg.setCurrentPingPort(DummyCurrentPingPort);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
reg.setPrefix(Configuration.PREFIX_DIR);
RegistrationResponse rr = handler.handleRegistration(reg);
RecoveryConfig rc = rr.getRecoveryConfig();
assertEquals(rc.getMaxCount(), "4");
assertEquals(rc.getType(), "AUTO_START");
assertEquals(rc.getMaxLifetimeCount(), "10");
assertEquals(rc.getRetryGap(), "2");
assertEquals(rc.getWindowInMinutes(), "23");
assertEquals(rc.getEnabledComponents(), "DATANODE,NAMENODE"); // HDFS_CLIENT is in maintenance mode
}
@Test
public void testRegistrationAgentConfig() throws Exception,
InvalidStateTransitionException {
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
HeartBeatHandler handler = new HeartBeatHandler(fsm, new ActionQueue(), am,
injector);
clusters.addHost(DummyHostname1);
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOsType);
reg.setHostname(DummyHostname1);
reg.setCurrentPingPort(DummyCurrentPingPort);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
reg.setPrefix(Configuration.PREFIX_DIR);
RegistrationResponse rr = handler.handleRegistration(reg);
Map<String, String> config = rr.getAgentConfig();
assertFalse(config.isEmpty());
assertTrue(config.containsKey(Configuration.CHECK_REMOTE_MOUNTS.getKey()));
assertTrue("false".equals(config.get(Configuration.CHECK_REMOTE_MOUNTS.getKey())));
assertTrue(config.containsKey(Configuration.CHECK_MOUNTS_TIMEOUT.getKey()));
assertTrue("0".equals(config.get(Configuration.CHECK_MOUNTS_TIMEOUT.getKey())));
assertTrue("true".equals(config.get(Configuration.ENABLE_AUTO_AGENT_CACHE_UPDATE.getKey())));
}
@Test
public void testRegistrationWithBadVersion() throws Exception,
InvalidStateTransitionException {
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
HeartBeatHandler handler = new HeartBeatHandler(fsm, new ActionQueue(), am,
injector);
clusters.addHost(DummyHostname1);
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOsType);
reg.setHostname(DummyHostname1);
reg.setHardwareProfile(hi);
reg.setAgentVersion(""); // Invalid agent version
reg.setPrefix(Configuration.PREFIX_DIR);
try {
handler.handleRegistration(reg);
fail ("Expected failure for non compatible agent version");
} catch (AmbariException e) {
log.debug("Error:" + e.getMessage());
Assert.assertTrue(e.getMessage().contains(
"Cannot register host with non compatible agent version"));
}
reg.setAgentVersion(null); // Invalid agent version
try {
handler.handleRegistration(reg);
fail ("Expected failure for non compatible agent version");
} catch (AmbariException e) {
log.debug("Error:" + e.getMessage());
Assert.assertTrue(e.getMessage().contains(
"Cannot register host with non compatible agent version"));
}
}
@Test
public void testRegistrationPublicHostname() throws Exception, InvalidStateTransitionException {
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
HeartBeatHandler handler = new HeartBeatHandler(fsm, new ActionQueue(), am,
injector);
clusters.addHost(DummyHostname1);
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOsType);
reg.setHostname(DummyHostname1);
reg.setHardwareProfile(hi);
reg.setPublicHostname(DummyHostname1 + "-public");
reg.setAgentVersion(metaInfo.getServerVersion());
handler.handleRegistration(reg);
assertEquals(hostObject.getState(), HostState.HEALTHY);
assertEquals(DummyOsType, hostObject.getOsType());
assertTrue(hostObject.getLastRegistrationTime() != 0);
assertEquals(hostObject.getLastHeartbeatTime(),
hostObject.getLastRegistrationTime());
Host verifyHost = clusters.getHost(DummyHostname1);
assertEquals(verifyHost.getPublicHostName(), reg.getPublicHostname());
}
@Test
public void testInvalidOSRegistration() throws Exception,
InvalidStateTransitionException {
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
HeartBeatHandler handler = new HeartBeatHandler(fsm, new ActionQueue(), am,
injector);
clusters.addHost(DummyHostname1);
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS("MegaOperatingSystem");
reg.setHostname(DummyHostname1);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
try {
handler.handleRegistration(reg);
fail ("Expected failure for non matching os type");
} catch (AmbariException e) {
// Expected
}
}
@Test
public void testIncompatibleAgentRegistration() throws Exception,
InvalidStateTransitionException {
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
HeartBeatHandler handler = new HeartBeatHandler(fsm, new ActionQueue(), am,
injector);
clusters.addHost(DummyHostname1);
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOsType);
reg.setHostname(DummyHostname1);
reg.setHardwareProfile(hi);
reg.setAgentVersion("0.0.0"); // Invalid agent version
try {
handler.handleRegistration(reg);
fail ("Expected failure for non compatible agent version");
} catch (AmbariException e) {
// Expected
}
}
@Test
public void testRegisterNewNode()
throws Exception, InvalidStateTransitionException {
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
fsm.addHost(DummyHostname1);
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
HeartBeatHandler handler = new HeartBeatHandler(fsm, new ActionQueue(), am,
injector);
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS("redhat5");
reg.setHostname(DummyHostname1);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
reg.setPrefix(Configuration.PREFIX_DIR);
RegistrationResponse response = handler.handleRegistration(reg);
assertEquals(hostObject.getState(), HostState.HEALTHY);
assertEquals("redhat5", hostObject.getOsType());
assertEquals(RegistrationStatus.OK, response.getResponseStatus());
assertEquals(0, response.getResponseId());
assertEquals(reg.getPrefix(), hostObject.getPrefix());
assertTrue(response.getStatusCommands().isEmpty());
}
@Test
public void testRequestId() throws IOException,
InvalidStateTransitionException, JsonGenerationException, JAXBException {
HeartBeatHandler heartBeatHandler = injector.getInstance(
HeartBeatHandler.class);
Register register = new Register();
register.setHostname("newHost");
register.setTimestamp(new Date().getTime());
register.setResponseId(123);
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS("redhat5");
register.setHardwareProfile(hi);
register.setAgentVersion(metaInfo.getServerVersion());
RegistrationResponse registrationResponse = heartBeatHandler.handleRegistration(register);
assertEquals("ResponseId should start from zero", 0L, registrationResponse.getResponseId());
HeartBeat heartBeat = constructHeartBeat("newHost", registrationResponse.getResponseId(), Status.HEALTHY);
HeartBeatResponse hbResponse = heartBeatHandler.handleHeartBeat(heartBeat);
assertEquals("responseId was not incremented", 1L, hbResponse.getResponseId());
assertTrue("Not cached response returned", hbResponse == heartBeatHandler.handleHeartBeat(heartBeat));
heartBeat.setResponseId(1L);
hbResponse = heartBeatHandler.handleHeartBeat(heartBeat);
assertEquals("responseId was not incremented", 2L, hbResponse.getResponseId());
assertFalse("Agent is flagged for restart", hbResponse.isRestartAgent());
log.debug(StageUtils.jaxbToString(hbResponse));
heartBeat.setResponseId(20L);
hbResponse = heartBeatHandler.handleHeartBeat(heartBeat);
// assertEquals("responseId was not incremented", 2L, hbResponse.getResponseId());
assertTrue("Agent is not flagged for restart", hbResponse.isRestartAgent());
log.debug(StageUtils.jaxbToString(hbResponse));
}
private HeartBeat constructHeartBeat(String hostName, long responseId, Status status) {
HeartBeat heartBeat = new HeartBeat();
heartBeat.setHostname(hostName);
heartBeat.setTimestamp(new Date().getTime());
heartBeat.setResponseId(responseId);
HostStatus hs = new HostStatus();
hs.setCause("");
hs.setStatus(status);
heartBeat.setNodeStatus(hs);
heartBeat.setReports(Collections.<CommandReport>emptyList());
return heartBeat;
}
@Test
public void testStateCommandsAtRegistration() throws Exception, InvalidStateTransitionException {
List<StatusCommand> dummyCmds = new ArrayList<>();
StatusCommand statusCmd1 = new StatusCommand();
statusCmd1.setClusterName(DummyCluster);
statusCmd1.setServiceName(HDFS);
dummyCmds.add(statusCmd1);
HeartbeatMonitor hm = mock(HeartbeatMonitor.class);
when(hm.generateStatusCommands(anyString())).thenReturn(dummyCmds);
ActionManager am = actionManagerTestHelper.getMockActionManager();
replay(am);
Clusters fsm = clusters;
ActionQueue actionQueue = new ActionQueue();
HeartBeatHandler handler = new HeartBeatHandler(fsm, actionQueue, am,
injector);
handler.setHeartbeatMonitor(hm);
clusters.addHost(DummyHostname1);
Host hostObject = clusters.getHost(DummyHostname1);
hostObject.setIPv4("ipv4");
hostObject.setIPv6("ipv6");
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOsType);
reg.setHostname(DummyHostname1);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
RegistrationResponse registrationResponse = handler.handleRegistration(reg);
registrationResponse.getStatusCommands();
assertTrue(registrationResponse.getStatusCommands().size() == 1);
assertTrue(registrationResponse.getStatusCommands().get(0).equals(statusCmd1));
}
@Test
@SuppressWarnings("unchecked")
public void testTaskInProgressHandling() throws Exception, InvalidStateTransitionException {
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE);
hdfs.getServiceComponent(DATANODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(NAMENODE);
hdfs.getServiceComponent(NAMENODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(SECONDARY_NAMENODE);
hdfs.getServiceComponent(SECONDARY_NAMENODE).addServiceComponentHost(DummyHostname1);
ActionQueue aq = new ActionQueue();
ServiceComponentHost serviceComponentHost1 = clusters.getCluster(DummyCluster).getService(HDFS).
getServiceComponent(DATANODE).getServiceComponentHost(DummyHostname1);
serviceComponentHost1.setState(State.INSTALLING);
HeartBeat hb = new HeartBeat();
hb.setTimestamp(System.currentTimeMillis());
hb.setResponseId(0);
hb.setHostname(DummyHostname1);
hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
List<CommandReport> reports = new ArrayList<>();
CommandReport cr = new CommandReport();
cr.setActionId(StageUtils.getActionId(requestId, stageId));
cr.setTaskId(1);
cr.setClusterName(DummyCluster);
cr.setServiceName(HDFS);
cr.setRole(DATANODE);
cr.setRoleCommand("INSTALL");
cr.setStatus("IN_PROGRESS");
cr.setStdErr("none");
cr.setStdOut("dummy output");
cr.setExitCode(777);
reports.add(cr);
hb.setReports(reports);
hb.setComponentStatus(new ArrayList<ComponentStatus>());
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1,
Role.DATANODE, null, RoleCommand.INSTALL);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
}});
replay(am);
HeartBeatHandler handler = heartbeatTestHelper.getHeartBeatHandler(am, aq);
handler.handleHeartBeat(hb);
handler.getHeartbeatProcessor().processHeartbeat(hb);
State componentState1 = serviceComponentHost1.getState();
assertEquals("Host state should still be installing", State.INSTALLING, componentState1);
}
@Test
@SuppressWarnings("unchecked")
public void testOPFailedEventForAbortedTask() throws Exception, InvalidStateTransitionException {
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE);
hdfs.getServiceComponent(DATANODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(NAMENODE);
hdfs.getServiceComponent(NAMENODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(SECONDARY_NAMENODE);
hdfs.getServiceComponent(SECONDARY_NAMENODE).addServiceComponentHost(DummyHostname1);
ActionQueue aq = new ActionQueue();
ServiceComponentHost serviceComponentHost1 = clusters.getCluster(DummyCluster).getService(HDFS).
getServiceComponent(DATANODE).getServiceComponentHost(DummyHostname1);
serviceComponentHost1.setState(State.INSTALLING);
Stage s = stageFactory.createNew(1, "/a/b", "cluster1", 1L, "action manager test",
"commandParamsStage", "hostParamsStage");
s.setStageId(1);
s.addHostRoleExecutionCommand(DummyHostname1, Role.DATANODE, RoleCommand.INSTALL,
new ServiceComponentHostInstallEvent(Role.DATANODE.toString(),
DummyHostname1, System.currentTimeMillis(), "HDP-1.3.0"),
DummyCluster, "HDFS", false, false);
List<Stage> stages = new ArrayList<>();
stages.add(s);
Request request = new Request(stages, "clusterHostInfo", clusters);
actionDBAccessor.persistActions(request);
actionDBAccessor.abortHostRole(DummyHostname1, 1, 1, Role.DATANODE.name());
HeartBeat hb = new HeartBeat();
hb.setTimestamp(System.currentTimeMillis());
hb.setResponseId(0);
hb.setHostname(DummyHostname1);
hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
List<CommandReport> reports = new ArrayList<>();
CommandReport cr = new CommandReport();
cr.setActionId(StageUtils.getActionId(1, 1));
cr.setTaskId(1);
cr.setClusterName(DummyCluster);
cr.setServiceName(HDFS);
cr.setRole(DATANODE);
cr.setRoleCommand("INSTALL");
cr.setStatus("FAILED");
cr.setStdErr("none");
cr.setStdOut("dummy output");
cr.setExitCode(777);
reports.add(cr);
hb.setReports(reports);
hb.setComponentStatus(new ArrayList<ComponentStatus>());
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1,
Role.DATANODE, null, null);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
}});
replay(am);
HeartBeatHandler handler = heartbeatTestHelper.getHeartBeatHandler(am, aq);
handler.handleHeartBeat(hb);
handler.getHeartbeatProcessor().processHeartbeat(hb);
State componentState1 = serviceComponentHost1.getState();
assertEquals("Host state should still be installing", State.INSTALLING,
componentState1);
}
@Test
@SuppressWarnings("unchecked")
public void testStatusHeartbeatWithVersion() throws Exception {
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE);
hdfs.getServiceComponent(DATANODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(NAMENODE);
hdfs.getServiceComponent(NAMENODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(HDFS_CLIENT);
hdfs.getServiceComponent(HDFS_CLIENT).addServiceComponentHost(DummyHostname1);
ServiceComponentHost serviceComponentHost1 = clusters.getCluster(DummyCluster).getService(HDFS).
getServiceComponent(DATANODE).getServiceComponentHost(DummyHostname1);
ServiceComponentHost serviceComponentHost2 = clusters.getCluster(DummyCluster).getService(HDFS).
getServiceComponent(NAMENODE).getServiceComponentHost(DummyHostname1);
ServiceComponentHost serviceComponentHost3 = clusters.getCluster(DummyCluster).getService(HDFS).
getServiceComponent(HDFS_CLIENT).getServiceComponentHost(DummyHostname1);
StackId stack130 = new StackId("HDP-1.3.0");
StackId stack120 = new StackId("HDP-1.2.0");
serviceComponentHost1.setState(State.INSTALLED);
serviceComponentHost2.setState(State.STARTED);
serviceComponentHost3.setState(State.STARTED);
serviceComponentHost1.setStackVersion(stack130);
serviceComponentHost2.setStackVersion(stack120);
serviceComponentHost3.setStackVersion(stack120);
HeartBeat hb = new HeartBeat();
hb.setTimestamp(System.currentTimeMillis());
hb.setResponseId(0);
hb.setHostname(DummyHostname1);
hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb.setReports(new ArrayList<CommandReport>());
hb.setAgentEnv(new AgentEnv());
hb.setMounts(new ArrayList<DiskInfo>());
ArrayList<ComponentStatus> componentStatuses = new ArrayList<>();
ComponentStatus componentStatus1 = createComponentStatus(DummyCluster, HDFS, DummyHostStatus, State.STARTED,
SecurityState.UNSECURED, DATANODE, "{\"stackName\":\"HDP\",\"stackVersion\":\"1.3.0\"}");
ComponentStatus componentStatus2 =
createComponentStatus(DummyCluster, HDFS, DummyHostStatus, State.STARTED, SecurityState.UNSECURED, NAMENODE, "");
ComponentStatus componentStatus3 = createComponentStatus(DummyCluster, HDFS, DummyHostStatus, State.INSTALLED,
SecurityState.UNSECURED, HDFS_CLIENT, "{\"stackName\":\"HDP\",\"stackVersion\":\"1.3.0\"}");
componentStatuses.add(componentStatus1);
componentStatuses.add(componentStatus2);
componentStatuses.add(componentStatus3);
hb.setComponentStatus(componentStatuses);
ActionQueue aq = new ActionQueue();
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(new ArrayList<HostRoleCommand>());
replay(am);
HeartBeatHandler handler = heartbeatTestHelper.getHeartBeatHandler(am, aq);
HeartbeatProcessor heartbeatProcessor = handler.getHeartbeatProcessor();
handler.handleHeartBeat(hb);
heartbeatProcessor.processHeartbeat(hb);
assertEquals("Matching value " + serviceComponentHost1.getStackVersion(),
stack130, serviceComponentHost1.getStackVersion());
assertEquals("Matching value " + serviceComponentHost2.getStackVersion(),
stack120, serviceComponentHost2.getStackVersion());
assertEquals("Matching value " + serviceComponentHost3.getStackVersion(),
stack130, serviceComponentHost3.getStackVersion());
assertTrue(hb.getAgentEnv().getHostHealth().getServerTimeStampAtReporting() >= hb.getTimestamp());
}
@Test
@SuppressWarnings("unchecked")
public void testRecoveryStatusReports() throws Exception {
Clusters fsm = clusters;
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Host hostObject = clusters.getHost(DummyHostname1);
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE);
hdfs.getServiceComponent(DATANODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(NAMENODE);
hdfs.getServiceComponent(NAMENODE).addServiceComponentHost(DummyHostname1);
hdfs.getServiceComponent(NAMENODE).getServiceComponentHost(DummyHostname1).setState(State.STARTED);
hdfs.getServiceComponent(DATANODE).getServiceComponentHost(DummyHostname1).setState(State.STARTED);
ActionQueue aq = new ActionQueue();
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1, Role.DATANODE, null, null);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
add(command);
}}).anyTimes();
replay(am);
HeartBeatHandler handler = new HeartBeatHandler(fsm, aq, am, injector);
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOs);
hi.setOSRelease(DummyOSRelease);
reg.setHostname(DummyHostname1);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
handler.handleRegistration(reg);
hostObject.setState(HostState.UNHEALTHY);
aq.enqueue(DummyHostname1, new StatusCommand());
//All components are up
HeartBeat hb1 = new HeartBeat();
hb1.setResponseId(0);
hb1.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb1.setHostname(DummyHostname1);
RecoveryReport rr = new RecoveryReport();
rr.setSummary("RECOVERABLE");
List<ComponentRecoveryReport> compRecReports = new ArrayList<>();
ComponentRecoveryReport compRecReport = new ComponentRecoveryReport();
compRecReport.setLimitReached(Boolean.FALSE);
compRecReport.setName("DATANODE");
compRecReport.setNumAttempts(2);
compRecReports.add(compRecReport);
rr.setComponentReports(compRecReports);
hb1.setRecoveryReport(rr);
handler.handleHeartBeat(hb1);
assertEquals("RECOVERABLE", hostObject.getRecoveryReport().getSummary());
assertEquals(1, hostObject.getRecoveryReport().getComponentReports().size());
assertEquals(2, hostObject.getRecoveryReport().getComponentReports().get(0).getNumAttempts());
HeartBeat hb2 = new HeartBeat();
hb2.setResponseId(1);
hb2.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb2.setHostname(DummyHostname1);
rr = new RecoveryReport();
rr.setSummary("UNRECOVERABLE");
compRecReports = new ArrayList<>();
compRecReport = new ComponentRecoveryReport();
compRecReport.setLimitReached(Boolean.TRUE);
compRecReport.setName("DATANODE");
compRecReport.setNumAttempts(5);
compRecReports.add(compRecReport);
rr.setComponentReports(compRecReports);
hb2.setRecoveryReport(rr);
handler.handleHeartBeat(hb2);
assertEquals("UNRECOVERABLE", hostObject.getRecoveryReport().getSummary());
assertEquals(1, hostObject.getRecoveryReport().getComponentReports().size());
assertEquals(5, hostObject.getRecoveryReport().getComponentReports().get(0).getNumAttempts());
}
@Test
@SuppressWarnings("unchecked")
public void testProcessStatusReports() throws Exception {
Clusters fsm = clusters;
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Host hostObject = clusters.getHost(DummyHostname1);
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE);
hdfs.getServiceComponent(DATANODE).addServiceComponentHost(DummyHostname1);
hdfs.addServiceComponent(NAMENODE);
hdfs.getServiceComponent(NAMENODE).addServiceComponentHost(DummyHostname1);
hdfs.getServiceComponent(NAMENODE).getServiceComponentHost(DummyHostname1).setState(State.STARTED);
hdfs.getServiceComponent(DATANODE).getServiceComponentHost(DummyHostname1).setState(State.STARTED);
ActionQueue aq = new ActionQueue();
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1,
Role.DATANODE, null, null);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
add(command);
}}).anyTimes();
replay(am);
HeartBeatHandler handler = new HeartBeatHandler(fsm, aq, am, injector);
HeartbeatProcessor heartbeatProcessor = handler.getHeartbeatProcessor();
Register reg = new Register();
HostInfo hi = new HostInfo();
hi.setHostName(DummyHostname1);
hi.setOS(DummyOs);
hi.setOSRelease(DummyOSRelease);
reg.setHostname(DummyHostname1);
reg.setHardwareProfile(hi);
reg.setAgentVersion(metaInfo.getServerVersion());
handler.handleRegistration(reg);
hostObject.setState(HostState.UNHEALTHY);
aq.enqueue(DummyHostname1, new StatusCommand());
//All components are up
HeartBeat hb1 = new HeartBeat();
hb1.setResponseId(0);
hb1.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb1.setHostname(DummyHostname1);
List<ComponentStatus> componentStatus = new ArrayList<>();
ComponentStatus dataNodeStatus = new ComponentStatus();
dataNodeStatus.setClusterName(cluster.getClusterName());
dataNodeStatus.setServiceName(HDFS);
dataNodeStatus.setComponentName(DATANODE);
dataNodeStatus.setStatus("STARTED");
componentStatus.add(dataNodeStatus);
ComponentStatus nameNodeStatus = new ComponentStatus();
nameNodeStatus.setClusterName(cluster.getClusterName());
nameNodeStatus.setServiceName(HDFS);
nameNodeStatus.setComponentName(NAMENODE);
nameNodeStatus.setStatus("STARTED");
componentStatus.add(nameNodeStatus);
hb1.setComponentStatus(componentStatus);
handler.handleHeartBeat(hb1);
heartbeatProcessor.processHeartbeat(hb1);
assertEquals(HostHealthStatus.HealthStatus.HEALTHY.name(), hostObject.getStatus());
//Some slaves are down, masters are up
HeartBeat hb2 = new HeartBeat();
hb2.setResponseId(1);
hb2.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb2.setHostname(DummyHostname1);
componentStatus = new ArrayList<>();
dataNodeStatus = new ComponentStatus();
dataNodeStatus.setClusterName(cluster.getClusterName());
dataNodeStatus.setServiceName(HDFS);
dataNodeStatus.setComponentName(DATANODE);
dataNodeStatus.setStatus("INSTALLED");
componentStatus.add(dataNodeStatus);
nameNodeStatus = new ComponentStatus();
nameNodeStatus.setClusterName(cluster.getClusterName());
nameNodeStatus.setServiceName(HDFS);
nameNodeStatus.setComponentName(NAMENODE);
nameNodeStatus.setStatus("STARTED");
componentStatus.add(nameNodeStatus);
hb2.setComponentStatus(componentStatus);
handler.handleHeartBeat(hb2);
heartbeatProcessor.processHeartbeat(hb2);
assertEquals(HostHealthStatus.HealthStatus.ALERT.name(), hostObject.getStatus());
// mark the installed DN as maintenance
hdfs.getServiceComponent(DATANODE).getServiceComponentHost(
DummyHostname1).setMaintenanceState(MaintenanceState.ON);
HeartBeat hb2a = new HeartBeat();
hb2a.setResponseId(2);
hb2a.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb2a.setHostname(DummyHostname1);
componentStatus = new ArrayList<>();
dataNodeStatus = new ComponentStatus();
dataNodeStatus.setClusterName(cluster.getClusterName());
dataNodeStatus.setServiceName(HDFS);
dataNodeStatus.setComponentName(DATANODE);
dataNodeStatus.setStatus("INSTALLED");
componentStatus.add(dataNodeStatus);
nameNodeStatus = new ComponentStatus();
nameNodeStatus.setClusterName(cluster.getClusterName());
nameNodeStatus.setServiceName(HDFS);
nameNodeStatus.setComponentName(NAMENODE);
nameNodeStatus.setStatus("STARTED");
componentStatus.add(nameNodeStatus);
hb2a.setComponentStatus(componentStatus);
handler.handleHeartBeat(hb2a);
heartbeatProcessor.processHeartbeat(hb2a);
assertEquals(HostHealthStatus.HealthStatus.HEALTHY.name(), hostObject.getStatus());
hdfs.getServiceComponent(DATANODE).getServiceComponentHost(
DummyHostname1).setMaintenanceState(MaintenanceState.OFF);
//Some masters are down
HeartBeat hb3 = new HeartBeat();
hb3.setResponseId(3);
hb3.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb3.setHostname(DummyHostname1);
componentStatus = new ArrayList<>();
dataNodeStatus = new ComponentStatus();
dataNodeStatus.setClusterName(cluster.getClusterName());
dataNodeStatus.setServiceName(HDFS);
dataNodeStatus.setComponentName(DATANODE);
dataNodeStatus.setStatus("INSTALLED");
componentStatus.add(dataNodeStatus);
nameNodeStatus = new ComponentStatus();
nameNodeStatus.setClusterName(cluster.getClusterName());
nameNodeStatus.setServiceName(HDFS);
nameNodeStatus.setComponentName(NAMENODE);
nameNodeStatus.setStatus("INSTALLED");
componentStatus.add(nameNodeStatus);
hb3.setComponentStatus(componentStatus);
handler.handleHeartBeat(hb3);
heartbeatProcessor.processHeartbeat(hb3);
assertEquals(HostHealthStatus.HealthStatus.UNHEALTHY.name(), hostObject.getStatus());
//All are up
hb1.setResponseId(4);
handler.handleHeartBeat(hb1);
heartbeatProcessor.processHeartbeat(hb1);
assertEquals(HostHealthStatus.HealthStatus.HEALTHY.name(), hostObject.getStatus());
reset(am);
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
}}).anyTimes();
replay(am);
//Only one component reported status
hdfs.getServiceComponent(NAMENODE).getServiceComponentHost(DummyHostname1).setState(State.INSTALLED);
HeartBeat hb4 = new HeartBeat();
hb4.setResponseId(5);
hb4.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb4.setHostname(DummyHostname1);
componentStatus = new ArrayList<>();
dataNodeStatus = new ComponentStatus();
dataNodeStatus.setClusterName(cluster.getClusterName());
dataNodeStatus.setServiceName(HDFS);
dataNodeStatus.setComponentName(DATANODE);
dataNodeStatus.setStatus("STARTED");
componentStatus.add(dataNodeStatus);
hb4.setComponentStatus(componentStatus);
handler.handleHeartBeat(hb4);
heartbeatProcessor.processHeartbeat(hb4);
assertEquals(HostHealthStatus.HealthStatus.UNHEALTHY.name(), hostObject.getStatus());
hb1.setResponseId(6);
handler.handleHeartBeat(hb1);
heartbeatProcessor.processHeartbeat(hb1);
assertEquals(HostHealthStatus.HealthStatus.HEALTHY.name(), hostObject.getStatus());
//Some command reports
HeartBeat hb5 = new HeartBeat();
hb5.setResponseId(7);
hb5.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb5.setHostname(DummyHostname1);
CommandReport cr1 = new CommandReport();
cr1.setActionId(StageUtils.getActionId(requestId, stageId));
cr1.setServiceName(HDFS);
cr1.setTaskId(1);
cr1.setRole(DATANODE);
cr1.setStatus("COMPLETED");
cr1.setStdErr("");
cr1.setStdOut("");
cr1.setExitCode(215);
cr1.setRoleCommand("STOP");
cr1.setClusterName(DummyCluster);
ArrayList<CommandReport> reports = new ArrayList<>();
reports.add(cr1);
hb5.setReports(reports);
handler.handleHeartBeat(hb5);
heartbeatProcessor.processHeartbeat(hb5);
assertEquals(HostHealthStatus.HealthStatus.ALERT.name(), hostObject.getStatus());
}
@Test
@SuppressWarnings("unchecked")
public void testIgnoreCustomActionReport() throws Exception, InvalidStateTransitionException {
CommandReport cr1 = new CommandReport();
cr1.setActionId(StageUtils.getActionId(requestId, stageId));
cr1.setTaskId(1);
cr1.setClusterName(DummyCluster);
cr1.setServiceName(HDFS);
cr1.setRole(NAMENODE);
cr1.setStatus(HostRoleStatus.FAILED.toString());
cr1.setRoleCommand("CUSTOM_COMMAND");
cr1.setStdErr("none");
cr1.setStdOut("dummy output");
cr1.setExitCode(0);
CommandReport cr2 = new CommandReport();
cr2.setActionId(StageUtils.getActionId(requestId, stageId));
cr2.setTaskId(2);
cr2.setClusterName(DummyCluster);
cr2.setServiceName(HDFS);
cr2.setRole(NAMENODE);
cr2.setStatus(HostRoleStatus.FAILED.toString());
cr2.setRoleCommand("ACTIONEXECUTE");
cr2.setStdErr("none");
cr2.setStdOut("dummy output");
cr2.setExitCode(0);
ArrayList<CommandReport> reports = new ArrayList<>();
reports.add(cr1);
reports.add(cr2);
HeartBeat hb = new HeartBeat();
hb.setTimestamp(System.currentTimeMillis());
hb.setResponseId(0);
hb.setHostname(DummyHostname1);
hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb.setReports(reports);
ActionQueue aq = new ActionQueue();
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1,
Role.DATANODE, null, null);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
add(command);
}});
replay(am);
HeartBeatHandler handler = heartbeatTestHelper.getHeartBeatHandler(am, aq);
// CUSTOM_COMMAND and ACTIONEXECUTE reports are ignored
// they should not change the host component state
try {
handler.handleHeartBeat(hb);
handler.getHeartbeatProcessor().processHeartbeat(hb);
} catch (Exception e) {
fail();
}
}
@Test
public void testComponents() throws Exception,
InvalidStateTransitionException {
ComponentsResponse expected = new ComponentsResponse();
StackId dummyStackId = new StackId(DummyStackId);
Map<String, Map<String, String>> dummyComponents = new HashMap<>();
Map<String, String> dummyCategoryMap = new HashMap<>();
dummyCategoryMap.put("PIG", "CLIENT");
dummyComponents.put("PIG", dummyCategoryMap);
dummyCategoryMap = new HashMap<>();
dummyCategoryMap.put("MAPREDUCE_CLIENT", "CLIENT");
dummyCategoryMap.put("JOBTRACKER", "MASTER");
dummyCategoryMap.put("TASKTRACKER", "SLAVE");
dummyComponents.put("MAPREDUCE", dummyCategoryMap);
dummyCategoryMap = new HashMap<>();
dummyCategoryMap.put("DATANODE2", "SLAVE");
dummyCategoryMap.put("NAMENODE", "MASTER");
dummyCategoryMap.put("HDFS_CLIENT", "CLIENT");
dummyCategoryMap.put("DATANODE1", "SLAVE");
dummyCategoryMap.put("SECONDARY_NAMENODE", "MASTER");
dummyCategoryMap.put("DATANODE", "SLAVE");
dummyComponents.put("HDFS", dummyCategoryMap);
expected.setClusterName(DummyCluster);
expected.setStackName(dummyStackId.getStackName());
expected.setStackVersion(dummyStackId.getStackVersion());
expected.setComponents(dummyComponents);
heartbeatTestHelper.getDummyCluster();
HeartBeatHandler handler = heartbeatTestHelper.getHeartBeatHandler(
actionManagerTestHelper.getMockActionManager(),
new ActionQueue());
ComponentsResponse actual = handler.handleComponents(DummyCluster);
if (log.isDebugEnabled()) {
log.debug(actual.toString());
}
assertEquals(expected.getClusterName(), actual.getClusterName());
assertEquals(expected.getStackName(), actual.getStackName());
assertEquals(expected.getStackVersion(), actual.getStackVersion());
assertEquals(expected.getComponents(), actual.getComponents());
}
private ComponentStatus createComponentStatus(String clusterName, String serviceName, String message,
State state, SecurityState securityState,
String componentName, String stackVersion) {
ComponentStatus componentStatus1 = new ComponentStatus();
componentStatus1.setClusterName(clusterName);
componentStatus1.setServiceName(serviceName);
componentStatus1.setMessage(message);
componentStatus1.setStatus(state.name());
componentStatus1.setComponentName(componentName);
componentStatus1.setStackVersion(stackVersion);
return componentStatus1;
}
@Test
@SuppressWarnings("unchecked")
public void testCommandStatusProcesses_empty() throws Exception {
Cluster cluster = heartbeatTestHelper.getDummyCluster();
Service hdfs = cluster.addService(HDFS);
hdfs.addServiceComponent(DATANODE);
hdfs.getServiceComponent(DATANODE).addServiceComponentHost(DummyHostname1);
hdfs.getServiceComponent(DATANODE).getServiceComponentHost(DummyHostname1).setState(State.STARTED);
ActionQueue aq = new ActionQueue();
HeartBeat hb = new HeartBeat();
hb.setTimestamp(System.currentTimeMillis());
hb.setResponseId(0);
hb.setHostname(DummyHostname1);
hb.setNodeStatus(new HostStatus(Status.HEALTHY, DummyHostStatus));
hb.setReports(new ArrayList<CommandReport>());
ArrayList<ComponentStatus> componentStatuses = new ArrayList<>();
ComponentStatus componentStatus1 = new ComponentStatus();
componentStatus1.setClusterName(DummyCluster);
componentStatus1.setServiceName(HDFS);
componentStatus1.setMessage(DummyHostStatus);
componentStatus1.setStatus(State.STARTED.name());
componentStatus1.setComponentName(DATANODE);
componentStatuses.add(componentStatus1);
hb.setComponentStatus(componentStatuses);
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1,
Role.DATANODE, null, null);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
}});
replay(am);
HeartBeatHandler handler = heartbeatTestHelper.getHeartBeatHandler(am, aq);
ServiceComponentHost sch = hdfs.getServiceComponent(DATANODE).getServiceComponentHost(DummyHostname1);
Assert.assertEquals(Integer.valueOf(0), Integer.valueOf(sch.getProcesses().size()));
}
@Test
public void testInjectKeytabApplicableHost() throws Exception {
List<Map<String, String>> kcp;
Map<String, String> properties;
kcp = testInjectKeytabSetKeytab("c6403.ambari.apache.org");
Assert.assertNotNull(kcp);
Assert.assertEquals(1, kcp.size());
properties = kcp.get(0);
Assert.assertNotNull(properties);
Assert.assertEquals("c6403.ambari.apache.org", properties.get(KerberosIdentityDataFileWriter.HOSTNAME));
Assert.assertEquals("HDFS", properties.get(KerberosIdentityDataFileWriter.SERVICE));
Assert.assertEquals("DATANODE", properties.get(KerberosIdentityDataFileWriter.COMPONENT));
Assert.assertEquals("dn/_HOST@_REALM", properties.get(KerberosIdentityDataFileWriter.PRINCIPAL));
Assert.assertEquals("/etc/security/keytabs/dn.service.keytab", properties.get(KerberosIdentityDataFileWriter.KEYTAB_FILE_PATH));
Assert.assertEquals("hdfs", properties.get(KerberosIdentityDataFileWriter.KEYTAB_FILE_OWNER_NAME));
Assert.assertEquals("r", properties.get(KerberosIdentityDataFileWriter.KEYTAB_FILE_OWNER_ACCESS));
Assert.assertEquals("hadoop", properties.get(KerberosIdentityDataFileWriter.KEYTAB_FILE_GROUP_NAME));
Assert.assertEquals("", properties.get(KerberosIdentityDataFileWriter.KEYTAB_FILE_GROUP_ACCESS));
Assert.assertEquals(Base64.encodeBase64String("hello".getBytes()), kcp.get(0).get(KerberosServerAction.KEYTAB_CONTENT_BASE64));
kcp = testInjectKeytabRemoveKeytab("c6403.ambari.apache.org");
Assert.assertNotNull(kcp);
Assert.assertEquals(1, kcp.size());
properties = kcp.get(0);
Assert.assertNotNull(properties);
Assert.assertEquals("c6403.ambari.apache.org", properties.get(KerberosIdentityDataFileWriter.HOSTNAME));
Assert.assertEquals("HDFS", properties.get(KerberosIdentityDataFileWriter.SERVICE));
Assert.assertEquals("DATANODE", properties.get(KerberosIdentityDataFileWriter.COMPONENT));
Assert.assertEquals("dn/_HOST@_REALM", properties.get(KerberosIdentityDataFileWriter.PRINCIPAL));
Assert.assertEquals("/etc/security/keytabs/dn.service.keytab", properties.get(KerberosIdentityDataFileWriter.KEYTAB_FILE_PATH));
Assert.assertFalse(properties.containsKey(KerberosIdentityDataFileWriter.KEYTAB_FILE_OWNER_NAME));
Assert.assertFalse(properties.containsKey(KerberosIdentityDataFileWriter.KEYTAB_FILE_OWNER_ACCESS));
Assert.assertFalse(properties.containsKey(KerberosIdentityDataFileWriter.KEYTAB_FILE_GROUP_NAME));
Assert.assertFalse(properties.containsKey(KerberosIdentityDataFileWriter.KEYTAB_FILE_GROUP_ACCESS));
Assert.assertFalse(properties.containsKey(KerberosServerAction.KEYTAB_CONTENT_BASE64));
}
@Test
public void testInjectKeytabNotApplicableHost() throws Exception {
List<Map<String, String>> kcp;
kcp = testInjectKeytabSetKeytab("c6401.ambari.apache.org");
Assert.assertNotNull(kcp);
Assert.assertTrue(kcp.isEmpty());
kcp = testInjectKeytabRemoveKeytab("c6401.ambari.apache.org");
Assert.assertNotNull(kcp);
Assert.assertTrue(kcp.isEmpty());
}
private List<Map<String, String>> testInjectKeytabSetKeytab(String targetHost) throws Exception {
ExecutionCommand executionCommand = new ExecutionCommand();
Map<String, String> hlp = new HashMap<>();
hlp.put("custom_command", "SET_KEYTAB");
executionCommand.setHostLevelParams(hlp);
Map<String, String> commandparams = new HashMap<>();
commandparams.put(KerberosServerAction.AUTHENTICATED_USER_NAME, "admin");
commandparams.put(KerberosServerAction.DATA_DIRECTORY, createTestKeytabData().getAbsolutePath());
executionCommand.setCommandParams(commandparams);
ActionQueue aq = new ActionQueue();
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1,
Role.DATANODE, null, null);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
}});
replay(am);
heartbeatTestHelper.getHeartBeatHandler(am, aq).injectKeytab(executionCommand, "SET_KEYTAB", targetHost);
return executionCommand.getKerberosCommandParams();
}
private List<Map<String, String>> testInjectKeytabRemoveKeytab(String targetHost) throws Exception {
ExecutionCommand executionCommand = new ExecutionCommand();
Map<String, String> hlp = new HashMap<>();
hlp.put("custom_command", "REMOVE_KEYTAB");
executionCommand.setHostLevelParams(hlp);
Map<String, String> commandparams = new HashMap<>();
commandparams.put(KerberosServerAction.AUTHENTICATED_USER_NAME, "admin");
commandparams.put(KerberosServerAction.DATA_DIRECTORY, createTestKeytabData().getAbsolutePath());
executionCommand.setCommandParams(commandparams);
ActionQueue aq = new ActionQueue();
final HostRoleCommand command = hostRoleCommandFactory.create(DummyHostname1,
Role.DATANODE, null, null);
ActionManager am = actionManagerTestHelper.getMockActionManager();
expect(am.getTasks(EasyMock.<List<Long>>anyObject())).andReturn(
new ArrayList<HostRoleCommand>() {{
add(command);
}});
replay(am);
heartbeatTestHelper.getHeartBeatHandler(am, aq).injectKeytab(executionCommand, "REMOVE_KEYTAB", targetHost);
return executionCommand.getKerberosCommandParams();
}
private File createTestKeytabData() throws Exception {
File dataDirectory = temporaryFolder.newFolder();
File identityDataFile = new File(dataDirectory, KerberosIdentityDataFileWriter.DATA_FILE_NAME);
KerberosIdentityDataFileWriter kerberosIdentityDataFileWriter = injector.getInstance(KerberosIdentityDataFileWriterFactory.class).createKerberosIdentityDataFileWriter(identityDataFile);
File hostDirectory = new File(dataDirectory, "c6403.ambari.apache.org");
File keytabFile;
if(hostDirectory.mkdirs()) {
keytabFile = new File(hostDirectory, DigestUtils.sha1Hex("/etc/security/keytabs/dn.service.keytab"));
} else {
throw new Exception("Failed to create " + hostDirectory.getAbsolutePath());
}
kerberosIdentityDataFileWriter.writeRecord("c6403.ambari.apache.org", "HDFS", "DATANODE",
"dn/_HOST@_REALM", "service",
"/etc/security/keytabs/dn.service.keytab",
"hdfs", "r", "hadoop", "", "false");
kerberosIdentityDataFileWriter.close();
// Ensure the host directory exists...
FileWriter fw = new FileWriter(keytabFile);
BufferedWriter bw = new BufferedWriter(fw);
bw.write("hello");
bw.close();
return dataDirectory;
}
}