Search in sources :

Example 1 with ServiceUpdateException

use of com.aws.greengrass.deployment.exceptions.ServiceUpdateException in project aws-greengrass-nucleus by aws-greengrass.

the class KernelUpdateDeploymentTask method call.

@SuppressWarnings({ "PMD.AvoidDuplicateLiterals" })
@Override
public DeploymentResult call() {
    Deployment.DeploymentStage stage = deployment.getDeploymentStage();
    try {
        List<GreengrassService> servicesToTrack = kernel.orderedDependencies().stream().filter(GreengrassService::shouldAutoStart).filter(o -> !kernel.getMain().equals(o)).collect(Collectors.toList());
        long mergeTimestamp = kernel.getConfig().lookup("system", "rootpath").getModtime();
        logger.atDebug().kv("serviceToTrack", servicesToTrack).kv("mergeTime", mergeTimestamp).log("Nucleus update workflow waiting for services to complete update");
        DeploymentConfigMerger.waitForServicesToStart(servicesToTrack, mergeTimestamp);
        DeploymentResult result = null;
        if (KERNEL_ACTIVATION.equals(stage)) {
            result = new DeploymentResult(DeploymentResult.DeploymentStatus.SUCCESSFUL, null);
        } else if (KERNEL_ROLLBACK.equals(stage)) {
            result = new DeploymentResult(DeploymentResult.DeploymentStatus.FAILED_ROLLBACK_COMPLETE, getDeploymentStatusDetails());
        }
        componentManager.cleanupStaleVersions();
        return result;
    } catch (InterruptedException e) {
        logger.atError("deployment-interrupted", e).log();
        try {
            saveDeploymentStatusDetails(e.getMessage());
        } catch (IOException ioException) {
            logger.atError().log("Failed to persist deployment error information", ioException);
        }
        // Interrupted workflow. Shutdown kernel and retry this stage.
        kernel.shutdown(30, REQUEST_RESTART);
        return null;
    } catch (ServiceUpdateException e) {
        logger.atError("deployment-errored", e).log();
        if (KERNEL_ACTIVATION.equals(stage)) {
            try {
                deployment.setDeploymentStage(KERNEL_ROLLBACK);
                saveDeploymentStatusDetails(e.getMessage());
                // Rollback workflow. Flip symlinks and restart kernel
                kernel.getContext().get(KernelAlternatives.class).prepareRollback();
                kernel.shutdown(30, REQUEST_RESTART);
            } catch (IOException ioException) {
                logger.atError().log("Failed to set up Nucleus rollback directory", ioException);
                return new DeploymentResult(DeploymentResult.DeploymentStatus.FAILED_UNABLE_TO_ROLLBACK, e);
            }
            return null;
        } else if (KERNEL_ROLLBACK.equals(stage)) {
            logger.atError().log("Nucleus update workflow failed on rollback", e);
            return new DeploymentResult(DeploymentResult.DeploymentStatus.FAILED_UNABLE_TO_ROLLBACK, getDeploymentStatusDetails());
        }
        return null;
    }
}
Also used : KERNEL_ROLLBACK(com.aws.greengrass.deployment.model.Deployment.DeploymentStage.KERNEL_ROLLBACK) Deployment(com.aws.greengrass.deployment.model.Deployment) IOException(java.io.IOException) DeploymentTask(com.aws.greengrass.deployment.model.DeploymentTask) Collectors(java.util.stream.Collectors) ComponentManager(com.aws.greengrass.componentmanager.ComponentManager) Kernel(com.aws.greengrass.lifecyclemanager.Kernel) GreengrassService(com.aws.greengrass.lifecyclemanager.GreengrassService) List(java.util.List) Utils(com.aws.greengrass.util.Utils) DEPLOYMENT_ID_LOG_KEY(com.aws.greengrass.deployment.DeploymentConfigMerger.DEPLOYMENT_ID_LOG_KEY) ServiceUpdateException(com.aws.greengrass.deployment.exceptions.ServiceUpdateException) KernelAlternatives(com.aws.greengrass.lifecyclemanager.KernelAlternatives) REQUEST_RESTART(com.aws.greengrass.deployment.bootstrap.BootstrapSuccessCode.REQUEST_RESTART) KERNEL_ACTIVATION(com.aws.greengrass.deployment.model.Deployment.DeploymentStage.KERNEL_ACTIVATION) Logger(com.aws.greengrass.logging.api.Logger) DeploymentResult(com.aws.greengrass.deployment.model.DeploymentResult) GreengrassService(com.aws.greengrass.lifecyclemanager.GreengrassService) Deployment(com.aws.greengrass.deployment.model.Deployment) DeploymentResult(com.aws.greengrass.deployment.model.DeploymentResult) IOException(java.io.IOException) ServiceUpdateException(com.aws.greengrass.deployment.exceptions.ServiceUpdateException)

Example 2 with ServiceUpdateException

use of com.aws.greengrass.deployment.exceptions.ServiceUpdateException in project aws-greengrass-nucleus by aws-greengrass.

the class DefaultActivator method activate.

@Override
@SuppressWarnings("PMD.PrematureDeclaration")
public void activate(Map<String, Object> newConfig, Deployment deployment, CompletableFuture<DeploymentResult> totallyCompleteFuture) {
    Map<String, Object> serviceConfig;
    if (newConfig.containsKey(SERVICES_NAMESPACE_TOPIC)) {
        serviceConfig = (Map<String, Object>) newConfig.get(SERVICES_NAMESPACE_TOPIC);
    } else {
        serviceConfig = new HashMap<>();
    }
    DeploymentDocument deploymentDocument = deployment.getDeploymentDocumentObj();
    if (isAutoRollbackRequested(deploymentDocument) && !takeConfigSnapshot(totallyCompleteFuture)) {
        return;
    }
    DeploymentConfigMerger.AggregateServicesChangeManager servicesChangeManager = new DeploymentConfigMerger.AggregateServicesChangeManager(kernel, serviceConfig);
    // Get the timestamp before updateMap(). It will be used to check whether services have started.
    long mergeTime = System.currentTimeMillis();
    updateConfiguration(deploymentDocument.getTimestamp(), newConfig);
    // wait until topic listeners finished processing mergeMap changes.
    Throwable setDesiredStateFailureCause = kernel.getContext().runOnPublishQueueAndWait(() -> {
        // polling to wait for all services to be started.
        servicesChangeManager.startNewServices();
        // Close unloadable service instances and initiate with new config
        servicesChangeManager.replaceUnloadableService();
        // Restart any services that may have been broken before this deployment
        // This is added to allow deployments to fix broken services
        servicesChangeManager.reinstallBrokenServices();
    });
    if (setDesiredStateFailureCause != null) {
        handleFailure(servicesChangeManager, deploymentDocument, totallyCompleteFuture, setDesiredStateFailureCause);
        return;
    }
    try {
        Set<GreengrassService> servicesToTrack = servicesChangeManager.servicesToTrack();
        logger.atDebug(MERGE_CONFIG_EVENT_KEY).kv("serviceToTrack", servicesToTrack).kv("mergeTime", mergeTime).log("Applied new service config. Waiting for services to complete update");
        waitForServicesToStart(servicesToTrack, mergeTime);
        logger.atDebug(MERGE_CONFIG_EVENT_KEY).log("new/updated services are running, will now remove old services");
        servicesChangeManager.removeObsoleteServices();
        logger.atInfo(MERGE_CONFIG_EVENT_KEY).kv(DEPLOYMENT_ID_LOG_KEY, deploymentDocument.getDeploymentId()).log("All services updated");
        totallyCompleteFuture.complete(new DeploymentResult(DeploymentResult.DeploymentStatus.SUCCESSFUL, null));
    } catch (InterruptedException | ExecutionException | ServiceUpdateException | ServiceLoadException e) {
        handleFailure(servicesChangeManager, deploymentDocument, totallyCompleteFuture, e);
    }
}
Also used : DeploymentDocument(com.aws.greengrass.deployment.model.DeploymentDocument) DeploymentResult(com.aws.greengrass.deployment.model.DeploymentResult) ServiceUpdateException(com.aws.greengrass.deployment.exceptions.ServiceUpdateException) DeploymentConfigMerger(com.aws.greengrass.deployment.DeploymentConfigMerger) GreengrassService(com.aws.greengrass.lifecyclemanager.GreengrassService) ExecutionException(java.util.concurrent.ExecutionException) ServiceLoadException(com.aws.greengrass.lifecyclemanager.exceptions.ServiceLoadException)

Example 3 with ServiceUpdateException

use of com.aws.greengrass.deployment.exceptions.ServiceUpdateException in project aws-greengrass-nucleus by aws-greengrass.

the class BootstrapManager method executeOneBootstrapTask.

/**
 * Execute the given bootstrap task.
 *
 * @param next BootstrapTaskStatus object
 * @return 100 if kernel restart is needed, 101 if device reboot is needed, 0 if no-op.
 */
protected int executeOneBootstrapTask(BootstrapTaskStatus next) throws ServiceUpdateException {
    Objects.requireNonNull(next);
    try {
        int exitCode = kernel.locate(next.getComponentName()).bootstrap();
        next.setStatus(DONE);
        next.setExitCode(exitCode);
        return exitCode;
    } catch (InterruptedException | TimeoutException | ServiceLoadException e) {
        throw new ServiceUpdateException(e);
    }
}
Also used : ServiceLoadException(com.aws.greengrass.lifecyclemanager.exceptions.ServiceLoadException) ServiceUpdateException(com.aws.greengrass.deployment.exceptions.ServiceUpdateException) TimeoutException(java.util.concurrent.TimeoutException)

Example 4 with ServiceUpdateException

use of com.aws.greengrass.deployment.exceptions.ServiceUpdateException in project aws-greengrass-nucleus by aws-greengrass.

the class DeploymentConfigMerger method mergeInNewConfig.

/**
 * Merge in new configuration values and new services.
 *
 * @param deployment deployment object
 * @param newConfig  the map of new configuration
 * @return future which completes only once the config is merged and all the services in the config are running
 */
public Future<DeploymentResult> mergeInNewConfig(Deployment deployment, Map<String, Object> newConfig) {
    CompletableFuture<DeploymentResult> totallyCompleteFuture = new CompletableFuture<>();
    DeploymentActivator activator;
    try {
        activator = kernel.getContext().get(DeploymentActivatorFactory.class).getDeploymentActivator(newConfig);
    } catch (ServiceUpdateException | ComponentConfigurationValidationException e) {
        // Failed to pre-process new config, no rollback needed
        logger.atError().setEventType(MERGE_ERROR_LOG_EVENT_KEY).setCause(e).log("Failed to process new configuration for activation");
        totallyCompleteFuture.complete(new DeploymentResult(DeploymentResult.DeploymentStatus.FAILED_NO_STATE_CHANGE, e));
        return totallyCompleteFuture;
    }
    boolean ggcRestart = false;
    if (activator instanceof KernelUpdateActivator) {
        ggcRestart = true;
    }
    DeploymentDocument deploymentDocument = deployment.getDeploymentDocumentObj();
    if (DeploymentComponentUpdatePolicyAction.NOTIFY_COMPONENTS.equals(deploymentDocument.getComponentUpdatePolicy().getComponentUpdatePolicyAction())) {
        kernel.getContext().get(UpdateSystemPolicyService.class).addUpdateAction(deploymentDocument.getDeploymentId(), new UpdateAction(deploymentDocument.getDeploymentId(), ggcRestart, deploymentDocument.getComponentUpdatePolicy().getTimeout(), () -> updateActionForDeployment(newConfig, deployment, activator, totallyCompleteFuture)));
    } else {
        logger.atInfo().log("Deployment is configured to skip update policy check," + " not waiting for disruptable time to update");
        updateActionForDeployment(newConfig, deployment, activator, totallyCompleteFuture);
    }
    return totallyCompleteFuture;
}
Also used : UpdateSystemPolicyService(com.aws.greengrass.lifecyclemanager.UpdateSystemPolicyService) CompletableFuture(java.util.concurrent.CompletableFuture) DeploymentDocument(com.aws.greengrass.deployment.model.DeploymentDocument) UpdateAction(com.aws.greengrass.lifecyclemanager.UpdateAction) DeploymentResult(com.aws.greengrass.deployment.model.DeploymentResult) ComponentConfigurationValidationException(com.aws.greengrass.deployment.exceptions.ComponentConfigurationValidationException) KernelUpdateActivator(com.aws.greengrass.deployment.activator.KernelUpdateActivator) ServiceUpdateException(com.aws.greengrass.deployment.exceptions.ServiceUpdateException) DeploymentActivator(com.aws.greengrass.deployment.activator.DeploymentActivator)

Example 5 with ServiceUpdateException

use of com.aws.greengrass.deployment.exceptions.ServiceUpdateException in project aws-greengrass-nucleus by aws-greengrass.

the class DeploymentConfigMerger method waitForServicesToStart.

/**
 * Completes the provided future when all of the listed services are running.
 *
 * @param servicesToTrack       services to track
 * @param mergeTime             time the merge was started, used to check if a service is broken due to the merge
 * @throws InterruptedException   if the thread is interrupted while waiting here
 * @throws ServiceUpdateException if a service could not be updated
 */
public static void waitForServicesToStart(Collection<GreengrassService> servicesToTrack, long mergeTime) throws InterruptedException, ServiceUpdateException {
    // assuming this loop will not get stuck waiting forever
    while (true) {
        boolean allServicesRunning = true;
        for (GreengrassService service : servicesToTrack) {
            State state = service.getState();
            // executes. Therefore we first check the service state has been updated since merge map occurs.
            if (service.getStateModTime() > mergeTime && State.BROKEN.equals(state)) {
                logger.atWarn(MERGE_CONFIG_EVENT_KEY).kv(SERVICE_NAME_LOG_KEY, service.getName()).log("merge-config-service BROKEN");
                throw new ServiceUpdateException(String.format("Service %s in broken state after deployment", service.getName()));
            }
            if (!service.reachedDesiredState()) {
                allServicesRunning = false;
                continue;
            }
            if (State.RUNNING.equals(state) || State.FINISHED.equals(state) || !service.shouldAutoStart() && service.reachedDesiredState()) {
                continue;
            }
            allServicesRunning = false;
        }
        if (allServicesRunning) {
            return;
        }
        // hardcoded
        Thread.sleep(WAIT_SVC_START_POLL_INTERVAL_MILLISEC);
    }
}
Also used : GreengrassService(com.aws.greengrass.lifecyclemanager.GreengrassService) State(com.aws.greengrass.dependency.State) ServiceUpdateException(com.aws.greengrass.deployment.exceptions.ServiceUpdateException)

Aggregations

ServiceUpdateException (com.aws.greengrass.deployment.exceptions.ServiceUpdateException)13 DeploymentResult (com.aws.greengrass.deployment.model.DeploymentResult)5 IOException (java.io.IOException)5 Test (org.junit.jupiter.api.Test)5 Deployment (com.aws.greengrass.deployment.model.Deployment)4 GreengrassService (com.aws.greengrass.lifecyclemanager.GreengrassService)4 Path (java.nio.file.Path)4 DeploymentDirectoryManager (com.aws.greengrass.deployment.DeploymentDirectoryManager)3 BootstrapManager (com.aws.greengrass.deployment.bootstrap.BootstrapManager)3 DeploymentDocument (com.aws.greengrass.deployment.model.DeploymentDocument)3 ServiceLoadException (com.aws.greengrass.lifecyclemanager.exceptions.ServiceLoadException)3 ExecutionException (java.util.concurrent.ExecutionException)2 ComponentManager (com.aws.greengrass.componentmanager.ComponentManager)1 State (com.aws.greengrass.dependency.State)1 DeploymentConfigMerger (com.aws.greengrass.deployment.DeploymentConfigMerger)1 DEPLOYMENT_ID_LOG_KEY (com.aws.greengrass.deployment.DeploymentConfigMerger.DEPLOYMENT_ID_LOG_KEY)1 DeploymentQueue (com.aws.greengrass.deployment.DeploymentQueue)1 DeviceConfiguration (com.aws.greengrass.deployment.DeviceConfiguration)1 DeploymentActivator (com.aws.greengrass.deployment.activator.DeploymentActivator)1 KernelUpdateActivator (com.aws.greengrass.deployment.activator.KernelUpdateActivator)1