package alien4cloud.deployment; import java.util.Map; import javax.annotation.Resource; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import alien4cloud.dao.IGenericSearchDAO; import alien4cloud.model.deployment.Deployment; import alien4cloud.model.deployment.DeploymentTopology; import org.alien4cloud.tosca.model.templates.Capability; import alien4cloud.orchestrators.plugin.IOrchestratorPlugin; import alien4cloud.paas.IPaaSCallback; import alien4cloud.paas.OrchestratorPluginService; import alien4cloud.paas.exception.MaintenanceModeException; import alien4cloud.paas.exception.OperationExecutionException; import alien4cloud.paas.exception.OrchestratorDisabledException; import alien4cloud.paas.model.OperationExecRequest; import alien4cloud.paas.model.PaaSDeploymentContext; import alien4cloud.topology.TopologyUtils; import alien4cloud.tosca.normative.NormativeComputeConstants; /** * Manages operations performed on a running deployment. */ @Slf4j @Service public class DeploymentRuntimeService { @Resource(name = "alien-monitor-es-dao") private IGenericSearchDAO alienMonitorDao; @Inject private DeploymentService deploymentService; @Inject private OrchestratorPluginService orchestratorPluginService; @Inject private DeploymentContextService deploymentContextService; @Inject private DeploymentRuntimeStateService deploymentRuntimeStateService; @Inject private DeploymentTopologyService deploymentTopologyService; /** * Trigger the execution of an operation on a node. * * @param request the operation's execution description ( see {@link alien4cloud.paas.model.OperationExecRequest}) * @throws alien4cloud.paas.exception.OperationExecutionException runtime exception during an operation */ public void triggerOperationExecution(OperationExecRequest request, IPaaSCallback<Map<String, String>> callback) throws OperationExecutionException { Deployment deployment = deploymentService.getActiveDeploymentOrFail(request.getApplicationEnvironmentId()); DeploymentTopology deploymentTopology = deploymentRuntimeStateService.getRuntimeTopologyFromEnvironment(deployment.getEnvironmentId()); IOrchestratorPlugin orchestratorPlugin = orchestratorPluginService.getOrFail(deployment.getOrchestratorId()); orchestratorPlugin.executeOperation(deploymentContextService.buildTopologyDeploymentContext(deployment, deploymentTopologyService.getLocations(deploymentTopology), deploymentTopology), request, callback); } /** * Switch an instance in a deployment to maintenance mode. If so the orchestrator should not perform self healing operations for this instance. * * @param applicationEnvironmentId The id of the application environment. * @param nodeTemplateId The id of the node template on which to enable maintenance mode. * @param instanceId The id of the instance. * @param maintenanceModeOn true if we should enable the maintenance mode, false if we should disable it. * @throws MaintenanceModeException In case the operation fails. */ public void switchInstanceMaintenanceMode(String applicationEnvironmentId, String nodeTemplateId, String instanceId, boolean maintenanceModeOn) throws MaintenanceModeException { Deployment deployment = deploymentService.getActiveDeploymentOrFail(applicationEnvironmentId); IOrchestratorPlugin orchestratorPlugin = orchestratorPluginService.getOrFail(deployment.getOrchestratorId()); DeploymentTopology deploymentTopology = deploymentRuntimeStateService.getRuntimeTopologyFromEnvironment(deployment.getEnvironmentId()); PaaSDeploymentContext deploymentContext = new PaaSDeploymentContext(deployment, deploymentTopology); orchestratorPlugin.switchInstanceMaintenanceMode(deploymentContext, nodeTemplateId, instanceId, maintenanceModeOn); } /** * Switch all instances in a deployment to maintenance mode. If so the orchestrator should not perform self healing operations for this instance. * * @param applicationEnvironmentId The id of the application environment. * @param maintenanceModeOn true if we should enable the maintenance mode, false if we should disable it. * @throws MaintenanceModeException In case the operation fails. */ public void switchMaintenanceMode(String applicationEnvironmentId, boolean maintenanceModeOn) throws MaintenanceModeException { Deployment deployment = deploymentService.getActiveDeploymentOrFail(applicationEnvironmentId); DeploymentTopology deploymentTopology = deploymentRuntimeStateService.getRuntimeTopologyFromEnvironment(deployment.getEnvironmentId()); IOrchestratorPlugin orchestratorPlugin = orchestratorPluginService.getOrFail(deployment.getOrchestratorId()); PaaSDeploymentContext deploymentContext = new PaaSDeploymentContext(deployment, deploymentTopology); orchestratorPlugin.switchMaintenanceMode(deploymentContext, maintenanceModeOn); } /** * Scale up/down a node in a topology * * @param applicationEnvironmentId id of the targeted environment * @param nodeTemplateId id of the compute node to scale up * @param instances the number of instances to be added (if positive) or removed (if negative) */ public void scale(String applicationEnvironmentId, final String nodeTemplateId, int instances, final IPaaSCallback<Object> callback) throws OrchestratorDisabledException { Deployment deployment = deploymentService.getActiveDeploymentOrFail(applicationEnvironmentId); DeploymentTopology deploymentTopology = deploymentRuntimeStateService.getRuntimeTopologyFromEnvironment(deployment.getEnvironmentId()); final DeploymentTopology topology = alienMonitorDao.findById(DeploymentTopology.class, deployment.getId()); final Capability capability = TopologyUtils.getScalableCapability(topology, nodeTemplateId, true); final int previousInitialInstances = TopologyUtils.getScalingProperty(NormativeComputeConstants.SCALABLE_DEFAULT_INSTANCES, capability); final int newInitialInstances = previousInitialInstances + instances; log.info("Scaling <{}> node from <{}> to <{}>. Updating runtime topology...", nodeTemplateId, previousInitialInstances, newInitialInstances); TopologyUtils.setScalingProperty(NormativeComputeConstants.SCALABLE_DEFAULT_INSTANCES, newInitialInstances, capability); alienMonitorDao.save(topology); IOrchestratorPlugin orchestratorPlugin = orchestratorPluginService.getOrFail(deployment.getOrchestratorId()); PaaSDeploymentContext deploymentContext = new PaaSDeploymentContext(deployment, deploymentTopology); orchestratorPlugin.scale(deploymentContext, nodeTemplateId, instances, new IPaaSCallback() { @Override public void onFailure(Throwable throwable) { log.info("Failed to scale <{}> node from <{}> to <{}>. rolling back to {}...", nodeTemplateId, previousInitialInstances, newInitialInstances, previousInitialInstances); TopologyUtils.setScalingProperty(NormativeComputeConstants.SCALABLE_DEFAULT_INSTANCES, previousInitialInstances, capability); alienMonitorDao.save(topology); callback.onFailure(throwable); } @Override public void onSuccess(Object data) { callback.onSuccess(data); } }); } }