More updates and cleanups around making common install/uninstall/runtime code useful for all.

This commit is contained in:
Joshua Harlow 2012-01-13 18:39:05 -08:00
parent a0a272d71c
commit ffd99219ec
6 changed files with 373 additions and 413 deletions

@ -1,4 +1,5 @@
# http://docs.python.org/dev/library/logging.config.html
[default]
[loggers]
@ -24,3 +25,4 @@ keys=form01
format=%(levelname)s: @%(name)s : %(message)s
class=Logger.TermFormatter

@ -13,13 +13,24 @@
# License for the specific language governing permissions and limitations
# under the License.
from Util import (component_pths)
from Util import (component_pths,
get_pkg_list,
param_replace,
STACK_CONFIG_DIR)
import Downloader
import Logger
from Shell import (execute, mkdirslist, write_file,
load_file, joinpths, touch_file,
unlink, deldir)
from Trace import (TraceWriter, TraceReader,
touch_trace, parse_fn,
IN_TRACE, PY_TRACE, START_TRACE)
import Runner
from runners.Foreground import (ForegroundRunner)
"""
An abstraction that different components
can inherit from to perform or basic install
and configure and uninstall actions.
"""
LOG = Logger.getLogger("install.component")
PY_INSTALL = ['python', 'setup.py', 'develop']
PY_UNINSTALL = ['python', 'setup.py', 'develop', '--uninstall']
class ComponentBase():
@ -34,6 +45,8 @@ class ComponentBase():
self.tracedir = pths.get("trace_dir")
self.appdir = pths.get("app_dir")
self.cfgdir = pths.get('config_dir')
self.component_name = component_name
#
#the following are just interfaces...
@ -71,3 +84,264 @@ class RuntimeComponent():
def restart(self):
raise NotImplementedError()
# useful impls
class PkgInstallComponent(ComponentBase, InstallComponent):
def __init__(self, component_name, *args, **kargs):
ComponentBase.__init__(self, component_name, *args, **kargs)
self.tracewriter = TraceWriter(self.tracedir, IN_TRACE)
def _get_download_location(self):
raise NotImplementedError()
def download(self):
#find out where to get it
(uri, branch) = self._get_download_location()
if(uri):
#now get it
dirsmade = Downloader.download(self.appdir, uri, branch)
#this trace isn't used yet but could be
self.tracewriter.downloaded(self.appdir, uri)
#this trace is used to remove the dirs created
self.tracewriter.dir_made(*dirsmade)
return self.tracedir
def _get_param_map(self, fn=None):
return None
def _do_pkg_install(self):
pkgs = get_pkg_list(self.distro, self.component_name)
if(len(pkgs)):
pkgnames = sorted(pkgs.keys())
LOG.debug("Installing packages %s" % (", ".join(pkgnames)))
mp = self._get_param_map()
#run pre, install, then post
self.packager.pre_install(pkgs, mp)
self.packager.install_batch(pkgs)
self.packager.post_install(pkgs, mp)
#add trace used to remove the pkgs
for name in pkgnames:
self.tracewriter.package_install(name, pkgs.get(name))
def install(self):
self._do_pkg_install()
return self.tracedir
def _get_config_files(self):
return list()
def _config_adjust(fn, contents):
return contents
def configure(self):
dirsmade = mkdirslist(self.cfgdir)
self.tracewriter.dir_made(*dirsmade)
configs = self._get_config_files()
if(configs and len(configs)):
for fn in configs:
parameters = self._get_param_map(fn)
sourcefn = joinpths(STACK_CONFIG_DIR, self.component_name, fn)
tgtfn = joinpths(self.cfgdir, fn)
LOG.info("Configuring template file %s" % (sourcefn))
contents = load_file(sourcefn)
LOG.info("Replacing parameters in file %s" % (sourcefn))
LOG.debug("Replacements = %s" % (parameters))
contents = param_replace(contents, parameters)
LOG.debug("Applying side-effects of param replacement for template %s" % (sourcefn))
contents = self._config_adjust(contents, fn)
LOG.info("Writing configuration file %s" % (tgtfn))
write_file(tgtfn, contents)
#this trace is used to remove the files configured
self.tracewriter.cfg_write(tgtfn)
return self.tracedir
class PythonInstallComponent(PkgInstallComponent):
def __init__(self, component_name, *args, **kargs):
PkgInstallComponent.__init__(self, component_name, *args, **kargs)
def _python_install(self):
pips = get_pip_list(self.distro, self.component_name)
#install any need pip items
if(len(pips)):
Pip.install(pips)
for name in pips.keys():
self.tracewriter.pip_install(name, pips.get(name))
#do the actual python install
dirsmade = mkdirslist(self.tracedir)
self.tracewriter.dir_made(*dirsmade)
recordwhere = touch_trace(self.tracedir, PY_TRACE)
self.tracewriter.py_install(recordwhere)
(sysout, stderr) = execute(*PY_INSTALL, cwd=self.appdir, run_as_root=True)
write_file(recordwhere, sysout)
def install(self):
self._do_pkg_install()
self._python_install()
return self.tracedir
class PkgUninstallComponent(ComponentBase, UninstallComponent):
def __init__(self, component_name, *args, **kargs):
ComponentBase.__init__(self, component_name, *args, **kargs)
self.tracereader = TraceReader(self.tracedir, IN_TRACE)
def unconfigure(self):
self._unconfigure_files()
def _unconfigure_files(self):
cfgfiles = self.tracereader.files_configured()
if(len(cfgfiles)):
LOG.info("Removing %s configuration files" % (len(cfgfiles)))
for fn in cfgfiles:
if(len(fn)):
unlink(fn)
LOG.info("Removed %s" % (fn))
def uninstall(self):
self._uninstall_pkgs()
self._uninstall_touched_files()
self._uninstall_dirs()
def _uninstall_pkgs(self):
pkgsfull = self.tracereader.packages_installed()
if(len(pkgsfull)):
LOG.info("Potentially removing %s packages" % (len(pkgsfull)))
self.packager.remove_batch(pkgsfull)
def _uninstall_touched_files(self):
filestouched = self.tracereader.files_touched()
if(len(filestouched)):
LOG.info("Removing %s touched files" % (len(filestouched)))
for fn in filestouched:
if(len(fn)):
unlink(fn)
LOG.info("Removed %s" % (fn))
def _uninstall_dirs(self):
dirsmade = self.tracereader.dirs_made()
if(len(dirsmade)):
LOG.info("Removing %s created directories" % (len(dirsmade)))
for dirname in dirsmade:
deldir(dirname)
LOG.info("Removed %s" % (dirname))
class PythonUninstallComponent(PkgUninstallComponent):
def __init__(self, component_name, *args, **kargs):
PkgUninstallComponent.__init__(self, component_name, *args, **kargs)
def uninstall(self):
self._uninstall_pkgs()
self._uninstall_touched_files()
self._uninstall_python()
self._uninstall_dirs()
def _uninstall_python(self):
pylisting = self.tracereader.py_listing()
if(pylisting and len(pylisting)):
execute(*PY_UNINSTALL, cwd=self.appdir, run_as_root=True)
class ProgramRuntime(ComponentBase, RuntimeComponent):
def __init__(self, component_name, *args, **kargs):
ComponentBase.__init__(self, component_name, *args, **kargs)
self.foreground = kargs.get("foreground", True)
self.tracereader = TraceReader(self.tracedir, IN_TRACE)
self.tracewriter = TraceWriter(self.tracedir, START_TRACE)
self.starttracereader = TraceReader(self.tracedir, START_TRACE)
def _getstartercls(self):
if(self.foreground):
return ForegroundRunner
else:
raise NotImplementedError("Can not yet start in non-foreground mode")
def _getstoppercls(self, starttype):
if(starttype == Foreground.RUN_TYPE):
return ForegroundRunner
else:
raise NotImplementedError("Can not yet stop type [%s]" % (starttype))
def _was_installed(self):
pkgsinstalled = self.tracereader.packages_installed()
if(len(pkgsinstalled) == 0):
return False
def _get_apps_to_start(self):
raise NotImplementedError()
def _get_app_options(self, app, params):
return list()
def _get_param_map(self, app=None):
replacements = dict()
replacements['ROOT'] = self.appdir
return replacements
def start(self):
#ensure it was installed
if(not self._was_installed()):
msg = "Can not start %s since it was not installed" % (self.component_name)
raise StartException(msg)
#select how we are going to start it
startercls = self._getstartercls()
starter = startercls()
#start all apps
#this fns list will have info about what was started
fns = list()
apps = self._get_apps_to_start()
for app in apps:
#adjust the program options now that we have real locations
params = self._get_param_map(app)
program_opts = self._get_app_options(app, params)
LOG.info("Starting %s with options [%s]" % (app, ", ".join(program_opts)))
#start it with the given settings
fn = starter.start(app, app, *program_opts, app_dir=self.appdir, trace_dir=self.tracedir)
if(fn and len(fn)):
fns.append(fn)
LOG.info("Started %s, details are in %s" % (app, fn))
#this trace is used to locate details about what to stop
self.tracewriter.started_info(app, fn)
else:
LOG.info("Started %s" % (app))
return fns
def stop(self):
#ensure it was installed
if(not self._was_installed()):
msg = "Can not stop %s since it was not installed" % (self.component_name)
raise StopException(msg)
#we can only stop what has a started trace
start_traces = self.starttracereader.apps_started()
killedam = 0
for mp in start_traces:
#extract the apps name and where its trace is
fn = mp.get('trace_fn')
name = mp.get('name')
#missing some key info, skip it
if(fn == None or name == None):
continue
#figure out which class will stop it
contents = parse_fn(fn)
killcls = None
for (cmd, action) in contents:
if(cmd == Runner.RUN_TYPE):
killcls = self._getstoppercls(action)
break
#did we find a class that can do it?
if(killcls):
#we can try to stop it
LOG.info("Stopping %s with %s in %s" % (name, runtype, self.tracedir))
#create an instance of the killer class and attempt to stop
killer = killcls()
killer.stop(name, trace_dir=self.tracedir)
killedam += 1
#if we got rid of them all get rid of the trace
if(killedam == len(start_traces)):
fn = self.starttracereader.trace_fn
LOG.info("Deleting trace file %s" % (fn))
unlink(fn)

@ -17,17 +17,16 @@ import re
import Logger
import Packager
from Component import (ComponentBase, RuntimeComponent,
UninstallComponent, InstallComponent)
from Component import (PkgUninstallComponent, PkgInstallComponent,
ComponentBase, RuntimeComponent)
from Util import (DB,
get_pkg_list, get_host_ip,
get_host_ip,
execute_template)
from Exceptions import (StartException, StopException,
StatusException, RestartException)
from Trace import (TraceWriter, TraceReader,
IN_TRACE)
from Shell import (mkdirslist, execute, deldir,
load_file, write_file)
from Shell import (execute)
from Trace import (TraceReader,
IN_TRACE)
LOG = Logger.getLogger("install.db")
TYPE = DB
@ -56,45 +55,20 @@ DB_ACTIONS = {
BASE_ERROR = 'Currently we do not know how to %s for database type [%s]'
class DBUninstaller(ComponentBase, UninstallComponent):
class DBUninstaller(PkgUninstallComponent):
def __init__(self, *args, **kargs):
ComponentBase.__init__(self, TYPE, *args, **kargs)
self.tracereader = TraceReader(self.tracedir, IN_TRACE)
PkgUninstallComponent.__init__(self, TYPE, *args, **kargs)
class DBInstaller(PkgInstallComponent):
def __init__(self, *args, **kargs):
PkgInstallComponent.__init__(self, TYPE, *args, **kargs)
self.runtime = DBRuntime(*args, **kargs)
def unconfigure(self):
#nothing to unconfigure, we are just a pkg
pass
def _get_download_location(self):
return (None, None)
def uninstall(self):
#clean out removeable packages
pkgsfull = self.tracereader.packages_installed()
if(len(pkgsfull)):
LOG.info("Potentially removing %s packages" % (len(pkgsfull)))
self.packager.remove_batch(pkgsfull)
dirsmade = self.tracereader.dirs_made()
if(len(dirsmade)):
LOG.info("Removing %s created directories" % (len(dirsmade)))
for dirname in dirsmade:
deldir(dirname)
LOG.info("Removed %s" % (dirname))
class DBInstaller(ComponentBase, InstallComponent):
def __init__(self, *args, **kargs):
ComponentBase.__init__(self, TYPE, *args, **kargs)
self.tracewriter = TraceWriter(self.tracedir, IN_TRACE)
self.runtime = DBRuntime(*args, **kargs)
def download(self):
#nothing to download, we are just a pkg
pass
def configure(self):
#nothing to configure, we are just a pkg
pass
def _get_install_params(self):
def _get_param_map(self, fn=None):
#this dictionary will be used for parameter replacement
#in pre-install and post-install sections
out = dict()
@ -106,20 +80,15 @@ class DBInstaller(ComponentBase, InstallComponent):
out['HOST_IP'] = hostip
return out
def _do_install(self, pkgs):
mp = self._get_install_params()
self.packager.pre_install(pkgs, mp)
self.packager.install_batch(pkgs)
self.packager.post_install(pkgs, mp)
#
def install(self):
PkgInstallComponent.install(self)
#extra actions to ensure we are granted access
#
dbtype = self.cfg.get("db", "type")
dbactions = DB_ACTIONS.get(dbtype)
if(dbactions and dbactions.get('grant_all')):
#update the DB to give user 'USER'@'%' full control of the all databases:
grant_cmd = dbactions.get('grant_all')
params = mp
params = self._get_param_map()
cmds = list()
cmds.append({
'cmd': grant_cmd,
@ -128,25 +97,13 @@ class DBInstaller(ComponentBase, InstallComponent):
#shell seems to be needed here
#since python escapes this to much...
execute_template(*cmds, params=params, shell=True)
#
#special mysql actions
if(dbactions and dbtype == MYSQL):
cmd = dbactions.get('host_adjust')
if(cmd):
execute(*cmd, run_as_root=True, shell=True)
def install(self):
#just install the pkgs
pkgs = get_pkg_list(self.distro, TYPE)
pkgnames = sorted(pkgs.keys())
LOG.info("Installing packages %s" % (", ".join(pkgnames)))
self._do_install(pkgs)
#add trace used to remove the pkgs
for name in pkgnames:
self.tracewriter.package_install(name, pkgs.get(name))
#restart it to make sure all good
self.runtime.restart()
return self.tracedir
class DBRuntime(ComponentBase, RuntimeComponent):

@ -17,24 +17,19 @@ import json
import os.path
import Logger
from Component import (ComponentBase, RuntimeComponent,
UninstallComponent, InstallComponent)
from Component import (PythonUninstallComponent,
PythonInstallComponent,
ProgramRuntime)
import Shell
import Util
from Trace import (TraceWriter, TraceReader,
IN_TRACE, START_TRACE, PY_TRACE,
parse_fn, touch_trace)
import Downloader
import Packager
import Runner
from runners.Foreground import (ForegroundRunner)
from Util import (GLANCE,
STACK_CONFIG_DIR,
get_pkg_list, get_host_ip,
get_host_ip,
param_replace, get_dbdsn,
)
from Shell import (execute, deldir, mkdirslist, unlink,
joinpths, load_file, write_file, touch_file)
from Shell import (deldir, mkdirslist, unlink,
joinpths, touch_file)
from Exceptions import (StopException, StartException, InstallException)
LOG = Logger.getLogger("install.glance")
@ -46,225 +41,60 @@ REG_CONF = "glance-registry.conf"
CONFIGS = [API_CONF, REG_CONF]
DB_NAME = "glance"
#why doesn't --record do anything??
PY_INSTALL = ['python', 'setup.py', 'develop']
PY_UNINSTALL = ['python', 'setup.py', 'develop', '--uninstall']
#what to start
APPS_TO_START = ['glance-api', 'glance-registry']
APP_OPTIONS = {
'glance-api': ['--config-file', joinpths('%ROOT%', "etc", API_CONF)],
'glance-registry': ['--config-file', joinpths('%ROOT%', "etc", REG_CONF)]
}
CONFIG_ACTUAL_DIR = 'etc'
class GlanceBase(ComponentBase):
class GlanceUninstaller(PythonUninstallComponent):
def __init__(self, *args, **kargs):
ComponentBase.__init__(self, TYPE, *args, **kargs)
#note, not config that parent sets
self.cfgdir = joinpths(self.appdir, "etc")
PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR)
class GlanceUninstaller(GlanceBase, UninstallComponent):
class GlanceRuntime(ProgramRuntime):
def __init__(self, *args, **kargs):
GlanceBase.__init__(self, *args, **kargs)
self.tracereader = TraceReader(self.tracedir, IN_TRACE)
ProgramRuntime.__init__(self, TYPE, *args, **kargs)
self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR)
def unconfigure(self):
#get rid of all files configured
cfgfiles = self.tracereader.files_configured()
if(len(cfgfiles)):
LOG.info("Removing %s configuration files" % (len(cfgfiles)))
for fn in cfgfiles:
if(len(fn)):
unlink(fn)
LOG.info("Removed %s" % (fn))
def uninstall(self):
#clean out removeable packages
pkgsfull = self.tracereader.packages_installed()
if(len(pkgsfull)):
LOG.info("Potentially removing %s packages" % (len(pkgsfull)))
self.packager.remove_batch(pkgsfull)
#clean out files touched
filestouched = self.tracereader.files_touched()
if(len(filestouched)):
LOG.info("Removing %s touched files" % (len(filestouched)))
for fn in filestouched:
if(len(fn)):
unlink(fn)
LOG.info("Removed %s" % (fn))
#undevelop python???
#how should this be done??
def _was_installed(self):
pres = ProgramRuntime._was_installed(self)
if(pres == False):
return False
pylisting = self.tracereader.py_listing()
if(pylisting != None):
execute(*PY_UNINSTALL, cwd=self.appdir, run_as_root=True)
#clean out dirs created
dirsmade = self.tracereader.dirs_made()
if(len(dirsmade)):
LOG.info("Removing %s created directories" % (len(dirsmade)))
for dirname in dirsmade:
deldir(dirname)
LOG.info("Removed %s" % (dirname))
if(pylisting and len(pylisting)):
return True
return False
def _get_apps_to_start(self):
raise list(APPS_TO_START)
class GlanceRuntime(GlanceBase, RuntimeComponent):
def __init__(self, *args, **kargs):
GlanceBase.__init__(self, *args, **kargs)
self.foreground = kargs.get("foreground", True)
self.tracereader = TraceReader(self.tracedir, IN_TRACE)
self.tracewriter = TraceWriter(self.tracedir, START_TRACE)
self.starttracereader = TraceReader(self.tracedir, START_TRACE)
def _getstartercls(self):
if(self.foreground):
return ForegroundRunner
else:
raise NotImplementedError("Can not yet start in non-foreground mode")
def _getstoppercls(self, starttype):
if(starttype == Foreground.RUN_TYPE):
return ForegroundRunner
else:
raise NotImplementedError("Can not yet stop type [%s]" % (starttype))
def start(self):
#ensure it was installed
pylisting = self.tracereader.py_listing()
if(len(pylisting) == 0):
msg = "Can not start %s since it was not installed" % (TYPE)
raise StartException(msg)
#select how we are going to start it
startercls = self._getstoppercls()
starter = startercls()
#start all apps
#this fns list will have info about what was started
fns = list()
#this dictionary will be used to adjust our start templates with actual values
replacements = dict()
replacements['ROOT'] = self.appdir
for app in APPS_TO_START:
#adjust the program options now that we have real locations
program_opts = []
def _get_app_options(self, app, params):
opts = list()
if(app in APP_OPTIONS):
for opt in APP_OPTIONS.get(app):
program_opts.append(param_replace(opt, replacements))
LOG.info("Starting %s with options [%s]" % (app, ", ".join(program_opts)))
#start it with the given settings
fn = starter.start(app, app, *program_opts, app_dir=self.appdir, trace_dir=self.tracedir)
if(fn):
fns.append(fn)
LOG.info("Started %s, details are in %s" % (app, fn))
#this trace is used to locate details about what to stop
self.tracewriter.started_info(app, fn)
else:
LOG.info("Started %s" % (app))
return fns
def stop(self):
#ensure it was installed
pylisting = self.tracereader.py_listing()
if(pylisting == None or len(pylisting) == 0):
msg = "Can not start %s since it was not installed" % (TYPE)
raise StopException(msg)
#we can only stop what has a started trace
start_traces = self.starttracereader.apps_started()
killedam = 0
for mp in start_traces:
#extract the apps name and where its trace is
fn = mp.get('trace_fn')
name = mp.get('name')
#missing some key info, skip it
if(fn == None or name == None):
continue
#figure out which class will stop it
contents = parse_fn(fn)
killcls = None
for (cmd, action) in contents:
if(cmd == Runner.RUN_TYPE):
killcls = self._getstoppercls(action)
break
#did we find a class that can do it?
if(killcls):
#we can try to stop it
LOG.info("Stopping %s with %s in %s" % (name, runtype, self.tracedir))
#create an instance of the killer class and attempt to stop
killer = killcls()
killer.stop(name, trace_dir=self.tracedir)
killedam += 1
#if we got rid of them all get rid of the trace
if(killedam == len(start_traces)):
fn = self.starttracereader.trace_fn
LOG.info("Deleting trace file %s" % (fn))
unlink(fn)
class GlanceInstaller(GlanceBase, InstallComponent):
opts.append(param_replace(opt, params))
return opts
class GlanceInstaller(PythonInstallComponent):
def __init__(self, *args, **kargs):
GlanceBase.__init__(self, *args, **kargs)
PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.gitloc = self.cfg.get("git", "glance_repo")
self.brch = self.cfg.get("git", "glance_branch")
self.tracewriter = TraceWriter(self.tracedir, IN_TRACE)
self.cfgdir = joinpths(self.appdir, CONFIG_ACTUAL_DIR)
def download(self):
dirsmade = Downloader.download(self.appdir, self.gitloc, self.brch)
#this trace isn't used yet but could be
self.tracewriter.downloaded(self.appdir, self.gitloc)
#this trace is used to remove the dirs created
self.tracewriter.dir_made(*dirsmade)
return self.tracedir
def _get_download_location(self):
uri = self.gitloc
branch = self.brch
return (uri, branch)
def _do_install(self, pkgs):
mp = self._get_param_map()
self.packager.pre_install(pkgs, mp)
self.packager.install_batch(pkgs)
self.packager.post_install(pkgs, mp)
def install(self):
#get all the packages for glance for the specified distro
pkgs = get_pkg_list(self.distro, TYPE)
pkgnames = sorted(pkgs.keys())
LOG.debug("Installing packages %s" % (", ".join(pkgnames)))
self._do_install(pkgs)
#add trace used to remove the pkgs
for name in pkgnames:
self.tracewriter.package_install(name, pkgs.get(name))
#make a directory for the python trace file (if its not already there)
dirsmade = mkdirslist(self.tracedir)
#this trace is used to remove the dirs created
self.tracewriter.dir_made(*dirsmade)
recordwhere = touch_trace(self.tracedir, PY_TRACE)
#this trace is used to remove the trace created
self.tracewriter.py_install(recordwhere)
(sysout, stderr) = execute(*PY_INSTALL, cwd=self.appdir, run_as_root=True)
write_file(recordwhere, sysout)
return self.tracedir
def configure(self):
dirsmade = mkdirslist(self.cfgdir)
#this trace is used to remove the dirs created
self.tracewriter.dir_made(*dirsmade)
parameters = self._get_param_map()
for fn in CONFIGS:
#go through each config in devstack (which is really a template)
#and adjust that template to have real values and then go through
#the resultant config file and perform and adjustments (directory creation...)
#and then write that to the glance configuration directory.
sourcefn = joinpths(STACK_CONFIG_DIR, TYPE, fn)
tgtfn = joinpths(self.cfgdir, fn)
LOG.info("Configuring template file %s" % (sourcefn))
contents = load_file(sourcefn)
LOG.info("Replacing parameters in file %s" % (sourcefn))
LOG.debug("Replacements = %s" % (parameters))
contents = param_replace(contents, parameters)
LOG.debug("Applying side-effects of param replacement for template %s" % (sourcefn))
self._config_apply(contents, fn)
LOG.info("Writing configuration file %s" % (tgtfn))
write_file(tgtfn, contents)
#this trace is used to remove the files configured
self.tracewriter.cfg_write(tgtfn)
return self.tracedir
def _config_apply(self, contents, fn):
def _get_config_files(self):
return list(CONFIGS)
def _config_adjust(self, contents, fn):
lines = contents.splitlines()
for line in lines:
cleaned = line.strip()
@ -308,8 +138,9 @@ class GlanceInstaller(GlanceBase, InstallComponent):
dirsmade = mkdirslist(val)
#this trace is used to remove the dirs created
self.tracewriter.dir_made(*dirsmade)
return contents
def _get_param_map(self):
def _get_param_map(self, fn=None):
#this dict will be used to fill in the configuration
#params with actual values
mp = dict()

@ -18,175 +18,68 @@ import os.path
import Pip
from Util import (KEYSTONE,
CONFIG_DIR, STACK_CONFIG_DIR,
CONFIG_DIR,
NOVA, GLANCE, SWIFT,
get_pkg_list, get_pip_list,
get_dbdsn,
param_replace, get_host_ip,
get_host_ip,
execute_template)
import Logger
import Downloader
import Db
from Trace import (TraceWriter, TraceReader,
touch_trace,
IN_TRACE, PY_TRACE)
from Shell import (execute, mkdirslist, write_file,
load_file, joinpths, touch_file,
unlink, deldir)
from Component import (ComponentBase, RuntimeComponent,
UninstallComponent, InstallComponent)
from Component import (PythonUninstallComponent, PythonInstallComponent, ProgramRuntime)
from Shell import (mkdirslist, unlink, touch_file, joinpths)
LOG = Logger.getLogger("install.keystone")
TYPE = KEYSTONE
PY_INSTALL = ['python', 'setup.py', 'develop']
PY_UNINSTALL = ['python', 'setup.py', 'develop', '--uninstall']
ROOT_CONF = "keystone.conf"
CONFIGS = [ROOT_CONF]
BIN_DIR = "bin"
DB_NAME = "keystone"
class KeystoneBase(ComponentBase):
class KeystoneUninstaller(PythonUninstallComponent):
def __init__(self, *args, **kargs):
ComponentBase.__init__(self, TYPE, *args, **kargs)
PythonUninstallComponent.__init__(self, TYPE, *args, **kargs)
self.cfgdir = joinpths(self.appdir, CONFIG_DIR)
self.bindir = joinpths(self.appdir, BIN_DIR)
class KeystoneUninstaller(KeystoneBase, UninstallComponent):
class KeystoneInstaller(PythonInstallComponent):
def __init__(self, *args, **kargs):
KeystoneBase.__init__(self, *args, **kargs)
self.tracereader = TraceReader(self.tracedir, IN_TRACE)
def unconfigure(self):
#get rid of all files configured
cfgfiles = self.tracereader.files_configured()
if(len(cfgfiles)):
LOG.info("Removing %s configuration files" % (len(cfgfiles)))
for fn in cfgfiles:
if(len(fn)):
unlink(fn)
LOG.info("Removed %s" % (fn))
def uninstall(self):
#clean out removeable packages
pkgsfull = self.tracereader.packages_installed()
if(len(pkgsfull)):
LOG.info("Potentially removing %s packages" % (len(pkgsfull)))
self.packager.remove_batch(pkgsfull)
#clean out pips
pipsfull = self.tracereader.pips_installed()
if(len(pipsfull)):
LOG.info("Potentially removing %s pips" % (len(pipsfull)))
Pip.uninstall(pipsfull)
#clean out files touched
filestouched = self.tracereader.files_touched()
if(len(filestouched)):
LOG.info("Removing %s touched files" % (len(filestouched)))
for fn in filestouched:
if(len(fn)):
unlink(fn)
LOG.info("Removed %s" % (fn))
#undevelop python???
#how should this be done??
pylisting = self.tracereader.py_listing()
if(pylisting != None):
execute(*PY_UNINSTALL, cwd=self.appdir, run_as_root=True)
#clean out dirs created
dirsmade = self.tracereader.dirs_made()
if(len(dirsmade)):
LOG.info("Removing %s created directories" % (len(dirsmade)))
for dirname in dirsmade:
deldir(dirname)
LOG.info("Removed %s" % (dirname))
class KeystoneInstaller(KeystoneBase, InstallComponent):
def __init__(self, *args, **kargs):
KeystoneBase.__init__(self, *args, **kargs)
PythonInstallComponent.__init__(self, TYPE, *args, **kargs)
self.gitloc = self.cfg.get("git", "keystone_repo")
self.brch = self.cfg.get("git", "keystone_branch")
self.tracewriter = TraceWriter(self.tracedir, IN_TRACE)
self.cfgdir = joinpths(self.appdir, CONFIG_DIR)
self.bindir = joinpths(self.appdir, BIN_DIR)
def download(self):
dirsmade = Downloader.download(self.appdir, self.gitloc, self.brch)
#this trace isn't used yet but could be
self.tracewriter.downloaded(self.appdir, self.gitloc)
#this trace is used to remove the dirs created
self.tracewriter.dir_made(*dirsmade)
return self.tracedir
def _do_install(self, pkgs):
LOG.debug("Installing packages %s" % (", ".join(pkgs.keys())))
self.packager.pre_install(pkgs)
self.packager.install_batch(pkgs)
self.packager.post_install(pkgs)
def _get_download_location(self):
uri = self.gitloc
branch = self.brch
return (uri, branch)
def install(self):
#install needed pkgs
pkgs = get_pkg_list(self.distro, TYPE)
if(len(pkgs)):
#do the install
self._do_install(pkgs)
#this trace is used to remove the pkgs installed
for name in pkgs.keys():
self.tracewriter.package_install(name, pkgs.get(name))
#install the needed pips
pips = get_pip_list(self.distro, TYPE)
if(len(pips)):
Pip.install(pips)
#this trace is used to remove the pips installed
for name in pips.keys():
self.tracewriter.pip_install(name, pips.get(name))
#this trace is used to remove the dirs created
dirsmade = mkdirslist(self.tracedir)
self.tracewriter.dir_made(*dirsmade)
recordwhere = touch_trace(self.tracedir, PY_TRACE)
#this trace is used to remove the trace created
self.tracewriter.py_install(recordwhere)
(sysout, stderr) = execute(*PY_INSTALL, cwd=self.appdir, run_as_root=True)
write_file(recordwhere, sysout)
PythonInstallComponent.install(self)
#adjust db
self._setup_db()
#setup any data
self._setup_data()
return self.tracedir
def configure(self):
dirsmade = mkdirslist(self.cfgdir)
self.tracewriter.dir_made(*dirsmade)
for fn in CONFIGS:
sourcefn = joinpths(STACK_CONFIG_DIR, TYPE, fn)
tgtfn = joinpths(self.cfgdir, fn)
LOG.info("Configuring template file %s" % (sourcefn))
contents = load_file(sourcefn)
pmap = self._get_param_map()
LOG.info("Replacing parameters in file %s" % (sourcefn))
LOG.debug("Replacements = %s" % (pmap))
contents = param_replace(contents, pmap)
LOG.debug("Applying side-effects of param replacement for template %s" % (sourcefn))
self._config_apply(contents, fn)
LOG.info("Writing configuration file %s" % (tgtfn))
write_file(tgtfn, contents)
#this trace is used to remove the files configured
self.tracewriter.cfg_write(tgtfn)
return self.tracedir
def _get_config_files(self):
return list(CONFIGS)
def _setup_db(self):
Db.drop_db(self.cfg, DB_NAME)
Db.create_db(self.cfg, DB_NAME)
def _setup_data(self):
params = self._get_param_map()
params = self._get_param_map(None)
cmds = _keystone_setup_cmds(self.othercomponents)
execute_template(*cmds, params=params, ignore_missing=True)
def _config_apply(self, contents, fn):
def _config_adjust(self, contents, fn):
lines = contents.splitlines()
for line in lines:
cleaned = line.strip()
if(len(cleaned) == 0 or cleaned[0] == '#' or cleaned[0] == '['):
if(len(cleaned) == 0 or
cleaned[0] == '#' or cleaned[0] == '['):
#not useful to examine these
continue
pieces = cleaned.split("=", 1)
@ -208,8 +101,9 @@ class KeystoneInstaller(KeystoneBase, InstallComponent):
unlink(val)
touch_file(val)
self.tracewriter.file_touched(val)
return contents
def _get_param_map(self):
def _get_param_map(self, fn=None):
#these be used to fill in the configuration/cmds +
#params with actual values
mp = dict()
@ -223,9 +117,11 @@ class KeystoneInstaller(KeystoneBase, InstallComponent):
return mp
class KeystoneRuntime(KeystoneBase, RuntimeComponent):
class KeystoneRuntime(ProgramRuntime):
def __init__(self, *args, **kargs):
KeystoneBase.__init__(self, *args, **kargs)
ProgramRuntime.__init__(self, TYPE, *args, **kargs)
self.cfgdir = joinpths(self.appdir, CONFIG_DIR)
self.bindir = joinpths(self.appdir, BIN_DIR)
# Keystone setup commands are the the following

8
stack

@ -150,15 +150,15 @@ def start(components, distro, rootdir, args):
def print_cfgs(cfg, action):
pws = dict(cfg.pws)
configs_fetched = dict(cfg.configs_fetched)
LOG.info("After %s your passwords are:" % (action))
LOG.info("After %s your fetched/generated passwords are:" % (action))
for (pwkey, val) in pws.items():
LOG.info("%s = %s" % (pwkey, val))
LOG.info("After %s your other configuration is:" % (action))
LOG.info("\t%s = %s" % (pwkey, val))
LOG.info("After %s your other fetched configuration was:" % (action))
for (key, val) in configs_fetched.items():
if(key in pws):
#already shown
continue
LOG.info("%s = %s" % (key, val))
LOG.info("\t%s = %s" % (key, val))
def install(components, distro, rootdir, args):