package com.sequenceiq.cloudbreak.core.flow2.stack.instance.termination; import static com.sequenceiq.cloudbreak.api.model.Status.AVAILABLE; import static com.sequenceiq.cloudbreak.api.model.Status.UPDATE_IN_PROGRESS; import java.util.Collections; import java.util.List; import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.sequenceiq.cloudbreak.api.model.DetailedStackStatus; import com.sequenceiq.cloudbreak.cloud.event.resource.RemoveInstanceResult; import com.sequenceiq.cloudbreak.common.type.HostMetadataState; import com.sequenceiq.cloudbreak.core.flow2.stack.FlowMessageService; import com.sequenceiq.cloudbreak.core.flow2.stack.Msg; import com.sequenceiq.cloudbreak.domain.HostMetadata; import com.sequenceiq.cloudbreak.domain.InstanceGroup; import com.sequenceiq.cloudbreak.domain.InstanceMetaData; import com.sequenceiq.cloudbreak.domain.Stack; import com.sequenceiq.cloudbreak.reactor.api.event.StackFailureEvent; import com.sequenceiq.cloudbreak.repository.HostMetadataRepository; import com.sequenceiq.cloudbreak.repository.StackUpdater; import com.sequenceiq.cloudbreak.service.stack.flow.ScalingFailedException; import com.sequenceiq.cloudbreak.service.stack.flow.StackScalingService; @Service public class InstanceTerminationService { private static final Logger LOGGER = LoggerFactory.getLogger(InstanceTerminationService.class); @Inject private StackUpdater stackUpdater; @Inject private StackScalingService stackScalingService; @Inject private FlowMessageService flowMessageService; @Inject private HostMetadataRepository hostMetadataRepository; public void instanceTermination(InstanceTerminationContext context) { Stack stack = context.getStack(); stackUpdater.updateStackStatus(stack.getId(), DetailedStackStatus.REMOVE_INSTANCE, "Removing instance"); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_REMOVING_INSTANCE, UPDATE_IN_PROGRESS.name()); List<InstanceMetaData> instanceMetaDataList = context.getInstanceMetaDataList(); for (InstanceMetaData instanceMetaData : instanceMetaDataList) { String hostName = instanceMetaData.getDiscoveryFQDN(); if (stack.getCluster() != null) { HostMetadata hostMetadata = hostMetadataRepository.findHostInClusterByName(stack.getCluster().getId(), hostName); if (hostMetadata == null) { LOGGER.info("Nothing to remove since hostmetadata is null"); } else if (hostMetadata != null && HostMetadataState.HEALTHY.equals(hostMetadata.getHostMetadataState())) { throw new ScalingFailedException(String.format("Host (%s) is in HEALTHY state. Cannot be removed.", hostName)); } } if (hostName != null) { String instanceGroupName = instanceMetaData.getInstanceGroup().getGroupName(); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_SCALING_TERMINATING_HOST_FROM_HOSTGROUP, UPDATE_IN_PROGRESS.name(), hostName, instanceGroupName); } } } public void finishInstanceTermination(InstanceTerminationContext context, RemoveInstanceResult payload) { Stack stack = context.getStack(); List<InstanceMetaData> instanceMetaDataList = context.getInstanceMetaDataList(); for (InstanceMetaData instanceMetaData : instanceMetaDataList) { String instanceId = instanceMetaData.getInstanceId(); InstanceGroup instanceGroup = stack.getInstanceGroupByInstanceGroupId(instanceMetaData.getInstanceGroup().getId()); stackScalingService.updateRemovedResourcesState(stack, Collections.singleton(instanceId), instanceGroup); if (stack.getCluster() != null) { HostMetadata hostMetadata = hostMetadataRepository.findHostInClusterByName(stack.getCluster().getId(), instanceMetaData.getDiscoveryFQDN()); if (hostMetadata != null) { LOGGER.info("Remove obsolete host: {}", hostMetadata.getHostName()); stackScalingService.removeHostmetadataIfExists(stack, instanceMetaData, hostMetadata); } } } LOGGER.info("Terminate instance result: {}", payload); stackUpdater.updateStackStatus(stack.getId(), DetailedStackStatus.AVAILABLE, "Instance removed"); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_REMOVING_INSTANCE_FINISHED, AVAILABLE.name()); } public void handleInstanceTerminationError(Stack stack, StackFailureEvent payload) { Exception ex = payload.getException(); LOGGER.error("Error during instance terminating flow:", ex); stackUpdater.updateStackStatus(stack.getId(), DetailedStackStatus.AVAILABLE, "Instance termination failed. " + ex.getMessage()); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_REMOVING_INSTANCE_FAILED, AVAILABLE.name(), ex.getMessage()); } }