| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.ambari.server.state; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.ConcurrentMap; |
| import java.util.concurrent.atomic.AtomicReference; |
| import java.util.concurrent.locks.Lock; |
| import java.util.concurrent.locks.ReentrantLock; |
| |
| import org.apache.ambari.server.AmbariException; |
| import org.apache.ambari.server.ObjectNotFoundException; |
| import org.apache.ambari.server.ServiceComponentNotFoundException; |
| import org.apache.ambari.server.api.services.AmbariMetaInfo; |
| import org.apache.ambari.server.collections.Predicate; |
| import org.apache.ambari.server.collections.PredicateUtils; |
| import org.apache.ambari.server.controller.AmbariManagementController; |
| import org.apache.ambari.server.controller.ServiceResponse; |
| import org.apache.ambari.server.controller.internal.AmbariServerLDAPConfigurationHandler; |
| import org.apache.ambari.server.controller.internal.AmbariServerSSOConfigurationHandler; |
| import org.apache.ambari.server.controller.internal.DeleteHostComponentStatusMetaData; |
| import org.apache.ambari.server.events.MaintenanceModeEvent; |
| import org.apache.ambari.server.events.ServiceCredentialStoreUpdateEvent; |
| import org.apache.ambari.server.events.ServiceInstalledEvent; |
| import org.apache.ambari.server.events.ServiceRemovedEvent; |
| import org.apache.ambari.server.events.publishers.AmbariEventPublisher; |
| import org.apache.ambari.server.orm.dao.ClusterDAO; |
| import org.apache.ambari.server.orm.dao.ClusterServiceDAO; |
| import org.apache.ambari.server.orm.dao.ServiceConfigDAO; |
| import org.apache.ambari.server.orm.dao.ServiceDesiredStateDAO; |
| import org.apache.ambari.server.orm.entities.ClusterConfigEntity; |
| import org.apache.ambari.server.orm.entities.ClusterEntity; |
| import org.apache.ambari.server.orm.entities.ClusterServiceEntity; |
| import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK; |
| import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; |
| import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity; |
| import org.apache.ambari.server.orm.entities.ServiceConfigEntity; |
| import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity; |
| import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntityPK; |
| import org.apache.ambari.server.orm.entities.StackEntity; |
| import org.apache.ambari.server.serveraction.kerberos.Component; |
| import org.apache.commons.lang.StringUtils; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.inject.Inject; |
| import com.google.inject.ProvisionException; |
| import com.google.inject.assistedinject.Assisted; |
| import com.google.inject.assistedinject.AssistedInject; |
| import com.google.inject.persist.Transactional; |
| |
| |
| public class ServiceImpl implements Service { |
| private final Lock lock = new ReentrantLock(); |
| private ServiceDesiredStateEntityPK serviceDesiredStateEntityPK; |
| private ClusterServiceEntityPK serviceEntityPK; |
| |
| private static final Logger LOG = LoggerFactory.getLogger(ServiceImpl.class); |
| |
| private final Cluster cluster; |
| private final ConcurrentMap<String, ServiceComponent> components = new ConcurrentHashMap<>(); |
| private boolean isClientOnlyService; |
| private boolean isCredentialStoreSupported; |
| private boolean isCredentialStoreRequired; |
| private final boolean ssoIntegrationSupported; |
| private final Predicate ssoEnabledTest; |
| private final boolean ldapIntegrationSupported; |
| private final Predicate ldapEnabledTest; |
| private final boolean ssoRequiresKerberos; |
| private final Predicate kerberosEnabledTest; |
| private AmbariMetaInfo ambariMetaInfo; |
| private AtomicReference<MaintenanceState> maintenanceState = new AtomicReference<>(); |
| |
| @Inject |
| private ServiceConfigDAO serviceConfigDAO; |
| |
| @Inject |
| private AmbariManagementController ambariManagementController; |
| |
| @Inject |
| private ConfigHelper configHelper; |
| |
| @Inject |
| private AmbariServerSSOConfigurationHandler ambariServerSSOConfigurationHandler; |
| |
| @Inject |
| private AmbariServerLDAPConfigurationHandler ambariServerLDAPConfigurationHandler; |
| |
| private final ClusterServiceDAO clusterServiceDAO; |
| private final ServiceDesiredStateDAO serviceDesiredStateDAO; |
| private final ClusterDAO clusterDAO; |
| private final ServiceComponentFactory serviceComponentFactory; |
| |
| /** |
| * Used to publish events relating to service CRUD operations. |
| */ |
| private final AmbariEventPublisher eventPublisher; |
| |
| /** |
| * The name of the service. |
| */ |
| private final String serviceName; |
| private final String displayName; |
| |
| @AssistedInject |
| ServiceImpl(@Assisted Cluster cluster, @Assisted String serviceName, |
| @Assisted RepositoryVersionEntity desiredRepositoryVersion, ClusterDAO clusterDAO, |
| ClusterServiceDAO clusterServiceDAO, ServiceDesiredStateDAO serviceDesiredStateDAO, |
| ServiceComponentFactory serviceComponentFactory, AmbariMetaInfo ambariMetaInfo, |
| AmbariEventPublisher eventPublisher) throws AmbariException { |
| this.cluster = cluster; |
| this.clusterDAO = clusterDAO; |
| this.clusterServiceDAO = clusterServiceDAO; |
| this.serviceDesiredStateDAO = serviceDesiredStateDAO; |
| this.serviceComponentFactory = serviceComponentFactory; |
| this.eventPublisher = eventPublisher; |
| this.serviceName = serviceName; |
| this.ambariMetaInfo = ambariMetaInfo; |
| |
| ClusterServiceEntity serviceEntity = new ClusterServiceEntity(); |
| serviceEntity.setClusterId(cluster.getClusterId()); |
| serviceEntity.setServiceName(serviceName); |
| ServiceDesiredStateEntity serviceDesiredStateEntity = new ServiceDesiredStateEntity(); |
| serviceDesiredStateEntity.setServiceName(serviceName); |
| serviceDesiredStateEntity.setClusterId(cluster.getClusterId()); |
| serviceDesiredStateEntity.setDesiredRepositoryVersion(desiredRepositoryVersion); |
| serviceDesiredStateEntityPK = getServiceDesiredStateEntityPK(serviceDesiredStateEntity); |
| serviceEntityPK = getServiceEntityPK(serviceEntity); |
| |
| serviceDesiredStateEntity.setClusterServiceEntity(serviceEntity); |
| serviceEntity.setServiceDesiredStateEntity(serviceDesiredStateEntity); |
| |
| StackId stackId = desiredRepositoryVersion.getStackId(); |
| |
| ServiceInfo sInfo = ambariMetaInfo.getService(stackId.getStackName(), |
| stackId.getStackVersion(), serviceName); |
| |
| displayName = sInfo.getDisplayName(); |
| isClientOnlyService = sInfo.isClientOnlyService(); |
| isCredentialStoreSupported = sInfo.isCredentialStoreSupported(); |
| isCredentialStoreRequired = sInfo.isCredentialStoreRequired(); |
| ssoIntegrationSupported = sInfo.isSingleSignOnSupported(); |
| ssoEnabledTest = compileSsoEnabledPredicate(sInfo); |
| ssoRequiresKerberos = sInfo.isKerberosRequiredForSingleSignOnIntegration(); |
| kerberosEnabledTest = compileKerberosEnabledPredicate(sInfo); |
| |
| if (ssoIntegrationSupported && ssoRequiresKerberos && (kerberosEnabledTest == null)) { |
| LOG.warn("The service, {}, requires Kerberos to be enabled for SSO integration support; " + |
| "however, the kerberosEnabledTest specification has not been specified in the metainfo.xml file. " + |
| "Automated SSO integration will not be allowed for this service.", |
| serviceName); |
| } |
| |
| ldapIntegrationSupported = sInfo.isLdapSupported(); |
| ldapEnabledTest = StringUtils.isNotBlank(sInfo.getLdapEnabledTest()) ? PredicateUtils.fromJSON(sInfo.getLdapEnabledTest()) : null; |
| |
| persist(serviceEntity); |
| } |
| |
| @AssistedInject |
| ServiceImpl(@Assisted Cluster cluster, @Assisted ClusterServiceEntity serviceEntity, |
| ClusterDAO clusterDAO, ClusterServiceDAO clusterServiceDAO, |
| ServiceDesiredStateDAO serviceDesiredStateDAO, |
| ServiceComponentFactory serviceComponentFactory, AmbariMetaInfo ambariMetaInfo, |
| AmbariEventPublisher eventPublisher) throws AmbariException { |
| this.cluster = cluster; |
| this.clusterDAO = clusterDAO; |
| this.clusterServiceDAO = clusterServiceDAO; |
| this.serviceDesiredStateDAO = serviceDesiredStateDAO; |
| this.serviceComponentFactory = serviceComponentFactory; |
| this.eventPublisher = eventPublisher; |
| serviceName = serviceEntity.getServiceName(); |
| this.ambariMetaInfo = ambariMetaInfo; |
| |
| ServiceDesiredStateEntity serviceDesiredStateEntity = serviceEntity.getServiceDesiredStateEntity(); |
| serviceDesiredStateEntityPK = getServiceDesiredStateEntityPK(serviceDesiredStateEntity); |
| serviceEntityPK = getServiceEntityPK(serviceEntity); |
| |
| if (!serviceEntity.getServiceComponentDesiredStateEntities().isEmpty()) { |
| for (ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity |
| : serviceEntity.getServiceComponentDesiredStateEntities()) { |
| try { |
| components.put(serviceComponentDesiredStateEntity.getComponentName(), |
| serviceComponentFactory.createExisting(this, |
| serviceComponentDesiredStateEntity)); |
| } catch (ProvisionException ex) { |
| StackId stackId = new StackId(serviceComponentDesiredStateEntity.getDesiredStack()); |
| LOG.error(String.format("Can not get component info: stackName=%s, stackVersion=%s, serviceName=%s, componentName=%s", |
| stackId.getStackName(), stackId.getStackVersion(), |
| serviceEntity.getServiceName(), serviceComponentDesiredStateEntity.getComponentName())); |
| ex.printStackTrace(); |
| } |
| } |
| } |
| |
| StackId stackId = getDesiredStackId(); |
| ServiceInfo sInfo = ambariMetaInfo.getService(stackId.getStackName(), |
| stackId.getStackVersion(), getName()); |
| isClientOnlyService = sInfo.isClientOnlyService(); |
| isCredentialStoreSupported = sInfo.isCredentialStoreSupported(); |
| isCredentialStoreRequired = sInfo.isCredentialStoreRequired(); |
| displayName = sInfo.getDisplayName(); |
| ssoIntegrationSupported = sInfo.isSingleSignOnSupported(); |
| ssoEnabledTest = compileSsoEnabledPredicate(sInfo); |
| ssoRequiresKerberos = sInfo.isKerberosRequiredForSingleSignOnIntegration(); |
| kerberosEnabledTest = compileKerberosEnabledPredicate(sInfo); |
| |
| if (ssoIntegrationSupported && ssoRequiresKerberos && (kerberosEnabledTest == null)) { |
| LOG.warn("The service, {}, requires Kerberos to be enabled for SSO integration support; " + |
| "however, the kerberosEnabledTest specification has not been specified in the metainfo.xml file. " + |
| "Automated SSO integration will not be allowed for this service.", |
| serviceName); |
| } |
| |
| ldapIntegrationSupported = sInfo.isLdapSupported(); |
| ldapEnabledTest = StringUtils.isNotBlank(sInfo.getLdapEnabledTest()) ? PredicateUtils.fromJSON(sInfo.getLdapEnabledTest()) : null; |
| } |
| |
| |
| /*** |
| * Refresh Service info due to current stack |
| * @throws AmbariException |
| */ |
| @Override |
| public void updateServiceInfo() throws AmbariException { |
| try { |
| ServiceInfo serviceInfo = ambariMetaInfo.getService(this); |
| |
| isClientOnlyService = serviceInfo.isClientOnlyService(); |
| isCredentialStoreSupported = serviceInfo.isCredentialStoreSupported(); |
| isCredentialStoreRequired = serviceInfo.isCredentialStoreRequired(); |
| |
| } catch (ObjectNotFoundException e) { |
| throw new RuntimeException("Trying to create a ServiceInfo" |
| + " not recognized in stack info" |
| + ", clusterName=" + cluster.getClusterName() |
| + ", serviceName=" + getName() |
| + ", stackInfo=" + getDesiredStackId().getStackName()); |
| } |
| } |
| |
| @Override |
| public String getName() { |
| return serviceName; |
| } |
| |
| @Override |
| public String getDisplayName() { |
| return StringUtils.isBlank(displayName) ? serviceName : displayName; |
| } |
| |
| @Override |
| public long getClusterId() { |
| return cluster.getClusterId(); |
| } |
| |
| @Override |
| public Map<String, ServiceComponent> getServiceComponents() { |
| return new HashMap<>(components); |
| } |
| |
| @Override |
| public Set<String> getServiceHosts() { |
| Set<String> hostNames = new HashSet<>(); |
| for (ServiceComponent serviceComponent : getServiceComponents().values()) { |
| hostNames.addAll(serviceComponent.getServiceComponentsHosts()); |
| } |
| return hostNames; |
| } |
| |
| @Override |
| public void addServiceComponents( |
| Map<String, ServiceComponent> components) throws AmbariException { |
| for (ServiceComponent sc : components.values()) { |
| addServiceComponent(sc); |
| } |
| } |
| |
| @Override |
| public void addServiceComponent(ServiceComponent component) throws AmbariException { |
| if (components.containsKey(component.getName())) { |
| throw new AmbariException("Cannot add duplicate ServiceComponent" |
| + ", clusterName=" + cluster.getClusterName() |
| + ", clusterId=" + cluster.getClusterId() |
| + ", serviceName=" + getName() |
| + ", serviceComponentName=" + component.getName()); |
| } |
| |
| components.put(component.getName(), component); |
| } |
| |
| @Override |
| public ServiceComponent addServiceComponent(String serviceComponentName) |
| throws AmbariException { |
| ServiceComponent component = serviceComponentFactory.createNew(this, serviceComponentName); |
| addServiceComponent(component); |
| return component; |
| } |
| |
| @Override |
| public ServiceComponent getServiceComponent(String componentName) |
| throws AmbariException { |
| ServiceComponent serviceComponent = components.get(componentName); |
| if (null == serviceComponent) { |
| throw new ServiceComponentNotFoundException(cluster.getClusterName(), |
| getName(), componentName); |
| } |
| |
| return serviceComponent; |
| } |
| |
| @Override |
| public State getDesiredState() { |
| ServiceDesiredStateEntity serviceDesiredStateEntity = getServiceDesiredStateEntity(); |
| return serviceDesiredStateEntity.getDesiredState(); |
| } |
| |
| @Override |
| public void setDesiredState(State state) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Setting DesiredState of Service, clusterName={}, clusterId={}, serviceName={}, oldDesiredState={}, newDesiredState={}", |
| cluster.getClusterName(), cluster.getClusterId(), getName(), getDesiredState(), state); |
| } |
| |
| ServiceDesiredStateEntity serviceDesiredStateEntity = getServiceDesiredStateEntity(); |
| serviceDesiredStateEntity.setDesiredState(state); |
| serviceDesiredStateDAO.merge(serviceDesiredStateEntity); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public StackId getDesiredStackId() { |
| ServiceDesiredStateEntity serviceDesiredStateEntity = getServiceDesiredStateEntity(); |
| |
| if (null == serviceDesiredStateEntity) { |
| return null; |
| } else { |
| StackEntity desiredStackEntity = serviceDesiredStateEntity.getDesiredStack(); |
| return new StackId(desiredStackEntity); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public RepositoryVersionEntity getDesiredRepositoryVersion() { |
| ServiceDesiredStateEntity serviceDesiredStateEntity = getServiceDesiredStateEntity(); |
| return serviceDesiredStateEntity.getDesiredRepositoryVersion(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| @Transactional |
| public void setDesiredRepositoryVersion(RepositoryVersionEntity repositoryVersionEntity) { |
| ServiceDesiredStateEntity serviceDesiredStateEntity = getServiceDesiredStateEntity(); |
| serviceDesiredStateEntity.setDesiredRepositoryVersion(repositoryVersionEntity); |
| serviceDesiredStateDAO.merge(serviceDesiredStateEntity); |
| |
| Collection<ServiceComponent> components = getServiceComponents().values(); |
| for (ServiceComponent component : components) { |
| component.setDesiredRepositoryVersion(repositoryVersionEntity); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public RepositoryVersionState getRepositoryState() { |
| if (components.isEmpty()) { |
| return RepositoryVersionState.NOT_REQUIRED; |
| } |
| |
| List<RepositoryVersionState> states = new ArrayList<>(); |
| for (ServiceComponent component : components.values()) { |
| states.add(component.getRepositoryState()); |
| } |
| |
| return RepositoryVersionState.getAggregateState(states); |
| } |
| |
| @Override |
| public ServiceResponse convertToResponse() { |
| RepositoryVersionEntity desiredRespositoryVersion = getDesiredRepositoryVersion(); |
| StackId desiredStackId = desiredRespositoryVersion.getStackId(); |
| |
| Map<String, Map<String, String>> existingConfigurations; |
| |
| try { |
| existingConfigurations = configHelper.calculateExistingConfigurations(ambariManagementController, cluster); |
| } catch (AmbariException e) { |
| LOG.warn("Failed to get the existing configurations for the cluster. Predicate calculations may not be correct due to missing data."); |
| existingConfigurations = Collections.emptyMap(); |
| } |
| |
| ServiceResponse r = new ServiceResponse(cluster.getClusterId(), cluster.getClusterName(), |
| getName(), desiredStackId, desiredRespositoryVersion.getVersion(), getRepositoryState(), |
| getDesiredState().toString(), isCredentialStoreSupported(), isCredentialStoreEnabled(), |
| ssoIntegrationSupported, isSsoIntegrationDesired(), isSsoIntegrationEnabled(existingConfigurations), |
| isKerberosRequiredForSsoIntegration(), isKerberosEnabled(existingConfigurations), ldapIntegrationSupported,isLdapIntegrationEnabeled(existingConfigurations), isLdapIntegrationDesired()); |
| |
| r.setDesiredRepositoryVersionId(desiredRespositoryVersion.getId()); |
| |
| r.setMaintenanceState(getMaintenanceState().name()); |
| return r; |
| } |
| |
| @Override |
| public Cluster getCluster() { |
| return cluster; |
| } |
| |
| /** |
| * Get a true or false value specifying whether |
| * credential store is supported by this service. |
| * |
| * @return true or false |
| */ |
| @Override |
| public boolean isCredentialStoreSupported() { |
| return isCredentialStoreSupported; |
| } |
| |
| /** |
| * Get a true or false value specifying whether |
| * credential store is required by this service. |
| * |
| * @return true or false |
| */ |
| @Override |
| public boolean isCredentialStoreRequired() { |
| return isCredentialStoreRequired; |
| } |
| |
| |
| /** |
| * Get a true or false value specifying whether |
| * credential store use is enabled for this service. |
| * |
| * @return true or false |
| */ |
| @Override |
| public boolean isCredentialStoreEnabled() { |
| ServiceDesiredStateEntity desiredStateEntity = getServiceDesiredStateEntity(); |
| |
| if (desiredStateEntity != null) { |
| return desiredStateEntity.isCredentialStoreEnabled(); |
| } else { |
| LOG.warn("Trying to fetch a member from an entity object that may " + |
| "have been previously deleted, serviceName = " + getName()); |
| } |
| return false; |
| } |
| |
| |
| /** |
| * Set a true or false value specifying whether this |
| * service is to be enabled for credential store use. |
| * |
| * @param credentialStoreEnabled - true or false |
| */ |
| @Override |
| public void setCredentialStoreEnabled(boolean credentialStoreEnabled) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Setting CredentialStoreEnabled of Service, clusterName={}, clusterId={}, serviceName={}, oldCredentialStoreEnabled={}, newCredentialStoreEnabled={}", |
| cluster.getClusterName(), cluster.getClusterId(), getName(), isCredentialStoreEnabled(), credentialStoreEnabled); |
| } |
| |
| ServiceDesiredStateEntity desiredStateEntity = getServiceDesiredStateEntity(); |
| |
| if (desiredStateEntity != null) { |
| ServiceCredentialStoreUpdateEvent serviceCredentialStoreUpdateEvent = null; |
| //create event only if the value changed |
| if (desiredStateEntity.isCredentialStoreEnabled() != credentialStoreEnabled) { |
| StackId stackId = getDesiredStackId(); |
| serviceCredentialStoreUpdateEvent = |
| new ServiceCredentialStoreUpdateEvent(getClusterId(), stackId.getStackName(), |
| stackId.getStackVersion(), getName()); |
| } |
| desiredStateEntity.setCredentialStoreEnabled(credentialStoreEnabled); |
| desiredStateEntity = serviceDesiredStateDAO.merge(desiredStateEntity); |
| |
| //publish event after the value has changed |
| if (serviceCredentialStoreUpdateEvent != null) { |
| eventPublisher.publish(serviceCredentialStoreUpdateEvent); |
| } |
| } else { |
| LOG.warn("Setting a member on an entity object that may have been " |
| + "previously deleted, serviceName = " + getName()); |
| } |
| } |
| |
| @Override |
| public void debugDump(StringBuilder sb) { |
| sb.append("Service={ serviceName=").append(getName()) |
| .append(", clusterName=").append(cluster.getClusterName()) |
| .append(", clusterId=").append(cluster.getClusterId()) |
| .append(", desiredStackVersion=").append(getDesiredStackId()) |
| .append(", desiredState=").append(getDesiredState()) |
| .append(", components=[ "); |
| boolean first = true; |
| for (ServiceComponent sc : components.values()) { |
| if (!first) { |
| sb.append(" , "); |
| } |
| first = false; |
| sb.append("\n "); |
| sc.debugDump(sb); |
| sb.append(" "); |
| } |
| sb.append(" ] }"); |
| } |
| |
| /** |
| * |
| */ |
| private void persist(ClusterServiceEntity serviceEntity) { |
| persistEntities(serviceEntity); |
| |
| // publish the service installed event |
| StackId stackId = getDesiredStackId(); |
| cluster.addService(this); |
| |
| ServiceInstalledEvent event = new ServiceInstalledEvent(getClusterId(), stackId.getStackName(), |
| stackId.getStackVersion(), getName()); |
| |
| eventPublisher.publish(event); |
| } |
| |
| @Transactional |
| void persistEntities(ClusterServiceEntity serviceEntity) { |
| long clusterId = cluster.getClusterId(); |
| ClusterEntity clusterEntity = clusterDAO.findById(clusterId); |
| serviceEntity.setClusterEntity(clusterEntity); |
| clusterServiceDAO.create(serviceEntity); |
| clusterEntity.getClusterServiceEntities().add(serviceEntity); |
| clusterDAO.merge(clusterEntity); |
| clusterServiceDAO.merge(serviceEntity); |
| } |
| |
| |
| @Override |
| public boolean canBeRemoved() { |
| // |
| // A service can be deleted if all it's components |
| // can be removed, irrespective of the state of |
| // the service itself. |
| // |
| for (ServiceComponent sc : components.values()) { |
| if (!sc.canBeRemoved()) { |
| LOG.warn("Found non removable component when trying to delete service" + ", clusterName=" |
| + cluster.getClusterName() + ", serviceName=" + getName() + ", componentName=" |
| + sc.getName()); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Transactional |
| void deleteAllServiceConfigs() throws AmbariException { |
| long clusterId = getClusterId(); |
| ServiceConfigEntity lastServiceConfigEntity = serviceConfigDAO.findMaxVersion(clusterId, getName()); |
| // de-select every configuration from the service |
| if (lastServiceConfigEntity != null) { |
| for (ClusterConfigEntity serviceConfigEntity : lastServiceConfigEntity.getClusterConfigEntities()) { |
| LOG.info("Disabling and unmapping configuration {}", serviceConfigEntity); |
| serviceConfigEntity.setSelected(false); |
| serviceConfigEntity.setUnmapped(true); |
| clusterDAO.merge(serviceConfigEntity); |
| } |
| } |
| |
| LOG.info("Deleting all configuration associations for {} on cluster {}", getName(), cluster.getClusterName()); |
| |
| List<ServiceConfigEntity> serviceConfigEntities = |
| serviceConfigDAO.findByService(cluster.getClusterId(), getName()); |
| |
| for (ServiceConfigEntity serviceConfigEntity : serviceConfigEntities) { |
| // unmapping all service configs |
| for (ClusterConfigEntity clusterConfigEntity : serviceConfigEntity.getClusterConfigEntities()) { |
| if (!clusterConfigEntity.isUnmapped()) { |
| LOG.info("Unmapping configuration {}", clusterConfigEntity); |
| clusterConfigEntity.setUnmapped(true); |
| clusterDAO.merge(clusterConfigEntity); |
| } |
| } |
| // Only delete the historical version information and not original |
| // config data |
| serviceConfigDAO.remove(serviceConfigEntity); |
| } |
| } |
| |
| void deleteAllServiceConfigGroups() throws AmbariException { |
| for (Long configGroupId : cluster.getConfigGroupsByServiceName(serviceName).keySet()) { |
| cluster.deleteConfigGroup(configGroupId); |
| } |
| } |
| |
| @Override |
| @Transactional |
| public void deleteAllComponents(DeleteHostComponentStatusMetaData deleteMetaData) { |
| lock.lock(); |
| try { |
| LOG.info("Deleting all components for service" + ", clusterName=" + cluster.getClusterName() |
| + ", serviceName=" + getName()); |
| // FIXME check dependencies from meta layer |
| for (ServiceComponent component : components.values()) { |
| if (!component.canBeRemoved()) { |
| deleteMetaData.setAmbariException(new AmbariException("Found non removable component when trying to" |
| + " delete all components from service" + ", clusterName=" + cluster.getClusterName() |
| + ", serviceName=" + getName() + ", componentName=" + component.getName())); |
| return; |
| } |
| } |
| |
| for (ServiceComponent serviceComponent : components.values()) { |
| serviceComponent.delete(deleteMetaData); |
| if (deleteMetaData.getAmbariException() != null) { |
| return; |
| } |
| } |
| |
| components.clear(); |
| } finally { |
| lock.unlock(); |
| } |
| } |
| |
| @Override |
| public void deleteServiceComponent(String componentName, DeleteHostComponentStatusMetaData deleteMetaData) |
| throws AmbariException { |
| lock.lock(); |
| try { |
| ServiceComponent component = getServiceComponent(componentName); |
| LOG.info("Deleting servicecomponent for cluster" + ", clusterName=" + cluster.getClusterName() |
| + ", serviceName=" + getName() + ", componentName=" + componentName); |
| // FIXME check dependencies from meta layer |
| if (!component.canBeRemoved()) { |
| throw new AmbariException("Could not delete component from cluster" |
| + ", clusterName=" + cluster.getClusterName() |
| + ", serviceName=" + getName() |
| + ", componentName=" + componentName); |
| } |
| |
| component.delete(deleteMetaData); |
| components.remove(componentName); |
| } finally { |
| lock.unlock(); |
| } |
| } |
| |
| @Override |
| public boolean isClientOnlyService() { |
| return isClientOnlyService; |
| } |
| |
| @Override |
| @Transactional |
| public void delete(DeleteHostComponentStatusMetaData deleteMetaData) { |
| List<Component> components = getComponents(); // XXX temporal coupling, need to call this BEFORE deletingAllComponents |
| deleteAllComponents(deleteMetaData); |
| if (deleteMetaData.getAmbariException() != null) { |
| return; |
| } |
| |
| StackId stackId = getDesiredStackId(); |
| try { |
| deleteAllServiceConfigs(); |
| deleteAllServiceConfigGroups(); |
| |
| removeEntities(); |
| } catch (AmbariException e) { |
| deleteMetaData.setAmbariException(e); |
| return; |
| } |
| |
| // publish the service removed event |
| if (null == stackId) { |
| return; |
| } |
| |
| ServiceRemovedEvent event = new ServiceRemovedEvent(getClusterId(), stackId.getStackName(), |
| stackId.getStackVersion(), getName(), components); |
| |
| eventPublisher.publish(event); |
| } |
| |
| private List<Component> getComponents() { |
| List<Component> result = new ArrayList<>(); |
| for (ServiceComponent component : getServiceComponents().values()) { |
| for (ServiceComponentHost host : component.getServiceComponentHosts().values()) { |
| result.add(new Component(host.getHostName(), getName(), component.getName(), host.getHost().getHostId())); |
| } |
| } |
| return result; |
| } |
| |
| @Transactional |
| protected void removeEntities() throws AmbariException { |
| serviceDesiredStateDAO.removeByPK(serviceDesiredStateEntityPK); |
| clusterServiceDAO.removeByPK(serviceEntityPK); |
| } |
| |
| @Override |
| public void setMaintenanceState(MaintenanceState state) { |
| ServiceDesiredStateEntity serviceDesiredStateEntity = getServiceDesiredStateEntity(); |
| serviceDesiredStateEntity.setMaintenanceState(state); |
| maintenanceState.set(serviceDesiredStateDAO.merge(serviceDesiredStateEntity).getMaintenanceState()); |
| |
| // broadcast the maintenance mode change |
| MaintenanceModeEvent event = new MaintenanceModeEvent(state, this); |
| eventPublisher.publish(event); |
| } |
| |
| @Override |
| public MaintenanceState getMaintenanceState() { |
| if (maintenanceState.get() == null) { |
| maintenanceState.set(getServiceDesiredStateEntity().getMaintenanceState()); |
| } |
| return maintenanceState.get(); |
| } |
| |
| @Override |
| public boolean isKerberosEnabled() { |
| if (kerberosEnabledTest != null) { |
| Map<String, Map<String, String>> existingConfigurations; |
| |
| try { |
| existingConfigurations = configHelper.calculateExistingConfigurations(ambariManagementController, cluster); |
| } catch (AmbariException e) { |
| LOG.warn("Failed to get the existing configurations for the cluster. Predicate calculations may not be correct due to missing data."); |
| existingConfigurations = Collections.emptyMap(); |
| } |
| return isKerberosEnabled(existingConfigurations); |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public boolean isKerberosEnabled(Map<String, Map<String, String>> configurations) { |
| return kerberosEnabledTest != null && kerberosEnabledTest.evaluate(configurations); |
| } |
| |
| |
| private ClusterServiceEntityPK getServiceEntityPK(ClusterServiceEntity serviceEntity) { |
| ClusterServiceEntityPK pk = new ClusterServiceEntityPK(); |
| pk.setClusterId(serviceEntity.getClusterId()); |
| pk.setServiceName(serviceEntity.getServiceName()); |
| return pk; |
| } |
| |
| private ServiceDesiredStateEntityPK getServiceDesiredStateEntityPK(ServiceDesiredStateEntity serviceDesiredStateEntity) { |
| ServiceDesiredStateEntityPK pk = new ServiceDesiredStateEntityPK(); |
| pk.setClusterId(serviceDesiredStateEntity.getClusterId()); |
| pk.setServiceName(serviceDesiredStateEntity.getServiceName()); |
| return pk; |
| } |
| |
| // Refresh the cached reference on setters |
| private ServiceDesiredStateEntity getServiceDesiredStateEntity() { |
| return serviceDesiredStateDAO.findByPK(serviceDesiredStateEntityPK); |
| } |
| |
| private Predicate compileSsoEnabledPredicate(ServiceInfo sInfo) { |
| if (StringUtils.isNotBlank(sInfo.getSingleSignOnEnabledTest())) { |
| if (StringUtils.isNotBlank(sInfo.getSingleSignOnEnabledConfiguration())) { |
| LOG.warn("Both <ssoEnabledTest> and <enabledConfiguration> have been declared within <sso> for {}; using <ssoEnabledTest>", serviceName); |
| } |
| return PredicateUtils.fromJSON(sInfo.getSingleSignOnEnabledTest()); |
| } else if (StringUtils.isNotBlank(sInfo.getSingleSignOnEnabledConfiguration())) { |
| LOG.warn("Only <enabledConfiguration> have been declared within <sso> for {}; converting its value to an equals predicate", serviceName); |
| final String equalsPredicateJson = "{\"equals\": [\"" + sInfo.getSingleSignOnEnabledConfiguration() + "\", \"true\"]}"; |
| return PredicateUtils.fromJSON(equalsPredicateJson); |
| } |
| return null; |
| } |
| |
| private Predicate compileKerberosEnabledPredicate(ServiceInfo sInfo) { |
| if (StringUtils.isNotBlank(sInfo.getKerberosEnabledTest())) { |
| return PredicateUtils.fromJSON(sInfo.getKerberosEnabledTest()); |
| } |
| return null; |
| } |
| |
| private boolean isSsoIntegrationDesired() { |
| return ambariServerSSOConfigurationHandler.getSSOEnabledServices().contains(serviceName); |
| } |
| |
| private boolean isSsoIntegrationEnabled(Map<String, Map<String, String>> existingConfigurations) { |
| return ssoIntegrationSupported && ssoEnabledTest != null && ssoEnabledTest.evaluate(existingConfigurations); |
| } |
| |
| private boolean isKerberosRequiredForSsoIntegration() { |
| return ssoRequiresKerberos; |
| } |
| |
| private boolean isLdapIntegrationEnabeled(Map<String, Map<String, String>> existingConfigurations) { |
| return ldapIntegrationSupported && ldapEnabledTest != null && ldapEnabledTest.evaluate(existingConfigurations); |
| } |
| |
| private boolean isLdapIntegrationDesired() { |
| return ambariServerLDAPConfigurationHandler.getLDAPEnabledServices().contains(serviceName); |
| } |
| } |