com.eucalyptus.bootstrap.SystemBootstrapper.java Source code

Java tutorial

Introduction

Here is the source code for com.eucalyptus.bootstrap.SystemBootstrapper.java

Source

/*************************************************************************
 * Copyright 2009-2012 Eucalyptus Systems, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/.
 *
 * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
 * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
 * additional information or have any questions.
 *
 * This file may incorporate work covered under the following copyright
 * and permission notice:
 *
 *   Software License Agreement (BSD License)
 *
 *   Copyright (c) 2008, Regents of the University of California
 *   All rights reserved.
 *
 *   Redistribution and use of this software in source and binary forms,
 *   with or without modification, are permitted provided that the
 *   following conditions are met:
 *
 *     Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *     Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer
 *     in the documentation and/or other materials provided with the
 *     distribution.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE
 *   THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL,
 *   COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE,
 *   AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
 *   IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA,
 *   SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY,
 *   WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION,
 *   REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO
 *   IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT
 *   NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS.
 ************************************************************************/

package com.eucalyptus.bootstrap;

import groovy.lang.ExpandoMetaClass;
import java.io.PrintStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.security.Security;
import java.util.Map;
import java.util.concurrent.Callable;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.eucalyptus.bootstrap.Bootstrap.Stage;
import com.eucalyptus.component.Component;
import com.eucalyptus.component.Components;
import com.eucalyptus.component.ServiceConfiguration;
import com.eucalyptus.empyrean.Empyrean;
import com.eucalyptus.records.EventClass;
import com.eucalyptus.records.EventRecord;
import com.eucalyptus.records.EventType;
import com.eucalyptus.records.Logs;
import com.eucalyptus.scripting.Groovyness;
import com.eucalyptus.system.Capabilities;
import com.eucalyptus.system.Threads;
import com.eucalyptus.util.Internets;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;

/**
 * Java entry point from eucalyptus-bootstrap. See {@link Bootstrap} for a detailed explanation of
 * the system startup procedure.
 * 
 * <b>IMPORTANT:</b> See {@link #init()} regarding exceptin handling.
 * 
 * @see Bootstrap
 * @see SystemBootstrapper#init()
 */
public class SystemBootstrapper {
    private static final String SEP = " -- ";

    static Logger LOG = Logger.getLogger(SystemBootstrapper.class);

    private static SystemBootstrapper singleton;
    private static ThreadGroup singletonGroup;
    public static final PrintStream out = System.out;
    public static final PrintStream err = System.err;

    public static SystemBootstrapper getInstance() {
        synchronized (SystemBootstrapper.class) {
            if (singleton == null) {
                singleton = new SystemBootstrapper();
                LOG.info("Creating Bootstrapper instance.");
            } else {
                LOG.info("Returning Bootstrapper instance.");
            }
        }
        return singleton;
    }

    public SystemBootstrapper() {
    }

    /**
     * <b>IMPORTANT NOTE:</b> this is the <b><i>only</i></b> class for which it is acceptable to
     * {@code catch} or {@code throw} the {@link Throwable} type. See {@link ThreadDeath} for an
     * explanation of the constraints on
     * handling {@link Throwable} propagation.
     * 
     * @see java.lang.ThreadDeath
     * @param t
     * @throws Throwable
     */
    private static void handleException(Throwable t) throws Throwable {
        if (t instanceof BootstrapException) {
            t.printStackTrace();
            LOG.fatal(t, t);
            throw t;
        } else {
            t.printStackTrace();
            LOG.fatal(t, t);
            System.exit(123);
        }
    }

    /**
     * {@inheritDoc #handleException(Throwable)}
     * 
     * @return
     * @throws Throwable
     */
    public boolean init() throws Throwable {
        ExpandoMetaClass.enableGlobally();
        Logs.init();
        Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {

            @Override
            public void uncaughtException(Thread t, Throwable e) {
                try {
                    String stack = Joiner.on("\t\n").join(Thread.currentThread().getStackTrace());
                    LOG.error(stack);
                    LOG.error(e, e);
                } catch (Exception ex) {
                    try {
                        System.out.println(Joiner.on("\t\n").join(Thread.currentThread().getStackTrace()));
                        e.printStackTrace();
                        ex.printStackTrace();
                    } catch (Exception ex1) {
                        System.out.println("Failed because of badness in uncaught exception path.");
                        System.out.println("Thread:      " + t.toString());
                        System.out.println("Exception:   " + e.getClass());
                        System.out.println("Message:     " + e.getMessage());
                        System.out.println("All threads:\n");
                        for (Map.Entry<Thread, StackTraceElement[]> ent : Thread.getAllStackTraces().entrySet()) {

                        }
                    }
                }
            }
        });
        OrderedShutdown.initialize();
        BootstrapArgs.init();
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            if (Security.getProviders().length > 4) {
                Security.insertProviderAt(new BouncyCastleProvider(), 4); // EUCA-5833
            } else {
                Security.addProvider(new BouncyCastleProvider());
            }
        }
        try {//GRZE:HACK: need to remove the nss add-on in deb based distros as it breaks ssl.
            Groovyness.eval(
                    "import sun.security.jca.*; Providers.setProviderList( ProviderList.remove( Providers.@providerList,\"SunPKCS11-NSS\") );");
        } catch (Exception ex) {
            LOG.error(ex, ex);
        }
        try {
            if (!BootstrapArgs.isInitializeSystem()) {
                Bootstrap.init();
                Bootstrap.Stage stage = Bootstrap.transition();
                stage.load();
            }
            return true;
        } catch (Throwable t) {
            SystemBootstrapper.handleException(t);
            return false;
        }
    }

    /**
     * {@inheritDoc #handleException(Throwable)}
     * 
     * @return
     * @throws Throwable
     */
    public boolean load() throws Throwable {
        if (BootstrapArgs.isInitializeSystem()) {
            try {
                Bootstrap.initializeSystem();
                System.exit(0);
            } catch (Throwable t) {
                LOG.error(t, t);
                System.exit(1);
                throw t;
            }
        } else {
            SystemBootstrapper.runSystemStages(new Predicate<Stage>() {

                @Override
                public boolean apply(Stage input) {
                    input.load();
                    return true;
                }
            });
            Bootstrap.applyTransition(Component.State.LOADED, Components.whichCanLoad());
        }
        return true;
    }

    /**
     * NOTE: this is the /only/ class for which it is acceptable to {@code catch} or {@code throw} the
     * {@link Throwable} type. See {@link ThreadDeath} for an explanation of the constraints on
     * handling {@link Throwable} propagation.
     * 
     * @see java.lang.ThreadDeath
     * @return
     * @throws Throwable
     */
    public boolean start() throws Throwable {
        Capabilities.initialize();
        SystemBootstrapper.runSystemStages(new Predicate<Stage>() {

            @Override
            public boolean apply(Stage input) {
                input.start();
                return true;
            }
        });
        Bootstrap.applyTransition(Component.State.LOADED, Components.whichCanLoad());
        Threads.enqueue(Empyrean.class, SystemBootstrapper.class, new Callable<Boolean>() {
            @Override
            public Boolean call() {
                try {
                    Bootstrap.applyTransition(Component.State.DISABLED, Components.whichCanLoad());
                    Bootstrap.applyTransition(Component.State.ENABLED, Components.whichCanEnable());
                } catch (Exception ex) {
                    LOG.error(ex, ex);
                }
                return Boolean.TRUE;
            }
        }).get();
        try {
            SystemBootstrapper.printBanner();
        } catch (Exception ex) {
            LOG.error(ex, ex);
        }
        return true;
    }

    private static void runSystemStages(Predicate<Bootstrap.Stage> exec) throws Throwable {
        try {
            // TODO: validation-api
            /** @NotNull */
            Bootstrap.Stage stage = Bootstrap.transition();
            do {
                exec.apply(stage);
            } while ((stage = Bootstrap.transition()) != null);
        } catch (Throwable t) {
            LOG.error(t);
            Logs.extreme().error(t, t);
            System.exit(123);
        }
    }

    public String getVersion() {
        return BillOfMaterials.RequiredFields.VERSION.getValue();
    }

    public boolean check() {
        return true;
    }

    public boolean destroy() {
        return true;
    }

    public boolean stop() throws Exception {
        LOG.warn("Shutting down Eucalyptus.");
        EventRecord.here(SystemBootstrapper.class, EventClass.SYSTEM, EventType.SYSTEM_STOP, "SHUT DOWN").info();
        return true;
    }

    public static void restart() {
        System.exit(123);
    }

    private static native void shutdown(boolean reload);

    public static native void hello();

    private static String printBanner() {
        //    String prefix = "\n-----------------------------------------------------";
        String prefix = "\n\t";
        String headerHeader = "\n-----------------_________________________________________________________\n-----------------|";
        String headerFormat = "  %-53.53s";
        String headerFooter = "|\n-----------------|#######################################################|\n";
        String banner = "-----------------._______________________________________________________.\n"
                + "-----------------|#######################################################|\n"
                + "----------------.|#                                                  .____,+\n"
                + "-----------------|#  -------------------------------_.._._____ +--..vH~n===+\n"
                + "-_, +------------|)|.-----------------------------._ggQgp;;;;;.I__gI\"\"`:`-\n"
                + " -!M08mQgggggggggwwg_gww_g_w_w_________. |----___vvvvn0+(.n|<._V+\"|::=:-#|\n"
                + "+iv-\"\"!\"{{vnvvvvvvvvvvvvvvs%%iiiiiiQiigi,W---.jivvvvvl`:<o^^wg2\"'-:-----#|\n"
                + "---:+ii:   -\"\"~~\"+MMMMMMM{IIvvnvvvvvnvnnnng_jvvnvvlHF|Q|s.;~`IL|:-------#|\n"
                + "-------.  :+|+=--^\"\"\"\"\"\"!~~^\"\"M{IvvvnvnvvnlgvvIvIIF\"'=.gwg\"v:-L=--------#|\n"
                + "----------------.|) -+iI=. ..-    -\"~~~~n_unvvIM!|._%<~\")|i:--<+--------#|\n"
                + "----------------.|#  ..-...---.   --    gvvvvl~\"-:=T^\" |]n---.-#.-------#|\n"
                + "-----------------|#   ..------------. _invvMEI_|_\"` :=|:;|-----m_.------#|\n"
                + "-----------------|)-  ..-----_.,---- _vvnIN\"'.,i-+:----.f+----Qvg_:-----#|\n"
                + "--,______...____..______wgi%vvvvi6_q%v%ME._.)T`+------.H`--- _vlnlc.----#|\n"
                + "--<qggggggggggwwgiiigsQvvvvvvvvI+~qinvF\"'.;g~i:----- _p^  --]ivvvvL=----#|\n"
                + "--+=\"\"^MM*MIM*HNMMMM*MMMllIlMN`Q_w}M~`v.]\"}n_._<v=qg%IF-..-.)vvnvnE=----#|\n"
                + "-----| (\"\"\"!\"\"\"\"\"\"\"\"\"\"\"\"~~~~1w,j>+~{=`_a;X`.gI\"\"\"ninvv[:-.-.vvnvnvF|----#|\n"
                + "-----------------|#---------:.4C_...._W#==)~'==+.vvnvv`.---.vvvnvvf+----#|\n"
                + "-----------------|# ..---------^-|!{gvQ!^^^n+:--jnvnvM .--..vvnvnv[-----#|\n"
                + "----------------.|#   --------+|||_)nv}n=::--- gnnvv}+..--..vvnvvv`+----#|\n"
                + "-----------------|#   .----------_%vvvF ------]IvnvvF -----.vvnvnI i----#|\n"
                + "-----------------|#    --------_j%nv}+c.-----.Qlnv}+  -----.vvnvvT=:----#|\n"
                + "-----------------|#    .------ jvvvI!>C+----_gvIvn@--.-----.{vnvv+=-----#|\n"
                + "-----------------|#     -----_qvvIN' \"`:---.jIvvv+` -------.vnvv}Q:-----#|\n"
                + "-----------------|#     ----.qvn}F^'n+:----.jnvn}^  -------.vvvn%.------#|\n"
                + "-----------------|#     . _qvn}+'=i+:----- wvnvI`  .-------.vvnvf=------#|\n"
                + "-----------------|#     __vvv}~'i---------<vvnvT =..-------.vvnv`-------#|\n"
                + "-----------------|#   __%v}M`':::--------.)vnv@-=:---------.vvnH..------#|\n"
                + "-----------------|#   w%vn~``I:--------- gnnvv` ..---------.vvn!.-------#|\n"
                + "-----------------|# _qn}+~ =+:----------jnnv}i  ..---------.vvv= -------#|\n"
                + "-----------------|)-ju}~^ :-------------%vvvF=....---------.vvvQ--------#|\n"
                + "----------------  _q}+ --=:------------XnvnM`=-------------.vnE.--------#|\n"
                + "--------------.. /g%`'i:---------------_nv}\" I-------------.nI` --------#|\n"
                + "--------------./_)``=+:---------------Qvnv[+I=------------ iN\"----------#|\n"
                + "----------------\" X:------------------<vnM`---------------QT^|----------#|\n"
                + "-----------------|)-------------------jn}=.--------------- v::----------#|\n"
                + "----------------.|#  .---------------.jvF                               #|\n"
                + "-----------------|#                   jnf^     Started Eucalyptus       #|\n"
                + "-----------------|#___________________ N' ______________________________#|\n"
                + "-----------------(#################### v' ###############################)\n"
                + "----------------     .--------------:I ^   . .. .. .. .. ..... .. .. ...=v\n"
                + "---------------..     ------------------  ................................\n";

        banner += "\n----------------- Version: " + singleton.getVersion() + "\n";
        banner += headerHeader + String.format(headerFormat, "System Bootstrap Configuration") + headerFooter;
        for (Bootstrap.Stage stage : Bootstrap.Stage.values()) {
            banner += prefix + stage.name() + SEP + stage.describe()
                    .replaceAll("(\\w*)\\w\n", "\1\n" + prefix + stage.name() + SEP).replaceAll("^\\w* ", "");
        }
        banner += headerHeader + String.format(headerFormat, "Component Bootstrap Configuration") + headerFooter;
        for (Component c : Components.list()) {
            if (c.getComponentId().isAvailableLocally()) {
                banner += c.getBootstrapper();
            }
        }
        banner += headerHeader + String.format(headerFormat, "Local Services") + headerFooter;
        for (Component c : Components.list()) {
            if (c.hasLocalService()) {
                ServiceConfiguration localConfig = c.getLocalServiceConfiguration();
                banner += prefix + c.getName() + SEP + localConfig.toString();
                banner += prefix + c.getName() + SEP + localConfig.getComponentId().toString();
                banner += prefix + c.getName() + SEP + localConfig.lookupState().toString();
            }
        }
        banner += headerHeader + String.format(headerFormat, "Detected Interfaces") + headerFooter;
        for (NetworkInterface iface : Internets.getNetworkInterfaces()) {
            banner += prefix + iface.getDisplayName() + SEP
                    + Lists.transform(iface.getInterfaceAddresses(), Functions.toStringFunction());
            for (InetAddress addr : Lists.newArrayList(Iterators.forEnumeration(iface.getInetAddresses()))) {
                banner += prefix + iface.getDisplayName() + SEP + addr;
            }
        }
        LOG.info(banner);
        return banner;
    }

}