From 495f4bcbba868b193b4d4f305731b3ab4954c931 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Fri, 13 Jan 2012 12:07:41 -0800 Subject: [PATCH] Mass import/from adjustment and adding option force to ignore traces not found. --- devstack/Component.py | 4 +- devstack/Config.py | 7 +- devstack/Db.py | 14 ++-- devstack/Exceptions.py | 4 + devstack/Glance.py | 25 +++--- devstack/Horizon.py | 9 ++- devstack/Keystone.py | 45 +++++------ devstack/Logger.py | 2 +- devstack/Nova.py | 9 ++- devstack/Options.py | 20 +++-- devstack/Packager.py | 4 +- devstack/Quantum.py | 19 ++--- devstack/Rabbit.py | 14 ++-- devstack/Shell.py | 20 ++--- devstack/Swift.py | 9 ++- devstack/Trace.py | 21 ++--- devstack/Util.py | 23 +++--- stack | 175 ++++++++++++++++++++++------------------- 18 files changed, 210 insertions(+), 214 deletions(-) diff --git a/devstack/Component.py b/devstack/Component.py index d4215ba0..d1398224 100644 --- a/devstack/Component.py +++ b/devstack/Component.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -import Util +from Util import (component_pths) """ An abstraction that different components @@ -29,7 +29,7 @@ class ComponentBase(): self.distro = kargs.get("distro") self.root = kargs.get("root") self.othercomponents = set(kargs.get("components")) - pths = Util.component_pths(self.root, component_name) + pths = component_pths(self.root, component_name) self.componentroot = pths.get('root_dir') self.tracedir = pths.get("trace_dir") self.appdir = pths.get("app_dir") diff --git a/devstack/Config.py b/devstack/Config.py index b4edc0b1..ad5bdc31 100644 --- a/devstack/Config.py +++ b/devstack/Config.py @@ -13,14 +13,13 @@ # License for the specific language governing permissions and limitations # under the License. +import ConfigParser import os import re -import ConfigParser -import Shell -import Logger -import Exceptions from Exceptions import (BadParamException) +import Logger +import Shell LOG = Logger.getLogger("install.config") PW_TMPL = "Enter a password for %s: " diff --git a/devstack/Db.py b/devstack/Db.py index 27c9ce68..a5c26487 100644 --- a/devstack/Db.py +++ b/devstack/Db.py @@ -17,19 +17,15 @@ import re import Logger import Packager -import Component from Component import (ComponentBase, RuntimeComponent, UninstallComponent, InstallComponent) -import Util from Util import (DB, get_pkg_list, get_host_ip, execute_template) -import Exceptions from Exceptions import (StartException, StopException, StatusException, RestartException) -import Trace -from Trace import (TraceWriter, TraceReader) -import Shell +from Trace import (TraceWriter, TraceReader, + IN_TRACE) from Shell import (mkdirslist, execute, deldir, load_file, write_file) @@ -63,7 +59,7 @@ BASE_ERROR = 'Currently we do not know how to %s for database type [%s]' class DBUninstaller(ComponentBase, UninstallComponent): def __init__(self, *args, **kargs): ComponentBase.__init__(self, TYPE, *args, **kargs) - self.tracereader = TraceReader(self.tracedir, Trace.IN_TRACE) + self.tracereader = TraceReader(self.tracedir, IN_TRACE) self.runtime = DBRuntime(*args, **kargs) def unconfigure(self): @@ -87,7 +83,7 @@ class DBUninstaller(ComponentBase, UninstallComponent): class DBInstaller(ComponentBase, InstallComponent): def __init__(self, *args, **kargs): ComponentBase.__init__(self, TYPE, *args, **kargs) - self.tracewriter = TraceWriter(self.tracedir, Trace.IN_TRACE) + self.tracewriter = TraceWriter(self.tracedir, IN_TRACE) self.runtime = DBRuntime(*args, **kargs) def download(self): @@ -156,7 +152,7 @@ class DBInstaller(ComponentBase, InstallComponent): class DBRuntime(ComponentBase, RuntimeComponent): def __init__(self, *args, **kargs): ComponentBase.__init__(self, TYPE, *args, **kargs) - self.tracereader = TraceReader(self.tracedir, Trace.IN_TRACE) + self.tracereader = TraceReader(self.tracedir, IN_TRACE) def _gettypeactions(self, act, exception_cls): pkgsinstalled = self.tracereader.packages_installed() diff --git a/devstack/Exceptions.py b/devstack/Exceptions.py index 5ac3d777..bca6b641 100644 --- a/devstack/Exceptions.py +++ b/devstack/Exceptions.py @@ -26,6 +26,10 @@ class BadParamException(Exception): pass +class NoTraceException(Exception): + pass + + class NoReplacementException(Exception): pass diff --git a/devstack/Glance.py b/devstack/Glance.py index 43205b12..121f672b 100644 --- a/devstack/Glance.py +++ b/devstack/Glance.py @@ -17,25 +17,24 @@ import json import os.path import Logger -import Component from Component import (ComponentBase, RuntimeComponent, UninstallComponent, InstallComponent) import Shell import Util -import Trace -from Trace import (TraceWriter, TraceReader) +from Trace import (TraceWriter, TraceReader, + IN_TRACE, START_TRACE, PY_TRACE, + parse_fn, touch_trace) import Downloader import Packager import Runner -import runners.Foreground as Foreground from runners.Foreground import (ForegroundRunner) from Util import (GLANCE, + STACK_CONFIG_DIR, get_pkg_list, get_host_ip, param_replace, get_dbdsn, ) from Shell import (execute, deldir, mkdirslist, unlink, joinpths, load_file, write_file, touch_file) -import Exceptions from Exceptions import (StopException, StartException, InstallException) LOG = Logger.getLogger("install.glance") @@ -69,7 +68,7 @@ class GlanceBase(ComponentBase): class GlanceUninstaller(GlanceBase, UninstallComponent): def __init__(self, *args, **kargs): GlanceBase.__init__(self, *args, **kargs) - self.tracereader = TraceReader(self.tracedir, Trace.IN_TRACE) + self.tracereader = TraceReader(self.tracedir, IN_TRACE) def unconfigure(self): #get rid of all files configured @@ -113,9 +112,9 @@ class GlanceRuntime(GlanceBase, RuntimeComponent): def __init__(self, *args, **kargs): GlanceBase.__init__(self, *args, **kargs) self.foreground = kargs.get("foreground", True) - self.tracereader = TraceReader(self.tracedir, Trace.IN_TRACE) - self.tracewriter = TraceWriter(self.tracedir, Trace.START_TRACE) - self.starttracereader = TraceReader(self.tracedir, Trace.START_TRACE) + self.tracereader = TraceReader(self.tracedir, IN_TRACE) + self.tracewriter = TraceWriter(self.tracedir, START_TRACE) + self.starttracereader = TraceReader(self.tracedir, START_TRACE) def _getstartercls(self): if(self.foreground): @@ -178,7 +177,7 @@ class GlanceRuntime(GlanceBase, RuntimeComponent): if(fn == None or name == None): continue #figure out which class will stop it - contents = Trace.parse_fn(fn) + contents = parse_fn(fn) killcls = None for (cmd, action) in contents: if(cmd == Runner.RUN_TYPE): @@ -204,7 +203,7 @@ class GlanceInstaller(GlanceBase, InstallComponent): GlanceBase.__init__(self, *args, **kargs) self.gitloc = self.cfg.get("git", "glance_repo") self.brch = self.cfg.get("git", "glance_branch") - self.tracewriter = TraceWriter(self.tracedir, Trace.IN_TRACE) + self.tracewriter = TraceWriter(self.tracedir, IN_TRACE) def download(self): dirsmade = Downloader.download(self.appdir, self.gitloc, self.brch) @@ -233,7 +232,7 @@ class GlanceInstaller(GlanceBase, InstallComponent): dirsmade = mkdirslist(self.tracedir) #this trace is used to remove the dirs created self.tracewriter.dir_made(*dirsmade) - recordwhere = Trace.touch_trace(self.tracedir, Trace.PY_TRACE) + recordwhere = touch_trace(self.tracedir, PY_TRACE) #this trace is used to remove the trace created self.tracewriter.py_install(recordwhere) (sysout, stderr) = execute(*PY_INSTALL, cwd=self.appdir, run_as_root=True) @@ -250,7 +249,7 @@ class GlanceInstaller(GlanceBase, InstallComponent): #and adjust that template to have real values and then go through #the resultant config file and perform and adjustments (directory creation...) #and then write that to the glance configuration directory. - sourcefn = joinpths(Util.STACK_CONFIG_DIR, TYPE, fn) + sourcefn = joinpths(STACK_CONFIG_DIR, TYPE, fn) tgtfn = joinpths(self.cfgdir, fn) LOG.info("Configuring template file %s" % (sourcefn)) contents = load_file(sourcefn) diff --git a/devstack/Horizon.py b/devstack/Horizon.py index 190938bd..dd2721c3 100644 --- a/devstack/Horizon.py +++ b/devstack/Horizon.py @@ -15,7 +15,8 @@ import Logger -import Component +from Component import (ComponentBase, RuntimeComponent, + UninstallComponent, InstallComponent) LOG = Logger.getLogger("install.horizon") @@ -30,16 +31,16 @@ class HorizonTraceReader(): pass -class HorizonUninstaller(Component.UninstallComponent): +class HorizonUninstaller(UninstallComponent): def __init__(self, *args, **kargs): pass -class HorizonInstaller(Component.InstallComponent): +class HorizonInstaller(InstallComponent): def __init__(self, *args, **kargs): pass -class HorizonRuntime(Component.RuntimeComponent): +class HorizonRuntime(RuntimeComponent): def __init__(self, *args, **kargs): pass diff --git a/devstack/Keystone.py b/devstack/Keystone.py index eee419c6..f9b8e3db 100644 --- a/devstack/Keystone.py +++ b/devstack/Keystone.py @@ -16,22 +16,21 @@ import os import os.path -import Util -from Util import (KEYSTONE, +from Util import (KEYSTONE, + CONFIG_DIR, STACK_CONFIG_DIR, + NOVA, GLANCE, SWIFT, get_pkg_list, get_dbdsn, param_replace, get_host_ip, execute_template) import Logger -import Component import Downloader -import Trace import Db -from Trace import (TraceWriter, TraceReader) -import Shell +from Trace import (TraceWriter, TraceReader, + touch_trace, + IN_TRACE, PY_TRACE) from Shell import (execute, mkdirslist, write_file, load_file, joinpths, touch_file, unlink, deldir) -import Component from Component import (ComponentBase, RuntimeComponent, UninstallComponent, InstallComponent) @@ -49,15 +48,14 @@ DB_NAME = "keystone" class KeystoneBase(ComponentBase): def __init__(self, *args, **kargs): ComponentBase.__init__(self, TYPE, *args, **kargs) - self.cfgdir = joinpths(self.appdir, Util.CONFIG_DIR) + self.cfgdir = joinpths(self.appdir, CONFIG_DIR) self.bindir = joinpths(self.appdir, BIN_DIR) - self.scriptfn = joinpths(Util.STACK_CONFIG_DIR, TYPE, DATA_SCRIPT) class KeystoneUninstaller(KeystoneBase, UninstallComponent): def __init__(self, *args, **kargs): KeystoneBase.__init__(self, *args, **kargs) - self.tracereader = TraceReader(self.tracedir, Trace.IN_TRACE) + self.tracereader = TraceReader(self.tracedir, IN_TRACE) def unconfigure(self): #get rid of all files configured @@ -102,7 +100,7 @@ class KeystoneInstaller(KeystoneBase, InstallComponent): KeystoneBase.__init__(self, *args, **kargs) self.gitloc = self.cfg.get("git", "keystone_repo") self.brch = self.cfg.get("git", "keystone_branch") - self.tracewriter = TraceWriter(self.tracedir, Trace.IN_TRACE) + self.tracewriter = TraceWriter(self.tracedir, IN_TRACE) def download(self): dirsmade = Downloader.download(self.appdir, self.gitloc, self.brch) @@ -128,7 +126,7 @@ class KeystoneInstaller(KeystoneBase, InstallComponent): dirsmade = mkdirslist(self.tracedir) #this trace is used to remove the dirs created self.tracewriter.dir_made(*dirsmade) - recordwhere = Trace.touch_trace(self.tracedir, Trace.PY_TRACE) + recordwhere = touch_trace(self.tracedir, PY_TRACE) #this trace is used to remove the trace created self.tracewriter.py_install(recordwhere) (sysout, stderr) = execute(*PY_INSTALL, cwd=self.appdir, run_as_root=True) @@ -143,7 +141,7 @@ class KeystoneInstaller(KeystoneBase, InstallComponent): dirsmade = mkdirslist(self.cfgdir) self.tracewriter.dir_made(*dirsmade) for fn in CONFIGS: - sourcefn = joinpths(Util.STACK_CONFIG_DIR, TYPE, fn) + sourcefn = joinpths(STACK_CONFIG_DIR, TYPE, fn) tgtfn = joinpths(self.cfgdir, fn) LOG.info("Configuring template file %s" % (sourcefn)) contents = load_file(sourcefn) @@ -165,7 +163,6 @@ class KeystoneInstaller(KeystoneBase, InstallComponent): def _setup_data(self): params = self._get_param_map() - params['BIN_DIR'] = self.bindir cmds = _keystone_setup_cmds(self.othercomponents) execute_template(*cmds, params=params, ignore_missing=True) @@ -203,9 +200,9 @@ class KeystoneInstaller(KeystoneBase, InstallComponent): mp['DEST'] = self.appdir mp['SQL_CONN'] = get_dbdsn(self.cfg, DB_NAME) mp['ADMIN_PASSWORD'] = self.cfg.getpw('passwords', 'horizon_keystone_admin') - hostip = get_host_ip(self.cfg) - mp['SERVICE_HOST'] = hostip - mp['HOST_IP'] = hostip + mp['HOST_IP'] = get_host_ip(self.cfg) + mp['SERVICE_TOKEN'] = self.cfg.getpw("passwords", "service_token") + mp['BIN_DIR'] = self.bindir return mp @@ -360,7 +357,7 @@ def _keystone_setup_cmds(components): ] }) - if(Util.NOVA in components): + if(NOVA in components): services.append({ "cmd": [ "%BIN_DIR%/keystone-manage", "service", "add", @@ -374,7 +371,7 @@ def _keystone_setup_cmds(components): ] }) - if(Util.GLANCE in components): + if(GLANCE in components): services.append({ "cmd": [ "%BIN_DIR%/keystone-manage", "service", "add", "glance", @@ -382,7 +379,7 @@ def _keystone_setup_cmds(components): ] }) - if(Util.SWIFT in components): + if(SWIFT in components): services.append({ "cmd": [ "%BIN_DIR%/keystone-manage", "service", "add", @@ -404,7 +401,7 @@ def _keystone_setup_cmds(components): ] }) - if(Util.NOVA in components): + if(NOVA in components): endpoint_templates.append({ "cmd": [ "%BIN_DIR%/keystone-manage", "endpointTemplates", "add", @@ -428,7 +425,7 @@ def _keystone_setup_cmds(components): ] }) - if(Util.GLANCE in components): + if(GLANCE in components): endpoint_templates.append({ "cmd": [ "%BIN_DIR%/keystone-manage", "endpointTemplates", "add", @@ -441,7 +438,7 @@ def _keystone_setup_cmds(components): ] }) - if(Util.SWIFT in components): + if(SWIFT in components): endpoint_templates.append({ "cmd": [ "%BIN_DIR%/keystone-manage", "endpointTemplates", "add", @@ -468,7 +465,7 @@ def _keystone_setup_cmds(components): # but keystone doesn't parse them - it is just a blob from keystone's # point of view ec2_creds = [] - if(Util.NOVA in components): + if(NOVA in components): ec2_creds = [ { "cmd": [ diff --git a/devstack/Logger.py b/devstack/Logger.py index 369887d4..8fd68168 100644 --- a/devstack/Logger.py +++ b/devstack/Logger.py @@ -14,8 +14,8 @@ # under the License. import logging -import sys import os +import sys #requires http://pypi.python.org/pypi/termcolor #but the colors make it worth it :-) diff --git a/devstack/Nova.py b/devstack/Nova.py index 151a73cb..85cca704 100644 --- a/devstack/Nova.py +++ b/devstack/Nova.py @@ -15,21 +15,22 @@ import Logger -import Component +from Component import (ComponentBase, RuntimeComponent, + UninstallComponent, InstallComponent) LOG = Logger.getLogger("install.nova") -class NovaUninstaller(Component.UninstallComponent): +class NovaUninstaller(UninstallComponent): def __init__(self, *args, **kargs): pass -class NovaInstaller(Component.InstallComponent): +class NovaInstaller(InstallComponent): def __init__(self, *args, **kargs): pass -class NovaRuntime(Component.RuntimeComponent): +class NovaRuntime(RuntimeComponent): def __init__(self, *args, **kargs): pass diff --git a/devstack/Options.py b/devstack/Options.py index bef1b22a..cc180d90 100644 --- a/devstack/Options.py +++ b/devstack/Options.py @@ -13,19 +13,16 @@ # License for the specific language governing permissions and limitations # under the License. -import optparse from optparse import OptionParser -import Util - -VERSION_ID = "%0.2f" % (Util.VERSION) - +from Util import (VERSION, VERSION_STR, ACTIONS, COMPONENT_NAMES) def parse(): - versionstr = "%prog v" + VERSION_ID + + versionstr = "%prog v" + VERSION_STR parser = OptionParser(version=versionstr) - known_actions = sorted(set(Util.ACTIONS)) + known_actions = sorted(ACTIONS) actions = "(" + ", ".join(known_actions) + ")" parser.add_option("-a", "--action", action="store", @@ -41,13 +38,19 @@ def parse(): metavar="DIR", help="root DIR for new components or DIR with existing components (ACTION dependent)") - known_components = sorted(set(Util.NAMES)) + known_components = sorted(COMPONENT_NAMES) components = "(" + ", ".join(known_components) + ")" parser.add_option("-c", "--component", action="append", dest="component", help="stack component, ie %s" % (components)) + parser.add_option("-f", "--force", + action="store_true", + dest="force", + help="force ACTION even if no trace found (ACTION dependent)", + default=False) + (options, args) = parser.parse_args() #extract only what we care about @@ -56,4 +59,5 @@ def parse(): output['dir'] = options.dir output['action'] = options.action output['extras'] = args + output['force'] = options.force return output diff --git a/devstack/Packager.py b/devstack/Packager.py index 9d9b09bf..90ba3167 100644 --- a/devstack/Packager.py +++ b/devstack/Packager.py @@ -21,9 +21,7 @@ frameworks (ie apt, yum) can inherit from import Logger import Shell -from Shell import execute -import Util -from Util import execute_template +from Util import (execute_template) LOG = Logger.getLogger("install.packager") diff --git a/devstack/Quantum.py b/devstack/Quantum.py index 50a5f0d5..a9baf529 100644 --- a/devstack/Quantum.py +++ b/devstack/Quantum.py @@ -15,31 +15,22 @@ import Logger -import Component +from Component import (ComponentBase, RuntimeComponent, + UninstallComponent, InstallComponent) LOG = Logger.getLogger("install.quantum") -class QuantumTraceWriter(): - def __init__(self, root): - pass - - -class QuantumTraceReader(): - def __init__(self, root): - pass - - -class QuantumUninstaller(Component.UninstallComponent): +class QuantumUninstaller(UninstallComponent): def __init__(self, *args, **kargs): pass -class QuantumInstaller(Component.InstallComponent): +class QuantumInstaller(InstallComponent): def __init__(self, *args, **kargs): pass -class QuantumRuntime(Component.RuntimeComponent): +class QuantumRuntime(RuntimeComponent): def __init__(self, *args, **kargs): pass diff --git a/devstack/Rabbit.py b/devstack/Rabbit.py index 594d2e48..332ee85c 100644 --- a/devstack/Rabbit.py +++ b/devstack/Rabbit.py @@ -15,19 +15,15 @@ import Logger -import Component from Component import (ComponentBase, RuntimeComponent, UninstallComponent, InstallComponent) -import Exceptions from Exceptions import (StartException, StopException, StatusException, RestartException) import Packager -import Util from Util import (RABBIT, get_pkg_list) -import Trace -from Trace import (TraceWriter, TraceReader) -import Shell +from Trace import (TraceWriter, TraceReader, + IN_TRACE) from Shell import (mkdirslist, execute, deldir) LOG = Logger.getLogger("install.rabbit") @@ -44,7 +40,7 @@ PWD_CMD = ['rabbitmqctl', 'change_password', 'guest'] class RabbitUninstaller(ComponentBase, UninstallComponent): def __init__(self, *args, **kargs): ComponentBase.__init__(self, TYPE, *args, **kargs) - self.tracereader = TraceReader(self.tracedir, Trace.IN_TRACE) + self.tracereader = TraceReader(self.tracedir, IN_TRACE) def unconfigure(self): #nothing to unconfigure, we are just a pkg @@ -67,7 +63,7 @@ class RabbitUninstaller(ComponentBase, UninstallComponent): class RabbitInstaller(ComponentBase, InstallComponent): def __init__(self, *args, **kargs): ComponentBase.__init__(self, TYPE, *args, **kargs) - self.tracewriter = TraceWriter(self.tracedir, Trace.IN_TRACE) + self.tracewriter = TraceWriter(self.tracedir, IN_TRACE) self.runtime = RabbitRuntime(*args, **kargs) def download(self): @@ -109,7 +105,7 @@ class RabbitInstaller(ComponentBase, InstallComponent): class RabbitRuntime(ComponentBase, RuntimeComponent): def __init__(self, *args, **kargs): ComponentBase.__init__(self, TYPE, *args, **kargs) - self.tracereader = TraceReader(self.tracedir, Trace.IN_TRACE) + self.tracereader = TraceReader(self.tracedir, IN_TRACE) def start(self): pkgsinstalled = self.tracereader.packages_installed() diff --git a/devstack/Shell.py b/devstack/Shell.py index 061478a7..7956a0c0 100644 --- a/devstack/Shell.py +++ b/devstack/Shell.py @@ -13,17 +13,16 @@ # License for the specific language governing permissions and limitations # under the License. -import subprocess -import shlex import getpass -import sys -import os.path -import os -import shutil import json +import os +import os.path +import shlex +import shutil +import subprocess +import sys -import Exceptions -from Exceptions import ProcessExecutionError, FileException +from Exceptions import (ProcessExecutionError, FileException) import Logger ROOT_HELPER = ["sudo"] @@ -33,6 +32,7 @@ LOG = Logger.getLogger("install.shell") def execute(*cmd, **kwargs): + process_input = kwargs.pop('process_input', None) check_exit_code = kwargs.pop('check_exit_code', [0]) cwd = kwargs.pop('cwd', None) @@ -77,9 +77,9 @@ def execute(*cmd, **kwargs): stderr_fh = kwargs.get('stderr_fh') LOG.debug("Redirecting stderr to file handle: %s" % (stderr_fh)) - process_env = None + process_env = dict(os.environ) + LOG.debug("With environment: %s" % (process_env)) if(env_overrides and len(env_overrides)): - process_env = dict(os.environ) LOG.debug("With additional environment overrides: %s" % (env_overrides)) for (k, v) in env_overrides.items(): process_env[k] = str(v) diff --git a/devstack/Swift.py b/devstack/Swift.py index 4faf8629..dc9ed108 100644 --- a/devstack/Swift.py +++ b/devstack/Swift.py @@ -15,21 +15,22 @@ import Logger -import Component +from Component import (ComponentBase, RuntimeComponent, + UninstallComponent, InstallComponent) LOG = Logger.getLogger("install.swift") -class SwiftUninstaller(Component.UninstallComponent): +class SwiftUninstaller(UninstallComponent): def __init__(self, *args, **kargs): pass -class SwiftInstaller(Component.InstallComponent): +class SwiftInstaller(InstallComponent): def __init__(self, *args, **kargs): pass -class SwiftRuntime(Component.RuntimeComponent): +class SwiftRuntime(RuntimeComponent): def __init__(self, *args, **kargs): pass diff --git a/devstack/Trace.py b/devstack/Trace.py index 37961d18..34cff2a7 100644 --- a/devstack/Trace.py +++ b/devstack/Trace.py @@ -13,14 +13,14 @@ # License for the specific language governing permissions and limitations # under the License. -import os.path import json +import os.path -import Util +from Exceptions import (NoTraceException) from Util import (rcf8222date) - -import Shell -from Shell import (touch_file, append_file, joinpths, load_file, mkdirslist) +from Shell import (touch_file, append_file, + joinpths, load_file, mkdirslist, + isfile) TRACE_FMT = "%s - %s\n" TRACE_EXT = ".trace" @@ -148,7 +148,6 @@ class TraceReader(): for (cmd, action) in lines: if(cmd == FILE_TOUCHED and len(action)): files.append(action) - #ensure no dups files = list(set(files)) files.sort() return files @@ -159,9 +158,8 @@ class TraceReader(): for (cmd, action) in lines: if(cmd == DIR_MADE and len(action)): dirs.append(action) - #ensure not dups - dirs = list(set(dirs)) #ensure in ok order (ie /tmp is before /) + dirs = list(set(dirs)) dirs.sort() dirs.reverse() return dirs @@ -182,7 +180,6 @@ class TraceReader(): for (cmd, action) in lines: if(cmd == CFG_WRITING_FILE and len(action)): files.append(action) - #ensure not dups files = list(set(files)) files.sort() return files @@ -231,6 +228,9 @@ def read(rootdir, name): def parse_fn(fn): + if(not isfile(fn)): + msg = "No trace found at filename %s" % (fn) + raise NoTraceException(msg) contents = load_file(fn) lines = contents.splitlines() accum = list() @@ -243,4 +243,5 @@ def parse_fn(fn): def parse_name(rootdir, name): - return parse_fn(trace_fn(rootdir, name)) + fn = trace_fn(rootdir, name) + return parse_fn(fn) diff --git a/devstack/Util.py b/devstack/Util.py index 21ac6482..85f4df9e 100644 --- a/devstack/Util.py +++ b/devstack/Util.py @@ -13,28 +13,27 @@ # License for the specific language governing permissions and limitations # under the License. -import Exceptions +from time import (localtime, strftime) +from termcolor import colored +import os +import platform +import re +import subprocess + from Exceptions import (BadRegexException, NoReplacementException, FileException) import Logger -import Shell from Shell import (joinpths, load_json, execute) -from time import (localtime, strftime) -from termcolor import colored -import subprocess -import platform -import re -import os - #constant goodies VERSION = 0x2 +VERSION_STR = "%0.2f" % (VERSION) DEVSTACK = 'DEVSTACK' #these also have meaning outside python #ie in the pkg listings so update there also! -UBUNTU12 = "ubuntu-oneiric" +UBUNTU11 = "ubuntu-oneiric" RHEL6 = "rhel-6" #GIT master @@ -58,7 +57,7 @@ HORIZON = "horizon" KEYSTONE = "keystone" DB = "db" RABBIT = "rabbit" -NAMES = [NOVA, GLANCE, QUANTUM, +COMPONENT_NAMES = [NOVA, GLANCE, QUANTUM, SWIFT, HORIZON, KEYSTONE, DB, RABBIT] @@ -112,7 +111,7 @@ STACK_CFG_LOC = joinpths(STACK_CONFIG_DIR, "stack.ini") #this regex is how we match python platform output to #a known constant KNOWN_OS = { - UBUNTU12: '/Ubuntu(.*)oneiric/i', + UBUNTU11: '/Ubuntu(.*)oneiric/i', RHEL6: '/redhat-6\.(\d+)/i', } diff --git a/stack b/stack index 884a0bde..f3473182 100755 --- a/stack +++ b/stack @@ -13,26 +13,26 @@ # License for the specific language governing permissions and limitations # under the License. +import operator import os import os.path import sys -import operator #TODO is this needed? sys.path.append("devstack") import Logger import Options -import Util -from Util import ( - welcome, - rcf8222date, - determine_os, - get_pkg_list - ) -import Shell +from Util import (welcome, rcf8222date, determine_os, get_pkg_list) +from Util import (NOVA, GLANCE, QUANTUM, SWIFT, KEYSTONE, HORIZON, DB, RABBIT, + INSTALL, UNINSTALL, START, STOP, + ACTIONS, COMPONENT_NAMES, NAMES_PRIORITY, + UBUNTU11, RHEL6, + STACK_CFG_LOC) from Shell import (mkdir, joinpths, unlink) -import Config +from Config import (EnvConfigParser) +from Exceptions import (NoTraceException) + import Glance import Horizon import Keystone @@ -42,82 +42,82 @@ import Config import Swift import Db import Rabbit -import Trace LOG = Logger.getLogger("install") #this determines what classes to use to install/uninstall/... ACTION_CLASSES = { - Util.INSTALL: { - Util.NOVA: Nova.NovaInstaller, - Util.GLANCE: Glance.GlanceInstaller, - Util.QUANTUM: Quantum.QuantumInstaller, - Util.SWIFT: Swift.SwiftInstaller, - Util.HORIZON: Horizon.HorizonInstaller, - Util.KEYSTONE: Keystone.KeystoneInstaller, - Util.DB: Db.DBInstaller, - Util.RABBIT: Rabbit.RabbitInstaller, + 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, }, - Util.UNINSTALL: { - Util.NOVA: Nova.NovaUninstaller, - Util.GLANCE: Glance.GlanceUninstaller, - Util.QUANTUM: Quantum.QuantumUninstaller, - Util.SWIFT: Swift.SwiftUninstaller, - Util.HORIZON: Horizon.HorizonUninstaller, - Util.KEYSTONE: Keystone.KeystoneUninstaller, - Util.DB: Db.DBUninstaller, - Util.RABBIT: Rabbit.RabbitUninstaller, + 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, }, - Util.START: { - Util.NOVA: Nova.NovaRuntime, - Util.GLANCE: Glance.GlanceRuntime, - Util.QUANTUM: Quantum.QuantumRuntime, - Util.SWIFT: Swift.SwiftRuntime, - Util.HORIZON: Horizon.HorizonRuntime, - Util.KEYSTONE: Keystone.KeystoneRuntime, - Util.DB: Db.DBRuntime, - Util.RABBIT: Rabbit.RabbitRuntime, + 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, }, - Util.STOP: { - Util.NOVA: Nova.NovaRuntime, - Util.GLANCE: Glance.GlanceRuntime, - Util.QUANTUM: Quantum.QuantumRuntime, - Util.SWIFT: Swift.SwiftRuntime, - Util.HORIZON: Horizon.HorizonRuntime, - Util.KEYSTONE: Keystone.KeystoneRuntime, - Util.DB: Db.DBRuntime, - Util.RABBIT: Rabbit.RabbitRuntime, + 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, }, } #actions which need dependent actions to occur -DEP_ACTIONS_NEEDED = set([Util.START, Util.STOP, Util.INSTALL]) +DEP_ACTIONS_NEEDED = set([START, STOP, INSTALL]) -def get_pkg_manager(distro): +def get_package_manager_kls(distro): klass = None - if(distro == Util.UBUNTU12): + if(distro == UBUNTU11): #late import required #TODO better way to do this? from packaging import Apt klass = Apt.AptPackager - elif(distro == Util.RHEL6): + elif(distro == RHEL6): #late import required #TODO better way to do this? from packaging import Yum klass = Yum.YumPackager - return klass() + return klass def get_config(): - LOG.info("Loading config from %s" % (Util.STACK_CFG_LOC)) - cfg = Config.EnvConfigParser() - cfg.read(Util.STACK_CFG_LOC) + LOG.info("Loading config from %s" % (STACK_CFG_LOC)) + cfg = EnvConfigParser() + cfg.read(STACK_CFG_LOC) return cfg -def stop(components, distro, rootdir): - pkg_manager = get_pkg_manager(distro) +def stop(components, distro, rootdir, args): + pkg_manager_cls = get_package_manager_kls(distro) + pkg_manager = pkg_manager_cls() cfg = get_config() LOG.info("Will stop [%s] from %s" % (", ".join(components), rootdir)) klass_lookup = ACTION_CLASSES.get(Util.START) @@ -130,8 +130,9 @@ def stop(components, distro, rootdir): return None -def start(components, distro, rootdir): - pkg_manager = get_pkg_manager(distro) +def start(components, distro, rootdir, args): + pkg_manager_cls = get_package_manager_kls(distro) + pkg_manager = pkg_manager_cls() cfg = get_config() LOG.info("Will start [%s] from %s" % (", ".join(components), rootdir)) klass_lookup = ACTION_CLASSES.get(Util.START) @@ -146,8 +147,9 @@ def start(components, distro, rootdir): return locations -def install(components, distro, rootdir): - pkg_manager = get_pkg_manager(distro) +def install(components, distro, rootdir, args): + pkg_manager_cls = get_package_manager_kls(distro) + pkg_manager = pkg_manager_cls() cfg = get_config() mkdir(rootdir) LOG.info("Will install [%s] and store in %s." % (", ".join(components), rootdir)) @@ -167,18 +169,26 @@ def install(components, distro, rootdir): return traces -def uninstall(components, distro, rootdir): - pkg_manager = get_pkg_manager(distro) +def uninstall(components, distro, rootdir, args): + ignore_traces_missing = args.get('force', False) + pkg_manager_cls = get_package_manager_kls(distro) + pkg_manager = pkg_manager_cls() cfg = get_config() LOG.info("Will uninstall [%s] with traces from directory %s." % (", ".join(components), rootdir)) - klass_lookup = ACTION_CLASSES.get(Util.UNINSTALL) + klass_lookup = ACTION_CLASSES.get(UNINSTALL) for c in components: klass = klass_lookup.get(c) - instance = klass(components=components, distro=distro, pkg=pkg_manager, cfg=cfg, root=rootdir) - LOG.info("Unconfiguring %s." % (c)) - instance.unconfigure() - LOG.info("Uninstalling %s." % (c)) - instance.uninstall() + try: + instance = klass(components=components, distro=distro, pkg=pkg_manager, cfg=cfg, root=rootdir) + LOG.info("Unconfiguring %s." % (c)) + instance.unconfigure() + LOG.info("Uninstalling %s." % (c)) + instance.uninstall() + except NoTraceException, e: + if(ignore_traces_missing): + pass + else: + raise #trash the root if we can try: os.rmdir(rootdir) @@ -203,7 +213,7 @@ def resolve_dependencies(action, components): def check_root(action, rootdir): - if(action == Util.INSTALL): + if(action == INSTALL): root_there = False if(os.path.isdir(rootdir)): sublisting = os.listdir(rootdir) @@ -223,7 +233,7 @@ def prioritize_components(action, components): #get the right component order (by priority) mporder = dict() for c in components: - priority = Util.NAMES_PRIORITY.get(c) + priority = NAMES_PRIORITY.get(c) if(priority == None): priority = sys.maxint mporder[c] = priority @@ -236,34 +246,33 @@ def prioritize_components(action, components): #what functions to activate for each action ACTION_FUNC_MAP = { - Util.INSTALL: install, - Util.UNINSTALL: uninstall, - Util.START: start, - Util.STOP: stop + INSTALL: install, + UNINSTALL: uninstall, + START: start, + STOP: stop } def main(): me = __file__ args = Options.parse() - components = args.get("component") or [] + components = args.pop("component") or [] if(len(components) == 0): - #assume them all?? - components = list(Util.NAMES) + components = list(COMPONENT_NAMES) components = set([x.lower() for x in components]) - components = set(Util.NAMES).intersection(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.get("action") or "" + action = args.pop("action") or "" #normalize the action action = action.strip().lower() - if(not (action in Util.ACTIONS)): + if(not (action in ACTIONS)): LOG.error("No valid action specified!") LOG.info("Perhaps you should try %s --help" % (me)) return 1 - rootdir = args.get("dir") or "" + 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)) @@ -286,7 +295,7 @@ def main(): #now do it! funcAction = ACTION_FUNC_MAP.get(action) LOG.info("Starting action [%s] on %s for operating system/distro [%s]" % (action, rcf8222date(), install_os)) - resultList = funcAction(components, install_os, rootdir) + resultList = funcAction(components, install_os, rootdir, args) LOG.info("Finished action [%s] on %s" % (action, rcf8222date())) if(resultList): msg = "Check [%s] for traces of what happened." % (", ".join(resultList))