@Override
  protected Flow executeFromState(MasterProcedureEnv env, ModifyTableDescriptorState state)
    throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {
    try {
      switch (state) {
        case MODIFY_TABLE_DESCRIPTOR_PREPARE:
          TableDescriptor current = env.getMasterServices().getTableDescriptors().get(tableName);
          if (current == null) {
            LOG.info("Table {} does not exist, skip modifying", tableName);
            return Flow.NO_MORE_STATE;
          }
          Optional<TableDescriptor> modified = modify(env, current);
          if (modified.isPresent()) {
            modifiedTableDescriptor = modified.get();
            setNextState(ModifyTableDescriptorState.MODIFY_TABLE_DESCRIPTOR_UPDATE);
            return Flow.HAS_MORE_STATE;
          } else {
            // do not need to modify
            return Flow.NO_MORE_STATE;
          }
        case MODIFY_TABLE_DESCRIPTOR_UPDATE:
          env.getMasterServices().getTableDescriptors().update(modifiedTableDescriptor);
          return Flow.NO_MORE_STATE;
        default:
          throw new UnsupportedOperationException("unhandled state=" + state);
      }
    } catch (IOException e) {
      if (isRollbackSupported(state)) {
        setFailure("master-modify-table-descriptor", e);
      } else {
        LOG.warn("Retriable error trying to modify table descriptor={} (in state={})",
          getTableName(), state, e);
      }
    }
    return Flow.HAS_MORE_STATE;
  }
Sub class should implement this method to modify the table descriptor, such as storing the rs
group information.
<p/>
Since the migrating is asynchronouns, it is possible that users have already changed the rs
group for a table, in this case we do not need to modify the table descriptor any more, then
you could just return {@link Optional#empty()}.
hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ModifyTableDescriptorProcedure.java