protected synchronized void updateHosts(Set<HostRequest> requests) throws AmbariException, AuthorizationException {

    if (requests.isEmpty()) {
      LOG.warn("Received an empty requests set");
      return;
    }

    AmbariManagementController controller = getManagementController();
    Clusters                   clusters   = controller.getClusters();

    for (HostRequest request : requests) {
      if (request.getHostname() == null || request.getHostname().isEmpty()) {
        throw new IllegalArgumentException("Invalid arguments, hostname should be provided");
      }
    }

    TreeMap<String, TopologyCluster> topologyUpdates = new TreeMap<>();
    for (HostRequest request : requests) {
      if (LOG.isDebugEnabled()) {
        LOG.debug("Received an updateHost request, hostname={}, request={}", request.getHostname(), request);
      }

      Host host = clusters.getHost(request.getHostname());

      String clusterName = request.getClusterName();
      Cluster cluster = clusters.getCluster(clusterName);
      Long clusterId = cluster.getClusterId();
      Long resourceId = cluster.getResourceId();
      TopologyHost topologyHost = new TopologyHost(host.getHostId(), host.getHostName());

      try {
        // The below method call throws an exception when trying to create a duplicate mapping in the clusterhostmapping
        // table. This is done to detect duplicates during host create. In order to be robust, handle these gracefully.
        clusters.mapAndPublishHostsToCluster(new HashSet<>(Arrays.asList(request.getHostname())), clusterName);
      } catch (DuplicateResourceException e) {
        // do nothing
      }

      boolean rackChange = updateHostRackInfoIfChanged(cluster, host, request);

      if (rackChange) {
        topologyHost.setRackName(host.getRackInfo());
      }

      if (null != request.getPublicHostName()) {
        if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, resourceId, RoleAuthorization.HOST_ADD_DELETE_HOSTS)) {
          throw new AuthorizationException("The authenticated user is not authorized to update host attributes");
        }
        host.setPublicHostName(request.getPublicHostName());
        topologyHost.setHostName(request.getPublicHostName());
      }

      if (null != clusterName && null != request.getMaintenanceState()) {
        if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, resourceId, RoleAuthorization.HOST_TOGGLE_MAINTENANCE)) {
          throw new AuthorizationException("The authenticated user is not authorized to update host maintenance state");
        }
        MaintenanceState newState = MaintenanceState.valueOf(request.getMaintenanceState());
        MaintenanceState oldState = host.getMaintenanceState(clusterId);
        if (!newState.equals(oldState)) {
          if (newState.equals(MaintenanceState.IMPLIED_FROM_HOST)
              || newState.equals(MaintenanceState.IMPLIED_FROM_SERVICE)) {
            throw new IllegalArgumentException("Invalid arguments, can only set " +
              "maintenance state to one of " + EnumSet.of(MaintenanceState.OFF, MaintenanceState.ON));
          } else {
            host.setMaintenanceState(clusterId, newState);
          }
        }
      }

      // Create configurations
      if (null != clusterName && null != request.getDesiredConfigs()) {
        if (clusters.getHostsForCluster(clusterName).containsKey(host.getHostName())) {

          for (ConfigurationRequest cr : request.getDesiredConfigs()) {
            if (null != cr.getProperties() && cr.getProperties().size() > 0) {
              LOG.info(MessageFormat.format("Applying configuration with tag ''{0}'' to host ''{1}'' in cluster ''{2}''",
                  cr.getVersionTag(),
                  request.getHostname(),
                  clusterName));

              cr.setClusterName(cluster.getClusterName());
              controller.createConfiguration(cr);
            }

            Config baseConfig = cluster.getConfig(cr.getType(), cr.getVersionTag());
            if (null != baseConfig) {
              String authName = controller.getAuthName();
              DesiredConfig oldConfig = host.getDesiredConfigs(clusterId).get(cr.getType());

              if (host.addDesiredConfig(clusterId, cr.isSelected(), authName,  baseConfig)) {
                Logger logger = LoggerFactory.getLogger("configchange");
                logger.info("(configchange) cluster '" + cluster.getClusterName() + "', "
                    + "host '" + host.getHostName() + "' "
                    + "changed by: '" + authName + "'; "
                    + "type='" + baseConfig.getType() + "' "
                    + "version='" + baseConfig.getVersion() + "'"
                    + "tag='" + baseConfig.getTag() + "'"
                    + (null == oldConfig ? "" : ", from='" + oldConfig.getTag() + "'"));
              }
            }
          }
        }
      }

      if (StringUtils.isNotBlank(clusterName) && rackChange) {
        // Authorization check for this update was performed before we got to this point.
        controller.registerRackChange(clusterName);
      }

      if (!topologyUpdates.containsKey(clusterId.toString())) {
        topologyUpdates.put(clusterId.toString(), new TopologyCluster());
      }
      topologyUpdates.get(clusterId.toString()).addTopologyHost(topologyHost);
      TopologyUpdateEvent topologyUpdateEvent = new TopologyUpdateEvent(topologyUpdates,
          UpdateEventType.UPDATE);
      topologyHolder.updateData(topologyUpdateEvent);
      //todo: if attempt was made to update a property other than those
      //todo: that are allowed above, should throw exception
    }
  }
@param osFamily provides OS to OS family lookup; may be null if OS family is ignored anyway (eg. for liveness check)
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java