001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.snapshot; 019 020import static org.junit.jupiter.api.Assertions.assertFalse; 021import static org.junit.jupiter.api.Assertions.assertTrue; 022import static org.junit.jupiter.api.Assertions.fail; 023 024import java.io.IOException; 025import java.net.URI; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.fs.FileSystem; 028import org.apache.hadoop.fs.Path; 029import org.apache.hadoop.hbase.HBaseConfiguration; 030import org.apache.hadoop.hbase.HBaseTestingUtil; 031import org.apache.hadoop.hbase.HConstants; 032import org.apache.hadoop.hbase.testclassification.RegionServerTests; 033import org.apache.hadoop.hbase.testclassification.SmallTests; 034import org.apache.hadoop.hbase.util.EnvironmentEdgeManagerTestHelper; 035import org.junit.jupiter.api.AfterEach; 036import org.junit.jupiter.api.BeforeAll; 037import org.junit.jupiter.api.Tag; 038import org.junit.jupiter.api.Test; 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription; 043 044/** 045 * Test that the {@link SnapshotDescription} helper is helping correctly. 046 */ 047@Tag(RegionServerTests.TAG) 048@Tag(SmallTests.TAG) 049public class TestSnapshotDescriptionUtils { 050 051 private static final HBaseTestingUtil UTIL = new HBaseTestingUtil(); 052 private static FileSystem fs; 053 private static Path root; 054 055 @BeforeAll 056 public static void setupFS() throws Exception { 057 fs = UTIL.getTestFileSystem(); 058 root = new Path(UTIL.getDataTestDir(), "hbase"); 059 } 060 061 @AfterEach 062 public void cleanupFS() throws Exception { 063 if (fs.exists(root)) { 064 if (!fs.delete(root, true)) { 065 throw new IOException("Failed to delete root test dir: " + root); 066 } 067 if (!fs.mkdirs(root)) { 068 throw new IOException("Failed to create root test dir: " + root); 069 } 070 } 071 EnvironmentEdgeManagerTestHelper.reset(); 072 } 073 074 private static final Logger LOG = LoggerFactory.getLogger(TestSnapshotDescriptionUtils.class); 075 076 @Test 077 public void testValidateMissingTableName() throws IOException { 078 Configuration conf = new Configuration(false); 079 try { 080 SnapshotDescriptionUtils.validate(SnapshotDescription.newBuilder().setName("fail").build(), 081 conf); 082 fail("Snapshot was considered valid without a table name"); 083 } catch (IllegalArgumentException e) { 084 LOG.debug("Correctly failed when snapshot doesn't have a tablename"); 085 } 086 } 087 088 /** 089 * Test that we throw an exception if there is no working snapshot directory when we attempt to 090 * 'complete' the snapshot 091 * @throws Exception on failure 092 */ 093 @Test 094 public void testCompleteSnapshotWithNoSnapshotDirectoryFailure() throws Exception { 095 Path snapshotDir = new Path(root, HConstants.SNAPSHOT_DIR_NAME); 096 Path tmpDir = new Path(snapshotDir, ".tmp"); 097 Path workingDir = new Path(tmpDir, "not_a_snapshot"); 098 Configuration conf = new Configuration(); 099 FileSystem workingFs = workingDir.getFileSystem(conf); 100 assertFalse(fs.exists(workingDir), 101 "Already have working snapshot dir: " + workingDir + " but shouldn't. Test file leak?"); 102 SnapshotDescription snapshot = SnapshotDescription.newBuilder().setName("snapshot").build(); 103 Path finishedDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshot, snapshotDir); 104 105 try { 106 SnapshotDescriptionUtils.completeSnapshot(finishedDir, workingDir, fs, workingFs, conf); 107 fail("Shouldn't successfully complete move of a non-existent directory."); 108 } catch (IOException e) { 109 LOG.info("Correctly failed to move non-existant directory: " + e.getMessage()); 110 } 111 } 112 113 @Test 114 public void testIsSubDirectoryWorks() { 115 Path rootDir = new Path("hdfs://root/.hbase-snapshot/"); 116 117 assertFalse(SnapshotDescriptionUtils.isSubDirectoryOf(rootDir, rootDir)); 118 assertFalse(SnapshotDescriptionUtils 119 .isSubDirectoryOf(new Path("hdfs://root/.hbase-snapshotdir"), rootDir)); 120 assertFalse( 121 SnapshotDescriptionUtils.isSubDirectoryOf(new Path("hdfs://root/.hbase-snapshot"), rootDir)); 122 assertFalse( 123 SnapshotDescriptionUtils.isSubDirectoryOf(new Path("hdfs://.hbase-snapshot"), rootDir)); 124 assertFalse( 125 SnapshotDescriptionUtils.isSubDirectoryOf(new Path("hdfs://.hbase-snapshot/.tmp"), rootDir)); 126 assertFalse(SnapshotDescriptionUtils.isSubDirectoryOf(new Path("hdfs://root"), rootDir)); 127 assertTrue(SnapshotDescriptionUtils 128 .isSubDirectoryOf(new Path("hdfs://root/.hbase-snapshot/.tmp"), rootDir)); 129 assertTrue(SnapshotDescriptionUtils 130 .isSubDirectoryOf(new Path("hdfs://root/.hbase-snapshot/.tmp/snapshot"), rootDir)); 131 132 assertFalse( 133 SnapshotDescriptionUtils.isSubDirectoryOf(new Path("s3://root/.hbase-snapshot/"), rootDir)); 134 assertFalse(SnapshotDescriptionUtils.isSubDirectoryOf(new Path("s3://root"), rootDir)); 135 assertFalse(SnapshotDescriptionUtils 136 .isSubDirectoryOf(new Path("s3://root/.hbase-snapshot/.tmp/snapshot"), rootDir)); 137 } 138 139 @Test 140 public void testIsWithinWorkingDir() throws IOException { 141 Configuration conf = new Configuration(); 142 conf.set(HConstants.HBASE_DIR, "hdfs://localhost/root/"); 143 144 assertFalse( 145 SnapshotDescriptionUtils.isWithinDefaultWorkingDir(new Path("hdfs://localhost/root/"), conf)); 146 assertFalse(SnapshotDescriptionUtils 147 .isWithinDefaultWorkingDir(new Path("hdfs://localhost/root/.hbase-snapshotdir"), conf)); 148 assertFalse(SnapshotDescriptionUtils 149 .isWithinDefaultWorkingDir(new Path("hdfs://localhost/root/.hbase-snapshot"), conf)); 150 assertFalse(SnapshotDescriptionUtils 151 .isWithinDefaultWorkingDir(new Path("hdfs://localhost/.hbase-snapshot"), conf)); 152 assertFalse(SnapshotDescriptionUtils 153 .isWithinDefaultWorkingDir(new Path("hdfs://localhost/.hbase-snapshot/.tmp"), conf)); 154 assertFalse( 155 SnapshotDescriptionUtils.isWithinDefaultWorkingDir(new Path("hdfs://localhost/root"), conf)); 156 assertTrue(SnapshotDescriptionUtils 157 .isWithinDefaultWorkingDir(new Path("hdfs://localhost/root/.hbase-snapshot/.tmp"), conf)); 158 assertTrue(SnapshotDescriptionUtils.isWithinDefaultWorkingDir( 159 new Path("hdfs://localhost/root/.hbase-snapshot/.tmp/snapshot"), conf)); 160 161 assertFalse(SnapshotDescriptionUtils 162 .isWithinDefaultWorkingDir(new Path("s3://localhost/root/.hbase-snapshot/"), conf)); 163 assertFalse( 164 SnapshotDescriptionUtils.isWithinDefaultWorkingDir(new Path("s3://localhost/root"), conf)); 165 assertFalse(SnapshotDescriptionUtils.isWithinDefaultWorkingDir( 166 new Path("s3://localhost/root/.hbase-snapshot/.tmp/snapshot"), conf)); 167 168 // for local mode 169 conf = HBaseConfiguration.create(); 170 String hbsaeDir = conf.get(HConstants.HBASE_DIR); 171 172 assertFalse( 173 SnapshotDescriptionUtils.isWithinDefaultWorkingDir(new Path("file:" + hbsaeDir + "/"), conf)); 174 assertFalse(SnapshotDescriptionUtils 175 .isWithinDefaultWorkingDir(new Path("file:" + hbsaeDir + "/.hbase-snapshotdir"), conf)); 176 assertFalse(SnapshotDescriptionUtils 177 .isWithinDefaultWorkingDir(new Path("file:" + hbsaeDir + "/.hbase-snapshot"), conf)); 178 assertFalse( 179 SnapshotDescriptionUtils.isWithinDefaultWorkingDir(new Path("file:/.hbase-snapshot"), conf)); 180 assertFalse(SnapshotDescriptionUtils 181 .isWithinDefaultWorkingDir(new Path("file:/.hbase-snapshot/.tmp"), conf)); 182 assertFalse( 183 SnapshotDescriptionUtils.isWithinDefaultWorkingDir(new Path("file:" + hbsaeDir), conf)); 184 assertTrue(SnapshotDescriptionUtils 185 .isWithinDefaultWorkingDir(new Path("file:" + hbsaeDir + "/.hbase-snapshot/.tmp"), conf)); 186 assertTrue(SnapshotDescriptionUtils.isWithinDefaultWorkingDir( 187 new Path("file:" + hbsaeDir + "/.hbase-snapshot/.tmp/snapshot"), conf)); 188 } 189 190 @Test 191 public void testShouldSkipRenameSnapshotDirectories() { 192 URI workingDirURI = URI.create("/User/test1"); 193 URI rootDirURI = URI.create("hdfs:///User/test2"); 194 195 // should skip rename if it's not the same scheme; 196 assertTrue( 197 SnapshotDescriptionUtils.shouldSkipRenameSnapshotDirectories(workingDirURI, rootDirURI)); 198 199 workingDirURI = URI.create("/User/test1"); 200 rootDirURI = URI.create("file:///User/test2"); 201 assertTrue( 202 SnapshotDescriptionUtils.shouldSkipRenameSnapshotDirectories(workingDirURI, rootDirURI)); 203 204 // skip rename when either scheme or authority are the not same 205 workingDirURI = URI.create("hdfs://localhost:8020/User/test1"); 206 rootDirURI = URI.create("hdfs://otherhost:8020/User/test2"); 207 assertTrue( 208 SnapshotDescriptionUtils.shouldSkipRenameSnapshotDirectories(workingDirURI, rootDirURI)); 209 210 workingDirURI = URI.create("file:///User/test1"); 211 rootDirURI = URI.create("hdfs://localhost:8020/User/test2"); 212 assertTrue( 213 SnapshotDescriptionUtils.shouldSkipRenameSnapshotDirectories(workingDirURI, rootDirURI)); 214 215 workingDirURI = URI.create("hdfs:///User/test1"); 216 rootDirURI = URI.create("hdfs:///User/test2"); 217 assertFalse( 218 SnapshotDescriptionUtils.shouldSkipRenameSnapshotDirectories(workingDirURI, rootDirURI)); 219 220 workingDirURI = URI.create("hdfs://localhost:8020/User/test1"); 221 rootDirURI = URI.create("hdfs://localhost:8020/User/test2"); 222 assertFalse( 223 SnapshotDescriptionUtils.shouldSkipRenameSnapshotDirectories(workingDirURI, rootDirURI)); 224 225 workingDirURI = URI.create("hdfs://user:password@localhost:8020/User/test1"); 226 rootDirURI = URI.create("hdfs://user:password@localhost:8020/User/test2"); 227 assertFalse( 228 SnapshotDescriptionUtils.shouldSkipRenameSnapshotDirectories(workingDirURI, rootDirURI)); 229 230 // skip rename when user information is not the same 231 workingDirURI = URI.create("hdfs://user:password@localhost:8020/User/test1"); 232 rootDirURI = URI.create("hdfs://user2:password2@localhost:8020/User/test2"); 233 assertTrue( 234 SnapshotDescriptionUtils.shouldSkipRenameSnapshotDirectories(workingDirURI, rootDirURI)); 235 } 236 237}