Large amount of renaming and cleanups to make everything much more pythonic. Yippe.

This commit is contained in:
Joshua Harlow
2012-01-20 14:12:20 -08:00
parent ca8046f5c2
commit 0b46c02ac8
39 changed files with 1025 additions and 943 deletions

View File

@@ -14,7 +14,7 @@ formatter=form01
keys=hand01 keys=hand01
[handler_hand01] [handler_hand01]
class=Logger.TermHandler class=devstack.log.TermHandler
formatter=form01 formatter=form01
args=() args=()
@@ -23,6 +23,6 @@ keys=form01
[formatter_form01] [formatter_form01]
format=%(levelname)s: @%(name)s : %(message)s format=%(levelname)s: @%(name)s : %(message)s
class=Logger.TermFormatter class=devstack.log.TermFormatter

View File

@@ -12,3 +12,4 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.

94
devstack/actions.py Normal file
View File

@@ -0,0 +1,94 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# 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.
from devstack import constants as c
from devstack.components import db
from devstack.components import glance
from devstack.components import horizon
from devstack.components import keystone
from devstack.components import keystone_client
from devstack.components import nova
from devstack.components import nova_client
from devstack.components import openstack_x
from devstack.components import quantum
from devstack.components import rabbit
from devstack.components import swift
# This determines what classes to use to install/uninstall/...
ACTION_CLASSES = {
c.INSTALL: {
c.NOVA: nova.NovaInstaller,
c.GLANCE: glance.GlanceInstaller,
c.QUANTUM: quantum.QuantumInstaller,
c.SWIFT: swift.SwiftInstaller,
c.HORIZON: horizon.HorizonInstaller,
c.KEYSTONE: keystone.KeystoneInstaller,
c.DB: db.DBInstaller,
c.RABBIT: rabbit.RabbitInstaller,
c.KEYSTONE_CLIENT: keystone_client.KeyStoneClientInstaller,
c.NOVA_CLIENT: nova_client.NovaClientInstaller,
c.OPENSTACK_X: openstack_x.OpenstackXInstaller,
},
c.UNINSTALL: {
c.NOVA: nova.NovaUninstaller,
c.GLANCE: glance.GlanceUninstaller,
c.QUANTUM: quantum.QuantumUninstaller,
c.SWIFT: swift.SwiftUninstaller,
c.HORIZON: horizon.HorizonUninstaller,
c.KEYSTONE: keystone.KeystoneUninstaller,
c.DB: db.DBUninstaller,
c.RABBIT: rabbit.RabbitUninstaller,
c.KEYSTONE_CLIENT: keystone_client.KeyStoneClientUninstaller,
c.NOVA_CLIENT: nova_client.NovaClientUninstaller,
c.OPENSTACK_X: openstack_x.OpenstackXUninstaller,
},
c.START: {
c.NOVA: nova.NovaRuntime,
c.GLANCE: glance.GlanceRuntime,
c.QUANTUM: quantum.QuantumRuntime,
c.SWIFT: swift.SwiftRuntime,
c.HORIZON: horizon.HorizonRuntime,
c.KEYSTONE: keystone.KeystoneRuntime,
c.DB: db.DBRuntime,
c.RABBIT: rabbit.RabbitRuntime,
c.KEYSTONE_CLIENT: keystone_client.KeyStoneClientRuntime,
c.NOVA_CLIENT: nova_client.NovaClientRuntime,
c.OPENSTACK_X: openstack_x.OpenstackXRuntime,
},
c.STOP: {
c.NOVA: nova.NovaRuntime,
c.GLANCE: glance.GlanceRuntime,
c.QUANTUM: quantum.QuantumRuntime,
c.SWIFT: swift.SwiftRuntime,
c.HORIZON: horizon.HorizonRuntime,
c.KEYSTONE: keystone.KeystoneRuntime,
c.DB: db.DBRuntime,
c.RABBIT: rabbit.RabbitRuntime,
c.KEYSTONE_CLIENT: keystone_client.KeyStoneClientRuntime,
c.NOVA_CLIENT: nova_client.NovaClientRuntime,
c.OPENSTACK_X: openstack_x.OpenstackXRuntime,
},
}
def get_action_cls(action_name, component_name):
action_cls_map = ACTION_CLASSES.get(action_name)
if(not action_cls_map):
return None
cls = action_cls_map.get(component_name)
return cls

View File

@@ -13,18 +13,16 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import ConfigParser
import os import os
import re import re
import ConfigParser
#TODO fix these from devstack import env
from Exceptions import (BadParamException) from devstack import exceptions as excp
from Environment import (get_environment_key) from devstack import log as logging
from devstack import shell as sh
import Logger LOG = logging.getLogger("devstack.cfg")
import Shell
LOG = Logger.getLogger("install.config")
PW_TMPL = "Enter a password for %s: " PW_TMPL = "Enter a password for %s: "
ENV_PAT = re.compile(r"^\s*\$\{([\w\d]+):\-(.*)\}\s*$") ENV_PAT = re.compile(r"^\s*\$\{([\w\d]+):\-(.*)\}\s*$")
CACHE_MSG = "(value will now be internally cached)" CACHE_MSG = "(value will now be internally cached)"
@@ -103,10 +101,10 @@ class EnvConfigParser(ConfigParser.RawConfigParser):
defv = mtch.group(2) defv = mtch.group(2)
if(len(defv) == 0 and len(key) == 0): if(len(defv) == 0 and len(key) == 0):
msg = "Invalid bash-like value \"%s\" for \"%s\"" % (v, key) msg = "Invalid bash-like value \"%s\" for \"%s\"" % (v, key)
raise BadParamException(msg) raise excp.BadParamException(msg)
if(len(key) == 0): if(len(key) == 0):
return defv return defv
v = get_environment_key(key) v = env.get_key(key)
if(v == None): if(v == None):
v = defv v = defv
return v return v
@@ -125,11 +123,11 @@ class EnvConfigParser(ConfigParser.RawConfigParser):
#dsn = "<driver>://<username>:<password>@<host>:<port>/<database>" #dsn = "<driver>://<username>:<password>@<host>:<port>/<database>"
if(not host): if(not host):
msg = "Unable to fetch a database dsn - no host found" msg = "Unable to fetch a database dsn - no host found"
raise BadParamException(msg) raise excp.BadParamException(msg)
driver = self.get("db", "type") driver = self.get("db", "type")
if(not driver): if(not driver):
msg = "Unable to fetch a database dsn - no driver type found" msg = "Unable to fetch a database dsn - no driver type found"
raise BadParamException(msg) raise excp.BadParamException(msg)
dsn = driver + "://" dsn = driver + "://"
if(user): if(user):
dsn += user dsn += user
@@ -159,7 +157,7 @@ class EnvConfigParser(ConfigParser.RawConfigParser):
pw = "" pw = ""
if(len(pw) == 0): if(len(pw) == 0):
while(len(pw) == 0): while(len(pw) == 0):
pw = Shell.password(PW_TMPL % (key)) pw = sh.password(PW_TMPL % (key))
LOG.debug("Password for \"%s\" will be \"%s\" %s" % (key, pw, CACHE_MSG)) LOG.debug("Password for \"%s\" will be \"%s\" %s" % (key, pw, CACHE_MSG))
self.pws[key] = pw self.pws[key] = pw
return pw return pw

View File

@@ -14,42 +14,28 @@
# under the License. # under the License.
import os import os
import os.path
import Downloader from devstack import constants as c
import Exceptions from devstack import downloader as down
import Logger from devstack import exceptions as excp
import Pip from devstack import log as logging
import Runner from devstack import pip
import runners.Foreground from devstack import shell as sh
import runners.Screen from devstack import trace as tr
import Shell from devstack import utils
import Trace from devstack.runners import fork
import Util from devstack.runners import screen
LOG = Logger.getLogger("install.component") LOG = logging.getLogger("devstack.component")
PY_INSTALL = ['python', 'setup.py', 'develop'] PY_INSTALL = ['python', 'setup.py', 'develop']
PY_UNINSTALL = ['python', 'setup.py', 'develop', '--uninstall'] PY_UNINSTALL = ['python', 'setup.py', 'develop', '--uninstall']
class ComponentBase():
def __init__(self, component_name, **kargs):
self.cfg = kargs.get("cfg")
self.packager = kargs.get("pkg")
self.distro = kargs.get("distro")
self.root = kargs.get("root")
self.all_components = set(kargs.get("components", []))
(self.componentroot, self.tracedir,
self.appdir, self.cfgdir) = Util.component_paths(self.root, component_name)
self.component_name = component_name
self.component_info = kargs.get('component_info')
# #
#the following are just interfaces... #the following are just interfaces...
# #
class InstallComponent(): class InstallComponent():
def __init__(self): def __init__(self):
pass pass
@@ -101,11 +87,24 @@ class RuntimeComponent():
# useful impls # useful impls
class ComponentBase():
def __init__(self, component_name, **kargs):
self.cfg = kargs.get("cfg")
self.packager = kargs.get("pkg")
self.distro = kargs.get("distro")
self.root = kargs.get("root")
self.all_components = set(kargs.get("components", []))
(self.componentroot, self.tracedir,
self.appdir, self.cfgdir) = utils.component_paths(self.root, component_name)
self.component_name = component_name
self.component_info = kargs.get('component_info')
class PkgInstallComponent(ComponentBase, InstallComponent): class PkgInstallComponent(ComponentBase, InstallComponent):
def __init__(self, component_name, *args, **kargs): def __init__(self, component_name, *args, **kargs):
ComponentBase.__init__(self, component_name, *args, **kargs) ComponentBase.__init__(self, component_name, *args, **kargs)
InstallComponent.__init__(self) InstallComponent.__init__(self)
self.tracewriter = Trace.TraceWriter(self.tracedir, Trace.IN_TRACE) self.tracewriter = tr.TraceWriter(self.tracedir, tr.IN_TRACE)
def _get_download_locations(self): def _get_download_locations(self):
return list() return list()
@@ -122,10 +121,10 @@ class PkgInstallComponent(ComponentBase, InstallComponent):
subdir = location_info.get("subdir") subdir = location_info.get("subdir")
target_loc = None target_loc = None
if(subdir and len(subdir)): if(subdir and len(subdir)):
target_loc = Shell.joinpths(base_dir, subdir) target_loc = sh.joinpths(base_dir, subdir)
else: else:
target_loc = base_dir target_loc = base_dir
dirsmade = Downloader.download(target_loc, uri, branch) dirsmade = down.download(target_loc, uri, branch)
self.tracewriter.downloaded(target_loc, uri) self.tracewriter.downloaded(target_loc, uri)
self.tracewriter.dir_made(*dirsmade) self.tracewriter.dir_made(*dirsmade)
am_downloaded += 1 am_downloaded += 1
@@ -135,10 +134,10 @@ class PkgInstallComponent(ComponentBase, InstallComponent):
return None return None
def install(self): def install(self):
pkgs = Util.get_pkg_list(self.distro, self.component_name) pkgs = utils.get_pkg_list(self.distro, self.component_name)
if(len(pkgs)): if(len(pkgs)):
pkgnames = sorted(pkgs.keys()) pkgnames = sorted(pkgs.keys())
LOG.info("Installing packages %s" % (", ".join(pkgnames))) LOG.info("Installing packages (%s)." % (", ".join(pkgnames)))
self.packager.install_batch(pkgs) self.packager.install_batch(pkgs)
#add trace used to remove the pkgs #add trace used to remove the pkgs
for name in pkgnames: for name in pkgnames:
@@ -146,14 +145,14 @@ class PkgInstallComponent(ComponentBase, InstallComponent):
return self.tracedir return self.tracedir
def pre_install(self): def pre_install(self):
pkgs = Util.get_pkg_list(self.distro, self.component_name) pkgs = utils.get_pkg_list(self.distro, self.component_name)
if(len(pkgs)): if(len(pkgs)):
mp = self._get_param_map(None) mp = self._get_param_map(None)
self.packager.pre_install(pkgs, mp) self.packager.pre_install(pkgs, mp)
return self.tracedir return self.tracedir
def post_install(self): def post_install(self):
pkgs = Util.get_pkg_list(self.distro, self.component_name) pkgs = utils.get_pkg_list(self.distro, self.component_name)
if(len(pkgs)): if(len(pkgs)):
mp = self._get_param_map(None) mp = self._get_param_map(None)
self.packager.post_install(pkgs, mp) self.packager.post_install(pkgs, mp)
@@ -166,13 +165,13 @@ class PkgInstallComponent(ComponentBase, InstallComponent):
return contents return contents
def _get_target_config_name(self, name): def _get_target_config_name(self, name):
return Shell.joinpths(self.cfgdir, name) return sh.joinpths(self.cfgdir, name)
def _get_source_config_name(self, name): def _get_source_config_name(self, name):
return Shell.joinpths(Util.STACK_CONFIG_DIR, self.component_name, name) return sh.joinpths(c.STACK_CONFIG_DIR, self.component_name, name)
def configure(self): def configure(self):
dirsmade = Shell.mkdirslist(self.cfgdir) dirsmade = sh.mkdirslist(self.cfgdir)
self.tracewriter.dir_made(*dirsmade) self.tracewriter.dir_made(*dirsmade)
configs = self._get_config_files() configs = self._get_config_files()
if(len(configs)): if(len(configs)):
@@ -183,19 +182,19 @@ class PkgInstallComponent(ComponentBase, InstallComponent):
sourcefn = self._get_source_config_name(fn) sourcefn = self._get_source_config_name(fn)
tgtfn = self._get_target_config_name(fn) tgtfn = self._get_target_config_name(fn)
#ensure directory is there (if not created previously) #ensure directory is there (if not created previously)
dirsmade = Shell.mkdirslist(os.path.dirname(tgtfn)) dirsmade = sh.mkdirslist(sh.dirname(tgtfn))
self.tracewriter.dir_made(*dirsmade) self.tracewriter.dir_made(*dirsmade)
#now configure it #now configure it
LOG.info("Configuring template file %s" % (sourcefn)) LOG.info("Configuring template file %s" % (sourcefn))
contents = Shell.load_file(sourcefn) contents = sh.load_file(sourcefn)
LOG.info("Replacing parameters in file %s" % (sourcefn)) LOG.info("Replacing parameters in file %s" % (sourcefn))
LOG.debug("Replacements = %s" % (parameters)) LOG.debug("Replacements = %s" % (parameters))
contents = Util.param_replace(contents, parameters) contents = utils.param_replace(contents, parameters)
LOG.debug("Applying side-effects of param replacement for template %s" % (sourcefn)) LOG.debug("Applying side-effects of param replacement for template %s" % (sourcefn))
contents = self._config_adjust(contents, fn) contents = self._config_adjust(contents, fn)
LOG.info("Writing configuration file %s" % (tgtfn)) LOG.info("Writing configuration file %s" % (tgtfn))
#this trace is used to remove the files configured #this trace is used to remove the files configured
Shell.write_file(tgtfn, contents) sh.write_file(tgtfn, contents)
self.tracewriter.cfg_write(tgtfn) self.tracewriter.cfg_write(tgtfn)
return len(configs) return len(configs)
@@ -214,10 +213,10 @@ class PythonInstallComponent(PkgInstallComponent):
def _install_pips(self): def _install_pips(self):
#install any need pip items #install any need pip items
pips = Util.get_pip_list(self.distro, self.component_name) pips = utils.get_pip_list(self.distro, self.component_name)
if(len(pips)): if(len(pips)):
LOG.info("Setting up %s pips" % (len(pips))) LOG.info("Setting up %s pips" % (len(pips)))
Pip.install(pips) pip.install(pips)
for name in pips.keys(): for name in pips.keys():
self.tracewriter.pip_install(name, pips.get(name)) self.tracewriter.pip_install(name, pips.get(name))
@@ -233,14 +232,14 @@ class PythonInstallComponent(PkgInstallComponent):
return combined_output return combined_output
def _format_trace_name(self, name): def _format_trace_name(self, name):
return "%s-%s" % (Trace.PY_TRACE, name) return "%s-%s" % (tr.PY_TRACE, name)
def _install_python_setups(self): def _install_python_setups(self):
#setup any python directories #setup any python directories
pydirs = self._get_python_directories() pydirs = self._get_python_directories()
if(len(pydirs)): if(len(pydirs)):
LOG.info("Setting up %s python directories" % (len(pydirs))) LOG.info("Setting up %s python directories" % (len(pydirs)))
dirsmade = Shell.mkdirslist(self.tracedir) dirsmade = sh.mkdirslist(self.tracedir)
self.tracewriter.dir_made(*dirsmade) self.tracewriter.dir_made(*dirsmade)
for pydir_info in pydirs: for pydir_info in pydirs:
name = pydir_info.get("name") name = pydir_info.get("name")
@@ -248,10 +247,10 @@ class PythonInstallComponent(PkgInstallComponent):
#TODO should we raise an exception here? #TODO should we raise an exception here?
continue continue
working_dir = pydir_info.get('work_dir', self.appdir) working_dir = pydir_info.get('work_dir', self.appdir)
record_fn = Trace.touch_trace(self.tracedir, self._format_trace_name(name)) record_fn = tr.touch_trace(self.tracedir, self._format_trace_name(name))
self.tracewriter.file_touched(record_fn) self.tracewriter.file_touched(record_fn)
(stdout, stderr) = Shell.execute(*PY_INSTALL, cwd=working_dir, run_as_root=True) (stdout, stderr) = sh.execute(*PY_INSTALL, cwd=working_dir, run_as_root=True)
Shell.write_file(record_fn, self._format_stderr_out(stderr, stdout)) sh.write_file(record_fn, self._format_stderr_out(stderr, stdout))
self.tracewriter.py_install(name, record_fn, working_dir) self.tracewriter.py_install(name, record_fn, working_dir)
def _python_install(self): def _python_install(self):
@@ -268,7 +267,7 @@ class PkgUninstallComponent(ComponentBase, UninstallComponent):
def __init__(self, component_name, *args, **kargs): def __init__(self, component_name, *args, **kargs):
ComponentBase.__init__(self, component_name, *args, **kargs) ComponentBase.__init__(self, component_name, *args, **kargs)
UninstallComponent.__init__(self) UninstallComponent.__init__(self)
self.tracereader = Trace.TraceReader(self.tracedir, Trace.IN_TRACE) self.tracereader = tr.TraceReader(self.tracedir, tr.IN_TRACE)
def unconfigure(self): def unconfigure(self):
self._unconfigure_files() self._unconfigure_files()
@@ -279,7 +278,7 @@ class PkgUninstallComponent(ComponentBase, UninstallComponent):
LOG.info("Removing %s configuration files" % (len(cfgfiles))) LOG.info("Removing %s configuration files" % (len(cfgfiles)))
for fn in cfgfiles: for fn in cfgfiles:
if(len(fn)): if(len(fn)):
Shell.unlink(fn) sh.unlink(fn)
def uninstall(self): def uninstall(self):
self._uninstall_pkgs() self._uninstall_pkgs()
@@ -298,14 +297,14 @@ class PkgUninstallComponent(ComponentBase, UninstallComponent):
LOG.info("Removing %s touched files" % (len(filestouched))) LOG.info("Removing %s touched files" % (len(filestouched)))
for fn in filestouched: for fn in filestouched:
if(len(fn)): if(len(fn)):
Shell.unlink(fn) sh.unlink(fn)
def _uninstall_dirs(self): def _uninstall_dirs(self):
dirsmade = self.tracereader.dirs_made() dirsmade = self.tracereader.dirs_made()
if(len(dirsmade)): if(len(dirsmade)):
LOG.info("Removing %s created directories" % (len(dirsmade))) LOG.info("Removing %s created directories" % (len(dirsmade)))
for dirname in dirsmade: for dirname in dirsmade:
Shell.deldir(dirname) sh.deldir(dirname)
class PythonUninstallComponent(PkgUninstallComponent): class PythonUninstallComponent(PkgUninstallComponent):
@@ -323,7 +322,7 @@ class PythonUninstallComponent(PkgUninstallComponent):
pips = self.tracereader.pips_installed() pips = self.tracereader.pips_installed()
if(len(pips)): if(len(pips)):
LOG.info("Uninstalling %s pips" % (len(pips))) LOG.info("Uninstalling %s pips" % (len(pips)))
Pip.uninstall(pips) pip.uninstall(pips)
def _uninstall_python(self): def _uninstall_python(self):
pylisting = self.tracereader.py_listing() pylisting = self.tracereader.py_listing()
@@ -331,28 +330,28 @@ class PythonUninstallComponent(PkgUninstallComponent):
LOG.info("Uninstalling %s python setups" % (len(pylisting))) LOG.info("Uninstalling %s python setups" % (len(pylisting)))
for entry in pylisting: for entry in pylisting:
where = entry.get('where') where = entry.get('where')
Shell.execute(*PY_UNINSTALL, cwd=where, run_as_root=True) sh.execute(*PY_UNINSTALL, cwd=where, run_as_root=True)
class ProgramRuntime(ComponentBase, RuntimeComponent): class ProgramRuntime(ComponentBase, RuntimeComponent):
#this here determines how we start and stop and #this here determines how we start and stop and
#what classes handle different running/stopping types #what classes handle different running/stopping types
STARTER_CLS_MAPPING = { STARTER_CLS_MAPPING = {
runners.Foreground.RUN_TYPE: runners.Foreground.ForegroundRunner, fork.RUN_TYPE: fork.ForkRunner,
runners.Screen.RUN_TYPE: runners.Screen.ScreenRunner, screen.RUN_TYPE: screen.ScreenRunner,
} }
STOPPER_CLS_MAPPING = { STOPPER_CLS_MAPPING = {
runners.Foreground.RUN_TYPE: runners.Foreground.ForegroundRunner, fork.RUN_TYPE: fork.ForkRunner,
runners.Screen.RUN_TYPE: runners.Screen.ScreenRunner, screen.RUN_TYPE: screen.ScreenRunner,
} }
def __init__(self, component_name, *args, **kargs): def __init__(self, component_name, *args, **kargs):
ComponentBase.__init__(self, component_name, *args, **kargs) ComponentBase.__init__(self, component_name, *args, **kargs)
RuntimeComponent.__init__(self) RuntimeComponent.__init__(self)
self.run_type = kargs.get("run_type", runners.Foreground.RUN_TYPE) self.run_type = kargs.get("run_type", fork.RUN_TYPE)
self.tracereader = Trace.TraceReader(self.tracedir, Trace.IN_TRACE) self.tracereader = tr.TraceReader(self.tracedir, tr.IN_TRACE)
self.tracewriter = Trace.TraceWriter(self.tracedir, Trace.START_TRACE) self.tracewriter = tr.TraceWriter(self.tracedir, tr.START_TRACE)
self.starttracereader = Trace.TraceReader(self.tracedir, Trace.START_TRACE) self.starttracereader = tr.TraceReader(self.tracedir, tr.START_TRACE)
self.check_installed_pkgs = kargs.get("check_installed_pkgs", True) self.check_installed_pkgs = kargs.get("check_installed_pkgs", True)
def _getstartercls(self, start_mode): def _getstartercls(self, start_mode):
@@ -387,7 +386,7 @@ class ProgramRuntime(ComponentBase, RuntimeComponent):
#ensure it was installed #ensure it was installed
if(not self._was_installed()): if(not self._was_installed()):
msg = "Can not start %s since it was not installed" % (self.component_name) msg = "Can not start %s since it was not installed" % (self.component_name)
raise Exceptions.StartException(msg) raise excp.StartException(msg)
#select how we are going to start it #select how we are going to start it
startercls = self._getstartercls(self.run_type) startercls = self._getstartercls(self.run_type)
starter = startercls() starter = startercls()
@@ -406,7 +405,7 @@ class ProgramRuntime(ComponentBase, RuntimeComponent):
if(params and program_opts): if(params and program_opts):
adjusted_opts = list() adjusted_opts = list()
for opt in program_opts: for opt in program_opts:
adjusted_opts.append(Util.param_replace(opt, params)) adjusted_opts.append(utils.param_replace(opt, params))
program_opts = adjusted_opts program_opts = adjusted_opts
LOG.info("Starting [%s] with options [%s]" % (app_name, ", ".join(program_opts))) LOG.info("Starting [%s] with options [%s]" % (app_name, ", ".join(program_opts)))
#start it with the given settings #start it with the given settings
@@ -425,7 +424,7 @@ class ProgramRuntime(ComponentBase, RuntimeComponent):
#ensure it was installed #ensure it was installed
if(not self._was_installed()): if(not self._was_installed()):
msg = "Can not stop %s since it was not installed" % (self.component_name) msg = "Can not stop %s since it was not installed" % (self.component_name)
raise Exceptions.StopException(msg) raise excp.StopException(msg)
#we can only stop what has a started trace #we can only stop what has a started trace
start_traces = self.starttracereader.apps_started() start_traces = self.starttracereader.apps_started()
killedam = 0 killedam = 0
@@ -437,7 +436,7 @@ class ProgramRuntime(ComponentBase, RuntimeComponent):
if(fn == None or name == None): if(fn == None or name == None):
continue continue
#figure out which class will stop it #figure out which class will stop it
contents = Trace.parse_fn(fn) contents = tr.parse_fn(fn)
killcls = None killcls = None
for (cmd, action) in contents: for (cmd, action) in contents:
if(cmd == Runner.RUN_TYPE): if(cmd == Runner.RUN_TYPE):
@@ -455,7 +454,7 @@ class ProgramRuntime(ComponentBase, RuntimeComponent):
if(killedam == len(start_traces)): if(killedam == len(start_traces)):
fn = self.starttracereader.trace_fn fn = self.starttracereader.trace_fn
LOG.info("Deleting trace file %s" % (fn)) LOG.info("Deleting trace file %s" % (fn))
Shell.unlink(fn) sh.unlink(fn)
return killedam return killedam
def status(self): def status(self):

View File

@@ -0,0 +1,14 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# 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.

View File

@@ -15,23 +15,17 @@
import re import re
import Logger from devstack import component as comp
import Packager from devstack import constants
from devstack import exceptions as excp
from devstack import log as logging
from devstack import shell as sh
from devstack import trace as tr
from devstack import utils
#TODO fix these
from Component import (PkgUninstallComponent, PkgInstallComponent,
ComponentBase, RuntimeComponent)
from Util import (DB,
get_host_ip,
execute_template)
from Exceptions import (StartException, StopException,
StatusException, RestartException)
from Shell import (execute)
from Trace import (TraceReader,
IN_TRACE)
LOG = Logger.getLogger("install.db") LOG = logging.getLogger("devstack.components.db")
TYPE = DB TYPE = constants.DB
MYSQL = 'mysql' MYSQL = 'mysql'
DB_ACTIONS = { DB_ACTIONS = {
MYSQL: { MYSQL: {
@@ -57,14 +51,14 @@ DB_ACTIONS = {
BASE_ERROR = 'Currently we do not know how to %s for database type [%s]' BASE_ERROR = 'Currently we do not know how to %s for database type [%s]'
class DBUninstaller(PkgUninstallComponent): class DBUninstaller(comp.PkgUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PkgUninstallComponent.__init__(self, TYPE, *args, **kargs) comp.PkgUninstallComponent.__init__(self, TYPE, *args, **kargs)
class DBInstaller(PkgInstallComponent): class DBInstaller(comp.PkgInstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PkgInstallComponent.__init__(self, TYPE, *args, **kargs) comp.PkgInstallComponent.__init__(self, TYPE, *args, **kargs)
self.runtime = DBRuntime(*args, **kargs) self.runtime = DBRuntime(*args, **kargs)
def _get_param_map(self, config_fn): def _get_param_map(self, config_fn):
@@ -74,13 +68,13 @@ class DBInstaller(PkgInstallComponent):
out['PASSWORD'] = self.cfg.getpw("passwords", "sql") out['PASSWORD'] = self.cfg.getpw("passwords", "sql")
out['BOOT_START'] = str(True).lower() out['BOOT_START'] = str(True).lower()
out['USER'] = self.cfg.get("db", "sql_user") out['USER'] = self.cfg.get("db", "sql_user")
hostip = get_host_ip(self.cfg) hostip = utils.get_host_ip(self.cfg)
out['SERVICE_HOST'] = hostip out['SERVICE_HOST'] = hostip
out['HOST_IP'] = hostip out['HOST_IP'] = hostip
return out return out
def post_install(self): def post_install(self):
parent_result = PkgInstallComponent.post_install(self) parent_result = comp.PkgInstallComponent.post_install(self)
#extra actions to ensure we are granted access #extra actions to ensure we are granted access
dbtype = self.cfg.get("db", "type") dbtype = self.cfg.get("db", "type")
dbactions = DB_ACTIONS.get(dbtype) dbactions = DB_ACTIONS.get(dbtype)
@@ -95,21 +89,21 @@ class DBInstaller(PkgInstallComponent):
}) })
#shell seems to be needed here #shell seems to be needed here
#since python escapes this to much... #since python escapes this to much...
execute_template(*cmds, params=params, shell=True) utils.execute_template(*cmds, params=params, shell=True)
#special mysql actions #special mysql actions
if(dbactions and dbtype == MYSQL): if(dbactions and dbtype == MYSQL):
cmd = dbactions.get('host_adjust') cmd = dbactions.get('host_adjust')
if(cmd): if(cmd):
execute(*cmd, run_as_root=True, shell=True) sh.execute(*cmd, run_as_root=True, shell=True)
#restart it to make sure all good #restart it to make sure all good
self.runtime.restart() self.runtime.restart()
return parent_result return parent_result
class DBRuntime(ComponentBase, RuntimeComponent): class DBRuntime(comp.ComponentBase, comp.RuntimeComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
ComponentBase.__init__(self, TYPE, *args, **kargs) comp.ComponentBase.__init__(self, TYPE, *args, **kargs)
self.tracereader = TraceReader(self.tracedir, IN_TRACE) self.tracereader = tr.TraceReader(self.tracedir, tr.IN_TRACE)
def _gettypeactions(self, act, exception_cls): def _gettypeactions(self, act, exception_cls):
pkgsinstalled = self.tracereader.packages_installed() pkgsinstalled = self.tracereader.packages_installed()
@@ -126,25 +120,25 @@ class DBRuntime(ComponentBase, RuntimeComponent):
def start(self): def start(self):
if(self.status().find('start') == -1): if(self.status().find('start') == -1):
startcmd = self._gettypeactions('start', StartException) startcmd = self._gettypeactions('start', excp.StartException)
execute(*startcmd, run_as_root=True) sh.execute(*startcmd, run_as_root=True)
return None return None
def stop(self): def stop(self):
if(self.status().find('stop') == -1): if(self.status().find('stop') == -1):
stopcmd = self._gettypeactions('stop', StopException) stopcmd = self._gettypeactions('stop', excp.StopException)
execute(*stopcmd, run_as_root=True) sh.execute(*stopcmd, run_as_root=True)
return 1 return 1
return 0 return 0
def restart(self): def restart(self):
restartcmd = self._gettypeactions('restart', RestartException) restartcmd = self._gettypeactions('restart', excp.RestartException)
execute(*restartcmd, run_as_root=True) sh.execute(*restartcmd, run_as_root=True)
return 1 return 1
def status(self): def status(self):
statuscmd = self._gettypeactions('status', StatusException) statuscmd = self._gettypeactions('status', excp.StatusException)
(sysout, stderr) = execute(*statuscmd, run_as_root=True) (sysout, stderr) = sh.execute(*statuscmd, run_as_root=True)
return sysout.strip() return sysout.strip()
@@ -162,7 +156,7 @@ def drop_db(cfg, dbname):
'cmd': dropcmd, 'cmd': dropcmd,
'run_as_root': False, 'run_as_root': False,
}) })
execute_template(*cmds, params=params) utils.execute_template(*cmds, params=params)
else: else:
msg = BASE_ERROR % ('drop', dbtype) msg = BASE_ERROR % ('drop', dbtype)
raise NotImplementedError(msg) raise NotImplementedError(msg)
@@ -182,7 +176,7 @@ def create_db(cfg, dbname):
'cmd': createcmd, 'cmd': createcmd,
'run_as_root': False, 'run_as_root': False,
}) })
execute_template(*cmds, params=params) utils.execute_template(*cmds, params=params)
else: else:
msg = BASE_ERROR % ('create', dbtype) msg = BASE_ERROR % ('create', dbtype)
raise NotImplementedError(msg) raise NotImplementedError(msg)

View File

@@ -13,27 +13,23 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import io
import json import json
import os.path import os.path
import io
import Config from devstack import cfg
import Logger from devstack import component as comp
import Db from devstack import constants
from devstack import exceptions as excp
from devstack import log as logging
from devstack import shell as sh
from devstack import utils
from devstack.components import db
#TODO fix these LOG = logging.getLogger("devstack.components.glance")
from Component import (PythonUninstallComponent,
PythonInstallComponent,
PythonRuntime)
from Util import (GLANCE,
get_host_ip, param_replace)
from Shell import (deldir, mkdirslist, unlink,
joinpths, touch_file)
LOG = Logger.getLogger("install.glance")
#naming + config files #naming + config files
TYPE = GLANCE TYPE = constants.GLANCE
API_CONF = "glance-api.conf" API_CONF = "glance-api.conf"
REG_CONF = "glance-registry.conf" REG_CONF = "glance-registry.conf"
CONFIGS = [API_CONF, REG_CONF] CONFIGS = [API_CONF, REG_CONF]
@@ -42,30 +38,30 @@ CFG_SECTION = 'DEFAULT'
#what to start #what to start
APP_OPTIONS = { APP_OPTIONS = {
'glance-api': ['--config-file', joinpths('%ROOT%', "etc", API_CONF)], 'glance-api': ['--config-file', sh.joinpths('%ROOT%', "etc", API_CONF)],
'glance-registry': ['--config-file', joinpths('%ROOT%', "etc", REG_CONF)] 'glance-registry': ['--config-file', sh.joinpths('%ROOT%', "etc", REG_CONF)]
} }
CONFIG_ACTUAL_DIR = 'etc' CONFIG_ACTUAL_DIR = 'etc'
BIN_DIR = 'bin' BIN_DIR = 'bin'
class GlanceUninstaller(PythonUninstallComponent): class GlanceUninstaller(comp.PythonUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonUninstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR) self.cfgdir = sh.joinpths(self.appdir, CONFIG_ACTUAL_DIR)
class GlanceRuntime(PythonRuntime): class GlanceRuntime(comp.PythonRuntime):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonRuntime.__init__(self, TYPE, *args, **kargs) comp.PythonRuntime.__init__(self, TYPE, *args, **kargs)
self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR) self.cfgdir = sh.joinpths(self.appdir, CONFIG_ACTUAL_DIR)
def _get_apps_to_start(self): def _get_apps_to_start(self):
apps = list() apps = list()
for app_name in APP_OPTIONS.keys(): for app_name in APP_OPTIONS.keys():
apps.append({ apps.append({
'name': app_name, 'name': app_name,
'path': joinpths(self.appdir, BIN_DIR, app_name), 'path': sh.joinpths(self.appdir, BIN_DIR, app_name),
}) })
return apps return apps
@@ -73,15 +69,15 @@ class GlanceRuntime(PythonRuntime):
return APP_OPTIONS.get(app) return APP_OPTIONS.get(app)
class GlanceInstaller(PythonInstallComponent): class GlanceInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonInstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.git_loc = self.cfg.get("git", "glance_repo") self.git_loc = self.cfg.get("git", "glance_repo")
self.git_branch = self.cfg.get("git", "glance_branch") self.git_branch = self.cfg.get("git", "glance_branch")
self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR) self.cfgdir = sh.joinpths(self.appdir, CONFIG_ACTUAL_DIR)
def _get_download_locations(self): def _get_download_locations(self):
places = PythonInstallComponent._get_download_locations(self) places = comp.PythonInstallComponent._get_download_locations(self)
places.append({ places.append({
'uri': self.git_loc, 'uri': self.git_loc,
'branch': self.git_branch, 'branch': self.git_branch,
@@ -93,13 +89,13 @@ class GlanceInstaller(PythonInstallComponent):
return list(CONFIGS) return list(CONFIGS)
def post_install(self): def post_install(self):
parent_result = PythonInstallComponent.post_install(self) parent_result = comp.PythonInstallComponent.post_install(self)
self._setup_db() self._setup_db()
return parent_result return parent_result
def _setup_db(self): def _setup_db(self):
Db.drop_db(self.cfg, DB_NAME) db.drop_db(self.cfg, DB_NAME)
Db.create_db(self.cfg, DB_NAME) db.create_db(self.cfg, DB_NAME)
def _config_adjust(self, contents, name): def _config_adjust(self, contents, name):
if(name not in CONFIGS): if(name not in CONFIGS):
@@ -108,7 +104,7 @@ class GlanceInstaller(PythonInstallComponent):
#then extract known configs that #then extract known configs that
#will need locations/directories/files made (or touched)... #will need locations/directories/files made (or touched)...
with io.BytesIO(contents) as stream: with io.BytesIO(contents) as stream:
config = Config.IgnoreMissingConfigParser() config = cfg.IgnoreMissingConfigParser()
config.readfp(stream) config.readfp(stream)
if(config.getboolean('image_cache_enabled', CFG_SECTION)): if(config.getboolean('image_cache_enabled', CFG_SECTION)):
cache_dir = config.get("image_cache_datadir", CFG_SECTION) cache_dir = config.get("image_cache_datadir", CFG_SECTION)
@@ -163,7 +159,7 @@ class GlanceInstaller(PythonInstallComponent):
mp['SYSLOG'] = self.cfg.getboolean("default", "syslog") mp['SYSLOG'] = self.cfg.getboolean("default", "syslog")
mp['SERVICE_TOKEN'] = self.cfg.getpw("passwords", "service_token") mp['SERVICE_TOKEN'] = self.cfg.getpw("passwords", "service_token")
mp['SQL_CONN'] = self.cfg.get_dbdsn(DB_NAME) mp['SQL_CONN'] = self.cfg.get_dbdsn(DB_NAME)
hostip = get_host_ip(self.cfg) hostip = utils.get_host_ip(self.cfg)
mp['SERVICE_HOST'] = hostip mp['SERVICE_HOST'] = hostip
mp['HOST_IP'] = hostip mp['HOST_IP'] = hostip
return mp return mp

View File

@@ -14,17 +14,13 @@
# under the License. # under the License.
import Logger from devstack import component as comp
import Util from devstack import constants
import Shell from devstack import log as logging
from devstack import shell as sh
from devstack import utils
#TODO fix these TYPE = constants.HORIZON
from Component import (PythonUninstallComponent,
PythonInstallComponent,
NullRuntime)
LOG = Logger.getLogger("install.horizon")
TYPE = Util.HORIZON
ROOT_HORIZON = 'horizon' ROOT_HORIZON = 'horizon'
HORIZON_NAME = 'horizon' HORIZON_NAME = 'horizon'
@@ -35,22 +31,24 @@ HORIZON_PY_CONF = "horizon_settings.py"
HORIZON_PY_CONF_TGT = ['local', 'local_settings.py'] HORIZON_PY_CONF_TGT = ['local', 'local_settings.py']
CONFIGS = [HORIZON_PY_CONF] CONFIGS = [HORIZON_PY_CONF]
LOG = logging.getLogger("devstack.components.horizon")
class HorizonUninstaller(PythonUninstallComponent):
class HorizonUninstaller(comp.PythonUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonUninstallComponent.__init__(self, TYPE, *args, **kargs) PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
class HorizonInstaller(PythonInstallComponent): class HorizonInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonInstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.git_loc = self.cfg.get("git", "horizon_repo") self.git_loc = self.cfg.get("git", "horizon_repo")
self.git_branch = self.cfg.get("git", "horizon_branch") self.git_branch = self.cfg.get("git", "horizon_branch")
self.horizon_dir = Shell.joinpths(self.appdir, ROOT_HORIZON) self.horizon_dir = sh.joinpths(self.appdir, ROOT_HORIZON)
self.dash_dir = Shell.joinpths(self.appdir, ROOT_DASH) self.dash_dir = sh.joinpths(self.appdir, ROOT_DASH)
def _get_download_locations(self): def _get_download_locations(self):
places = PythonInstallComponent._get_download_locations(self) places = comp.PythonInstallComponent._get_download_locations(self)
places.append({ places.append({
'uri': self.git_loc, 'uri': self.git_loc,
'branch': self.git_branch, 'branch': self.git_branch,
@@ -59,9 +57,9 @@ class HorizonInstaller(PythonInstallComponent):
def _get_target_config_name(self, config_name): def _get_target_config_name(self, config_name):
if(config_name == HORIZON_PY_CONF): if(config_name == HORIZON_PY_CONF):
return Shell.joinpths(self.dash_dir, *HORIZON_PY_CONF_TGT) return sh.joinpths(self.dash_dir, *HORIZON_PY_CONF_TGT)
else: else:
return PythonInstallComponent._get_target_config_name(self, config_name) return comp.PythonInstallComponent._get_target_config_name(self, config_name)
def _get_python_directories(self): def _get_python_directories(self):
py_dirs = list() py_dirs = list()
@@ -83,10 +81,10 @@ class HorizonInstaller(PythonInstallComponent):
#this dict will be used to fill in the configuration #this dict will be used to fill in the configuration
#params with actual values #params with actual values
mp = dict() mp = dict()
mp['OPENSTACK_HOST'] = Util.get_host_ip(self.cfg) mp['OPENSTACK_HOST'] = utils.get_host_ip(self.cfg)
return mp return mp
class HorizonRuntime(NullRuntime): class HorizonRuntime(comp.NullRuntime):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
NullRuntime.__init__(self, TYPE, *args, **kargs) comp.NullRuntime.__init__(self, TYPE, *args, **kargs)

View File

@@ -13,58 +13,51 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import io
import os import os
import os.path import os.path
import io
import Pip from devstack import cfg
import Logger from devstack import component as comp
import Db from devstack import constants
import Config from devstack import log as logging
from devstack import shell as sh
from devstack import utils
from devstack.components import db
#TODO fix these LOG = logging.getLogger("devstack.components.keystone")
from Util import (KEYSTONE,
CONFIG_DIR,
NOVA, GLANCE, SWIFT,
get_host_ip,
execute_template,
param_replace)
from Component import (PythonUninstallComponent,
PythonInstallComponent, PythonRuntime)
from Shell import (mkdirslist, unlink, touch_file, joinpths)
LOG = Logger.getLogger("install.keystone") TYPE = constants.KEYSTONE
TYPE = KEYSTONE
ROOT_CONF = "keystone.conf" ROOT_CONF = "keystone.conf"
CONFIGS = [ROOT_CONF] CONFIGS = [ROOT_CONF]
BIN_DIR = "bin" BIN_DIR = "bin"
CONFIG_DIR = "config"
DB_NAME = "keystone" DB_NAME = "keystone"
CFG_SECTION = 'DEFAULT' CFG_SECTION = 'DEFAULT'
#what to start #what to start
APP_OPTIONS = { APP_OPTIONS = {
'keystone': ['--config-file', joinpths('%ROOT%', "config", ROOT_CONF), "--verbose"], 'keystone': ['--config-file', sh.joinpths('%ROOT%', "config", ROOT_CONF), "--verbose"],
} }
class KeystoneUninstaller(PythonUninstallComponent): class KeystoneUninstaller(comp.PythonUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonUninstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
self.cfgdir = joinpths(self.appdir, CONFIG_DIR) self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = joinpths(self.appdir, BIN_DIR) self.bindir = sh.joinpths(self.appdir, BIN_DIR)
class KeystoneInstaller(PythonInstallComponent): class KeystoneInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonInstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.git_loc = self.cfg.get("git", "keystone_repo") self.git_loc = self.cfg.get("git", "keystone_repo")
self.git_branch = self.cfg.get("git", "keystone_branch") self.git_branch = self.cfg.get("git", "keystone_branch")
self.cfgdir = joinpths(self.appdir, CONFIG_DIR) self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = joinpths(self.appdir, BIN_DIR) self.bindir = sh.joinpths(self.appdir, BIN_DIR)
def _get_download_locations(self): def _get_download_locations(self):
places = PythonInstallComponent._get_download_locations(self) places = comp.PythonInstallComponent._get_download_locations(self)
places.append({ places.append({
'uri': self.git_loc, 'uri': self.git_loc,
'branch': self.git_branch, 'branch': self.git_branch,
@@ -72,7 +65,7 @@ class KeystoneInstaller(PythonInstallComponent):
return places return places
def post_install(self): def post_install(self):
parent_result = PythonInstallComponent.post_install(self) parent_result = comp.PythonInstallComponent.post_install(self)
self._setup_db() self._setup_db()
self._setup_data() self._setup_data()
return parent_result return parent_result
@@ -81,13 +74,13 @@ class KeystoneInstaller(PythonInstallComponent):
return list(CONFIGS) return list(CONFIGS)
def _setup_db(self): def _setup_db(self):
Db.drop_db(self.cfg, DB_NAME) db.drop_db(self.cfg, DB_NAME)
Db.create_db(self.cfg, DB_NAME) db.create_db(self.cfg, DB_NAME)
def _setup_data(self): def _setup_data(self):
params = self._get_param_map(None) params = self._get_param_map(None)
cmds = _keystone_setup_cmds(self.all_components) cmds = _keystone_setup_cmds(self.all_components)
execute_template(*cmds, params=params, ignore_missing=True) utils.execute_template(*cmds, params=params, ignore_missing=True)
def _config_adjust(self, contents, name): def _config_adjust(self, contents, name):
if(name not in CONFIGS): if(name not in CONFIGS):
@@ -96,7 +89,7 @@ class KeystoneInstaller(PythonInstallComponent):
#then extract known configs that #then extract known configs that
#will need locations/directories/files made (or touched)... #will need locations/directories/files made (or touched)...
with io.BytesIO(contents) as stream: with io.BytesIO(contents) as stream:
config = Config.IgnoreMissingConfigParser() config = cfg.IgnoreMissingConfigParser()
config.readfp(stream) config.readfp(stream)
log_filename = config.get('log_file', CFG_SECTION) log_filename = config.get('log_file', CFG_SECTION)
if(log_filename): if(log_filename):
@@ -104,12 +97,12 @@ class KeystoneInstaller(PythonInstallComponent):
log_dir = os.path.dirname(log_filename) log_dir = os.path.dirname(log_filename)
if(log_dir): if(log_dir):
LOG.info("Ensuring log directory %s exists" % (log_dir)) LOG.info("Ensuring log directory %s exists" % (log_dir))
dirsmade = mkdirslist(log_dir) dirsmade = sh.mkdirslist(log_dir)
#this trace is used to remove the dirs created #this trace is used to remove the dirs created
self.tracewriter.dir_made(*dirsmade) self.tracewriter.dir_made(*dirsmade)
#destroy then recreate it (the log file) #destroy then recreate it (the log file)
unlink(log_filename) sh.unlink(log_filename)
touch_file(log_filename) sh.touch_file(log_filename)
self.tracewriter.file_touched(log_filename) self.tracewriter.file_touched(log_filename)
#we might need to handle more in the future... #we might need to handle more in the future...
#nothing modified so just return the original #nothing modified so just return the original
@@ -122,25 +115,25 @@ class KeystoneInstaller(PythonInstallComponent):
mp['DEST'] = self.appdir mp['DEST'] = self.appdir
mp['SQL_CONN'] = self.cfg.get_dbdsn(DB_NAME) mp['SQL_CONN'] = self.cfg.get_dbdsn(DB_NAME)
mp['ADMIN_PASSWORD'] = self.cfg.getpw('passwords', 'horizon_keystone_admin') mp['ADMIN_PASSWORD'] = self.cfg.getpw('passwords', 'horizon_keystone_admin')
mp['HOST_IP'] = get_host_ip(self.cfg) mp['HOST_IP'] = utils.get_host_ip(self.cfg)
mp['SERVICE_TOKEN'] = self.cfg.getpw("passwords", "service_token") mp['SERVICE_TOKEN'] = self.cfg.getpw("passwords", "service_token")
mp['BIN_DIR'] = self.bindir mp['BIN_DIR'] = self.bindir
mp['CONFIG_FILE'] = joinpths(self.cfgdir, ROOT_CONF) mp['CONFIG_FILE'] = sh.joinpths(self.cfgdir, ROOT_CONF)
return mp return mp
class KeystoneRuntime(PythonRuntime): class KeystoneRuntime(comp.PythonRuntime):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonRuntime.__init__(self, TYPE, *args, **kargs) comp.PythonRuntime.__init__(self, TYPE, *args, **kargs)
self.cfgdir = joinpths(self.appdir, CONFIG_DIR) self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = joinpths(self.appdir, BIN_DIR) self.bindir = sh.joinpths(self.appdir, BIN_DIR)
def _get_apps_to_start(self): def _get_apps_to_start(self):
apps = list() apps = list()
for app_name in APP_OPTIONS.keys(): for app_name in APP_OPTIONS.keys():
apps.append({ apps.append({
'name': app_name, 'name': app_name,
'path': joinpths(self.bindir, app_name), 'path': sh.joinpths(self.bindir, app_name),
}) })
return apps return apps
@@ -233,7 +226,7 @@ def _keystone_setup_cmds(components):
"cmd": root_cmd + ["service", "add", "keystone", "identity", "Keystone Identity Service"] "cmd": root_cmd + ["service", "add", "keystone", "identity", "Keystone Identity Service"]
}) })
if(NOVA in components): if(constants.NOVA in components):
services.append({ services.append({
"cmd": root_cmd + ["service", "add", "nova", "compute", "Nova Compute Service"] "cmd": root_cmd + ["service", "add", "nova", "compute", "Nova Compute Service"]
}) })
@@ -241,12 +234,12 @@ def _keystone_setup_cmds(components):
"cmd": root_cmd + ["service", "add", "ec2", "ec2", "EC2 Compatability Layer"] "cmd": root_cmd + ["service", "add", "ec2", "ec2", "EC2 Compatability Layer"]
}) })
if(GLANCE in components): if(constants.GLANCE in components):
services.append({ services.append({
"cmd": root_cmd + ["service", "add", "glance", "image", "Glance Image Service"] "cmd": root_cmd + ["service", "add", "glance", "image", "Glance Image Service"]
}) })
if(SWIFT in components): if(constants.SWIFT in components):
services.append({ services.append({
"cmd": root_cmd + ["service", "add", "swift", "object-store", "Swift Service"] "cmd": root_cmd + ["service", "add", "swift", "object-store", "Swift Service"]
}) })
@@ -264,7 +257,7 @@ def _keystone_setup_cmds(components):
] ]
}) })
if(NOVA in components): if(constants.NOVA in components):
endpoint_templates.append({ endpoint_templates.append({
"cmd": root_cmd + ["endpointTemplates", "add", "cmd": root_cmd + ["endpointTemplates", "add",
"RegionOne", "nova", "RegionOne", "nova",
@@ -286,7 +279,7 @@ def _keystone_setup_cmds(components):
] ]
}) })
if(GLANCE in components): if(constants.GLANCE in components):
endpoint_templates.append({ endpoint_templates.append({
"cmd": root_cmd + ["endpointTemplates", "add", "cmd": root_cmd + ["endpointTemplates", "add",
"RegionOne", "glance", "RegionOne", "glance",
@@ -298,7 +291,7 @@ def _keystone_setup_cmds(components):
] ]
}) })
if(SWIFT in components): if(constants.SWIFT in components):
endpoint_templates.append({ endpoint_templates.append({
"cmd": root_cmd + ["endpointTemplates", "add", "cmd": root_cmd + ["endpointTemplates", "add",
"RegionOne", "swift", "RegionOne", "swift",
@@ -321,7 +314,7 @@ def _keystone_setup_cmds(components):
# but keystone doesn't parse them - it is just a blob from keystone's # but keystone doesn't parse them - it is just a blob from keystone's
# point of view # point of view
ec2_creds = [] ec2_creds = []
if(NOVA in components): if(constants.NOVA in components):
ec2_creds = [ ec2_creds = [
{ {
"cmd": root_cmd + ["credentials", "add", "cmd": root_cmd + ["credentials", "add",

View File

@@ -14,32 +14,29 @@
# under the License. # under the License.
import Logger from devstack import component as comp
import Util from devstack import constants
from devstack import log as logging
from devstack import shell as sh
from devstack import utils
#TODO fix these TYPE = constants.KEYSTONE_CLIENT
from Component import (PythonUninstallComponent, LOG = logging.getLogger("devstack.components.keystone_client")
PythonInstallComponent,
NullRuntime)
LOG = Logger.getLogger("install.keystone.client") class KeyStoneClientUninstaller(comp.PythonUninstallComponent):
TYPE = Util.KEYSTONE_CLIENT
class KeyStoneClientUninstaller(PythonUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonUninstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
class KeyStoneClientInstaller(PythonInstallComponent): class KeyStoneClientInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonInstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.git_loc = self.cfg.get("git", "keystoneclient_repo") self.git_loc = self.cfg.get("git", "keystoneclient_repo")
self.git_branch = self.cfg.get("git", "keystoneclient_branch") self.git_branch = self.cfg.get("git", "keystoneclient_branch")
def _get_download_locations(self): def _get_download_locations(self):
places = PythonInstallComponent._get_download_locations(self) places = comp.PythonInstallComponent._get_download_locations(self)
places.append({ places.append({
'uri': self.git_loc, 'uri': self.git_loc,
'branch': self.git_branch, 'branch': self.git_branch,
@@ -47,6 +44,6 @@ class KeyStoneClientInstaller(PythonInstallComponent):
return places return places
class KeyStoneClientRuntime(NullRuntime): class KeyStoneClientRuntime(comp.NullRuntime):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
NullRuntime.__init__(self, TYPE, *args, **kargs) comp.NullRuntime.__init__(self, TYPE, *args, **kargs)

View File

@@ -14,25 +14,18 @@
# under the License. # under the License.
import Logger from devstack import component as comp
from devstack import constants
from devstack import log as logging
from devstack import shell as sh
from devstack import utils
from devstack.components import nova_conf as nc
from Component import (PythonUninstallComponent, LOG = logging.getLogger("devstack.components.nova")
PythonInstallComponent,
PythonRuntime)
import Shell
import os
LOG = Logger.getLogger("install.nova")
API_CONF = "nova.conf" API_CONF = "nova.conf"
CONFIGS = [API_CONF] CONFIGS = [API_CONF]
DB_NAME = "nova" DB_NAME = "nova"
# TYPE = constants.NOVA
from Util import (NOVA)
from NovaConf import (NovaConf)
TYPE = NOVA
#what to start #what to start
# Does this start nova-compute, nova-volume, nova-network, nova-scheduler # Does this start nova-compute, nova-volume, nova-network, nova-scheduler
@@ -43,22 +36,22 @@ TYPE = NOVA
#} #}
class NovaUninstaller(PythonUninstallComponent): class NovaUninstaller(comp.PythonUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonUninstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
#self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR) #self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR)
class NovaInstaller(PythonInstallComponent): class NovaInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonInstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.gitloc = self.cfg.get("git", "nova_repo") self.gitloc = self.cfg.get("git", "nova_repo")
self.brch = self.cfg.get("git", "nova_branch") self.brch = self.cfg.get("git", "nova_branch")
# TBD is this the install location of the conf file? # TBD is this the install location of the conf file?
#self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR) #self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR)
def _get_download_location(self): def _get_download_location(self):
places = PythonInstallComponent._get_download_locations(self) places = comp.PythonInstallComponent._get_download_locations(self)
places.append({ places.append({
'uri': self.gitloc, 'uri': self.gitloc,
'branch': self.brch, 'branch': self.brch,
@@ -67,9 +60,9 @@ class NovaInstaller(PythonInstallComponent):
def configure(self): def configure(self):
# FIXME, is this necessary? Is it for the template source? # FIXME, is this necessary? Is it for the template source?
dirsmade = Shell.mkdirslist(self.cfgdir) dirsmade = sh.mkdirslist(self.cfgdir)
self.tracewriter.dir_made(*dirsmade) self.tracewriter.dir_made(*dirsmade)
nconf = NovaConf(self) nconf = nc.NovaConf(self)
LOG.info("Getting dynamic content for nova.conf") LOG.info("Getting dynamic content for nova.conf")
# Get dynamic content for nova.conf # Get dynamic content for nova.conf
lines = nconf.generate() lines = nconf.generate()
@@ -77,15 +70,15 @@ class NovaInstaller(PythonInstallComponent):
# Set up and write lines to the file # Set up and write lines to the file
fn = API_CONF fn = API_CONF
tgtfn = self._get_full_config_name(fn) tgtfn = self._get_full_config_name(fn)
dirsmade = Shell.mkdirslist(os.path.dirname(tgtfn)) dirsmade = sh.mkdirslist(os.path.dirname(tgtfn))
self.tracewriter.dir_made(*dirsmade) self.tracewriter.dir_made(*dirsmade)
LOG.info("Writing configuration file %s" % (tgtfn)) LOG.info("Writing configuration file %s" % (tgtfn))
#this trace is used to remove the files configured #this trace is used to remove the files configured
Shell.write_file(tgtfn, os.linesep.join(lines)) sh.write_file(tgtfn, os.linesep.join(lines))
self.tracewriter.cfg_write(tgtfn) self.tracewriter.cfg_write(tgtfn)
return 1 return 1
class NovaRuntime(PythonRuntime): class NovaRuntime(comp.PythonRuntime):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonRuntime.__init__(self, TYPE, *args, **kargs) comp.PythonRuntime.__init__(self, TYPE, *args, **kargs)

View File

@@ -13,33 +13,29 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from devstack import component as comp
from devstack import constants
from devstack import log as logging
from devstack import shell as sh
from devstack import utils
import Logger LOG = logging.getLogger("devstack.components.nova_client")
import Util TYPE = constants.NOVA_CLIENT
#TODO fix these
from Component import (PythonUninstallComponent,
PythonInstallComponent,
NullRuntime)
LOG = Logger.getLogger("install.nova.client") class NovaClientUninstaller(comp.PythonUninstallComponent):
TYPE = Util.NOVA_CLIENT
class NovaClientUninstaller(PythonUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonUninstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
class NovaClientInstaller(PythonInstallComponent): class NovaClientInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonInstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.git_loc = self.cfg.get("git", "novaclient_repo") self.git_loc = self.cfg.get("git", "novaclient_repo")
self.git_branch = self.cfg.get("git", "novaclient_branch") self.git_branch = self.cfg.get("git", "novaclient_branch")
def _get_download_locations(self): def _get_download_locations(self):
places = PythonInstallComponent._get_download_locations(self) places = comp.PythonInstallComponent._get_download_locations(self)
places.append({ places.append({
'uri': self.git_loc, 'uri': self.git_loc,
'branch': self.git_branch, 'branch': self.git_branch,
@@ -51,10 +47,10 @@ class NovaClientInstaller(PythonInstallComponent):
#params with actual values #params with actual values
mp = dict() mp = dict()
mp['DEST'] = self.appdir mp['DEST'] = self.appdir
mp['OPENSTACK_HOST'] = Util.get_host_ip(self.cfg) mp['OPENSTACK_HOST'] = utils.get_host_ip(self.cfg)
return mp return mp
class NovaClientRuntime(NullRuntime): class NovaClientRuntime(comp.NullRuntime):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
NullRuntime.__init__(self, TYPE, *args, **kargs) comp.NullRuntime.__init__(self, TYPE, *args, **kargs)

View File

@@ -12,11 +12,13 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import Logger from devstack import component as comp
from devstack import constants
from devstack import log as logging
from devstack import shell as sh
from devstack import utils
from Util import (QUANTUM, get_host_ip) LOG = logging.getLogger("devstack.components.nova_conf")
LOG = Logger.getLogger("install.nova_conf")
QUANTUM_OPENSWITCH_OPS = [ QUANTUM_OPENSWITCH_OPS = [
'--libvirt_vif_type=ethernet', '--libvirt_vif_type=ethernet',

View File

@@ -13,33 +13,29 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from devstack import component as comp
from devstack import constants
from devstack import log as logging
from devstack import shell as sh
from devstack import utils
import Logger LOG = logging.getLogger("devstack.components.openstackx")
import Util TYPE = constants.OPENSTACK_X
#TODO fix these
from Component import (PythonUninstallComponent,
PythonInstallComponent,
NullRuntime)
LOG = Logger.getLogger("install.openstackx") class OpenstackXUninstaller(comp.PythonUninstallComponent):
TYPE = Util.OPENSTACK_X
class OpenstackXUninstaller(PythonUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonUninstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
class OpenstackXInstaller(PythonInstallComponent): class OpenstackXInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PythonInstallComponent.__init__(self, TYPE, *args, **kargs) comp.PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.git_loc = self.cfg.get("git", "openstackx_repo") self.git_loc = self.cfg.get("git", "openstackx_repo")
self.git_branch = self.cfg.get("git", "openstackx_branch") self.git_branch = self.cfg.get("git", "openstackx_branch")
def _get_download_locations(self): def _get_download_locations(self):
places = PythonInstallComponent._get_download_locations(self) places = comp.PythonInstallComponent._get_download_locations(self)
places.append({ places.append({
'uri': self.git_loc, 'uri': self.git_loc,
'branch': self.git_branch, 'branch': self.git_branch,
@@ -47,6 +43,6 @@ class OpenstackXInstaller(PythonInstallComponent):
return places return places
class OpenstackXRuntime(NullRuntime): class OpenstackXRuntime(comp.NullRuntime):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
NullRuntime.__init__(self, TYPE, *args, **kargs) comp.NullRuntime.__init__(self, TYPE, *args, **kargs)

View File

@@ -13,17 +13,18 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from devstack import component as comp
from devstack import constants
from devstack import log as logging
from devstack import shell as sh
from devstack import utils
import Logger LOG = logging.getLogger("devstack.components.quantum")
TYPE = constants.QUANTUM
import Component class QuantumUninstaller(comp.UninstallComponent):
LOG = Logger.getLogger("install.quantum")
class QuantumUninstaller(Component.UninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
Component.UninstallComponent.__init__(self) comp.UninstallComponent.__init__(self)
def unconfigure(self): def unconfigure(self):
pass pass
@@ -32,9 +33,9 @@ class QuantumUninstaller(Component.UninstallComponent):
pass pass
class QuantumInstaller(Component.InstallComponent): class QuantumInstaller(comp.InstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
Component.InstallComponent.__init__(self) comp.InstallComponent.__init__(self)
def download(self): def download(self):
pass pass
@@ -52,9 +53,9 @@ class QuantumInstaller(Component.InstallComponent):
pass pass
class QuantumRuntime(Component.RuntimeComponent): class QuantumRuntime(comp.RuntimeComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
Component.RuntimeComponent.__init__(self) comp.RuntimeComponent.__init__(self)
def start(self): def start(self):
pass pass

View File

@@ -16,21 +16,16 @@
from tempfile import TemporaryFile from tempfile import TemporaryFile
import Logger from devstack import component as comp
import Packager from devstack import constants
from devstack import exceptions as excp
from devstack import log as logging
from devstack import shell as sh
from devstack import trace as tr
from devstack import utils
#TODO fix these LOG = logging.getLogger("devstack.components.rabbit")
from Component import (ComponentBase, RuntimeComponent, TYPE = constants.RABBIT
PkgUninstallComponent, PkgInstallComponent)
from Exceptions import (StartException, StopException,
StatusException, RestartException)
from Util import (RABBIT, UBUNTU11)
from Trace import (TraceReader,
IN_TRACE)
from Shell import (execute)
LOG = Logger.getLogger("install.rabbit")
TYPE = RABBIT
#hopefully these are distro independent.. #hopefully these are distro independent..
START_CMD = ['service', "rabbitmq-server", "start"] START_CMD = ['service', "rabbitmq-server", "start"]
@@ -40,38 +35,38 @@ RESTART_CMD = ['service', "rabbitmq-server", "restart"]
PWD_CMD = ['rabbitmqctl', 'change_password', 'guest'] PWD_CMD = ['rabbitmqctl', 'change_password', 'guest']
class RabbitUninstaller(PkgUninstallComponent): class RabbitUninstaller(comp.PkgUninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PkgUninstallComponent.__init__(self, TYPE, *args, **kargs) comp.PkgUninstallComponent.__init__(self, TYPE, *args, **kargs)
class RabbitInstaller(PkgInstallComponent): class RabbitInstaller(comp.PkgInstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
PkgInstallComponent.__init__(self, TYPE, *args, **kargs) comp.PkgInstallComponent.__init__(self, TYPE, *args, **kargs)
self.runtime = RabbitRuntime(*args, **kargs) self.runtime = RabbitRuntime(*args, **kargs)
def _setup_pw(self): def _setup_pw(self):
passwd = self.cfg.getpw("passwords", "rabbit") passwd = self.cfg.getpw("passwords", "rabbit")
cmd = PWD_CMD + [passwd] cmd = PWD_CMD + [passwd]
execute(*cmd, run_as_root=True) sh.execute(*cmd, run_as_root=True)
def post_install(self): def post_install(self):
parent_result = PkgInstallComponent.post_install(self) parent_result = comp.PkgInstallComponent.post_install(self)
self._setup_pw() self._setup_pw()
self.runtime.restart() self.runtime.restart()
return parent_result return parent_result
class RabbitRuntime(ComponentBase, RuntimeComponent): class RabbitRuntime(comp.ComponentBase, comp.RuntimeComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
ComponentBase.__init__(self, TYPE, *args, **kargs) comp.ComponentBase.__init__(self, TYPE, *args, **kargs)
self.tracereader = TraceReader(self.tracedir, IN_TRACE) self.tracereader = tr.TraceReader(self.tracedir, tr.IN_TRACE)
def start(self): def start(self):
pkgsinstalled = self.tracereader.packages_installed() pkgsinstalled = self.tracereader.packages_installed()
if(len(pkgsinstalled) == 0): if(len(pkgsinstalled) == 0):
msg = "Can not start %s since it was not installed" % (TYPE) msg = "Can not start %s since it was not installed" % (TYPE)
raise StartException(msg) raise excp.StartException(msg)
if(self.status().find('start') == -1): if(self.status().find('start') == -1):
self._run_cmd(START_CMD) self._run_cmd(START_CMD)
return None return None
@@ -80,23 +75,23 @@ class RabbitRuntime(ComponentBase, RuntimeComponent):
pkgsinstalled = self.tracereader.packages_installed() pkgsinstalled = self.tracereader.packages_installed()
if(len(pkgsinstalled) == 0): if(len(pkgsinstalled) == 0):
msg = "Can not check the status of %s since it was not installed" % (TYPE) msg = "Can not check the status of %s since it was not installed" % (TYPE)
raise StatusException(msg) raise excp.StatusException(msg)
(sysout, stderr) = execute(*STATUS_CMD, run_as_root=True) (sysout, stderr) = sh.execute(*STATUS_CMD, run_as_root=True)
return sysout.strip().lower() return sysout.strip().lower()
def _run_cmd(self, cmd): def _run_cmd(self, cmd):
if(self.distro == UBUNTU11): if(self.distro == constants.UBUNTU11):
with TemporaryFile() as f: with TemporaryFile() as f:
execute(*cmd, run_as_root=True, sh.execute(*cmd, run_as_root=True,
stdout_fh=f, stderr_fh=f) stdout_fh=f, stderr_fh=f)
else: else:
execute(*cmd, run_as_root=True) sh.execute(*cmd, run_as_root=True)
def restart(self): def restart(self):
pkgsinstalled = self.tracereader.packages_installed() pkgsinstalled = self.tracereader.packages_installed()
if(len(pkgsinstalled) == 0): if(len(pkgsinstalled) == 0):
msg = "Can not check the status of %s since it was not installed" % (TYPE) msg = "Can not check the status of %s since it was not installed" % (TYPE)
raise RestartException(msg) raise excp.RestartException(msg)
self._run_cmd(RESTART_CMD) self._run_cmd(RESTART_CMD)
return None return None
@@ -104,7 +99,7 @@ class RabbitRuntime(ComponentBase, RuntimeComponent):
pkgsinstalled = self.tracereader.packages_installed() pkgsinstalled = self.tracereader.packages_installed()
if(len(pkgsinstalled) == 0): if(len(pkgsinstalled) == 0):
msg = "Can not stop %s since it was not installed" % (TYPE) msg = "Can not stop %s since it was not installed" % (TYPE)
raise StopException(msg) raise excp.StopException(msg)
if(self.status().find('stop') == -1): if(self.status().find('stop') == -1):
self._run_cmd(STOP_CMD) self._run_cmd(STOP_CMD)
return None return None

View File

@@ -14,25 +14,25 @@
# under the License. # under the License.
import Logger from devstack import component as comp
from devstack import constants
from devstack import log as logging
from devstack import shell as sh
from devstack import utils
#TODO fix these LOG = logging.getLogger("devstack.components.swift")
from Component import (ComponentBase, RuntimeComponent,
UninstallComponent, InstallComponent)
LOG = Logger.getLogger("install.swift")
class SwiftUninstaller(UninstallComponent): class SwiftUninstaller(comp.UninstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
pass pass
class SwiftInstaller(InstallComponent): class SwiftInstaller(comp.InstallComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
pass pass
class SwiftRuntime(RuntimeComponent): class SwiftRuntime(comp.RuntimeComponent):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
pass pass

203
devstack/constants.py Normal file
View File

@@ -0,0 +1,203 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# 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.path
import re
# These also have meaning outside python,
# ie in the pkg/pip listings so update there also!
UBUNTU11 = "ubuntu-oneiric"
RHEL6 = "rhel-6"
# What this program is called
PROG_NICE_NAME = "DEVSTACK"
# These 2 identify the json post and pre install sections
PRE_INSTALL = 'pre-install'
POST_INSTALL = 'post-install'
# Default interfaces for network ip detection
IPV4 = 'IPv4'
IPV6 = 'IPv6'
DEFAULT_NET_INTERFACE = 'eth0'
DEFAULT_NET_INTERFACE_IP_VERSION = IPV4
# Component name mappings
NOVA = "nova"
NOVA_CLIENT = 'nova-client'
GLANCE = "glance"
QUANTUM = "quantum"
SWIFT = "swift"
HORIZON = "horizon"
KEYSTONE = "keystone"
KEYSTONE_CLIENT = 'keystone-client'
DB = "db"
RABBIT = "rabbit"
OPENSTACK_X = 'openstack-x'
COMPONENT_NAMES = [
NOVA, NOVA_CLIENT,
GLANCE,
QUANTUM,
SWIFT,
HORIZON,
KEYSTONE, KEYSTONE_CLIENT,
OPENSTACK_X,
DB,
RABBIT,
]
# Ordering of install (lower priority means earlier)
COMPONENT_NAMES_PRIORITY = {
DB: 1,
RABBIT: 2,
KEYSTONE: 3,
GLANCE: 4,
QUANTUM: 4,
SWIFT: 4,
NOVA: 5,
KEYSTONE_CLIENT: 6,
NOVA_CLIENT: 6,
OPENSTACK_X: 6,
HORIZON: 10,
}
# When a component is asked for it may
# need another component, that dependency
# mapping is listed here
COMPONENT_DEPENDENCIES = {
DB: [],
KEYSTONE_CLIENT: [],
RABBIT: [],
GLANCE: [KEYSTONE, DB],
KEYSTONE: [DB],
NOVA: [KEYSTONE, GLANCE, DB, RABBIT],
SWIFT: [],
HORIZON: [KEYSTONE_CLIENT, GLANCE, NOVA_CLIENT, OPENSTACK_X],
QUANTUM: [],
}
# Default subdirs of a components root directory
COMPONENT_TRACE_DIR = "traces"
COMPONENT_APP_DIR = "app"
COMPONENT_CONFIG_DIR = "config"
# Program
# actions
INSTALL = "install"
UNINSTALL = "uninstall"
START = "start"
STOP = "stop"
ACTIONS = [INSTALL, UNINSTALL, START, STOP]
# This is used to map an action to a useful string for
# the welcome display
WELCOME_MAP = {
INSTALL: "Installer",
UNINSTALL: "Uninstaller",
START: "Runner",
STOP: "Stopper",
}
# Where we should get the config file and where stacks config
# directory is
STACK_CONFIG_DIR = "conf"
STACK_PKG_DIR = os.path.join(STACK_CONFIG_DIR, "pkgs")
STACK_PIP_DIR = os.path.join(STACK_CONFIG_DIR, "pips")
STACK_CONFIG_LOCATION = os.path.join(STACK_CONFIG_DIR, "stack.ini")
# These regex is how we match python platform output to a known constant
KNOWN_DISTROS = {
UBUNTU11: re.compile('Ubuntu(.*)oneiric', re.IGNORECASE),
RHEL6: re.compile('redhat-6\.(\d+)', re.IGNORECASE),
}
# The pip files that each component needs
PIP_MAP = {
NOVA:
[],
GLANCE:
[],
KEYSTONE:
[
os.path.join(STACK_PIP_DIR, 'keystone.json'),
],
HORIZON:
[
os.path.join(STACK_PIP_DIR, 'horizon.json'),
],
SWIFT:
[],
KEYSTONE_CLIENT:
[],
DB:
[],
RABBIT:
[],
QUANTUM:
[],
}
# The pkg files that each component needs
PKG_MAP = {
NOVA:
[
os.path.join(STACK_PKG_DIR, "general.json"),
os.path.join(STACK_PKG_DIR, "nova.json"),
],
QUANTUM:
[],
NOVA_CLIENT:
[
os.path.join(STACK_PKG_DIR, "general.json"),
os.path.join(STACK_PKG_DIR, "nova-client.json"),
],
GLANCE:
[
os.path.join(STACK_PKG_DIR, "general.json"),
os.path.join(STACK_PKG_DIR, 'glance.json'),
],
KEYSTONE:
[
os.path.join(STACK_PKG_DIR, "general.json"),
os.path.join(STACK_PKG_DIR, 'keystone.json'),
],
HORIZON:
[
os.path.join(STACK_PKG_DIR, "general.json"),
os.path.join(STACK_PKG_DIR, 'horizon.json'),
],
SWIFT:
[
os.path.join(STACK_PKG_DIR, "general.json"),
os.path.join(STACK_PKG_DIR, 'swift.json'),
],
KEYSTONE_CLIENT:
[
os.path.join(STACK_PKG_DIR, "keystone-client.json"),
],
DB:
[
os.path.join(STACK_PKG_DIR, 'db.json'),
],
RABBIT:
[
os.path.join(STACK_PKG_DIR, 'rabbitmq.json'),
],
OPENSTACK_X:
[
os.path.join(STACK_PKG_DIR, 'openstackx.json'),
],
}

19
devstack/date.py Normal file
View File

@@ -0,0 +1,19 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# 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.
from time import (localtime, strftime)
def rcf8222date():
return strftime("%a, %d %b %Y %H:%M:%S", localtime())

View File

@@ -17,25 +17,25 @@
from urlparse import urlparse from urlparse import urlparse
import re import re
#TODO fix these from devstack import log as logging
from Shell import (execute, mkdirslist) from devstack import shell as sh
from Util import (MASTER_BRANCH)
import Logger LOG = logging.getLogger("devstack.downloader")
LOG = Logger.getLogger("install.downloader")
EXT_REG = re.compile(r"^(.*?)\.git\s*$", re.IGNORECASE) EXT_REG = re.compile(r"^(.*?)\.git\s*$", re.IGNORECASE)
# What the git master string is
GIT_MASTER_BRANCH = "master"
def _gitdownload(storewhere, uri, branch=None): def _gitdownload(storewhere, uri, branch=None):
dirsmade = mkdirslist(storewhere) dirsmade = sh.mkdirslist(storewhere)
LOG.info("Downloading from %s to %s" % (uri, storewhere)) LOG.info("Downloading from %s to %s" % (uri, storewhere))
cmd = ["git", "clone"] + [uri, storewhere] cmd = ["git", "clone"] + [uri, storewhere]
execute(*cmd) sh.execute(*cmd)
if(branch and branch != MASTER_BRANCH): if(branch and branch != GIT_MASTER_BRANCH):
LOG.info("Adjusting git branch to %s" % (branch)) LOG.info("Adjusting git branch to %s" % (branch))
cmd = ['git', 'checkout'] + [branch] cmd = ['git', 'checkout'] + [branch]
execute(*cmd, cwd=storewhere) sh.execute(*cmd, cwd=storewhere)
return dirsmade return dirsmade

View File

@@ -15,10 +15,10 @@
import os import os
import Logger from devstack import log as logging
TRUE_VALUES = ['yes', 'true', 't', '1', 'on'] TRUE_VALUES = ['yes', 'true', 't', '1', 'on']
LOG = Logger.getLogger("install.environment") LOG = logging.getLogger("devstack.environment")
def _str2bool(value_str): def _str2bool(value_str):
@@ -27,13 +27,13 @@ def _str2bool(value_str):
return False return False
def get_environment(): def get():
return dict(os.environ) return dict(os.environ)
def get_environment_key(key, default_value=None): def get_key(key, default_value=None):
LOG.debug("Looking up environment variable \"%s\"" % (key)) LOG.debug("Looking up environment variable \"%s\"" % (key))
value = get_environment().get(key) value = get().get(key)
if(value == None): if(value == None):
LOG.debug("Could not find anything in environment variable \"%s\"" % (key)) LOG.debug("Could not find anything in environment variable \"%s\"" % (key))
value = default_value value = default_value
@@ -42,8 +42,8 @@ def get_environment_key(key, default_value=None):
return value return value
def get_environment_bool(key, default_value=False): def get_bool(key, default_value=False):
value = get_environment_key(key, None) value = get_key(key, None)
if(value == None): if(value == None):
return default_value return default_value
return _str2bool(value) return _str2bool(value)

View File

@@ -0,0 +1,14 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# 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.

View File

@@ -75,8 +75,4 @@ def getLogger(name):
return logging.getLogger(name) return logging.getLogger(name)
#this should happen first (and once)
INIT_LOGGING = False
if(not INIT_LOGGING):
setupLogging()
INIT_LOGGING = True

View File

@@ -14,18 +14,24 @@
# under the License. # under the License.
from optparse import OptionParser from optparse import OptionParser
from optparse import IndentedHelpFormatter
import Util from devstack import constants
from devstack import utils
from devstack import version
HELP_WIDTH = 80
def parse(): def parse():
#version #version
version_str = "%prog v" + Util.VERSION_STR version_str = "%prog v" + version.version_string()
parser = OptionParser(version=version_str) help_formatter = IndentedHelpFormatter(width=HELP_WIDTH)
parser = OptionParser(version=version_str, formatter=help_formatter)
#non-boolean options #non-boolean options
known_actions = sorted(Util.ACTIONS) known_actions = sorted(constants.ACTIONS)
actions = "(" + ", ".join(known_actions) + ")" actions = "(" + ", ".join(known_actions) + ")"
parser.add_option("-a", "--action", parser.add_option("-a", "--action",
action="store", action="store",
@@ -42,7 +48,7 @@ def parse():
help="root DIR for new components or "\ help="root DIR for new components or "\
"DIR with existing components (ACTION dependent)") "DIR with existing components (ACTION dependent)")
known_components = sorted(Util.COMPONENT_NAMES) known_components = sorted(constants.COMPONENT_NAMES)
components = "(" + ", ".join(known_components) + ")" components = "(" + ", ".join(known_components) + ")"
parser.add_option("-c", "--component", parser.add_option("-c", "--component",
action="append", action="append",
@@ -84,5 +90,4 @@ def parse():
output['force'] = options.force output['force'] = options.force
output['ignore_deps'] = options.ignore_deps output['ignore_deps'] = options.ignore_deps
output['extras'] = args output['extras'] = args
return output return output

View File

@@ -13,20 +13,11 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from devstack import constants
from devstack import log as logging
from devstack import utils
""" LOG = logging.getLogger("devstack.packager")
An abstraction that different packaging
frameworks (ie apt, yum) can inherit from
"""
import Logger
import Shell
#TODO fix these
from Util import (execute_template,
PRE_INSTALL, POST_INSTALL)
LOG = Logger.getLogger("install.packager")
class Packager(): class Packager():
@@ -43,16 +34,16 @@ class Packager():
pkgnames = sorted(pkgs.keys()) pkgnames = sorted(pkgs.keys())
for name in pkgnames: for name in pkgnames:
packageinfo = pkgs.get(name) packageinfo = pkgs.get(name)
preinstallcmds = packageinfo.get(PRE_INSTALL) preinstallcmds = packageinfo.get(constants.PRE_INSTALL)
if(preinstallcmds and len(preinstallcmds)): if(preinstallcmds and len(preinstallcmds)):
LOG.info("Running pre-install commands for package %s." % (name)) LOG.info("Running pre-install commands for package %s." % (name))
execute_template(*preinstallcmds, params=installparams) utils.execute_template(*preinstallcmds, params=installparams)
def post_install(self, pkgs, installparams=None): def post_install(self, pkgs, installparams=None):
pkgnames = sorted(pkgs.keys()) pkgnames = sorted(pkgs.keys())
for name in pkgnames: for name in pkgnames:
packageinfo = pkgs.get(name) packageinfo = pkgs.get(name)
postinstallcmds = packageinfo.get(POST_INSTALL) postinstallcmds = packageinfo.get(constants.POST_INSTALL)
if(postinstallcmds and len(postinstallcmds)): if(postinstallcmds and len(postinstallcmds)):
LOG.info("Running post-install commands for package %s." % (name)) LOG.info("Running post-install commands for package %s." % (name))
execute_template(*postinstallcmds, params=installparams) utils.execute_template(*postinstallcmds, params=installparams)

View File

@@ -13,21 +13,20 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from tempfile import TemporaryFile
import os import os
import re import re
from tempfile import TemporaryFile
import time import time
import Packager from devstack import constants
import Logger from devstack import log as logging
from devstack import packager as pack
from devstack import shell as sh
from devstack import utils
#TODO fix these LOG = logging.getLogger("devstack.packaging.apt")
from Util import (UBUNTU11, RHEL6)
from Util import param_replace
from Shell import execute
LOG = Logger.getLogger("install.package.apt")
#base apt commands
APT_GET = ['apt-get'] APT_GET = ['apt-get']
APT_PURGE = ["purge", "-y"] APT_PURGE = ["purge", "-y"]
APT_REMOVE = ["remove", "-y"] APT_REMOVE = ["remove", "-y"]
@@ -44,21 +43,25 @@ ENV_ADDITIONS = {'DEBIAN_FRONTEND': 'noninteractive'}
VERSION_TEMPL = "%s=%s" VERSION_TEMPL = "%s=%s"
class AptPackager(Packager.Packager): class AptPackager(pack.Packager):
def __init__(self, distro): def __init__(self, distro):
Packager.Packager.__init__(self, distro) pack.Packager.__init__(self, distro)
def _form_cmd(self, name, version): def _format_version(self, name, version):
return VERSION_TEMPL % (name, version)
def _format_pkg(self, name, version):
if(version and len(version)): if(version and len(version)):
cmd = VERSION_TEMPL % (name, version) cmd = self._format_version(name, version)
else: else:
cmd = name cmd = name
return cmd return cmd
def _execute_apt(self, cmd, run_as_root, check_exit=True): def _execute_apt(self, cmd, **kargs):
execute(*cmd, run_as_root=run_as_root, sh.execute(*cmd, run_as_root=True,
check_exit_code=check_exit, check_exit_code=True,
env_overrides=ENV_ADDITIONS) env_overrides=ENV_ADDITIONS,
**kargs)
def remove_batch(self, pkgs): def remove_batch(self, pkgs):
pkgnames = sorted(pkgs.keys()) pkgnames = sorted(pkgs.keys())
@@ -71,15 +74,14 @@ class AptPackager(Packager.Packager):
continue continue
if(self._pkg_remove_special(name, info)): if(self._pkg_remove_special(name, info)):
continue continue
full_cmd = self._form_cmd(name, info.get("version")) pkg_full = self._format_pkg(name, info.get("version"))
if(full_cmd): cmds.append(pkg_full)
cmds.append(full_cmd)
if(len(cmds)): if(len(cmds)):
cmd = APT_GET + APT_DO_REMOVE + cmds cmd = APT_GET + APT_DO_REMOVE + cmds
self._execute_apt(cmd, True) self._execute_apt(cmd)
#clean them out #clean them out
cmd = APT_GET + APT_AUTOREMOVE cmd = APT_GET + APT_AUTOREMOVE
self._execute_apt(cmd, True) self._execute_apt(cmd)
def install_batch(self, pkgs): def install_batch(self, pkgs):
pkgnames = sorted(pkgs.keys()) pkgnames = sorted(pkgs.keys())
@@ -89,28 +91,26 @@ class AptPackager(Packager.Packager):
info = pkgs.get(name) or {} info = pkgs.get(name) or {}
if(self._pkg_install_special(name, info)): if(self._pkg_install_special(name, info)):
continue continue
full_cmd = self._form_cmd(name, info.get("version")) pkg_full = self._format_pkg(name, info.get("version"))
if(full_cmd): cmds.append(pkg_full)
cmds.append(full_cmd)
#install them #install them
if(len(cmds)): if(len(cmds)):
cmd = APT_GET + APT_INSTALL + cmds cmd = APT_GET + APT_INSTALL + cmds
self._execute_apt(cmd, True) self._execute_apt(cmd)
def _pkg_remove_special(self, name, pkginfo): def _pkg_remove_special(self, name, pkginfo):
if(name == 'rabbitmq-server' and self.distro == UBUNTU11): if(name == 'rabbitmq-server' and self.distro == UBUNTU11):
#https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/878597 #https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/878597
#https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/878600 #https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/878600
LOG.info("Handling special remove of %s" % (name)) LOG.info("Handling special remove of %s" % (name))
full_cmd = self._form_cmd(name, pkginfo.get("version")) pkg_full = self._format_pkg(name, pkginfo.get("version"))
if(full_cmd): cmd = APT_GET + APT_REMOVE + [pkg_full]
cmd = APT_GET + APT_REMOVE + [full_cmd] self._execute_apt(cmd)
self._execute_apt(cmd, True, True)
#probably useful to do this #probably useful to do this
time.sleep(1) time.sleep(1)
#purge #purge
cmd = APT_GET + APT_PURGE + [full_cmd] cmd = APT_GET + APT_PURGE + [pkg_full]
self._execute_apt(cmd, True) self._execute_apt(cmd)
return True return True
return False return False
@@ -121,9 +121,8 @@ class AptPackager(Packager.Packager):
LOG.info("Handling special install of %s" % (name)) LOG.info("Handling special install of %s" % (name))
#this seems to be a temporary fix for that bug #this seems to be a temporary fix for that bug
with TemporaryFile() as f: with TemporaryFile() as f:
full_cmd = self._form_cmd(name, pkginfo.get("version")) pkg_full = self._format_pkg(name, pkginfo.get("version"))
if(full_cmd): cmd = APT_GET + APT_INSTALL + [pkg_full]
cmd = APT_GET + APT_INSTALL + [full_cmd] self._execute_apt(*cmd, stdout_fh=f, stderr_fh=f)
execute(*cmd, run_as_root=True, stdout_fh=f, stderr_fh=f, env_overrides=ENV_ADDITIONS)
return True return True
return False return False

View File

@@ -13,46 +13,35 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import Packager from devstack import packager as pack
import Logger from devstack import shell as sh
import Util from devstack import log as logging
import Shell
#TODO fix these LOG = logging.getLogger("devstack.packaging.yum")
from Shell import execute
from Util import param_replace
LOG = Logger.getLogger("install.package.yum")
YUM_CMD = ['yum'] YUM_CMD = ['yum']
YUM_INSTALL = ["install", "-y"] YUM_INSTALL = ["install", "-y"]
class YumPackager(Packager.Packager): class YumPackager(pack.Packager):
def __init__(self, distro): def __init__(self, distro):
Packager.Packager.__init__(self, distro) pack.Packager.__init__(self, distro)
def _form_cmd(self, name, version): def _format_pkg_name(self, name, version):
cmd = name cmd = name
if(version and len(version)): if(version != None and len(version)):
cmd = cmd + "-" + version cmd = cmd + "-" + version
return cmd return cmd
def _do_cmd(self, base_cmd, pkgs): def _do_cmd(self, base_cmd, pkgs):
pkgnames = pkgs.keys() pkgnames = sorted(pkgs.keys())
pkgnames.sort() cmds = list()
cmds = []
for name in pkgnames: for name in pkgnames:
version = None pkg_info = pkgs.get(name)
info = pkgs.get(name) torun = self._format_pkg_name(name, pkg_info.get("version"))
if(info):
version = info.get("version")
torun = self._form_cmd(name, version)
cmds.append(torun) cmds.append(torun)
if(len(cmds)): if(len(cmds)):
cmd = YUM_CMD + base_cmd + cmds cmd = YUM_CMD + base_cmd + cmds
LOG.debug("About to run:%s" % (cmd)) sh.execute(*cmd, run_as_root=True)
execute(*cmd, run_as_root=True)
def install_batch(self, pkgs): def install_batch(self, pkgs):
LOG.info("install_batch called")
self._do_cmd(YUM_INSTALL, pkgs) self._do_cmd(YUM_INSTALL, pkgs)

View File

@@ -13,13 +13,12 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import Logger
#TODO fix these from devstack import exceptions as excp
from Shell import (execute) from devstack import log as logging
from Exceptions import (ProcessExecutionError) from devstack import shell as sh
LOG = Logger.getLogger("install.pip") LOG = logging.getLogger("devstack.pip")
INSTALL_CMD = ['pip', 'install'] INSTALL_CMD = ['pip', 'install']
UNINSTALL_CMD = ['pip', 'uninstall'] UNINSTALL_CMD = ['pip', 'uninstall']
@@ -41,7 +40,7 @@ def install(pips):
if(len(actions)): if(len(actions)):
LOG.info("Installing python packages [%s]" % (", ".join(actions))) LOG.info("Installing python packages [%s]" % (", ".join(actions)))
cmd = INSTALL_CMD + actions cmd = INSTALL_CMD + actions
execute(*cmd, run_as_root=True) sh.execute(*cmd, run_as_root=True)
def uninstall(pips): def uninstall(pips):
@@ -55,10 +54,10 @@ def uninstall(pips):
skip_errors = pipinfo.get('skip_uninstall_errors', False) skip_errors = pipinfo.get('skip_uninstall_errors', False)
try: try:
cmd = UNINSTALL_CMD + [name] cmd = UNINSTALL_CMD + [name]
execute(*cmd, run_as_root=True) sh.execute(*cmd, run_as_root=True)
except ProcessExecutionError, e: except excp.ProcessExecutionError, e:
if(skip_errors): if(skip_errors):
LOG.warn("Ignoring execution error that occured when uninstalling %s" % (name)) LOG.warn("Ignoring execution error that occured when uninstalling %s!" % (name))
pass pass
else: else:
raise raise

View File

@@ -20,27 +20,23 @@ import signal
import errno import errno
import time import time
import Runner from devstack import exceptions as excp
import Util from devstack import log as logging
import Exceptions from devstack import runner
import Trace from devstack import shell as sh
import Logger from devstack import trace as tr
import Shell from devstack import utils
#TODO fix these
from Exceptions import (StartException, StopException)
from Shell import (unlink, mkdir, joinpths, write_file,
load_file, isfile)
# Maximum for the number of available file descriptors (when not found) # Maximum for the number of available file descriptors (when not found)
MAXFD = 2048 MAXFD = 2048
MAX_KILL_TRY = 5 MAX_KILL_TRY = 5
SLEEP_TIME = 1 SLEEP_TIME = 1
LOG = Logger.getLogger("install.runners.foreground") LOG = logging.getLogger("devstack.runners.foreground")
#trace constants #trace constants
RUN = Runner.RUN_TYPE RUN = runner.RUN_TYPE
RUN_TYPE = "FORK" RUN_TYPE = "FORK"
PID_FN = "PID_FN" PID_FN = "PID_FN"
STDOUT_FN = "STDOUT_FN" STDOUT_FN = "STDOUT_FN"
@@ -49,9 +45,9 @@ NAME = "NAME"
FORK_TEMPL = "%s.fork" FORK_TEMPL = "%s.fork"
class ForegroundRunner(Runner.Runner): class ForkRunner(runner.Runner):
def __init__(self): def __init__(self):
Runner.Runner.__init__(self) runner.Runner.__init__(self)
def _stop_pid(self, pid): def _stop_pid(self, pid):
killed = False killed = False
@@ -76,7 +72,7 @@ class ForegroundRunner(Runner.Runner):
tracedir = kargs.get("trace_dir") tracedir = kargs.get("trace_dir")
fn_name = FORK_TEMPL % (name) fn_name = FORK_TEMPL % (name)
(pidfile, stderr, stdout) = self._form_file_names(tracedir, fn_name) (pidfile, stderr, stdout) = self._form_file_names(tracedir, fn_name)
tfname = Trace.trace_fn(tracedir, fn_name) tfname = tr.trace_fn(tracedir, fn_name)
if(isfile(pidfile) and isfile(tfname)): if(isfile(pidfile) and isfile(tfname)):
pid = int(load_file(pidfile).strip()) pid = int(load_file(pidfile).strip())
killed = self._stop_pid(pid) killed = self._stop_pid(pid)
@@ -158,8 +154,8 @@ class ForegroundRunner(Runner.Runner):
appdir = kargs.get("app_dir") appdir = kargs.get("app_dir")
fn_name = FORK_TEMPL % (name) fn_name = FORK_TEMPL % (name)
(pidfile, stderrfn, stdoutfn) = self._form_file_names(tracedir, fn_name) (pidfile, stderrfn, stdoutfn) = self._form_file_names(tracedir, fn_name)
tracefn = Trace.touch_trace(tracedir, fn_name) tracefn = tr.touch_trace(tracedir, fn_name)
runtrace = Trace.Trace(tracefn) runtrace = tr.Trace(tracefn)
runtrace.trace(RUN, RUN_TYPE) runtrace.trace(RUN, RUN_TYPE)
runtrace.trace(PID_FN, pidfile) runtrace.trace(PID_FN, pidfile)
runtrace.trace(STDERR_FN, stderrfn) runtrace.trace(STDERR_FN, stderrfn)

View File

@@ -17,28 +17,27 @@ import time
import os import os
import re import re
import Runner from devstack import exceptions as excp
import Logger from devstack import log as logging
from devstack import runner
from devstack import shell as sh
from devstack import trace as tr
from devstack import utils
#TODO fix these LOG = logging.getLogger("install.screen")
from Exceptions import (StartException, StopException)
from Util import (execute_template)
from Shell import (execute)
LOG = Logger.getLogger("install.screen")
SCREEN_MAKE = ['screen', '-d', '-m', '-S', '%NAME%', '-t', '%NAME%'] SCREEN_MAKE = ['screen', '-d', '-m', '-S', '%NAME%', '-t', '%NAME%']
NAME_POSTFIX = ".devstack" NAME_POSTFIX = ".devstack"
RUN_TYPE = "SCREEN" RUN_TYPE = "SCREEN"
class ScreenRunner(Runner.Runner): class ScreenRunner(runner.Runner):
def __init__(self): def __init__(self):
Runner.Runner.__init__(self) runner.Runner.__init__(self)
def stop(self, name, *args, **kargs): def stop(self, name, *args, **kargs):
real_name = name + NAME_POSTFIX real_name = name + NAME_POSTFIX
list_cmd = ['screen', '-list'] list_cmd = ['screen', '-list']
(sysout, stderr) = execute(*list_cmd) (sysout, stderr) = sh.execute(*list_cmd)
lines = sysout.splitlines() lines = sysout.splitlines()
entries = list() entries = list()
lookfor = r"^(\d+\." + re.escape(real_name) + r")\s+(.*)$" lookfor = r"^(\d+\." + re.escape(real_name) + r")\s+(.*)$"
@@ -64,5 +63,5 @@ class ScreenRunner(Runner.Runner):
params['NAME'] = name + NAME_POSTFIX params['NAME'] = name + NAME_POSTFIX
runcmd = SCREEN_MAKE + [program] + list(args) runcmd = SCREEN_MAKE + [program] + list(args)
cmds = [{'cmd':runcmd}] cmds = [{'cmd':runcmd}]
execute_template(*cmds, params=params, cwd=app_dir, **kargs) utils.execute_template(*cmds, params=params, cwd=app_dir, **kargs)
return None return None

View File

@@ -22,16 +22,14 @@ import shutil
import subprocess import subprocess
import sys import sys
import Logger from devstack import log as logging
from devstack import exceptions as excp
#TODO fix these from devstack import env
from Exceptions import (ProcessExecutionError, FileException, BadParamException)
from Environment import (get_environment_bool, get_environment)
ROOT_HELPER = ["sudo"] ROOT_HELPER = ["sudo"]
MKPW_CMD = ["openssl", 'rand', '-hex'] MKPW_CMD = ["openssl", 'rand', '-hex']
PASS_ASK_ENV = 'PASS_ASK' PASS_ASK_ENV = 'PASS_ASK'
LOG = Logger.getLogger("install.shell") LOG = logging.getLogger("devstack.shell")
def execute(*cmd, **kwargs): def execute(*cmd, **kwargs):
@@ -78,12 +76,13 @@ def execute(*cmd, **kwargs):
if('stdin_fh' in kwargs.keys()): if('stdin_fh' in kwargs.keys()):
stdin_fh = kwargs.get('stdin_fh') stdin_fh = kwargs.get('stdin_fh')
LOG.debug("Redirecting stdin to file handle: %s" % (stdin_fh)) LOG.debug("Redirecting stdin to file handle: %s" % (stdin_fh))
process_input = None
if('stderr_fh' in kwargs.keys()): if('stderr_fh' in kwargs.keys()):
stderr_fh = kwargs.get('stderr_fh') stderr_fh = kwargs.get('stderr_fh')
LOG.debug("Redirecting stderr to file handle: %s" % (stderr_fh)) LOG.debug("Redirecting stderr to file handle: %s" % (stderr_fh))
process_env = get_environment() process_env = env.get()
LOG.debug("With environment: %s" % (process_env)) LOG.debug("With environment: %s" % (process_env))
if(env_overrides and len(env_overrides)): if(env_overrides and len(env_overrides)):
LOG.debug("With additional environment overrides: %s" % (env_overrides)) LOG.debug("With additional environment overrides: %s" % (env_overrides))
@@ -114,7 +113,7 @@ def execute(*cmd, **kwargs):
ecmd = cmd ecmd = cmd
if(not shell): if(not shell):
ecmd = ' '.join(cmd) ecmd = ' '.join(cmd)
raise ProcessExecutionError( raise excp.ProcessExecutionError(
exit_code=_returncode, exit_code=_returncode,
stdout=stdout, stdout=stdout,
stderr=stderr, stderr=stderr,
@@ -123,6 +122,10 @@ def execute(*cmd, **kwargs):
return result return result
def listdir(path):
return os.listdir(path)
def isfile(fn): def isfile(fn):
return os.path.isfile(fn) return os.path.isfile(fn)
@@ -138,7 +141,7 @@ def joinpths(*paths):
def _gen_password(pw_len): def _gen_password(pw_len):
if(pw_len <= 0): if(pw_len <= 0):
msg = "Password length %s can not be less than or equal to zero" % (pw_len) msg = "Password length %s can not be less than or equal to zero" % (pw_len)
raise BadParamException(msg) raise excp.BadParamException(msg)
LOG.debug("Generating you a pseudo-random password of byte length: %s" % (pw_len)) LOG.debug("Generating you a pseudo-random password of byte length: %s" % (pw_len))
cmd = MKPW_CMD + [pw_len] cmd = MKPW_CMD + [pw_len]
(stdout, stderr) = execute(*cmd) (stdout, stderr) = execute(*cmd)
@@ -154,7 +157,7 @@ def _prompt_password(prompt=None):
def password(prompt=None, pw_len=8): def password(prompt=None, pw_len=8):
rd = "" rd = ""
ask_for_pw = get_environment_bool(PASS_ASK_ENV, True) ask_for_pw = env.get_bool(PASS_ASK_ENV, True)
if(ask_for_pw): if(ask_for_pw):
rd = _prompt_password(prompt) rd = _prompt_password(prompt)
if(len(rd) == 0): if(len(rd) == 0):
@@ -204,7 +207,7 @@ def touch_file(fn, die_if_there=True):
else: else:
if(die_if_there): if(die_if_there):
msg = "Can not touch file %s since it already exists" % (fn) msg = "Can not touch file %s since it already exists" % (fn)
raise FileException(msg) raise excp.FileException(msg)
def load_file(fn): def load_file(fn):
@@ -230,8 +233,30 @@ def deldir(path):
shutil.rmtree(path) shutil.rmtree(path)
def prompt(prompt): def rmdir(path, quiet=True):
return raw_input(prompt) if(not isdir(path)):
return
try:
LOG.debug("Deleting directory \"%s\" with the cavet that we will fail if it's not empty." % (path))
os.rmdir(path)
LOG.debug("Deleted directory \"%s\"" % (path))
except OSError, e:
if(not quiet):
raise
else:
pass
def dirname(path):
return os.path.dirname(path)
def canon_path(path):
return os.path.realpath(path)
def prompt(prompt_str):
return raw_input(prompt_str)
def unlink(path, ignore_errors=True): def unlink(path, ignore_errors=True):

View File

@@ -14,15 +14,12 @@
# under the License. # under the License.
import json import json
import os.path
#TODO fix these from devstack import exceptions as excp
from Exceptions import (NoTraceException) from devstack import shell as sh
from Util import (rcf8222date) from devstack import date
from Shell import (touch_file, append_file,
joinpths, load_file, mkdirslist,
isfile)
#trace per line output and file extension formats
TRACE_FMT = "%s - %s\n" TRACE_FMT = "%s - %s\n"
TRACE_EXT = ".trace" TRACE_EXT = ".trace"
@@ -55,9 +52,9 @@ class Trace():
def trace(self, cmd, action=None): def trace(self, cmd, action=None):
if(action == None): if(action == None):
action = rcf8222date() action = date.rcf8222date()
line = TRACE_FMT % (cmd, action) line = TRACE_FMT % (cmd, action)
append_file(self.tracefn, line) sh.append_file(self.tracefn, line)
class TraceWriter(): class TraceWriter():
@@ -71,7 +68,7 @@ class TraceWriter():
if(self.started): if(self.started):
return return
else: else:
dirs = mkdirslist(self.root) dirs = sh.mkdirslist(self.root)
self.fn = touch_trace(self.root, self.name) self.fn = touch_trace(self.root, self.name)
self.tracer = Trace(self.fn) self.tracer = Trace(self.fn)
self.tracer.trace(TRACE_VERSION, str(TRACE_VER)) self.tracer.trace(TRACE_VERSION, str(TRACE_VER))
@@ -227,12 +224,12 @@ class TraceReader():
def trace_fn(rootdir, name): def trace_fn(rootdir, name):
fullname = name + TRACE_EXT fullname = name + TRACE_EXT
return joinpths(rootdir, fullname) return sh.joinpths(rootdir, fullname)
def touch_trace(rootdir, name): def touch_trace(rootdir, name):
tracefn = trace_fn(rootdir, name) tracefn = trace_fn(rootdir, name)
touch_file(tracefn) sh.touch_file(tracefn)
return tracefn return tracefn
@@ -248,16 +245,16 @@ def split_line(line):
def read(rootdir, name): def read(rootdir, name):
pth = trace_fn(rootdir, name) pth = trace_fn(rootdir, name)
contents = load_file(pth) contents = sh.load_file(pth)
lines = contents.splitlines() lines = contents.splitlines()
return lines return lines
def parse_fn(fn): def parse_fn(fn):
if(not isfile(fn)): if(not sh.isfile(fn)):
msg = "No trace found at filename %s" % (fn) msg = "No trace found at filename %s" % (fn)
raise NoTraceException(msg) raise excp.NoTraceException(msg)
contents = load_file(fn) contents = sh.load_file(fn)
lines = contents.splitlines() lines = contents.splitlines()
accum = list() accum = list()
for line in lines: for line in lines:

View File

@@ -13,210 +13,30 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from time import (localtime, strftime)
from termcolor import colored
import os
import platform
import re
import sys
import json import json
import netifaces import netifaces
import operator import operator
import os
import platform
import re
import string
import sys
import Exceptions from termcolor import colored
import Logger
import Shell
#constant goodies from devstack import constants
VERSION = 0x2 from devstack import exceptions as excp
VERSION_STR = "%0.2f" % (VERSION) from devstack import log as logging
DEVSTACK = 'DEVSTACK' from devstack import shell as sh
from devstack import version
#these also have meaning outside python
#ie in the pkg/pip listings so update there also!
UBUNTU11 = "ubuntu-oneiric"
RHEL6 = "rhel-6"
#GIT master
MASTER_BRANCH = "master"
#other constants
PRE_INSTALL = 'pre-install'
POST_INSTALL = 'post-install'
IPV4 = 'IPv4'
IPV6 = 'IPv6'
DEFAULT_NET_INTERFACE = 'eth0'
DEFAULT_NET_INTERFACE_IP_VERSION = IPV4
#this regex is used for parameter substitution
PARAM_SUB_REGEX = re.compile(r"%([\w\d]+?)%") PARAM_SUB_REGEX = re.compile(r"%([\w\d]+?)%")
LOG = logging.getLogger("devstack.util")
#component name mappings
NOVA = "nova"
NOVA_CLIENT = 'nova-client'
GLANCE = "glance"
QUANTUM = "quantum"
SWIFT = "swift"
HORIZON = "horizon"
KEYSTONE = "keystone"
KEYSTONE_CLIENT = 'keystone-client'
DB = "db"
RABBIT = "rabbit"
OPENSTACK_X = 'openstack-x'
COMPONENT_NAMES = [NOVA, NOVA_CLIENT,
GLANCE, QUANTUM,
SWIFT, HORIZON,
KEYSTONE, KEYSTONE_CLIENT,
OPENSTACK_X,
DB, RABBIT]
#ordering of install (lower priority means earlier)
NAMES_PRIORITY = {
DB: 1,
RABBIT: 2,
KEYSTONE: 3,
GLANCE: 4,
QUANTUM: 4,
SWIFT: 4,
NOVA: 5,
KEYSTONE_CLIENT: 6,
NOVA_CLIENT: 6,
OPENSTACK_X: 6,
HORIZON: 10,
}
#when a component is asked for it may
#need another component, that dependency
#map is listed here...
COMPONENT_DEPENDENCIES = {
DB: [],
KEYSTONE_CLIENT: [],
RABBIT: [],
GLANCE: [KEYSTONE, DB],
KEYSTONE: [DB],
NOVA: [KEYSTONE, GLANCE, DB, RABBIT],
SWIFT: [],
HORIZON: [KEYSTONE_CLIENT, GLANCE, NOVA_CLIENT, OPENSTACK_X],
QUANTUM: [],
}
#program
#actions
INSTALL = "install"
UNINSTALL = "uninstall"
START = "start"
STOP = "stop"
ACTIONS = [INSTALL, UNINSTALL, START, STOP]
#this is used to map an action to a useful string for
#the welcome display...
WELCOME_MAP = {
INSTALL: "Installer",
UNINSTALL: "Uninstaller",
START: "Runner",
STOP: "Stopper",
}
#where we should get the config file...
STACK_CONFIG_DIR = "conf"
STACK_CFG_LOC = Shell.joinpths(STACK_CONFIG_DIR, "stack.ini")
#default subdirs of a components dir (valid unless overriden)
TRACE_DIR = "traces"
APP_DIR = "app"
CONFIG_DIR = "config"
#this regex is how we match python platform output to
#a known constant
KNOWN_OS = {
UBUNTU11: re.compile('Ubuntu(.*)oneiric', re.IGNORECASE),
RHEL6: re.compile('redhat-6\.(\d+)', re.IGNORECASE),
}
#the pip files that each component
#needs
PIP_MAP = {
NOVA:
[],
GLANCE:
[],
KEYSTONE:
[
Shell.joinpths(STACK_CONFIG_DIR, "pips", 'keystone.json'),
],
HORIZON:
[
Shell.joinpths(STACK_CONFIG_DIR, "pips", 'horizon.json'),
],
SWIFT:
[],
KEYSTONE_CLIENT:
[],
DB:
[],
RABBIT:
[],
}
#the pkg files that each component
#needs
PKG_MAP = {
NOVA:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", "nova.json"),
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", "general.json"),
],
NOVA_CLIENT:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", "nova-client.json"),
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", "general.json"),
],
GLANCE:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", "general.json"),
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", 'glance.json'),
],
KEYSTONE:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", "general.json"),
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", 'keystone.json'),
],
HORIZON:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", "general.json"),
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", 'horizon.json'),
],
SWIFT:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", "general.json"),
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", 'swift.json'),
],
KEYSTONE_CLIENT:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", "keystone-client.json"),
],
DB:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", 'db.json'),
],
RABBIT:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", 'rabbitmq.json'),
],
OPENSTACK_X:
[
Shell.joinpths(STACK_CONFIG_DIR, "pkgs", 'openstackx.json'),
],
}
LOG = Logger.getLogger("install.util")
def get_dependencies(component): def get_dependencies(component):
deps = COMPONENT_DEPENDENCIES.get(component) deps = constants.COMPONENT_DEPENDENCIES.get(component, list())
if(deps == None): return sorted(deps)
return list()
return list(deps)
def resolve_dependencies(components): def resolve_dependencies(components):
@@ -255,7 +75,7 @@ def execute_template(*cmds, **kargs):
stdin_full.append(piece) stdin_full.append(piece)
stdin = joinlinesep(*stdin_full) stdin = joinlinesep(*stdin_full)
root_run = cmdinfo.get('run_as_root', False) root_run = cmdinfo.get('run_as_root', False)
Shell.execute(*cmd_to_run, run_as_root=root_run, process_input=stdin, **kargs) sh.execute(*cmd_to_run, run_as_root=root_run, process_input=stdin, **kargs)
def fetch_dependencies(component, add=False): def fetch_dependencies(component, add=False):
@@ -273,8 +93,9 @@ def fetch_dependencies(component, add=False):
def prioritize_components(components): def prioritize_components(components):
#get the right component order (by priority) #get the right component order (by priority)
mporder = dict() mporder = dict()
priorities = constants.COMPONENT_NAMES_PRIORITY
for c in components: for c in components:
priority = NAMES_PRIORITY.get(c) priority = priorities.get(c)
if(priority == None): if(priority == None):
priority = sys.maxint priority = sys.maxint
mporder[c] = priority mporder[c] = priority
@@ -286,15 +107,15 @@ def prioritize_components(components):
def component_paths(root, component_name): def component_paths(root, component_name):
component_root = Shell.joinpths(root, component_name) component_root = sh.joinpths(root, component_name)
tracedir = Shell.joinpths(component_root, TRACE_DIR) tracedir = sh.joinpths(component_root, constants.COMPONENT_TRACE_DIR)
appdir = Shell.joinpths(component_root, APP_DIR) appdir = sh.joinpths(component_root, constants.COMPONENT_APP_DIR)
cfgdir = Shell.joinpths(component_root, CONFIG_DIR) cfgdir = sh.joinpths(component_root, constants.COMPONENT_CONFIG_DIR)
return (component_root, tracedir, appdir, cfgdir) return (component_root, tracedir, appdir, cfgdir)
def load_json(fn): def load_json(fn):
data = Shell.load_file(fn) data = sh.load_file(fn)
lines = data.splitlines() lines = data.splitlines()
new_lines = list() new_lines = list()
for line in lines: for line in lines:
@@ -313,14 +134,14 @@ def get_host_ip(cfg=None):
ip = cfg_ip ip = cfg_ip
if(ip == None): if(ip == None):
interfaces = get_interfaces() interfaces = get_interfaces()
def_info = interfaces.get(DEFAULT_NET_INTERFACE) def_info = interfaces.get(constants.DEFAULT_NET_INTERFACE)
if(def_info): if(def_info):
ipinfo = def_info.get(DEFAULT_NET_INTERFACE_IP_VERSION) ipinfo = def_info.get(constants.DEFAULT_NET_INTERFACE_IP_VERSION)
if(ipinfo): if(ipinfo):
ip = ipinfo.get('addr') ip = ipinfo.get('addr')
if(ip == None): if(ip == None):
msg = "Your host does not have an ip address!" msg = "Your host does not have an ip address!"
raise Exceptions.NoIpException(msg) raise excp.NoIpException(msg)
LOG.debug("Determined host ip to be: \"%s\"" % (ip)) LOG.debug("Determined host ip to be: \"%s\"" % (ip))
return ip return ip
@@ -333,20 +154,25 @@ def get_interfaces():
ip6 = interface_addresses.get(netifaces.AF_INET6) ip6 = interface_addresses.get(netifaces.AF_INET6)
if(ip6 and len(ip6)): if(ip6 and len(ip6)):
#just take the first #just take the first
interface_info[IPV6] = ip6[0] interface_info[constants.IPV6] = ip6[0]
ip4 = interface_addresses.get(netifaces.AF_INET) ip4 = interface_addresses.get(netifaces.AF_INET)
if(ip4 and len(ip4)): if(ip4 and len(ip4)):
#just take the first #just take the first
interface_info[IPV4] = ip4[0] interface_info[constants.IPV4] = ip4[0]
#there are others but this is good for now #there are others but this is good for now
interfaces[intfc] = interface_info interfaces[intfc] = interface_info
return interfaces return interfaces
def determine_os(): def determine_distro():
found_os = None
plt = platform.platform() plt = platform.platform()
for (known_os, pattern) in KNOWN_OS.items(): #ensure its a linux distro
(distname, version, id) = platform.linux_distribution()
if(not distname):
return (None, plt)
#attempt to match it to our platforms
found_os = None
for (known_os, pattern) in constants.KNOWN_DISTROS.items():
if(pattern.search(plt)): if(pattern.search(plt)):
found_os = known_os found_os = known_os
break break
@@ -356,7 +182,7 @@ def determine_os():
def get_pip_list(distro, component): def get_pip_list(distro, component):
LOG.info("Getting pip packages for distro %s and component %s." % (distro, component)) LOG.info("Getting pip packages for distro %s and component %s." % (distro, component))
all_pkgs = dict() all_pkgs = dict()
fns = PIP_MAP.get(component) fns = constants.PIP_MAP.get(component)
if(fns == None): if(fns == None):
return all_pkgs return all_pkgs
#load + merge them #load + merge them
@@ -375,7 +201,7 @@ def get_pip_list(distro, component):
def get_pkg_list(distro, component): def get_pkg_list(distro, component):
LOG.info("Getting packages for distro %s and component %s." % (distro, component)) LOG.info("Getting packages for distro %s and component %s." % (distro, component))
all_pkgs = dict() all_pkgs = dict()
fns = PKG_MAP.get(component) fns = constants.PKG_MAP.get(component)
if(fns == None): if(fns == None):
return all_pkgs return all_pkgs
#load + merge them #load + merge them
@@ -391,7 +217,7 @@ def get_pkg_list(distro, component):
for (infokey, infovalue) in pkginfo.items(): for (infokey, infovalue) in pkginfo.items():
#this is expected to be a list of cmd actions #this is expected to be a list of cmd actions
#so merge that accordingly #so merge that accordingly
if(infokey == PRE_INSTALL or infokey == POST_INSTALL): if(infokey == constants.PRE_INSTALL or infokey == constants.POST_INSTALL):
oldinstalllist = oldpkginfo.get(infokey) or [] oldinstalllist = oldpkginfo.get(infokey) or []
infovalue = oldinstalllist + infovalue infovalue = oldinstalllist + infovalue
newpkginfo[infokey] = infovalue newpkginfo[infokey] = infovalue
@@ -427,7 +253,7 @@ def param_replace(text, replacements, ignore_missing=False):
v = org v = org
elif(v == None and not ignore_missing): elif(v == None and not ignore_missing):
msg = "No replacement found for parameter %s" % (org) msg = "No replacement found for parameter %s" % (org)
raise Exceptions.NoReplacementException(msg) raise excp.NoReplacementException(msg)
else: else:
LOG.debug("Replacing [%s] with [%s]" % (org, str(v))) LOG.debug("Replacing [%s] with [%s]" % (org, str(v)))
return str(v) return str(v)
@@ -435,9 +261,11 @@ def param_replace(text, replacements, ignore_missing=False):
return PARAM_SUB_REGEX.sub(replacer, text) return PARAM_SUB_REGEX.sub(replacer, text)
def welcome(program_action): def welcome(program_action):
formatted_action = WELCOME_MAP.get(program_action) formatted_action = constants.WELCOME_MAP.get(program_action, "")
lower = "!%s v%s!" % (formatted_action.upper(), VERSION) ver_str = version.version_string()
lower = "!%s %s!" % (formatted_action.upper(), ver_str)
welcome = r''' welcome = r'''
___ ____ _____ _ _ ____ _____ _ ____ _ __ ___ ____ _____ _ _ ____ _____ _ ____ _ __
/ _ \| _ \| ____| \ | / ___|_ _|/ \ / ___| |/ / / _ \| _ \| ____| \ | / ___|_ _|/ \ / ___| |/ /
@@ -446,15 +274,15 @@ def welcome(program_action):
\___/|_| |_____|_| \_|____/ |_/_/ \_\____|_|\_\ \___/|_| |_____|_| \_|____/ |_/_/ \_\____|_|\_\
''' '''
#this seems needed, weird...
welcome = " " + welcome.strip() welcome = " " + welcome.strip()
lower_out = (" " * 17) + colored(DEVSTACK, 'green') + ": " + colored(lower, 'blue') max_len = 0
for line in welcome.splitlines():
if(len(line) > max_len):
max_len = len(line)
lower_out = colored(constants.PROG_NICE_NAME, 'green') + \
": " + colored(lower, 'blue')
center_len = (max_len + max_len/3)
lower_out = string.center(lower_out, center_len)
msg = welcome + os.linesep + lower_out msg = welcome + os.linesep + lower_out
print(msg) print(msg)
def rcf8222date():
return strftime("%a, %d %b %Y %H:%M:%S", localtime())
def fs_safe_date():
return strftime("%m_%d_%G-%H-%M-%S", localtime())

38
devstack/version.py Normal file
View File

@@ -0,0 +1,38 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# 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.
DEVSTACK = 'DEVSTACK'
DEVSTACK_VERSION = ['2012', '1']
YEAR, COUNT = DEVSTACK_VERSION
FINAL = False # May never be final ;-)
def canonical_version_string():
return '.'.join([YEAR, COUNT])
def version_string():
if FINAL:
return canonical_version_string()
else:
return '%s-dev' % (canonical_version_string(),)
def vcs_version_string():
return 'LOCALBRANCH:LOCALREVISION'
def version_string_with_vcs():
return '%s-%s' % (canonical_version_string(), vcs_version_string())

255
stack
View File

@@ -15,123 +15,38 @@
import os import os
import os.path import os.path
import sys
import re import re
import sys
#TODO is this needed? # This needs to happen immediately
sys.path.append("devstack") from devstack import log as logging
logging.setupLogging()
import Logger from devstack import actions
import Options from devstack import cfg
from devstack import constants
from devstack import date
from devstack import exceptions as excp
from devstack import opts
from devstack import shell as sh
from devstack import utils
from devstack.packaging import apt
from devstack.packaging import yum
#TODO fix these LOG = logging.getLogger("devstack")
from Util import (welcome, rcf8222date, determine_os,
prioritize_components, resolve_dependencies,
get_dependencies)
from Util import (NOVA, GLANCE, QUANTUM, SWIFT, KEYSTONE,
HORIZON, DB, RABBIT, KEYSTONE_CLIENT,
NOVA_CLIENT, OPENSTACK_X)
from Util import(INSTALL, UNINSTALL, START, STOP,
ACTIONS, COMPONENT_NAMES, NAMES_PRIORITY,
UBUNTU11, RHEL6,
STACK_CFG_LOC, DEVSTACK)
from Shell import (mkdir, joinpths, unlink)
from Exceptions import (NoTraceException)
import Glance PKGR_MAP = {
import Horizon constants.UBUNTU11: apt.AptPackager,
import Keystone constants.RHEL6: yum.YumPackager,
import Nova
import Quantum
import Config
import Swift
import Db
import Rabbit
import Config
import KeystoneClient
import NovaClient
import OpenstackX
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,
NOVA_CLIENT: NovaClient.NovaClientInstaller,
OPENSTACK_X: OpenstackX.OpenstackXInstaller,
},
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,
NOVA_CLIENT: NovaClient.NovaClientUninstaller,
OPENSTACK_X: OpenstackX.OpenstackXUninstaller,
},
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,
NOVA_CLIENT: NovaClient.NovaClientRuntime,
OPENSTACK_X: OpenstackX.OpenstackXRuntime,
},
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,
NOVA_CLIENT: NovaClient.NovaClientRuntime,
OPENSTACK_X: OpenstackX.OpenstackXRuntime,
},
} }
def get_package_manager_class(distro): def get_config():
klass = None cfg_fn = sh.canon_path(constants.STACK_CONFIG_LOCATION)
if(distro == UBUNTU11): LOG.info("Loading config from [%s]" % (cfg_fn))
#late import required config_instance = cfg.EnvConfigParser()
#TODO better way to do this? config_instance.read(cfg_fn)
from packaging import Apt return config_instance
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): def print_cfgs(cfg, action):
@@ -170,24 +85,34 @@ def print_cfgs(cfg, action):
map_print(db_dsns) map_print(db_dsns)
def runner(action_name, component_order, components_info, distro, root_dir, program_args): def pre_run_components(action_name, **kargs):
#have to make the root dir.... if(action_name == constants.INSTALL):
if(action_name == INSTALL): root_dir = kargs.get("root_dir")
mkdir(root_dir) if(root_dir):
pkg_manager_cls = get_package_manager_class(distro) sh.mkdir(root_dir)
pkg_manager = pkg_manager_cls(distro)
config = get_config(action_name)
def post_run_components(action_name, **kargs):
if(action_name == constants.UNINSTALL):
root_dir = kargs.get("root_dir")
if(root_dir):
sh.rmdir(root_dir)
def run_components(action_name, component_order, components_info, distro, root_dir, program_args):
pkg_manager = PKGR_MAP.get(distro)(distro)
config = get_config()
pre_run_components(action_name, root_dir=root_dir, pkg=pkg_manager, cfg=config)
LOG.info("Will %s [%s] (in that order) using root directory \"%s\"" % (action_name, ", ".join(component_order), root_dir)) LOG.info("Will %s [%s] (in that order) using root directory \"%s\"" % (action_name, ", ".join(component_order), root_dir))
results = list() results = list()
class_lookup = ACTION_CLASSES.get(action_name)
force = program_args.get('force', False) force = program_args.get('force', False)
for c in component_order: for c in component_order:
klass = actions.get_action_cls(action_name, c)
component_info = components_info.get(c) or list() component_info = components_info.get(c) or list()
klass = class_lookup.get(c)
instance = klass(components=set(component_order), distro=distro, instance = klass(components=set(component_order), distro=distro,
pkg=pkg_manager, cfg=config, root=root_dir, pkg=pkg_manager, cfg=config, root=root_dir,
component_info=component_info) component_info=component_info)
if(action_name == INSTALL): if(action_name == constants.INSTALL):
LOG.info("Downloading %s." % (c)) LOG.info("Downloading %s." % (c))
am_downloaded = instance.download() am_downloaded = instance.download()
LOG.info("Performed %s downloads." % (str(am_downloaded))) LOG.info("Performed %s downloads." % (str(am_downloaded)))
@@ -205,7 +130,7 @@ def runner(action_name, component_order, components_info, distro, root_dir, prog
results.append(trace) results.append(trace)
else: else:
LOG.info("Finished install of %s" % (c)) LOG.info("Finished install of %s" % (c))
elif(action_name == STOP): elif(action_name == constants.STOP):
try: try:
LOG.info("Stopping %s." % (c)) LOG.info("Stopping %s." % (c))
stop_am = instance.stop() stop_am = instance.stop()
@@ -216,7 +141,7 @@ def runner(action_name, component_order, components_info, distro, root_dir, prog
LOG.info("Passing on stopping %s since no trace file was found." % (c)) LOG.info("Passing on stopping %s since no trace file was found." % (c))
else: else:
raise raise
elif(action_name == START): elif(action_name == constants.START):
LOG.info("Starting %s." % (c)) LOG.info("Starting %s." % (c))
start_info = instance.start() start_info = instance.start()
if(type(start_info) == list): if(type(start_info) == list):
@@ -225,45 +150,34 @@ def runner(action_name, component_order, components_info, distro, root_dir, prog
elif(type(start_info) == int): elif(type(start_info) == int):
LOG.info("Started %s applications." % (str(start_info))) LOG.info("Started %s applications." % (str(start_info)))
LOG.info("Finished start of %s." % (c)) LOG.info("Finished start of %s." % (c))
elif(action_name == UNINSTALL): elif(action_name == constants.UNINSTALL):
try: try:
LOG.info("Unconfiguring %s." % (c)) LOG.info("Unconfiguring %s." % (c))
instance.unconfigure() instance.unconfigure()
LOG.info("Uninstalling %s." % (c)) LOG.info("Uninstalling %s." % (c))
instance.uninstall() instance.uninstall()
except NoTraceException, e: except excp.NoTraceException, e:
if(force): if(force):
LOG.info("Passing on uninstalling %s since no trace file was found." % (c)) LOG.info("Passing on uninstalling %s since no trace file was found." % (c))
else: else:
raise raise
#display any configs touched... #display any configs touched...
print_cfgs(config, action_name) print_cfgs(config, action_name)
#attempt to remove the root dir (might fail if not empty) #any post run actions go now
if(action_name == UNINSTALL): post_run_components(action_name, root_dir=root_dir)
try:
os.rmdir(root_dir)
except OSError, e:
pass
return results return results
def check_root(action, rootdir): def check_root(action, rootdir):
if(rootdir == None or len(rootdir) == 0): if(rootdir == None or len(rootdir) == 0):
return False return False
if(action == INSTALL): if(action == constants.INSTALL):
root_there = False if(sh.isdir(rootdir)):
if(os.path.isdir(rootdir)): sublisting = sh.listdir(rootdir)
sublisting = os.listdir(rootdir)
if(len(sublisting) != 0): 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)! "\ LOG.error("Root directory [%s] already exists (and it's not empty)! "\
"Please remove it or uninstall components!" % (rootdir)) "Please remove it or uninstall components!" % (rootdir))
return False return False
else:
return True
else:
return True return True
@@ -271,16 +185,16 @@ def parse_action(action):
if(action == None): if(action == None):
return None return None
action = action.strip().lower() action = action.strip().lower()
if(not (action in ACTIONS)): if(not (action in constants.ACTIONS)):
return None return None
return action return action
def parse_components(components, assume_all=False): def parse_components(components, assume_all=False):
#none provided #none provided, init it
if(components == None): if(components == None):
components = list() components = list()
# #this regex is used to extract a components options (if any) and its name
EXT_COMPONENT = re.compile(r"^\s*([\w-]+)(?:\((.*)\))?\s*$") EXT_COMPONENT = re.compile(r"^\s*([\w-]+)(?:\((.*)\))?\s*$")
adjusted_components = dict() adjusted_components = dict()
for c in components: for c in components:
@@ -288,8 +202,9 @@ def parse_components(components, assume_all=False):
if(mtch): if(mtch):
component_name = mtch.group(1) component_name = mtch.group(1)
component_name = component_name.lower().strip() component_name = component_name.lower().strip()
if(component_name not in COMPONENT_NAMES): if(component_name not in constants.COMPONENT_NAMES):
continue LOG.warn("Unknown component named %s" % (c))
else:
component_opts = mtch.group(2) component_opts = mtch.group(2)
components_opts_cleaned = list() components_opts_cleaned = list()
if(component_opts == None or len(component_opts) == 0): if(component_opts == None or len(component_opts) == 0):
@@ -301,11 +216,13 @@ def parse_components(components, assume_all=False):
if(len(cleaned_opt)): if(len(cleaned_opt)):
components_opts_cleaned.append(cleaned_opt) components_opts_cleaned.append(cleaned_opt)
adjusted_components[component_name] = components_opts_cleaned adjusted_components[component_name] = components_opts_cleaned
#should we adjust them?? else:
LOG.warn("Unparseable component %s" % (c))
#should we adjust them to be all the components?
if(len(adjusted_components) == 0): if(len(adjusted_components) == 0):
all_components = dict() all_components = dict()
if(assume_all): if(assume_all):
for c in (COMPONENT_NAMES): for c in constants.COMPONENT_NAMES:
all_components[c] = list() all_components[c] = list()
adjusted_components = all_components adjusted_components = all_components
return adjusted_components return adjusted_components
@@ -316,6 +233,7 @@ def check_python():
major = py_version[0] major = py_version[0]
minor = py_version[1] minor = py_version[1]
if(major < 2 or (major == 2 and minor < 6)): if(major < 2 or (major == 2 and minor < 6)):
LOG.error("Your python version is to old, please upgrade to >= 2.6!")
return False return False
if(major >= 3): if(major >= 3):
LOG.warn("%s has not been tested in python %s, use at your own risk!" % (DEVSTACK, major)) LOG.warn("%s has not been tested in python %s, use at your own risk!" % (DEVSTACK, major))
@@ -330,17 +248,17 @@ def run_list_only(prog, args):
left_show = list(components) left_show = list(components)
while(len(left_show) != 0): while(len(left_show) != 0):
c = left_show.pop() c = left_show.pop()
deps = get_dependencies(c) deps = utils.get_dependencies(c)
cname = "" dep_str = ""
if(len(deps) >= 1): dep_len = len(deps)
cname = "component" if(dep_len >= 1):
if(cname > 1): dep_str = "component"
cname += "s" if(dep_len > 1):
cname += ":" dep_str += "s"
if(len(deps) == 0): dep_str += ":"
cname = "no components." elif(dep_len == 0):
LOG.info("%s depends on %s" % (c, cname)) dep_str = "no components."
if(len(deps)): LOG.info("%s depends on %s" % (c, dep_str))
for d in deps: for d in deps:
LOG.info("\t%s" % (d)) LOG.info("\t%s" % (d))
shown.add(c) shown.add(c)
@@ -369,27 +287,26 @@ def run_action(prog, args):
LOG.info("Perhaps you should try %s --help" % (prog)) LOG.info("Perhaps you should try %s --help" % (prog))
return False return False
#ensure os/distro is known #ensure os/distro is known
(install_os, plt) = determine_os() (distro, platform) = utils.determine_distro()
if(install_os == None): if(distro == None):
LOG.error("Unsupported operating system/distro: %s" % (plt)) LOG.error("Unsupported platform: %s" % (platform))
return False return False
#start it #start it
welcome(action) utils.welcome(action)
#need to figure out dependencies for components (if any) #need to figure out dependencies for components (if any)
if(not ignore_deps): if(not ignore_deps):
new_components = resolve_dependencies(components.keys()) new_components = utils.resolve_dependencies(components.keys())
component_diff = new_components.difference(components.keys()) component_diff = new_components.difference(components.keys())
if(len(component_diff)): if(len(component_diff)):
LOG.info("Having to activate dependent components: [%s]" % (", ".join(component_diff))) LOG.info("Having to activate dependent components: [%s]" % (", ".join(component_diff)))
#TBD - probably need to do this better
for new_component in component_diff: for new_component in component_diff:
components[new_component] = list() components[new_component] = list()
#get the right component order (by priority) #get the right component order (by priority)
component_order = prioritize_components(components.keys()) component_order = utils.prioritize_components(components.keys())
#now do it! #now do it!
LOG.info("Starting action [%s] on %s for operating system/distro [%s]" % (action, rcf8222date(), install_os)) LOG.info("Starting action [%s] on %s for distro [%s]" % (action, date.rcf8222date(), distro))
resultList = runner(action, component_order, components, install_os, rootdir, args) resultList = run_components(action, component_order, components, distro, rootdir, args)
LOG.info("Finished action [%s] on %s" % (action, rcf8222date())) LOG.info("Finished action [%s] on %s" % (action, date.rcf8222date()))
if(resultList and len(resultList)): if(resultList and len(resultList)):
msg = "Check [%s] for traces of what happened." % (", ".join(resultList)) msg = "Check [%s] for traces of what happened." % (", ".join(resultList))
LOG.info(msg) LOG.info(msg)
@@ -398,13 +315,13 @@ def run_action(prog, args):
def main(): def main():
if(not check_python()): if(not check_python()):
LOG.error("Your python version is to old, please upgrade to >= 2.6!")
return 1 return 1
#parse and get it done! #parse and get it done!
args = Options.parse() args = opts.parse()
me = os.path.basename(sys.argv[0]) me = os.path.basename(sys.argv[0])
#figure out what to do #figure out what to do
only_list_deps = args.pop('list_deps', False) only_list_deps = args.pop('list_deps', False)
#now do it
rc_ok = False rc_ok = False
if(only_list_deps): if(only_list_deps):
rc_ok = run_list_only(me, args) rc_ok = run_list_only(me, args)