@Override
  public void registerRemoteHost(
      final String hostName,
      final ManagementChannelHandler handler,
      final Transformers transformers,
      Long remoteConnectionId,
      DomainControllerRuntimeIgnoreTransformationEntry runtimeIgnoreTransformation)
      throws SlaveRegistrationException {
    if (!hostControllerInfo.isMasterDomainController()) {
      throw SlaveRegistrationException.forHostIsNotMaster();
    }

    if (runningModeControl.getRunningMode() == RunningMode.ADMIN_ONLY) {
      throw SlaveRegistrationException.forMasterInAdminOnlyMode(
          runningModeControl.getRunningMode());
    }

    final PathElement pe = PathElement.pathElement(ModelDescriptionConstants.HOST, hostName);
    final PathAddress addr = PathAddress.pathAddress(pe);
    ProxyController existingController = modelNodeRegistration.getProxyController(addr);

    if (existingController != null || hostControllerInfo.getLocalHostName().equals(pe.getValue())) {
      throw SlaveRegistrationException.forHostAlreadyExists(pe.getValue());
    }

    SlaveHostPinger pinger =
        remoteConnectionId == null
            ? null
            : new SlaveHostPinger(hostName, handler, pingScheduler, remoteConnectionId);
    hostRegistrationMap.put(hostName, new HostRegistration(remoteConnectionId, handler, pinger));

    // Create the proxy controller
    final TransformingProxyController hostControllerClient =
        TransformingProxyController.Factory.create(
            handler, transformers, addr, ProxyOperationAddressTranslator.HOST);

    modelNodeRegistration.registerProxyController(pe, hostControllerClient);
    runtimeIgnoreTransformationRegistry.registerHost(hostName, runtimeIgnoreTransformation);
    hostProxies.put(hostName, hostControllerClient);
    //        if (pinger != null) {
    //            pinger.schedulePing(SlaveHostPinger.STD_TIMEOUT, SlaveHostPinger.STD_INTERVAL);
    //        }
  }
  // See superclass start. This method is invoked from a separate non-MSC thread after start. So we
  // can do a fair
  // bit of stuff
  @Override
  protected void boot(final BootContext context) throws ConfigurationPersistenceException {

    final ServiceTarget serviceTarget = context.getServiceTarget();
    boolean ok = false;
    boolean reachedServers = false;
    try {
      // Install server inventory callback
      ServerInventoryCallbackService.install(serviceTarget);

      // Parse the host.xml and invoke all the ops. The ops should rollback on any Stage.RUNTIME
      // failure
      // We run the first op ("add-host") separately to let it set up the host
      // ManagementResourceRegistration
      List<ModelNode> hostBootOps = hostControllerConfigurationPersister.load();
      ModelNode addHostOp = hostBootOps.remove(0);
      ok = boot(Collections.singletonList(addHostOp), true);
      ok = ok && boot(hostBootOps, true);

      final RunningMode currentRunningMode = runningModeControl.getRunningMode();

      if (ok) {

        // Now we know our discovery configuration.
        List<DiscoveryOption> discoveryOptions =
            hostControllerInfo.getRemoteDomainControllerDiscoveryOptions();
        if (hostControllerInfo.isMasterDomainController() && (discoveryOptions != null)) {
          // Install the discovery service
          DiscoveryService.install(
              serviceTarget,
              discoveryOptions,
              hostControllerInfo.getNativeManagementInterface(),
              hostControllerInfo.getNativeManagementPort(),
              hostControllerInfo.isMasterDomainController());
        }

        // Now we know our management interface configuration. Install the server inventory
        Future<ServerInventory> inventoryFuture =
            ServerInventoryService.install(
                serviceTarget,
                this,
                runningModeControl,
                environment,
                extensionRegistry,
                hostControllerInfo.getNativeManagementInterface(),
                hostControllerInfo.getNativeManagementPort());

        if (!hostControllerInfo.isMasterDomainController() && !environment.isUseCachedDc()) {
          serverInventory = getFuture(inventoryFuture);

          if ((discoveryOptions != null) && !discoveryOptions.isEmpty()) {
            Future<MasterDomainControllerClient> clientFuture =
                RemoteDomainConnectionService.install(
                    serviceTarget,
                    getValue(),
                    extensionRegistry,
                    hostControllerInfo,
                    environment.getProductConfig(),
                    hostControllerInfo.getRemoteDomainControllerSecurityRealm(),
                    remoteFileRepository,
                    ignoredRegistry,
                    new InternalExecutor(),
                    this,
                    environment);
            MasterDomainControllerClient masterDomainControllerClient = getFuture(clientFuture);
            // Registers us with the master and gets down the master copy of the domain model to our
            // DC
            // TODO make sure that the RDCS checks env.isUseCachedDC, and if true falls through to
            // that
            // BES 2012/02/04 Comment ^^^ implies the semantic is to use isUseCachedDC as a fallback
            // to
            // a failure to connect as opposed to being an instruction to not connect at all. I
            // believe
            // the current impl is the latter. Don't change this without a discussion first, as the
            // current semantic is a reasonable one.
            try {
              masterDomainControllerClient.register();
            } catch (Exception e) {
              // We could not connect to the host
              ROOT_LOGGER.cannotConnectToMaster(e);
              System.exit(ExitCodes.HOST_CONTROLLER_ABORT_EXIT_CODE);
            }
          } else if (currentRunningMode != RunningMode.ADMIN_ONLY) {
            // Invalid configuration; no way to get the domain config
            ROOT_LOGGER.noDomainControllerConfigurationProvided(
                currentRunningMode, CommandLineConstants.ADMIN_ONLY, RunningMode.ADMIN_ONLY);
            System.exit(ExitCodes.HOST_CONTROLLER_ABORT_EXIT_CODE);
          }

        } else {

          if (environment.isUseCachedDc()) {
            remoteFileRepository.setRemoteFileRepositoryExecutor(
                new RemoteDomainConnectionService.RemoteFileRepositoryExecutor() {
                  @Override
                  public File getFile(
                      String relativePath, byte repoId, HostFileRepository localFileRepository) {
                    return localFileRepository.getFile(relativePath);
                  }
                });
          }

          // parse the domain.xml and load the steps
          // TODO look at having LocalDomainControllerAdd do this, using Stage.IMMEDIATE for the
          // steps
          ConfigurationPersister domainPersister =
              hostControllerConfigurationPersister.getDomainPersister();
          ok = boot(domainPersister.load(), false);

          if (!ok && runningModeControl.getRunningMode().equals(RunningMode.ADMIN_ONLY)) {
            ROOT_LOGGER.reportAdminOnlyDomainXmlFailure();
            ok = true;
          }

          if (ok) {
            InternalExecutor executor = new InternalExecutor();
            ManagementRemotingServices.installManagementChannelServices(
                serviceTarget,
                ManagementRemotingServices.MANAGEMENT_ENDPOINT,
                new MasterDomainControllerOperationHandlerService(
                    this, executor, executor, runtimeIgnoreTransformationRegistry),
                DomainModelControllerService.SERVICE_NAME,
                ManagementRemotingServices.DOMAIN_CHANNEL,
                null,
                null);
            serverInventory = getFuture(inventoryFuture);
          }
        }
      }

      if (ok) {
        // Install the server > host operation handler
        ServerToHostOperationHandlerFactoryService.install(
            serviceTarget,
            ServerInventoryService.SERVICE_NAME,
            proxyExecutor,
            new InternalExecutor(),
            this,
            expressionResolver);

        // demand native mgmt services
        serviceTarget
            .addService(ServiceName.JBOSS.append("native-mgmt-startup"), Service.NULL)
            .addDependency(
                ManagementRemotingServices.channelServiceName(
                    ManagementRemotingServices.MANAGEMENT_ENDPOINT,
                    ManagementRemotingServices.SERVER_CHANNEL))
            .setInitialMode(ServiceController.Mode.ACTIVE)
            .install();

        // demand http mgmt services
        serviceTarget
            .addService(ServiceName.JBOSS.append("http-mgmt-startup"), Service.NULL)
            .addDependency(
                ServiceBuilder.DependencyType.OPTIONAL, _UndertowHttpManagementService.SERVICE_NAME)
            .setInitialMode(ServiceController.Mode.ACTIVE)
            .install();

        reachedServers = true;
        if (currentRunningMode == RunningMode.NORMAL) {
          startServers();
        }
      }

    } catch (Exception e) {
      ROOT_LOGGER.caughtExceptionDuringBoot(e);
      if (!reachedServers) {
        ok = false;
      }
    } finally {
      if (ok) {
        try {
          finishBoot();
        } finally {
          // Trigger the started message
          bootstrapListener.printBootStatistics();
        }
      } else {
        // Die!
        ROOT_LOGGER.unsuccessfulBoot();
        System.exit(ExitCodes.HOST_CONTROLLER_ABORT_EXIT_CODE);
      }
    }
  }
 @Override
 public RunningMode getCurrentRunningMode() {
   return runningModeControl.getRunningMode();
 }