org.cloudifysource.rest.deploy.ApplicationDeployerRunnable.java Source code

Java tutorial

Introduction

Here is the source code for org.cloudifysource.rest.deploy.ApplicationDeployerRunnable.java

Source

/*******************************************************************************
 * Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved
 *
 * Licensed 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.cloudifysource.rest.deploy;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;

import org.apache.commons.io.FileUtils;
import org.cloudifysource.dsl.Service;
import org.cloudifysource.dsl.internal.DSLApplicationCompilatioResult;
import org.cloudifysource.dsl.internal.DSLReader;
import org.cloudifysource.dsl.internal.DSLUtils;
import org.cloudifysource.dsl.internal.packaging.Packager;
import org.cloudifysource.dsl.rest.request.InstallApplicationRequest;
import org.cloudifysource.dsl.rest.request.InstallServiceRequest;
import org.cloudifysource.dsl.utils.ServiceUtils;
import org.cloudifysource.rest.controllers.DeploymentsController;
import org.cloudifysource.rest.controllers.RestErrorException;

import com.j_spaces.kernel.Environment;

/**
 * A Runnable implementation that executes the deployment logic of an application.
 * 
 * @author adaml
 *
 */
public class ApplicationDeployerRunnable implements Runnable {
    private static final int SERVICE_INSTANCE_STARTUP_TIMEOUT_MINUTES = 60;

    private static final java.util.logging.Logger logger = java.util.logging.Logger
            .getLogger(ApplicationDeployerRunnable.class.getName());

    private final DeploymentsController controller;
    private final InstallApplicationRequest request;
    private final String applicationName;
    private final File overridesFile;
    private final List<Service> services;
    private final DSLApplicationCompilatioResult result;
    //a list of deployment IDs, one for each service.
    private final String deploymentID;

    /**
     * Constructor.
     * @param controller
     *       installation requests are delegated to this controller.
     * @param request
     *       the install application request.
     * @param result
     *       the application compilation result.
     * @param services
     *       the list of services.
     * @param overridesFile
     *       application overrides file.
     * @throws org.cloudifysource.rest.controllers.RestErrorException
     */
    public ApplicationDeployerRunnable(final DeploymentsController controller,
            final InstallApplicationRequest request, final DSLApplicationCompilatioResult result,
            final List<Service> services, final String deploymentID, final File overridesFile)
            throws RestErrorException {
        this.request = request;
        this.controller = controller;
        this.result = result;
        this.services = services;
        this.deploymentID = deploymentID;
        this.applicationName = request.getApplicationName();
        this.overridesFile = overridesFile;
    }

    @Override
    public void run() {
        logger.fine("Installing application " + applicationName + " with the following services: " + services);

        final boolean asyncInstallPossible = isAsyncInstallPossibleForApplication();
        logger.info("Async install setting is " + asyncInstallPossible);
        try {
            installServices(asyncInstallPossible);
        } catch (final IOException e) {
            e.printStackTrace();
        }
    }

    private void installServices(final boolean async) throws IOException {

        final File appDir = result.getApplicationDir();

        logger.info("Installing services for application: " + applicationName + ". Async install: " + async
                + ". Number of services: " + this.services.size());
        for (final Service service : services) {
            logger.info("Installing service: " + service.getName() + " for application: " + applicationName);
            service.getCustomProperties().put("usmJarPath", Environment.getHomeDirectory() + "/lib/platform/usm");

            final String serviceName = service.getName();
            final String absolutePUName = ServiceUtils.getAbsolutePUName(applicationName, serviceName);
            final File serviceDirectory = new File(appDir, serviceName);

            boolean found = false;

            try {
                // lookup application properties file
                final File applicationPropertiesFile = DSLReader
                        .findDefaultDSLFileIfExists(DSLUtils.APPLICATION_PROPERTIES_FILE_NAME, appDir);
                // lookup overrides file
                File actualOverridesFile = overridesFile;
                if (actualOverridesFile == null) {
                    // when using the CLI, the application overrides file is inside the directory
                    actualOverridesFile = DSLReader
                            .findDefaultDSLFileIfExists(DSLUtils.APPLICATION_OVERRIDES_FILE_NAME, appDir);
                }
                // Pack the folder and name it absolutePuName
                final File packedFile = Packager.pack(service, serviceDirectory, absolutePUName, null);
                result.getApplicationFile().delete();
                packedFile.deleteOnExit();
                // Deployment will be done using the service's absolute PU name.
                final InstallServiceRequest installServiceReq = createInstallServiceRequest(packedFile);
                final String appName = this.request.getApplicationName();

                final DeploymentFileHolder fileHolder = new DeploymentFileHolder();
                fileHolder.setPackedFile(packedFile);
                fileHolder.setServiceOverridesFile(actualOverridesFile);
                fileHolder.setApplicationPropertiesFile(applicationPropertiesFile);

                controller.installServiceInternal(appName, serviceName, installServiceReq, deploymentID,
                        fileHolder);
                try {
                    FileUtils.deleteDirectory(packedFile.getParentFile());
                } catch (final IOException ioe) {
                    // sometimes this delete fails. Not sure why. Maybe deploy
                    // is async?
                    logger.warning("Failed to delete temporary directory: " + packedFile.getParentFile());
                }

                if (!async) {
                    logger.info("Waiting for instance of service: " + serviceName + " of application: "
                            + applicationName);
                    final boolean instanceFound = controller.waitForServiceInstance(applicationName, serviceName,
                            SERVICE_INSTANCE_STARTUP_TIMEOUT_MINUTES, TimeUnit.MINUTES);
                    if (!instanceFound) {
                        throw new TimeoutException("Service " + serviceName + " of application " + applicationName
                                + " was installed, but no instance of the service has started after "
                                + SERVICE_INSTANCE_STARTUP_TIMEOUT_MINUTES + " minutes.");
                    }
                    logger.info("Found instance of: " + serviceName);
                }

                found = true;
                logger.fine("service " + service + " deployed.");
            } catch (final Exception e) {
                logger.log(Level.SEVERE, "Failed to install service: " + serviceName + " of application: "
                        + applicationName + ". Application installation will halt. "
                        + "Some services may already have started, and should be shutdown manually. Error was: "
                        + e.getMessage(), e);
                return;
            }

            if (!found) {
                logger.severe("Failed to find an instance of service: " + serviceName
                        + " while installing application " + applicationName
                        + ". Application installation will stop. Some services may have been installed!");
                return;
            }
        }
        FileUtils.deleteDirectory(appDir);
    }

    InstallServiceRequest createInstallServiceRequest(final File packedFile) {
        final InstallServiceRequest installServiceReq = new InstallServiceRequest();
        installServiceReq.setCloudOverridesUploadKey(request.getCloudOverridesUploadKey());
        installServiceReq.setCloudConfigurationUploadKey(request.getCloudConfigurationUploadKey());
        installServiceReq.setAuthGroups(this.request.getAuthGroups());
        installServiceReq.setDebugAll(this.request.isDebugAll());
        installServiceReq.setDebugEvents(this.request.getDebugEvents());
        installServiceReq.setDebugMode(this.request.getDebugMode());
        installServiceReq.setSelfHealing(this.request.isSelfHealing());
        installServiceReq.setServiceFileName(null);
        installServiceReq.setTimeoutInMillis(0);

        return installServiceReq;
    }

    /**
     *
     * @return true if all services have Lifecycle events.
     */
    public boolean isAsyncInstallPossibleForApplication() {
        // check if all services are USM
        for (final Service service : this.services) {
            if (service.getLifecycle() == null) {
                return false;
            }
        }

        return true;
    }
}