// 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);
      }
    }
  }
  // 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();
    try {
      super.boot(
          hostControllerConfigurationPersister
              .load()); // This parses the host.xml and invokes all ops

      final RunningMode currentRunningMode = runningModeControl.getRunningMode();

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

      // Install the core remoting endpoint and listener
      ManagementRemotingServices.installRemotingEndpoint(
          serviceTarget,
          ManagementRemotingServices.MANAGEMENT_ENDPOINT,
          hostControllerInfo.getLocalHostName(),
          EndpointService.EndpointType.MANAGEMENT,
          null,
          null);

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

        if (hostControllerInfo.getRemoteDomainControllerHost() != null) {
          Future<MasterDomainControllerClient> clientFuture =
              RemoteDomainConnectionService.install(
                  serviceTarget,
                  getValue(),
                  hostControllerInfo.getLocalHostName(),
                  hostControllerInfo.getRemoteDomainControllerHost(),
                  hostControllerInfo.getRemoteDomainControllertPort(),
                  hostControllerInfo.getRemoteDomainControllerSecurityRealm(),
                  remoteFileRepository);
          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
          try {
            masterDomainControllerClient.register();
          } catch (IllegalStateException e) {
            // We could not connect to the host
            log.error(HostControllerMessages.MESSAGES.cannotConnectToMaster(e));
            System.exit(ExitCodes.HOST_CONTROLLER_ABORT_EXIT_CODE);
          }
        } else if (currentRunningMode != RunningMode.ADMIN_ONLY) {
          // We could not connect to the host
          log.error(
              HostControllerMessages.MESSAGES.noDomainControllerConfigurationProvided(
                  currentRunningMode, CommandLineConstants.ADMIN_ONLY, RunningMode.ADMIN_ONLY));
          System.exit(ExitCodes.HOST_CONTROLLER_ABORT_EXIT_CODE);
        }

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

        ManagementRemotingServices.installManagementChannelServices(
            serviceTarget,
            ManagementRemotingServices.MANAGEMENT_ENDPOINT,
            new MasterDomainControllerOperationHandlerService(this, this),
            DomainModelControllerService.SERVICE_NAME,
            ManagementRemotingServices.DOMAIN_CHANNEL,
            null,
            null);
        serverInventory = getFuture(inventoryFuture);
      }

      // TODO look into adding some of these services in the handlers, but ON-DEMAND.
      // Then here just add some simple service that demands them

      ServerToHostOperationHandlerFactoryService.install(
          serviceTarget, ServerInventoryService.SERVICE_NAME, proxyExecutor);

      NativeManagementAddHandler.installNativeManagementServices(
          serviceTarget, hostControllerInfo, null, null);

      if (hostControllerInfo.getHttpManagementInterface() != null) {
        HttpManagementAddHandler.installHttpManagementServices(
            serviceTarget, hostControllerInfo, environment, null);
      }

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

      // TODO when to call hostControllerConfigurationPersister.successful boot? Look into this for
      // standalone as well; may be broken now
    } finally {
      try {
        finishBoot();
      } finally {
        bootstrapListener.tick();
      }
    }
  }