More updates and cleanups around making common install/uninstall/runtime code useful for all.
This commit is contained in:
parent
a0a272d71c
commit
ffd99219ec
@ -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
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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user