package com.sequenceiq.cloudbreak.core.flow2.stack.start; import static com.sequenceiq.cloudbreak.api.model.Status.AVAILABLE; import static com.sequenceiq.cloudbreak.api.model.Status.STOPPED; 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.api.model.Status; import com.sequenceiq.cloudbreak.cloud.model.CloudVmMetaDataStatus; import com.sequenceiq.cloudbreak.common.type.BillingStatus; import com.sequenceiq.cloudbreak.core.flow2.stack.FlowMessageService; import com.sequenceiq.cloudbreak.core.flow2.stack.Msg; import com.sequenceiq.cloudbreak.domain.Stack; import com.sequenceiq.cloudbreak.logger.MDCBuilder; import com.sequenceiq.cloudbreak.reactor.api.event.StackFailureEvent; import com.sequenceiq.cloudbreak.repository.StackUpdater; import com.sequenceiq.cloudbreak.service.cluster.ClusterService; import com.sequenceiq.cloudbreak.service.cluster.flow.EmailSenderService; import com.sequenceiq.cloudbreak.service.stack.flow.MetadataSetupService; import com.sequenceiq.cloudbreak.service.stack.flow.WrongMetadataException; import com.sequenceiq.cloudbreak.service.usages.UsageService; import com.sequenceiq.cloudbreak.util.StackUtil; @Service public class StackStartStopService { private static final Logger LOGGER = LoggerFactory.getLogger(StackStartStopService.class); @Inject private StackUpdater stackUpdater; @Inject private FlowMessageService flowMessageService; @Inject private EmailSenderService emailSenderService; @Inject private ClusterService clusterService; @Inject private MetadataSetupService metadatSetupService; @Inject private UsageService usageService; @Inject private StackUtil stackUtil; public void startStackStart(StackStartStopContext context) { Stack stack = context.getStack(); MDCBuilder.buildMdcContext(stack); stackUpdater.updateStackStatus(stack.getId(), DetailedStackStatus.START_IN_PROGRESS, "Cluster infrastructure is now starting."); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_INFRASTRUCTURE_STARTING, Status.START_IN_PROGRESS.name()); } public void finishStackStart(Stack stack, List<CloudVmMetaDataStatus> coreInstanceMetaData) { if (coreInstanceMetaData.size() != stack.getFullNodeCount()) { throw new WrongMetadataException(String.format( "Size of the collected metadata set does not equal the node count of the stack. [metadata size=%s] [nodecount=%s]", coreInstanceMetaData.size(), stack.getFullNodeCount())); } metadatSetupService.saveInstanceMetaData(stack, coreInstanceMetaData, null); stackUpdater.updateStackStatus(stack.getId(), DetailedStackStatus.STARTED, "Cluster infrastructure started successfully."); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_INFRASTRUCTURE_STARTED, AVAILABLE.name()); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_BILLING_STARTED, BillingStatus.BILLING_STARTED.name()); usageService.startUsagesForStack(stack); } public void handleStackStartError(Stack stack, StackFailureEvent payload) { handleError(stack, payload.getException(), DetailedStackStatus.START_FAILED, Msg.STACK_INFRASTRUCTURE_START_FAILED, "Stack start failed: "); } public void startStackStop(StackStartStopContext context) { Stack stack = context.getStack(); if (isStopPossible(stack)) { MDCBuilder.buildMdcContext(stack); stackUpdater.updateStackStatus(context.getStack().getId(), DetailedStackStatus.STOP_IN_PROGRESS, "Cluster infrastructure is now stopping."); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_INFRASTRUCTURE_STOPPING, Status.STOP_IN_PROGRESS.name()); } } public void finishStackStop(StackStartStopContext context) { Stack stack = context.getStack(); stackUpdater.updateStackStatus(stack.getId(), DetailedStackStatus.STOPPED, "Cluster infrastructure stopped successfully."); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_INFRASTRUCTURE_STOPPED, Status.STOPPED.name()); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_BILLING_STOPPED, BillingStatus.BILLING_STOPPED.name()); usageService.stopUsagesForStack(stack); if (stack.getCluster() != null && stack.getCluster().getEmailNeeded()) { emailSenderService.sendStopSuccessEmail(stack.getCluster().getOwner(), stack.getCluster().getEmailTo(), stackUtil.extractAmbariIp(stack), stack.getCluster().getName()); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_NOTIFICATION_EMAIL, Status.STOPPED.name()); } } public void handleStackStopError(Stack stack, StackFailureEvent payload) { handleError(stack, payload.getException(), DetailedStackStatus.STOP_FAILED, Msg.STACK_INFRASTRUCTURE_STOP_FAILED, "Stack stop failed: "); } public boolean isStopPossible(Stack stack) { if (stack != null && stack.isStopRequested()) { return true; } else { LOGGER.info("Stack stop has not been requested because stack isn't in stop requested state, stop stack later."); return false; } } private void handleError(Stack stack, Exception exception, DetailedStackStatus detailedStackStatus, Msg msg, String logMessage) { LOGGER.error(logMessage, exception); Status stackStatus = detailedStackStatus.getStatus(); stackUpdater.updateStackStatus(stack.getId(), detailedStackStatus, logMessage + exception.getMessage()); flowMessageService.fireEventAndLog(stack.getId(), msg, stackStatus.name(), exception.getMessage()); if (stack.getCluster() != null) { clusterService.updateClusterStatusByStackId(stack.getId(), STOPPED); if (stack.getCluster().getEmailNeeded()) { emailSenderService.sendStopFailureEmail(stack.getCluster().getOwner(), stack.getCluster().getEmailTo(), stackUtil.extractAmbariIp(stack), stack.getCluster().getName()); flowMessageService.fireEventAndLog(stack.getId(), Msg.STACK_NOTIFICATION_EMAIL, stackStatus.name()); } } } }