Skip to content

Commit 59ded76

Browse files
swaglenandakumar131
authored andcommitted
HDDS-1411. Add unit test to check if SCM correctly sends close commands for containers in closing state after a restart. (#755)
1 parent 7e1f8d3 commit 59ded76

File tree

2 files changed

+122
-9
lines changed

2 files changed

+122
-9
lines changed

hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,14 +400,14 @@ private void initalizeSystemManagers(OzoneConfiguration conf,
400400
new SCMPipelineManager(conf, scmNodeManager, eventQueue);
401401
}
402402

403-
if(configurator.getContainerManager() != null) {
403+
if (configurator.getContainerManager() != null) {
404404
containerManager = configurator.getContainerManager();
405405
} else {
406406
containerManager = new SCMContainerManager(
407407
conf, scmNodeManager, pipelineManager, eventQueue);
408408
}
409409

410-
if(configurator.getScmBlockManager() != null) {
410+
if (configurator.getScmBlockManager() != null) {
411411
scmBlockManager = configurator.getScmBlockManager();
412412
} else {
413413
scmBlockManager = new BlockManagerImpl(conf, this);

hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestStorageContainerManager.java

Lines changed: 120 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,17 @@
2020
import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_COMMAND_STATUS_REPORT_INTERVAL;
2121
import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_CONTAINER_REPORT_INTERVAL;
2222
import static org.junit.Assert.fail;
23+
import static org.mockito.Matchers.any;
24+
import static org.mockito.Matchers.argThat;
25+
import static org.mockito.Matchers.eq;
26+
import static org.mockito.Mockito.doNothing;
27+
import static org.mockito.Mockito.mock;
28+
import static org.mockito.Mockito.verify;
29+
import static org.mockito.Mockito.when;
2330

24-
import com.google.common.collect.Lists;
25-
import com.google.common.collect.Maps;
2631
import java.io.IOException;
32+
import java.lang.reflect.Field;
33+
import java.lang.reflect.Modifier;
2734
import java.nio.file.Path;
2835
import java.nio.file.Paths;
2936
import java.util.Collections;
@@ -33,6 +40,7 @@
3340
import java.util.Set;
3441
import java.util.UUID;
3542
import java.util.concurrent.TimeUnit;
43+
3644
import org.apache.commons.lang3.RandomUtils;
3745
import org.apache.hadoop.hdds.HddsConfigKeys;
3846
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
@@ -46,42 +54,54 @@
4654
import org.apache.hadoop.hdds.scm.XceiverClientManager;
4755
import org.apache.hadoop.hdds.scm.block.DeletedBlockLog;
4856
import org.apache.hadoop.hdds.scm.block.SCMBlockDeletingService;
57+
import org.apache.hadoop.hdds.scm.container.ContainerInfo;
4958
import org.apache.hadoop.hdds.scm.container.ContainerNotFoundException;
59+
import org.apache.hadoop.hdds.scm.container.ReplicationManager;
5060
import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline;
61+
import org.apache.hadoop.hdds.scm.events.SCMEvents;
5162
import org.apache.hadoop.hdds.scm.exceptions.SCMException;
5263
import org.apache.hadoop.hdds.scm.node.NodeManager;
5364
import org.apache.hadoop.hdds.scm.server.SCMClientProtocolServer;
5465
import org.apache.hadoop.hdds.scm.server.SCMStorageConfig;
5566
import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
5667
import org.apache.hadoop.hdds.scm.server.StorageContainerManager.StartupOption;
68+
import org.apache.hadoop.hdds.server.events.EventPublisher;
69+
import org.apache.hadoop.hdds.server.events.TypedEvent;
5770
import org.apache.hadoop.ozone.container.ContainerTestHelper;
5871
import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
5972
import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
73+
import org.apache.hadoop.ozone.protocol.commands.CloseContainerCommand;
74+
import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode;
6075
import org.apache.hadoop.ozone.protocol.commands.DeleteBlocksCommand;
6176
import org.apache.hadoop.ozone.protocol.commands.SCMCommand;
6277
import org.apache.hadoop.security.authentication.client.AuthenticationException;
6378
import org.apache.hadoop.test.GenericTestUtils;
6479
import org.apache.hadoop.util.ExitUtil;
6580
import org.apache.hadoop.utils.HddsVersionInfo;
66-
6781
import org.junit.Assert;
6882
import org.junit.Rule;
6983
import org.junit.Test;
7084
import org.junit.rules.ExpectedException;
85+
import org.junit.rules.TemporaryFolder;
7186
import org.junit.rules.Timeout;
87+
import org.mockito.ArgumentMatcher;
7288
import org.mockito.Mockito;
7389
import org.slf4j.Logger;
7490
import org.slf4j.LoggerFactory;
7591

92+
import com.google.common.collect.Lists;
93+
import com.google.common.collect.Maps;
94+
7695
/**
7796
* Test class that exercises the StorageContainerManager.
7897
*/
7998
public class TestStorageContainerManager {
8099
private static XceiverClientManager xceiverClientManager =
81100
new XceiverClientManager(
82101
new OzoneConfiguration());
83-
private static final Logger LOG = LoggerFactory
84-
.getLogger(TestStorageContainerManager.class);
102+
private static final Logger LOG = LoggerFactory.getLogger(
103+
TestStorageContainerManager.class);
104+
85105
/**
86106
* Set the timeout for every test.
87107
*/
@@ -94,6 +114,9 @@ public class TestStorageContainerManager {
94114
@Rule
95115
public ExpectedException exception = ExpectedException.none();
96116

117+
@Rule
118+
public TemporaryFolder folder= new TemporaryFolder();
119+
97120
@Test
98121
public void testRpcPermission() throws Exception {
99122
// Test with default configuration
@@ -119,7 +142,7 @@ private void testRpcPermissionWithConf(
119142

120143
SCMClientProtocolServer mockClientServer = Mockito.spy(
121144
cluster.getStorageContainerManager().getClientProtocolServer());
122-
Mockito.when(mockClientServer.getRpcRemoteUsername())
145+
when(mockClientServer.getRpcRemoteUsername())
123146
.thenReturn(fakeRemoteUsername);
124147

125148
try {
@@ -405,7 +428,6 @@ public void testSCMInitialization() throws Exception {
405428
StorageContainerManager.scmInit(conf);
406429
Assert.assertEquals(NodeType.SCM, scmStore.getNodeType());
407430
Assert.assertEquals("testClusterId", scmStore.getClusterID());
408-
409431
}
410432

411433
@Test
@@ -482,4 +504,95 @@ public void testScmInfo() throws Exception {
482504
Assert.assertEquals(expectedVersion, actualVersion);
483505
}
484506

507+
@Test
508+
@SuppressWarnings("unchecked")
509+
public void testCloseContainerCommandOnRestart() throws Exception {
510+
int numKeys = 15;
511+
OzoneConfiguration conf = new OzoneConfiguration();
512+
conf.setTimeDuration(HDDS_CONTAINER_REPORT_INTERVAL, 1, TimeUnit.SECONDS);
513+
conf.setInt(ScmConfigKeys.OZONE_SCM_BLOCK_DELETION_MAX_RETRY, 5);
514+
conf.setTimeDuration(OzoneConfigKeys.OZONE_BLOCK_DELETING_SERVICE_INTERVAL,
515+
100, TimeUnit.MILLISECONDS);
516+
conf.setInt(ScmConfigKeys.OZONE_SCM_PIPELINE_OWNER_CONTAINER_COUNT,
517+
numKeys);
518+
519+
MiniOzoneCluster cluster = MiniOzoneCluster.newBuilder(conf)
520+
.setHbInterval(1000)
521+
.setHbProcessorInterval(3000)
522+
.setTrace(false)
523+
.setNumDatanodes(1)
524+
.build();
525+
cluster.waitForClusterToBeReady();
526+
527+
TestStorageContainerManagerHelper helper =
528+
new TestStorageContainerManagerHelper(cluster, conf);
529+
530+
helper.createKeys(10, 4096);
531+
Thread.sleep(5000);
532+
533+
StorageContainerManager scm = cluster.getStorageContainerManager();
534+
List<ContainerInfo> containers = cluster.getStorageContainerManager()
535+
.getContainerManager().getContainers();
536+
Assert.assertNotNull(containers);
537+
ContainerInfo selectedContainer = containers.iterator().next();
538+
539+
// Stop processing HB
540+
scm.getDatanodeProtocolServer().stop();
541+
EventPublisher publisher = mock(EventPublisher.class);
542+
ReplicationManager replicationManager = scm.getReplicationManager();
543+
Field f = replicationManager.getClass().getDeclaredField("eventPublisher");
544+
f.setAccessible(true);
545+
Field modifiersField = Field.class.getDeclaredField("modifiers");
546+
modifiersField.setAccessible(true);
547+
modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
548+
f.set(replicationManager, publisher);
549+
550+
doNothing().when(publisher).fireEvent(any(TypedEvent.class),
551+
any(CommandForDatanode.class));
552+
553+
scm.getContainerManager().updateContainerState(selectedContainer
554+
.containerID(), HddsProtos.LifeCycleEvent.FINALIZE);
555+
cluster.restartStorageContainerManager(true);
556+
scm.getReplicationManager().start();
557+
Thread.sleep(2000);
558+
559+
UUID dnUuid = cluster.getHddsDatanodes().iterator().next()
560+
.getDatanodeDetails().getUuid();
561+
562+
CloseContainerCommand closeContainerCommand =
563+
new CloseContainerCommand(selectedContainer.getContainerID(),
564+
selectedContainer.getPipelineID(), false);
565+
566+
CommandForDatanode commandForDatanode = new CommandForDatanode(
567+
dnUuid, closeContainerCommand);
568+
569+
verify(publisher).fireEvent(eq(SCMEvents.DATANODE_COMMAND), argThat(new
570+
CloseContainerCommandMatcher(dnUuid, commandForDatanode)));
571+
}
572+
573+
@SuppressWarnings("visibilitymodifier")
574+
static class CloseContainerCommandMatcher
575+
extends ArgumentMatcher<CommandForDatanode> {
576+
577+
private final CommandForDatanode cmd;
578+
private final UUID uuid;
579+
580+
CloseContainerCommandMatcher(UUID uuid, CommandForDatanode cmd) {
581+
this.uuid = uuid;
582+
this.cmd = cmd;
583+
}
584+
585+
@Override
586+
public boolean matches(Object argument) {
587+
CommandForDatanode cmdRight = (CommandForDatanode) argument;
588+
CloseContainerCommand left = (CloseContainerCommand) cmd.getCommand();
589+
CloseContainerCommand right =
590+
(CloseContainerCommand) cmdRight.getCommand();
591+
return cmdRight.getDatanodeId().equals(uuid)
592+
&& left.getContainerID() == right.getContainerID()
593+
&& left.getPipelineID() == right.getPipelineID()
594+
&& left.getType() == right.getType()
595+
&& left.getProto().equals(right.getProto());
596+
}
597+
}
485598
}

0 commit comments

Comments
 (0)