#!/usr/bin/env python # # 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 os import os.path import sys #TODO is this needed? sys.path.append("devstack") import Logger import Options #TODO fix these from Util import (welcome, rcf8222date, determine_os, prioritize_components, resolve_dependencies) from Util import (NOVA, GLANCE, QUANTUM, SWIFT, KEYSTONE, HORIZON, DB, RABBIT, KEYSTONE_CLIENT, INSTALL, UNINSTALL, START, STOP, ACTIONS, COMPONENT_NAMES, NAMES_PRIORITY, UBUNTU11, RHEL6, STACK_CFG_LOC) from Shell import (mkdir, joinpths, unlink) from Exceptions import (NoTraceException) import Glance import Horizon import Keystone import Nova import Quantum import Config import Swift import Db import Rabbit import Config import KeystoneClient LOG = Logger.getLogger("install") #this determines what classes to use to install/uninstall/... ACTION_CLASSES = { INSTALL: { NOVA: Nova.NovaInstaller, GLANCE: Glance.GlanceInstaller, QUANTUM: Quantum.QuantumInstaller, SWIFT: Swift.SwiftInstaller, HORIZON: Horizon.HorizonInstaller, KEYSTONE: Keystone.KeystoneInstaller, DB: Db.DBInstaller, RABBIT: Rabbit.RabbitInstaller, KEYSTONE_CLIENT: KeystoneClient.KeyStoneClientInstaller, }, UNINSTALL: { NOVA: Nova.NovaUninstaller, GLANCE: Glance.GlanceUninstaller, QUANTUM: Quantum.QuantumUninstaller, SWIFT: Swift.SwiftUninstaller, HORIZON: Horizon.HorizonUninstaller, KEYSTONE: Keystone.KeystoneUninstaller, DB: Db.DBUninstaller, RABBIT: Rabbit.RabbitUninstaller, KEYSTONE_CLIENT: KeystoneClient.KeyStoneClientUninstaller, }, START: { NOVA: Nova.NovaRuntime, GLANCE: Glance.GlanceRuntime, QUANTUM: Quantum.QuantumRuntime, SWIFT: Swift.SwiftRuntime, HORIZON: Horizon.HorizonRuntime, KEYSTONE: Keystone.KeystoneRuntime, DB: Db.DBRuntime, RABBIT: Rabbit.RabbitRuntime, KEYSTONE_CLIENT: KeystoneClient.KeyStoneClientRuntime, }, STOP: { NOVA: Nova.NovaRuntime, GLANCE: Glance.GlanceRuntime, QUANTUM: Quantum.QuantumRuntime, SWIFT: Swift.SwiftRuntime, HORIZON: Horizon.HorizonRuntime, KEYSTONE: Keystone.KeystoneRuntime, DB: Db.DBRuntime, RABBIT: Rabbit.RabbitRuntime, KEYSTONE_CLIENT: KeystoneClient.KeyStoneClientRuntime, }, } def get_package_manager_class(distro): klass = None if(distro == UBUNTU11): #late import required #TODO better way to do this? from packaging import Apt klass = Apt.AptPackager elif(distro == RHEL6): #late import required #TODO better way to do this? from packaging import Yum klass = Yum.YumPackager return klass def get_config(action): fn = STACK_CFG_LOC LOG.info("Loading config from %s" % (fn)) cfg = Config.EnvConfigParser() cfg.read(fn) return cfg def print_cfgs(cfg, action): #this will make the items nice and pretty def item_format(k, v): return "\t%s=%s" % (str(k), str(v)) def map_print(mp): for key in sorted(mp.keys()): value = mp.get(key) LOG.info(item_format(key, value)) #now make it pretty passwords_gotten = cfg.pws full_cfgs = cfg.configs_fetched db_dsns = cfg.db_dsns if(len(passwords_gotten) or len(full_cfgs) or len(db_dsns)): LOG.info("After %s your config is:" % (action)) if(len(passwords_gotten)): LOG.info("Passwords:") map_print(passwords_gotten) if(len(full_cfgs)): #TOD #better way to do this?? (ie a list difference?) filtered_mp = dict() for key in full_cfgs.keys(): if(key in passwords_gotten): continue filtered_mp[key] = full_cfgs.get(key) if(len(filtered_mp)): LOG.info("Configs:") map_print(filtered_mp) if(len(db_dsns)): LOG.info("Data source names:") map_print(db_dsns) def runner(action_name, component_set, distro, root_dir, program_args): #have to make the root dir.... if(action_name == INSTALL): mkdir(root_dir) pkg_manager_cls = get_package_manager_class(distro) pkg_manager = pkg_manager_cls(distro) config = get_config(action_name) LOG.info("Will %s [%s] using root directory %s" % (action_name, ", ".join(component_set), root_dir)) results = list() class_lookup = ACTION_CLASSES.get(action_name) force = program_args.get('force', False) for c in component_set: klass = class_lookup.get(c) instance = klass(components=component_set, distro=distro, pkg=pkg_manager, cfg=config, root=root_dir) if(action_name == INSTALL): LOG.info("Downloading %s." % (c)) am_downloaded = instance.download() LOG.info("Performed %s downloads." % (str(am_downloaded))) LOG.info("Configuring %s." % (c)) am_configured = instance.configure() LOG.info("Configured %s files." % (str(am_configured))) LOG.info("Pre-installing %s." % (c)) instance.pre_install() LOG.info("Installing %s." % (c)) instance.install() LOG.info("Post-installing %s." % (c)) trace = instance.post_install() if(trace): LOG.info("Finished install of %s - check %s for traces of what happened." % (c, trace)) results.append(trace) else: LOG.info("Finished install of %s" % (c)) elif(action_name == STOP): try: LOG.info("Stopping %s." % (c)) stop_am = instance.stop() LOG.info("Stopped %s applications." % (str(stop_am))) LOG.info("Finished stop of %s" % (c)) except NoTraceException, e: if(force): LOG.info("Passing on stopping %s since no trace file was found." % (c)) else: raise elif(action_name == START): LOG.info("Starting %s." % (c)) start_info = instance.start() if(type(start_info) == list): LOG.info("Check [%s] for traces of what happened." % (", ".join(start_info))) results = results + start_info elif(type(start_info) == int): LOG.info("Started %s applications." % (str(start_info))) LOG.info("Finished start of %s." % (c)) elif(action_name == UNINSTALL): try: LOG.info("Unconfiguring %s." % (c)) instance.unconfigure() LOG.info("Uninstalling %s." % (c)) instance.uninstall() except NoTraceException, e: if(force): LOG.info("Passing on uninstalling %s since no trace file was found." % (c)) else: raise #display any configs touched... print_cfgs(config, action_name) #attempt to remove the root dir (might fail if not empty) if(action_name == UNINSTALL): try: os.rmdir(root_dir) except OSError, e: pass return results def check_root(action, rootdir): if(action == INSTALL): root_there = False if(os.path.isdir(rootdir)): sublisting = os.listdir(rootdir) if(len(sublisting) != 0): #something exists, not good root_there = True if(root_there): LOG.error("Root directory [%s] already exists (and it's not empty)! Please remove it or uninstall components!" % (rootdir)) return False else: return True else: return True def check_python(): py_version = sys.version_info major = py_version[0] minor = py_version[1] if(major < 2 or (major == 2 and minor < 6)): return False if(major >= 3): LOG.warn("This script has not been tested in python %s, use at your own risk!" % (major)) return True def main(): if(not check_python()): LOG.error("Your python version is to old, please upgrade to >= 2.6!") return 1 me = __file__ args = Options.parse() components = args.pop("component") or [] if(len(components) == 0): #assume user wants them all components = list(COMPONENT_NAMES) else: #clean the names up and see what is valid after an intersection components = set([x.lower().strip() for x in components]) components = set(COMPONENT_NAMES).intersection(components) if(len(components) == 0): LOG.error("No valid components specified!") LOG.info("Perhaps you should try %s --help" % (me)) return 1 action = args.pop("action") or "" #normalize the action action = action.strip().lower() if(not (action in ACTIONS)): LOG.error("No valid action specified!") LOG.info("Perhaps you should try %s --help" % (me)) return 1 rootdir = args.pop("dir") or "" if(len(rootdir) == 0 or not check_root(action, rootdir)): LOG.error("No valid root directory specified!") LOG.info("Perhaps you should try %s --help" % (me)) return 1 #ensure os/distro is known (install_os, plt) = determine_os() if(install_os == None): LOG.error("Unsupported operating system/distro: %s" % (plt)) return 1 #start it welcome(action) #need to figure out dependencies for components (if any) new_components = resolve_dependencies(action, components) component_diff = new_components.difference(components) if(len(component_diff)): LOG.info("Having to install dependent components: [%s]" % (",".join(component_diff))) components = new_components #get the right component order (by priority) components = prioritize_components(components) #now do it! LOG.info("Starting action [%s] on %s for operating system/distro [%s]" % (action, rcf8222date(), install_os)) resultList = runner(action, components, install_os, rootdir, args) LOG.info("Finished action [%s] on %s" % (action, rcf8222date())) if(resultList and len(resultList)): msg = "Check [%s] for traces of what happened." % (", ".join(resultList)) LOG.info(msg) return 0 if __name__ == "__main__": rc = main() sys.exit(rc)