HDFS-3835. Long-lived 2NN cannot perform a checkpoint if security is enabled and the NN restarts with outstanding delegation tokens. Contributed by Aaron T. Myers.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1376189 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8c28ebabcd
commit
4e75deb4e7
|
@ -113,6 +113,16 @@ extends AbstractDelegationTokenIdentifier>
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all data structures and mutable state.
|
||||
*/
|
||||
public synchronized void reset() {
|
||||
currentId = 0;
|
||||
allKeys.clear();
|
||||
delegationTokenSequenceNumber = 0;
|
||||
currentTokens.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a previously used master key to cache (when NN restarts),
|
||||
* should be called before activate().
|
||||
|
@ -190,7 +200,6 @@ extends AbstractDelegationTokenIdentifier>
|
|||
|
||||
@Override
|
||||
protected synchronized byte[] createPassword(TokenIdent identifier) {
|
||||
LOG.info("Creating password for identifier: "+identifier);
|
||||
int sequenceNum;
|
||||
long now = Time.now();
|
||||
sequenceNum = ++delegationTokenSequenceNumber;
|
||||
|
@ -198,6 +207,7 @@ extends AbstractDelegationTokenIdentifier>
|
|||
identifier.setMaxDate(now + tokenMaxLifetime);
|
||||
identifier.setMasterKeyId(currentId);
|
||||
identifier.setSequenceNumber(sequenceNum);
|
||||
LOG.info("Creating password for identifier: " + identifier);
|
||||
byte[] password = createPassword(identifier.getBytes(), currentKey.getKey());
|
||||
currentTokens.put(identifier, new DelegationTokenInformation(now
|
||||
+ tokenRenewInterval, password));
|
||||
|
|
|
@ -491,6 +491,9 @@ Release 2.0.1-alpha - UNRELEASED
|
|||
|
||||
HDFS-3837. Fix DataNode.recoverBlock findbugs warning. (eli)
|
||||
|
||||
HDFS-3835. Long-lived 2NN cannot perform a checkpoint if security is
|
||||
enabled and the NN restarts with outstanding delegation tokens. (atm)
|
||||
|
||||
BREAKDOWN OF HDFS-3042 SUBTASKS
|
||||
|
||||
HDFS-2185. HDFS portion of ZK-based FailoverController (todd)
|
||||
|
|
|
@ -536,6 +536,7 @@ public class FSImage implements Closeable {
|
|||
*/
|
||||
void reloadFromImageFile(File file, FSNamesystem target) throws IOException {
|
||||
target.dir.reset();
|
||||
target.dtSecretManager.reset();
|
||||
|
||||
LOG.debug("Reloading namespace from " + file);
|
||||
loadFSImage(file, target, null);
|
||||
|
|
|
@ -283,7 +283,7 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
|
|||
// Scan interval is not configurable.
|
||||
private static final long DELEGATION_TOKEN_REMOVER_SCAN_INTERVAL =
|
||||
TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS);
|
||||
private final DelegationTokenSecretManager dtSecretManager;
|
||||
final DelegationTokenSecretManager dtSecretManager;
|
||||
private final boolean alwaysUseDelegationTokensForTests;
|
||||
|
||||
|
||||
|
|
|
@ -376,6 +376,7 @@ public class SecondaryNameNode implements Runnable {
|
|||
downloadImage = false;
|
||||
LOG.info("Image has not changed. Will not download image.");
|
||||
} else {
|
||||
LOG.info("Image has changed. Downloading updated image from NN.");
|
||||
MD5Hash downloadedHash = TransferFsImage.downloadImageToStorage(
|
||||
nnHostPort, sig.mostRecentCheckpointTxId, dstImage.getStorage(), true);
|
||||
dstImage.saveDigestAndRenameCheckpointImage(
|
||||
|
|
|
@ -67,6 +67,7 @@ import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols;
|
|||
import org.apache.hadoop.hdfs.server.protocol.RemoteEditLog;
|
||||
import org.apache.hadoop.hdfs.server.protocol.RemoteEditLogManifest;
|
||||
import org.apache.hadoop.hdfs.tools.DFSAdmin;
|
||||
import org.apache.hadoop.io.Text;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
import org.apache.hadoop.test.GenericTestUtils;
|
||||
import org.apache.hadoop.test.GenericTestUtils.DelayAnswer;
|
||||
|
@ -1835,6 +1836,49 @@ public class TestCheckpoint {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Regression test for HDFS-3835 - "Long-lived 2NN cannot perform a
|
||||
* checkpoint if security is enabled and the NN restarts without outstanding
|
||||
* delegation tokens"
|
||||
*/
|
||||
@Test
|
||||
public void testSecondaryNameNodeWithDelegationTokens() throws IOException {
|
||||
MiniDFSCluster cluster = null;
|
||||
SecondaryNameNode secondary = null;
|
||||
|
||||
Configuration conf = new HdfsConfiguration();
|
||||
conf.setBoolean(
|
||||
DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_ALWAYS_USE_KEY, true);
|
||||
try {
|
||||
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(numDatanodes)
|
||||
.format(true).build();
|
||||
|
||||
assertNotNull(cluster.getNamesystem().getDelegationToken(new Text("atm")));
|
||||
|
||||
secondary = startSecondaryNameNode(conf);
|
||||
|
||||
// Checkpoint once, so the 2NN loads the DT into its in-memory sate.
|
||||
secondary.doCheckpoint();
|
||||
|
||||
// Perform a saveNamespace, so that the NN has a new fsimage, and the 2NN
|
||||
// therefore needs to download a new fsimage the next time it performs a
|
||||
// checkpoint.
|
||||
cluster.getNameNodeRpc().setSafeMode(SafeModeAction.SAFEMODE_ENTER);
|
||||
cluster.getNameNodeRpc().saveNamespace();
|
||||
cluster.getNameNodeRpc().setSafeMode(SafeModeAction.SAFEMODE_LEAVE);
|
||||
|
||||
// Ensure that the 2NN can still perform a checkpoint.
|
||||
secondary.doCheckpoint();
|
||||
} finally {
|
||||
if (secondary != null) {
|
||||
secondary.shutdown();
|
||||
}
|
||||
if (cluster != null) {
|
||||
cluster.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommandLineParsing() throws ParseException {
|
||||
SecondaryNameNode.CommandLineOpts opts =
|
||||
|
|
Loading…
Reference in New Issue