HDFS-3084. FenceMethod.tryFence() and ShellCommandFencer should pass namenodeId as well as host:port. Contributed by Todd Lipcon.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1309526 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4f7f58fa8b
commit
a7d6bdc63b
@ -313,6 +313,9 @@ Release 2.0.0 - UNRELEASED
|
|||||||
HDFS-2564. Cleanup unnecessary exceptions thrown and unnecessary casts.
|
HDFS-2564. Cleanup unnecessary exceptions thrown and unnecessary casts.
|
||||||
(Hari Mankude via eli)
|
(Hari Mankude via eli)
|
||||||
|
|
||||||
|
HDFS-3084. FenceMethod.tryFence() and ShellCommandFencer should pass
|
||||||
|
namenodeId as well as host:port (todd)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
HDFS-3024. Improve performance of stringification in addStoredBlock (todd)
|
HDFS-3024. Improve performance of stringification in addStoredBlock (todd)
|
||||||
|
@ -1026,13 +1026,7 @@ public static String getNamenodeServiceAddr(final Configuration conf,
|
|||||||
String nsId, String nnId) {
|
String nsId, String nnId) {
|
||||||
|
|
||||||
if (nsId == null) {
|
if (nsId == null) {
|
||||||
Collection<String> nsIds = getNameServiceIds(conf);
|
nsId = getOnlyNameServiceIdOrNull(conf);
|
||||||
if (1 == nsIds.size()) {
|
|
||||||
nsId = nsIds.toArray(new String[1])[0];
|
|
||||||
} else {
|
|
||||||
// No nameservice ID was given and more than one is configured
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String serviceAddrKey = concatSuffixes(
|
String serviceAddrKey = concatSuffixes(
|
||||||
@ -1047,4 +1041,18 @@ public static String getNamenodeServiceAddr(final Configuration conf,
|
|||||||
}
|
}
|
||||||
return serviceRpcAddr;
|
return serviceRpcAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the configuration refers to only a single nameservice, return the
|
||||||
|
* name of that nameservice. If it refers to 0 or more than 1, return null.
|
||||||
|
*/
|
||||||
|
public static String getOnlyNameServiceIdOrNull(Configuration conf) {
|
||||||
|
Collection<String> nsIds = getNameServiceIds(conf);
|
||||||
|
if (1 == nsIds.size()) {
|
||||||
|
return nsIds.toArray(new String[1])[0];
|
||||||
|
} else {
|
||||||
|
// No nameservice ID was given and more than one is configured
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package org.apache.hadoop.hdfs.tools;
|
package org.apache.hadoop.hdfs.tools;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.ha.BadFencingConfigurationException;
|
import org.apache.hadoop.ha.BadFencingConfigurationException;
|
||||||
@ -28,6 +29,8 @@
|
|||||||
import org.apache.hadoop.hdfs.server.namenode.NameNode;
|
import org.apache.hadoop.hdfs.server.namenode.NameNode;
|
||||||
import org.apache.hadoop.net.NetUtils;
|
import org.apache.hadoop.net.NetUtils;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One of the NN NameNodes acting as the target of an administrative command
|
* One of the NN NameNodes acting as the target of an administrative command
|
||||||
* (e.g. failover).
|
* (e.g. failover).
|
||||||
@ -35,14 +38,36 @@
|
|||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
public class NNHAServiceTarget extends HAServiceTarget {
|
public class NNHAServiceTarget extends HAServiceTarget {
|
||||||
|
|
||||||
|
// Keys added to the fencing script environment
|
||||||
|
private static final String NAMESERVICE_ID_KEY = "nameserviceid";
|
||||||
|
private static final String NAMENODE_ID_KEY = "namenodeid";
|
||||||
|
|
||||||
private final InetSocketAddress addr;
|
private final InetSocketAddress addr;
|
||||||
private NodeFencer fencer;
|
private NodeFencer fencer;
|
||||||
private BadFencingConfigurationException fenceConfigError;
|
private BadFencingConfigurationException fenceConfigError;
|
||||||
|
private final String nnId;
|
||||||
|
private final String nsId;
|
||||||
|
|
||||||
public NNHAServiceTarget(HdfsConfiguration conf,
|
public NNHAServiceTarget(HdfsConfiguration conf,
|
||||||
String nsId, String nnId) {
|
String nsId, String nnId) {
|
||||||
|
Preconditions.checkNotNull(nnId);
|
||||||
|
|
||||||
|
if (nsId == null) {
|
||||||
|
nsId = DFSUtil.getOnlyNameServiceIdOrNull(conf);
|
||||||
|
if (nsId == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unable to determine the nameservice id.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert nsId != null;
|
||||||
|
|
||||||
|
// Make a copy of the conf, and override configs based on the
|
||||||
|
// target node -- not the node we happen to be running on.
|
||||||
|
HdfsConfiguration targetConf = new HdfsConfiguration(conf);
|
||||||
|
NameNode.initializeGenericKeys(targetConf, nsId, nnId);
|
||||||
|
|
||||||
String serviceAddr =
|
String serviceAddr =
|
||||||
DFSUtil.getNamenodeServiceAddr(conf, nsId, nnId);
|
DFSUtil.getNamenodeServiceAddr(targetConf, nsId, nnId);
|
||||||
if (serviceAddr == null) {
|
if (serviceAddr == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Unable to determine service address for namenode '" + nnId + "'");
|
"Unable to determine service address for namenode '" + nnId + "'");
|
||||||
@ -50,10 +75,12 @@ public NNHAServiceTarget(HdfsConfiguration conf,
|
|||||||
this.addr = NetUtils.createSocketAddr(serviceAddr,
|
this.addr = NetUtils.createSocketAddr(serviceAddr,
|
||||||
NameNode.DEFAULT_PORT);
|
NameNode.DEFAULT_PORT);
|
||||||
try {
|
try {
|
||||||
this.fencer = NodeFencer.create(conf);
|
this.fencer = NodeFencer.create(targetConf);
|
||||||
} catch (BadFencingConfigurationException e) {
|
} catch (BadFencingConfigurationException e) {
|
||||||
this.fenceConfigError = e;
|
this.fenceConfigError = e;
|
||||||
}
|
}
|
||||||
|
this.nnId = nnId;
|
||||||
|
this.nsId = nsId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,4 +108,19 @@ public String toString() {
|
|||||||
return "NameNode at " + addr;
|
return "NameNode at " + addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getNameServiceId() {
|
||||||
|
return this.nsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNameNodeId() {
|
||||||
|
return this.nnId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addFencingParameters(Map<String, String> ret) {
|
||||||
|
super.addFencingParameters(ret);
|
||||||
|
|
||||||
|
ret.put(NAMESERVICE_ID_KEY, getNameServiceId());
|
||||||
|
ret.put(NAMENODE_ID_KEY, getNameNodeId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,6 +180,17 @@ public void testGetNameServiceIds() {
|
|||||||
assertEquals("nn2", it.next().toString());
|
assertEquals("nn2", it.next().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetOnlyNameServiceIdOrNull() {
|
||||||
|
HdfsConfiguration conf = new HdfsConfiguration();
|
||||||
|
conf.set(DFS_FEDERATION_NAMESERVICES, "ns1,ns2");
|
||||||
|
assertNull(DFSUtil.getOnlyNameServiceIdOrNull(conf));
|
||||||
|
conf.set(DFS_FEDERATION_NAMESERVICES, "");
|
||||||
|
assertNull(DFSUtil.getOnlyNameServiceIdOrNull(conf));
|
||||||
|
conf.set(DFS_FEDERATION_NAMESERVICES, "ns1");
|
||||||
|
assertEquals("ns1", DFSUtil.getOnlyNameServiceIdOrNull(conf));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link DFSUtil#getNNServiceRpcAddresses(Configuration)}
|
* Test for {@link DFSUtil#getNNServiceRpcAddresses(Configuration)}
|
||||||
* {@link DFSUtil#getNameServiceIdFromAddress(Configuration, InetSocketAddress, String...)
|
* {@link DFSUtil#getNameServiceIdFromAddress(Configuration, InetSocketAddress, String...)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
@ -41,6 +42,7 @@
|
|||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for HAAdmin command with {@link MiniDFSCluster} set up in HA mode.
|
* Tests for HAAdmin command with {@link MiniDFSCluster} set up in HA mode.
|
||||||
@ -59,6 +61,8 @@ public class TestDFSHAAdminMiniCluster {
|
|||||||
|
|
||||||
private String errOutput;
|
private String errOutput;
|
||||||
|
|
||||||
|
private int nn1Port;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
conf = new Configuration();
|
conf = new Configuration();
|
||||||
@ -69,6 +73,8 @@ public void setup() throws IOException {
|
|||||||
tool.setConf(conf);
|
tool.setConf(conf);
|
||||||
tool.setErrOut(new PrintStream(errOutBytes));
|
tool.setErrOut(new PrintStream(errOutBytes));
|
||||||
cluster.waitActive();
|
cluster.waitActive();
|
||||||
|
|
||||||
|
nn1Port = cluster.getNameNodePort(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -125,8 +131,16 @@ public void testFencer() throws Exception {
|
|||||||
// Test failover with no fencer
|
// Test failover with no fencer
|
||||||
assertEquals(-1, runTool("-failover", "nn1", "nn2"));
|
assertEquals(-1, runTool("-failover", "nn1", "nn2"));
|
||||||
|
|
||||||
|
// Set up fencer to write info about the fencing target into a
|
||||||
|
// tmp file, so we can verify that the args were substituted right
|
||||||
|
File tmpFile = File.createTempFile("testFencer", ".txt");
|
||||||
|
tmpFile.deleteOnExit();
|
||||||
|
conf.set(NodeFencer.CONF_METHODS_KEY,
|
||||||
|
"shell(echo -n $target_nameserviceid.$target_namenodeid " +
|
||||||
|
"$target_port $dfs_ha_namenode_id > " +
|
||||||
|
tmpFile.getAbsolutePath() + ")");
|
||||||
|
|
||||||
// Test failover with fencer
|
// Test failover with fencer
|
||||||
conf.set(NodeFencer.CONF_METHODS_KEY, "shell(true)");
|
|
||||||
tool.setConf(conf);
|
tool.setConf(conf);
|
||||||
assertEquals(0, runTool("-transitionToActive", "nn1"));
|
assertEquals(0, runTool("-transitionToActive", "nn1"));
|
||||||
assertEquals(0, runTool("-failover", "nn1", "nn2"));
|
assertEquals(0, runTool("-failover", "nn1", "nn2"));
|
||||||
@ -134,21 +148,36 @@ public void testFencer() throws Exception {
|
|||||||
// Test failover with fencer and nameservice
|
// Test failover with fencer and nameservice
|
||||||
assertEquals(0, runTool("-ns", "minidfs-ns", "-failover", "nn2", "nn1"));
|
assertEquals(0, runTool("-ns", "minidfs-ns", "-failover", "nn2", "nn1"));
|
||||||
|
|
||||||
|
// Fencer has not run yet, since none of the above required fencing
|
||||||
|
assertEquals("", Files.toString(tmpFile, Charsets.UTF_8));
|
||||||
|
|
||||||
// Test failover with fencer and forcefence option
|
// Test failover with fencer and forcefence option
|
||||||
assertEquals(0, runTool("-failover", "nn1", "nn2", "--forcefence"));
|
assertEquals(0, runTool("-failover", "nn1", "nn2", "--forcefence"));
|
||||||
|
|
||||||
|
// The fence script should run with the configuration from the target
|
||||||
|
// node, rather than the configuration from the fencing node
|
||||||
|
assertEquals("minidfs-ns.nn1 " + nn1Port + " nn1",
|
||||||
|
Files.toString(tmpFile, Charsets.UTF_8));
|
||||||
|
tmpFile.delete();
|
||||||
|
|
||||||
// Test failover with forceactive option
|
// Test failover with forceactive option
|
||||||
assertEquals(0, runTool("-failover", "nn2", "nn1", "--forceactive"));
|
assertEquals(0, runTool("-failover", "nn2", "nn1", "--forceactive"));
|
||||||
|
|
||||||
|
// Fencing should not occur, since it was graceful
|
||||||
|
assertFalse(tmpFile.exists());
|
||||||
|
|
||||||
|
|
||||||
// Test failover with not fencer and forcefence option
|
// Test failover with not fencer and forcefence option
|
||||||
conf.unset(NodeFencer.CONF_METHODS_KEY);
|
conf.unset(NodeFencer.CONF_METHODS_KEY);
|
||||||
tool.setConf(conf);
|
tool.setConf(conf);
|
||||||
assertEquals(-1, runTool("-failover", "nn1", "nn2", "--forcefence"));
|
assertEquals(-1, runTool("-failover", "nn1", "nn2", "--forcefence"));
|
||||||
|
assertFalse(tmpFile.exists());
|
||||||
|
|
||||||
// Test failover with bad fencer and forcefence option
|
// Test failover with bad fencer and forcefence option
|
||||||
conf.set(NodeFencer.CONF_METHODS_KEY, "foobar!");
|
conf.set(NodeFencer.CONF_METHODS_KEY, "foobar!");
|
||||||
tool.setConf(conf);
|
tool.setConf(conf);
|
||||||
assertEquals(-1, runTool("-failover", "nn1", "nn2", "--forcefence"));
|
assertEquals(-1, runTool("-failover", "nn1", "nn2", "--forcefence"));
|
||||||
|
assertFalse(tmpFile.exists());
|
||||||
|
|
||||||
// Test failover with force fence listed before the other arguments
|
// Test failover with force fence listed before the other arguments
|
||||||
conf.set(NodeFencer.CONF_METHODS_KEY, "shell(true)");
|
conf.set(NodeFencer.CONF_METHODS_KEY, "shell(true)");
|
||||||
|
Loading…
Reference in New Issue
Block a user