Start using the Distro class throughout the system instead of local platform maps.

This commit is contained in:
Doug Hellmann 2012-03-14 16:55:47 -04:00
parent b1f372e8f6
commit 81cbd39b67
13 changed files with 94 additions and 165 deletions

View File

@ -82,8 +82,7 @@ class ComponentBase(object):
self.kargs = kwds
def get_dependencies(self):
deps = settings.COMPONENT_DEPENDENCIES.get(self.component_name) or list()
return list(deps)
return self.runner.distro.components[self.component_name].get('dependencies', [])[:]
def verify(self):
pass
@ -157,10 +156,12 @@ class PkgInstallComponent(ComponentBase):
pkgs = dict()
for fn in short:
full_name = sh.joinpths(settings.STACK_PKG_DIR, fn)
pkgs = utils.extract_pkg_list([full_name], self.distro, pkgs)
pkgs = utils.extract_pkg_list([full_name], self.distro.name, pkgs)
return pkgs
def install(self):
LOG.debug('Preparing to install packages for %s',
self.component_name)
pkgs = self._get_pkgs_expanded()
if pkgs:
pkgnames = sorted(pkgs.keys())
@ -170,6 +171,9 @@ class PkgInstallComponent(ComponentBase):
self.tracewriter.package_installed(name, pkgs.get(name))
#now actually install
self.packager.install_batch(pkgs)
else:
LOG.info('No packages to install for %s',
self.component_name)
return self.tracedir
def pre_install(self):
@ -270,7 +274,7 @@ class PythonInstallComponent(PkgInstallComponent):
pips = dict()
for fn in shorts:
full_name = sh.joinpths(settings.STACK_PIP_DIR, fn)
pips = utils.extract_pip_list([full_name], self.distro, pips)
pips = utils.extract_pip_list([full_name], self.distro.name, pips)
return pips
def _install_pips(self):

View File

@ -29,52 +29,15 @@ LOG = logging.getLogger("devstack.components.db")
MYSQL = 'mysql'
START_WAIT_TIME = settings.WAIT_ALIVE_SECS
#TODO maybe we should handle this differently in the future, blah
#ie in a special set of classes (make this class abstract)...
DB_ACTIONS = {
MYSQL: {
# Of course these aren't distro independent...
'runtime': {
settings.UBUNTU11: {
'start': ["service", "mysql", 'start'],
'stop': ["service", 'mysql', "stop"],
'status': ["service", 'mysql', "status"],
'restart': ["service", 'mysql', "restart"],
},
settings.RHEL6: {
'start': ["service", "mysqld", 'start'],
'stop': ["service", 'mysqld', "stop"],
'status': ["service", 'mysqld', "status"],
'restart': ["service", 'mysqld', "restart"],
},
settings.FEDORA16: {
'start': ["service", "mysqld", 'start'],
'stop': ["service", 'mysqld', "stop"],
'status': ["service", 'mysqld', "status"],
'restart': ["service", 'mysqld', "restart"],
},
},
#modification commands
#NOTE: we aren't stopping any sql injection...
'set_pwd': ['mysql', '--user=%USER%', '--password=%OLD_PASSWORD%', '-e',
("\"USE mysql; UPDATE user SET "
" password=PASSWORD('%NEW_PASSWORD%') WHERE User='%USER%'; FLUSH PRIVILEGES;\"")],
'create_db': ['mysql', '--user=%USER%', '--password=%PASSWORD%',
'-e', 'CREATE DATABASE %DB%;'],
'drop_db': ['mysql', '--user=%USER%', '--password=%PASSWORD%',
'-e', 'DROP DATABASE IF EXISTS %DB%;'],
'grant_all': ["mysql", "--user=%USER%", "--password=%PASSWORD%", '-e',
("\"GRANT ALL PRIVILEGES ON *.* TO '%USER%'@'%' "
" IDENTIFIED BY '%PASSWORD%'; FLUSH PRIVILEGES;\"")],
},
}
#need to reset pw to blank since this distributions don't seem to always reset it when u uninstall the db
#need to reset pw to blank since this distributions don't seem to
#always reset it when u uninstall the db
RESET_BASE_PW = ''
#links about how to reset if it fails
SQL_RESET_PW_LINKS = ['https://help.ubuntu.com/community/MysqlPasswordReset',
'http://dev.mysql.com/doc/refman/5.0/en/resetting-permissions.html']
SQL_RESET_PW_LINKS = [
'https://help.ubuntu.com/community/MysqlPasswordReset',
'http://dev.mysql.com/doc/refman/5.0/en/resetting-permissions.html',
]
#used as a generic error message
BASE_ERROR = 'Currently we do not know how to [%s] for database type [%s]'
@ -97,7 +60,7 @@ class DBUninstaller(comp.PkgUninstallComponent):
def pre_uninstall(self):
dbtype = self.cfg.get("db", "type")
dbactions = DB_ACTIONS.get(dbtype)
dbactions = self.distro.commands[dbtype]
try:
if dbactions:
LOG.info(("Attempting to reset your db password to \"%s\" so"
@ -143,8 +106,9 @@ class DBInstaller(comp.PkgInstallComponent):
def _configure_db_confs(self):
dbtype = self.cfg.get("db", "type")
#TODO: maybe this should be a subclass that handles these differences
if self.distro == settings.RHEL6 and dbtype == MYSQL:
#TODO: use separate classes in devstack.distros.$distro.db and
# specify them in the yaml file
if self.distro.name == settings.RHEL6 and dbtype == MYSQL:
LOG.info("Fixing up %s mysql configs." % (settings.RHEL6))
fc = sh.load_file('/etc/my.cnf')
lines = fc.splitlines()
@ -180,7 +144,7 @@ class DBInstaller(comp.PkgInstallComponent):
#extra actions to ensure we are granted access
dbtype = self.cfg.get("db", "type")
dbactions = DB_ACTIONS.get(dbtype)
dbactions = self.distro.commands[dbtype]
#set your password
try:
@ -226,11 +190,11 @@ class DBRuntime(comp.EmptyRuntime):
def _get_run_actions(self, act, exception_cls):
dbtype = self.cfg.get("db", "type")
type_actions = DB_ACTIONS.get(dbtype)
type_actions = self.distro.commands[dbtype]
if type_actions is None:
msg = BASE_ERROR % (act, dbtype)
raise NotImplementedError(msg)
distro_options = type_actions.get('runtime').get(self.distro)
distro_options = self.distro.commands[dbtype]
if distro_options is None:
msg = BASE_ERROR % (act, dbtype)
raise NotImplementedError(msg)
@ -286,9 +250,9 @@ class DBRuntime(comp.EmptyRuntime):
return comp.STATUS_UNKNOWN
def drop_db(cfg, pw_gen, dbname):
def drop_db(cfg, pw_gen, distro, dbname):
dbtype = cfg.get("db", "type")
dbactions = DB_ACTIONS.get(dbtype)
dbactions = distro.commands[dbtype]
if dbactions and dbactions.get('drop_db'):
dropcmd = dbactions.get('drop_db')
params = dict()
@ -306,9 +270,9 @@ def drop_db(cfg, pw_gen, dbname):
raise NotImplementedError(msg)
def create_db(cfg, pw_gen, dbname):
def create_db(cfg, pw_gen, distro, dbname):
dbtype = cfg.get("db", "type")
dbactions = DB_ACTIONS.get(dbtype)
dbactions = distro.commands[dbtype]
if dbactions and dbactions.get('create_db'):
createcmd = dbactions.get('create_db')
params = dict()

View File

@ -119,8 +119,8 @@ class GlanceInstaller(comp.PythonInstallComponent):
def _setup_db(self):
LOG.info("Fixing up database named %s.", DB_NAME)
db.drop_db(self.cfg, self.pw_gen, DB_NAME)
db.create_db(self.cfg, self.pw_gen, DB_NAME)
db.drop_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
db.create_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
def _get_source_config(self, config_fn):
if config_fn == POLICY_JSON:

View File

@ -40,13 +40,6 @@ HORIZON_APACHE_CONF = '000-default'
CONFIGS = [HORIZON_PY_CONF, HORIZON_APACHE_CONF]
#http://wiki.apache.org/httpd/DistrosDefaultLayout
#TODO: maybe this should be a subclass that handles these differences
APACHE_CONF_TARGETS = {
settings.UBUNTU11: '/etc/apache2/sites-enabled/000-default',
#ensure runs after wsgi.conf (naming wise)
settings.RHEL6: '/etc/httpd/conf.d/wsgi-horizon-000-default.conf',
settings.FEDORA16: '/etc/httpd/conf.d/wsgi-horizon-000-default.conf',
}
#db sync that needs to happen for horizon
DB_SYNC_CMD = ['python', 'manage.py', 'syncdb']
@ -54,18 +47,6 @@ DB_SYNC_CMD = ['python', 'manage.py', 'syncdb']
#special apache directory (TODO describe more about this)
BLACKHOLE_DIR = '.blackhole'
#hopefully this will be distro independent ??
#of course they aren't!
#TODO: maybe this should be a subclass that handles these differences
APACHE_SVC_NAME = {
settings.RHEL6: 'httpd',
settings.FEDORA16: 'httpd',
settings.UBUNTU11: 'apache2',
}
APACHE_RESTART_CMD = ['service', '%SERVICE%', 'restart']
APACHE_START_CMD = ['service', '%SERVICE%', 'start']
APACHE_STOP_CMD = ['service', '%SERVICE%', 'stop']
APACHE_STATUS_CMD = ['service', '%SERVICE%', 'status']
APACHE_ERROR_LOG_FN = "error.log"
APACHE_ACCESS_LOG_FN = "access.log"
APACHE_DEF_PORT = 80
@ -119,7 +100,7 @@ class HorizonInstaller(comp.PythonInstallComponent):
def _get_symlinks(self):
links = comp.PythonInstallComponent._get_symlinks(self)
src = self._get_target_config_name(HORIZON_APACHE_CONF)
links[src] = APACHE_CONF_TARGETS[self.distro]
links[src] = self.distro.commands['apache']['settings']['conf-link-target']
if utils.service_enabled(settings.QUANTUM_CLIENT, self.instances, False):
#TODO remove this junk, blah, puke that we have to do this
qc = self.instances[settings.QUANTUM_CLIENT]
@ -257,58 +238,46 @@ class HorizonRuntime(comp.EmptyRuntime):
if curr_status == comp.STATUS_STARTED:
return self.restart()
else:
mp = dict()
mp['SERVICE'] = APACHE_SVC_NAME[self.distro]
cmds = list()
cmds.append({
'cmd': APACHE_START_CMD,
'run_as_root': True,
})
cmds = [{
'cmd': self.distro.commands['apache']['start'],
'run_as_root': True,
}]
utils.execute_template(*cmds,
check_exit_code=True,
params=mp)
params={})
return 1
def restart(self):
mp = dict()
mp['SERVICE'] = APACHE_SVC_NAME[self.distro]
cmds = list()
cmds.append({
'cmd': APACHE_RESTART_CMD,
cmds = [{
'cmd': self.distro.commands['apache']['restart'],
'run_as_root': True,
})
}]
utils.execute_template(*cmds,
check_exit_code=True,
params=mp)
check_exit_code=True,
params={})
return 1
def stop(self):
curr_status = self.status()
if curr_status != comp.STATUS_STOPPED:
mp = dict()
mp['SERVICE'] = APACHE_SVC_NAME[self.distro]
cmds = list()
cmds.append({
'cmd': APACHE_STOP_CMD,
'run_as_root': True,
})
cmds = [{
'cmd': self.distro.commands['apache']['stop'],
'run_as_root': True,
}]
utils.execute_template(*cmds,
check_exit_code=True,
params=mp)
check_exit_code=True,
params={})
return 1
return 0
def status(self):
mp = dict()
mp['SERVICE'] = APACHE_SVC_NAME[self.distro]
cmds = list()
cmds.append({
'cmd': APACHE_STATUS_CMD,
'run_as_root': True,
})
cmds = [{
'cmd': self.distro.commands['apache']['status'],
'run_as_root': True,
}]
run_result = utils.execute_template(*cmds,
check_exit_code=False,
params=mp)
check_exit_code=False,
params={})
if not run_result or not run_result[0]:
return comp.STATUS_UNKNOWN
(sysout, stderr) = run_result[0]

View File

@ -133,8 +133,8 @@ class KeystoneInstaller(comp.PythonInstallComponent):
def _setup_db(self):
LOG.info("Fixing up database named %s.", DB_NAME)
db.drop_db(self.cfg, self.pw_gen, DB_NAME)
db.create_db(self.cfg, self.pw_gen, DB_NAME)
db.drop_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
db.create_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
def _setup_initer(self):
LOG.info("Configuring keystone initializer template %s.", MANAGE_DATA_CONF)

View File

@ -89,8 +89,8 @@ class MelangeInstaller(comp.PythonInstallComponent):
def _setup_db(self):
LOG.info("Fixing up database named %s.", DB_NAME)
db.drop_db(self.cfg, self.pw_gen, DB_NAME)
db.create_db(self.cfg, self.pw_gen, DB_NAME)
db.drop_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
db.create_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
def _get_pkgs(self):
return list(REQ_PKGS)

View File

@ -293,7 +293,7 @@ class NovaUninstaller(comp.PythonUninstallComponent):
if virt_driver == 'libvirt':
inst_prefix = self.cfg.getdefaulted('nova', 'instance_name_prefix', DEF_INSTANCE_PREFIX)
libvirt_type = _canon_libvirt_type(self.cfg.get('nova', 'libvirt_type'))
virsh.clear_libvirt_domains(self.distro, libvirt_type, inst_prefix)
virsh.clear_libvirt_domains(self.distro.name, libvirt_type, inst_prefix)
class NovaInstaller(comp.PythonInstallComponent):
@ -383,8 +383,8 @@ class NovaInstaller(comp.PythonInstallComponent):
def _setup_db(self):
LOG.info("Fixing up database named %s.", DB_NAME)
db.drop_db(self.cfg, self.pw_gen, DB_NAME)
db.create_db(self.cfg, self.pw_gen, DB_NAME)
db.drop_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
db.create_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
def _generate_nova_conf(self):
LOG.info("Generating dynamic content for nova configuration (%s)." % (API_CONF))
@ -427,7 +427,7 @@ class NovaInstaller(comp.PythonInstallComponent):
configs_made += 1
# TODO: maybe this should be a subclass that handles these differences
driver_canon = _canon_virt_driver(self.cfg.get('nova', 'virt_driver'))
if (self.distro in POLICY_DISTROS) and driver_canon == 'libvirt':
if (self.distro.name in POLICY_DISTROS) and driver_canon == 'libvirt':
dirs_made = list()
with sh.Rooted(True):
dirs_made = sh.mkdirslist(sh.dirname(LIBVIRT_POLICY_FN))
@ -467,6 +467,7 @@ class NovaRuntime(comp.PythonRuntime):
def get_dependencies(self):
deps = comp.PythonRuntime.get_dependencies(self)
# FIXME: This should come from a persona.
if utils.service_enabled(settings.QUANTUM, self.instances, False):
deps.append(settings.QUANTUM)
return deps
@ -497,11 +498,11 @@ class NovaRuntime(comp.PythonRuntime):
if virt_driver == 'libvirt':
virt_type = _canon_libvirt_type(self.cfg.get('nova', 'libvirt_type'))
LOG.info("Checking that your selected libvirt virtualization type [%s] is working and running." % (virt_type))
if not virsh.virt_ok(virt_type, self.distro):
if not virsh.virt_ok(virt_type, self.distro.name):
msg = ("Libvirt type %s for distro %s does not seem to be active or configured correctly, "
"perhaps you should be using %s instead." % (virt_type, self.distro, DEF_VIRT_TYPE))
"perhaps you should be using %s instead." % (virt_type, self.distro.name, DEF_VIRT_TYPE))
raise exceptions.StartException(msg)
virsh.restart(self.distro)
virsh.restart(self.distro.name)
def _get_param_map(self, app_name):
params = comp.PythonRuntime._get_param_map(self, app_name)
@ -553,7 +554,7 @@ class NovaVolumeConfigurator(object):
# logical volumes
self._process_lvs(mp)
# Finish off by restarting tgt, and ignore any errors
utils.execute_template(*RESTART_TGT_CMD[self.distro], check_exit_code=False)
utils.execute_template(*RESTART_TGT_CMD[self.distro.name], check_exit_code=False)
def _process_lvs(self, mp):
LOG.info("Attempting to setup logical volumes for nova volume management.")

View File

@ -113,6 +113,7 @@ class QuantumInstaller(comp.PkgInstallComponent):
def get_dependencies(self):
common_deps = comp.PkgInstallComponent.get_dependencies(self)
add_deps = list()
# FIXME: This should come from a persona.
if self.q_vswitch_agent:
#just need the client
add_deps.append(settings.QUANTUM_CLIENT)
@ -200,8 +201,8 @@ class QuantumInstaller(comp.PkgInstallComponent):
def _setup_db(self):
LOG.info("Fixing up database named %s.", DB_NAME)
db.drop_db(self.cfg, self.pw_gen, DB_NAME)
db.create_db(self.cfg, self.pw_gen, DB_NAME)
db.drop_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
db.create_db(self.cfg, self.pw_gen, self.distro, DB_NAME)
def _get_source_config(self, config_fn):
if config_fn == PLUGIN_CONF:

View File

@ -102,7 +102,7 @@ class AptPackager(pack.Packager):
def _pkg_remove_special(self, name, pkginfo):
#TODO: maybe this should be a subclass that handles these differences
if name == 'rabbitmq-server' and self.distro == settings.UBUNTU11:
if name == 'rabbitmq-server' and self.distro.name == settings.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))
@ -119,7 +119,7 @@ class AptPackager(pack.Packager):
def _pkg_install_special(self, name, pkginfo):
#TODO: maybe this should be a subclass that handles these differences
if name == 'rabbitmq-server' and self.distro == settings.UBUNTU11:
if name == 'rabbitmq-server' and self.distro.name == settings.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))

View File

@ -62,7 +62,7 @@ class YumPackager(pack.Packager):
def _remove_special(self, pkgname, pkginfo):
#TODO: maybe this should be a subclass that handles these differences
if self.distro == settings.RHEL6 and pkgname in RHEL_RELINKS:
if self.distro.name == settings.RHEL6 and pkgname in RHEL_RELINKS:
#we don't return true here so that
#the normal package cleanup happens
sh.unlink(RHEL_RELINKS.get(pkgname).get("tgt"))
@ -84,7 +84,7 @@ class YumPackager(pack.Packager):
#TODO: maybe this should be a subclass that handles these differences
def _install_special(self, pkgname, pkginfo):
if self.distro == settings.RHEL6 and pkgname in RHEL_RELINKS:
if self.distro.name == settings.RHEL6 and pkgname in RHEL_RELINKS:
return self._install_rhel_relinks(pkgname, pkginfo)
return False

View File

@ -24,17 +24,10 @@ LOG = logging.getLogger("devstack.pip")
PIP_UNINSTALL_CMD_OPTS = ['-y', '-q']
PIP_INSTALL_CMD_OPTS = ['-q']
#the pip command is named different :-(
PIP_CMD_NAMES = {
settings.RHEL6: 'pip-python',
settings.FEDORA16: 'pip-python',
settings.UBUNTU11: 'pip',
}
def install(pips, distro):
pipnames = sorted(pips.keys())
root_cmd = PIP_CMD_NAMES[distro]
root_cmd = distro.commands.get('pip', 'pip')
LOG.info("Installing python packages (%s) using command (%s)" % (", ".join(pipnames), root_cmd))
for name in pipnames:
pipfull = name
@ -56,7 +49,7 @@ def install(pips, distro):
def uninstall(pips, distro, skip_errors=True):
pipnames = sorted(pips.keys())
root_cmd = PIP_CMD_NAMES[distro]
root_cmd = distro.commands.get('pip', 'pip')
LOG.info("Uninstalling python packages (%s) using command (%s)" % (", ".join(pipnames), root_cmd))
for name in pipnames:
try:

View File

@ -173,18 +173,16 @@ class ActionRunner(object):
adjusted_components = dict(components)
if self.ignore_deps:
return (adjusted_components, list(components.keys()))
all_components = common.get_components_deps(
runner=self,
action_name=self.action,
base_components=components,
root_dir=self.directory,
distro=self.distro,
all_components = self.distro.resolve_component_dependencies(
list(components.keys())
)
component_diff = set(all_components.keys()).difference(components.keys())
if component_diff:
LOG.info("Having to activate dependent components: [%s]" % (", ".join(sorted(component_diff))))
LOG.info("Activating dependencies: [%s]",
", ".join(sorted(component_diff))
)
for new_component in component_diff:
adjusted_components[new_component] = list()
adjusted_components[new_component] = []
return (adjusted_components, utils.get_components_order(all_components))
def _inject_references(self, components):
@ -198,10 +196,7 @@ class ActionRunner(object):
def _instanciate_components(self, components):
all_instances = dict()
for component in components.keys():
cls = common.get_action_cls(self.action, component, self.distro)
# FIXME: Instead of passing some of these options,
# pass a reference to the runner itself and let
# the component keep a weakref to it.
cls = self.distro.get_component_action_class(component, self.action)
instance = cls(instances=all_instances,
runner=self,
root_dir=self.directory,
@ -223,10 +218,14 @@ class ActionRunner(object):
preq_components[c] = components[c]
if preq_components:
LOG.info("Having to activate prerequisite action [%s] for %s components." % (preq_action, len(preq_components)))
preq_runner = ActionRunner(self.distro, preq_action,
self.directory, self.cfg, self.pw_gen,
self.pkg_manager,
components=preq_components, **self.kargs)
preq_runner = ActionRunner(distro=self.distro,
action=preq_action,
directory=self.directory,
config=self.cfg,
pw_gen=self.pw_gen,
pkg_manager=self.pkg_manager,
components=preq_components,
**self.kargs)
preq_runner.run()
def _pre_run(self, instances, component_order):

16
stack
View File

@ -22,6 +22,7 @@ import traceback
from devstack import cfg_helpers
from devstack import date
from devstack.distro import Distro
from devstack import env
from devstack import env_rc
from devstack import log as logging
@ -102,12 +103,7 @@ def load_rc_files():
def run(args):
(distro, platform) = utils.determine_distro()
if distro is None:
print("Unsupported platform " + utils.color_text(platform, "red") + "!")
return False
distro = Distro.get_current()
action = args.pop("action").strip().lower()
if not (action in settings.ACTIONS):
print(utils.color_text("No valid action specified!", "red"))
@ -138,9 +134,11 @@ def run(args):
# Stash the dryrun value (if any) into the global configuration
sh.set_dryrun(args['dryrun'])
config = common.get_config()
pw_gen = passwords.PasswordGenerator(config, args['prompt_for_passwords'])
pkg_manager = common.get_packager(distro, args['keep_old'])
config_kv_cache = dict()
config = common.get_config(kv_cache=config_kv_cache)
pw_gen = passwords.PasswordGenerator(config_kv_cache, config, args['prompt_for_passwords'])
pkg_factory = distro.get_packager_factory()
pkg_manager = pkg_factory(distro, args['keep_old'])
components = utils.parse_components(args.pop("components"))
runner = actions.ActionRunner(distro, action, rootdir, config, pw_gen,