class HostsMasterMaintenanceCheck extends AbstractCheckDescriptor {

  @Override
  public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException {
    final String clusterName = request.getClusterName();
    final Cluster cluster = clustersProvider.get().getCluster(clusterName);
    final StackId stackId = request.getSourceStackId();
    final Set<String> hostsWithMasterComponent = new HashSet<>();

    // TODO AMBARI-12698, need to pass the upgrade pack to use in the request, or at least the type.
    RepositoryVersionEntity repositoryVersion = request.getTargetRepositoryVersion();

    final String upgradePackName = repositoryVersionHelper.get().getUpgradePackageName(
        stackId.getStackName(), stackId.getStackVersion(), repositoryVersion.getVersion(), null);

    if (upgradePackName == null) {
      prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
      String fail = getFailReason(KEY_NO_UPGRADE_NAME, prerequisiteCheck, request);
      prerequisiteCheck.setFailReason(String.format(fail, stackId.getStackName(), stackId.getStackVersion()));
      return;
    }

    final UpgradePack upgradePack = ambariMetaInfo.get().getUpgradePacks(stackId.getStackName(), stackId.getStackVersion()).get(upgradePackName);
    if (upgradePack == null) {
      prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
      String fail = getFailReason(KEY_NO_UPGRADE_PACK, prerequisiteCheck, request);
      prerequisiteCheck.setFailReason(String.format(fail, upgradePackName));
      return;
    }

    final Set<String> componentsFromUpgradePack = new HashSet<>();
    for (Map<String, ProcessingComponent> task: upgradePack.getTasks().values()) {
      componentsFromUpgradePack.addAll(task.keySet());
    }

    for (Service service: cluster.getServices().values()) {
      for (ServiceComponent serviceComponent: service.getServiceComponents().values()) {
        if (serviceComponent.isMasterComponent() && componentsFromUpgradePack.contains(serviceComponent.getName())) {
          hostsWithMasterComponent.addAll(serviceComponent.getServiceComponentHosts().keySet());
        }
      }
    }

    final Map<String, Host> clusterHosts = clustersProvider.get().getHostsForCluster(clusterName);
    for (Map.Entry<String, Host> hostEntry : clusterHosts.entrySet()) {
      final Host host = hostEntry.getValue();
      if (host.getMaintenanceState(cluster.getClusterId()) == MaintenanceState.ON && hostsWithMasterComponent.contains(host.getHostName())) {
        prerequisiteCheck.getFailedOn().add(host.getHostName());

        prerequisiteCheck.getFailedDetail().add(
            new HostDetail(host.getHostId(), host.getHostName()));
      }
    }

    if (!prerequisiteCheck.getFailedOn().isEmpty()) {
      prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
      prerequisiteCheck.setFailReason(getFailReason(prerequisiteCheck, request));
    }
  }

  public  HostsMasterMaintenanceCheck();

}