diff --git a/devstack/components/db.py b/devstack/components/db.py index 53eaa2af..ad99c491 100644 --- a/devstack/components/db.py +++ b/devstack/components/db.py @@ -143,8 +143,8 @@ class DBInstaller(comp.PkgInstallComponent): 'USER': user, } cmds = [{'cmd': grant_cmd}] - #shell seems to be needed here - #since python escapes this to much... + # Shell seems to be needed here + # since python escapes this to much... utils.execute_template(*cmds, params=params, shell=True) diff --git a/devstack/components/horizon.py b/devstack/components/horizon.py index 0aadb231..631aa3fa 100644 --- a/devstack/components/horizon.py +++ b/devstack/components/horizon.py @@ -23,47 +23,35 @@ from devstack import utils LOG = logging.getLogger("devstack.components.horizon") -#actual dir names +# Actual dir names ROOT_HORIZON = 'horizon' ROOT_DASH = 'openstack_dashboard' -#name used for python install trace +# Name used for python install trace HORIZON_NAME = ROOT_HORIZON DASH_NAME = 'dashboard' -#config files messed with +# Config files messed with HORIZON_PY_CONF = "horizon_settings.py" HORIZON_PY_CONF_TGT = ['local', 'local_settings.py'] HORIZON_APACHE_CONF = '000-default' CONFIGS = [HORIZON_PY_CONF, HORIZON_APACHE_CONF] -#http://wiki.apache.org/httpd/DistrosDefaultLayout - -#db sync that needs to happen for horizon +# DB sync that needs to happen for horizon DB_SYNC_CMD = ['python', 'manage.py', 'syncdb'] -#special apache directory (TODO describe more about this) +# Special apache directory (TODO describe more about this) BLACKHOLE_DIR = '.blackhole' +# Other apache settings APACHE_ERROR_LOG_FN = "error.log" 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_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'] - -#users which apache may not like starting as +# Users which apache may not like starting as.. BAD_APACHE_USERS = ['root'] -#apache logs will go here +# Apache logs will go here LOGS_DIR = "logs" @@ -93,9 +81,9 @@ 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] = self.distro.commands['apache']['settings']['conf-link-target'] + links[src] = self.distro.get_command('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 + # TODO remove this junk, blah, puke that we have to do this qc = self.instances[settings.QUANTUM_CLIENT] src_pth = sh.joinpths(qc.app_dir, 'quantum') tgt_dir = sh.joinpths(self.dash_dir, 'quantum') @@ -124,17 +112,18 @@ class HorizonInstaller(comp.PythonInstallComponent): return list(CONFIGS) def _setup_blackhole(self): - #create an empty directory that apache uses as docroot + # Create an empty directory that apache uses as docroot 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). + # 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.app_dir) def _ensure_db_access(self): - # ../openstack-dashboard/local needs to be writeable by the runtime user + # Need db access: + # openstack-dashboard/local needs to be writeable by the runtime user # since currently its storing the sql-lite databases there (TODO fix that) path = sh.joinpths(self.dash_dir, 'local') if sh.isdir(path): @@ -150,44 +139,10 @@ class HorizonInstaller(comp.PythonInstallComponent): self.tracewriter.dirs_made(*sh.mkdirslist(self.log_dir)) def _config_fixups(self): - #currently just handling rhel fixups - #TODO: maybe this should be a subclass that handles these differences - if not (self.distro in APACHE_FIXUPS_DISTROS): - return - #it seems like to get this to work - #we need to do some conf.d/conf work which sort of sucks - (user, group) = self._get_apache_user_group() - socket_fn = APACHE_FIXUPS.get("SOCKET_CONF") - self.tracewriter.file_touched(socket_fn) - #not recorded since we aren't really creating this - httpd_fn = APACHE_FIXUPS.get("HTTPD_CONF") - with sh.Rooted(True): - #fix the socket prefix to someplace we can use - fc = "WSGISocketPrefix %s" % (sh.joinpths(self.log_dir, "wsgi-socket")) - sh.write_file(socket_fn, fc) - #now adjust the run user and group (of httpd.conf) - new_lines = list() - for line in sh.load_file(httpd_fn).splitlines(): - if line.startswith("User "): - line = "User %s" % (user) - if line.startswith("Group "): - line = "Group %s" % (group) - new_lines.append(line) - sh.write_file(httpd_fn, utils.joinlinesep(*new_lines)) - - def _fix_quantum(self): - if not (utils.service_enabled(settings.QUANTUM_CLIENT, self.instances, False)): - #make the fake quantum (apparently needed so imports don't fail???) - #TODO remove this... - quantum_dir = sh.joinpths(self.dash_dir, 'quantum') - if not sh.isdir(quantum_dir): - self.tracewriter.dirs_made(*sh.mkdirslist(quantum_dir)) - for fn in FAKE_QUANTUM_FILES: - self.tracewriter.file_touched(sh.touch_file(sh.joinpths(quantum_dir, fn))) + pass def post_install(self): comp.PythonInstallComponent.post_install(self) - self._fix_quantum() self._sync_db() self._setup_blackhole() self._ensure_db_access() @@ -199,17 +154,17 @@ class HorizonInstaller(comp.PythonInstallComponent): return (user, group) def _get_param_map(self, config_fn): - #this dict will be used to fill in the configuration - #params with actual values + # This dict will be used to fill in the configuration + # params with actual values mp = dict() if config_fn == HORIZON_APACHE_CONF: (user, group) = self._get_apache_user_group() + mp['GROUP'] = group + mp['USER'] = user 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.app_dir mp['HORIZON_PORT'] = self.cfg.getdefaulted('horizon', 'port', APACHE_DEF_PORT) - mp['USER'] = user mp['VPN_DIR'] = sh.joinpths(self.app_dir, "vpn") else: mp['OPENSTACK_HOST'] = self.cfg.get('host', 'ip') @@ -226,7 +181,7 @@ class HorizonRuntime(comp.EmptyRuntime): return self.restart() else: cmds = [{ - 'cmd': self.distro.commands['apache']['start'], + 'cmd': self.distro.get_command('apache', 'start'), 'run_as_root': True, }] utils.execute_template(*cmds, @@ -236,7 +191,7 @@ class HorizonRuntime(comp.EmptyRuntime): def restart(self): cmds = [{ - 'cmd': self.distro.commands['apache']['restart'], + 'cmd': self.distro.get_command('apache', 'restart'), 'run_as_root': True, }] utils.execute_template(*cmds, @@ -248,7 +203,7 @@ class HorizonRuntime(comp.EmptyRuntime): curr_status = self.status() if curr_status != comp.STATUS_STOPPED: cmds = [{ - 'cmd': self.distro.commands['apache']['stop'], + 'cmd': self.distro.get_command('apache', 'stop'), 'run_as_root': True, }] utils.execute_template(*cmds, @@ -259,7 +214,7 @@ class HorizonRuntime(comp.EmptyRuntime): def status(self): cmds = [{ - 'cmd': self.distro.commands['apache']['status'], + 'cmd': self.distro.get_command('apache', 'status'), 'run_as_root': True, }] run_result = utils.execute_template(*cmds, diff --git a/devstack/components/keystone_client.py b/devstack/components/keystone_client.py index 040b6f89..401caaa9 100644 --- a/devstack/components/keystone_client.py +++ b/devstack/components/keystone_client.py @@ -16,7 +16,6 @@ from devstack import component as comp from devstack import log as logging -from devstack import settings LOG = logging.getLogger("devstack.components.keystone_client") diff --git a/devstack/components/melange_client.py b/devstack/components/melange_client.py index 07864c4a..e935f218 100644 --- a/devstack/components/melange_client.py +++ b/devstack/components/melange_client.py @@ -16,7 +16,6 @@ from devstack import component as comp from devstack import log as logging -from devstack import settings LOG = logging.getLogger("devstack.components.melange_client") diff --git a/devstack/components/nova_client.py b/devstack/components/nova_client.py index eacae024..fcabd713 100644 --- a/devstack/components/nova_client.py +++ b/devstack/components/nova_client.py @@ -16,7 +16,6 @@ from devstack import component as comp from devstack import log as logging -from devstack import settings LOG = logging.getLogger("devstack.components.nova_client") diff --git a/devstack/components/quantum.py b/devstack/components/quantum.py index 6936057a..4df1e8f4 100644 --- a/devstack/components/quantum.py +++ b/devstack/components/quantum.py @@ -80,15 +80,8 @@ class QuantumInstaller(comp.PkgInstallComponent): self.q_vswitch_service = False plugin = self.cfg.getdefaulted("quantum", "q_plugin", VSWITCH_PLUGIN) if plugin == VSWITCH_PLUGIN: - #default to on if not specified self.q_vswitch_agent = True self.q_vswitch_service = True - # else: - # #only turn on if requested - # if QUANTUM_SERVICE in self.component_opts: - # self.q_vswitch_service = True - # if QUANTUM_AGENT in self.component_opts: - # self.q_vswitch_agent = True def _get_download_locations(self): places = list() @@ -98,18 +91,6 @@ class QuantumInstaller(comp.PkgInstallComponent): }) return places - 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) - if self.q_vswitch_service: - #in this case we need the db - add_deps.append(settings.DB) - return common_deps + add_deps - def _get_config_files(self): return list(CONFIG_FILES) diff --git a/devstack/components/quantum_client.py b/devstack/components/quantum_client.py index 3483cab6..2fb56fe5 100644 --- a/devstack/components/quantum_client.py +++ b/devstack/components/quantum_client.py @@ -16,7 +16,6 @@ from devstack import component as comp from devstack import log as logging -from devstack import settings LOG = logging.getLogger("devstack.components.quantum_client") diff --git a/devstack/components/swift.py b/devstack/components/swift.py index d0caf7e9..cb4a765e 100644 --- a/devstack/components/swift.py +++ b/devstack/components/swift.py @@ -18,7 +18,6 @@ import re from devstack import component as comp from devstack import log as logging -from devstack import settings from devstack import shell as sh from devstack import utils diff --git a/devstack/distro.py b/devstack/distro.py index dfbc38a4..1e319dc1 100644 --- a/devstack/distro.py +++ b/devstack/distro.py @@ -16,7 +16,6 @@ # under the License. import glob -import os import platform import re @@ -25,31 +24,28 @@ import yaml from devstack import importer from devstack import log as logging from devstack import settings -from devstack import utils - +from devstack import shell as sh LOG = logging.getLogger('devstack.distro') -DISTRO_CONF_DIR = os.path.join(settings.STACK_CONFIG_DIR, 'distros') - class Distro(object): @classmethod - def load_all(cls, path=DISTRO_CONF_DIR): + def load_all(cls, path=settings.STACK_DISTRO_DIR): """Returns a list of the known distros.""" results = [] - input_files = glob.glob(os.path.join(DISTRO_CONF_DIR, '*.yaml')) + input_files = glob.glob(sh.joinpths(path, '*.yaml')) if not input_files: raise RuntimeError( 'Did not find any distro definition files in %s' % - DISTRO_CONF_DIR) + path) for filename in input_files: try: with open(filename, 'r') as f: data = yaml.load(f) results.append(cls(**data)) - except Exception as err: + except (IOError, yaml.YAMLError) as err: LOG.warning('Could not load distro definition from %s: %s', filename, err) return results @@ -81,11 +77,23 @@ class Distro(object): def __repr__(self): return "\"%s\" using packager \"%s\"" % (self.name, self.packager_name) - def get_command(self, cmd_key, quiet=False): + def get_command(self, key, *args, **kargs): + place = self.commands + acutal_keys = [key] + list(args) + run_over_keys = acutal_keys[0:-1] + end_key = acutal_keys[-1] + quiet = kargs.get('quiet', False) + for k in run_over_keys: + if quiet: + place = place.get(k) + if place is None: + return None + else: + place = place[k] if not quiet: - return self.commands[cmd_key] + return place[end_key] else: - return self.commands.get(cmd_key) + return place.get(end_key) def supports_distro(self, distro_name): """Does this distro support the named Linux distro? diff --git a/devstack/distros/rhel6.py b/devstack/distros/rhel6.py index 154ad369..0179ca7a 100644 --- a/devstack/distros/rhel6.py +++ b/devstack/distros/rhel6.py @@ -18,11 +18,18 @@ """Platform-specific logic for RHEL6 components. """ -from devstack.components import db from devstack import log as logging +from devstack import shell as sh +from devstack import utils + +from devstack.components import db +from devstack.components import horizon LOG = logging.getLogger(__name__) +SOCKET_CONF = "/etc/httpd/conf.d/wsgi-socket-prefix.conf" +HTTPD_CONF = '/etc/httpd/conf/httpd.conf' + class Rhel6DBInstaller(db.DBInstaller): @@ -40,3 +47,25 @@ class Rhel6DBInstaller(db.DBInstaller): fc = utils.joinlinesep(*new_lines) with sh.Rooted(True): sh.write_file('/etc/my.cnf', fc) + + +class Rhel6HorizonInstaller(horizon.HorizonInstaller): + + def _config_fixups(self): + (user, group) = self._get_apache_user_group() + self.tracewriter.file_touched(SOCKET_CONF) + # Not recorded since we aren't really creating this + LOG.info("Fixing up %s and %s files" % (SOCKET_CONF, HTTPD_CONF)) + with sh.Rooted(True): + # Fix the socket prefix to someplace we can use + fc = "WSGISocketPrefix %s" % (sh.joinpths(self.log_dir, "wsgi-socket")) + sh.write_file(SOCKET_CONF, fc) + # Now adjust the run user and group (of httpd.conf) + new_lines = list() + for line in sh.load_file(HTTPD_CONF).splitlines(): + if line.startswith("User "): + line = "User %s" % (user) + if line.startswith("Group "): + line = "Group %s" % (group) + new_lines.append(line) + sh.write_file(HTTPD_CONF, utils.joinlinesep(*new_lines)) diff --git a/devstack/importer.py b/devstack/importer.py index 5d18ff05..cf74f7c7 100644 --- a/devstack/importer.py +++ b/devstack/importer.py @@ -16,6 +16,9 @@ # under the License. +from devstack import utils + + def partition(fullname): """ The name should be in dotted.path:ClassName syntax. @@ -30,9 +33,9 @@ def import_entry_point(fullname): """ Given a name import the class and return it. """ - module_name, ignore, classname = partition(fullname) + (module_name, _, classname) = partition(fullname) try: - module = __import__(module_name) + module = utils.import_module(module_name, False) for submodule in module_name.split('.')[1:]: module = getattr(module, submodule) cls = getattr(module, classname) diff --git a/devstack/packaging/apt.py b/devstack/packaging/apt.py index aca7ca0c..6bb2054b 100644 --- a/devstack/packaging/apt.py +++ b/devstack/packaging/apt.py @@ -14,11 +14,9 @@ # License for the specific language governing permissions and limitations # under the License. -import time from devstack import log as logging from devstack import packager as pack -from devstack import settings from devstack import shell as sh LOG = logging.getLogger("devstack.packaging.apt") diff --git a/devstack/packaging/yum.py b/devstack/packaging/yum.py index 53ff07aa..fbcd369e 100644 --- a/devstack/packaging/yum.py +++ b/devstack/packaging/yum.py @@ -16,7 +16,6 @@ from devstack import log as logging from devstack import packager as pack -from devstack import settings from devstack import shell as sh LOG = logging.getLogger("devstack.packaging.yum") @@ -62,10 +61,10 @@ class YumPackager(pack.Packager): def _remove_special(self, pkgname, pkginfo): #TODO: maybe this should be a subclass that handles these differences - 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")) + #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")) return False #TODO: maybe this should be a subclass that handles these differences @@ -84,8 +83,9 @@ class YumPackager(pack.Packager): #TODO: maybe this should be a subclass that handles these differences def _install_special(self, pkgname, pkginfo): - if self.distro.name == settings.RHEL6 and pkgname in RHEL_RELINKS: - return self._install_rhel_relinks(pkgname, pkginfo) + # FIXME + #if self.distro.name == settings.RHEL6 and pkgname in RHEL_RELINKS: + # return self._install_rhel_relinks(pkgname, pkginfo) return False def install_batch(self, pkgs): diff --git a/devstack/pip.py b/devstack/pip.py index 9b7b06c5..1a24dae5 100644 --- a/devstack/pip.py +++ b/devstack/pip.py @@ -18,7 +18,6 @@ from devstack import exceptions as excp from devstack import log as logging from devstack import shell as sh -from devstack import settings LOG = logging.getLogger("devstack.pip") PIP_UNINSTALL_CMD_OPTS = ['-y', '-q'] diff --git a/devstack/progs/actions.py b/devstack/progs/actions.py index cf654e56..d9b64b21 100644 --- a/devstack/progs/actions.py +++ b/devstack/progs/actions.py @@ -21,7 +21,6 @@ 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 import passwords LOG = logging.getLogger("devstack.progs.actions") diff --git a/devstack/settings.py b/devstack/settings.py index 9a9d40d6..09038e85 100644 --- a/devstack/settings.py +++ b/devstack/settings.py @@ -15,7 +15,6 @@ # under the License. import os -import re import sys # What this program is called @@ -95,5 +94,6 @@ ACTIONS = [INSTALL, UNINSTALL, START, STOP] # Where the configs and templates should be at. STACK_BIN_DIR = os.path.abspath(os.path.dirname(sys.argv[0])) STACK_CONFIG_DIR = os.path.join(STACK_BIN_DIR, "conf") +STACK_DISTRO_DIR = os.path.join(STACK_BIN_DIR, "distros") STACK_TEMPLATE_DIR = os.path.join(STACK_CONFIG_DIR, "templates") STACK_CONFIG_LOCATION = os.path.join(STACK_CONFIG_DIR, "stack.ini") diff --git a/devstack/utils.py b/devstack/utils.py index 635781b3..808fe4f5 100644 --- a/devstack/utils.py +++ b/devstack/utils.py @@ -21,7 +21,6 @@ import distutils.version import json import netifaces import os -import platform import random import re import socket @@ -139,12 +138,15 @@ def to_bytes(text): return byte_val -def import_module(module_name): +def import_module(module_name, quiet=True): try: __import__(module_name) return sys.modules.get(module_name, None) except ImportError: - return None + if quiet: + return None + else: + raise def load_json(fn): diff --git a/stack b/stack index 07e27375..d8e3afe2 100755 --- a/stack +++ b/stack @@ -28,7 +28,6 @@ from devstack import env from devstack import env_rc from devstack import log as logging from devstack import opts -from devstack import passwords from devstack import settings from devstack import shell as sh from devstack import utils @@ -128,7 +127,9 @@ def run(args): (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)!! + # !! # If we didn't load them before, load them now if not loaded_rcs: