org.cloudifysource.shell.commands.StartLocalCloud.java Source code

Java tutorial

Introduction

Here is the source code for org.cloudifysource.shell.commands.StartLocalCloud.java

Source

/*******************************************************************************
 * Copyright 2011 GigaSpaces Technologies Ltd
 *
 * 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.shell.commands;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.ExecuteResultHandler;
import org.apache.commons.exec.ExecuteStreamHandler;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.gogo.commands.CompleterValues;
import org.openspaces.admin.Admin;
import org.openspaces.admin.AdminFactory;
import org.openspaces.admin.gsm.GridServiceManager;
import org.openspaces.admin.pu.ProcessingUnit;
import org.openspaces.admin.pu.ProcessingUnitInstance;
import org.openspaces.admin.pu.elastic.ElasticStatelessProcessingUnitDeployment;
import org.openspaces.admin.pu.elastic.config.DiscoveredMachineProvisioningConfigurer;
import org.openspaces.admin.pu.elastic.config.EagerScaleConfigurer;
import org.openspaces.core.util.MemoryUnit;
import org.openspaces.pu.service.ServiceDetails;
import org.cloudifysource.shell.AbstractAdminFacade;
import org.cloudifysource.shell.AdminFacade;
import org.cloudifysource.shell.Constants;
import org.cloudifysource.shell.rest.ErrorStatusException;
import org.cloudifysource.shell.rest.RestAdminFacade;

import com.j_spaces.kernel.Environment;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import javax.jms.IllegalStateException;

/**
 * @author rafi
 * @since 2.0.0
 */
@Command(scope = "cloudify", name = "start-local-cloud", description = "starts a local cloud")
public class StartLocalCloud extends AbstractGSCommand {

    private static final String LINUX_EXECUTABLE = "gs-agent.sh";
    private static final String WINDOWS_EXECUTABLE = "cmd.exe";// /c
    // gs-agent.bat";
    private static final String[] WINDOWS_PREFIX = { "/c", "gs-agent.bat" };
    private static final String[] AGENT_PARAMETERS = { "gsa.global.esm", "1", "gsa.gsc", "0", "gsa.global.gsm", "1",
            "gsa.global.lus", "1" };

    private static final String[] LINUX_SUFFIX = { ">", "/dev/null", "2>", "/dev/null" };
    private static final String[] WINDOWS_SUFFIX = { ">", "NUL", "2>", "NUL" };

    @Argument(index = 0, required = false, name = "groups", description = "The Lookup Group be used by the local cloud. Will default to the LOOKUPGROUPS environment variable if not specified")
    private String groups;

    @Override
    protected Object doExecute() throws ErrorStatusException {

        // TODO - scan for open ports - 8080, 8099
        Admin admin = createAdmin();
        boolean lusFound = admin.getLookupServices().waitFor(1, 2, TimeUnit.SECONDS);
        if (lusFound) {
            return getFormattedMessage("lus_already_running", Arrays.toString(admin.getGroups()));
        }

        // "gs-agent.bat gsa.global.esm 1 gsa.gsc 0 gsa.global.gsm 1 gsa.global.lus 1"
        try {
            startLocalAgent(admin);
        } catch (ExecuteException e) {
            logger.log(Level.SEVERE, "Failed to start local cloud agent", e);
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Failed to start local cloud agent", e);
        }

        try {
            deployRestAdminServer(admin);
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Failed to start REST Admin Server", e);
        }

        // connect to local rest server
        if (session != null) {
            this.adminFacade = (AbstractAdminFacade) session.get(Constants.ADMIN_FACADE);

        } else {
            this.adminFacade = new RestAdminFacade();
        }
        adminFacade.connect(null, null, "http://localhost:8080/restful");

        try {
            deployWebUI(admin);
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Failed to start Web UI for local cloud", e);
        }

        return getFormattedMessage("local_cloud_started"); // TODO - add local
        // cloud messages
    }

    private void deployRestAdminServer(Admin admin) throws IOException {
        final String restFileName = "tools" + File.separator + "rest" + File.separator + "rest.war";
        final File restFile = getGSFile(restFileName);

        final ElasticStatelessProcessingUnitDeployment deployment = new ElasticStatelessProcessingUnitDeployment(
                restFile)
                        // .memoryCapacityPerContainer(externalProcessMemoryInMB,
                        // MemoryUnit.MEGABYTES)
                        .addCommandLineArgument("-Xmx" + 64 + "m")
                        // .addCommandLineArgument("-Xms" + containerMemoryInMB + "m")
                        .addContextProperty("com.gs.application", "management").name("restful")
                        // All PUs on this role share the same machine. Machines
                        // are identified by zone.
                        .sharedMachineProvisioning("public",
                                new DiscoveredMachineProvisioningConfigurer().addGridServiceAgentZone("management")
                                        // .reservedMemoryCapacityPerMachine(reservedMemoryCapacityPerMachineInMB,
                                        // MemoryUnit.MEGABYTES)
                                        .create())
                        // Eager scale (1 container per machine per PU)
                        .scale(new EagerScaleConfigurer().atMostOneContainerPerMachine().create());

        GridServiceManager gsm = admin.getGridServiceManagers().waitForAtLeastOne(5, TimeUnit.SECONDS);
        if (gsm == null) {
            throw new java.lang.IllegalStateException("Could not find a GSM in the local cloud");
        }

        ProcessingUnit pu = gsm.deploy(deployment);
        boolean res = pu.waitFor(1, 30, TimeUnit.SECONDS);
        if (!res) {
            throw new java.lang.IllegalStateException("REST Admin server did not deploy successfully");
        }

        String url = getWebProcessingUnitURL(pu);

        System.out.println("REST Admin server is available at: " + url);

    }

    private String getWebProcessingUnitURL(ProcessingUnit pu) {
        ProcessingUnitInstance pui = pu.getInstances()[0];
        Map<String, ServiceDetails> alldetails = pui.getServiceDetailsByServiceId();

        ServiceDetails details = alldetails.get("jee-container");
        String host = details.getAttributes().get("host").toString();
        String port = details.getAttributes().get("port").toString();
        String ctx = details.getAttributes().get("context-path").toString();
        String url = "http://" + host + ":" + port + ctx;
        return url;
    }

    private void startLocalAgent(Admin admin) throws ExecuteException, IOException {

        File binDir = new File(Environment.getHomeDirectory(), "bin");
        DefaultExecutor executor = new DefaultExecutor();
        executor.setWorkingDirectory(binDir);

        CommandLine cmdLine = createCommandLine();

        executor.setExitValue(0);

        executor.execute(cmdLine, new ExecuteResultHandler() {

            @Override
            public void onProcessFailed(ExecuteException e) {
                logger.log(Level.SEVERE, "Local Cloud Agent terminated unexpectedly", e);
            }

            @Override
            public void onProcessComplete(int arg0) {
                logger.fine("Local Cloud Agent terminated");

            }
        });

        boolean foundLus = admin.getLookupServices().waitFor(1, 1, TimeUnit.MINUTES);
        if (!foundLus) {
            throw new java.lang.IllegalStateException("Local Cloud Lookup Service did not start!");
        }
    }

    private CommandLine createCommandLine() {
        String os = System.getProperty("os.name");
        logger.fine("os.name = " + os);
        if (os == null) {
            throw new java.lang.IllegalStateException("The System Property variable 'os.name' was not set");
        }

        os = os.toLowerCase();
        CommandLine cmdLine = null;
        boolean isWindows = os.startsWith("win");

        if (isWindows) {
            cmdLine = new CommandLine(WINDOWS_EXECUTABLE);
            for (String param : WINDOWS_PREFIX) {
                cmdLine.addArgument(param);
            }

        } else {
            cmdLine = new CommandLine(LINUX_EXECUTABLE);
        }

        for (String param : AGENT_PARAMETERS) {
            cmdLine.addArgument(param);

        }

        if (isWindows) {
            for (String param : WINDOWS_SUFFIX) {
                cmdLine.addArgument(param);
            }
        } else {
            for (String param : LINUX_SUFFIX) {
                cmdLine.addArgument(param);
            }
        }

        return cmdLine;
    }

    private void deployWebUI(Admin admin) throws Exception {
        final String webUIFileName = "tools" + File.separator + "gs-webui" + File.separator
                + "gs-webui-9.5.0-SNAPSHOT.war";

        File webUIFile = getGSFile(webUIFileName);

        this.adminFacade.installElastic(webUIFile, "management", "web-ui", "web-ui", null);

        ProcessingUnit pu = admin.getProcessingUnits().waitFor("web-ui", 10, TimeUnit.SECONDS);
        if (pu == null) {
            throw new IllegalStateException("Could not find 'web-ui' processing unit");
        }

        boolean res = pu.waitFor(1, 30, TimeUnit.SECONDS);
        if (!res) {
            throw new java.lang.IllegalStateException("Could not find instance of 'web-ui' processing unit");
        }

        String url = getWebProcessingUnitURL(pu);

        System.out.println("Web UI is available at: " + url);

    }

    private File getGSFile(final String relativeFileName) throws FileNotFoundException, IOException {
        final String absoluteFileName = Environment.getHomeDirectory() + File.separator + relativeFileName;
        File file = new File(absoluteFileName);
        if (!file.exists()) {
            throw new FileNotFoundException("File: " + file + " was not found");
        }
        if (!file.isFile()) {
            throw new IOException(file + " is not a file");
        }
        return file;
    }

    private Admin createAdmin() {
        AdminFactory adminFactory = new AdminFactory();
        adminFactory.useDaemonThreads(true);

        if (this.groups != null) {
            adminFactory.addGroups(groups);

        }

        Admin admin = adminFactory.createAdmin();

        return admin;
    }

    public static void main(String[] args) throws ErrorStatusException {
        StartLocalCloud cmd = new StartLocalCloud();

        cmd.doExecute();
    }
}