/** * Action before any real action of deleting namespace. * @param env MasterProcedureEnv * @throws IOException */ private void prepareDelete(final MasterProcedureEnv env) throws IOException { if (getTableNamespaceManager(env).doesNamespaceExist(namespaceName) == false) { throw new NamespaceNotFoundException(namespaceName); } if (NamespaceDescriptor.RESERVED_NAMESPACES.contains(namespaceName)) { throw new ConstraintException("Reserved namespace "+ namespaceName +" cannot be removed."); } int tableCount = 0; try { tableCount = env.getMasterServices().listTableDescriptorsByNamespace(namespaceName).size(); } catch (FileNotFoundException fnfe) { throw new NamespaceNotFoundException(namespaceName); } if (tableCount > 0) { throw new ConstraintException("Only empty namespaces can be removed. " + "Namespace "+ namespaceName + " has "+ tableCount +" tables"); } // This is used for rollback nsDescriptor = getTableNamespaceManager(env).get(namespaceName); }
@Test(timeout=60000) public void testModifyNamespaceWithInvalidRegionCount() throws Exception { final NamespaceDescriptor nsd = NamespaceDescriptor.create("testModifyNamespaceWithInvalidRegionCount").build(); final String nsKey = "hbase.namespace.quota.maxregions"; final String nsValue = "-1"; final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); createNamespaceForTesting(nsd); // Modify nsd.setConfiguration(nsKey, nsValue); long procId = procExec.submitProcedure( new ModifyNamespaceProcedure(procExec.getEnvironment(), nsd)); // Wait the completion ProcedureTestingUtility.waitProcedure(procExec, procId); Procedure<?> result = procExec.getResult(procId); assertTrue(result.isFailed()); LOG.debug("Modify namespace failed with exception: " + result.getException()); assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); }
@Test(timeout=60000) public void testModifyNamespaceWithInvalidTableCount() throws Exception { final NamespaceDescriptor nsd = NamespaceDescriptor.create("testModifyNamespaceWithInvalidTableCount").build(); final String nsKey = "hbase.namespace.quota.maxtables"; final String nsValue = "-1"; final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); createNamespaceForTesting(nsd); // Modify nsd.setConfiguration(nsKey, nsValue); long procId = procExec.submitProcedure( new ModifyNamespaceProcedure(procExec.getEnvironment(), nsd)); // Wait the completion ProcedureTestingUtility.waitProcedure(procExec, procId); Procedure<?> result = procExec.getResult(procId); assertTrue(result.isFailed()); LOG.debug("Modify namespace failed with exception: " + result.getException()); assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); }
@Test(timeout=60000) public void testCreateNamespaceWithInvalidRegionCount() throws Exception { final NamespaceDescriptor nsd = NamespaceDescriptor.create("testCreateNamespaceWithInvalidRegionCount").build(); final String nsKey = "hbase.namespace.quota.maxregions"; final String nsValue = "-1"; final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); nsd.setConfiguration(nsKey, nsValue); long procId = procExec.submitProcedure( new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); // Wait the completion ProcedureTestingUtility.waitProcedure(procExec, procId); Procedure<?> result = procExec.getResult(procId); assertTrue(result.isFailed()); LOG.debug("Create namespace failed with exception: " + result.getException()); assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); }
@Test(timeout=60000) public void testCreateNamespaceWithInvalidTableCount() throws Exception { final NamespaceDescriptor nsd = NamespaceDescriptor.create("testCreateNamespaceWithInvalidTableCount").build(); final String nsKey = "hbase.namespace.quota.maxtables"; final String nsValue = "-1"; final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); nsd.setConfiguration(nsKey, nsValue); long procId = procExec.submitProcedure( new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); // Wait the completion ProcedureTestingUtility.waitProcedure(procExec, procId); Procedure<?> result = procExec.getResult(procId); assertTrue(result.isFailed()); LOG.debug("Create namespace failed with exception: " + result.getException()); assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); }
@Test(timeout=60000) public void testDeleteNonEmptyNamespace() throws Exception { final String namespaceName = "testDeleteNonExistNamespace"; final TableName tableName = TableName.valueOf("testDeleteNonExistNamespace:" + name.getMethodName()); final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); // create namespace createNamespaceForTesting(namespaceName); // create the table under the new namespace MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1"); long procId = procExec.submitProcedure( new DeleteNamespaceProcedure(procExec.getEnvironment(), namespaceName)); // Wait the completion ProcedureTestingUtility.waitProcedure(procExec, procId); Procedure<?> result = procExec.getResult(procId); assertTrue(result.isFailed()); LOG.debug("Delete namespace failed with exception: " + result.getException()); assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); }
void assignTableToGroup(TableDescriptor desc) throws IOException { String groupName = master.getClusterSchema().getNamespace(desc.getTableName().getNamespaceAsString()) .getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); if (groupName == null) { groupName = RSGroupInfo.DEFAULT_GROUP; } RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName); if (rsGroupInfo == null) { throw new ConstraintException("Default RSGroup (" + groupName + ") for this table's " + "namespace does not exist."); } if (!rsGroupInfo.containsTable(desc.getTableName())) { LOG.debug("Pre-moving table " + desc.getTableName() + " to RSGroup " + groupName); groupAdminServer.moveTables(Sets.newHashSet(desc.getTableName()), groupName); } }
@Override public void removeServers(Set<Address> servers) throws IOException { { if (servers == null || servers.isEmpty()) { throw new ConstraintException("The set of servers to remove cannot be null or empty."); } // Hold a lock on the manager instance while moving servers to prevent // another writer changing our state while we are working. synchronized (rsGroupInfoManager) { if (master.getMasterCoprocessorHost() != null) { master.getMasterCoprocessorHost().preRemoveServers(servers); } //check the set of servers checkForDeadOrOnlineServers(servers); rsGroupInfoManager.removeServers(servers); if (master.getMasterCoprocessorHost() != null) { master.getMasterCoprocessorHost().postRemoveServers(servers); } LOG.info("Remove decommissioned servers " + servers + " from rsgroup done."); } } }
@Override public void preModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName, HTableDescriptor htd) throws IOException { if (!authorizationEnabled) { return; } if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); } }
@Override public void preAddColumn(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName, HColumnDescriptor column) throws IOException { if (!authorizationEnabled) { return; } if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); } }
@Override public void preModifyColumn(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName, HColumnDescriptor descriptor) throws IOException { if (!authorizationEnabled) { return; } if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); } }
@Override public void preDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName, byte[] c) throws IOException { if (!authorizationEnabled) { return; } if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); } }
@Override public void preDisableTable(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName) throws IOException { if (!authorizationEnabled) { return; } if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot disable " + LABELS_TABLE_NAME); } }
/** * Action before any real action of disabling table. Set the exception in the procedure instead * of throwing it. This approach is to deal with backward compatible with 1.0. * @param env MasterProcedureEnv * @throws HBaseException * @throws IOException */ private boolean prepareDisable(final MasterProcedureEnv env) throws HBaseException, IOException { boolean canTableBeDisabled = true; if (tableName.equals(TableName.META_TABLE_NAME)) { setFailure("master-disable-table", new ConstraintException("Cannot disable catalog table")); canTableBeDisabled = false; } else if (!MetaTableAccessor.tableExists(env.getMasterServices().getConnection(), tableName)) { setFailure("master-disable-table", new TableNotFoundException(tableName)); canTableBeDisabled = false; } else if (!skipTableStateCheck) { // There could be multiple client requests trying to disable or enable // the table at the same time. Ensure only the first request is honored // After that, no other requests can be accepted until the table reaches // DISABLED or ENABLED. // // Note: A quick state check should be enough for us to move forward. However, instead of // calling TableStateManager.isTableState() to just check the state, we called // TableStateManager.setTableStateIfInStates() to set the state to DISABLING from ENABLED. // This is because we treat empty state as enabled from 0.92-clusters. See // ZKTableStateManager.setTableStateIfInStates() that has a hack solution to work around // this issue. TableStateManager tsm = env.getMasterServices().getAssignmentManager().getTableStateManager(); if (!tsm.setTableStateIfInStates(tableName, ZooKeeperProtos.Table.State.DISABLING, ZooKeeperProtos.Table.State.DISABLING, ZooKeeperProtos.Table.State.ENABLED)) { LOG.info("Table " + tableName + " isn't enabled; skipping disable"); setFailure("master-disable-table", new TableNotEnabledException(tableName)); canTableBeDisabled = false; } } // We are done the check. Future actions in this procedure could be done asynchronously. ProcedurePrepareLatch.releaseLatch(syncLatch, this); return canTableBeDisabled; }
public synchronized void remove(String name) throws IOException { if (get(name) == null) { throw new NamespaceNotFoundException(name); } if (NamespaceDescriptor.RESERVED_NAMESPACES.contains(name)) { throw new ConstraintException("Reserved namespace "+name+" cannot be removed."); } int tableCount; try { tableCount = masterServices.listTableDescriptorsByNamespace(name).size(); } catch (FileNotFoundException fnfe) { throw new NamespaceNotFoundException(name); } if (tableCount > 0) { throw new ConstraintException("Only empty namespaces can be removed. " + "Namespace "+name+" has "+tableCount+" tables"); } Delete d = new Delete(Bytes.toBytes(name)); getNamespaceTable().delete(d); //don't abort if cleanup isn't complete //it will be replaced on new namespace creation zkNamespaceManager.remove(name); FileSystem fs = masterServices.getMasterFileSystem().getFileSystem(); for(FileStatus status : fs.listStatus(FSUtils.getNamespaceDir( masterServices.getMasterFileSystem().getRootDir(), name))) { if (!HConstants.HBASE_NON_TABLE_DIRS.contains(status.getPath().getName())) { throw new IOException("Namespace directory contains table dir: "+status.getPath()); } } if (!fs.delete(FSUtils.getNamespaceDir( masterServices.getMasterFileSystem().getRootDir(), name), true)) { throw new IOException("Failed to remove namespace: "+name); } this.masterServices.getMasterQuotaManager().removeNamespaceQuota(name); }
void validateTableAndRegionCount(NamespaceDescriptor desc) throws IOException { if (getMaxRegions(desc) <= 0) { throw new ConstraintException("The max region quota for " + desc.getName() + " is less than or equal to zero."); } if (getMaxTables(desc) <= 0) { throw new ConstraintException("The max tables quota for " + desc.getName() + " is less than or equal to zero."); } }
@Test (timeout=300000) public void testDisableCatalogTable() throws Exception { try { this.admin.disableTable(TableName.META_TABLE_NAME); fail("Expected to throw ConstraintException"); } catch (ConstraintException e) { } // Before the fix for HBASE-6146, the below table creation was failing as the hbase:meta table // actually getting disabled by the disableTable() call. HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("testDisableCatalogTable".getBytes())); HColumnDescriptor hcd = new HColumnDescriptor("cf1".getBytes()); htd.addFamily(hcd); TEST_UTIL.getHBaseAdmin().createTable(htd); }
@Override public void preModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName, HTableDescriptor htd) throws IOException { if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); } }
@Override public void preAddColumn(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName, HColumnDescriptor column) throws IOException { if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); } }
@Override public void preModifyColumn(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName, HColumnDescriptor descriptor) throws IOException { if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); } }
@Override public void preDeleteColumn(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName, byte[] c) throws IOException { if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); } }
@Override public void preDisableTable(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName) throws IOException { if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot disable " + LABELS_TABLE_NAME); } }
public synchronized void remove(String name) throws IOException { if (get(name) == null) { throw new NamespaceNotFoundException(name); } if (NamespaceDescriptor.RESERVED_NAMESPACES.contains(name)) { throw new ConstraintException("Reserved namespace "+name+" cannot be removed."); } int tableCount; try { tableCount = masterServices.listTableDescriptorsByNamespace(name).size(); } catch (FileNotFoundException fnfe) { throw new NamespaceNotFoundException(name); } if (tableCount > 0) { throw new ConstraintException("Only empty namespaces can be removed. " + "Namespace "+name+" has "+tableCount+" tables"); } Delete d = new Delete(Bytes.toBytes(name)); getNamespaceTable().delete(d); //don't abort if cleanup isn't complete //it will be replaced on new namespace creation zkNamespaceManager.remove(name); FileSystem fs = masterServices.getMasterFileSystem().getFileSystem(); for(FileStatus status : fs.listStatus(FSUtils.getNamespaceDir( masterServices.getMasterFileSystem().getRootDir(), name))) { if (!HConstants.HBASE_NON_TABLE_DIRS.contains(status.getPath().getName())) { throw new IOException("Namespace directory contains table dir: "+status.getPath()); } } if (!fs.delete(FSUtils.getNamespaceDir( masterServices.getMasterFileSystem().getRootDir(), name), true)) { throw new IOException("Failed to remove namespace: "+name); } }
@Override public void preModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx, TableName tableName, TableDescriptor htd) throws IOException { if (!authorizationEnabled) { return; } if (LABELS_TABLE_NAME.equals(tableName)) { throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); } }
/** * Action before any real action of disabling table. Set the exception in the procedure instead * of throwing it. This approach is to deal with backward compatible with 1.0. * @param env MasterProcedureEnv * @throws IOException */ private boolean prepareDisable(final MasterProcedureEnv env) throws IOException { boolean canTableBeDisabled = true; if (tableName.equals(TableName.META_TABLE_NAME)) { setFailure("master-disable-table", new ConstraintException("Cannot disable catalog table")); canTableBeDisabled = false; } else if (!MetaTableAccessor.tableExists(env.getMasterServices().getConnection(), tableName)) { setFailure("master-disable-table", new TableNotFoundException(tableName)); canTableBeDisabled = false; } else if (!skipTableStateCheck) { // There could be multiple client requests trying to disable or enable // the table at the same time. Ensure only the first request is honored // After that, no other requests can be accepted until the table reaches // DISABLED or ENABLED. // // Note: in 1.0 release, we called TableStateManager.setTableStateIfInStates() to set // the state to DISABLING from ENABLED. The implementation was done before table lock // was implemented. With table lock, there is no need to set the state here (it will // set the state later on). A quick state check should be enough for us to move forward. TableStateManager tsm = env.getMasterServices().getTableStateManager(); TableState.State state = tsm.getTableState(tableName); if (!state.equals(TableState.State.ENABLED)){ LOG.info("Table " + tableName + " isn't enabled;is "+state.name()+"; skipping disable"); setFailure("master-disable-table", new TableNotEnabledException( tableName+" state is "+state.name())); canTableBeDisabled = false; } } // We are done the check. Future actions in this procedure could be done asynchronously. releaseSyncLatch(); return canTableBeDisabled; }
public void validateTableAndRegionCount(NamespaceDescriptor desc) throws IOException { if (getMaxRegions(desc) <= 0) { throw new ConstraintException("The max region quota for " + desc.getName() + " is less than or equal to zero."); } if (getMaxTables(desc) <= 0) { throw new ConstraintException("The max tables quota for " + desc.getName() + " is less than or equal to zero."); } }
@Test (timeout=300000) public void testDisableCatalogTable() throws Exception { try { this.admin.disableTable(TableName.META_TABLE_NAME); fail("Expected to throw ConstraintException"); } catch (ConstraintException e) { } // Before the fix for HBASE-6146, the below table creation was failing as the hbase:meta table // actually getting disabled by the disableTable() call. HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(Bytes.toBytes(name.getMethodName()))); HColumnDescriptor hcd = new HColumnDescriptor(Bytes.toBytes("cf1")); htd.addFamily(hcd); TEST_UTIL.getHBaseAdmin().createTable(htd); }
@Test(timeout=60000) public void testDeleteSystemNamespace() throws Exception { final String namespaceName = NamespaceDescriptor.SYSTEM_NAMESPACE.getName(); final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); long procId = procExec.submitProcedure( new DeleteNamespaceProcedure(procExec.getEnvironment(), namespaceName)); // Wait the completion ProcedureTestingUtility.waitProcedure(procExec, procId); Procedure<?> result = procExec.getResult(procId); assertTrue(result.isFailed()); LOG.debug("Delete namespace failed with exception: " + result.getException()); assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); }
@Override public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx, NamespaceDescriptor ns) throws IOException { String group = ns.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); if(group != null && groupAdminServer.getRSGroupInfo(group) == null) { throw new ConstraintException("Region server group "+group+" does not exit"); } }
private void checkOnlineServersOnly(Set<Address> servers) throws ConstraintException { // This uglyness is because we only have Address, not ServerName. // Online servers are keyed by ServerName. Set<Address> onlineServers = new HashSet<>(); for(ServerName server: master.getServerManager().getOnlineServers().keySet()) { onlineServers.add(server.getAddress()); } for (Address address: servers) { if (!onlineServers.contains(address)) { throw new ConstraintException( "Server " + address + " is not an online server in 'default' RSGroup."); } } }
/** * Check passed name. Fail if nulls or if corresponding RSGroupInfo not found. * @return The RSGroupInfo named <code>name</code> */ private RSGroupInfo getAndCheckRSGroupInfo(String name) throws IOException { if (StringUtils.isEmpty(name)) { throw new ConstraintException("RSGroup cannot be null."); } RSGroupInfo rsGroupInfo = getRSGroupInfo(name); if (rsGroupInfo == null) { throw new ConstraintException("RSGroup does not exist: " + name); } return rsGroupInfo; }