Initial attempt/work for personas

This commit is contained in:
Joshua Harlow 2012-03-15 14:22:14 -07:00
parent 7e9dc5f7fc
commit a20a06edac
31 changed files with 470 additions and 795 deletions

View File

@ -18,6 +18,8 @@ commands:
status: ["service", "apache2", "status"]
settings:
conf-link-target: /etc/apache2/sites-enabled/000-default
libvirt-daemon: 'libvirt-bin'
mysql:
start: ["service", "mysql", 'start']
@ -31,7 +33,12 @@ commands:
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;\""]
iscsi:
start: ['service', 'tgt', 'start']
stop: ['service', 'tgt', 'stop']
restart: ['service', 'tgt', 'restart']
status: ['service', 'tgt', 'status']
components:
db:
@ -435,7 +442,7 @@ components:
removable: True
version: 0.14.*
n-vnc:
no-vnc:
install: devstack.components.novnc:NoVNCInstaller
uninstall: devstack.components.novnc:NoVNCUninstaller
start: devstack.components.novnc:NoVNCRuntime
@ -664,7 +671,7 @@ components:
removable: True
version: 1.12*
rabbit:
rabbit-mq:
install: devstack.components.rabbit:RabbitInstaller
uninstall: devstack.components.rabbit:RabbitUninstaller
start: devstack.components.rabbit:RabbitRuntime

View File

@ -0,0 +1,31 @@
---
created_on: Wed, 14 Mar 2012 17:28:24 -0700
description: Devstack.sh matching component installation (as of the above date).
supports:
- rhel-6
- ubuntu-oneiric
- fedora-16
components:
- db
- rabbit-mq
- keystone-client
- keystone
- glance
- nova
- no-vnc
- quantum-client
- nova-client
- horizon
subsystems:
glance:
- api
- reg
nova:
- api
- cauth
- cert
- cpu
- net
- sched
- vol
- xvnc

View File

@ -22,6 +22,7 @@ from devstack import date
from devstack import env
from devstack import exceptions as excp
from devstack import log as logging
from devstack import settings
from devstack import shell as sh
from devstack import utils
@ -31,6 +32,16 @@ SUB_MATCH = re.compile(r"(?:\$\(([\w\d]+):([\w\d]+))\)")
CACHE_MSG = "(value will now be internally cached)"
def get_config(cfg_fn=None, cfg_cls=None):
if not cfg_fn:
cfg_fn = sh.canon_path(settings.STACK_CONFIG_LOCATION)
if not cfg_cls:
cfg_cls = StackConfigParser
config_instance = cfg_cls()
config_instance.read(cfg_fn)
return config_instance
class IgnoreMissingConfigParser(ConfigParser.RawConfigParser):
DEF_INT = 0
DEF_FLOAT = 0.0

View File

@ -32,12 +32,10 @@ def make_id(section, option):
def fetch_run_type(config):
run_type = config.getdefaulted("default", "run_type", settings.RUN_TYPE_DEF)
run_type = run_type.upper()
return run_type
return run_type.upper()
def fetch_dbdsn(config, pw_gen, dbname=''):
#check the dsn cache
user = config.get("db", "sql_user")
host = config.get("db", "sql_host")
port = config.get("db", "port")
@ -65,5 +63,5 @@ def fetch_dbdsn(config, pw_gen, dbname=''):
dsn += "/" + dbname
else:
dsn += "/"
LOG.debug("For database [%s] fetched dsn [%s]" % (dbname, dsn))
LOG.audit("For database [%s] fetched dsn [%s]" % (dbname, dsn))
return dsn

View File

@ -53,37 +53,40 @@ BASE_LINK_DIR = "/etc"
class ComponentBase(object):
def __init__(self, component_name, runner,
root_dir, component_options,
instances=None,
**kwds):
self.component_name = component_name
def __init__(self,
subsystems,
runner,
component_dir,
all_instances,
name,
*args,
**kargs):
# Required vars
self.subsystems = subsystems
self.instances = all_instances
# The runner has a reference to us, so use a weakref here to
# avoid breaking garbage collection.
self.runner = weakref.proxy(runner)
self.root = root_dir
self.component_opts = component_options or {}
self.instances = instances or {}
# Parts of the global runner context that we use
self.cfg = runner.cfg
self.pw_gen = runner.pw_gen
self.packager = runner.pkg_manager
self.distro = runner.distro
self.component_root = sh.joinpths(self.root, component_name)
self.tracedir = sh.joinpths(self.component_root,
# What this component is called
self.component_name = name
# Required component directories
self.component_dir = component_dir
self.trace_dir = sh.joinpths(self.component_dir,
settings.COMPONENT_TRACE_DIR)
self.appdir = sh.joinpths(self.component_root,
self.app_dir = sh.joinpths(self.component_dir,
settings.COMPONENT_APP_DIR)
self.cfgdir = sh.joinpths(self.component_root,
self.cfg_dir = sh.joinpths(self.component_dir,
settings.COMPONENT_CONFIG_DIR)
self.kargs = kwds
def get_dependencies(self):
return self.runner.distro.components[self.component_name].get('dependencies', [])[:]
def verify(self):
pass
@ -92,26 +95,25 @@ class ComponentBase(object):
pass
def is_started(self):
reader = tr.TraceReader(tr.trace_fn(self.tracedir, tr.START_TRACE))
reader = tr.TraceReader(tr.trace_fn(self.trace_dir, tr.START_TRACE))
return reader.exists()
def is_installed(self):
return tr.TraceReader(tr.trace_fn(self.tracedir, tr.IN_TRACE)).exists()
return tr.TraceReader(tr.trace_fn(self.trace_dir, tr.IN_TRACE)).exists()
class PkgInstallComponent(ComponentBase):
def __init__(self, component_name, **kargs):
ComponentBase.__init__(self, component_name, **kargs)
self.tracewriter = tr.TraceWriter(tr.trace_fn(self.tracedir,
tr.IN_TRACE)
)
def __init__(self, *args, **kargs):
ComponentBase.__init__(self, *args, **kargs)
self.tracewriter = tr.TraceWriter(tr.trace_fn(self.trace_dir,
tr.IN_TRACE))
def _get_download_locations(self):
return list()
def download(self):
locations = self._get_download_locations()
base_dir = self.appdir
base_dir = self.app_dir
for location_info in locations:
uri_tuple = location_info["uri"]
branch_tuple = location_info.get("branch")
@ -164,7 +166,7 @@ class PkgInstallComponent(ComponentBase):
else:
LOG.info('No packages to install for %s',
self.component_name)
return self.tracedir
return self.trace_dir
def pre_install(self):
pkgs = self.component_opts.get('packages', [])
@ -185,7 +187,7 @@ class PkgInstallComponent(ComponentBase):
return contents
def _get_target_config_name(self, config_fn):
return sh.joinpths(self.cfgdir, config_fn)
return sh.joinpths(self.cfg_dir, config_fn)
def _get_source_config(self, config_fn):
return utils.load_template(self.component_name, config_fn)
@ -246,12 +248,12 @@ class PkgInstallComponent(ComponentBase):
class PythonInstallComponent(PkgInstallComponent):
def __init__(self, component_name, *args, **kargs):
PkgInstallComponent.__init__(self, component_name, *args, **kargs)
def __init__(self, *args, **kargs):
PkgInstallComponent.__init__(self, *args, **kargs)
def _get_python_directories(self):
py_dirs = dict()
py_dirs[self.component_name] = self.appdir
py_dirs[self.component_name] = self.app_dir
return py_dirs
def _install_pips(self):
@ -273,7 +275,7 @@ class PythonInstallComponent(PkgInstallComponent):
LOG.info("Setting up %s python directories (%s)",
len(pydirs), pydirs)
for (name, wkdir) in pydirs.items():
working_dir = wkdir or self.appdir
working_dir = wkdir or self.app_dir
#ensure working dir is there
self.tracewriter.dirs_made(*sh.mkdirslist(working_dir))
#do this before write just incase it craps out half way through
@ -283,7 +285,7 @@ class PythonInstallComponent(PkgInstallComponent):
cwd=working_dir,
run_as_root=True)
py_trace_name = "%s-%s" % (tr.PY_TRACE, name)
py_writer = tr.TraceWriter(tr.trace_fn(self.tracedir,
py_writer = tr.TraceWriter(tr.trace_fn(self.trace_dir,
py_trace_name))
py_writer.trace("CMD", " ".join(PY_INSTALL))
py_writer.trace("STDOUT", stdout)
@ -301,11 +303,11 @@ class PythonInstallComponent(PkgInstallComponent):
class PkgUninstallComponent(ComponentBase):
def __init__(self, component_name, keep_old=None, **kargs):
ComponentBase.__init__(self, component_name, **kargs)
self.tracereader = tr.TraceReader(tr.trace_fn(self.tracedir,
def __init__(self, *args, **kargs):
ComponentBase.__init__(self, *args, **kargs)
self.tracereader = tr.TraceReader(tr.trace_fn(self.trace_dir,
tr.IN_TRACE))
self.keep_old = keep_old
self.keep_old = kargs.get('keep_old')
def unconfigure(self):
if not self.keep_old:
@ -321,7 +323,7 @@ class PkgUninstallComponent(ComponentBase):
if RUNNER_CLS_MAPPING:
LOG.info("Unconfiguring %s runners.", len(RUNNER_CLS_MAPPING))
for (_, cls) in RUNNER_CLS_MAPPING.items():
instance = cls(self.cfg, self.component_name, self.tracedir)
instance = cls(self.cfg, self.component_name, self.trace_dir)
instance.unconfigure()
def _unconfigure_links(self):
@ -386,8 +388,8 @@ class PkgUninstallComponent(ComponentBase):
class PythonUninstallComponent(PkgUninstallComponent):
def __init__(self, component_name, *args, **kargs):
PkgUninstallComponent.__init__(self, component_name, *args, **kargs)
def __init__(self, *args, **kargs):
PkgUninstallComponent.__init__(self, *args, **kargs)
def uninstall(self):
self._uninstall_python()
@ -409,10 +411,10 @@ class PythonUninstallComponent(PkgUninstallComponent):
class ProgramRuntime(ComponentBase):
def __init__(self, component_name, **kargs):
ComponentBase.__init__(self, component_name, **kargs)
self.tracewriter = tr.TraceWriter(tr.trace_fn(self.tracedir, tr.START_TRACE))
self.tracereader = tr.TraceReader(tr.trace_fn(self.tracedir, tr.START_TRACE))
def __init__(self, *args, **kargs):
ComponentBase.__init__(self, *args, **kargs)
self.tracewriter = tr.TraceWriter(tr.trace_fn(self.trace_dir, tr.START_TRACE))
self.tracereader = tr.TraceReader(tr.trace_fn(self.trace_dir, tr.START_TRACE))
def _get_apps_to_start(self):
return list()
@ -422,7 +424,7 @@ class ProgramRuntime(ComponentBase):
def _get_param_map(self, app_name):
return {
'ROOT': self.appdir,
'ROOT': self.app_dir,
}
def pre_start(self):
@ -435,12 +437,12 @@ class ProgramRuntime(ComponentBase):
# First make a pass and make sure all runtime (e.g. upstart)
# config files are in place....
cls = RUNNER_CLS_MAPPING[cfg_helpers.fetch_run_type(self.cfg)]
instance = cls(self.cfg, self.component_name, self.tracedir)
instance = cls(self.cfg, self.component_name, self.trace_dir)
tot_am = 0
for app_info in self._get_apps_to_start():
app_name = app_info["name"]
app_pth = app_info.get("path", app_name)
app_dir = app_info.get("app_dir", self.appdir)
app_dir = app_info.get("app_dir", self.app_dir)
# Adjust the program options now that we have real locations
program_opts = utils.param_replace_list(
self._get_app_options(app_name),
@ -458,12 +460,12 @@ class ProgramRuntime(ComponentBase):
def start(self):
# Select how we are going to start it
cls = RUNNER_CLS_MAPPING[cfg_helpers.fetch_run_type(self.cfg)]
instance = cls(self.cfg, self.component_name, self.tracedir)
instance = cls(self.cfg, self.component_name, self.trace_dir)
am_started = 0
for app_info in self._get_apps_to_start():
app_name = app_info["name"]
app_pth = app_info.get("path", app_name)
app_dir = app_info.get("app_dir", self.appdir)
app_dir = app_info.get("app_dir", self.app_dir)
# Adjust the program options now that we have real locations
program_opts = utils.param_replace_list(
self._get_app_options(app_name),
@ -500,7 +502,7 @@ class ProgramRuntime(ComponentBase):
else:
killer = killcls(self.cfg,
self.component_name,
self.tracedir,
self.trace_dir,
)
killer_instances[killcls] = killer
to_kill.append((app_name, killer))
@ -526,14 +528,14 @@ class ProgramRuntime(ComponentBase):
class PythonRuntime(ProgramRuntime):
def __init__(self, component_name, *args, **kargs):
ProgramRuntime.__init__(self, component_name, *args, **kargs)
def __init__(self, *args, **kargs):
ProgramRuntime.__init__(self, *args, **kargs)
class EmptyRuntime(ComponentBase):
def __init__(self, component_name, **kargs):
ComponentBase.__init__(self, component_name, **kargs)
self.tracereader = tr.TraceReader(tr.trace_fn(self.tracedir, tr.IN_TRACE))
def __init__(self, *args, **kargs):
ComponentBase.__init__(self, *args, **kargs)
self.tracereader = tr.TraceReader(tr.trace_fn(self.trace_dir, tr.IN_TRACE))
def configure(self):
return 0

View File

@ -21,8 +21,6 @@ from devstack import settings
from devstack import shell as sh
from devstack import utils
#id
TYPE = settings.DB
LOG = logging.getLogger("devstack.components.db")
#used for special setups
@ -239,7 +237,7 @@ class DBRuntime(comp.EmptyRuntime):
def drop_db(cfg, pw_gen, distro, dbname):
dbtype = cfg.get("db", "type")
dbactions = distro.commands[dbtype]
dbactions = distro.get_command(dbtype)
if dbactions and dbactions.get('drop_db'):
dropcmd = dbactions.get('drop_db')
params = dict()
@ -259,7 +257,7 @@ def drop_db(cfg, pw_gen, distro, dbname):
def create_db(cfg, pw_gen, distro, dbname):
dbtype = cfg.get("db", "type")
dbactions = distro.commands[dbtype]
dbactions = distro.get_command(dbtype)
if dbactions and dbactions.get('create_db'):
createcmd = dbactions.get('create_db')
params = dict()

View File

@ -28,8 +28,6 @@ from devstack.components import keystone
from devstack.image import creator
#id
TYPE = settings.GLANCE
LOG = logging.getLogger("devstack.components.glance")
#config files/sections
@ -82,13 +80,13 @@ BIN_DIR = 'bin'
class GlanceUninstaller(comp.PythonUninstallComponent):
def __init__(self, *args, **kargs):
comp.PythonUninstallComponent.__init__(self, *args, **kargs)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
class GlanceInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs):
comp.PythonInstallComponent.__init__(self, *args, **kargs)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
def _get_download_locations(self):
places = list()
@ -112,11 +110,11 @@ class GlanceInstaller(comp.PythonInstallComponent):
def _get_source_config(self, config_fn):
if config_fn == POLICY_JSON:
fn = sh.joinpths(self.cfgdir, POLICY_JSON)
fn = sh.joinpths(self.cfg_dir, POLICY_JSON)
contents = sh.load_file(fn)
return (fn, contents)
elif config_fn == LOGGING_CONF:
fn = sh.joinpths(self.cfgdir, LOGGING_SOURCE_FN)
fn = sh.joinpths(self.cfg_dir, LOGGING_SOURCE_FN)
contents = sh.load_file(fn)
return (fn, contents)
return comp.PythonInstallComponent._get_source_config(self, config_fn)
@ -171,7 +169,7 @@ class GlanceInstaller(comp.PythonInstallComponent):
#this dict will be used to fill in the configuration
#params with actual values
mp = dict()
mp['DEST'] = self.appdir
mp['DEST'] = self.app_dir
mp['SYSLOG'] = self.cfg.getboolean("default", "syslog")
mp['SQL_CONN'] = cfg_helpers.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
mp['SERVICE_HOST'] = self.cfg.get('host', 'ip')
@ -183,11 +181,11 @@ class GlanceInstaller(comp.PythonInstallComponent):
class GlanceRuntime(comp.PythonRuntime):
def __init__(self, *args, **kargs):
comp.PythonRuntime.__init__(self, *args, **kargs)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
def _get_apps_to_start(self):
apps = [{'name': app_name,
'path': sh.joinpths(self.appdir, BIN_DIR, app_name),
'path': sh.joinpths(self.app_dir, BIN_DIR, app_name),
}
for app_name in APP_OPTIONS.keys()
]

View File

@ -21,8 +21,6 @@ from devstack import settings
from devstack import shell as sh
from devstack import utils
#id
TYPE = settings.HORIZON
LOG = logging.getLogger("devstack.components.horizon")
#actual dir names
@ -52,11 +50,12 @@ APACHE_ACCESS_LOG_FN = "access.log"
APACHE_DEF_PORT = 80
#TODO: maybe this should be a subclass that handles these differences
APACHE_FIXUPS = {
'SOCKET_CONF': "/etc/httpd/conf.d/wsgi-socket-prefix.conf",
'HTTPD_CONF': '/etc/httpd/conf/httpd.conf',
}
APACHE_FIXUPS_DISTROS = [settings.RHEL6, settings.FEDORA16]
# APACHE_FIXUPS = {
# 'SOCKET_CONF': "/etc/httpd/conf.d/wsgi-socket-prefix.conf",
# 'HTTPD_CONF': '/etc/httpd/conf/httpd.conf',
# }
# APACHE_FIXUPS_DISTROS = [settings.RHEL6, settings.FEDORA16]
APACHE_FIXUPS_DISTROS = []
#for when quantum client is not need we need some fake files so python doesn't croak
FAKE_QUANTUM_FILES = ['__init__.py', 'client.py']
@ -76,9 +75,9 @@ class HorizonUninstaller(comp.PythonUninstallComponent):
class HorizonInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs):
comp.PythonInstallComponent.__init__(self, *args, **kargs)
self.horizon_dir = sh.joinpths(self.appdir, ROOT_HORIZON)
self.dash_dir = sh.joinpths(self.appdir, ROOT_DASH)
self.log_dir = sh.joinpths(self.component_root, LOGS_DIR)
self.horizon_dir = sh.joinpths(self.app_dir, ROOT_HORIZON)
self.dash_dir = sh.joinpths(self.app_dir, ROOT_DASH)
self.log_dir = sh.joinpths(self.component_dir, LOGS_DIR)
def _get_download_locations(self):
places = list()
@ -98,7 +97,7 @@ class HorizonInstaller(comp.PythonInstallComponent):
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]
src_pth = sh.joinpths(qc.appdir, 'quantum')
src_pth = sh.joinpths(qc.app_dir, 'quantum')
tgt_dir = sh.joinpths(self.dash_dir, 'quantum')
links[src_pth] = tgt_dir
return links
@ -126,13 +125,13 @@ class HorizonInstaller(comp.PythonInstallComponent):
def _setup_blackhole(self):
#create an empty directory that apache uses as docroot
self.tracewriter.dirs_made(*sh.mkdirslist(sh.joinpths(self.appdir, BLACKHOLE_DIR)))
self.tracewriter.dirs_made(*sh.mkdirslist(sh.joinpths(self.app_dir, BLACKHOLE_DIR)))
def _sync_db(self):
#Initialize the horizon database (it stores sessions and notices shown to users).
#The user system is external (keystone).
LOG.info("Initializing the horizon database.")
sh.execute(*DB_SYNC_CMD, cwd=self.appdir)
sh.execute(*DB_SYNC_CMD, cwd=self.app_dir)
def _ensure_db_access(self):
# ../openstack-dashboard/local needs to be writeable by the runtime user
@ -208,10 +207,10 @@ class HorizonInstaller(comp.PythonInstallComponent):
mp['ACCESS_LOG'] = sh.joinpths(self.log_dir, APACHE_ACCESS_LOG_FN)
mp['ERROR_LOG'] = sh.joinpths(self.log_dir, APACHE_ERROR_LOG_FN)
mp['GROUP'] = group
mp['HORIZON_DIR'] = self.appdir
mp['HORIZON_DIR'] = self.app_dir
mp['HORIZON_PORT'] = self.cfg.getdefaulted('horizon', 'port', APACHE_DEF_PORT)
mp['USER'] = user
mp['VPN_DIR'] = sh.joinpths(self.appdir, "vpn")
mp['VPN_DIR'] = sh.joinpths(self.app_dir, "vpn")
else:
mp['OPENSTACK_HOST'] = self.cfg.get('host', 'ip')
return mp

View File

@ -28,8 +28,6 @@ from devstack import utils
from devstack.components import db
#id
TYPE = settings.KEYSTONE
LOG = logging.getLogger("devstack.components.keystone")
#this db will be dropped then created
@ -86,15 +84,15 @@ QUANTUM_TEMPL_ADDS = ['catalog.RegionOne.network.publicURL = http://%SERVICE_HOS
class KeystoneUninstaller(comp.PythonUninstallComponent):
def __init__(self, *args, **kargs):
comp.PythonUninstallComponent.__init__(self, *args, **kargs)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
class KeystoneInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs):
comp.PythonInstallComponent.__init__(self, *args, **kargs)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
def _get_download_locations(self):
places = list()
@ -113,9 +111,9 @@ class KeystoneInstaller(comp.PythonInstallComponent):
def _sync_db(self):
LOG.info("Syncing keystone to database named %s.", DB_NAME)
params = dict()
params['BINDIR'] = self.bindir
params['BINDIR'] = self.bin_dir
cmds = [{'cmd': SYNC_DB_CMD}]
utils.execute_template(*cmds, cwd=self.bindir, params=params)
utils.execute_template(*cmds, cwd=self.bin_dir, params=params)
def _get_config_files(self):
return list(CONFIGS)
@ -130,7 +128,7 @@ class KeystoneInstaller(comp.PythonInstallComponent):
(_, contents) = utils.load_template(self.component_name, MANAGE_DATA_CONF)
params = self._get_param_map(MANAGE_DATA_CONF)
contents = utils.param_replace(contents, params, True)
tgt_fn = sh.joinpths(self.bindir, MANAGE_DATA_CONF)
tgt_fn = sh.joinpths(self.bin_dir, MANAGE_DATA_CONF)
sh.write_file(tgt_fn, contents)
sh.chmod(tgt_fn, 0755)
self.tracewriter.file_touched(tgt_fn)
@ -175,7 +173,7 @@ class KeystoneInstaller(comp.PythonInstallComponent):
def _get_source_config(self, config_fn):
if config_fn == LOGGING_CONF:
fn = sh.joinpths(self.cfgdir, LOGGING_SOURCE_FN)
fn = sh.joinpths(self.cfg_dir, LOGGING_SOURCE_FN)
contents = sh.load_file(fn)
return (fn, contents)
return comp.PythonInstallComponent._get_source_config(self, config_fn)
@ -188,12 +186,12 @@ class KeystoneInstaller(comp.PythonInstallComponent):
#params with actual values
mp = dict()
mp['SERVICE_HOST'] = self.cfg.get('host', 'ip')
mp['DEST'] = self.appdir
mp['BIN_DIR'] = self.bindir
mp['CONFIG_FILE'] = sh.joinpths(self.cfgdir, ROOT_CONF)
mp['DEST'] = self.app_dir
mp['BIN_DIR'] = self.bin_dir
mp['CONFIG_FILE'] = sh.joinpths(self.cfg_dir, ROOT_CONF)
if config_fn == ROOT_CONF:
mp['SQL_CONN'] = cfg_helpers.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
mp['KEYSTONE_DIR'] = self.appdir
mp['KEYSTONE_DIR'] = self.app_dir
mp.update(get_shared_params(self.cfg, self.pw_gen))
elif config_fn == MANAGE_DATA_CONF:
mp.update(get_shared_params(self.cfg, self.pw_gen))
@ -203,11 +201,11 @@ class KeystoneInstaller(comp.PythonInstallComponent):
class KeystoneRuntime(comp.PythonRuntime):
def __init__(self, *args, **kargs):
comp.PythonRuntime.__init__(self, *args, **kargs)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
def post_start(self):
tgt_fn = sh.joinpths(self.bindir, MANAGE_DATA_CONF)
tgt_fn = sh.joinpths(self.bin_dir, MANAGE_DATA_CONF)
if sh.isfile(tgt_fn):
#still there, run it
#these environment additions are important
@ -216,7 +214,7 @@ class KeystoneRuntime(comp.PythonRuntime):
sh.sleep(WAIT_ONLINE_TO)
env = dict()
env['ENABLED_SERVICES'] = ",".join(self.instances.keys())
env['BIN_DIR'] = self.bindir
env['BIN_DIR'] = self.bin_dir
setup_cmd = MANAGE_CMD_ROOT + [tgt_fn]
LOG.info("Running (%s) command to initialize keystone." % (" ".join(setup_cmd)))
sh.execute(*setup_cmd, env_overrides=env, run_as_root=False)
@ -228,7 +226,7 @@ class KeystoneRuntime(comp.PythonRuntime):
for app_name in APP_OPTIONS.keys():
apps.append({
'name': app_name,
'path': sh.joinpths(self.bindir, app_name),
'path': sh.joinpths(self.bin_dir, app_name),
})
return apps

View File

@ -18,8 +18,6 @@ from devstack import component as comp
from devstack import log as logging
from devstack import settings
#id
TYPE = settings.KEYSTONE_CLIENT
LOG = logging.getLogger("devstack.components.keystone_client")

View File

@ -26,8 +26,6 @@ from devstack import utils
from devstack.components import db
#id
TYPE = settings.MELANGE
LOG = logging.getLogger("devstack.components.melange")
#this db will be dropped then created
@ -47,7 +45,7 @@ DEF_CIDR_RANGE = 'FE-EE-DD-00-00-00/24'
#how we sync melange with the db
DB_SYNC_CMD = [
{'cmd': ['%BINDIR%/melange-manage', '--config-file=%CFG_FILE%', 'db_sync']},
{'cmd': ['%BIN_DIR%/melange-manage', '--config-file=%CFG_FILE%', 'db_sync']},
]
#???
@ -73,8 +71,8 @@ class MelangeUninstaller(comp.PythonUninstallComponent):
class MelangeInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs):
comp.PythonInstallComponent.__init__(self, *args, **kargs)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.cfgdir = sh.joinpths(self.appdir, *CFG_LOC)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, *CFG_LOC)
def _get_download_locations(self):
places = list()
@ -97,8 +95,8 @@ class MelangeInstaller(comp.PythonInstallComponent):
def _sync_db(self):
LOG.info("Syncing the database with melange.")
mp = dict()
mp['BINDIR'] = self.bindir
mp['CFG_FILE'] = sh.joinpths(self.cfgdir, ROOT_CONF_REAL_NAME)
mp['BIN_DIR'] = self.bin_dir
mp['CFG_FILE'] = sh.joinpths(self.cfg_dir, ROOT_CONF_REAL_NAME)
utils.execute_template(*DB_SYNC_CMD, params=mp)
def _get_config_files(self):
@ -123,7 +121,7 @@ class MelangeInstaller(comp.PythonInstallComponent):
def _get_source_config(self, config_fn):
if config_fn == ROOT_CONF:
srcfn = sh.joinpths(self.cfgdir, config_fn)
srcfn = sh.joinpths(self.cfg_dir, config_fn)
contents = sh.load_file(srcfn)
return (srcfn, contents)
else:
@ -131,7 +129,7 @@ class MelangeInstaller(comp.PythonInstallComponent):
def _get_target_config_name(self, config_fn):
if config_fn == ROOT_CONF:
return sh.joinpths(self.cfgdir, ROOT_CONF_REAL_NAME)
return sh.joinpths(self.cfg_dir, ROOT_CONF_REAL_NAME)
else:
return comp.PythonInstallComponent._get_target_config_name(self, config_fn)
@ -139,15 +137,15 @@ class MelangeInstaller(comp.PythonInstallComponent):
class MelangeRuntime(comp.PythonRuntime):
def __init__(self, *args, **kargs):
comp.PythonRuntime.__init__(self, *args, **kargs)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.cfgdir = sh.joinpths(self.appdir, *CFG_LOC)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, *CFG_LOC)
def _get_apps_to_start(self):
apps = list()
for app_name in APP_OPTIONS.keys():
apps.append({
'name': app_name,
'path': sh.joinpths(self.bindir, app_name),
'path': sh.joinpths(self.bin_dir, app_name),
})
return apps
@ -156,7 +154,7 @@ class MelangeRuntime(comp.PythonRuntime):
def _get_param_map(self, app_name):
pmap = comp.PythonRuntime._get_param_map(self, app_name)
pmap['CFG_FILE'] = sh.joinpths(self.cfgdir, ROOT_CONF_REAL_NAME)
pmap['CFG_FILE'] = sh.joinpths(self.cfg_dir, ROOT_CONF_REAL_NAME)
return pmap
def post_start(self):

View File

@ -18,8 +18,6 @@ from devstack import component as comp
from devstack import log as logging
from devstack import settings
#id
TYPE = settings.MELANGE_CLIENT
LOG = logging.getLogger("devstack.components.melange_client")

View File

@ -29,17 +29,15 @@ from devstack import utils
from devstack.components import db
from devstack.components import keystone
#id
TYPE = settings.NOVA
LOG = logging.getLogger('devstack.components.nova')
#special generated conf
# Special generated conf
API_CONF = 'nova.conf'
#how we reference some config files (in applications)
# How we reference some config files (in applications)
CFG_FILE_OPT = '--config-file'
#normal conf
# Normal conf
PASTE_CONF = 'nova-api-paste.ini'
PASTE_SOURCE_FN = 'api-paste.ini'
POLICY_CONF = 'policy.json'
@ -48,19 +46,19 @@ LOGGING_CONF = "logging.conf"
CONFIGS = [PASTE_CONF, POLICY_CONF, LOGGING_CONF]
ADJUST_CONFIGS = [PASTE_CONF]
#this is a special conf
# This is a special conf
NET_INIT_CONF = 'nova-network-init.sh'
NET_INIT_CMD_ROOT = [sh.joinpths("/", "bin", 'bash')]
#this db will be dropped then created
# This db will be dropped then created
DB_NAME = 'nova'
#this makes the database be in sync with nova
# This makes the database be in sync with nova
DB_SYNC_CMD = [
{'cmd': ['%BINDIR%/nova-manage', CFG_FILE_OPT, '%CFGFILE%', 'db', 'sync']},
{'cmd': ['%BIN_DIR%/nova-manage', CFG_FILE_OPT, '%CFGFILE%', 'db', 'sync']},
]
#these are used for nova volumens
# These are used for nova volumes
VG_CHECK_CMD = [
{'cmd': ['vgs', '%VOLUME_GROUP%'],
'run_as_root': True}
@ -82,21 +80,6 @@ VG_LVREMOVE_CMD = [
'run_as_root': True}
]
# iscsi restart commands
RESTART_TGT_CMD = {
settings.UBUNTU11: [
{'cmd': ['stop', 'tgt'], 'run_as_root': True},
{'cmd': ['start', 'tgt'], 'run_as_root': True}
],
settings.RHEL6: [
{'cmd': ['service', 'tgtd', 'stop'], 'run_as_root': True},
{'cmd': ['service', 'tgtd', 'start'], 'run_as_root': True}
],
settings.FEDORA16: [
{'cmd': ['service', 'tgtd', 'stop'], 'run_as_root': True},
{'cmd': ['service', 'tgtd', 'start'], 'run_as_root': True}
],
}
# NCPU, NVOL, NAPI ... are here as possible subcomponents of nova
NCPU = "cpu"
@ -187,16 +170,15 @@ CLEANER_CMD_ROOT = [sh.joinpths("/", "bin", 'bash')]
#rhel6/fedora libvirt policy
#http://wiki.libvirt.org/page/SSHPolicyKitSetup
LIBVIRT_POLICY_FN = "/etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla"
LIBVIRT_POLICY_CONTENTS = """
[libvirt Management Access]
Identity=unix-group:libvirtd
Action=org.libvirt.unix.manage
ResultAny=yes
ResultInactive=yes
ResultActive=yes
"""
POLICY_DISTROS = [settings.RHEL6, settings.FEDORA16]
#LIBVIRT_POLICY_FN = "/etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla"
#LIBVIRT_POLICY_CONTENTS = """
#[libvirt Management Access]
#Identity=unix-group:libvirtd
#Action=org.libvirt.unix.manage
#ResultAny=yes
#ResultInactive=yes
#ResultActive=yes
#"""
#xenserver specific defaults
XS_DEF_INTERFACE = 'eth1'
@ -245,8 +227,8 @@ def _canon_libvirt_type(virt_type):
class NovaUninstaller(comp.PythonUninstallComponent):
def __init__(self, *args, **kargs):
comp.PythonUninstallComponent.__init__(self, *args, **kargs)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
def pre_uninstall(self):
self._clear_libvirt_domains()
@ -256,10 +238,10 @@ class NovaUninstaller(comp.PythonUninstallComponent):
#these environment additions are important
#in that they eventually affect how this script runs
env = dict()
env['ENABLED_SERVICES'] = ",".join(SUBCOMPONENTS)
env['BIN_DIR'] = self.bindir
env['ENABLED_SERVICES'] = ",".join(self.subsystems)
env['BIN_DIR'] = self.bin_dir
env['VOLUME_NAME_PREFIX'] = self.cfg.getdefaulted('nova', 'volume_name_prefix', DEF_VOL_PREFIX)
cleaner_fn = sh.joinpths(self.bindir, CLEANER_DATA_CONF)
cleaner_fn = sh.joinpths(self.bin_dir, CLEANER_DATA_CONF)
if sh.isfile(cleaner_fn):
LOG.info("Cleaning up your system by running nova cleaner script [%s]." % (cleaner_fn))
cmd = CLEANER_CMD_ROOT + [cleaner_fn]
@ -270,28 +252,25 @@ 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.name, libvirt_type, inst_prefix)
virsh.clear_libvirt_domains(self.distro, libvirt_type, inst_prefix)
class NovaInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs):
comp.PythonInstallComponent.__init__(self, *args, **kargs)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.paste_conf_fn = self._get_target_config_name(PASTE_CONF)
self.volumes_enabled = False
package_names = [p['name']
for p in self.component_opts.get('packages', [])
]
if NVOL in package_names:
if NVOL in self.subsystems:
self.volumes_enabled = True
self.xvnc_enabled = False
if NXVNC in package_names:
if NXVNC in self.subsystems:
self.xvnc_enabled = True
def _get_symlinks(self):
links = comp.PythonInstallComponent._get_symlinks(self)
source_fn = sh.joinpths(self.cfgdir, API_CONF)
source_fn = sh.joinpths(self.cfg_dir, API_CONF)
links[source_fn] = sh.joinpths(self._get_link_dir(), API_CONF)
return links
@ -318,7 +297,7 @@ class NovaInstaller(comp.PythonInstallComponent):
(_, contents) = utils.load_template(self.component_name, NET_INIT_CONF)
params = self._get_param_map(NET_INIT_CONF)
contents = utils.param_replace(contents, params, True)
tgt_fn = sh.joinpths(self.bindir, NET_INIT_CONF)
tgt_fn = sh.joinpths(self.bin_dir, NET_INIT_CONF)
sh.write_file(tgt_fn, contents)
sh.chmod(tgt_fn, 0755)
self.tracewriter.file_touched(tgt_fn)
@ -326,8 +305,8 @@ class NovaInstaller(comp.PythonInstallComponent):
def _sync_db(self):
LOG.info("Syncing the database with nova.")
mp = dict()
mp['BINDIR'] = self.bindir
mp['CFGFILE'] = sh.joinpths(self.cfgdir, API_CONF)
mp['BIN_DIR'] = self.bin_dir
mp['CFGFILE'] = sh.joinpths(self.cfg_dir, API_CONF)
utils.execute_template(*DB_SYNC_CMD, params=mp)
def post_install(self):
@ -345,7 +324,7 @@ class NovaInstaller(comp.PythonInstallComponent):
def _setup_cleaner(self):
LOG.info("Configuring cleaner template %s.", CLEANER_DATA_CONF)
(_, contents) = utils.load_template(self.component_name, CLEANER_DATA_CONF)
tgt_fn = sh.joinpths(self.bindir, CLEANER_DATA_CONF)
tgt_fn = sh.joinpths(self.bin_dir, CLEANER_DATA_CONF)
sh.write_file(tgt_fn, contents)
sh.chmod(tgt_fn, 0755)
self.tracewriter.file_touched(tgt_fn)
@ -372,15 +351,15 @@ class NovaInstaller(comp.PythonInstallComponent):
return comp.PythonInstallComponent._get_source_config(self, PASTE_SOURCE_FN)
elif config_fn == LOGGING_CONF:
name = LOGGING_SOURCE_FN
srcfn = sh.joinpths(self.cfgdir, "nova", name)
srcfn = sh.joinpths(self.cfg_dir, "nova", name)
contents = sh.load_file(srcfn)
return (srcfn, contents)
def _get_param_map(self, config_fn):
mp = dict()
if config_fn == NET_INIT_CONF:
mp['NOVA_DIR'] = self.appdir
mp['CFG_FILE'] = sh.joinpths(self.cfgdir, API_CONF)
mp['NOVA_DIR'] = self.app_dir
mp['CFG_FILE'] = sh.joinpths(self.cfg_dir, API_CONF)
mp['FLOATING_RANGE'] = self.cfg.getdefaulted('nova', 'floating_range', '172.24.4.224/28')
mp['TEST_FLOATING_RANGE'] = self.cfg.getdefaulted('nova', 'test_floating_range', '192.168.253.0/29')
mp['TEST_FLOATING_POOL'] = self.cfg.getdefaulted('nova', 'test_floating_pool', 'test')
@ -394,15 +373,16 @@ class NovaInstaller(comp.PythonInstallComponent):
configs_made = comp.PythonInstallComponent.configure(self)
self._generate_nova_conf()
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.name in POLICY_DISTROS) and driver_canon == 'libvirt':
# TODO maybe move this??
if driver_canon == 'libvirt' and self.distro.get_command('virt-policy', quiet=True):
(fn, contents) = self.distro.get_command('virt-policy')
dirs_made = list()
with sh.Rooted(True):
dirs_made = sh.mkdirslist(sh.dirname(LIBVIRT_POLICY_FN))
sh.write_file(LIBVIRT_POLICY_FN, LIBVIRT_POLICY_CONTENTS)
dirs_made = sh.mkdirslist(sh.dirname(fn))
sh.write_file(fn, contents)
self.tracewriter.dirs_made(*dirs_made)
self.tracewriter.cfg_file_written(LIBVIRT_POLICY_FN)
self.tracewriter.cfg_file_written(fn)
configs_made += 1
return configs_made
@ -410,11 +390,11 @@ class NovaInstaller(comp.PythonInstallComponent):
class NovaRuntime(comp.PythonRuntime):
def __init__(self, *args, **kargs):
comp.PythonRuntime.__init__(self, *args, **kargs)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
def _setup_network_init(self):
tgt_fn = sh.joinpths(self.bindir, NET_INIT_CONF)
tgt_fn = sh.joinpths(self.bin_dir, NET_INIT_CONF)
if sh.isfile(tgt_fn):
LOG.info("Creating your nova network to be used with instances.")
#still there, run it
@ -434,16 +414,9 @@ class NovaRuntime(comp.PythonRuntime):
def post_start(self):
self._setup_network_init()
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
def _get_apps_to_start(self):
result = [{'name': app_name,
'path': sh.joinpths(self.bindir, app_name),
'path': sh.joinpths(self.bin_dir, app_name),
}
for app_name in sorted(APP_OPTIONS.keys())
]
@ -456,15 +429,15 @@ 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.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.name, DEF_VIRT_TYPE))
if not virsh.virt_ok(virt_type, self.distro):
msg = ("Libvirt type %s does not seem to be active or configured correctly, "
"perhaps you should be using %s instead." % (virt_type, DEF_VIRT_TYPE))
raise exceptions.StartException(msg)
virsh.restart(self.distro.name)
virsh.restart(self.distro)
def _get_param_map(self, app_name):
params = comp.PythonRuntime._get_param_map(self, app_name)
params['CFGFILE'] = sh.joinpths(self.cfgdir, API_CONF)
params['CFGFILE'] = sh.joinpths(self.cfg_dir, API_CONF)
return params
def _get_app_options(self, app):
@ -476,7 +449,7 @@ class NovaRuntime(comp.PythonRuntime):
class NovaVolumeConfigurator(object):
def __init__(self, ni):
self.cfg = ni.cfg
self.appdir = ni.appdir
self.app_dir = ni.app_dir
self.distro = ni.distro
def setup_volumes(self):
@ -485,7 +458,7 @@ class NovaVolumeConfigurator(object):
def _setup_vol_groups(self):
LOG.info("Attempting to setup volume groups for nova volume management.")
mp = dict()
backing_file = self.cfg.getdefaulted('nova', 'volume_backing_file', sh.joinpths(self.appdir, 'nova-volumes-backing-file'))
backing_file = self.cfg.getdefaulted('nova', 'volume_backing_file', sh.joinpths(self.app_dir, 'nova-volumes-backing-file'))
vol_group = self.cfg.getdefaulted('nova', 'volume_group', 'nova-volumes')
backing_file_size = utils.to_bytes(self.cfg.getdefaulted('nova', 'volume_backing_file_size', '2052M'))
mp['VOLUME_GROUP'] = vol_group
@ -512,7 +485,10 @@ 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.name], check_exit_code=False)
iscsi_cmds = self.distro.get_command('iscsi', quiet=True)
if iscsi_cmds:
restart_cmd = iscsi_cmds['restart']
utils.execute_template(*restart_cmd, run_as_root=True, check_exit_code=False)
def _process_lvs(self, mp):
LOG.info("Attempting to setup logical volumes for nova volume management.")
@ -548,12 +524,12 @@ class NovaConfConfigurator(object):
self.cfg = ni.cfg
self.pw_gen = ni.pw_gen
self.instances = ni.instances
self.component_root = ni.component_root
self.appdir = ni.appdir
self.component_dir = ni.component_dir
self.app_dir = ni.app_dir
self.tracewriter = ni.tracewriter
self.paste_conf_fn = ni.paste_conf_fn
self.distro = ni.distro
self.cfgdir = ni.cfgdir
self.cfg_dir = ni.cfg_dir
self.xvnc_enabled = ni.xvnc_enabled
self.volumes_enabled = ni.volumes_enabled
self.novnc_enabled = utils.service_enabled(settings.NOVNC, self.instances)
@ -649,7 +625,7 @@ class NovaConfConfigurator(object):
nova_conf.add('rabbit_password', self.cfg.get("passwords", "rabbit"))
#where instances will be stored
instances_path = self._getstr('instances_path', sh.joinpths(self.component_root, 'instances'))
instances_path = self._getstr('instances_path', sh.joinpths(self.component_dir, 'instances'))
self._configure_instances_path(instances_path, nova_conf)
#is this a multihost setup?
@ -766,7 +742,7 @@ class NovaConfConfigurator(object):
nova_conf.add('network_manager', NET_MANAGER_TEMPLATE % (self._getstr('network_manager', DEF_NET_MANAGER)))
#dhcp bridge stuff???
nova_conf.add('dhcpbridge_flagfile', sh.joinpths(self.cfgdir, API_CONF))
nova_conf.add('dhcpbridge_flagfile', sh.joinpths(self.cfg_dir, API_CONF))
#Network prefix for the IP network that all the projects for future VM guests reside on. Example: 192.168.0.0/12
nova_conf.add('fixed_range', self._getstr('fixed_range'))

View File

@ -18,8 +18,6 @@ from devstack import component as comp
from devstack import log as logging
from devstack import settings
#id
TYPE = settings.NOVA_CLIENT
LOG = logging.getLogger("devstack.components.nova_client")

View File

@ -22,8 +22,6 @@ from devstack import utils
from devstack.components import nova
#id
TYPE = settings.NOVNC
LOG = logging.getLogger("devstack.components.novnc")
#where the application is really
@ -67,7 +65,7 @@ class NoVNCRuntime(comp.ProgramRuntime):
for app_name in APP_OPTIONS.keys():
apps.append({
'name': app_name,
'path': sh.joinpths(self.appdir, UTIL_DIR, app_name),
'path': sh.joinpths(self.app_dir, UTIL_DIR, app_name),
})
return apps
@ -76,7 +74,7 @@ class NoVNCRuntime(comp.ProgramRuntime):
if app_name == VNC_PROXY_APP and utils.service_enabled(settings.NOVA, self.instances, False):
#have to reach into the nova conf (puke)
nova_runtime = self.instances[settings.NOVA]
root_params['NOVA_CONF'] = sh.joinpths(nova_runtime.cfgdir, nova.API_CONF)
root_params['NOVA_CONF'] = sh.joinpths(nova_runtime.cfg_dir, nova.API_CONF)
return root_params
def _get_app_options(self, app):

View File

@ -26,8 +26,6 @@ from devstack import utils
from devstack.components import db
#id
TYPE = settings.QUANTUM
LOG = logging.getLogger("devstack.components.quantum")
#vswitch pkgs
@ -117,10 +115,10 @@ class QuantumInstaller(comp.PkgInstallComponent):
def _get_target_config_name(self, config_fn):
if config_fn == PLUGIN_CONF:
tgt_loc = [self.appdir] + PLUGIN_LOC + [config_fn]
tgt_loc = [self.app_dir] + PLUGIN_LOC + [config_fn]
return sh.joinpths(*tgt_loc)
elif config_fn == AGENT_CONF:
tgt_loc = [self.appdir] + AGENT_LOC + [config_fn]
tgt_loc = [self.app_dir] + AGENT_LOC + [config_fn]
return sh.joinpths(*tgt_loc)
else:
return comp.PkgInstallComponent._get_target_config_name(self, config_fn)
@ -190,12 +188,12 @@ class QuantumInstaller(comp.PkgInstallComponent):
def _get_source_config(self, config_fn):
if config_fn == PLUGIN_CONF:
srcloc = [self.appdir] + PLUGIN_LOC + [config_fn]
srcloc = [self.app_dir] + PLUGIN_LOC + [config_fn]
srcfn = sh.joinpths(*srcloc)
contents = sh.load_file(srcfn)
return (srcfn, contents)
elif config_fn == AGENT_CONF:
srcloc = [self.appdir] + AGENT_LOC + [config_fn]
srcloc = [self.app_dir] + AGENT_LOC + [config_fn]
srcfn = sh.joinpths(*srcloc)
contents = sh.load_file(srcfn)
return (srcfn, contents)
@ -225,10 +223,10 @@ class QuantumRuntime(comp.ProgramRuntime):
if self.q_vswitch_service:
app_list.append({
'name': APP_Q_SERVER,
'path': sh.joinpths(self.appdir, BIN_DIR, APP_Q_SERVER),
'path': sh.joinpths(self.app_dir, BIN_DIR, APP_Q_SERVER),
})
if self.q_vswitch_agent:
full_pth = [self.appdir] + AGENT_BIN_LOC + [APP_Q_AGENT]
full_pth = [self.app_dir] + AGENT_BIN_LOC + [APP_Q_AGENT]
app_list.append({
'name': APP_Q_AGENT,
'path': sh.joinpths(*full_pth)
@ -241,8 +239,8 @@ class QuantumRuntime(comp.ProgramRuntime):
def _get_param_map(self, app_name):
param_dict = comp.ProgramRuntime._get_param_map(self, app_name)
if app_name == APP_Q_AGENT:
tgt_loc = [self.appdir] + AGENT_LOC + [AGENT_CONF]
tgt_loc = [self.app_dir] + AGENT_LOC + [AGENT_CONF]
param_dict['OVS_CONFIG_FILE'] = sh.joinpths(*tgt_loc)
elif app_name == APP_Q_SERVER:
param_dict['QUANTUM_CONFIG_FILE'] = sh.joinpths(self.appdir, CONFIG_DIR, QUANTUM_CONF)
param_dict['QUANTUM_CONFIG_FILE'] = sh.joinpths(self.app_dir, CONFIG_DIR, QUANTUM_CONF)
return param_dict

View File

@ -18,8 +18,6 @@ from devstack import component as comp
from devstack import log as logging
from devstack import settings
#id
TYPE = settings.QUANTUM_CLIENT
LOG = logging.getLogger("devstack.components.quantum_client")

View File

@ -21,8 +21,6 @@ from devstack import log as logging
from devstack import settings
from devstack import shell as sh
#id
TYPE = settings.RABBIT
LOG = logging.getLogger("devstack.components.rabbit")
#hopefully these are distro independent..

View File

@ -22,8 +22,6 @@ from devstack import settings
from devstack import shell as sh
from devstack import utils
#id
TYPE = settings.SWIFT
LOG = logging.getLogger("devstack.components.swift")
#swift has alot of config files!
@ -71,9 +69,9 @@ WARMUP_PWS = ['service_token', 'swift_hash']
class SwiftUninstaller(comp.PythonUninstallComponent):
def __init__(self, *args, **kargs):
comp.PythonUninstallComponent.__init__(self, *args, **kargs)
self.datadir = sh.joinpths(self.appdir, self.cfg.getdefaulted('swift', 'data_location', 'data'))
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.datadir = sh.joinpths(self.app_dir, self.cfg.getdefaulted('swift', 'data_location', 'data'))
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
self.logdir = sh.joinpths(self.datadir, LOG_DIR)
def pre_uninstall(self):
@ -88,12 +86,12 @@ class SwiftUninstaller(comp.PythonUninstallComponent):
class SwiftInstaller(comp.PythonInstallComponent):
def __init__(self, *args, **kargs):
comp.PythonInstallComponent.__init__(self, *args, **kargs)
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.datadir = sh.joinpths(self.appdir, self.cfg.getdefaulted('swift', 'data_location', 'data'))
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
self.datadir = sh.joinpths(self.app_dir, self.cfg.getdefaulted('swift', 'data_location', 'data'))
self.logdir = sh.joinpths(self.datadir, LOG_DIR)
self.startmain_file = sh.joinpths(self.bindir, SWIFT_STARTMAIN)
self.makerings_file = sh.joinpths(self.bindir, SWIFT_MAKERINGS)
self.startmain_file = sh.joinpths(self.bin_dir, SWIFT_STARTMAIN)
self.makerings_file = sh.joinpths(self.bin_dir, SWIFT_MAKERINGS)
self.fs_dev = sh.joinpths(self.datadir, DEVICE_PATH)
self.fs_image = sh.joinpths(self.datadir, SWIFT_IMG)
self.auth_server = AUTH_SERVICE
@ -118,7 +116,7 @@ class SwiftInstaller(comp.PythonInstallComponent):
'USER': self.cfg.getdefaulted('swift', 'swift_user', sh.getuser()),
'GROUP': self.cfg.getdefaulted('swift', 'swift_group', sh.getgroupname()),
'SWIFT_DATA_LOCATION': self.datadir,
'SWIFT_CONFIG_LOCATION': self.cfgdir,
'SWIFT_CONFIG_LOCATION': self.cfg_dir,
'SERVICE_TOKEN': self.cfg.get('passwords', 'service_token'),
'AUTH_SERVER': self.auth_server,
'SWIFT_HASH': self.cfg.get('passwords', 'swift_hash'),
@ -145,8 +143,8 @@ class SwiftInstaller(comp.PythonInstallComponent):
def _create_node_config(self, node_number, port):
for t in ['object', 'container', 'account']:
src_fn = sh.joinpths(self.cfgdir, '%s-server.conf' % t)
tgt_fn = sh.joinpths(self.cfgdir, '%s-server/%d.conf' % (t, node_number))
src_fn = sh.joinpths(self.cfg_dir, '%s-server.conf' % t)
tgt_fn = sh.joinpths(self.cfg_dir, '%s-server/%d.conf' % (t, node_number))
adjustments = {
'%NODE_PATH%': sh.joinpths(self.datadir, str(node_number)),
'%BIND_PORT%': str(port),
@ -157,7 +155,7 @@ class SwiftInstaller(comp.PythonInstallComponent):
def _delete_templates(self):
for t in ['object', 'container', 'account']:
sh.unlink(sh.joinpths(self.cfgdir, '%s-server.conf' % t))
sh.unlink(sh.joinpths(self.cfg_dir, '%s-server.conf' % t))
def _create_nodes(self):
for i in range(1, 5):
@ -170,20 +168,20 @@ class SwiftInstaller(comp.PythonInstallComponent):
self._delete_templates()
def _turn_on_rsync(self):
sh.symlink(sh.joinpths(self.cfgdir, RSYNC_CONF), RSYNCD_CONF_LOC)
sh.symlink(sh.joinpths(self.cfg_dir, RSYNC_CONF), RSYNCD_CONF_LOC)
self.tracewriter.symlink_made(RSYNCD_CONF_LOC)
sh.replace_in(RSYNC_CONF_LOC, RSYNC_ON_OFF_RE, 'RSYNC_ENABLE=true', True)
def _create_log_dirs(self):
self.tracewriter.dirs_made(*sh.mkdirslist(sh.joinpths(self.logdir, 'hourly')))
sh.symlink(sh.joinpths(self.cfgdir, SYSLOG_CONF), SWIFT_RSYNC_LOC)
sh.symlink(sh.joinpths(self.cfg_dir, SYSLOG_CONF), SWIFT_RSYNC_LOC)
self.tracewriter.symlink_made(SWIFT_RSYNC_LOC)
def _setup_binaries(self):
sh.move(sh.joinpths(self.cfgdir, SWIFT_MAKERINGS), self.makerings_file)
sh.move(sh.joinpths(self.cfg_dir, SWIFT_MAKERINGS), self.makerings_file)
sh.chmod(self.makerings_file, 0777)
self.tracewriter.file_touched(self.makerings_file)
sh.move(sh.joinpths(self.cfgdir, SWIFT_STARTMAIN), self.startmain_file)
sh.move(sh.joinpths(self.cfg_dir, SWIFT_STARTMAIN), self.startmain_file)
sh.chmod(self.startmain_file, 0777)
self.tracewriter.file_touched(self.startmain_file)
@ -202,21 +200,21 @@ class SwiftInstaller(comp.PythonInstallComponent):
class SwiftRuntime(comp.PythonRuntime):
def __init__(self, *args, **kargs):
comp.PythonRuntime.__init__(self, *args, **kargs)
self.datadir = sh.joinpths(self.appdir, self.cfg.getdefaulted('swift', 'data_location', 'data'))
self.cfgdir = sh.joinpths(self.appdir, CONFIG_DIR)
self.bindir = sh.joinpths(self.appdir, BIN_DIR)
self.datadir = sh.joinpths(self.app_dir, self.cfg.getdefaulted('swift', 'data_location', 'data'))
self.cfg_dir = sh.joinpths(self.app_dir, CONFIG_DIR)
self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR)
self.logdir = sh.joinpths(self.datadir, LOG_DIR)
def start(self):
sh.execute(*RSYSLOG_SERVICE_RESTART, run_as_root=True)
sh.execute(*RSYNC_SERVICE_RESTART, run_as_root=True)
swift_start_cmd = [sh.joinpths(self.bindir, SWIFT_INIT)] + ['all', 'start']
swift_start_cmd = [sh.joinpths(self.bin_dir, SWIFT_INIT)] + ['all', 'start']
sh.execute(*swift_start_cmd, run_as_root=True)
def stop(self):
swift_stop_cmd = [sh.joinpths(self.bindir, SWIFT_INIT)] + ['all', 'stop']
swift_stop_cmd = [sh.joinpths(self.bin_dir, SWIFT_INIT)] + ['all', 'stop']
sh.execute(*swift_stop_cmd, run_as_root=True)
def restart(self):
swift_restart_cmd = [sh.joinpths(self.bindir, SWIFT_INIT)] + ['all', 'restart']
swift_restart_cmd = [sh.joinpths(self.bin_dir, SWIFT_INIT)] + ['all', 'restart']
sh.execute(*swift_restart_cmd, run_as_root=True)

View File

@ -64,7 +64,7 @@ class Distro(object):
LOG.debug('Looking for distro data for %s (%s)', plt, distname)
for p in cls.load_all():
if p.supports_distro(plt):
LOG.info('Using distro "%s" for "%s"', p.name, plt)
LOG.info('Using distro "%s" for platform "%s"', p.name, plt)
return p
else:
raise RuntimeError(
@ -78,6 +78,15 @@ class Distro(object):
self.commands = commands
self.components = components
def __repr__(self):
return "\"%s\" using packager \"%s\"" % (self.name, self.packager_name)
def get_command(self, cmd_key, quiet=False):
if not quiet:
return self.commands[cmd_key]
else:
return self.commands.get(cmd_key)
def supports_distro(self, distro_name):
"""Does this distro support the named Linux distro?
@ -97,27 +106,3 @@ class Distro(object):
raise RuntimeError('No class configured to %s %s on %s' %
(action, name, self.name))
return importer.import_entry_point(entry_point)
def resolve_component_dependencies(self, components):
"""Returns list of all components needed for the named components."""
all_components = {}
active_names = [(c, None) for c in components]
while active_names:
component, parent = active_names.pop()
try:
component_details = self.components[component]
except KeyError:
if parent:
raise RuntimeError(
'Could not find details about component %r, a dependency of %s, for %s' %
(component, parent, self.name))
else:
raise RuntimeError(
'Could not find details about component %r for %s' %
(component, self.name))
deps = set(component_details.get('dependencies', []))
all_components[component] = deps
for d in deps:
if d not in all_components and d not in active_names:
active_names.append((d, component))
return all_components

View File

@ -10,7 +10,7 @@ LOG = logging.getLogger(__name__)
class OneiricDBInstaller(db.DBInstaller):
def _configure_db_confs(self):
LOG.info("Fixing up %s mysql configs.", self.distro.name)
fc = sh.load_file('/etc/mysql/my.cnf')

View File

@ -43,5 +43,5 @@ def get_key(key, default_value=None):
LOG.debug("Could not find anything in environment variable [%s]" % (key))
value = default_value
else:
LOG.debug("Found [%s] in environment variable [%s]" % (value, key))
LOG.audit("Found [%s] in environment variable [%s]" % (value, key))
return value

View File

@ -246,11 +246,25 @@ class RcReader(object):
def __init__(self):
pass
def _is_comment(self, line):
if line.lstrip().startswith("#"):
return True
return False
def extract(self, fn):
extracted_vars = dict()
contents = sh.load_file(fn)
contents = ''
#not using shell here since
#we don't want this to be "nulled" in a dry-run
LOG.audit("Loading rc file [%s]" % (fn))
try:
with open(fn, 'r') as fh:
contents = fh.read()
except IOError as e:
LOG.warn("Failed extracting rc file [%s] due to [%s]" % (fn, e.message))
return extracted_vars
for line in contents.splitlines():
if line.lstrip().startswith("#"):
if self._is_comment(line):
continue
m = EXP_PAT.search(line)
if m:

View File

@ -1,13 +1,36 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (C) 2012 Yahoo! Inc. All Rights Reserved.
# Copyright (C) 2012 Dreamhost Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def import_entry_point(fullname):
"""Given a name import the class and return it.
def partition(fullname):
"""
The name should be in dotted.path:ClassName syntax.
"""
if ':' not in fullname:
raise ValueError('Invalid entry point specifier %r' % fullname)
module_name, ignore, classname = fullname.partition(':')
return (module_name, ignore, classname)
def import_entry_point(fullname):
"""
Given a name import the class and return it.
"""
module_name, ignore, classname = partition(fullname)
try:
module = __import__(module_name)
for submodule in module_name.split('.')[1:]:

View File

@ -32,13 +32,6 @@ LIBVIRT_PROTOCOL_MAP = {
}
VIRT_LIB = 'libvirt'
#distros name the libvirt service differently :-(
SV_NAME_MAP = {
settings.RHEL6: 'libvirtd',
settings.FEDORA16: 'libvirtd',
settings.UBUNTU11: 'libvirt-bin',
}
#how libvirt is restarted
LIBVIRT_RESTART_CMD = ['service', '%SERVICE%', 'restart']
@ -71,7 +64,7 @@ def _status(distro):
'run_as_root': True,
})
mp = dict()
mp['SERVICE'] = SV_NAME_MAP[distro]
mp['SERVICE'] = distro.get_command('libvirt-daemon')
result = utils.execute_template(*cmds,
check_exit_code=False,
params=mp)
@ -104,7 +97,7 @@ def restart(distro):
'run_as_root': True,
})
mp = dict()
mp['SERVICE'] = SV_NAME_MAP[distro]
mp['SERVICE'] = distro.get_command('libvirt-daemon')
utils.execute_template(*cmds, params=mp)
LOG.info("Restarting the libvirt service, please wait %s seconds until its started." % (WAIT_ALIVE_TIME))
sh.sleep(WAIT_ALIVE_TIME)
@ -117,7 +110,7 @@ def virt_ok(virt_type, distro):
try:
restart(distro)
except excp.ProcessExecutionError, e:
LOG.warn("Could not restart libvirt on distro [%s] due to [%s]" % (distro, e.message))
LOG.warn("Could not restart libvirt due to [%s]" % (e))
return False
try:
cmds = list()
@ -148,7 +141,7 @@ def clear_libvirt_domains(distro, virt_type, inst_prefix):
try:
restart(distro)
except excp.ProcessExecutionError, e:
LOG.warn("Could not restart libvirt on distro [%s] due to [%s]" % (distro, e.message))
LOG.warn("Could not restart libvirt due to [%s]" % (e))
return
try:
conn = libvirt.open(virt_protocol)

View File

@ -35,10 +35,8 @@ def parse():
version_str = "%prog v" + version.version_string()
help_formatter = IndentedHelpFormatter(width=HELP_WIDTH)
parser = OptionParser(version=version_str, formatter=help_formatter)
parser.add_option("-c", "--component",
action="append",
dest="component",
help="openstack component: %s" % (_format_list(settings.COMPONENT_NAMES)))
#root options
parser.add_option("-v", "--verbose",
action="append_const",
const=1,
@ -52,7 +50,14 @@ def parse():
help=("perform ACTION but do not actually run any of the commands"
" that would normally complete ACTION: (default: %default)"))
#install/start/stop/uninstall specific options
base_group = OptionGroup(parser, "Install & uninstall & start & stop specific options")
base_group.add_option("-p", "--persona",
action="store",
type="string",
dest="persona_fn",
metavar="FILE",
help="required persona yaml file to apply")
base_group.add_option("-a", "--action",
action="store",
type="string",
@ -66,28 +71,15 @@ def parse():
metavar="DIR",
help=("empty root DIR for install or "
"DIR with existing components for start/stop/uninstall"))
base_group.add_option("-i", "--ignore-deps",
action="store_false",
dest="ensure_deps",
help="ignore dependencies when performing ACTION")
base_group.add_option("--no-prompt-passwords",
action="store_false",
dest="prompt_for_passwords",
default=True,
help="do not prompt the user for passwords",
)
base_group.add_option("-e", "--ensure-deps",
action="store_true",
dest="ensure_deps",
help="ensure dependencies when performing ACTION (default: %default)",
default=True)
base_group.add_option("-r", "--ref-component",
action="append",
dest="ref_components",
metavar="COMPONENT",
help="component which will not have ACTION applied but will be referenced as if it was (ACTION dependent)")
parser.add_option_group(base_group)
#uninstall and stop options
stop_un_group = OptionGroup(parser, "Uninstall & stop specific options")
stop_un_group.add_option("-n", "--no-force",
action="store_true",
@ -107,15 +99,13 @@ def parse():
#extract only what we care about
(options, args) = parser.parse_args()
output = dict()
output['components'] = options.component or list()
output['dir'] = options.dir or ""
output['dryrun'] = options.dryrun or False
output['ref_components'] = options.ref_components or list()
output['action'] = options.action or ""
output['force'] = not options.force
output['ignore_deps'] = not options.ensure_deps
output['keep_old'] = options.keep_old
output['extras'] = args
output['persona_fn'] = options.persona_fn
output['verbosity'] = len(options.verbosity)
output['prompt_for_passwords'] = options.prompt_for_passwords

View File

@ -14,22 +14,23 @@
# License for the specific language governing permissions and limitations
# under the License..
import yaml
from devstack import env_rc
from devstack import exceptions as excp
from devstack import log as logging
from devstack import settings
from devstack import shell as sh
from devstack import utils
from devstack.progs import common
from devstack import passwords
LOG = logging.getLogger("devstack.progs.actions")
# For actions in this list we will reverse the component order
_REVERSE_ACTIONS = [settings.UNINSTALL, settings.STOP]
REVERSE_ACTIONS = [settings.UNINSTALL, settings.STOP]
# For these actions we will attempt to make an rc file if it does not exist
_RC_FILE_MAKE_ACTIONS = [settings.INSTALL]
RC_FILE_MAKE_ACTIONS = [settings.INSTALL]
# The order of which uninstalls happen + message of what is happening
# (before and after)
@ -138,125 +139,93 @@ PREQ_ACTIONS = {
class ActionRunner(object):
def __init__(self, distro, action, directory, config,
pw_gen, pkg_manager,
**kargs):
def __init__(self, distro, action, cfg, **kargs):
self.distro = distro
self.action = action
self.directory = directory
self.cfg = config
self.pw_gen = pw_gen
self.pkg_manager = pkg_manager
self.kargs = kargs
self.components = dict()
def_components = common.get_default_components()
unclean_components = kargs.pop("components")
if not unclean_components:
self.components = def_components
else:
for (c, opts) in unclean_components.items():
if opts is None and c in def_components:
self.components[c] = def_components[c]
elif opts is None:
self.components[c] = list()
else:
self.components[c] = opts
self.cfg = cfg
self.pw_gen = passwords.PasswordGenerator(self.cfg, kargs.get('prompt_for_passwords', True))
pkg_cls = distro.get_packager_factory()
self.pkg_manager = pkg_cls(self.distro.name, kargs.get('keep_old', False))
self.force = kargs.get('force', False)
self.ignore_deps = kargs.get('ignore_deps', False)
self.ref_components = kargs.get("ref_components")
self.gen_rc = action in _RC_FILE_MAKE_ACTIONS
self.kargs = kargs
def _get_components(self):
return dict(self.components)
def _apply_reverse(self, action, component_order):
if not component_order:
component_order = list()
else:
component_order = list(component_order)
adjusted_order = list(component_order)
if action in REVERSE_ACTIONS:
adjusted_order.reverse()
return adjusted_order
def _order_components(self, components):
adjusted_components = dict(components)
if self.ignore_deps:
return (adjusted_components, list(components.keys()))
all_components = self.distro.resolve_component_dependencies(
list(components.keys())
)
component_diff = set(all_components.keys()).difference(components.keys())
if component_diff:
LOG.info("Activating dependencies: [%s]",
", ".join(sorted(component_diff))
)
for new_component in component_diff:
adjusted_components[new_component] = []
return (adjusted_components, utils.get_components_order(all_components))
def _load_persona(self, persona_fn):
persona_fn = sh.abspth(persona_fn)
LOG.audit("Loading persona from file [%s]", persona_fn)
contents = ''
with open(persona_fn, "r") as fh:
contents = fh.read()
return self._verify_persona(yaml.load(contents), persona_fn)
def _inject_references(self, components):
ref_components = utils.parse_components(self.ref_components)
adjusted_components = dict(components)
for c in ref_components.keys():
if c not in components:
adjusted_components[c] = ref_components.get(c)
return adjusted_components
def _instantiate_components(self, components):
all_instances = dict()
for component in components.keys():
cls = self.distro.get_component_action_class(component,
self.action)
LOG.debug('instantiating %s to handle %s for %s',
cls, self.action, component)
instance = cls(component_name=component,
instances=all_instances,
runner=self,
root_dir=self.directory,
component_options=self.distro.components[component],
keep_old=self.kargs.get("keep_old")
)
all_instances[component] = instance
return all_instances
def _run_preqs(self, components, component_order):
if not (self.action in PREQ_ACTIONS):
return
(check_functor, preq_action) = PREQ_ACTIONS[self.action]
instances = self._instantiate_components(components)
preq_components = dict()
def _verify_persona(self, persona, fn):
# Some sanity checks
try:
if self.distro.name not in persona['supports']:
raise RuntimeError("Persona does not support distro %s"
% (self.distro.name))
for c in persona['components']:
if c not in self.distro.components:
raise RuntimeError("Distro %s does not support component %s" %
(self.distro.name, c))
except (KeyError, RuntimeError) as e:
msg = ("Could not validate persona defined in [%s] due to: %s"
% (fn, e))
raise excp.ConfigException(msg)
return persona
def _construct_instances(self, persona, action, root_dir):
components = persona['components'] # Required
subsystems = persona.get('subsystems') or dict() # Not required
instances = dict()
for c in components:
cls = self.distro.get_component_action_class(c, action)
LOG.debug("Constructing class %s" % (cls))
cls_kvs = dict()
cls_kvs['runner'] = self
cls_kvs['component_dir'] = sh.joinpths(root_dir, c)
cls_kvs['subsystems'] = set(subsystems.get(c, list()))
cls_kvs['all_instances'] = instances
cls_kvs['name'] = c
# FIXME:
cls_kvs['keep_old'] = False
LOG.debug("Using k/v map %s", cls_kvs)
instances[c] = cls(*list(), **cls_kvs)
return instances
def _verify_components(self, component_order, instances):
LOG.info("Verifying that the components are ready to rock-n-roll.")
for c in component_order:
instance = instances[c]
if check_functor(instance):
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(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):
if not sh.isdir(self.directory):
sh.mkdir(self.directory)
LOG.info("Verifying that the components are ready to rock-n-roll.")
for component in component_order:
inst = instances[component]
inst.verify()
instance.verify()
def _warm_components(self, component_order, instances):
LOG.info("Warming up your component configurations (ie so you won't be prompted later)")
for component in component_order:
inst = instances[component]
inst.warm_configs()
if self.gen_rc:
writer = env_rc.RcWriter(self.cfg, self.pw_gen, self.directory)
if not sh.isfile(settings.OSRC_FN):
LOG.info("Generating a file at [%s] that will contain your environment settings." % (settings.OSRC_FN))
writer.write(settings.OSRC_FN)
else:
LOG.info("Updating a file at [%s] that contains your environment settings." % (settings.OSRC_FN))
am_upd = writer.update(settings.OSRC_FN)
LOG.info("Updated [%s] settings in rc file [%s]" % (am_upd, settings.OSRC_FN))
def _run_instances(self, instances, component_order):
component_order = self._apply_reverse(component_order)
LOG.info("Running in the following order: %s" % ("->".join(component_order)))
for (start_msg, functor, end_msg) in ACTION_MP[self.action]:
for c in component_order:
instance = instances[c]
instance.warm_configs()
def _write_rc_file(self, root_dir):
writer = env_rc.RcWriter(self.cfg, self.pw_gen, root_dir)
if not sh.isfile(settings.OSRC_FN):
LOG.info("Generating a file at [%s] that will contain your environment settings." % (settings.OSRC_FN))
writer.write(settings.OSRC_FN)
else:
LOG.info("Updating a file at [%s] that contains your environment settings." % (settings.OSRC_FN))
am_upd = writer.update(settings.OSRC_FN)
LOG.info("Updated [%s] settings in rc file [%s]" % (am_upd, settings.OSRC_FN))
def _run_instances(self, action, component_order, instances):
for (start_msg, functor, end_msg) in ACTION_MP[action]:
for c in component_order:
instance = instances[c]
if start_msg:
@ -271,19 +240,30 @@ class ActionRunner(object):
else:
raise
def _apply_reverse(self, component_order):
adjusted_order = list(component_order)
if self.action in _REVERSE_ACTIONS:
adjusted_order.reverse()
return adjusted_order
def _start(self, components, component_order):
LOG.info("Activating components required to complete action [%s]" % (self.action))
instances = self._instantiate_components(components)
self._pre_run(instances, component_order)
self._run_preqs(components, component_order)
self._run_instances(instances, component_order)
def run(self):
(components, component_order) = self._order_components(self._get_components())
self._start(self._inject_references(components), component_order)
def _run_action(self, persona, action, root_dir):
LOG.info("Running action [%s] using root directory [%s]" % (action, root_dir))
instances = self._construct_instances(persona, action, root_dir)
if action in PREQ_ACTIONS:
(check_functor, preq_action) = PREQ_ACTIONS[action]
checks_passed_components = list()
for (c, instance) in instances.items():
if check_functor(instance):
checks_passed_components.append(c)
if checks_passed_components:
LOG.info("Activating prerequisite action [%s] requested by (%s) components."
% (preq_action, ", ".join(checks_passed_components)))
self._run_action(persona, preq_action, root_dir)
component_order = self._apply_reverse(action, persona['components'])
LOG.info("Activating components [%s] (in that order) for action [%s]" %
("->".join(component_order), action))
self._verify_components(component_order, instances)
self._warm_components(component_order, instances)
if action in RC_FILE_MAKE_ACTIONS:
self._write_rc_file(root_dir)
self._run_instances(action, component_order, instances)
def run(self, persona_fn, root_dir):
persona = self._load_persona(persona_fn)
if not sh.isdir(root_dir):
sh.mkdir(root_dir)
self._run_action(persona, self.action, root_dir)

View File

@ -1,190 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (C) 2012 Yahoo! Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import tempfile
from devstack import cfg
from devstack import exceptions as excp
from devstack import settings
from devstack import shell as sh
from devstack.components import db
from devstack.components import glance
from devstack.components import horizon
from devstack.components import keystone
from devstack.components import keystone_client
from devstack.components import melange
from devstack.components import melange_client
from devstack.components import nova
from devstack.components import nova_client
from devstack.components import novnc
from devstack.components import quantum
from devstack.components import quantum_client
from devstack.components import rabbit
from devstack.components import swift
from devstack.packaging import apt
from devstack.packaging import yum
# This determines what classes to use to install/uninstall/...
# ACTION_CLASSES = {
# settings.INSTALL: {
# settings.DB: db.DBInstaller,
# settings.GLANCE: glance.GlanceInstaller,
# settings.HORIZON: horizon.HorizonInstaller,
# settings.KEYSTONE: keystone.KeystoneInstaller,
# settings.KEYSTONE_CLIENT: keystone_client.KeyStoneClientInstaller,
# settings.MELANGE: melange.MelangeInstaller,
# settings.MELANGE_CLIENT: melange_client.MelangeClientInstaller,
# settings.NOVA: nova.NovaInstaller,
# settings.NOVA_CLIENT: nova_client.NovaClientInstaller,
# settings.NOVNC: novnc.NoVNCInstaller,
# settings.QUANTUM: quantum.QuantumInstaller,
# settings.QUANTUM_CLIENT: quantum_client.QuantumClientInstaller,
# settings.RABBIT: rabbit.RabbitInstaller,
# settings.SWIFT: swift.SwiftInstaller,
# },
# settings.UNINSTALL: {
# settings.DB: db.DBUninstaller,
# settings.GLANCE: glance.GlanceUninstaller,
# settings.HORIZON: horizon.HorizonUninstaller,
# settings.KEYSTONE: keystone.KeystoneUninstaller,
# settings.KEYSTONE_CLIENT: keystone_client.KeyStoneClientUninstaller,
# settings.MELANGE: melange.MelangeUninstaller,
# settings.MELANGE_CLIENT: melange_client.MelangeClientUninstaller,
# settings.NOVA: nova.NovaUninstaller,
# settings.NOVA_CLIENT: nova_client.NovaClientUninstaller,
# settings.NOVNC: novnc.NoVNCUninstaller,
# settings.QUANTUM: quantum.QuantumUninstaller,
# settings.QUANTUM_CLIENT: quantum_client.QuantumClientUninstaller,
# settings.RABBIT: rabbit.RabbitUninstaller,
# settings.SWIFT: swift.SwiftUninstaller,
# },
# settings.START: {
# settings.DB: db.DBRuntime,
# settings.GLANCE: glance.GlanceRuntime,
# settings.HORIZON: horizon.HorizonRuntime,
# settings.KEYSTONE: keystone.KeystoneRuntime,
# settings.KEYSTONE_CLIENT: keystone_client.KeyStoneClientRuntime,
# settings.MELANGE: melange.MelangeRuntime,
# settings.MELANGE_CLIENT: melange_client.MelangeClientRuntime,
# settings.NOVA: nova.NovaRuntime,
# settings.NOVA_CLIENT: nova_client.NovaClientRuntime,
# settings.NOVNC: novnc.NoVNCRuntime,
# settings.QUANTUM: quantum.QuantumRuntime,
# settings.QUANTUM_CLIENT: quantum_client.QuantumClientRuntime,
# settings.RABBIT: rabbit.RabbitRuntime,
# settings.SWIFT: swift.SwiftRuntime,
# },
# }
# # Just a copy
# ACTION_CLASSES[settings.STOP] = ACTION_CLASSES[settings.START]
# Used only for figuring out deps
_FAKE_ROOT_DIR = tempfile.gettempdir()
# This map controls which distro has
# which package management class
_PKGR_MAP = {
settings.UBUNTU11: apt.AptPackager,
settings.RHEL6: yum.YumPackager,
settings.FEDORA16: yum.YumPackager,
}
def get_default_components():
def_components = dict()
def_components[settings.GLANCE] = [
glance.GAPI,
glance.GREG,
]
def_components[settings.KEYSTONE] = []
def_components[settings.NOVA] = [
nova.NAPI,
nova.NCAUTH,
nova.NCERT,
nova.NCPU,
nova.NNET,
nova.NOBJ,
nova.NSCHED,
nova.NXVNC,
nova.NVOL,
]
def_components[settings.NOVNC] = []
def_components[settings.HORIZON] = []
def_components[settings.DB] = []
def_components[settings.RABBIT] = []
return def_components
def format_secs_taken(secs):
output = "%.03f seconds" % (secs)
output += " or %.02f minutes" % (secs / 60.0)
return output
# def get_action_cls(action_name, component_name, distro=None):
# action_cls_map = ACTION_CLASSES.get(action_name)
# if not action_cls_map:
# raise excp.StackException("Action %s has no component to class mapping" % (action_name))
# cls = action_cls_map.get(component_name)
# if not cls:
# raise excp.StackException("Action %s has no class entry for component %s" % (action_name, component_name))
# return cls
def get_packager(distro, keep_packages):
cls = _PKGR_MAP.get(distro)
if not cls:
msg = "No package manager found for distro %s!" % (distro)
raise excp.StackException(msg)
return cls(distro, keep_packages)
def get_config(cfg_fn=None):
if not cfg_fn:
cfg_fn = sh.canon_path(settings.STACK_CONFIG_LOCATION)
config_instance = cfg.StackConfigParser()
config_instance.read(cfg_fn)
return config_instance
# def get_components_deps(runner,
# action_name,
# base_components,
# root_dir=None,
# distro=None,
# ):
# all_components = dict()
# active_names = list(base_components)
# root_dir = root_dir or _FAKE_ROOT_DIR
# while len(active_names):
# component = active_names.pop()
# component_opts = base_components.get(component) or list()
# cls = get_action_cls(action_name, component, distro)
# instance = cls(instances=list(),
# runner=runner,
# root_dir=root_dir,
# component_options=component_opts,
# keep_old=False
# )
# deps = instance.get_dependencies() or set()
# all_components[component] = set(deps)
# for d in deps:
# if d not in all_components and d not in active_names:
# active_names.append(d)
# return all_components

View File

@ -18,13 +18,6 @@ import os
import re
import sys
# These also have meaning outside python,
# ie in the pkg/pip listings so update there also!
# FIXME: Delete
UBUNTU11 = "ubuntu-oneiric"
RHEL6 = "rhel-6"
FEDORA16 = "fedora-16"
# What this program is called
PROG_NICE_NAME = "DEVSTACKpy"
@ -36,7 +29,7 @@ POST_INSTALL = 'post-install'
IPV4 = 'IPv4'
IPV6 = 'IPv6'
#how long to wait for a service to startup
# How long to wait for a service to startup
WAIT_ALIVE_SECS = 5
# Component name mappings
@ -68,29 +61,6 @@ COMPONENT_NAMES = [
MELANGE, MELANGE_CLIENT,
]
# When a component is asked for it may
# need another component, that dependency
# mapping is listed here. A topological sort
# will be applied to determine the exact order.
# COMPONENT_DEPENDENCIES = {
# DB: [],
# KEYSTONE_CLIENT: [],
# RABBIT: [],
# GLANCE: [KEYSTONE, DB],
# KEYSTONE: [DB, KEYSTONE_CLIENT],
# NOVA: [KEYSTONE, GLANCE, DB, RABBIT, NOVA_CLIENT],
# SWIFT: [KEYSTONE_CLIENT],
# NOVA_CLIENT: [],
# # Horizon depends on glances client (which should really be a client package)
# HORIZON: [KEYSTONE_CLIENT, GLANCE, NOVA_CLIENT, QUANTUM_CLIENT],
# # More of quantums deps come from its module function get_dependencies
# QUANTUM: [],
# NOVNC: [NOVA],
# QUANTUM_CLIENT: [],
# MELANGE: [DB],
# MELANGE_CLIENT: [],
# }
# Different run types supported
RUN_TYPE_FORK = "FORK"
RUN_TYPE_UPSTART = "UPSTART"
@ -126,6 +96,4 @@ ACTIONS = [INSTALL, UNINSTALL, START, STOP]
STACK_BIN_DIR = os.path.abspath(os.path.dirname(sys.argv[0]))
STACK_CONFIG_DIR = os.path.join(STACK_BIN_DIR, "conf")
STACK_TEMPLATE_DIR = os.path.join(STACK_CONFIG_DIR, "templates")
STACK_PKG_DIR = os.path.join(STACK_CONFIG_DIR, "pkgs")
STACK_PIP_DIR = os.path.join(STACK_CONFIG_DIR, "pips")
STACK_CONFIG_LOCATION = os.path.join(STACK_CONFIG_DIR, "stack.ini")

View File

@ -257,79 +257,10 @@ def get_interfaces():
return interfaces
def get_components_order(components):
if not components:
return dict()
#deep copy so components isn't messed with
all_components = dict()
for (name, deps) in components.items():
all_components[name] = set(deps)
#figure out which ones have no one depending on them
no_deps_components = set()
for (name, deps) in all_components.items():
referenced = False
for (_name, _deps) in all_components.items():
if _name == name:
continue
else:
if name in _deps:
referenced = True
break
if not referenced:
no_deps_components.add(name)
if not no_deps_components:
msg = "Components specifed have no root components, there is most likely a dependency cycle!"
raise excp.DependencyException(msg)
#now we have to do a quick check to ensure no component is causing a cycle
for (root, deps) in all_components.items():
#DFS down through the "roots" deps and there deps and so on and
#ensure that nobody is referencing the "root" component name,
#that would mean there is a cycle if a dependency of the "root" is.
active_deps = list(deps)
checked_deps = dict()
while len(active_deps):
dep = active_deps.pop()
itsdeps = all_components.get(dep)
checked_deps[dep] = True
if root in itsdeps:
msg = "Circular dependency between component %s and component %s!" % (root, dep)
raise excp.DependencyException(msg)
else:
for d in itsdeps:
if d not in checked_deps and d not in active_deps:
active_deps.append(d)
#now form the order
#basically a topological sorting
#https://en.wikipedia.org/wiki/Topological_sorting
ordering = list()
no_edges = set(no_deps_components)
while len(no_edges):
node = no_edges.pop()
ordering.append(node)
its_deps = all_components.get(node)
while len(its_deps):
name = its_deps.pop()
referenced = False
for (_name, _deps) in all_components.items():
if _name == name:
continue
else:
if name in _deps:
referenced = True
break
if not referenced:
no_edges.add(name)
#should now be no edges else something bad happended
for (_, deps) in all_components.items():
if len(deps):
msg = "Your specified components have at least one cycle!"
raise excp.DependencyException(msg)
#reverse so its in the right order for us since we just determined
#the pkgs that have no one depending on them (which should be installed
#last and those that have incoming edges that packages are depending on need
#to go first, but those were inserted last), so this reverse fixes that
ordering.reverse()
return ordering
def format_secs_taken(secs):
output = "%.03f seconds" % (secs)
output += " or %.02f minutes" % (secs / 60.0)
return output
def joinlinesep(*pieces):
@ -707,28 +638,6 @@ def goodbye(worked):
print(msg)
def parse_components(components):
if not components:
return dict()
adjusted_components = dict()
for c in components:
mtch = EXT_COMPONENT.match(c)
if mtch:
component_name = mtch.group(1).lower().strip()
if component_name in settings.COMPONENT_NAMES:
component_opts = mtch.group(2)
components_opts_cleaned = None
if component_opts:
components_opts_cleaned = list()
sp_component_opts = component_opts.split(",")
for co in sp_component_opts:
cleaned_opt = co.strip()
if cleaned_opt:
components_opts_cleaned.append(cleaned_opt)
adjusted_components[component_name] = components_opts_cleaned
return adjusted_components
def welcome(ident):
lower = "| %s %s |" % (ident, version.version_string())
welcome_header = _get_welcome_stack()

59
stack
View File

@ -20,6 +20,7 @@ import sys
import time
import traceback
from devstack import cfg
from devstack import cfg_helpers
from devstack import date
from devstack import distro
@ -33,7 +34,6 @@ from devstack import shell as sh
from devstack import utils
from devstack.progs import actions
from devstack.progs import common
LOG = logging.getLogger("devstack.stack")
@ -50,7 +50,7 @@ _WELCOME_MAP = {
_CFG_GROUPS = {
cfg_helpers.make_id('passwords', None): 'Passwords',
cfg_helpers.make_id('db', None): 'Database info',
#catch all
# Catch all
cfg_helpers.make_id(None, None): 'Misc configs',
}
@ -68,12 +68,12 @@ def dump_config(config_cache):
value = mp.get(key)
LOG.info(item_format(key, value))
#first partition into our groups
# First partition into our groups
partitions = dict()
for name in _CFG_ORDERING:
partitions[name] = dict()
#now put the config cached values into there partition
# Now put the config cached values into there partitions
for (k, v) in config_cache.items():
for name in _CFG_ORDERING:
entries = partitions[name]
@ -81,7 +81,7 @@ def dump_config(config_cache):
entries[k] = v
break
#now print them..
# Now print them..
for name in _CFG_ORDERING:
nice_name = _CFG_GROUPS.get(name)
LOG.info(nice_name + ":")
@ -103,49 +103,52 @@ def load_rc_files():
def run(args):
action = args.pop("action").strip().lower()
action = args.pop("action", '').strip().lower()
if not (action in settings.ACTIONS):
print(utils.color_text("No valid action specified!", "red"))
return False
loaded_rcs = False
rootdir = args.pop("dir")
if not rootdir:
root_dir = args.pop("dir")
if not root_dir:
load_rc_files()
loaded_rcs = True
rootdir = env.get_key(env_rc.INSTALL_ROOT)
if not rootdir:
root_dir = env.get_key(env_rc.INSTALL_ROOT)
if not root_dir:
print(utils.color_text("No root directory specified!", "red"))
return False
#welcome!
persona_fn = args.pop('persona_fn')
if not persona_fn or not sh.isfile(persona_fn):
print(utils.color_text("No valid persona file name specified!", "red"))
return False
# Welcome!
(repeat_string, line_max_len) = utils.welcome(_WELCOME_MAP.get(action))
print(utils.center_text("Action Runner", repeat_string, line_max_len))
#here on out we should be using the logger (and not print)
start_time = time.time()
# Here on out we should be using the logger (and not print)!!
# if we didn't load them before, load them now
# If we didn't load them before, load them now
if not loaded_rcs:
load_rc_files()
loaded_rcs = True
# Stash the dryrun value (if any) into the global configuration
sh.set_dryrun(args['dryrun'])
sh.set_dryrun(args.pop('dryrun'))
dist = distro.Distro.get_current()
config = common.get_config()
pw_gen = passwords.PasswordGenerator(config, args['prompt_for_passwords'])
pkg_factory = dist.get_packager_factory()
pkg_manager = pkg_factory(dist, args['keep_old'])
components = utils.parse_components(args.pop("components"))
runner = actions.ActionRunner(dist, action, rootdir, config, pw_gen,
pkg_manager, components=components, **args)
config = cfg.get_config()
runner = actions.ActionRunner(dist, action, config, **args)
LOG.info("Starting action [%s] on %s for distro [%s]" % (action, date.rcf8222date(), dist))
runner.run()
LOG.info("It took (%s) to complete action [%s]" % (common.format_secs_taken((time.time() - start_time)), action))
start_time = time.time()
runner.run(persona_fn, root_dir)
end_time = time.time()
LOG.info("It took (%s) to complete action [%s]" %
(utils.format_secs_taken((end_time - start_time)), action))
LOG.info("After action [%s] your settings which were created or read are:" % (action))
dump_config(config.configs_fetched)
@ -154,7 +157,7 @@ def run(args):
def main():
#do this first so people can see the help message...
# Do this first so people can see the help message...
args = opts.parse()
prog_name = sys.argv[0]
@ -163,7 +166,7 @@ def main():
LOG.debug("Command line options %s" % (args))
#will need root to setup openstack
# Will need root to setup openstack
if not sh.got_root():
rest_args = sys.argv[1:]
print("This program requires a user with sudo access.")
@ -173,7 +176,7 @@ def main():
return 1
try:
#drop to usermode
# Drop to usermode
sh.user_mode(False)
started_ok = run(args)
if not started_ok: