Updated to have preinstall and post install in the main stack install loop.
Also updated keystone and glance config "adjustment" to use python config parsers since they can be used directly in that format.
This commit is contained in:
parent
ae73a3618a
commit
701502991f
@ -66,8 +66,14 @@ class InstallComponent():
|
||||
def configure(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def pre_install(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def install(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def post_install(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class UninstallComponent():
|
||||
@ -118,28 +124,35 @@ class PkgInstallComponent(ComponentBase, InstallComponent):
|
||||
def _get_param_map(self, fn=None):
|
||||
return None
|
||||
|
||||
def _do_pkg_install(self):
|
||||
def 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)
|
||||
LOG.info("Installing packages %s" % (", ".join(pkgnames)))
|
||||
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))
|
||||
return self.tracedir
|
||||
|
||||
def install(self):
|
||||
self._do_pkg_install()
|
||||
def pre_install(self):
|
||||
pkgs = get_pkg_list(self.distro, self.component_name)
|
||||
if(len(pkgs)):
|
||||
mp = self._get_param_map()
|
||||
self.packager.pre_install(pkgs, mp)
|
||||
return self.tracedir
|
||||
|
||||
def post_install(self):
|
||||
pkgs = get_pkg_list(self.distro, self.component_name)
|
||||
if(len(pkgs)):
|
||||
mp = self._get_param_map()
|
||||
self.packager.post_install(pkgs, mp)
|
||||
return self.tracedir
|
||||
|
||||
def _get_config_files(self):
|
||||
return list()
|
||||
|
||||
def _config_adjust(fn, contents):
|
||||
def _config_adjust(contents, name):
|
||||
return contents
|
||||
|
||||
def configure(self):
|
||||
@ -186,9 +199,9 @@ class PythonInstallComponent(PkgInstallComponent):
|
||||
|
||||
# Overridden
|
||||
def install(self):
|
||||
self._do_pkg_install()
|
||||
parent_result = PkgInstallComponent.install(self)
|
||||
self._python_install()
|
||||
return self.tracedir
|
||||
return parent_result
|
||||
|
||||
|
||||
class PkgUninstallComponent(ComponentBase, UninstallComponent):
|
||||
@ -294,7 +307,7 @@ class ProgramRuntime(ComponentBase, RuntimeComponent):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _get_app_options(self, app):
|
||||
return None
|
||||
return list()
|
||||
|
||||
def _get_param_map(self, app=None):
|
||||
return {
|
||||
@ -375,6 +388,12 @@ class PythonRuntime(ProgramRuntime):
|
||||
def __init__(self, component_name, *args, **kargs):
|
||||
ProgramRuntime.__init__(self, component_name, *args, **kargs)
|
||||
|
||||
def status(self):
|
||||
return None
|
||||
|
||||
def restart(self):
|
||||
return None
|
||||
|
||||
def _was_installed(self):
|
||||
parent_result = ProgramRuntime._was_installed(self)
|
||||
if(not parent_result):
|
||||
|
@ -27,11 +27,52 @@ import Shell
|
||||
LOG = Logger.getLogger("install.config")
|
||||
PW_TMPL = "Enter a password for %s: "
|
||||
ENV_PAT = re.compile(r"^\s*\$\{([\w\d]+):\-(.*)\}\s*$")
|
||||
CACHE_MSG = "(value will now be internally cached)"
|
||||
|
||||
|
||||
class IgnoreMissingConfigParser(ConfigParser.RawConfigParser):
|
||||
DEF_INT = 0
|
||||
DEF_FLOAT = 0.0
|
||||
DEF_BOOLEAN = False
|
||||
|
||||
def __init__(self):
|
||||
ConfigParser.RawConfigParser.__init__(self, allow_no_value=True)
|
||||
|
||||
def get(self, section, option):
|
||||
value = None
|
||||
try:
|
||||
value = ConfigParser.RawConfigParser.get(self, section, option)
|
||||
except ConfigParser.NoSectionError, e:
|
||||
pass
|
||||
except ConfigParser.NoOptionError, e:
|
||||
pass
|
||||
return value
|
||||
|
||||
def getboolean(self, section, option):
|
||||
value = self.get(section, option)
|
||||
if(value == None):
|
||||
#not there so don't let the parent blowup
|
||||
return IgnoreMissingConfigParser.DEF_BOOLEAN
|
||||
return ConfigParser.RawConfigParser.getboolean(self, section, option)
|
||||
|
||||
def getfloat(self, section, option):
|
||||
value = self.get(section, option)
|
||||
if(value == None):
|
||||
#not there so don't let the parent blowup
|
||||
return IgnoreMissingConfigParser.DEF_FLOAT
|
||||
return ConfigParser.RawConfigParser.getfloat(self, section, option)
|
||||
|
||||
def getint(self, section, option):
|
||||
value = self.get(section, option)
|
||||
if(value == None):
|
||||
#not there so don't let the parent blowup
|
||||
return IgnoreMissingConfigParser.DEF_INT
|
||||
return ConfigParser.RawConfigParser.getint(self, section, option)
|
||||
|
||||
|
||||
class EnvConfigParser(ConfigParser.RawConfigParser):
|
||||
def __init__(self):
|
||||
ConfigParser.RawConfigParser.__init__(self)
|
||||
ConfigParser.RawConfigParser.__init__(self, allow_no_value=True)
|
||||
self.pws = dict()
|
||||
self.configs_fetched = dict()
|
||||
self.db_dsns = dict()
|
||||
@ -47,46 +88,10 @@ class EnvConfigParser(ConfigParser.RawConfigParser):
|
||||
else:
|
||||
LOG.debug("Fetching value for param %s" % (key))
|
||||
v = self._get_special(section, option)
|
||||
LOG.debug("Fetched \"%s\" for %s (will now be cached)" % (v, key))
|
||||
LOG.debug("Fetched \"%s\" for %s %s" % (v, key, CACHE_MSG))
|
||||
self.configs_fetched[key] = v
|
||||
return v
|
||||
|
||||
def __len__(self):
|
||||
return (len(self.pws) +
|
||||
len(self.configs_fetched) +
|
||||
len(self.db_dsns))
|
||||
|
||||
def __str__(self):
|
||||
#this will make the items nice and pretty
|
||||
def item_format(k, v):
|
||||
return "\t%s=%s" % (str(k), str(v))
|
||||
#collect all the lines
|
||||
password_lines = list()
|
||||
if(len(self.pws)):
|
||||
password_lines.append("Passwords:")
|
||||
keys = sorted(self.pws.keys())
|
||||
for key in keys:
|
||||
value = self.pws.get(key)
|
||||
password_lines.append(item_format(key, value))
|
||||
cfg_lines = list()
|
||||
if(len(self.configs_fetched)):
|
||||
cfg_lines.append("Configs:")
|
||||
keys = sorted(self.configs_fetched.keys())
|
||||
for key in keys:
|
||||
if(key in self.pws):
|
||||
continue
|
||||
value = self.configs_fetched.get(key)
|
||||
cfg_lines.append(item_format(key, value))
|
||||
dsn_lines = list()
|
||||
if(len(self.db_dsns)):
|
||||
dsn_lines.append("Data source names:")
|
||||
keys = sorted(self.db_dsns.keys())
|
||||
for key in keys:
|
||||
value = self.db_dsns.get(key)
|
||||
dsn_lines.append(item_format(key, value))
|
||||
#make a nice string
|
||||
combined_lines = cfg_lines + password_lines + dsn_lines
|
||||
return os.linesep.join(combined_lines)
|
||||
|
||||
def _get_special(self, section, option):
|
||||
key = self._makekey(section, option)
|
||||
@ -140,7 +145,7 @@ class EnvConfigParser(ConfigParser.RawConfigParser):
|
||||
dsn += "/" + dbname
|
||||
else:
|
||||
dsn += "/"
|
||||
LOG.debug("For database %s fetched dsn %s" % (dbname, dsn))
|
||||
LOG.debug("For database %s fetched dsn %s %s" % (dbname, dsn, CACHE_MSG))
|
||||
#store for later...
|
||||
self.db_dsns[dbname] = dsn
|
||||
return dsn
|
||||
@ -156,6 +161,6 @@ class EnvConfigParser(ConfigParser.RawConfigParser):
|
||||
if(len(pw) == 0):
|
||||
while(len(pw) == 0):
|
||||
pw = Shell.password(PW_TMPL % (key))
|
||||
LOG.debug("Password for %s will be %s" % (key, pw))
|
||||
LOG.debug("Password for %s will be %s %s" % (key, pw, CACHE_MSG))
|
||||
self.pws[key] = pw
|
||||
return pw
|
||||
|
@ -82,8 +82,8 @@ class DBInstaller(PkgInstallComponent):
|
||||
out['HOST_IP'] = hostip
|
||||
return out
|
||||
|
||||
def install(self):
|
||||
pres = PkgInstallComponent.install(self)
|
||||
def post_install(self):
|
||||
parent_result = PkgInstallComponent.post_install(self)
|
||||
#extra actions to ensure we are granted access
|
||||
dbtype = self.cfg.get("db", "type")
|
||||
dbactions = DB_ACTIONS.get(dbtype)
|
||||
@ -106,7 +106,7 @@ class DBInstaller(PkgInstallComponent):
|
||||
execute(*cmd, run_as_root=True, shell=True)
|
||||
#restart it to make sure all good
|
||||
self.runtime.restart()
|
||||
return pres
|
||||
return parent_result
|
||||
|
||||
|
||||
class DBRuntime(ComponentBase, RuntimeComponent):
|
||||
|
@ -15,7 +15,9 @@
|
||||
|
||||
import json
|
||||
import os.path
|
||||
import io
|
||||
|
||||
import Config
|
||||
import Logger
|
||||
import Db
|
||||
|
||||
@ -36,6 +38,7 @@ API_CONF = "glance-api.conf"
|
||||
REG_CONF = "glance-registry.conf"
|
||||
CONFIGS = [API_CONF, REG_CONF]
|
||||
DB_NAME = "glance"
|
||||
CFG_SECTION = 'DEFAULT'
|
||||
|
||||
#what to start
|
||||
APP_OPTIONS = {
|
||||
@ -78,60 +81,67 @@ class GlanceInstaller(PythonInstallComponent):
|
||||
#these are the config files we will be adjusting
|
||||
return list(CONFIGS)
|
||||
|
||||
def install(self):
|
||||
parent_res = PythonInstallComponent.install(self)
|
||||
#setup the database
|
||||
def post_install(self):
|
||||
parent_result = PythonInstallComponent.post_install(self)
|
||||
self._setup_db()
|
||||
return parent_res
|
||||
|
||||
return parent_result
|
||||
|
||||
def _setup_db(self):
|
||||
Db.drop_db(self.cfg, DB_NAME)
|
||||
Db.create_db(self.cfg, DB_NAME)
|
||||
|
||||
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] == '['):
|
||||
#not useful to examine these
|
||||
continue
|
||||
pieces = cleaned.split("=", 1)
|
||||
if(len(pieces) != 2):
|
||||
continue
|
||||
key = pieces[0].strip()
|
||||
val = pieces[1].strip()
|
||||
if(len(key) == 0 or len(val) == 0):
|
||||
continue
|
||||
#now we take special actions
|
||||
if(key == 'filesystem_store_datadir'):
|
||||
#delete existing images
|
||||
deldir(val)
|
||||
#recreate the image directory
|
||||
dirsmade = mkdirslist(val)
|
||||
self.tracewriter.dir_made(*dirsmade)
|
||||
elif(key == 'log_file'):
|
||||
#ensure that we can write to the log file
|
||||
dirname = os.path.dirname(val)
|
||||
if(len(dirname)):
|
||||
dirsmade = mkdirslist(dirname)
|
||||
def _config_adjust(self, contents, name):
|
||||
if(name not in CONFIGS):
|
||||
return contents
|
||||
#use config parser and
|
||||
#then extract known configs that
|
||||
#will need locations/directories/files made (or touched)...
|
||||
with io.BytesIO(contents) as stream:
|
||||
config = Config.IgnoreMissingConfigParser()
|
||||
config.readfp(stream)
|
||||
if(config.getboolean('image_cache_enabled', CFG_SECTION)):
|
||||
cache_dir = config.get("image_cache_datadir", CFG_SECTION)
|
||||
if(cache_dir):
|
||||
LOG.info("Ensuring image cache data directory %s exists (and is empty)" % (cache_dir))
|
||||
#destroy then recreate the image cache directory
|
||||
deldir(cache_dir)
|
||||
dirsmade = mkdirslist(cache_dir)
|
||||
#this trace is used to remove the dirs created
|
||||
self.tracewriter.dir_made(*dirsmade)
|
||||
if(config.get('default_store', CFG_SECTION) == 'file'):
|
||||
file_dir = config.get('filesystem_store_datadir', CFG_SECTION)
|
||||
if(file_dir):
|
||||
LOG.info("Ensuring file system store directory %s exists and is empty" % (file_dir))
|
||||
#delete existing images
|
||||
deldir(file_dir)
|
||||
#recreate the image directory
|
||||
dirsmade = mkdirslist(file_dir)
|
||||
#this trace is used to remove the dirs created
|
||||
self.tracewriter.dir_made(*dirsmade)
|
||||
log_filename = config.get('log_file', CFG_SECTION)
|
||||
if(log_filename):
|
||||
LOG.info("Ensuring log file %s exists and is empty" % (log_filename))
|
||||
log_dir = os.path.dirname(log_filename)
|
||||
if(log_dir):
|
||||
LOG.info("Ensuring log directory %s exists" % (log_dir))
|
||||
dirsmade = mkdirslist(log_dir)
|
||||
#this trace is used to remove the dirs created
|
||||
self.tracewriter.dir_made(*dirsmade)
|
||||
#destroy then recreate it (the log file)
|
||||
unlink(val)
|
||||
touch_file(val)
|
||||
self.tracewriter.file_touched(val)
|
||||
elif(key == 'image_cache_datadir'):
|
||||
#destroy then recreate the image cache directory
|
||||
deldir(val)
|
||||
dirsmade = mkdirslist(val)
|
||||
#this trace is used to remove the dirs created
|
||||
self.tracewriter.dir_made(*dirsmade)
|
||||
elif(key == 'scrubber_datadir'):
|
||||
#destroy then recreate the scrubber data directory
|
||||
deldir(val)
|
||||
dirsmade = mkdirslist(val)
|
||||
#this trace is used to remove the dirs created
|
||||
self.tracewriter.dir_made(*dirsmade)
|
||||
unlink(log_filename)
|
||||
touch_file(log_filename)
|
||||
self.tracewriter.file_touched(log_filename)
|
||||
if(config.getboolean('delayed_delete', CFG_SECTION)):
|
||||
data_dir = config.get('scrubber_datadir', CFG_SECTION)
|
||||
if(data_dir):
|
||||
LOG.info("Ensuring scrubber data dir %s exists and is empty" % (data_dir))
|
||||
#destroy then recreate the scrubber data directory
|
||||
deldir(data_dir)
|
||||
dirsmade = mkdirslist(data_dir)
|
||||
#this trace is used to remove the dirs created
|
||||
self.tracewriter.dir_made(*dirsmade)
|
||||
#we might need to handle more in the future...
|
||||
#nothing modified so just return the original
|
||||
return contents
|
||||
|
||||
def _get_param_map(self, fn=None):
|
||||
|
@ -15,10 +15,12 @@
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import io
|
||||
|
||||
import Pip
|
||||
import Logger
|
||||
import Db
|
||||
import Config
|
||||
|
||||
#TODO fix these
|
||||
from Util import (KEYSTONE,
|
||||
@ -38,6 +40,7 @@ ROOT_CONF = "keystone.conf"
|
||||
CONFIGS = [ROOT_CONF]
|
||||
BIN_DIR = "bin"
|
||||
DB_NAME = "keystone"
|
||||
CFG_SECTION = 'DEFAULT'
|
||||
|
||||
#what to start
|
||||
APP_OPTIONS = {
|
||||
@ -63,13 +66,11 @@ class KeystoneInstaller(PythonInstallComponent):
|
||||
def _get_download_location(self):
|
||||
return (self.gitloc, self.brch)
|
||||
|
||||
def install(self):
|
||||
parent_res = PythonInstallComponent.install(self)
|
||||
#adjust db
|
||||
def post_install(self):
|
||||
parent_result = PythonInstallComponent.post_install(self)
|
||||
self._setup_db()
|
||||
#setup any data
|
||||
self._setup_data()
|
||||
return parent_res
|
||||
return parent_result
|
||||
|
||||
def _get_config_files(self):
|
||||
return list(CONFIGS)
|
||||
@ -83,33 +84,30 @@ class KeystoneInstaller(PythonInstallComponent):
|
||||
cmds = _keystone_setup_cmds(self.othercomponents)
|
||||
execute_template(*cmds, params=params, ignore_missing=True)
|
||||
|
||||
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] == '['):
|
||||
#not useful to examine these
|
||||
continue
|
||||
pieces = cleaned.split("=", 1)
|
||||
if(len(pieces) != 2):
|
||||
continue
|
||||
key = pieces[0].strip()
|
||||
val = pieces[1].strip()
|
||||
if(len(key) == 0 or len(val) == 0):
|
||||
continue
|
||||
#now we take special actions
|
||||
if(key == 'log_file'):
|
||||
# Ensure that we can write to the log file
|
||||
dirname = os.path.dirname(val)
|
||||
if(len(dirname)):
|
||||
dirsmade = mkdirslist(dirname)
|
||||
# This trace is used to remove the dirs created
|
||||
def _config_adjust(self, contents, name):
|
||||
if(name not in CONFIGS):
|
||||
return contents
|
||||
#use config parser and
|
||||
#then extract known configs that
|
||||
#will need locations/directories/files made (or touched)...
|
||||
with io.BytesIO(contents) as stream:
|
||||
config = Config.IgnoreMissingConfigParser()
|
||||
config.readfp(stream)
|
||||
log_filename = config.get('log_file', CFG_SECTION)
|
||||
if(log_filename):
|
||||
LOG.info("Ensuring log file %s exists and is empty" % (log_filename))
|
||||
log_dir = os.path.dirname(log_filename)
|
||||
if(log_dir):
|
||||
LOG.info("Ensuring log directory %s exists" % (log_dir))
|
||||
dirsmade = mkdirslist(log_dir)
|
||||
#this trace is used to remove the dirs created
|
||||
self.tracewriter.dir_made(*dirsmade)
|
||||
# Destroy then recreate it
|
||||
unlink(val)
|
||||
touch_file(val)
|
||||
self.tracewriter.file_touched(val)
|
||||
#destroy then recreate it (the log file)
|
||||
unlink(log_filename)
|
||||
touch_file(log_filename)
|
||||
self.tracewriter.file_touched(log_filename)
|
||||
#we might need to handle more in the future...
|
||||
#nothing modified so just return the original
|
||||
return contents
|
||||
|
||||
def _get_param_map(self, fn=None):
|
||||
|
@ -30,8 +30,8 @@ LOG = Logger.getLogger("install.packager")
|
||||
|
||||
|
||||
class Packager():
|
||||
def __init__(self):
|
||||
pass
|
||||
def __init__(self, distro):
|
||||
self.distro = distro
|
||||
|
||||
def install_batch(self, pkgs):
|
||||
raise NotImplementedError()
|
||||
|
@ -57,14 +57,12 @@ class RabbitInstaller(PkgInstallComponent):
|
||||
passwd = self.cfg.getpw("passwords", "rabbit")
|
||||
cmd = PWD_CMD + [passwd]
|
||||
execute(*cmd, run_as_root=True)
|
||||
|
||||
def install(self):
|
||||
pres = PkgInstallComponent.install(self)
|
||||
#ensure setup right
|
||||
|
||||
def post_install(self):
|
||||
parent_result = PkgInstallComponent.post_install(self)
|
||||
self._setup_pw()
|
||||
#restart it to make sure its ok to go
|
||||
self.runtime.restart()
|
||||
return pres
|
||||
return parent_result
|
||||
|
||||
|
||||
class RabbitRuntime(ComponentBase, RuntimeComponent):
|
||||
|
@ -25,7 +25,7 @@ import sys
|
||||
import Logger
|
||||
|
||||
#TODO fix these
|
||||
from Exceptions import (ProcessExecutionError, FileException)
|
||||
from Exceptions import (ProcessExecutionError, FileException, BadParamException)
|
||||
from Environment import (get_environment_bool, get_environment)
|
||||
|
||||
ROOT_HELPER = ["sudo"]
|
||||
@ -128,6 +128,16 @@ def joinpths(*pths):
|
||||
return os.path.join(*pths)
|
||||
|
||||
|
||||
def _gen_password(genlen):
|
||||
if(genlen <= 0):
|
||||
msg = "Generated password length %s can not be less than or equal to zero" % (genlen)
|
||||
raise BadParamException(msg)
|
||||
LOG.debug("Generating you a pseudo-random password of byte length: %s" % (genlen))
|
||||
cmd = MKPW_CMD + [genlen]
|
||||
(stdout, stderr) = execute(*cmd)
|
||||
return stdout.strip()
|
||||
|
||||
|
||||
def password(prompt=None, genlen=8):
|
||||
rd = ""
|
||||
pass_ask = get_environment_bool("PASS_ASK", True)
|
||||
@ -137,10 +147,7 @@ def password(prompt=None, genlen=8):
|
||||
else:
|
||||
rd = getpass.getpass()
|
||||
if(len(rd) == 0):
|
||||
LOG.debug("Generating you a password of length: %s" % (genlen))
|
||||
cmd = MKPW_CMD + [genlen]
|
||||
(stdout, stderr) = execute(*cmd)
|
||||
return stdout.strip()
|
||||
return _gen_password(genlen)
|
||||
else:
|
||||
return rd
|
||||
|
||||
|
@ -22,6 +22,7 @@ import Packager
|
||||
import Logger
|
||||
|
||||
#TODO fix these
|
||||
from Util import (UBUNTU11, RHEL6)
|
||||
from Util import param_replace
|
||||
from Shell import execute
|
||||
|
||||
@ -39,22 +40,26 @@ APT_DO_REMOVE = APT_PURGE
|
||||
#make sure its non-interactive
|
||||
ENV_ADDITIONS = {'DEBIAN_FRONTEND': 'noninteractive'}
|
||||
|
||||
#not 100% right but it will work for us
|
||||
#ie we aren't handling : for epochs
|
||||
#http://www.ducea.com/2006/06/17/ubuntu-package-version-naming-explanation/
|
||||
UB_PKG_VERSION_REGEX = re.compile(r"^(\d*)\.(\d*)(?:\.(\d*))?-(\d*)ubuntu(\d*)$", re.IGNORECASE)
|
||||
#how versions are expressed by apt
|
||||
VERSION_TEMPL = "%s=%s"
|
||||
|
||||
|
||||
class AptPackager(Packager.Packager):
|
||||
def __init__(self):
|
||||
Packager.Packager.__init__(self)
|
||||
def __init__(self, distro):
|
||||
Packager.Packager.__init__(self, distro)
|
||||
|
||||
def _form_cmd(self, name, version):
|
||||
cmd = name
|
||||
if(version and len(version)):
|
||||
cmd = cmd + "=" + version
|
||||
cmd = VERSION_TEMPL % (name, version)
|
||||
else:
|
||||
cmd = name
|
||||
return cmd
|
||||
|
||||
def _execute_apt(self, cmd, run_as_root, check_exit=True):
|
||||
execute(*cmd, run_as_root=run_as_root,
|
||||
check_exit_code=check_exit,
|
||||
env_overrides=ENV_ADDITIONS)
|
||||
|
||||
def remove_batch(self, pkgs):
|
||||
pkgnames = sorted(pkgs.keys())
|
||||
#form the needed commands
|
||||
@ -64,19 +69,17 @@ class AptPackager(Packager.Packager):
|
||||
removable = info.get('removable', True)
|
||||
if(not removable):
|
||||
continue
|
||||
if(_pkg_remove_special(name, info)):
|
||||
#handled by the special remove
|
||||
if(self._pkg_remove_special(name, info)):
|
||||
continue
|
||||
torun = self._form_cmd(name, info.get("version"))
|
||||
cmds.append(torun)
|
||||
full_cmd = self._form_cmd(name, info.get("version"))
|
||||
if(full_cmd):
|
||||
cmds.append(full_cmd)
|
||||
if(len(cmds)):
|
||||
cmd = APT_GET + APT_DO_REMOVE + cmds
|
||||
execute(*cmd, run_as_root=True,
|
||||
env_overrides=ENV_ADDITIONS)
|
||||
self._execute_apt(cmd, True)
|
||||
#clean them out
|
||||
cmd = APT_GET + APT_AUTOREMOVE
|
||||
execute(*cmd, run_as_root=True,
|
||||
env_overrides=ENV_ADDITIONS)
|
||||
self._execute_apt(cmd, True)
|
||||
|
||||
def install_batch(self, pkgs):
|
||||
pkgnames = sorted(pkgs.keys())
|
||||
@ -84,83 +87,43 @@ class AptPackager(Packager.Packager):
|
||||
cmds = []
|
||||
for name in pkgnames:
|
||||
info = pkgs.get(name) or {}
|
||||
if(_pkg_install_special(name, info)):
|
||||
#handled by the special install
|
||||
if(self._pkg_install_special(name, info)):
|
||||
continue
|
||||
torun = self._form_cmd(name, info.get("version"))
|
||||
cmds.append(torun)
|
||||
full_cmd = self._form_cmd(name, info.get("version"))
|
||||
if(full_cmd):
|
||||
cmds.append(full_cmd)
|
||||
#install them
|
||||
if(len(cmds)):
|
||||
cmd = APT_GET + APT_INSTALL + cmds
|
||||
execute(*cmd, run_as_root=True,
|
||||
env_overrides=ENV_ADDITIONS)
|
||||
self._execute_apt(cmd, True)
|
||||
|
||||
|
||||
def _extract_version(version):
|
||||
version_info = dict()
|
||||
if(version.lower().find("ubuntu") != -1):
|
||||
mtch = UB_PKG_VERSION_REGEX.search(version)
|
||||
if(mtch):
|
||||
major = mtch.group(1)
|
||||
major = int(major) if major != None else -1
|
||||
minor = mtch.group(2)
|
||||
minor = int(minor) if minor != None else -1
|
||||
release = mtch.group(3)
|
||||
release = int(release) if release != None else -1
|
||||
debian_version = mtch.group(4)
|
||||
debian_version = int(debian_version) if debian_version != None else -1
|
||||
ubuntu_version = mtch.group(5)
|
||||
ubuntu_version = int(ubuntu_version) if ubuntu_version != None else -1
|
||||
version_info['type'] = 'ubuntu'
|
||||
version_info['major'] = major
|
||||
version_info['minor'] = minor
|
||||
version_info['release'] = release
|
||||
version_info['debian_version'] = debian_version
|
||||
version_info['ubuntu_version'] = ubuntu_version
|
||||
return version_info
|
||||
|
||||
|
||||
def _pkg_remove_special(name, pkginfo):
|
||||
#https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/878597
|
||||
#https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/878600
|
||||
if(name == 'rabbitmq-server'):
|
||||
version = pkginfo.get('version')
|
||||
version_info = _extract_version(version)
|
||||
if(len(version_info)):
|
||||
if(version_info.get('type') == 'ubuntu' and
|
||||
version_info.get('major') <= 2 and
|
||||
version_info.get('minor') < 6):
|
||||
LOG.info("Handling special remove of %s v%s" % (name, version))
|
||||
#the first time seems to fail with exit code 100 but the second
|
||||
#time seems to not fail, pretty weird, most likely the above bugs
|
||||
cmd = APT_GET + APT_REMOVE + [name + "=" + version]
|
||||
execute(*cmd, run_as_root=True,
|
||||
check_exit_code=False, env_overrides=ENV_ADDITIONS)
|
||||
def _pkg_remove_special(self, name, pkginfo):
|
||||
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/878600
|
||||
LOG.info("Handling special remove of %s" % (name))
|
||||
full_cmd = self._form_cmd(name, pkginfo.get("version"))
|
||||
if(full_cmd):
|
||||
cmd = APT_GET + APT_REMOVE + [full_cmd]
|
||||
self._execute_apt(cmd, True. True)
|
||||
#probably useful to do this
|
||||
time.sleep(1)
|
||||
cmd = APT_GET + APT_PURGE + [name + "=" + version]
|
||||
execute(*cmd, run_as_root=True,
|
||||
env_overrides=ENV_ADDITIONS)
|
||||
#purge
|
||||
cmd = APT_GET + APT_PURGE + [full_cmd]
|
||||
self._execute_apt(cmd, True)
|
||||
return True
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def _pkg_install_special(name, pkginfo):
|
||||
#https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/878597
|
||||
#https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/878600
|
||||
if(name == 'rabbitmq-server'):
|
||||
version = pkginfo.get('version')
|
||||
version_info = _extract_version(version)
|
||||
if(len(version_info)):
|
||||
if(version_info.get('type') == 'ubuntu' and
|
||||
version_info.get('major') <= 2 and
|
||||
version_info.get('minor') < 6):
|
||||
LOG.info("Handling special install of %s v%s" % (name, version))
|
||||
#this seems to be a temporary fix for that bug
|
||||
with TemporaryFile() as f:
|
||||
cmd = APT_GET + APT_INSTALL + [name + "=" + version]
|
||||
execute(*cmd, run_as_root=True,
|
||||
stdout_fh=f, stderr_fh=f,
|
||||
env_overrides=ENV_ADDITIONS)
|
||||
def _pkg_install_special(self, name, pkginfo):
|
||||
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/878600
|
||||
LOG.info("Handling special install of %s" % (name))
|
||||
#this seems to be a temporary fix for that bug
|
||||
with TemporaryFile() as f:
|
||||
full_cmd = self._form_cmd(name, pkginfo.get("version"))
|
||||
if(full_cmd):
|
||||
cmd = APT_GET + APT_INSTALL + [full_cmd]
|
||||
execute(*cmd, run_as_root=True, stdout_fh=f, stderr_fh=f, env_overrides=ENV_ADDITIONS)
|
||||
return True
|
||||
return False
|
||||
return False
|
||||
|
@ -28,9 +28,8 @@ YUM_INSTALL = ["install", "-y"]
|
||||
|
||||
|
||||
class YumPackager(Packager.Packager):
|
||||
def __init__(self):
|
||||
LOG.info("Init called")
|
||||
Packager.Packager.__init__(self)
|
||||
def __init__(self, distro):
|
||||
Packager.Packager.__init__(self, distro)
|
||||
|
||||
def _form_cmd(self, name, version):
|
||||
cmd = name
|
||||
|
45
stack
45
stack
@ -32,7 +32,6 @@ from Util import (NOVA, GLANCE, QUANTUM, SWIFT, KEYSTONE, HORIZON, DB, RABBIT,
|
||||
UBUNTU11, RHEL6,
|
||||
STACK_CFG_LOC)
|
||||
from Shell import (mkdir, joinpths, unlink)
|
||||
from Config import (EnvConfigParser)
|
||||
from Exceptions import (NoTraceException)
|
||||
|
||||
import Glance
|
||||
@ -44,6 +43,7 @@ import Config
|
||||
import Swift
|
||||
import Db
|
||||
import Rabbit
|
||||
import Config
|
||||
|
||||
LOG = Logger.getLogger("install")
|
||||
|
||||
@ -108,16 +108,41 @@ def get_package_manager_class(distro):
|
||||
|
||||
|
||||
def get_config(action):
|
||||
LOG.info("Loading config from %s" % (STACK_CFG_LOC))
|
||||
cfg = EnvConfigParser()
|
||||
cfg.read(STACK_CFG_LOC)
|
||||
fn = STACK_CFG_LOC
|
||||
LOG.info("Loading config from %s" % (fn))
|
||||
cfg = Config.EnvConfigParser()
|
||||
cfg.read(fn)
|
||||
return cfg
|
||||
|
||||
|
||||
def print_cfgs(cfg, action):
|
||||
if(len(cfg)):
|
||||
#this will make the items nice and pretty
|
||||
def item_format(k, v):
|
||||
return "\t%s=%s" % (str(k), str(v))
|
||||
def map_print(mp):
|
||||
for key in sorted(mp.keys()):
|
||||
value = mp.get(key)
|
||||
LOG.info(item_format(key, value))
|
||||
#now make it pretty
|
||||
passwords_gotten = cfg.pws
|
||||
full_cfgs = cfg.configs_fetched
|
||||
db_dsns = cfg.db_dsns
|
||||
if(len(passwords_gotten) or len(full_cfgs) or len(db_dsns)):
|
||||
LOG.info("After %s your config is:" % (action))
|
||||
LOG.info(str(cfg).strip())
|
||||
if(len(passwords_gotten)):
|
||||
LOG.info("Passwords:")
|
||||
map_print(passwords_gotten)
|
||||
if(len(full_cfgs)):
|
||||
filtered_mp = dict()
|
||||
for key in full_cfgs.keys():
|
||||
if(key in passwords_gotten):
|
||||
continue
|
||||
filtered_mp[key] = full_cfgs.get(key)
|
||||
LOG.info("Configs:")
|
||||
map_print(filtered_mp)
|
||||
if(len(db_dsns)):
|
||||
LOG.info("Data source names:")
|
||||
map_print(db_dsns)
|
||||
|
||||
|
||||
def runner(action_name, component_set, distro, root_dir, program_args):
|
||||
@ -125,7 +150,7 @@ def runner(action_name, component_set, distro, root_dir, program_args):
|
||||
if(action_name == INSTALL):
|
||||
mkdir(root_dir)
|
||||
pkg_manager_cls = get_package_manager_class(distro)
|
||||
pkg_manager = pkg_manager_cls()
|
||||
pkg_manager = pkg_manager_cls(distro)
|
||||
config = get_config(action_name)
|
||||
LOG.info("Will %s [%s] using root directory %s" % (action_name, ", ".join(component_set), root_dir))
|
||||
results = list()
|
||||
@ -139,8 +164,12 @@ def runner(action_name, component_set, distro, root_dir, program_args):
|
||||
instance.download()
|
||||
LOG.info("Configuring %s." % (c))
|
||||
instance.configure()
|
||||
LOG.info("Pre-installing %s." % (c))
|
||||
instance.pre_install()
|
||||
LOG.info("Installing %s." % (c))
|
||||
trace = instance.install()
|
||||
instance.install()
|
||||
LOG.info("Post-installing %s." % (c))
|
||||
trace = instance.post_install()
|
||||
if(trace):
|
||||
LOG.info("Finished install of %s - check %s for traces of what happened." % (c, trace))
|
||||
results.append(trace)
|
||||
|
Loading…
x
Reference in New Issue
Block a user