HDFS-2805. Add a test for a federated cluster with HA NNs. Contributed by Brandon Li.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/HDFS-1623@1236471 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jitendra Nath Pandey 2012-01-27 00:34:37 +00:00
parent fdf7b18247
commit e7775e0b3b
5 changed files with 119 additions and 41 deletions

View File

@ -133,3 +133,5 @@ HDFS-2807. Service level authorizartion for HAServiceProtocol. (jitendra)
HDFS-2809. Add test to verify that delegation tokens are honored after failover. (jitendra and atm)
HDFS-2838. NPE in FSNamesystem when in safe mode. (Gregory Chanan via eli)
HDFS-2805. Add a test for a federated cluster with HA NNs. (Brandon Li via jitendra)

View File

@ -586,11 +586,19 @@ public class MiniDFSCluster {
conf.set(FS_DEFAULT_NAME_KEY, "127.0.0.1:" + onlyNN.getIpcPort());
}
// If we have more than one nameservice, need to enumerate them in the
// config.
if (federation) {
List<String> allNsIds = Lists.newArrayList();
for (MiniDFSNNTopology.NSConf nameservice : nnTopology.getNameservices()) {
allNsIds.add(nameservice.getId());
}
conf.set(DFS_FEDERATION_NAMESERVICES, Joiner.on(",").join(allNsIds));
}
int nnCounter = 0;
List<String> nsIds = Lists.newArrayList();
for (MiniDFSNNTopology.NSConf nameservice : nnTopology.getNameservices()) {
String nsId = nameservice.getId();
nsIds.add(nameservice.getId());
Preconditions.checkArgument(
!federation || nsId != null,
@ -643,6 +651,7 @@ public class MiniDFSCluster {
}
prevNNDirs = FSNamesystem.getNamespaceDirs(conf);
}
// Start all Namenodes
for (NNConf nn : nameservice.getNNs()) {
initNameNodeConf(conf, nsId, nn.getNnId(), manageNameDfsDirs, nnCounter);
@ -651,11 +660,6 @@ public class MiniDFSCluster {
}
}
if (federation) {
// If we have more than one nameservice, need to enumerate them in the
// config.
conf.set(DFS_FEDERATION_NAMESERVICES, Joiner.on(",").join(nsIds));
}
}

View File

@ -77,6 +77,22 @@ public class MiniDFSNNTopology {
return topology;
}
/**
* Set up federated cluster with the given number of nameservices, each
* of which has two NameNodes.
*/
public static MiniDFSNNTopology simpleHAFederatedTopology(
int numNameservices) {
MiniDFSNNTopology topology = new MiniDFSNNTopology();
for (int i = 0; i < numNameservices; i++) {
topology.addNameservice(new MiniDFSNNTopology.NSConf("ns" + i)
.addNN(new MiniDFSNNTopology.NNConf("nn0"))
.addNN(new MiniDFSNNTopology.NNConf("nn1")));
}
topology.setFederation(true);
return topology;
}
public MiniDFSNNTopology setFederation(boolean federation) {
this.federation = federation;
return this;

View File

@ -131,18 +131,36 @@ public abstract class HATestUtil {
/** Gets the filesystem instance by setting the failover configurations */
public static FileSystem configureFailoverFs(MiniDFSCluster cluster, Configuration conf)
throws IOException, URISyntaxException {
return configureFailoverFs(cluster, conf, 0);
}
/**
* Gets the filesystem instance by setting the failover configurations
* @param cluster the single process DFS cluster
* @param conf cluster configuration
* @param nsIndex namespace index starting with zero
* @throws IOException if an error occurs rolling the edit log
*/
public static FileSystem configureFailoverFs(MiniDFSCluster cluster, Configuration conf,
int nsIndex) throws IOException, URISyntaxException {
conf = new Configuration(conf);
String logicalName = getLogicalHostname(cluster);
setFailoverConfigurations(cluster, conf, logicalName);
setFailoverConfigurations(cluster, conf, logicalName, nsIndex);
FileSystem fs = FileSystem.get(new URI("hdfs://" + logicalName), conf);
return fs;
}
/** Sets the required configurations for performing failover */
/** Sets the required configurations for performing failover of default namespace. */
public static void setFailoverConfigurations(MiniDFSCluster cluster,
Configuration conf, String logicalName) {
InetSocketAddress nnAddr1 = cluster.getNameNode(0).getNameNodeAddress();
InetSocketAddress nnAddr2 = cluster.getNameNode(1).getNameNodeAddress();
setFailoverConfigurations(cluster, conf, logicalName, 0);
}
/** Sets the required configurations for performing failover. */
public static void setFailoverConfigurations(MiniDFSCluster cluster,
Configuration conf, String logicalName, int nsIndex) {
InetSocketAddress nnAddr1 = cluster.getNameNode(2 * nsIndex).getNameNodeAddress();
InetSocketAddress nnAddr2 = cluster.getNameNode(2 * nsIndex + 1).getNameNodeAddress();
String nameNodeId1 = "nn1";
String nameNodeId2 = "nn2";
String address1 = "hdfs://" + nnAddr1.getHostName() + ":" + nnAddr1.getPort();

View File

@ -106,6 +106,46 @@ public class TestHAStateTransitions {
}
}
/**
* Test manual failover failback for one namespace
* @param cluster single process test cluster
* @param conf cluster configuration
* @param nsIndex namespace index starting from zero
* @throws Exception
*/
private void testManualFailoverFailback(MiniDFSCluster cluster,
Configuration conf, int nsIndex) throws Exception {
int nn0 = 2 * nsIndex, nn1 = 2 * nsIndex + 1;
cluster.transitionToActive(nn0);
LOG.info("Starting with NN 0 active in namespace " + nsIndex);
FileSystem fs = HATestUtil.configureFailoverFs(cluster, conf);
fs.mkdirs(TEST_DIR);
LOG.info("Failing over to NN 1 in namespace " + nsIndex);
cluster.transitionToStandby(nn0);
cluster.transitionToActive(nn1);
assertTrue(fs.exists(TEST_DIR));
DFSTestUtil.writeFile(fs, TEST_FILE_PATH, TEST_FILE_DATA);
LOG.info("Failing over to NN 0 in namespace " + nsIndex);
cluster.transitionToStandby(nn1);
cluster.transitionToActive(nn0);
assertTrue(fs.exists(TEST_DIR));
assertEquals(TEST_FILE_DATA,
DFSTestUtil.readFile(fs, TEST_FILE_PATH));
LOG.info("Removing test file");
fs.delete(TEST_DIR, true);
assertFalse(fs.exists(TEST_DIR));
LOG.info("Failing over to NN 1 in namespace " + nsIndex);
cluster.transitionToStandby(nn0);
cluster.transitionToActive(nn1);
assertFalse(fs.exists(TEST_DIR));
}
/**
* Tests manual failover back and forth between two NameNodes.
*/
@ -118,34 +158,8 @@ public class TestHAStateTransitions {
.build();
try {
cluster.waitActive();
cluster.transitionToActive(0);
LOG.info("Starting with NN 0 active");
FileSystem fs = HATestUtil.configureFailoverFs(cluster, conf);
fs.mkdirs(TEST_DIR);
LOG.info("Failing over to NN 1");
cluster.transitionToStandby(0);
cluster.transitionToActive(1);
assertTrue(fs.exists(TEST_DIR));
DFSTestUtil.writeFile(fs, TEST_FILE_PATH, TEST_FILE_DATA);
LOG.info("Failing over to NN 0");
cluster.transitionToStandby(1);
cluster.transitionToActive(0);
assertTrue(fs.exists(TEST_DIR));
assertEquals(TEST_FILE_DATA,
DFSTestUtil.readFile(fs, TEST_FILE_PATH));
LOG.info("Removing test file");
fs.delete(TEST_DIR, true);
assertFalse(fs.exists(TEST_DIR));
LOG.info("Failing over to NN 1");
cluster.transitionToStandby(0);
cluster.transitionToActive(1);
assertFalse(fs.exists(TEST_DIR));
// test the only namespace
testManualFailoverFailback(cluster, conf, 0);
} finally {
cluster.shutdown();
}
@ -294,4 +308,28 @@ public class TestHAStateTransitions {
cluster.shutdown();
}
}
/**
* Tests manual failover back and forth between two NameNodes
* for federation cluster with two namespaces.
*/
@Test
public void testManualFailoverFailbackFederationHA() throws Exception {
Configuration conf = new Configuration();
MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf)
.nnTopology(MiniDFSNNTopology.simpleHAFederatedTopology(2))
.numDataNodes(1)
.build();
try {
cluster.waitActive();
// test for namespace 0
testManualFailoverFailback(cluster, conf, 0);
// test for namespace 1
testManualFailoverFailback(cluster, conf, 1);
} finally {
cluster.shutdown();
}
}
}