Package io.fathom.auto.fathomcloud

Source Code of io.fathom.auto.fathomcloud.CloudServerProcess

package io.fathom.auto.fathomcloud;

import io.fathom.auto.TimeSpan;
import io.fathom.auto.fathomcloud.config.ConfigurationFileTemplate;
import io.fathom.auto.fathomcloud.config.LogConfigurationTemplate;
import io.fathom.auto.processes.Pid;
import io.fathom.auto.processes.ProcFs;
import io.fathom.auto.processes.ProcessExecution;
import io.fathom.auto.processes.Processes;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.io.Files;

public class CloudServerProcess {
    private static final String MAIN_CLASS_NAME = "io.fathom.cloud.CloudServer";

    private static final Logger log = LoggerFactory.getLogger(CloudServerProcess.class);

    private final Pid pid;

    final File instanceDir;

    private final FathomCloudConfig config;

    final File installDir;

    public CloudServerProcess(FathomCloudConfig config, Pid pid) {
        this.instanceDir = config.getInstanceDir();
        this.installDir = config.getInstallDir();
        this.config = config;
        this.pid = pid;
    }

    static File getPidFile(File instanceDir) {
        return new File(instanceDir, "fathomcloud.pid");
    }

    static File getLogFile(File instanceDir) {
        return new File(instanceDir, "fathomcloud.log");
    }

    static File getConfigFile(File instanceDir) {
        return new File(instanceDir, "configuration.properties");
    }

    static File getLogConfigFile(File instanceDir) {
        return new File(instanceDir, "logback.xml");
    }

    public static CloudServerProcess start(FathomCloudConfig config) throws IOException {
        File instanceDir = config.getInstanceDir();

        configureInstance(config);

        ProcessBuilder pb = buildLauncherProcess(config);

        ProcessExecution execution = Processes.run(pb, TimeSpan.minutes(1));

        if (!execution.didExit()) {
            throw new IOException("Timeout while starting Process");
        } else {
            if (execution.getExitCode() == 0) {
                log.info("Process started OK");

                // TODO: Poll loop with timeout?
                TimeSpan.seconds(2).sleep();

                File pidFile = getPidFile(instanceDir);

                Pid pid = Pid.read(pidFile);
                if (pid == null) {
                    throw new IOException("Process started, but could not read pid from file");
                }

                return new CloudServerProcess(config, pid);
            } else {
                throw new IOException("Error starting Process process");
            }
        }
    }

    private static void configureInstance(FathomCloudConfig config) throws IOException {
        File instanceDir = config.getInstanceDir();

        {
            ConfigurationFileTemplate template = new ConfigurationFileTemplate();
            template.write(getConfigFile(instanceDir), config);
        }

        {
            LogConfigurationTemplate template = new LogConfigurationTemplate();
            template.write(getLogConfigFile(instanceDir), config);
        }
    }

    private static ProcessBuilder buildLauncherProcess(FathomCloudConfig config) throws IOException {
        File instanceDir = config.getInstanceDir();

        File logFile = getLogFile(instanceDir);
        File pidFile = getPidFile(instanceDir);

        File tmpDir = new File("/tmp");

        // Be sure we don't end up as the process parent...
        File trampolineScript = new File(tmpDir, "run-fathomcloud.sh");

        {
            StringWriter stringWriter = new StringWriter();
            try (PrintWriter s = new PrintWriter(stringWriter)) {
                s.println("#!/bin/bash");
                s.println("");

                List<String> args = Lists.newArrayList();

                args.add("su");
                args.add("fathomcloud");
                args.add("-c");
                args.add("\"java");
                args.add("-cp '/opt/fathomcloud/lib/*'");
                args.add("-Dconf=/var/fathomcloud/configuration.properties");
                args.add("-Dlogback.configurationFile=/var/fathomcloud/logback.xml");
                args.add("-Dzookeeper.jmx.log4j.disable=true");
                args.add(MAIN_CLASS_NAME + "\"");
                args.add(">");
                args.add(logFile.getAbsolutePath());
                args.add("2>&1");
                args.add("&");

                s.println(Joiner.on(" ").join(args));

                s.println("pid=$!");
                s.println("echo ${pid} > " + pidFile.getAbsolutePath());
            }

            Files.write(stringWriter.toString(), trampolineScript, Charsets.UTF_8);
        }

        List<String> args = Lists.newArrayList();
        args.add("/bin/bash"); // Avoids need to chmod
        args.add(trampolineScript.getAbsolutePath());

        ProcessBuilder pb = new ProcessBuilder(args);
        return pb;
    }

    public static CloudServerProcess find(FathomCloudConfig config) throws IOException {
        File pidFile = getPidFile(config.getInstanceDir());

        Pid pid = Pid.read(pidFile);
        if (pid == null) {
            return null;
        }

        CloudServerProcess process = new CloudServerProcess(config, pid);

        if (!process.isRunning()) {
            log.info("Found process in pid file, but was not our process: {}", pid);

            pidFile.delete();
            process = null;
        } else {
            log.info("Found existing process: {}", pid);
        }

        return process;
    }

    public boolean isRunning() throws IOException {
        ProcFs.Process process = ProcFs.findProcess(pid);
        if (process == null) {
            log.info("Process went away (no process with pid)");
            return false;
        }
        List<String> cmdline = process.getCmdline();
        return isOurProcess(cmdline);
    }

    private boolean isOurProcess(List<String> cmdline) {
        if (cmdline == null) {
            // Process stopped
            log.info("Process went away (no process with pid)");
            return false;
        }

        if (cmdline.isEmpty()) {
            log.info("Process went away (cmdline empty)");
            return false;
        }

        String c = Joiner.on(" ").join(cmdline);
        if (c.indexOf(MAIN_CLASS_NAME) == -1) {
            log.info("Process went away (cmdline is {})", c);
            return false;
        }

        return true;
    }
}
TOP

Related Classes of io.fathom.auto.fathomcloud.CloudServerProcess

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.