void readProperties(StorageDirectory sd, StartupOption startupOption) throws IOException { Properties props = readPropertiesFile(sd.getVersionFile()); if (HdfsServerConstants.RollingUpgradeStartupOption.ROLLBACK.matches (startupOption)) { int lv = Integer.parseInt(getProperty(props, sd, "layoutVersion")); if (lv > getServiceLayoutVersion()) { // we should not use a newer version for rollingUpgrade rollback throw new IncorrectVersionException(getServiceLayoutVersion(), lv, "storage directory " + sd.getRoot().getAbsolutePath()); } props.setProperty("layoutVersion", Integer.toString(HdfsConstants.NAMENODE_LAYOUT_VERSION)); } setFieldsFromProperties(props, sd); }
private void checkNNVersion(NamespaceInfo nsInfo) throws IncorrectVersionException { // build and layout versions should match String nnVersion = nsInfo.getSoftwareVersion(); String minimumNameNodeVersion = dnConf.getMinimumNameNodeVersion(); if (VersionUtil.compareVersions(nnVersion, minimumNameNodeVersion) < 0) { IncorrectVersionException ive = new IncorrectVersionException( minimumNameNodeVersion, nnVersion, "NameNode", "DataNode"); LOG.warn(ive.getMessage()); throw ive; } String dnVersion = VersionInfo.getVersion(); if (!nnVersion.equals(dnVersion)) { LOG.info("Reported NameNode version '" + nnVersion + "' does not match " + "DataNode version '" + dnVersion + "' but is within acceptable " + "limits. Note: This is normal during a rolling upgrade."); } }
/** * Ensure that during downgrade the NN fails to load a fsimage with newer * format. */ @Test(expected = IncorrectVersionException.class) public void testRejectNewFsImage() throws IOException { final Configuration conf = new Configuration(); MiniDFSCluster cluster = null; try { cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0).build(); cluster.waitActive(); DistributedFileSystem fs = cluster.getFileSystem(); fs.setSafeMode(SafeModeAction.SAFEMODE_ENTER); fs.saveNamespace(); fs.setSafeMode(SafeModeAction.SAFEMODE_LEAVE); NNStorage storage = spy(cluster.getNameNode().getFSImage().getStorage()); int futureVersion = NameNodeLayoutVersion.CURRENT_LAYOUT_VERSION - 1; doReturn(futureVersion).when(storage).getServiceLayoutVersion(); storage.writeAll(); cluster.restartNameNode(0, true, "-rollingUpgrade", "downgrade"); } finally { if (cluster != null) { cluster.shutdown(); } } }
@Test public void testSoftwareVersionDifferences() throws Exception { // We expect no exception to be thrown when the software versions match. assertEquals(VersionInfo.getVersion(), actor.retrieveNamespaceInfo().getSoftwareVersion()); // We expect no exception to be thrown when the min NN version is below the // reported NN version. doReturn("4.0.0").when(fakeNsInfo).getSoftwareVersion(); doReturn("3.0.0").when(mockDnConf).getMinimumNameNodeVersion(); assertEquals("4.0.0", actor.retrieveNamespaceInfo().getSoftwareVersion()); // When the NN reports a version that's too low, throw an exception. doReturn("3.0.0").when(fakeNsInfo).getSoftwareVersion(); doReturn("4.0.0").when(mockDnConf).getMinimumNameNodeVersion(); try { actor.retrieveNamespaceInfo(); fail("Should have thrown an exception for NN with too-low version"); } catch (IncorrectVersionException ive) { GenericTestUtils.assertExceptionContains( "The reported NameNode version is too low", ive); LOG.info("Got expected exception", ive); } }
void readProperties(StorageDirectory sd, StartupOption startupOption) throws IOException { Properties props = readPropertiesFile(sd.getVersionFile()); if (HdfsServerConstants.RollingUpgradeStartupOption.ROLLBACK.matches (startupOption)) { int lv = Integer.parseInt(getProperty(props, sd, "layoutVersion")); if (lv > getServiceLayoutVersion()) { // we should not use a newer version for rollingUpgrade rollback throw new IncorrectVersionException(getServiceLayoutVersion(), lv, "storage directory " + sd.getRoot().getAbsolutePath()); } props.setProperty("layoutVersion", Integer.toString(HdfsServerConstants.NAMENODE_LAYOUT_VERSION)); } setFieldsFromProperties(props, sd); }
void handleRegistrationError(RemoteException re, InetSocketAddress failedNode) { // If either the primary or standby NN throws these exceptions, this // datanode will exit. I think this is the right behaviour because // the excludes list on both namenode better be the same. String reClass = re.getClassName(); if (failedNode.equals(primaryAddr) && (UnregisteredDatanodeException.class.getName().equals(reClass) || DisallowedDatanodeException.class.getName().equals(reClass) || IncorrectVersionException.class.getName().equals(reClass)) ) { LOG.warn("Shut down this service: ", re); this.shouldServiceRun = false; } else { LOG.warn(re); } }
private void checkNNVersion(NamespaceInfo nsInfo) throws IncorrectVersionException { // build and layout versions should match String nnVersion = nsInfo.getSoftwareVersion(); String minimumNameNodeVersion = dnConf.getMinimumNameNodeVersion(); if (VersionUtil.compareVersions(nnVersion, minimumNameNodeVersion) < 0) { IncorrectVersionException ive = new IncorrectVersionException( minimumNameNodeVersion, nnVersion, "NameNode", "DataNode"); LOG.warn(ive.getMessage()); throw ive; } String dnVersion = VersionInfo.getVersion(); if (!nnVersion.equals(dnVersion)) { LOG.info("Reported NameNode version '" + nnVersion + "' does not match " + "DataNode version '" + dnVersion + "' but is within acceptable " + "limits. Note: This is normal during a rolling upgrade."); } if (HdfsConstants.LAYOUT_VERSION != nsInfo.getLayoutVersion()) { LOG.warn("DataNode and NameNode layout versions must be the same." + " Expected: "+ HdfsConstants.LAYOUT_VERSION + " actual "+ nsInfo.getLayoutVersion()); throw new IncorrectVersionException( nsInfo.getLayoutVersion(), "namenode"); } }
@Test public void testDifferentLayoutVersions() throws Exception { // We expect no exceptions to be thrown when the layout versions match. assertEquals(HdfsConstants.LAYOUT_VERSION, actor.retrieveNamespaceInfo().getLayoutVersion()); // We expect an exception to be thrown when the NN reports a layout version // different from that of the DN. doReturn(HdfsConstants.LAYOUT_VERSION * 1000).when(fakeNsInfo) .getLayoutVersion(); try { actor.retrieveNamespaceInfo(); fail("Should have failed to retrieve NS info from DN with bad layout version"); } catch (IncorrectVersionException ive) { GenericTestUtils.assertExceptionContains( "Unexpected version of namenode", ive); LOG.info("Got expected exception", ive); } }
@Test public void testSoftwareVersionDifferences() throws Exception { // We expect no exception to be thrown when the software versions match. assertEquals(VersionInfo.getVersion(), actor.retrieveNamespaceInfo().getSoftwareVersion()); // We expect no exception to be thrown when the min NN version is below the // reported NN version. doReturn("4.0.0").when(fakeNsInfo).getSoftwareVersion(); doReturn("3.0.0").when(mockDnConf).getMinimumNameNodeVersion(); assertEquals("4.0.0", actor.retrieveNamespaceInfo().getSoftwareVersion()); // When the NN reports a version that's too low, throw an exception. doReturn("3.0.0").when(fakeNsInfo).getSoftwareVersion(); doReturn("4.0.0").when(mockDnConf).getMinimumNameNodeVersion(); try { actor.retrieveNamespaceInfo(); fail("Should have thrown an exception for NN with too-low version"); } catch (IncorrectVersionException ive) { GenericTestUtils .assertExceptionContains("The reported NameNode version is too low", ive); LOG.info("Got expected exception", ive); } }
@Test public void testDifferentLayoutVersions() throws Exception { // We expect no exceptions to be thrown when the layout versions match. assertEquals(HdfsConstants.LAYOUT_VERSION, actor.retrieveNamespaceInfo().getLayoutVersion()); // We expect an exception to be thrown when the NN reports a layout version // different from that of the DN. doReturn(HdfsConstants.LAYOUT_VERSION * 1000).when(fakeNsInfo) .getLayoutVersion(); try { actor.retrieveNamespaceInfo(); fail( "Should have failed to retrieve NS info from DN with bad layout version"); } catch (IncorrectVersionException ive) { GenericTestUtils .assertExceptionContains("Unexpected version of namenode", ive); LOG.info("Got expected exception", ive); } }
@Override protected void setLayoutVersion(Properties props, StorageDirectory sd) throws IncorrectVersionException, InconsistentFSStateException { int lv = Integer.parseInt(getProperty(props, sd, "layoutVersion")); // For journal node, since it now does not decode but just scan through the // edits, it can handle edits with future version in most of the cases. // Thus currently we may skip the layoutVersion check here. layoutVersion = lv; }
@Override protected void _processEventIO(InjectionEventI event, Object... args) throws IOException { if (service == 1 && event == InjectionEvent.AVATARDATANODE_BEFORE_START_OFFERSERVICE1) { done = true; throw new RemoteException(IncorrectVersionException.class.getName(), "Unexpected data transfer protocol version"); } if (service == 2 && event == InjectionEvent.AVATARDATANODE_BEFORE_START_OFFERSERVICE2) { done = true; throw new RemoteException(IncorrectVersionException.class.getName(), "Unexpected data transfer protocol version"); } }
synchronized UpgradeCommand processUpgradeCommand(UpgradeCommand command ) throws IOException { NameNode.LOG.debug("\n Distributed upgrade for NameNode version " + getUpgradeVersion() + " to current LV " + FSConstants.LAYOUT_VERSION + " is processing upgrade command: " + command.getAction() + " status = " + getUpgradeStatus() + "%"); if(currentUpgrades == null) { NameNode.LOG.info("Ignoring upgrade command: " + command.getAction() + " version " + command.getVersion() + ". No distributed upgrades are currently running on the NameNode"); return null; } UpgradeObjectNamenode curUO = (UpgradeObjectNamenode)currentUpgrades.first(); if(command.getVersion() != curUO.getVersion()) throw new IncorrectVersionException(command.getVersion(), "UpgradeCommand", curUO.getVersion()); UpgradeCommand reply = curUO.processUpgradeCommand(command); if(curUO.getUpgradeStatus() < 100) { return reply; } // current upgrade is done curUO.completeUpgrade(); NameNode.LOG.info("\n Distributed upgrade for NameNode version " + curUO.getVersion() + " to current LV " + FSConstants.LAYOUT_VERSION + " is complete."); // proceede with the next one currentUpgrades.remove(curUO); if(currentUpgrades.isEmpty()) { // all upgrades are done completeUpgrade(); } else { // start next upgrade curUO = (UpgradeObjectNamenode)currentUpgrades.first(); this.broadcastCommand = curUO.startUpgrade(); } return reply; }