/** * 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.svccomphost; import java.text.MessageFormat; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.agent.AlertDefinitionCommand; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.ServiceComponentHostResponse; import org.apache.ambari.server.events.AlertHashInvalidationEvent; import org.apache.ambari.server.events.MaintenanceModeEvent; import org.apache.ambari.server.events.ServiceComponentInstalledEvent; import org.apache.ambari.server.events.ServiceComponentUninstalledEvent; import org.apache.ambari.server.events.publishers.AmbariEventPublisher; import org.apache.ambari.server.orm.dao.HostComponentDesiredStateDAO; import org.apache.ambari.server.orm.dao.HostComponentStateDAO; import org.apache.ambari.server.orm.dao.HostDAO; import org.apache.ambari.server.orm.dao.RepositoryVersionDAO; import org.apache.ambari.server.orm.dao.ServiceComponentDesiredStateDAO; import org.apache.ambari.server.orm.dao.StackDAO; import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity; import org.apache.ambari.server.orm.entities.HostComponentStateEntity; import org.apache.ambari.server.orm.entities.HostEntity; import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity; import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.ComponentInfo; import org.apache.ambari.server.state.ConfigHelper; import org.apache.ambari.server.state.DesiredConfig; import org.apache.ambari.server.state.Host; import org.apache.ambari.server.state.HostComponentAdminState; import org.apache.ambari.server.state.HostConfig; import org.apache.ambari.server.state.HostState; import org.apache.ambari.server.state.MaintenanceState; import org.apache.ambari.server.state.SecurityState; import org.apache.ambari.server.state.ServiceComponent; import org.apache.ambari.server.state.ServiceComponentHost; import org.apache.ambari.server.state.ServiceComponentHostEvent; import org.apache.ambari.server.state.ServiceComponentHostEventType; import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.state.StackInfo; import org.apache.ambari.server.state.State; import org.apache.ambari.server.state.UpgradeState; import org.apache.ambari.server.state.alert.AlertDefinitionHash; import org.apache.ambari.server.state.configgroup.ConfigGroup; import org.apache.ambari.server.state.fsm.InvalidStateTransitionException; import org.apache.ambari.server.state.fsm.SingleArcTransition; import org.apache.ambari.server.state.fsm.StateMachine; import org.apache.ambari.server.state.fsm.StateMachineFactory; import org.apache.ambari.server.state.stack.upgrade.RepositoryVersionHelper; import org.jboss.netty.util.internal.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableList; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; import com.google.inject.persist.Transactional; public class ServiceComponentHostImpl implements ServiceComponentHost { private static final Logger LOG = LoggerFactory.getLogger(ServiceComponentHostImpl.class); private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final Lock writeLock = readWriteLock.writeLock(); private final ServiceComponent serviceComponent; private final Host host; private final HostComponentStateDAO hostComponentStateDAO; private final HostComponentDesiredStateDAO hostComponentDesiredStateDAO; private final HostDAO hostDAO; @Inject private RepositoryVersionDAO repositoryVersionDAO; private final ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO; private final Clusters clusters; @Inject private ConfigHelper helper; @Inject private AmbariMetaInfo ambariMetaInfo; @Inject private RepositoryVersionHelper repositoryVersionHelper; /** * Used for creating commands to send to the agents when alert definitions are * added as the result of a service install. */ @Inject private AlertDefinitionHash alertDefinitionHash; /** * Used to publish events relating to service CRUD operations. */ private final AmbariEventPublisher eventPublisher; /** * Data access object for stack. */ private final StackDAO stackDAO; /** * The desired component state entity id. */ private final Long desiredStateEntityId; /** * Cache the generated id for host component state for fast lookups. */ private final Long hostComponentStateId; private long lastOpStartTime; private long lastOpEndTime; private long lastOpLastUpdateTime; private ConcurrentMap<String, HostConfig> actualConfigs = new ConcurrentHashMap<>(); private ImmutableList<Map<String, String>> processes = ImmutableList.of(); /** * The name of the host (which should never, ever change) */ private final String hostName; private static final StateMachineFactory <ServiceComponentHostImpl, State, ServiceComponentHostEventType, ServiceComponentHostEvent> daemonStateMachineFactory = new StateMachineFactory<ServiceComponentHostImpl, State, ServiceComponentHostEventType, ServiceComponentHostEvent> (State.INIT) // define the state machine of a HostServiceComponent for runnable // components .addTransition(State.INIT, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLING, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALLING, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new AlertDefinitionCommandTransition()) .addTransition(State.INSTALLED, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) // Allow transition on abort .addTransition(State.INSTALLED, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALLING, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.INSTALLING, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLING, State.INSTALL_FAILED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALL_FAILED, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_RESTART, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALL_FAILED, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) // Allow transition on abort .addTransition(State.INSTALL_FAILED, State.INSTALL_FAILED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALLED, State.STARTING, ServiceComponentHostEventType.HOST_SVCCOMP_START, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLED, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_UNINSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLED, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLED, State.STOPPING, ServiceComponentHostEventType.HOST_SVCCOMP_STOP, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLED, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_UPGRADE, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLED, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.INSTALLED, State.STARTED, ServiceComponentHostEventType.HOST_SVCCOMP_STARTED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALLED, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_STOPPED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.STARTING, State.STARTING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.STARTING, State.STARTING, ServiceComponentHostEventType.HOST_SVCCOMP_START, new ServiceComponentHostOpStartedTransition()) .addTransition(State.STARTING, State.STARTED, ServiceComponentHostEventType.HOST_SVCCOMP_STARTED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.STARTING, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALLED, State.STARTING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_RESTART, new ServiceComponentHostOpStartedTransition()) .addTransition(State.STARTED, State.STARTED, ServiceComponentHostEventType.HOST_SVCCOMP_STARTED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.STARTED, State.STOPPING, ServiceComponentHostEventType.HOST_SVCCOMP_STOP, new ServiceComponentHostOpStartedTransition()) .addTransition(State.STARTED, State.STARTED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) // Allow transition on abort .addTransition(State.STARTED, State.STARTED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.STARTED, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_STOPPED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.STOPPING, State.STOPPING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.STOPPING, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_STOPPED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.STOPPING, State.STARTED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.STARTED, State.STOPPING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_RESTART, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UPGRADING, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.UPGRADING, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UPGRADING, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UPGRADING, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_UPGRADE, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UPGRADING, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_UPGRADE, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_RESTART, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_UNINSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UNINSTALLED, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UNINSTALLED, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_WIPEOUT, new ServiceComponentHostOpStartedTransition()) .addTransition(State.WIPING_OUT, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.WIPING_OUT, State.INIT, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.WIPING_OUT, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.WIPING_OUT, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_OP_RESTART, new ServiceComponentHostOpStartedTransition()) .addTransition(State.WIPING_OUT, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_WIPEOUT, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLED, State.DISABLED, ServiceComponentHostEventType.HOST_SVCCOMP_DISABLE, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.DISABLED, State.DISABLED, ServiceComponentHostEventType.HOST_SVCCOMP_DISABLE, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UNKNOWN, State.DISABLED, ServiceComponentHostEventType.HOST_SVCCOMP_DISABLE, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UNKNOWN, State.UNKNOWN, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALL_FAILED, State.DISABLED, ServiceComponentHostEventType.HOST_SVCCOMP_DISABLE, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.DISABLED, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_RESTORE, new ServiceComponentHostOpCompletedTransition()) .installTopology(); private static final StateMachineFactory <ServiceComponentHostImpl, State, ServiceComponentHostEventType, ServiceComponentHostEvent> clientStateMachineFactory = new StateMachineFactory<ServiceComponentHostImpl, State, ServiceComponentHostEventType, ServiceComponentHostEvent> (State.INIT) // define the state machine of a HostServiceComponent for client only // components .addTransition(State.INIT, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLING, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALLING, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLING, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.INSTALLED, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) // Allow transition on abort .addTransition(State.INSTALLED, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALLING, State.INSTALL_FAILED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALL_FAILED, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_RESTART, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALL_FAILED, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) // Allow transition on abort .addTransition(State.INSTALL_FAILED, State.INSTALL_FAILED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALL_FAILED, State.INSTALL_FAILED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.INSTALLED, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.INSTALLED, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_UNINSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLED, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.INSTALLED, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_UPGRADE, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UPGRADING, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.UPGRADING, State.INSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UPGRADING, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UPGRADING, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_UPGRADE, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UPGRADING, State.UPGRADING, ServiceComponentHostEventType.HOST_SVCCOMP_UPGRADE, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLED, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_OP_RESTART, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UNINSTALLING, State.UNINSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_UNINSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UNINSTALLED, State.INSTALLING, ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL, new ServiceComponentHostOpStartedTransition()) .addTransition(State.UNINSTALLED, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_WIPEOUT, new ServiceComponentHostOpStartedTransition()) .addTransition(State.WIPING_OUT, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS, new ServiceComponentHostOpInProgressTransition()) .addTransition(State.WIPING_OUT, State.INIT, ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.WIPING_OUT, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED, new ServiceComponentHostOpCompletedTransition()) .addTransition(State.WIPING_OUT, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_OP_RESTART, new ServiceComponentHostOpStartedTransition()) .addTransition(State.WIPING_OUT, State.WIPING_OUT, ServiceComponentHostEventType.HOST_SVCCOMP_WIPEOUT, new ServiceComponentHostOpStartedTransition()) .installTopology(); private final StateMachine<State, ServiceComponentHostEventType, ServiceComponentHostEvent> stateMachine; static class ServiceComponentHostOpCompletedTransition implements SingleArcTransition<ServiceComponentHostImpl, ServiceComponentHostEvent> { @Override public void transition(ServiceComponentHostImpl impl, ServiceComponentHostEvent event) { // TODO Audit logs impl.updateLastOpInfo(event.getType(), event.getOpTimestamp()); } } /** * The {@link AlertDefinitionCommandTransition} is used to capture the * transition from {@link State#INSTALLING} to {@link State#INSTALLED} so that * the host affected will have new {@link AlertDefinitionCommand}s pushed to * it. */ static class AlertDefinitionCommandTransition implements SingleArcTransition<ServiceComponentHostImpl, ServiceComponentHostEvent> { @Override public void transition(ServiceComponentHostImpl impl, ServiceComponentHostEvent event) { if (event.getType() != ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED) { return; } // invalidate the host String hostName = impl.getHostName(); impl.alertDefinitionHash.invalidate(impl.getClusterName(), hostName); // publish the event AlertHashInvalidationEvent hashInvalidationEvent = new AlertHashInvalidationEvent( impl.getClusterId(), Collections.singletonList(hostName)); impl.eventPublisher.publish(hashInvalidationEvent); impl.updateLastOpInfo(event.getType(), event.getOpTimestamp()); } } static class ServiceComponentHostOpStartedTransition implements SingleArcTransition<ServiceComponentHostImpl, ServiceComponentHostEvent> { @Override public void transition(ServiceComponentHostImpl impl, ServiceComponentHostEvent event) { // TODO Audit logs // FIXME handle restartOp event impl.updateLastOpInfo(event.getType(), event.getOpTimestamp()); if (event.getType() == ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL) { ServiceComponentHostInstallEvent e = (ServiceComponentHostInstallEvent) event; if (LOG.isDebugEnabled()) { LOG.debug("Updating live stack version during INSTALL event" + ", new stack version=" + e.getStackId()); } impl.setStackVersion(new StackId(e.getStackId())); } } } static class ServiceComponentHostOpInProgressTransition implements SingleArcTransition<ServiceComponentHostImpl, ServiceComponentHostEvent> { @Override public void transition(ServiceComponentHostImpl impl, ServiceComponentHostEvent event) { // TODO Audit logs impl.updateLastOpInfo(event.getType(), event.getOpTimestamp()); } } private void resetLastOpInfo() { setLastOpStartTime(-1); setLastOpLastUpdateTime(-1); setLastOpEndTime(-1); } private void updateLastOpInfo(ServiceComponentHostEventType eventType, long time) { try { writeLock.lock(); switch (eventType) { case HOST_SVCCOMP_INSTALL: case HOST_SVCCOMP_START: case HOST_SVCCOMP_STOP: case HOST_SVCCOMP_UNINSTALL: case HOST_SVCCOMP_WIPEOUT: case HOST_SVCCOMP_OP_RESTART: resetLastOpInfo(); setLastOpStartTime(time); break; case HOST_SVCCOMP_OP_FAILED: case HOST_SVCCOMP_OP_SUCCEEDED: case HOST_SVCCOMP_STOPPED: case HOST_SVCCOMP_STARTED: setLastOpLastUpdateTime(time); setLastOpEndTime(time); break; case HOST_SVCCOMP_OP_IN_PROGRESS: setLastOpLastUpdateTime(time); break; } } finally { writeLock.unlock(); } } @AssistedInject public ServiceComponentHostImpl(@Assisted ServiceComponent serviceComponent, @Assisted String hostName, Clusters clusters, StackDAO stackDAO, HostDAO hostDAO, ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO, HostComponentStateDAO hostComponentStateDAO, HostComponentDesiredStateDAO hostComponentDesiredStateDAO, AmbariEventPublisher eventPublisher) { this.serviceComponent = serviceComponent; this.hostName = hostName; this.clusters = clusters; this.stackDAO = stackDAO; this.hostDAO = hostDAO; this.serviceComponentDesiredStateDAO = serviceComponentDesiredStateDAO; this.hostComponentStateDAO = hostComponentStateDAO; this.hostComponentDesiredStateDAO = hostComponentDesiredStateDAO; this.eventPublisher = eventPublisher; if (serviceComponent.isClientComponent()) { stateMachine = clientStateMachineFactory.make(this); } else { stateMachine = daemonStateMachineFactory.make(this); } HostEntity hostEntity = null; try { host = clusters.getHost(hostName); hostEntity = hostDAO.findByName(hostName); if (hostEntity == null) { throw new AmbariException("Could not find host " + hostName); } } catch (AmbariException e) { LOG.error("Host '{}' was not found" + hostName); throw new RuntimeException(e); } StackId stackId = serviceComponent.getDesiredStackVersion(); StackEntity stackEntity = stackDAO.find(stackId.getStackName(), stackId.getStackVersion()); HostComponentStateEntity stateEntity = new HostComponentStateEntity(); stateEntity.setClusterId(serviceComponent.getClusterId()); stateEntity.setComponentName(serviceComponent.getName()); stateEntity.setServiceName(serviceComponent.getServiceName()); stateEntity.setVersion(State.UNKNOWN.toString()); stateEntity.setHostEntity(hostEntity); stateEntity.setCurrentState(stateMachine.getCurrentState()); stateEntity.setUpgradeState(UpgradeState.NONE); stateEntity.setCurrentStack(stackEntity); HostComponentDesiredStateEntity desiredStateEntity = new HostComponentDesiredStateEntity(); desiredStateEntity.setClusterId(serviceComponent.getClusterId()); desiredStateEntity.setComponentName(serviceComponent.getName()); desiredStateEntity.setServiceName(serviceComponent.getServiceName()); desiredStateEntity.setHostEntity(hostEntity); desiredStateEntity.setDesiredState(State.INIT); desiredStateEntity.setDesiredStack(stackEntity); if(!serviceComponent.isMasterComponent() && !serviceComponent.isClientComponent()) { desiredStateEntity.setAdminState(HostComponentAdminState.INSERVICE); } else { desiredStateEntity.setAdminState(null); } persistEntities(hostEntity, stateEntity, desiredStateEntity); // publish the service component installed event ServiceComponentInstalledEvent event = new ServiceComponentInstalledEvent(getClusterId(), stackId.getStackName(), stackId.getStackVersion(), getServiceName(), getServiceComponentName(), getHostName(), isRecoveryEnabled()); eventPublisher.publish(event); desiredStateEntityId = desiredStateEntity.getId(); hostComponentStateId = stateEntity.getId(); resetLastOpInfo(); } @AssistedInject public ServiceComponentHostImpl(@Assisted ServiceComponent serviceComponent, @Assisted HostComponentStateEntity stateEntity, @Assisted HostComponentDesiredStateEntity desiredStateEntity, Clusters clusters, StackDAO stackDAO, HostDAO hostDAO, ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO, HostComponentStateDAO hostComponentStateDAO, HostComponentDesiredStateDAO hostComponentDesiredStateDAO, AmbariEventPublisher eventPublisher) { hostName = stateEntity.getHostName(); this.serviceComponent = serviceComponent; this.clusters = clusters; this.stackDAO = stackDAO; this.hostDAO = hostDAO; this.serviceComponentDesiredStateDAO = serviceComponentDesiredStateDAO; this.hostComponentStateDAO = hostComponentStateDAO; this.hostComponentDesiredStateDAO = hostComponentDesiredStateDAO; this.eventPublisher = eventPublisher; desiredStateEntityId = desiredStateEntity.getId(); hostComponentStateId = stateEntity.getId(); //TODO implement State Machine init as now type choosing is hardcoded in above code if (serviceComponent.isClientComponent()) { stateMachine = clientStateMachineFactory.make(this); } else { stateMachine = daemonStateMachineFactory.make(this); } stateMachine.setCurrentState(stateEntity.getCurrentState()); try { host = clusters.getHost(stateEntity.getHostName()); } catch (AmbariException e) { //TODO exception? impossible due to database restrictions LOG.error("Host '{}' was not found " + stateEntity.getHostName()); throw new RuntimeException(e); } } @Override public State getState() { // there's no reason to lock around the state machine for this SCH since // the state machine is synchronized return stateMachine.getCurrentState(); } @Override public void setState(State state) { stateMachine.setCurrentState(state); HostComponentStateEntity stateEntity = getStateEntity(); if (stateEntity != null) { stateEntity.setCurrentState(state); stateEntity = hostComponentStateDAO.merge(stateEntity); } else { LOG.warn("Setting a member on an entity object that may have been " + "previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } } @Override public String getVersion() { HostComponentStateEntity stateEntity = getStateEntity(); if (stateEntity != null) { return stateEntity.getVersion(); } else { LOG.warn("Trying to fetch a member from an entity object that may " + "have been previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } return null; } @Override public void setVersion(String version) { HostComponentStateEntity stateEntity = getStateEntity(); if (stateEntity != null) { stateEntity.setVersion(version); stateEntity = hostComponentStateDAO.merge(stateEntity); } else { LOG.warn("Setting a member on an entity object that may have been " + "previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } } @Override public SecurityState getSecurityState() { HostComponentStateEntity stateEntity = getStateEntity(); if (stateEntity != null) { return stateEntity.getSecurityState(); } else { LOG.warn("Trying to fetch a member from an entity object that may " + "have been previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } return null; } @Override public void setSecurityState(SecurityState securityState) { HostComponentStateEntity stateEntity = getStateEntity(); if (stateEntity != null) { stateEntity.setSecurityState(securityState); stateEntity = hostComponentStateDAO.merge(stateEntity); } else { LOG.warn("Setting a member on an entity object that may have been " + "previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } } @Override public SecurityState getDesiredSecurityState() { HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); if (desiredStateEntity != null) { return desiredStateEntity.getSecurityState(); } else { LOG.warn("Trying to fetch a member from an entity object that may " + "have been previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } return null; } @Override public void setDesiredSecurityState(SecurityState securityState) throws AmbariException { if(!securityState.isEndpoint()) { throw new AmbariException("The security state must be an endpoint state"); } LOG.debug("Set DesiredSecurityState on serviceName = {} componentName = {} hostName = {} to {}", getServiceName(), getServiceComponentName(), getHostName(), securityState); HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); desiredStateEntity.setSecurityState(securityState); hostComponentDesiredStateDAO.merge(desiredStateEntity); } /** * To be called during the upgrade of a specific Component in a host. * The potential upgrade states are NONE (default), PENDING, IN_PROGRESS, FAILED. * If the upgrade completes successfully, the upgradeState should be set back to NONE. * If the upgrade fails, then the user can retry to set it back into PENDING or IN_PROGRESS. * If the upgrade is aborted, then the upgradeState should be set back to NONE. * * @param upgradeState the upgrade state */ @Override public void setUpgradeState(UpgradeState upgradeState) { HostComponentStateEntity stateEntity = getStateEntity(); if (stateEntity != null) { stateEntity.setUpgradeState(upgradeState); stateEntity = hostComponentStateDAO.merge(stateEntity); } else { LOG.warn("Setting a member on an entity object that may have been " + "previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } } @Override public UpgradeState getUpgradeState() { HostComponentStateEntity stateEntity = getStateEntity(); if (stateEntity != null) { return stateEntity.getUpgradeState(); } else { LOG.warn("Trying to fetch a state entity from an object that may " + "have been previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } return UpgradeState.NONE; } @Override public void handleEvent(ServiceComponentHostEvent event) throws InvalidStateTransitionException { if (LOG.isDebugEnabled()) { LOG.debug("Handling ServiceComponentHostEvent event," + " eventType=" + event.getType().name() + ", event=" + event.toString()); } State oldState = getState(); try { writeLock.lock(); try { stateMachine.doTransition(event.getType(), event); HostComponentStateEntity stateEntity = getStateEntity(); stateEntity.setCurrentState(stateMachine.getCurrentState()); stateEntity = hostComponentStateDAO.merge(stateEntity); // TODO Audit logs } catch (InvalidStateTransitionException e) { LOG.error("Can't handle ServiceComponentHostEvent event at" + " current state" + ", serviceComponentName=" + getServiceComponentName() + ", hostName=" + getHostName() + ", currentState=" + oldState + ", eventType=" + event.getType() + ", event=" + event); throw e; } } finally { writeLock.unlock(); } if (!oldState.equals(getState())) { LOG.info("Host role transitioned to a new state" + ", serviceComponentName=" + getServiceComponentName() + ", hostName=" + getHostName() + ", oldState=" + oldState + ", currentState=" + getState()); if (LOG.isDebugEnabled()) { LOG.debug("ServiceComponentHost transitioned to a new state" + ", serviceComponentName=" + getServiceComponentName() + ", hostName=" + getHostName() + ", oldState=" + oldState + ", currentState=" + getState() + ", eventType=" + event.getType().name() + ", event=" + event); } } } @Override public String getServiceComponentName() { return serviceComponent.getName(); } @Override public String getHostName() { return host.getHostName(); } @Override public String getPublicHostName() { return host.getPublicHostName(); } @Override public Host getHost() { return host; } /** * @return the lastOpStartTime */ public long getLastOpStartTime() { return lastOpStartTime; } /** * @param lastOpStartTime the lastOpStartTime to set */ public void setLastOpStartTime(long lastOpStartTime) { this.lastOpStartTime = lastOpStartTime; } /** * @return the lastOpEndTime */ public long getLastOpEndTime() { return lastOpEndTime; } /** * @param lastOpEndTime the lastOpEndTime to set */ public void setLastOpEndTime(long lastOpEndTime) { this.lastOpEndTime = lastOpEndTime; } /** * @return the lastOpLastUpdateTime */ public long getLastOpLastUpdateTime() { return lastOpLastUpdateTime; } /** * @param lastOpLastUpdateTime the lastOpLastUpdateTime to set */ public void setLastOpLastUpdateTime(long lastOpLastUpdateTime) { this.lastOpLastUpdateTime = lastOpLastUpdateTime; } @Override public long getClusterId() { return serviceComponent.getClusterId(); } @Override public String getServiceName() { return serviceComponent.getServiceName(); } @Override public boolean isClientComponent() { return serviceComponent.isClientComponent(); } @Override public StackId getStackVersion() { HostComponentStateEntity schStateEntity = getStateEntity(); return getStackVersionFromSCHStateEntity(schStateEntity); } private StackId getStackVersionFromSCHStateEntity(HostComponentStateEntity schStateEntity) { if (schStateEntity == null) { return new StackId(); } StackEntity currentStackEntity = schStateEntity.getCurrentStack(); return new StackId(currentStackEntity.getStackName(), currentStackEntity.getStackVersion()); } @Override public void setStackVersion(StackId stackId) { StackEntity stackEntity = stackDAO.find(stackId.getStackName(), stackId.getStackVersion()); HostComponentStateEntity stateEntity = getStateEntity(); if (stateEntity != null) { stateEntity.setCurrentStack(stackEntity); stateEntity = hostComponentStateDAO.merge(stateEntity); } else { LOG.warn("Setting a member on an entity object that may have been " + "previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } } @Override public State getDesiredState() { HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); if (desiredStateEntity != null) { return desiredStateEntity.getDesiredState(); } else { LOG.warn("Trying to fetch a member from an entity object that may " + "have been previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } return null; } @Override public void setDesiredState(State state) { LOG.debug("Set DesiredState on serviceName = {} componentName = {} hostName = {} to {} ", getServiceName(), getServiceComponentName(), getHostName(), state); HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); if (desiredStateEntity != null) { desiredStateEntity.setDesiredState(state); hostComponentDesiredStateDAO.merge(desiredStateEntity); } else { LOG.warn("Setting a member on an entity object that may have been " + "previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + "hostName = " + getHostName()); } } @Override public StackId getDesiredStackVersion() { HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); return getDesiredStackVersionFromHostComponentDesiredStateEntity(desiredStateEntity); } private StackId getDesiredStackVersionFromHostComponentDesiredStateEntity(HostComponentDesiredStateEntity desiredStateEntity) { if (desiredStateEntity != null) { StackEntity desiredStackEntity = desiredStateEntity.getDesiredStack(); return new StackId(desiredStackEntity.getStackName(), desiredStackEntity.getStackVersion()); } else { LOG.warn("Trying to fetch a member from an entity object that may " + "have been previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", " + "hostName = " + getHostName()); } return null; } @Override public void setDesiredStackVersion(StackId stackId) { LOG.debug("Set DesiredStackVersion on serviceName = {} componentName = {} hostName = {} to {}", getServiceName(), getServiceComponentName(), getHostName(), stackId); HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); if (desiredStateEntity != null) { StackEntity stackEntity = stackDAO.find(stackId.getStackName(), stackId.getStackVersion()); desiredStateEntity.setDesiredStack(stackEntity); hostComponentDesiredStateDAO.merge(desiredStateEntity); } } @Override public HostComponentAdminState getComponentAdminState() { HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); return getComponentAdminStateFromDesiredStateEntity(desiredStateEntity); } private HostComponentAdminState getComponentAdminStateFromDesiredStateEntity(HostComponentDesiredStateEntity desiredStateEntity) { if (desiredStateEntity != null) { HostComponentAdminState adminState = desiredStateEntity.getAdminState(); if (adminState == null && !serviceComponent.isClientComponent() && !serviceComponent.isMasterComponent()) { adminState = HostComponentAdminState.INSERVICE; } return adminState; } return null; } @Override public void setComponentAdminState(HostComponentAdminState attribute) { LOG.debug("Set ComponentAdminState on serviceName = {} componentName = {} hostName = {} to {}", getServiceName(), getServiceComponentName(), getHostName(), attribute); HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); if (desiredStateEntity != null) { desiredStateEntity.setAdminState(attribute); hostComponentDesiredStateDAO.merge(desiredStateEntity); } else { LOG.warn("Setting a member on an entity object that may have been " + "previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + "hostName = " + getHostName()); } } @Override public ServiceComponentHostResponse convertToResponse(Map<String, DesiredConfig> desiredConfigs) { HostComponentStateEntity hostComponentStateEntity = getStateEntity(); HostEntity hostEntity = hostComponentStateEntity.getHostEntity(); if (null == hostComponentStateEntity) { LOG.warn( "Could not convert ServiceComponentHostResponse to a response. It's possible that Host {} was deleted.", getHostName()); return null; } StackId stackVersion = getStackVersionFromSCHStateEntity(hostComponentStateEntity); HostComponentDesiredStateEntity hostComponentDesiredStateEntity = getDesiredStateEntity(); String clusterName = serviceComponent.getClusterName(); String serviceName = serviceComponent.getServiceName(); String serviceComponentName = serviceComponent.getName(); String hostName = getHostName(); String publicHostName = hostEntity.getPublicHostName(); String state = getState().toString(); String stackId = stackVersion.getStackId(); String desiredState = (hostComponentDesiredStateEntity == null) ? null : hostComponentDesiredStateEntity.getDesiredState().toString(); String desiredStackId = getDesiredStackVersionFromHostComponentDesiredStateEntity(hostComponentDesiredStateEntity).getStackId(); HostComponentAdminState componentAdminState = getComponentAdminStateFromDesiredStateEntity(hostComponentDesiredStateEntity); UpgradeState upgradeState = hostComponentStateEntity.getUpgradeState(); String displayName = null; try { ComponentInfo compInfo = ambariMetaInfo.getComponent(stackVersion.getStackName(), stackVersion.getStackVersion(), serviceName, serviceComponentName); displayName = compInfo.getDisplayName(); } catch (AmbariException e) { displayName = serviceComponentName; } ServiceComponentHostResponse r = new ServiceComponentHostResponse(clusterName, serviceName, serviceComponentName, displayName, hostName, publicHostName, state, stackId, desiredState, desiredStackId, componentAdminState); r.setActualConfigs(actualConfigs); r.setUpgradeState(upgradeState); try { r.setStaleConfig(helper.isStaleConfigs(this, desiredConfigs, hostComponentDesiredStateEntity)); } catch (Exception e) { LOG.error("Could not determine stale config", e); } return r; } @Override public String getClusterName() { return serviceComponent.getClusterName(); } @Override public void debugDump(StringBuilder sb) { sb.append("ServiceComponentHost={ hostname=").append(getHostName()) .append(", serviceComponentName=") .append(serviceComponent.getName()) .append(", clusterName=") .append(serviceComponent.getClusterName()) .append(", serviceName=") .append(serviceComponent.getServiceName()) .append(", desiredStackVersion=") .append(getDesiredStackVersion()) .append(", desiredState=") .append(getDesiredState()) .append(", stackVersion=") .append(getStackVersion()) .append(", state=") .append(getState()) .append(", securityState=") .append(getSecurityState()) .append(", desiredSecurityState=") .append(getDesiredSecurityState()) .append(" }"); } @Transactional void persistEntities(HostEntity hostEntity, HostComponentStateEntity stateEntity, HostComponentDesiredStateEntity desiredStateEntity) { ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.findByName( serviceComponent.getClusterId(), serviceComponent.getServiceName(), serviceComponent.getName()); desiredStateEntity.setServiceComponentDesiredStateEntity(serviceComponentDesiredStateEntity); desiredStateEntity.setHostEntity(hostEntity); stateEntity.setServiceComponentDesiredStateEntity(serviceComponentDesiredStateEntity); stateEntity.setHostEntity(hostEntity); hostComponentStateDAO.create(stateEntity); hostComponentDesiredStateDAO.create(desiredStateEntity); serviceComponentDesiredStateEntity.getHostComponentDesiredStateEntities().add( desiredStateEntity); serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.merge( serviceComponentDesiredStateEntity); hostEntity.addHostComponentStateEntity(stateEntity); hostEntity.addHostComponentDesiredStateEntity(desiredStateEntity); hostEntity = hostDAO.merge(hostEntity); } @Override public boolean canBeRemoved() { return getState().isRemovableState(); } @Override public void delete() { boolean fireRemovalEvent = false; writeLock.lock(); try { removeEntities(); fireRemovalEvent = true; clusters.getCluster(getClusterName()).removeServiceComponentHost(this); } catch (AmbariException ex) { LOG.error("Unable to remove a service component from a host", ex); } finally { writeLock.unlock(); } // publish event for the removal of the SCH after the removal is // completed, but only if it was persisted if (fireRemovalEvent) { long clusterId = getClusterId(); StackId stackId = getStackVersion(); String stackVersion = stackId.getStackVersion(); String stackName = stackId.getStackName(); String serviceName = getServiceName(); String componentName = getServiceComponentName(); String hostName = getHostName(); boolean recoveryEnabled = isRecoveryEnabled(); ServiceComponentUninstalledEvent event = new ServiceComponentUninstalledEvent( clusterId, stackName, stackVersion, serviceName, componentName, hostName, recoveryEnabled); eventPublisher.publish(event); } } @Transactional protected void removeEntities() { HostComponentStateEntity stateEntity = getStateEntity(); if (stateEntity != null) { HostEntity hostEntity = stateEntity.getHostEntity(); HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); // Make sure that the state entity is removed from its host entity hostEntity.removeHostComponentStateEntity(stateEntity); hostEntity.removeHostComponentDesiredStateEntity(desiredStateEntity); hostDAO.merge(hostEntity); hostComponentDesiredStateDAO.remove(desiredStateEntity); hostComponentStateDAO.remove(stateEntity); } } @Override public void updateActualConfigs(Map<String, Map<String, String>> configTags) { Map<Long, ConfigGroup> configGroupMap; String clusterName = getClusterName(); try { Cluster cluster = clusters.getCluster(clusterName); configGroupMap = cluster.getConfigGroups(); } catch (AmbariException e) { LOG.warn("Unable to find cluster, " + clusterName); return; } LOG.debug("Updating configuration tags for {}: {}", hostName, configTags); final ConcurrentMap<String, HostConfig> newActualConfigs = new ConcurrentHashMap<>(); for (Entry<String, Map<String, String>> entry : configTags.entrySet()) { String type = entry.getKey(); Map<String, String> values = new HashMap<>(entry.getValue()); String tag = values.get(ConfigHelper.CLUSTER_DEFAULT_TAG); values.remove(ConfigHelper.CLUSTER_DEFAULT_TAG); HostConfig hc = new HostConfig(); hc.setDefaultVersionTag(tag); newActualConfigs.put(type, hc); if (!values.isEmpty()) { for (Entry<String, String> overrideEntry : values.entrySet()) { Long groupId = Long.parseLong(overrideEntry.getKey()); hc.getConfigGroupOverrides().put(groupId, overrideEntry.getValue()); if (!configGroupMap.containsKey(groupId)) { LOG.debug("Config group does not exist, id = " + groupId); } } } } // update internal stateful collection in an "atomic" manner actualConfigs = newActualConfigs; } @Override public Map<String, HostConfig> getActualConfigs() { return actualConfigs; } @Override public HostState getHostState() { return host.getState(); } @Override public boolean isRecoveryEnabled() { return serviceComponent.isRecoveryEnabled(); } @Override public void setMaintenanceState(MaintenanceState state) { LOG.debug("Set MaintenanceState on serviceName = {} componentName = {} hostName = {} to {}", getServiceName(), getServiceComponentName(), getHostName(), state); HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); if (desiredStateEntity != null) { desiredStateEntity.setMaintenanceState(state); hostComponentDesiredStateDAO.merge(desiredStateEntity); // broadcast the maintenance mode change MaintenanceModeEvent event = new MaintenanceModeEvent(state, this); eventPublisher.publish(event); } else { LOG.warn("Setting a member on an entity object that may have been " + "previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", hostName = " + getHostName()); } } @Override public MaintenanceState getMaintenanceState() { return getDesiredStateEntity().getMaintenanceState(); } @Override public void setProcesses(List<Map<String, String>> procs) { processes = ImmutableList.copyOf(procs); } @Override public List<Map<String, String>> getProcesses() { return processes; } @Override public boolean isRestartRequired() { return getDesiredStateEntity().isRestartRequired(); } @Override public boolean isRestartRequired(HostComponentDesiredStateEntity hostComponentDesiredStateEntity) { return hostComponentDesiredStateEntity.isRestartRequired(); } @Override @Transactional public void setRestartRequired(boolean restartRequired) { LOG.debug("Set RestartRequired on serviceName = {} componentName = {} hostName = {} to {}", getServiceName(), getServiceComponentName(), getHostName(), restartRequired); HostComponentDesiredStateEntity desiredStateEntity = getDesiredStateEntity(); if (desiredStateEntity != null) { desiredStateEntity.setRestartRequired(restartRequired); hostComponentDesiredStateDAO.merge(desiredStateEntity); } else { LOG.warn("Setting a member on an entity object that may have been " + "previously deleted, serviceName = " + getServiceName() + ", " + "componentName = " + getServiceComponentName() + ", hostName = " + getHostName()); } } @Transactional RepositoryVersionEntity createRepositoryVersion(String version, final StackId stackId, final StackInfo stackInfo) throws AmbariException { // During an Ambari Upgrade from 1.7.0 -> 2.0.0, the Repo Version will not exist, so bootstrap it. LOG.info("Creating new repository version " + stackId.getStackName() + "-" + version); StackEntity stackEntity = stackDAO.find(stackId.getStackName(), stackId.getStackVersion()); // Ensure that the version provided is part of the Stack. // E.g., version 2.3.0.0 is part of HDP 2.3, so is 2.3.0.0-1234 if (null == version) { throw new AmbariException(MessageFormat.format("Cannot create Repository Version for Stack {0}-{1} if the version is empty", stackId.getStackName(), stackId.getStackVersion())); } return repositoryVersionDAO.create( stackEntity, version, stackId.getStackName() + "-" + version, repositoryVersionHelper.serializeOperatingSystems(stackInfo.getRepositories())); } /** * Bootstrap any Repo Version, and potentially transition the Host Version across states. * If a Host Component has a valid version, then create a Host Version if it does not already exist. * If a Host Component does not have a version, return right away because no information is known. * @return Return the Repository Version object * @throws AmbariException */ @Override public RepositoryVersionEntity recalculateHostVersionState() throws AmbariException { RepositoryVersionEntity repositoryVersion = null; String version = getVersion(); if (getUpgradeState().equals(UpgradeState.IN_PROGRESS) || getUpgradeState().equals(UpgradeState.VERSION_MISMATCH) || State.UNKNOWN.toString().equals(version)) { // TODO: we still recalculate host version if upgrading component failed. It seems to be ok // Recalculate only if no upgrade in progress/no version mismatch return null; } final String hostName = getHostName(); final long hostId = getHost().getHostId(); final Set<Cluster> clustersForHost = clusters.getClustersForHost(hostName); if (clustersForHost.size() != 1) { throw new AmbariException("Host " + hostName + " should be assigned only to one cluster"); } final Cluster cluster = clustersForHost.iterator().next(); final StackId stackId = cluster.getDesiredStackVersion(); final StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(), stackId.getStackVersion()); // Check if there is a Repo Version already for the version. // If it doesn't exist, will have to create it. repositoryVersion = repositoryVersionDAO.findByStackNameAndVersion(stackId.getStackName(), version); if (null == repositoryVersion) { repositoryVersion = createRepositoryVersion(version, stackId, stackInfo); } final HostEntity host = hostDAO.findById(hostId); cluster.transitionHostVersionState(host, repositoryVersion, stackId); return repositoryVersion; } /** * Gets the desired state entity for this {@link ServiceComponentHost}. * * @return */ @Override public HostComponentDesiredStateEntity getDesiredStateEntity() { return hostComponentDesiredStateDAO.findById(desiredStateEntityId); } /** * Gets the state entity for this {@link ServiceComponentHost}. * * @return the {@link HostComponentStateEntity} for this * {@link ServiceComponentHost}, or {@code null} if there is none. */ private HostComponentStateEntity getStateEntity() { return hostComponentStateDAO.findById(hostComponentStateId); } }