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.master.procedure; 019 020import static org.junit.Assert.assertNotNull; 021import static org.junit.Assert.assertNull; 022import static org.junit.Assert.assertTrue; 023 024import java.io.IOException; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.HBaseClassTestRule; 027import org.apache.hadoop.hbase.HBaseTestingUtil; 028import org.apache.hadoop.hbase.NamespaceDescriptor; 029import org.apache.hadoop.hbase.NamespaceExistException; 030import org.apache.hadoop.hbase.NamespaceNotFoundException; 031import org.apache.hadoop.hbase.constraint.ConstraintException; 032import org.apache.hadoop.hbase.procedure2.Procedure; 033import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; 034import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility; 035import org.apache.hadoop.hbase.testclassification.MasterTests; 036import org.apache.hadoop.hbase.testclassification.MediumTests; 037import org.junit.After; 038import org.junit.AfterClass; 039import org.junit.Before; 040import org.junit.BeforeClass; 041import org.junit.ClassRule; 042import org.junit.Test; 043import org.junit.experimental.categories.Category; 044import org.slf4j.Logger; 045import org.slf4j.LoggerFactory; 046 047@Category({ MasterTests.class, MediumTests.class }) 048public class TestCreateNamespaceProcedure { 049 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestCreateNamespaceProcedure.class); 053 054 private static final Logger LOG = LoggerFactory.getLogger(TestCreateNamespaceProcedure.class); 055 056 protected static final HBaseTestingUtil UTIL = new HBaseTestingUtil(); 057 058 private static void setupConf(Configuration conf) { 059 conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1); 060 } 061 062 @BeforeClass 063 public static void setupCluster() throws Exception { 064 setupConf(UTIL.getConfiguration()); 065 UTIL.startMiniCluster(1); 066 } 067 068 @AfterClass 069 public static void cleanupTest() throws Exception { 070 try { 071 UTIL.shutdownMiniCluster(); 072 } catch (Exception e) { 073 LOG.warn("failure shutting down cluster", e); 074 } 075 } 076 077 @Before 078 public void setup() throws Exception { 079 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false); 080 } 081 082 @After 083 public void tearDown() throws Exception { 084 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false); 085 } 086 087 @Test 088 public void testCreateNamespace() throws Exception { 089 final NamespaceDescriptor nsd = NamespaceDescriptor.create("testCreateNamespace").build(); 090 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 091 092 long procId = 093 procExec.submitProcedure(new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 094 // Wait the completion 095 ProcedureTestingUtility.waitProcedure(procExec, procId); 096 ProcedureTestingUtility.assertProcNotFailed(procExec, procId); 097 098 validateNamespaceCreated(nsd); 099 } 100 101 @Test 102 public void testCreateSameNamespaceTwice() throws Exception { 103 final NamespaceDescriptor nsd = 104 NamespaceDescriptor.create("testCreateSameNamespaceTwice").build(); 105 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 106 107 long procId1 = 108 procExec.submitProcedure(new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 109 // Wait the completion 110 ProcedureTestingUtility.waitProcedure(procExec, procId1); 111 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1); 112 113 // Create the namespace that exists 114 long procId2 = 115 procExec.submitProcedure(new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 116 // Wait the completion 117 ProcedureTestingUtility.waitProcedure(procExec, procId2); 118 119 // Second create should fail with NamespaceExistException 120 Procedure<?> result = procExec.getResult(procId2); 121 assertTrue(result.isFailed()); 122 LOG.debug("Create namespace failed with exception: " + result.getException()); 123 assertTrue( 124 ProcedureTestingUtility.getExceptionCause(result) instanceof NamespaceExistException); 125 } 126 127 @Test 128 public void testCreateSystemNamespace() throws Exception { 129 final NamespaceDescriptor nsd = 130 UTIL.getAdmin().getNamespaceDescriptor(NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 131 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 132 133 long procId = 134 procExec.submitProcedure(new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 135 // Wait the completion 136 ProcedureTestingUtility.waitProcedure(procExec, procId); 137 Procedure<?> result = procExec.getResult(procId); 138 assertTrue(result.isFailed()); 139 LOG.debug("Create namespace failed with exception: " + result.getException()); 140 assertTrue( 141 ProcedureTestingUtility.getExceptionCause(result) instanceof NamespaceExistException); 142 } 143 144 @Test 145 public void testCreateNamespaceWithInvalidRegionCount() throws Exception { 146 final NamespaceDescriptor nsd = 147 NamespaceDescriptor.create("testCreateNamespaceWithInvalidRegionCount").build(); 148 final String nsKey = "hbase.namespace.quota.maxregions"; 149 final String nsValue = "-1"; 150 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 151 152 nsd.setConfiguration(nsKey, nsValue); 153 154 long procId = 155 procExec.submitProcedure(new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 156 // Wait the completion 157 ProcedureTestingUtility.waitProcedure(procExec, procId); 158 Procedure<?> result = procExec.getResult(procId); 159 assertTrue(result.isFailed()); 160 LOG.debug("Create namespace failed with exception: " + result.getException()); 161 assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); 162 } 163 164 @Test 165 public void testCreateNamespaceWithInvalidTableCount() throws Exception { 166 final NamespaceDescriptor nsd = 167 NamespaceDescriptor.create("testCreateNamespaceWithInvalidTableCount").build(); 168 final String nsKey = "hbase.namespace.quota.maxtables"; 169 final String nsValue = "-1"; 170 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 171 172 nsd.setConfiguration(nsKey, nsValue); 173 174 long procId = 175 procExec.submitProcedure(new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 176 // Wait the completion 177 ProcedureTestingUtility.waitProcedure(procExec, procId); 178 Procedure<?> result = procExec.getResult(procId); 179 assertTrue(result.isFailed()); 180 LOG.debug("Create namespace failed with exception: " + result.getException()); 181 assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); 182 } 183 184 @Test 185 public void testRecoveryAndDoubleExecution() throws Exception { 186 final NamespaceDescriptor nsd = 187 NamespaceDescriptor.create("testRecoveryAndDoubleExecution").build(); 188 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 189 190 ProcedureTestingUtility.waitNoProcedureRunning(procExec); 191 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); 192 193 // Start the CreateNamespace procedure && kill the executor 194 long procId = 195 procExec.submitProcedure(new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 196 197 // Restart the executor and execute the step twice 198 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId); 199 200 // Validate the creation of namespace 201 ProcedureTestingUtility.assertProcNotFailed(procExec, procId); 202 validateNamespaceCreated(nsd); 203 } 204 205 @Test 206 public void testRollbackAndDoubleExecution() throws Exception { 207 final NamespaceDescriptor nsd = 208 NamespaceDescriptor.create("testRollbackAndDoubleExecution").build(); 209 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 210 211 ProcedureTestingUtility.waitNoProcedureRunning(procExec); 212 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); 213 214 // Start the CreateNamespace procedure && kill the executor 215 long procId = 216 procExec.submitProcedure(new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 217 218 int lastStep = 2; // failing before CREATE_NAMESPACE_CREATE_DIRECTORY 219 MasterProcedureTestingUtility.testRollbackAndDoubleExecution(procExec, procId, lastStep); 220 221 // Validate the non-existence of namespace 222 try { 223 NamespaceDescriptor nsDescriptor = UTIL.getAdmin().getNamespaceDescriptor(nsd.getName()); 224 assertNull(nsDescriptor); 225 } catch (NamespaceNotFoundException nsnfe) { 226 // Expected 227 LOG.info("The namespace " + nsd.getName() + " is not created."); 228 } 229 } 230 231 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() { 232 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(); 233 } 234 235 private void validateNamespaceCreated(NamespaceDescriptor nsd) throws IOException { 236 NamespaceDescriptor createdNsDescriptor = UTIL.getAdmin().getNamespaceDescriptor(nsd.getName()); 237 assertNotNull(createdNsDescriptor); 238 } 239}