com.elasticgrid.amazon.boot.Bootstrapper.java Source code

Java tutorial

Introduction

Here is the source code for com.elasticgrid.amazon.boot.Bootstrapper.java

Source

/**
 * Elastic Grid
 * Copyright (C) 2008-2010 Elastic Grid, LLC.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elasticgrid.amazon.boot;

import com.elasticgrid.config.EC2Configuration;
import com.elasticgrid.model.Discovery;
import com.xerox.amazonws.ec2.EC2Exception;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;

/**
 * Bootstrapper in charge of fetching the EC2 launch parameters and generating the EG configuration files.
 * The launch parameters are available in the <tt>/tmp/user-data</tt> file.
 *
 * @author Jerome Bernard
 */
public class Bootstrapper {
    public static final String LAUNCH_PARAMETER_CLUSTER_NAME = "CLUSTER_NAME";
    public static final String LAUNCH_PARAMETER_DROP_BUCKET = "DROP_BUCKET";
    public static final String LAUNCH_PARAMETER_OVERRIDES_URL = "OVERRIDES_URL";
    public static final String LAUNCH_PARAMETER_YUM_PACKAGES = "YUM_PACKAGES";
    public static final String LAUNCH_PARAMETER_ACCESS_ID = "AWS_ACCESS_ID";
    public static final String LAUNCH_PARAMETER_SECRET_KEY = "AWS_SECRET_KEY";
    public static final String LAUNCH_PARAMETER_EC2_SECURED = "AWS_EC2_SECURED";
    public static final String LAUNCH_PARAMETER_SQS_SECURED = "AWS_SQS_SECURED";
    public static final String LAUNCH_PARAMETER_EC2_KEYPAIR = "AWS_EC2_KEYPAIR";
    public static final String LAUNCH_PARAMETER_EC2_AMI32 = "AWS_EC2_AMI32";
    public static final String LAUNCH_PARAMETER_EC2_AMI64 = "AWS_EC2_AMI64";

    public static final String LAUNCH_PARAMETERS_FILE = "/tmp/user-data";
    public static final String ELASTIC_GRID_CONFIGURATION_FILE = "eg.properties";

    private String egHome = System.getProperty("EG_HOME");
    private String egConfig = egHome + File.separatorChar + "config";

    public Bootstrapper() throws IOException, EC2Exception {
        // retrieve EC2 launch parameters
        Properties launchParameters = fetchLaunchParameters();
        if (launchParameters.getProperty(LAUNCH_PARAMETER_CLUSTER_NAME) == null) {
            System.err.println("No cluster name given. Assuming 'elastic-grid' as cluster name.");
            launchParameters.setProperty(LAUNCH_PARAMETER_CLUSTER_NAME, "elastic-grid");
        }
        Properties egParameters = translateProperties(launchParameters);

        // save configuration into an Elastic Grid configuration file
        File file = saveConfiguration(egParameters);
        System.out.printf("Elastic Grid configuration file generated in '%s'\n", file.getAbsolutePath());

        String securityGroups = FileUtils.readFileToString(new File("/tmp/security-groups"));
        System.out.printf("Security groups for this EC2 instances are '%s'\n", securityGroups);
        String profile = "monitor-agent";
        boolean hasMonitor = securityGroups.contains(Discovery.MONITOR.getGroupName());
        boolean hasAgent = securityGroups.contains(Discovery.AGENT.getGroupName());
        if (!hasAgent && !hasMonitor) {
            System.err
                    .println("Missing node profile information! Make sure this node has required security groups!");
            System.exit(-1);
        } else if (hasAgent && hasMonitor) {
            profile = "monitor-and-agent";
        } else if (hasMonitor) {
            profile = "monitor";
        } else {
            profile = "agent";
        }

        FileUtils.writeStringToFile(new File("/tmp/eg-node-to-start"), profile);
        System.out.printf("Local machine is morphed into a %s\n", profile);

        String overridesURL = "";
        if (launchParameters.containsKey(LAUNCH_PARAMETER_OVERRIDES_URL))
            overridesURL = launchParameters.getProperty(LAUNCH_PARAMETER_OVERRIDES_URL);
        FileUtils.writeStringToFile(new File("/tmp/overrides"), overridesURL);
    }

    /**
     * At boot time, a file is generated into {@link #LAUNCH_PARAMETERS_FILE}.
     * This method retrieve the content of the file and parse it as if it was a Java configuration file.
     *
     * @return the {@link Properties} object
     * @throws IOException if the file generated at boot time can't be found or read
     */
    private Properties fetchLaunchParameters() throws IOException {
        Properties launchProperties = new Properties();
        InputStream launchFile = null;
        try {
            launchFile = new FileInputStream(new File(LAUNCH_PARAMETERS_FILE));
            launchProperties.load(launchFile);
            return launchProperties;
        } finally {
            IOUtils.closeQuietly(launchFile);
        }
    }

    /**
     * This method translate EC2 lauch parameters into {@link Properties} which can be used through
     * all Elastic Grid code.
     *
     * @param launchParameters the EC2 launch parameters
     * @return the Elastic Grid parameters
     * @throws IOException if the metadata can't be fetched
     */
    private Properties translateProperties(Properties launchParameters) throws IOException {
        // translate properties
        Properties egParameters = new Properties();
        for (Map.Entry property : launchParameters.entrySet()) {
            String key = (String) property.getKey();
            if (LAUNCH_PARAMETER_ACCESS_ID.equals(key))
                egParameters.put(EC2Configuration.AWS_ACCESS_ID, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_ACCESS_ID))
                System.err.println("The Amazon Access ID could not be retrieved!");
            if (LAUNCH_PARAMETER_SECRET_KEY.equals(key))
                egParameters.put(EC2Configuration.AWS_SECRET_KEY, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_SECRET_KEY))
                System.err.println("The Amazon Secret Key could not be retrieved!");
            if (LAUNCH_PARAMETER_CLUSTER_NAME.equals(key))
                egParameters.put(EC2Configuration.EG_CLUSTER_NAME, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_CLUSTER_NAME))
                System.err.println("The name of the cluster could not be retrieved!");
            if (LAUNCH_PARAMETER_DROP_BUCKET.equals(key))
                egParameters.put(EC2Configuration.EG_DROP_BUCKET, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_DROP_BUCKET))
                System.err.println("The name of the Amazon S3 drop bucket could not be retrieved!");
            if (LAUNCH_PARAMETER_OVERRIDES_URL.equals(key))
                egParameters.put(EC2Configuration.EG_OVERRIDES_BUCKET, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_OVERRIDES_URL))
                egParameters.put(EC2Configuration.EG_OVERRIDES_BUCKET, "");
            if (LAUNCH_PARAMETER_EC2_SECURED.equals(key))
                egParameters.put(EC2Configuration.AWS_EC2_SECURED, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_EC2_SECURED))
                egParameters.put(EC2Configuration.AWS_EC2_SECURED, Boolean.TRUE.toString());
            if (LAUNCH_PARAMETER_SQS_SECURED.equals(key))
                egParameters.put(EC2Configuration.AWS_SQS_SECURED, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_SQS_SECURED))
                egParameters.put(EC2Configuration.AWS_SQS_SECURED, Boolean.TRUE.toString());
            if (LAUNCH_PARAMETER_EC2_KEYPAIR.equals(key))
                egParameters.put(EC2Configuration.AWS_EC2_KEYPAIR, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_EC2_KEYPAIR))
                System.err.println("The Amazon keypair name could not be retrieved!");
            /*
            else
            egParameters.put(EC2Configuration.AWS_EC2_KEYPAIR, EC2Utils.getInstanceMetadata("keypair"));    // todo: check the value of the metadata property
            */
            if (LAUNCH_PARAMETER_EC2_AMI32.equals(key))
                egParameters.put(EC2Configuration.AWS_EC2_AMI32, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_EC2_AMI32))
                System.err.println("The 32 bits AMI ID could not be retrieved!");
            if (LAUNCH_PARAMETER_EC2_AMI64.equals(key))
                egParameters.put(EC2Configuration.AWS_EC2_AMI64, property.getValue());
            else if (!launchParameters.containsKey(LAUNCH_PARAMETER_EC2_AMI64))
                System.err.println("The 64 bits AMI ID could not be retrieved!");

            if (LAUNCH_PARAMETER_YUM_PACKAGES.equals(key))
                egParameters.put(EC2Configuration.REDHAT_YUM_PACKAGES, property.getValue());
        }
        return egParameters;
    }

    /**
     * Dump Elastic Grid properties into a configuration file.
     *
     * @param egParameters the properties to dump in a file
     * @return the file where the properties have been dumped into.
     * @throws IOException if there is an error when generating the configuration file
     */
    private File saveConfiguration(Properties egParameters) throws IOException {
        // write EG configuration
        if (egHome == null) {
            System.err.println("Could not find EG_HOME environment variable. Please fix this.");
            System.exit(-1);
        }
        File config = new File(egConfig, ELASTIC_GRID_CONFIGURATION_FILE);
        FileOutputStream stream = null;
        try {
            stream = new FileOutputStream(config);
            egParameters.store(stream, "Elastic Grid Configuration File - Generated file, please do NOT edit!");
        } finally {
            IOUtils.closeQuietly(stream);
        }
        return config;
    }

    public static void main(String[] args) throws IOException, EC2Exception {
        System.out.printf("Preparing Elastic Grid environment...\n");
        new Bootstrapper();
    }
}