diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java index 7806b352575..18655687e0f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java @@ -423,23 +423,29 @@ public abstract class FSUtils extends CommonFSUtils { boolean message, int wait, int retries) throws IOException, DeserializationException { String version = getVersion(fs, rootdir); + String msg; if (version == null) { if (!metaRegionExists(fs, rootdir)) { // rootDir is empty (no version file and no root region) // just create new version file (HBASE-1195) setVersion(fs, rootdir, wait, retries); return; + } else { + msg = "hbase.version file is missing. Is your hbase.rootdir valid? " + + "You can restore hbase.version file by running 'HBCK2 filesystem -fix'. " + + "See https://github.com/apache/hbase-operator-tools/tree/master/hbase-hbck2"; } - } else if (version.compareTo(HConstants.FILE_SYSTEM_VERSION) == 0) return; + } else if (version.compareTo(HConstants.FILE_SYSTEM_VERSION) == 0) { + return; + } else { + msg = "HBase file layout needs to be upgraded. Current filesystem version is " + version + + " but software requires version " + HConstants.FILE_SYSTEM_VERSION + + ". Consult http://hbase.apache.org/book.html for further information about " + + "upgrading HBase."; + } // version is deprecated require migration // Output on stdout so user sees it in terminal. - String msg = "HBase file layout needs to be upgraded." - + " You have version " + version - + " and I want version " + HConstants.FILE_SYSTEM_VERSION - + ". Consult http://hbase.apache.org/book.html for further information about upgrading HBase." - + " Is your hbase.rootdir valid? If so, you may need to run " - + "'hbase hbck -fixVersionFile'."; if (message) { System.out.println("WARNING! " + msg); } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestFSUtils.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestFSUtils.java index c5863f7033a..1296c4723db 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestFSUtils.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestFSUtils.java @@ -39,6 +39,7 @@ import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HDFSBlocksDistribution; +import org.apache.hadoop.hbase.client.RegionInfoBuilder; import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.fs.HFileSystem; import org.apache.hadoop.hbase.testclassification.MediumTests; @@ -201,18 +202,43 @@ public class TestFSUtils { } } + private void writeVersionFile(Path versionFile, String version) throws IOException { + if (FSUtils.isExists(fs, versionFile)) { + assertTrue(FSUtils.delete(fs, versionFile, true)); + } + try (FSDataOutputStream s = fs.create(versionFile)) { + s.writeUTF(version); + } + assertTrue(fs.exists(versionFile)); + } + @Test public void testVersion() throws DeserializationException, IOException { final Path rootdir = htu.getDataTestDir(); final FileSystem fs = rootdir.getFileSystem(conf); assertNull(FSUtils.getVersion(fs, rootdir)); - // Write out old format version file. See if we can read it in and convert. + // No meta dir so no complaint from checkVersion. + // Presumes it a new install. Will create version file. + FSUtils.checkVersion(fs, rootdir, true); + // Now remove the version file and create a metadir so checkVersion fails. Path versionFile = new Path(rootdir, HConstants.VERSION_FILE_NAME); - FSDataOutputStream s = fs.create(versionFile); - final String version = HConstants.FILE_SYSTEM_VERSION; - s.writeUTF(version); - s.close(); - assertTrue(fs.exists(versionFile)); + assertTrue(FSUtils.isExists(fs, versionFile)); + assertTrue(FSUtils.delete(fs, versionFile, true)); + Path metaRegionDir = + FSUtils.getRegionDirFromRootDir(rootdir, RegionInfoBuilder.FIRST_META_REGIONINFO); + FsPermission defaultPerms = FSUtils.getFilePermissions(fs, this.conf, + HConstants.DATA_FILE_UMASK_KEY); + FSUtils.create(fs, metaRegionDir, defaultPerms, false); + boolean thrown = false; + try { + FSUtils.checkVersion(fs, rootdir, true); + } catch (FileSystemVersionException e) { + thrown = true; + } + assertTrue("Expected FileSystemVersionException", thrown); + // Write out a good version file. See if we can read it in and convert. + String version = HConstants.FILE_SYSTEM_VERSION; + writeVersionFile(versionFile, version); FileStatus [] status = fs.listStatus(versionFile); assertNotNull(status); assertTrue(status.length > 0); @@ -222,6 +248,18 @@ public class TestFSUtils { // File will have been converted. Exercise the pb format assertEquals(version, FSUtils.getVersion(fs, rootdir)); FSUtils.checkVersion(fs, rootdir, true); + // Write an old version file. + String oldVersion = "1"; + writeVersionFile(versionFile, oldVersion); + newVersion = FSUtils.getVersion(fs, rootdir); + assertNotEquals(version, newVersion); + thrown = false; + try { + FSUtils.checkVersion(fs, rootdir, true); + } catch (FileSystemVersionException e) { + thrown = true; + } + assertTrue("Expected FileSystemVersionException", thrown); } @Test