/** * Get a host request object from a map of property values. * * @param properties the predicate * @return the component request object */ private HostRequest getRequest(Map<String, Object> properties) { if (properties == null) { return new HostRequest(null, null, null); } HostRequest hostRequest = new HostRequest( getHostNameFromProperties(properties), (String) properties.get(HOST_CLUSTER_NAME_PROPERTY_ID), null); hostRequest.setPublicHostName((String) properties.get(HOST_PUBLIC_NAME_PROPERTY_ID)); hostRequest.setRackInfo((String) properties.get(HOST_RACK_INFO_PROPERTY_ID)); hostRequest.setBlueprintName((String) properties.get(BLUEPRINT_PROPERTY_ID)); hostRequest.setHostGroupName((String) properties.get(HOSTGROUP_PROPERTY_ID)); Object o = properties.get(HOST_MAINTENANCE_STATE_PROPERTY_ID); if (null != o) { hostRequest.setMaintenanceState(o.toString()); } List<ConfigurationRequest> cr = getConfigurationRequests("Hosts", properties); hostRequest.setDesiredConfigs(cr); return hostRequest; }
protected void deleteHosts(Set<HostRequest> requests) throws AmbariException { AmbariManagementController controller = getManagementController(); Clusters clusters = controller.getClusters(); List<HostRequest> okToRemove = new ArrayList<HostRequest>(); for (HostRequest hostRequest : requests) { String hostName = hostRequest.getHostname(); if (null == hostName) { continue; } Set<String> clusterNamesForHost = new HashSet<String>(); if (null != hostRequest.getClusterName()) { clusterNamesForHost.add(hostRequest.getClusterName()); } else { Set<Cluster> clustersForHost = clusters.getClustersForHost(hostRequest.getHostname()); if (null != clustersForHost) { for (Cluster c : clustersForHost) { clusterNamesForHost.add(c.getClusterName()); } } } for (String clusterName : clusterNamesForHost) { Cluster cluster = clusters.getCluster(clusterName); List<ServiceComponentHost> list = cluster.getServiceComponentHosts(hostName); if (!list.isEmpty()) { List<String> componentsToRemove = new ArrayList<String>(); for (ServiceComponentHost sch : list) { Service s = cluster.getService(sch.getServiceName()); ServiceComponent sc = s.getServiceComponent(sch.getServiceComponentName()); // Masters and Slaves must be deleted first. Clients are ok. if (!sc.isClientComponent()) { componentsToRemove.add(sch.getServiceComponentName()); } } if (!componentsToRemove.isEmpty()) { StringBuilder reason = new StringBuilder("Cannot remove host ") .append(hostName) .append(" from ") .append(hostRequest.getClusterName()) .append( ". The following roles exist, and these components must be stopped if running, and then deleted: "); reason.append(StringUtils.join(componentsToRemove, ", ")); throw new AmbariException(reason.toString()); } } } okToRemove.add(hostRequest); } for (HostRequest hostRequest : okToRemove) { // Assume the user also wants to delete it entirely, including all clusters. clusters.deleteHost(hostRequest.getHostname()); if (null != hostRequest.getClusterName()) { clusters.getCluster(hostRequest.getClusterName()).recalculateAllClusterVersionStates(); } } }
protected synchronized void updateHosts(Set<HostRequest> requests) throws AmbariException { 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"); } } for (HostRequest request : requests) { if (LOG.isDebugEnabled()) { LOG.debug( "Received an updateHost request" + ", hostname=" + request.getHostname() + ", request=" + request); } Host host = clusters.getHost(request.getHostname()); String clusterName = request.getClusterName(); 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.mapHostToCluster(request.getHostname(), clusterName); } catch (DuplicateResourceException e) { // do nothing } if (null != request.getHostAttributes()) { host.setHostAttributes(request.getHostAttributes()); } String rackInfo = host.getRackInfo(); String requestRackInfo = request.getRackInfo(); boolean rackChange = requestRackInfo != null && !requestRackInfo.equals(rackInfo); if (rackChange) { host.setRackInfo(requestRackInfo); } if (null != request.getPublicHostName()) { host.setPublicHostName(request.getPublicHostName()); } if (null != clusterName && null != request.getMaintenanceState()) { Cluster c = clusters.getCluster(clusterName); MaintenanceState newState = MaintenanceState.valueOf(request.getMaintenanceState()); MaintenanceState oldState = host.getMaintenanceState(c.getClusterId()); 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(c.getClusterId(), newState); } } } // Create configurations if (null != clusterName && null != request.getDesiredConfigs()) { Cluster c = clusters.getCluster(clusterName); 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(c.getClusterName()); controller.createConfiguration(cr); } Config baseConfig = c.getConfig(cr.getType(), cr.getVersionTag()); if (null != baseConfig) { String authName = controller.getAuthName(); DesiredConfig oldConfig = host.getDesiredConfigs(c.getClusterId()).get(cr.getType()); if (host.addDesiredConfig(c.getClusterId(), cr.isSelected(), authName, baseConfig)) { Logger logger = LoggerFactory.getLogger("configchange"); logger.info( "cluster '" + c.getClusterName() + "', " + "host '" + host.getHostName() + "' " + "changed by: '" + authName + "'; " + "type='" + baseConfig.getType() + "' " + "version='" + baseConfig.getVersion() + "'" + "tag='" + baseConfig.getTag() + "'" + (null == oldConfig ? "" : ", from='" + oldConfig.getTag() + "'")); } } } } } if (clusterName != null && !clusterName.isEmpty()) { clusters.getCluster(clusterName).recalculateAllClusterVersionStates(); if (rackChange) { controller.registerRackChange(clusterName); } } // todo: if attempt was made to update a property other than those // todo: that are allowed above, should throw exception } }
protected static Set<HostResponse> getHosts( AmbariManagementController controller, HostRequest request) throws AmbariException { // TODO/FIXME host can only belong to a single cluster so get host directly from Cluster // TODO/FIXME what is the requirement for filtering on host attributes? List<Host> hosts; Set<HostResponse> response = new HashSet<HostResponse>(); Cluster cluster = null; Clusters clusters = controller.getClusters(); String clusterName = request.getClusterName(); String hostName = request.getHostname(); if (clusterName != null) { // validate that cluster exists, throws exception if it doesn't. try { cluster = clusters.getCluster(clusterName); } catch (ObjectNotFoundException e) { throw new ParentObjectNotFoundException("Parent Cluster resource doesn't exist", e); } } if (hostName == null) { hosts = clusters.getHosts(); } else { hosts = new ArrayList<Host>(); try { hosts.add(clusters.getHost(request.getHostname())); } catch (HostNotFoundException e) { // add cluster name throw new HostNotFoundException(clusterName, hostName); } } for (Host h : hosts) { if (clusterName != null) { if (clusters.getClustersForHost(h.getHostName()).contains(cluster)) { HostResponse r = h.convertToResponse(); r.setClusterName(clusterName); r.setDesiredHostConfigs(h.getDesiredHostConfigs(cluster)); r.setMaintenanceState(h.getMaintenanceState(cluster.getClusterId())); response.add(r); } else if (hostName != null) { throw new HostNotFoundException(clusterName, hostName); } } else { HostResponse r = h.convertToResponse(); Set<Cluster> clustersForHost = clusters.getClustersForHost(h.getHostName()); // todo: host can only belong to a single cluster if (clustersForHost != null && clustersForHost.size() != 0) { r.setClusterName(clustersForHost.iterator().next().getClusterName()); } response.add(r); } } return response; }
private void createHostResource( Clusters clusters, Set<String> duplicates, Set<String> unknowns, Set<String> allHosts, HostRequest request) throws AmbariException { if (request.getHostname() == null || request.getHostname().isEmpty()) { throw new IllegalArgumentException("Invalid arguments, hostname" + " cannot be null"); } if (LOG.isDebugEnabled()) { LOG.debug( "Received a createHost request" + ", hostname=" + request.getHostname() + ", request=" + request); } if (allHosts.contains(request.getHostname())) { // throw dup error later duplicates.add(request.getHostname()); return; } allHosts.add(request.getHostname()); try { // ensure host is registered clusters.getHost(request.getHostname()); } catch (HostNotFoundException e) { unknowns.add(request.getHostname()); return; } if (request.getClusterName() != null) { try { // validate that cluster_name is valid clusters.getCluster(request.getClusterName()); } catch (ClusterNotFoundException e) { throw new ParentObjectNotFoundException( "Attempted to add a host to a cluster which doesn't exist: " + " clusterName=" + request.getClusterName()); } } }
/** * Accepts a request with registered hosts and if the request contains a cluster name then will * map all of the hosts onto that cluster. * * @param request Request that must contain registered hosts, and optionally a cluster. * @throws AmbariException */ public synchronized void createHosts(Request request) throws AmbariException { Set<Map<String, Object>> propertySet = request.getProperties(); if (propertySet == null || propertySet.isEmpty()) { LOG.warn("Received a create host request with no associated property sets"); return; } AmbariManagementController controller = getManagementController(); Clusters clusters = controller.getClusters(); Set<String> duplicates = new HashSet<String>(); Set<String> unknowns = new HashSet<String>(); Set<String> allHosts = new HashSet<String>(); Set<HostRequest> hostRequests = new HashSet<HostRequest>(); for (Map<String, Object> propertyMap : propertySet) { HostRequest hostRequest = getRequest(propertyMap); hostRequests.add(hostRequest); if (!propertyMap.containsKey(HOSTGROUP_PROPERTY_ID)) { createHostResource(clusters, duplicates, unknowns, allHosts, hostRequest); } } if (!duplicates.isEmpty()) { StringBuilder names = new StringBuilder(); boolean first = true; for (String hName : duplicates) { if (!first) { names.append(","); } first = false; names.append(hName); } throw new IllegalArgumentException( "Invalid request contains" + " duplicate hostnames" + ", hostnames=" + names.toString()); } if (!unknowns.isEmpty()) { StringBuilder names = new StringBuilder(); boolean first = true; for (String hName : unknowns) { if (!first) { names.append(","); } first = false; names.append(hName); } throw new IllegalArgumentException( "Attempted to add unknown hosts to a cluster. " + "These hosts have not been registered with the server: " + names.toString()); } Map<String, Set<String>> hostClustersMap = new HashMap<String, Set<String>>(); Map<String, Map<String, String>> hostAttributes = new HashMap<String, Map<String, String>>(); Set<String> allClusterSet = new HashSet<String>(); for (HostRequest hostRequest : hostRequests) { if (hostRequest.getHostname() != null && !hostRequest.getHostname().isEmpty() && hostRequest.getClusterName() != null && !hostRequest.getClusterName().isEmpty()) { Set<String> clusterSet = new HashSet<String>(); clusterSet.add(hostRequest.getClusterName()); allClusterSet.add(hostRequest.getClusterName()); hostClustersMap.put(hostRequest.getHostname(), clusterSet); if (hostRequest.getHostAttributes() != null) { hostAttributes.put(hostRequest.getHostname(), hostRequest.getHostAttributes()); } } } clusters.updateHostWithClusterAndAttributes(hostClustersMap, hostAttributes); for (String clusterName : allClusterSet) { clusters.getCluster(clusterName).recalculateAllClusterVersionStates(); } }