#!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (C) 2012 Yahoo! Inc. 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. import sys import time import traceback from devstack import cfg from devstack import cfg_helpers from devstack import date from devstack import distro from devstack import env from devstack import env_rc from devstack import log as logging from devstack import opts from devstack import settings from devstack import shell as sh from devstack import utils from devstack.progs import actions LOG = logging.getLogger("devstack.stack") # This is used to map an action to a useful string for # the welcome display _WELCOME_MAP = { settings.INSTALL: "INSTALLER", settings.UNINSTALL: "UNINSTALLER", settings.START: "STARTER", settings.STOP: "STOPPER", } _CFG_GROUPS = { cfg_helpers.make_id('passwords', None): 'Passwords', cfg_helpers.make_id('db', None): 'Database info', # Catch all cfg_helpers.make_id(None, None): 'Misc configs', } _CFG_ORDERING = sorted(_CFG_GROUPS.keys()) _CFG_ORDERING.reverse() def dump_config(config_cache): def item_format(key, value): return "\t%s=%s" % (str(key), str(value)) def map_print(mp): for key in sorted(mp.keys()): value = mp.get(key) LOG.info(item_format(key, value)) # First partition into our groups partitions = dict() for name in _CFG_ORDERING: partitions[name] = dict() # Now put the config cached values into there partitions for (k, v) in config_cache.items(): for name in _CFG_ORDERING: entries = partitions[name] if k.startswith(name): entries[k] = v break # Now print them.. for name in _CFG_ORDERING: nice_name = _CFG_GROUPS.get(name) LOG.info(nice_name + ":") entries = partitions.get(name) if entries: map_print(entries) def load_rc_files(): fns = [settings.OSRC_FN] for fn in fns: try: LOG.debug("Attempting to load rc file at [%s] which has your environment settings." % (fn)) am_loaded = env_rc.RcReader().load(fn) LOG.debug("Loaded [%s] settings from rc file [%s]" % (am_loaded, fn)) except IOError: LOG.warn('Error reading rc file located at [%s]. Skipping loading it.' % (fn)) return len(fns) def run(args): action = args.pop("action", '').strip().lower() if not (action in settings.ACTIONS): print(utils.color_text("No valid action specified!", "red")) return False loaded_rcs = False root_dir = args.pop("dir") if not root_dir: load_rc_files() loaded_rcs = True root_dir = env.get_key(env_rc.INSTALL_ROOT) if not root_dir: print(utils.color_text("No root directory specified!", "red")) return False root_dir = sh.abspth(root_dir) persona_fn = args.pop('persona_fn') if not persona_fn or not sh.isfile(persona_fn): print(utils.color_text("No valid persona file name specified!", "red")) return False # Welcome! (repeat_string, line_max_len) = utils.welcome(_WELCOME_MAP.get(action)) print(utils.center_text("Action Runner", repeat_string, line_max_len)) # !! # Here on out we should be using the logger (and not print)!! # !! # If we didn't load them before, load them now if not loaded_rcs: load_rc_files() loaded_rcs = True # Stash the dryrun value (if any) into the global configuration sh.set_dryrun(args.pop('dryrun')) dist = distro.Distro.get_current() config = cfg.get_config() runner = actions.ActionRunner(dist, action, config, **args) LOG.info("Starting action [%s] on %s for distro [%s]" % (action, date.rcf8222date(), dist)) start_time = time.time() runner.run(persona_fn, root_dir) end_time = time.time() LOG.info("It took (%s) to complete action [%s]" % (utils.format_secs_taken((end_time - start_time)), action)) LOG.info("After action [%s] your settings which were created or read are:" % (action)) dump_config(config.configs_fetched) return True def main(): # Do this first so people can see the help message... args = opts.parse() prog_name = sys.argv[0] # Configure logging utils.configure_logging(args['verbosity'], args['dryrun']) LOG.debug("Command line options %s" % (args)) # Will need root to setup openstack if not sh.got_root(): rest_args = sys.argv[1:] print("This program requires a user with sudo access.") msg = "Perhaps you should try %s %s" % \ (utils.color_text("sudo %s" % (prog_name), "red", True), " ".join(rest_args)) print(msg) return 1 try: # Drop to usermode sh.user_mode(False) started_ok = run(args) if not started_ok: me = utils.color_text(prog_name, "red", True) me += " " + utils.color_text('--help', 'red') print("Perhaps you should try %s" % (me)) return 1 else: utils.goodbye(True) return 0 except Exception: utils.goodbye(False) traceback.print_exc(file=sys.stdout) return 1 if __name__ == "__main__": sys.exit(main())