From 9871c5f963b6d98240635a9a447d14d46133c910 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Fri, 3 Feb 2012 00:50:58 +0000 Subject: Move cfg to nova.openstack.common Move it here so that it can be kept in sync with openstack-common using the new update.py script for code in openstack-common's incubation area. See here for more details: http://wiki.openstack.org/CommonLibrary#Incubation Note: this commit just moves the existing code in Nova with no other changes. A subsequent commit will sync it with latest openstack-common so that it is easier see the new changes. Change-Id: If88d678b1b9bad3d37117de7f7159d7fea8ab4c8 --- bin/clear_rabbit_queues | 2 +- bin/nova-ajax-console-proxy | 2 +- bin/nova-direct-api | 2 +- nova/api/auth.py | 2 +- nova/api/ec2/__init__.py | 2 +- nova/api/openstack/compute/__init__.py | 2 +- nova/auth/ldapdriver.py | 2 +- nova/auth/manager.py | 2 +- nova/cloudpipe/pipelib.py | 2 +- nova/common/cfg.py | 1126 ---------------------------- nova/compute/api.py | 2 +- nova/compute/manager.py | 2 +- nova/console/manager.py | 2 +- nova/console/vmrc.py | 2 +- nova/console/vmrc_manager.py | 2 +- nova/console/xvp.py | 2 +- nova/consoleauth/__init__.py | 2 +- nova/consoleauth/manager.py | 2 +- nova/crypto.py | 2 +- nova/db/api.py | 2 +- nova/db/base.py | 2 +- nova/flags.py | 2 +- nova/image/s3.py | 2 +- nova/ipv6/api.py | 2 +- nova/log.py | 2 +- nova/network/ldapdns.py | 2 +- nova/network/linux_net.py | 2 +- nova/network/manager.py | 2 +- nova/network/quantum/manager.py | 2 +- nova/network/quantum/melange_connection.py | 2 +- nova/network/quantum/quantum_connection.py | 2 +- nova/notifier/api.py | 2 +- nova/notifier/list_notifier.py | 2 +- nova/notifier/rabbit_notifier.py | 2 +- nova/objectstore/s3server.py | 2 +- nova/openstack/__init__.py | 15 + nova/openstack/common/__init__.py | 15 + nova/openstack/common/cfg.py | 1126 ++++++++++++++++++++++++++++ nova/policy.py | 2 +- nova/quota.py | 2 +- nova/rpc/__init__.py | 6 +- nova/rpc/common.py | 2 +- nova/rpc/impl_qpid.py | 2 +- nova/scheduler/api.py | 2 +- nova/scheduler/driver.py | 2 +- nova/scheduler/filters/core_filter.py | 2 +- nova/scheduler/filters/ram_filter.py | 2 +- nova/scheduler/host_manager.py | 2 +- nova/scheduler/least_cost.py | 2 +- nova/scheduler/manager.py | 2 +- nova/scheduler/multi.py | 2 +- nova/scheduler/scheduler_options.py | 2 +- nova/scheduler/simple.py | 2 +- nova/scheduler/vsa.py | 2 +- nova/scheduler/zone_manager.py | 2 +- nova/service.py | 2 +- nova/test.py | 2 +- nova/tests/declare_flags.py | 2 +- nova/tests/runtime_flags.py | 2 +- nova/tests/test_cfg.py | 789 ------------------- nova/tests/test_flags.py | 2 +- nova/tests/test_service.py | 2 +- nova/utils.py | 2 +- nova/virt/disk/api.py | 2 +- nova/virt/disk/nbd.py | 2 +- nova/virt/firewall.py | 2 +- nova/virt/libvirt/connection.py | 2 +- nova/virt/libvirt/imagecache.py | 2 +- nova/virt/libvirt/utils.py | 2 +- nova/virt/libvirt/vif.py | 2 +- nova/virt/vmwareapi/vim.py | 2 +- nova/virt/vmwareapi/vmops.py | 2 +- nova/virt/vmwareapi_conn.py | 2 +- nova/virt/xenapi/vif.py | 2 +- nova/virt/xenapi/vm_utils.py | 2 +- nova/virt/xenapi/vmops.py | 2 +- nova/virt/xenapi_conn.py | 2 +- nova/vnc/__init__.py | 2 +- nova/vnc/xvp_proxy.py | 2 +- nova/volume/driver.py | 2 +- nova/volume/iscsi.py | 2 +- nova/volume/manager.py | 2 +- nova/volume/san.py | 3 +- nova/vsa/api.py | 2 +- nova/vsa/manager.py | 2 +- 85 files changed, 1238 insertions(+), 1998 deletions(-) delete mode 100644 nova/common/cfg.py create mode 100644 nova/openstack/__init__.py create mode 100644 nova/openstack/common/__init__.py create mode 100644 nova/openstack/common/cfg.py delete mode 100644 nova/tests/test_cfg.py diff --git a/bin/clear_rabbit_queues b/bin/clear_rabbit_queues index f697ef6b4..9d0d803a5 100755 --- a/bin/clear_rabbit_queues +++ b/bin/clear_rabbit_queues @@ -40,11 +40,11 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')): gettext.install('nova', unicode=1) -from nova.common import cfg from nova import context from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import rpc from nova import utils diff --git a/bin/nova-ajax-console-proxy b/bin/nova-ajax-console-proxy index 7dd5266a7..94d93cd0e 100755 --- a/bin/nova-ajax-console-proxy +++ b/bin/nova-ajax-console-proxy @@ -38,9 +38,9 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) -from nova.common import cfg from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import rpc from nova import service from nova import utils diff --git a/bin/nova-direct-api b/bin/nova-direct-api index f77311914..6a79ef626 100755 --- a/bin/nova-direct-api +++ b/bin/nova-direct-api @@ -35,11 +35,11 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) -from nova.common import cfg from nova import compute from nova import flags from nova import log as logging from nova import network +from nova.openstack.common import cfg from nova import service from nova import utils from nova import volume diff --git a/nova/api/auth.py b/nova/api/auth.py index 84ba3376d..cb601bdb3 100644 --- a/nova/api/auth.py +++ b/nova/api/auth.py @@ -21,10 +21,10 @@ Common Auth Middleware. import webob.dec import webob.exc -from nova.common import cfg from nova import context from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import wsgi diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index dfcddbc4e..c9e499f1d 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -32,11 +32,11 @@ from nova.api.ec2 import ec2utils from nova.api.ec2 import faults from nova.api import validator from nova.auth import manager -from nova.common import cfg from nova import context from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova import wsgi diff --git a/nova/api/openstack/compute/__init__.py b/nova/api/openstack/compute/__init__.py index d035173ed..3884ffbad 100644 --- a/nova/api/openstack/compute/__init__.py +++ b/nova/api/openstack/compute/__init__.py @@ -31,9 +31,9 @@ from nova.api.openstack.compute import limits from nova.api.openstack.compute import servers from nova.api.openstack.compute import server_metadata from nova.api.openstack.compute import versions -from nova.common import cfg from nova import flags from nova import log as logging +from nova.openstack.common import cfg LOG = logging.getLogger('nova.api.openstack.compute') diff --git a/nova/auth/ldapdriver.py b/nova/auth/ldapdriver.py index 79da5bd8d..3cb0de783 100644 --- a/nova/auth/ldapdriver.py +++ b/nova/auth/ldapdriver.py @@ -27,10 +27,10 @@ public methods. import functools import sys -from nova.common import cfg from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg ldap_opts = [ diff --git a/nova/auth/manager.py b/nova/auth/manager.py index 234b9bf33..40f1fc842 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -30,13 +30,13 @@ import tempfile import uuid import zipfile -from nova.common import cfg from nova import context from nova import crypto from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.auth import signer diff --git a/nova/cloudpipe/pipelib.py b/nova/cloudpipe/pipelib.py index 3c92f72b1..7d43866e6 100644 --- a/nova/cloudpipe/pipelib.py +++ b/nova/cloudpipe/pipelib.py @@ -27,13 +27,13 @@ import string import tempfile import zipfile -from nova.common import cfg from nova import context from nova import crypto from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils # TODO(eday): Eventually changes these to something not ec2-specific from nova.api.ec2 import cloud diff --git a/nova/common/cfg.py b/nova/common/cfg.py deleted file mode 100644 index bfb7b8a19..000000000 --- a/nova/common/cfg.py +++ /dev/null @@ -1,1126 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 Red Hat, Inc. -# -# 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. - -r""" -Configuration options which may be set on the command line or in config files. - -The schema for each option is defined using the Opt sub-classes e.g. - - common_opts = [ - cfg.StrOpt('bind_host', - default='0.0.0.0', - help='IP address to listen on'), - cfg.IntOpt('bind_port', - default=9292, - help='Port number to listen on') - ] - -Options can be strings, integers, floats, booleans, lists or 'multi strings': - - enabled_apis_opt = \ - cfg.ListOpt('enabled_apis', - default=['ec2', 'osapi_compute'], - help='List of APIs to enable by default') - - DEFAULT_EXTENSIONS = [ - 'nova.api.openstack.contrib.standard_extensions' - ] - osapi_compute_extension_opt = \ - cfg.MultiStrOpt('osapi_compute_extension', - default=DEFAULT_EXTENSIONS) - -Option schemas are registered with with the config manager at runtime, but -before the option is referenced: - - class ExtensionManager(object): - - enabled_apis_opt = cfg.ListOpt(...) - - def __init__(self, conf): - self.conf = conf - self.conf.register_opt(enabled_apis_opt) - ... - - def _load_extensions(self): - for ext_factory in self.conf.osapi_compute_extension: - .... - -A common usage pattern is for each option schema to be defined in the module or -class which uses the option: - - opts = ... - - def add_common_opts(conf): - conf.register_opts(opts) - - def get_bind_host(conf): - return conf.bind_host - - def get_bind_port(conf): - return conf.bind_port - -An option may optionally be made available via the command line. Such options -must registered with the config manager before the command line is parsed (for -the purposes of --help and CLI arg validation): - - cli_opts = [ - cfg.BoolOpt('verbose', - short='v', - default=False, - help='Print more verbose output'), - cfg.BoolOpt('debug', - short='d', - default=False, - help='Print debugging output'), - ] - - def add_common_opts(conf): - conf.register_cli_opts(cli_opts) - -The config manager has a single CLI option defined by default, --config-file: - - class ConfigOpts(object): - - config_file_opt = \ - MultiStrOpt('config-file', - ... - - def __init__(self, ...): - ... - self.register_cli_opt(self.config_file_opt) - -Option values are parsed from any supplied config files using SafeConfigParser. -If none are specified, a default set is used e.g. glance-api.conf and -glance-common.conf: - - glance-api.conf: - [DEFAULT] - bind_port = 9292 - - glance-common.conf: - [DEFAULT] - bind_host = 0.0.0.0 - -Option values in config files override those on the command line. Config files -are parsed in order, with values in later files overriding those in earlier -files. - -The parsing of CLI args and config files is initiated by invoking the config -manager e.g. - - conf = ConfigOpts() - conf.register_opt(BoolOpt('verbose', ...)) - conf(sys.argv[1:]) - if conf.verbose: - ... - -Options can be registered as belonging to a group: - - rabbit_group = cfg.OptionGroup(name='rabbit', - title='RabbitMQ options') - - rabbit_host_opt = \ - cfg.StrOpt('host', - group='rabbit', - default='localhost', - help='IP/hostname to listen on'), - rabbit_port_opt = \ - cfg.IntOpt('port', - default=5672, - help='Port number to listen on') - rabbit_ssl_opt = \ - conf.BoolOpt('use_ssl', - default=False, - help='Whether to support SSL connections') - - def register_rabbit_opts(conf): - conf.register_group(rabbit_group) - # options can be registered under a group in any of these ways: - conf.register_opt(rabbit_host_opt) - conf.register_opt(rabbit_port_opt, group='rabbit') - conf.register_opt(rabbit_ssl_opt, group=rabbit_group) - -If no group is specified, options belong to the 'DEFAULT' section of config -files: - - glance-api.conf: - [DEFAULT] - bind_port = 9292 - ... - - [rabbit] - host = localhost - port = 5672 - use_ssl = False - userid = guest - password = guest - virtual_host = / - -Command-line options in a group are automatically prefixed with the group name: - - --rabbit-host localhost --rabbit-use-ssl False - -Option values in the default group are referenced as attributes/properties on -the config manager; groups are also attributes on the config manager, with -attributes for each of the options associated with the group: - - server.start(app, conf.bind_port, conf.bind_host, conf) - - self.connection = kombu.connection.BrokerConnection( - hostname=conf.rabbit.host, - port=conf.rabbit.port, - ...) - -Option values may reference other values using PEP 292 string substitution: - - opts = [ - cfg.StrOpt('state_path', - default=os.path.join(os.path.dirname(__file__), '../'), - help='Top-level directory for maintaining nova state'), - cfg.StrOpt('sqlite_db', - default='nova.sqlite', - help='file name for sqlite'), - cfg.StrOpt('sql_connection', - default='sqlite:///$state_path/$sqlite_db', - help='connection string for sql database'), - ] - -Note that interpolation can be avoided by using '$$'. -""" - -import sys -import ConfigParser -import copy -import optparse -import os -import string - - -class Error(Exception): - """Base class for cfg exceptions.""" - - def __init__(self, msg=None): - self.msg = msg - - def __str__(self): - return self.msg - - -class ArgsAlreadyParsedError(Error): - """Raised if a CLI opt is registered after parsing.""" - - def __str__(self): - ret = "arguments already parsed" - if self.msg: - ret += ": " + self.msg - return ret - - -class NoSuchOptError(Error, AttributeError): - """Raised if an opt which doesn't exist is referenced.""" - - def __init__(self, opt_name, group=None): - self.opt_name = opt_name - self.group = group - - def __str__(self): - if self.group is None: - return "no such option: %s" % self.opt_name - else: - return "no such option in group %s: %s" % (self.group.name, - self.opt_name) - - -class NoSuchGroupError(Error): - """Raised if a group which doesn't exist is referenced.""" - - def __init__(self, group_name): - self.group_name = group_name - - def __str__(self): - return "no such group: %s" % self.group_name - - -class DuplicateOptError(Error): - """Raised if multiple opts with the same name are registered.""" - - def __init__(self, opt_name): - self.opt_name = opt_name - - def __str__(self): - return "duplicate option: %s" % self.opt_name - - -class TemplateSubstitutionError(Error): - """Raised if an error occurs substituting a variable in an opt value.""" - - def __str__(self): - return "template substitution error: %s" % self.msg - - -class ConfigFilesNotFoundError(Error): - """Raised if one or more config files are not found.""" - - def __init__(self, config_files): - self.config_files = config_files - - def __str__(self): - return 'Failed to read some config files: %s' % \ - string.join(self.config_files, ',') - - -class ConfigFileParseError(Error): - """Raised if there is an error parsing a config file.""" - - def __init__(self, config_file, msg): - self.config_file = config_file - self.msg = msg - - def __str__(self): - return 'Failed to parse %s: %s' % (self.config_file, self.msg) - - -class ConfigFileValueError(Error): - """Raised if a config file value does not match its opt type.""" - pass - - -def find_config_files(project=None, prog=None): - """Return a list of default configuration files. - - We default to two config files: [${project}.conf, ${prog}.conf] - - And we look for those config files in the following directories: - - ~/.${project}/ - ~/ - /etc/${project}/ - /etc/ - - We return an absolute path for (at most) one of each the default config - files, for the topmost directory it exists in. - - For example, if project=foo, prog=bar and /etc/foo/foo.conf, /etc/bar.conf - and ~/.foo/bar.conf all exist, then we return ['/etc/foo/foo.conf', - '~/.foo/bar.conf'] - - If no project name is supplied, we only look for ${prog.conf}. - - :param project: an optional project name - :param prog: the program name, defaulting to the basename of sys.argv[0] - """ - if prog is None: - prog = os.path.basename(sys.argv[0]) - - fix_path = lambda p: os.path.abspath(os.path.expanduser(p)) - - cfg_dirs = [ - fix_path(os.path.join('~', '.' + project)) if project else None, - fix_path('~'), - os.path.join('/etc', project) if project else None, - '/etc' - ] - cfg_dirs = filter(bool, cfg_dirs) - - def search_dirs(dirs, basename): - for d in dirs: - path = os.path.join(d, basename) - if os.path.exists(path): - return path - - config_files = [] - if project: - config_files.append(search_dirs(cfg_dirs, '%s.conf' % project)) - config_files.append(search_dirs(cfg_dirs, '%s.conf' % prog)) - - return filter(bool, config_files) - - -def _is_opt_registered(opts, opt): - """Check whether an opt with the same name is already registered. - - The same opt may be registered multiple times, with only the first - registration having any effect. However, it is an error to attempt - to register a different opt with the same name. - - :param opts: the set of opts already registered - :param opt: the opt to be registered - :returns: True if the opt was previously registered, False otherwise - :raises: DuplicateOptError if a naming conflict is detected - """ - if opt.dest in opts: - if opts[opt.dest]['opt'] is not opt: - raise DuplicateOptError(opt.name) - return True - else: - return False - - -class Opt(object): - - """Base class for all configuration options. - - An Opt object has no public methods, but has a number of public string - properties: - - name: - the name of the option, which may include hyphens - dest: - the (hyphen-less) ConfigOpts property which contains the option value - short: - a single character CLI option name - default: - the default value of the option - metavar: - the name shown as the argument to a CLI option in --help output - help: - an string explaining how the options value is used - """ - - def __init__(self, name, dest=None, short=None, - default=None, metavar=None, help=None): - """Construct an Opt object. - - The only required parameter is the option's name. However, it is - common to also supply a default and help string for all options. - - :param name: the option's name - :param dest: the name of the corresponding ConfigOpts property - :param short: a single character CLI option name - :param default: the default value of the option - :param metavar: the option argument to show in --help - :param help: an explanation of how the option is used - """ - self.name = name - if dest is None: - self.dest = self.name.replace('-', '_') - else: - self.dest = dest - self.short = short - self.default = default - self.metavar = metavar - self.help = help - - def _get_from_config_parser(self, cparser, section): - """Retrieves the option value from a ConfigParser object. - - This is the method ConfigOpts uses to look up the option value from - config files. Most opt types override this method in order to perform - type appropriate conversion of the returned value. - - :param cparser: a ConfigParser object - :param section: a section name - """ - return cparser.get(section, self.dest) - - def _add_to_cli(self, parser, group=None): - """Makes the option available in the command line interface. - - This is the method ConfigOpts uses to add the opt to the CLI interface - as appropriate for the opt type. Some opt types may extend this method, - others may just extend the helper methods it uses. - - :param parser: the CLI option parser - :param group: an optional OptGroup object - """ - container = self._get_optparse_container(parser, group) - kwargs = self._get_optparse_kwargs(group) - prefix = self._get_optparse_prefix('', group) - self._add_to_optparse(container, self.name, self.short, kwargs, prefix) - - def _add_to_optparse(self, container, name, short, kwargs, prefix=''): - """Add an option to an optparse parser or group. - - :param container: an optparse.OptionContainer object - :param name: the opt name - :param short: the short opt name - :param kwargs: the keyword arguments for add_option() - :param prefix: an optional prefix to prepend to the opt name - :raises: DuplicateOptError if a naming confict is detected - """ - args = ['--' + prefix + name] - if short: - args += ['-' + short] - for a in args: - if container.has_option(a): - raise DuplicateOptError(a) - container.add_option(*args, **kwargs) - - def _get_optparse_container(self, parser, group): - """Returns an optparse.OptionContainer. - - :param parser: an optparse.OptionParser - :param group: an (optional) OptGroup object - :returns: an optparse.OptionGroup if a group is given, else the parser - """ - if group is not None: - return group._get_optparse_group(parser) - else: - return parser - - def _get_optparse_kwargs(self, group, **kwargs): - """Build a dict of keyword arguments for optparse's add_option(). - - Most opt types extend this method to customize the behaviour of the - options added to optparse. - - :param group: an optional group - :param kwargs: optional keyword arguments to add to - :returns: a dict of keyword arguments - """ - dest = self.dest - if group is not None: - dest = group.name + '_' + dest - kwargs.update({ - 'dest': dest, - 'metavar': self.metavar, - 'help': self.help, - }) - return kwargs - - def _get_optparse_prefix(self, prefix, group): - """Build a prefix for the CLI option name, if required. - - CLI options in a group are prefixed with the group's name in order - to avoid conflicts between similarly named options in different - groups. - - :param prefix: an existing prefix to append to (e.g. 'no' or '') - :param group: an optional OptGroup object - :returns: a CLI option prefix including the group name, if appropriate - """ - if group is not None: - return group.name + '-' + prefix - else: - return prefix - - -class StrOpt(Opt): - """ - String opts do not have their values transformed and are returned as - str objects. - """ - pass - - -class BoolOpt(Opt): - - """ - Bool opts are set to True or False on the command line using --optname or - --noopttname respectively. - - In config files, boolean values are case insensitive and can be set using - 1/0, yes/no, true/false or on/off. - """ - - def _get_from_config_parser(self, cparser, section): - """Retrieve the opt value as a boolean from ConfigParser.""" - return cparser.getboolean(section, self.dest) - - def _add_to_cli(self, parser, group=None): - """Extends the base class method to add the --nooptname option.""" - super(BoolOpt, self)._add_to_cli(parser, group) - self._add_inverse_to_optparse(parser, group) - - def _add_inverse_to_optparse(self, parser, group): - """Add the --nooptname option to the option parser.""" - container = self._get_optparse_container(parser, group) - kwargs = self._get_optparse_kwargs(group, action='store_false') - prefix = self._get_optparse_prefix('no', group) - self._add_to_optparse(container, self.name, None, kwargs, prefix) - - def _get_optparse_kwargs(self, group, action='store_true', **kwargs): - """Extends the base optparse keyword dict for boolean options.""" - return super(BoolOpt, - self)._get_optparse_kwargs(group, action=action, **kwargs) - - -class IntOpt(Opt): - - """Int opt values are converted to integers using the int() builtin.""" - - def _get_from_config_parser(self, cparser, section): - """Retrieve the opt value as a integer from ConfigParser.""" - return cparser.getint(section, self.dest) - - def _get_optparse_kwargs(self, group, **kwargs): - """Extends the base optparse keyword dict for integer options.""" - return super(IntOpt, - self)._get_optparse_kwargs(group, type='int', **kwargs) - - -class FloatOpt(Opt): - - """Float opt values are converted to floats using the float() builtin.""" - - def _get_from_config_parser(self, cparser, section): - """Retrieve the opt value as a float from ConfigParser.""" - return cparser.getfloat(section, self.dest) - - def _get_optparse_kwargs(self, group, **kwargs): - """Extends the base optparse keyword dict for float options.""" - return super(FloatOpt, - self)._get_optparse_kwargs(group, type='float', **kwargs) - - -class ListOpt(Opt): - - """ - List opt values are simple string values separated by commas. The opt value - is a list containing these strings. - """ - - def _get_from_config_parser(self, cparser, section): - """Retrieve the opt value as a list from ConfigParser.""" - return cparser.get(section, self.dest).split(',') - - def _get_optparse_kwargs(self, group, **kwargs): - """Extends the base optparse keyword dict for list options.""" - return super(ListOpt, - self)._get_optparse_kwargs(group, - type='string', - action='callback', - callback=self._parse_list, - **kwargs) - - def _parse_list(self, option, opt, value, parser): - """An optparse callback for parsing an option value into a list.""" - setattr(parser.values, self.dest, value.split(',')) - - -class MultiStrOpt(Opt): - - """ - Multistr opt values are string opts which may be specified multiple times. - The opt value is a list containing all the string values specified. - """ - - def _get_from_config_parser(self, cparser, section): - """Retrieve the opt value as a multistr from ConfigParser.""" - # FIXME(markmc): values spread across the CLI and multiple - # config files should be appended - value = \ - super(MultiStrOpt, self)._get_from_config_parser(cparser, section) - return value if value is None else [value] - - def _get_optparse_kwargs(self, group, **kwargs): - """Extends the base optparse keyword dict for multi str options.""" - return super(MultiStrOpt, - self)._get_optparse_kwargs(group, action='append') - - -class OptGroup(object): - - """ - Represents a group of opts. - - CLI opts in the group are automatically prefixed with the group name. - - Each group corresponds to a section in config files. - - An OptGroup object has no public methods, but has a number of public string - properties: - - name: - the name of the group - title: - the group title as displayed in --help - help: - the group description as displayed in --help - """ - - def __init__(self, name, title=None, help=None): - """Constructs an OptGroup object. - - :param name: the group name - :param title: the group title for --help - :param help: the group description for --help - """ - self.name = name - if title is None: - self.title = "%s options" % title - else: - self.title = title - self.help = help - - self._opts = {} # dict of dicts of {opt:, override:, default:) - self._optparse_group = None - - def _register_opt(self, opt): - """Add an opt to this group. - - :param opt: an Opt object - :returns: False if previously registered, True otherwise - :raises: DuplicateOptError if a naming conflict is detected - """ - if _is_opt_registered(self._opts, opt): - return False - - self._opts[opt.dest] = {'opt': opt, 'override': None, 'default': None} - - return True - - def _get_optparse_group(self, parser): - """Build an optparse.OptionGroup for this group.""" - if self._optparse_group is None: - self._optparse_group = \ - optparse.OptionGroup(parser, self.title, self.help) - return self._optparse_group - - -class ConfigOpts(object): - - """ - Config options which may be set on the command line or in config files. - - ConfigOpts is a configuration option manager with APIs for registering - option schemas, grouping options, parsing option values and retrieving - the values of options. - """ - - def __init__(self, - project=None, - prog=None, - version=None, - usage=None, - default_config_files=None): - """Construct a ConfigOpts object. - - Automatically registers the --config-file option with either a supplied - list of default config files, or a list from find_config_files(). - - :param project: the toplevel project name, used to locate config files - :param prog: the name of the program (defaults to sys.argv[0] basename) - :param version: the program version (for --version) - :param usage: a usage string (%prog will be expanded) - :param default_config_files: config files to use by default - """ - if prog is None: - prog = os.path.basename(sys.argv[0]) - - if default_config_files is None: - default_config_files = find_config_files(project, prog) - - self.project = project - self.prog = prog - self.version = version - self.usage = usage - self.default_config_files = default_config_files - - self._opts = {} # dict of dicts of (opt:, override:, default:) - self._groups = {} - - self._args = None - self._cli_values = {} - - self._oparser = optparse.OptionParser(prog=self.prog, - version=self.version, - usage=self.usage) - self._cparser = None - - self.register_cli_opt(\ - MultiStrOpt('config-file', - default=self.default_config_files, - metavar='PATH', - help='Path to a config file to use. Multiple config ' - 'files can be specified, with values in later ' - 'files taking precedence. The default files used ' - 'are: %s' % (self.default_config_files, ))) - - def __call__(self, args=None): - """Parse command line arguments and config files. - - Calling a ConfigOpts object causes the supplied command line arguments - and config files to be parsed, causing opt values to be made available - as attributes of the object. - - The object may be called multiple times, each time causing the previous - set of values to be overwritten. - - :params args: command line arguments (defaults to sys.argv[1:]) - :returns: the list of arguments left over after parsing options - :raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError - """ - self.reset() - - self._args = args - - (values, args) = self._oparser.parse_args(self._args) - - self._cli_values = vars(values) - - if self.config_file: - self._parse_config_files(self.config_file) - - return args - - def __getattr__(self, name): - """Look up an option value and perform string substitution. - - :param name: the opt name (or 'dest', more precisely) - :returns: the option value (after string subsititution) or a GroupAttr - :raises: NoSuchOptError,ConfigFileValueError,TemplateSubstitutionError - """ - return self._substitute(self._get(name)) - - def reset(self): - """Reset the state of the object to before it was called.""" - self._args = None - self._cli_values = None - self._cparser = None - - def register_opt(self, opt, group=None): - """Register an option schema. - - Registering an option schema makes any option value which is previously - or subsequently parsed from the command line or config files available - as an attribute of this object. - - :param opt: an instance of an Opt sub-class - :param group: an optional OptGroup object or group name - :return: False if the opt was already register, True otherwise - :raises: DuplicateOptError - """ - if group is not None: - return self._get_group(group)._register_opt(opt) - - if _is_opt_registered(self._opts, opt): - return False - - self._opts[opt.dest] = {'opt': opt, 'override': None, 'default': None} - - return True - - def register_opts(self, opts, group=None): - """Register multiple option schemas at once.""" - for opt in opts: - self.register_opt(opt, group) - - def register_cli_opt(self, opt, group=None): - """Register a CLI option schema. - - CLI option schemas must be registered before the command line and - config files are parsed. This is to ensure that all CLI options are - show in --help and option validation works as expected. - - :param opt: an instance of an Opt sub-class - :param group: an optional OptGroup object or group name - :return: False if the opt was already register, True otherwise - :raises: DuplicateOptError, ArgsAlreadyParsedError - """ - if self._args is not None: - raise ArgsAlreadyParsedError("cannot register CLI option") - - if not self.register_opt(opt, group): - return False - - if group is not None: - group = self._get_group(group) - - opt._add_to_cli(self._oparser, group) - - return True - - def register_cli_opts(self, opts, group=None): - """Register multiple CLI option schemas at once.""" - for opt in opts: - self.register_cli_opt(opt, group) - - def register_group(self, group): - """Register an option group. - - An option group must be registered before options can be registered - with the group. - - :param group: an OptGroup object - """ - if group.name in self._groups: - return - - self._groups[group.name] = copy.copy(group) - - def set_override(self, name, override, group=None): - """Override an opt value. - - Override the command line, config file and default values of a - given option. - - :param name: the name/dest of the opt - :param override: the override value - :param group: an option OptGroup object or group name - :raises: NoSuchOptError, NoSuchGroupError - """ - opt_info = self._get_opt_info(name, group) - opt_info['override'] = override - - def set_default(self, name, default, group=None): - """Override an opt's default value. - - Override the default value of given option. A command line or - config file value will still take precedence over this default. - - :param name: the name/dest of the opt - :param default: the default value - :param group: an option OptGroup object or group name - :raises: NoSuchOptError, NoSuchGroupError - """ - opt_info = self._get_opt_info(name, group) - opt_info['default'] = default - - def log_opt_values(self, logger, lvl): - """Log the value of all registered opts. - - It's often useful for an app to log its configuration to a log file at - startup for debugging. This method dumps to the entire config state to - the supplied logger at a given log level. - - :param logger: a logging.Logger object - :param lvl: the log level (e.g. logging.DEBUG) arg to logger.log() - """ - logger.log(lvl, "*" * 80) - logger.log(lvl, "Configuration options gathered from:") - logger.log(lvl, "command line args: %s", self._args) - logger.log(lvl, "config files: %s", self.config_file) - logger.log(lvl, "=" * 80) - - for opt_name in sorted(self._opts): - logger.log(lvl, "%-30s = %s", opt_name, getattr(self, opt_name)) - - for group_name in self._groups: - group_attr = self.GroupAttr(self, group_name) - for opt_name in sorted(self._groups[group_name]._opts): - logger.log(lvl, "%-30s = %s", - "%s.%s" % (group_name, opt_name), - getattr(group_attr, opt_name)) - - logger.log(lvl, "*" * 80) - - def print_usage(self, file=None): - """Print the usage message for the current program.""" - self._oparser.print_usage(file) - - def _get(self, name, group=None): - """Look up an option value. - - :param name: the opt name (or 'dest', more precisely) - :param group: an option OptGroup - :returns: the option value, or a GroupAttr object - :raises: NoSuchOptError, NoSuchGroupError, ConfigFileValueError, - TemplateSubstitutionError - """ - if group is None and name in self._groups: - return self.GroupAttr(self, name) - - if group is not None: - group = self._get_group(group) - - info = self._get_opt_info(name, group) - default, opt, override = map(lambda k: info[k], sorted(info.keys())) - - if override is not None: - return override - - if self._cparser is not None: - section = group.name if group is not None else 'DEFAULT' - try: - return opt._get_from_config_parser(self._cparser, section) - except (ConfigParser.NoOptionError, - ConfigParser.NoSectionError): - pass - except ValueError, ve: - raise ConfigFileValueError(str(ve)) - - name = name if group is None else group.name + '_' + name - value = self._cli_values.get(name, None) - if value is not None: - return value - - if default is not None: - return default - - return opt.default - - def _substitute(self, value): - """Perform string template substitution. - - Substititue any template variables (e.g. $foo, ${bar}) in the supplied - string value(s) with opt values. - - :param value: the string value, or list of string values - :returns: the substituted string(s) - """ - if isinstance(value, list): - return [self._substitute(i) for i in value] - elif isinstance(value, str): - tmpl = string.Template(value) - return tmpl.safe_substitute(self.StrSubWrapper(self)) - else: - return value - - def _get_group(self, group_or_name): - """Looks up a OptGroup object. - - Helper function to return an OptGroup given a parameter which can - either be the group's name or an OptGroup object. - - The OptGroup object returned is from the internal dict of OptGroup - objects, which will be a copy of any OptGroup object that users of - the API have access to. - - :param group_or_name: the group's name or the OptGroup object itself - :raises: NoSuchGroupError - """ - if isinstance(group_or_name, OptGroup): - group_name = group_or_name.name - else: - group_name = group_or_name - - if not group_name in self._groups: - raise NoSuchGroupError(group_name) - - return self._groups[group_name] - - def _get_opt_info(self, opt_name, group=None): - """Return the (opt, override, default) dict for an opt. - - :param opt_name: an opt name/dest - :param group: an optional group name or OptGroup object - :raises: NoSuchOptError, NoSuchGroupError - """ - if group is None: - opts = self._opts - else: - group = self._get_group(group) - opts = group._opts - - if not opt_name in opts: - raise NoSuchOptError(opt_name, group) - - return opts[opt_name] - - def _parse_config_files(self, config_files): - """Parse the supplied configuration files. - - :raises: ConfigFilesNotFoundError, ConfigFileParseError - """ - self._cparser = ConfigParser.SafeConfigParser() - - try: - read_ok = self._cparser.read(config_files) - except ConfigParser.ParsingError, cpe: - raise ConfigFileParseError(cpe.filename, cpe.message) - - if read_ok != config_files: - not_read_ok = filter(lambda f: f not in read_ok, config_files) - raise ConfigFilesNotFoundError(not_read_ok) - - class GroupAttr(object): - - """ - A helper class representing the option values of a group as attributes. - """ - - def __init__(self, conf, group): - """Construct a GroupAttr object. - - :param conf: a ConfigOpts object - :param group: a group name or OptGroup object - """ - self.conf = conf - self.group = group - - def __getattr__(self, name): - """Look up an option value and perform template substitution.""" - return self.conf._substitute(self.conf._get(name, self.group)) - - class StrSubWrapper(object): - - """ - A helper class exposing opt values as a dict for string substitution. - """ - - def __init__(self, conf): - """Construct a StrSubWrapper object. - - :param conf: a ConfigOpts object - """ - self.conf = conf - - def __getitem__(self, key): - """Look up an opt value from the ConfigOpts object. - - :param key: an opt name - :returns: an opt value - :raises: TemplateSubstitutionError if attribute is a group - """ - value = getattr(self.conf, key) - if isinstance(value, self.conf.GroupAttr): - raise TemplateSubstitutionError( - 'substituting group %s not supported' % key) - return value - - -class CommonConfigOpts(ConfigOpts): - - DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s" - DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" - - common_cli_opts = [ - BoolOpt('debug', - short='d', - default=False, - help='Print debugging output'), - BoolOpt('verbose', - short='v', - default=False, - help='Print more verbose output'), - ] - - logging_cli_opts = [ - StrOpt('log-config', - metavar='PATH', - help='If this option is specified, the logging configuration ' - 'file specified is used and overrides any other logging ' - 'options specified. Please see the Python logging module ' - 'documentation for details on logging configuration ' - 'files.'), - StrOpt('log-format', - default=DEFAULT_LOG_FORMAT, - metavar='FORMAT', - help='A logging.Formatter log message format string which may ' - 'use any of the available logging.LogRecord attributes. ' - 'Default: %default'), - StrOpt('log-date-format', - default=DEFAULT_LOG_DATE_FORMAT, - metavar='DATE_FORMAT', - help='Format string for %(asctime)s in log records. ' - 'Default: %default'), - StrOpt('log-file', - metavar='PATH', - help='(Optional) Name of log file to output to. ' - 'If not set, logging will go to stdout.'), - StrOpt('log-dir', - help='(Optional) The directory to keep log files in ' - '(will be prepended to --logfile)'), - BoolOpt('use-syslog', - default=False, - help='Use syslog for logging.'), - ] - - def __init__(self, **kwargs): - super(CommonConfigOpts, self).__init__(**kwargs) - self.register_cli_opts(self.common_cli_opts) - self.register_cli_opts(self.logging_cli_opts) diff --git a/nova/compute/api.py b/nova/compute/api.py index 42c4ea4f0..f54d184dd 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -28,7 +28,6 @@ import novaclient import webob.exc from nova import block_device -from nova.common import cfg from nova.compute import aggregate_states from nova.compute import instance_types from nova.compute import power_state @@ -40,6 +39,7 @@ from nova import flags import nova.image from nova import log as logging from nova import network +from nova.openstack.common import cfg import nova.policy from nova import quota from nova import rpc diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 0d49a19c4..64401eeca 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -45,7 +45,6 @@ from eventlet import greenthread from nova import block_device import nova.context -from nova.common import cfg from nova.compute import instance_types from nova.compute import power_state from nova.compute import task_states @@ -59,6 +58,7 @@ from nova import manager from nova import network from nova.network import model as network_model from nova.notifier import api as notifier +from nova.openstack.common import cfg from nova import rpc from nova import utils from nova.virt import driver diff --git a/nova/console/manager.py b/nova/console/manager.py index 220ac32c5..a181ee437 100644 --- a/nova/console/manager.py +++ b/nova/console/manager.py @@ -19,10 +19,10 @@ import socket -from nova.common import cfg from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import manager from nova import rpc from nova import utils diff --git a/nova/console/vmrc.py b/nova/console/vmrc.py index e29254d60..a104a5f7b 100644 --- a/nova/console/vmrc.py +++ b/nova/console/vmrc.py @@ -20,9 +20,9 @@ import base64 import json -from nova.common import cfg from nova import exception from nova import flags +from nova.openstack.common import cfg from nova.virt.vmwareapi import vim_util diff --git a/nova/console/vmrc_manager.py b/nova/console/vmrc_manager.py index 03cc46bf6..161499830 100644 --- a/nova/console/vmrc_manager.py +++ b/nova/console/vmrc_manager.py @@ -17,11 +17,11 @@ """VMRC Console Manager.""" -from nova.common import cfg from nova import exception from nova import flags from nova import log as logging from nova import manager +from nova.openstack.common import cfg from nova import rpc from nova import utils from nova.virt import vmwareapi_conn diff --git a/nova/console/xvp.py b/nova/console/xvp.py index 2b8dcc1e0..35e57f086 100644 --- a/nova/console/xvp.py +++ b/nova/console/xvp.py @@ -22,12 +22,12 @@ import signal from Cheetah import Template -from nova.common import cfg from nova import context from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils diff --git a/nova/consoleauth/__init__.py b/nova/consoleauth/__init__.py index 4048ae433..4b28776c0 100644 --- a/nova/consoleauth/__init__.py +++ b/nova/consoleauth/__init__.py @@ -18,8 +18,8 @@ """Module to authenticate Consoles.""" -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg consoleauth_topic_opt = \ diff --git a/nova/consoleauth/manager.py b/nova/consoleauth/manager.py index 08ddd5a3b..b3f85e1f9 100644 --- a/nova/consoleauth/manager.py +++ b/nova/consoleauth/manager.py @@ -22,10 +22,10 @@ import os import sys import time -from nova.common import cfg from nova import flags from nova import log as logging from nova import manager +from nova.openstack.common import cfg from nova import utils diff --git a/nova/crypto.py b/nova/crypto.py index ddc2f76a0..79e40337b 100644 --- a/nova/crypto.py +++ b/nova/crypto.py @@ -33,12 +33,12 @@ import tempfile import Crypto.Cipher.AES -from nova.common import cfg from nova import context from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils diff --git a/nova/db/api.py b/nova/db/api.py index de7b1de74..a8869458c 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -43,9 +43,9 @@ these objects be simple dictionaries. """ -from nova.common import cfg from nova import exception from nova import flags +from nova.openstack.common import cfg from nova import utils diff --git a/nova/db/base.py b/nova/db/base.py index 77b7d82a7..a1b3bf711 100644 --- a/nova/db/base.py +++ b/nova/db/base.py @@ -18,9 +18,9 @@ """Base class for classes that need modular database access.""" -from nova.common import cfg from nova import utils from nova import flags +from nova.openstack.common import cfg db_driver_opt = \ diff --git a/nova/flags.py b/nova/flags.py index 4c0d61498..5be28240d 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -32,7 +32,7 @@ import sys import gflags -from nova.common import cfg +from nova.openstack.common import cfg class FlagValues(object): diff --git a/nova/image/s3.py b/nova/image/s3.py index ee11c163c..2be1b5ede 100644 --- a/nova/image/s3.py +++ b/nova/image/s3.py @@ -31,11 +31,11 @@ import eventlet from nova import rpc import nova.db.api -from nova.common import cfg from nova import exception from nova import flags from nova import image from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.api.ec2 import ec2utils diff --git a/nova/ipv6/api.py b/nova/ipv6/api.py index 5931b8ba6..ea6d8eb22 100644 --- a/nova/ipv6/api.py +++ b/nova/ipv6/api.py @@ -14,8 +14,8 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg from nova import utils diff --git a/nova/log.py b/nova/log.py index 6432a0bef..c0bc256cc 100644 --- a/nova/log.py +++ b/nova/log.py @@ -40,9 +40,9 @@ import sys import traceback import nova -from nova.common import cfg from nova import flags from nova import local +from nova.openstack.common import cfg from nova import version diff --git a/nova/network/ldapdns.py b/nova/network/ldapdns.py index a5491a259..a6d921186 100644 --- a/nova/network/ldapdns.py +++ b/nova/network/ldapdns.py @@ -19,10 +19,10 @@ import tempfile import time from nova.auth import fakeldap -from nova.common import cfg from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg LOG = logging.getLogger("nova.network.manager") diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 56d07f983..285f7b2f6 100755 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -24,11 +24,11 @@ import inspect import netaddr import os -from nova.common import cfg from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils diff --git a/nova/network/manager.py b/nova/network/manager.py index c6d3122b6..bce00f0fd 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -56,7 +56,6 @@ import socket from eventlet import greenpool import netaddr -from nova.common import cfg from nova.compute import api as compute_api from nova.compute import instance_types from nova import context @@ -68,6 +67,7 @@ from nova import log as logging from nova import manager from nova.network import api as network_api from nova.network import model as network_model +from nova.openstack.common import cfg import nova.policy from nova import quota from nova import utils diff --git a/nova/network/quantum/manager.py b/nova/network/quantum/manager.py index e4a3b4903..5e2729cac 100644 --- a/nova/network/quantum/manager.py +++ b/nova/network/quantum/manager.py @@ -19,7 +19,6 @@ import time from netaddr import IPNetwork, IPAddress -from nova.common import cfg from nova.compute import instance_types from nova import context from nova import db @@ -29,6 +28,7 @@ from nova import log as logging from nova.network import manager from nova.network.quantum import melange_ipam_lib from nova.network.quantum import quantum_connection +from nova.openstack.common import cfg from nova import utils LOG = logging.getLogger("nova.network.quantum.manager") diff --git a/nova/network/quantum/melange_connection.py b/nova/network/quantum/melange_connection.py index 499ace6b3..c7e3c606d 100644 --- a/nova/network/quantum/melange_connection.py +++ b/nova/network/quantum/melange_connection.py @@ -20,9 +20,9 @@ import socket import urllib import json -from nova.common import cfg from nova import flags from nova import log as logging +from nova.openstack.common import cfg melange_opts = [ diff --git a/nova/network/quantum/quantum_connection.py b/nova/network/quantum/quantum_connection.py index 914b816d1..d8a4e1a48 100644 --- a/nova/network/quantum/quantum_connection.py +++ b/nova/network/quantum/quantum_connection.py @@ -15,10 +15,10 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.common import cfg from nova import flags from nova import log as logging from nova.network.quantum import client as quantum_client +from nova.openstack.common import cfg LOG = logging.getLogger("nova.network.quantum.quantum_connection") diff --git a/nova/notifier/api.py b/nova/notifier/api.py index 50730cb0f..4a59e0ba1 100644 --- a/nova/notifier/api.py +++ b/nova/notifier/api.py @@ -15,10 +15,10 @@ import uuid -from nova.common import cfg from nova import flags from nova import utils from nova import log as logging +from nova.openstack.common import cfg LOG = logging.getLogger('nova.exception') diff --git a/nova/notifier/list_notifier.py b/nova/notifier/list_notifier.py index 29c6ba720..d952b613e 100644 --- a/nova/notifier/list_notifier.py +++ b/nova/notifier/list_notifier.py @@ -13,9 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.common import cfg from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.exception import ClassNotFound diff --git a/nova/notifier/rabbit_notifier.py b/nova/notifier/rabbit_notifier.py index c88f76cb0..25956c611 100644 --- a/nova/notifier/rabbit_notifier.py +++ b/nova/notifier/rabbit_notifier.py @@ -16,8 +16,8 @@ import nova.context -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg from nova import rpc diff --git a/nova/objectstore/s3server.py b/nova/objectstore/s3server.py index 1ba8d44cf..e5217b4b9 100644 --- a/nova/objectstore/s3server.py +++ b/nova/objectstore/s3server.py @@ -44,9 +44,9 @@ import urllib import routes import webob -from nova.common import cfg from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova import wsgi diff --git a/nova/openstack/__init__.py b/nova/openstack/__init__.py new file mode 100644 index 000000000..0a3b98867 --- /dev/null +++ b/nova/openstack/__init__.py @@ -0,0 +1,15 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Red Hat, Inc. +# +# 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. diff --git a/nova/openstack/common/__init__.py b/nova/openstack/common/__init__.py new file mode 100644 index 000000000..0a3b98867 --- /dev/null +++ b/nova/openstack/common/__init__.py @@ -0,0 +1,15 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Red Hat, Inc. +# +# 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. diff --git a/nova/openstack/common/cfg.py b/nova/openstack/common/cfg.py new file mode 100644 index 000000000..bfb7b8a19 --- /dev/null +++ b/nova/openstack/common/cfg.py @@ -0,0 +1,1126 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Red Hat, Inc. +# +# 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. + +r""" +Configuration options which may be set on the command line or in config files. + +The schema for each option is defined using the Opt sub-classes e.g. + + common_opts = [ + cfg.StrOpt('bind_host', + default='0.0.0.0', + help='IP address to listen on'), + cfg.IntOpt('bind_port', + default=9292, + help='Port number to listen on') + ] + +Options can be strings, integers, floats, booleans, lists or 'multi strings': + + enabled_apis_opt = \ + cfg.ListOpt('enabled_apis', + default=['ec2', 'osapi_compute'], + help='List of APIs to enable by default') + + DEFAULT_EXTENSIONS = [ + 'nova.api.openstack.contrib.standard_extensions' + ] + osapi_compute_extension_opt = \ + cfg.MultiStrOpt('osapi_compute_extension', + default=DEFAULT_EXTENSIONS) + +Option schemas are registered with with the config manager at runtime, but +before the option is referenced: + + class ExtensionManager(object): + + enabled_apis_opt = cfg.ListOpt(...) + + def __init__(self, conf): + self.conf = conf + self.conf.register_opt(enabled_apis_opt) + ... + + def _load_extensions(self): + for ext_factory in self.conf.osapi_compute_extension: + .... + +A common usage pattern is for each option schema to be defined in the module or +class which uses the option: + + opts = ... + + def add_common_opts(conf): + conf.register_opts(opts) + + def get_bind_host(conf): + return conf.bind_host + + def get_bind_port(conf): + return conf.bind_port + +An option may optionally be made available via the command line. Such options +must registered with the config manager before the command line is parsed (for +the purposes of --help and CLI arg validation): + + cli_opts = [ + cfg.BoolOpt('verbose', + short='v', + default=False, + help='Print more verbose output'), + cfg.BoolOpt('debug', + short='d', + default=False, + help='Print debugging output'), + ] + + def add_common_opts(conf): + conf.register_cli_opts(cli_opts) + +The config manager has a single CLI option defined by default, --config-file: + + class ConfigOpts(object): + + config_file_opt = \ + MultiStrOpt('config-file', + ... + + def __init__(self, ...): + ... + self.register_cli_opt(self.config_file_opt) + +Option values are parsed from any supplied config files using SafeConfigParser. +If none are specified, a default set is used e.g. glance-api.conf and +glance-common.conf: + + glance-api.conf: + [DEFAULT] + bind_port = 9292 + + glance-common.conf: + [DEFAULT] + bind_host = 0.0.0.0 + +Option values in config files override those on the command line. Config files +are parsed in order, with values in later files overriding those in earlier +files. + +The parsing of CLI args and config files is initiated by invoking the config +manager e.g. + + conf = ConfigOpts() + conf.register_opt(BoolOpt('verbose', ...)) + conf(sys.argv[1:]) + if conf.verbose: + ... + +Options can be registered as belonging to a group: + + rabbit_group = cfg.OptionGroup(name='rabbit', + title='RabbitMQ options') + + rabbit_host_opt = \ + cfg.StrOpt('host', + group='rabbit', + default='localhost', + help='IP/hostname to listen on'), + rabbit_port_opt = \ + cfg.IntOpt('port', + default=5672, + help='Port number to listen on') + rabbit_ssl_opt = \ + conf.BoolOpt('use_ssl', + default=False, + help='Whether to support SSL connections') + + def register_rabbit_opts(conf): + conf.register_group(rabbit_group) + # options can be registered under a group in any of these ways: + conf.register_opt(rabbit_host_opt) + conf.register_opt(rabbit_port_opt, group='rabbit') + conf.register_opt(rabbit_ssl_opt, group=rabbit_group) + +If no group is specified, options belong to the 'DEFAULT' section of config +files: + + glance-api.conf: + [DEFAULT] + bind_port = 9292 + ... + + [rabbit] + host = localhost + port = 5672 + use_ssl = False + userid = guest + password = guest + virtual_host = / + +Command-line options in a group are automatically prefixed with the group name: + + --rabbit-host localhost --rabbit-use-ssl False + +Option values in the default group are referenced as attributes/properties on +the config manager; groups are also attributes on the config manager, with +attributes for each of the options associated with the group: + + server.start(app, conf.bind_port, conf.bind_host, conf) + + self.connection = kombu.connection.BrokerConnection( + hostname=conf.rabbit.host, + port=conf.rabbit.port, + ...) + +Option values may reference other values using PEP 292 string substitution: + + opts = [ + cfg.StrOpt('state_path', + default=os.path.join(os.path.dirname(__file__), '../'), + help='Top-level directory for maintaining nova state'), + cfg.StrOpt('sqlite_db', + default='nova.sqlite', + help='file name for sqlite'), + cfg.StrOpt('sql_connection', + default='sqlite:///$state_path/$sqlite_db', + help='connection string for sql database'), + ] + +Note that interpolation can be avoided by using '$$'. +""" + +import sys +import ConfigParser +import copy +import optparse +import os +import string + + +class Error(Exception): + """Base class for cfg exceptions.""" + + def __init__(self, msg=None): + self.msg = msg + + def __str__(self): + return self.msg + + +class ArgsAlreadyParsedError(Error): + """Raised if a CLI opt is registered after parsing.""" + + def __str__(self): + ret = "arguments already parsed" + if self.msg: + ret += ": " + self.msg + return ret + + +class NoSuchOptError(Error, AttributeError): + """Raised if an opt which doesn't exist is referenced.""" + + def __init__(self, opt_name, group=None): + self.opt_name = opt_name + self.group = group + + def __str__(self): + if self.group is None: + return "no such option: %s" % self.opt_name + else: + return "no such option in group %s: %s" % (self.group.name, + self.opt_name) + + +class NoSuchGroupError(Error): + """Raised if a group which doesn't exist is referenced.""" + + def __init__(self, group_name): + self.group_name = group_name + + def __str__(self): + return "no such group: %s" % self.group_name + + +class DuplicateOptError(Error): + """Raised if multiple opts with the same name are registered.""" + + def __init__(self, opt_name): + self.opt_name = opt_name + + def __str__(self): + return "duplicate option: %s" % self.opt_name + + +class TemplateSubstitutionError(Error): + """Raised if an error occurs substituting a variable in an opt value.""" + + def __str__(self): + return "template substitution error: %s" % self.msg + + +class ConfigFilesNotFoundError(Error): + """Raised if one or more config files are not found.""" + + def __init__(self, config_files): + self.config_files = config_files + + def __str__(self): + return 'Failed to read some config files: %s' % \ + string.join(self.config_files, ',') + + +class ConfigFileParseError(Error): + """Raised if there is an error parsing a config file.""" + + def __init__(self, config_file, msg): + self.config_file = config_file + self.msg = msg + + def __str__(self): + return 'Failed to parse %s: %s' % (self.config_file, self.msg) + + +class ConfigFileValueError(Error): + """Raised if a config file value does not match its opt type.""" + pass + + +def find_config_files(project=None, prog=None): + """Return a list of default configuration files. + + We default to two config files: [${project}.conf, ${prog}.conf] + + And we look for those config files in the following directories: + + ~/.${project}/ + ~/ + /etc/${project}/ + /etc/ + + We return an absolute path for (at most) one of each the default config + files, for the topmost directory it exists in. + + For example, if project=foo, prog=bar and /etc/foo/foo.conf, /etc/bar.conf + and ~/.foo/bar.conf all exist, then we return ['/etc/foo/foo.conf', + '~/.foo/bar.conf'] + + If no project name is supplied, we only look for ${prog.conf}. + + :param project: an optional project name + :param prog: the program name, defaulting to the basename of sys.argv[0] + """ + if prog is None: + prog = os.path.basename(sys.argv[0]) + + fix_path = lambda p: os.path.abspath(os.path.expanduser(p)) + + cfg_dirs = [ + fix_path(os.path.join('~', '.' + project)) if project else None, + fix_path('~'), + os.path.join('/etc', project) if project else None, + '/etc' + ] + cfg_dirs = filter(bool, cfg_dirs) + + def search_dirs(dirs, basename): + for d in dirs: + path = os.path.join(d, basename) + if os.path.exists(path): + return path + + config_files = [] + if project: + config_files.append(search_dirs(cfg_dirs, '%s.conf' % project)) + config_files.append(search_dirs(cfg_dirs, '%s.conf' % prog)) + + return filter(bool, config_files) + + +def _is_opt_registered(opts, opt): + """Check whether an opt with the same name is already registered. + + The same opt may be registered multiple times, with only the first + registration having any effect. However, it is an error to attempt + to register a different opt with the same name. + + :param opts: the set of opts already registered + :param opt: the opt to be registered + :returns: True if the opt was previously registered, False otherwise + :raises: DuplicateOptError if a naming conflict is detected + """ + if opt.dest in opts: + if opts[opt.dest]['opt'] is not opt: + raise DuplicateOptError(opt.name) + return True + else: + return False + + +class Opt(object): + + """Base class for all configuration options. + + An Opt object has no public methods, but has a number of public string + properties: + + name: + the name of the option, which may include hyphens + dest: + the (hyphen-less) ConfigOpts property which contains the option value + short: + a single character CLI option name + default: + the default value of the option + metavar: + the name shown as the argument to a CLI option in --help output + help: + an string explaining how the options value is used + """ + + def __init__(self, name, dest=None, short=None, + default=None, metavar=None, help=None): + """Construct an Opt object. + + The only required parameter is the option's name. However, it is + common to also supply a default and help string for all options. + + :param name: the option's name + :param dest: the name of the corresponding ConfigOpts property + :param short: a single character CLI option name + :param default: the default value of the option + :param metavar: the option argument to show in --help + :param help: an explanation of how the option is used + """ + self.name = name + if dest is None: + self.dest = self.name.replace('-', '_') + else: + self.dest = dest + self.short = short + self.default = default + self.metavar = metavar + self.help = help + + def _get_from_config_parser(self, cparser, section): + """Retrieves the option value from a ConfigParser object. + + This is the method ConfigOpts uses to look up the option value from + config files. Most opt types override this method in order to perform + type appropriate conversion of the returned value. + + :param cparser: a ConfigParser object + :param section: a section name + """ + return cparser.get(section, self.dest) + + def _add_to_cli(self, parser, group=None): + """Makes the option available in the command line interface. + + This is the method ConfigOpts uses to add the opt to the CLI interface + as appropriate for the opt type. Some opt types may extend this method, + others may just extend the helper methods it uses. + + :param parser: the CLI option parser + :param group: an optional OptGroup object + """ + container = self._get_optparse_container(parser, group) + kwargs = self._get_optparse_kwargs(group) + prefix = self._get_optparse_prefix('', group) + self._add_to_optparse(container, self.name, self.short, kwargs, prefix) + + def _add_to_optparse(self, container, name, short, kwargs, prefix=''): + """Add an option to an optparse parser or group. + + :param container: an optparse.OptionContainer object + :param name: the opt name + :param short: the short opt name + :param kwargs: the keyword arguments for add_option() + :param prefix: an optional prefix to prepend to the opt name + :raises: DuplicateOptError if a naming confict is detected + """ + args = ['--' + prefix + name] + if short: + args += ['-' + short] + for a in args: + if container.has_option(a): + raise DuplicateOptError(a) + container.add_option(*args, **kwargs) + + def _get_optparse_container(self, parser, group): + """Returns an optparse.OptionContainer. + + :param parser: an optparse.OptionParser + :param group: an (optional) OptGroup object + :returns: an optparse.OptionGroup if a group is given, else the parser + """ + if group is not None: + return group._get_optparse_group(parser) + else: + return parser + + def _get_optparse_kwargs(self, group, **kwargs): + """Build a dict of keyword arguments for optparse's add_option(). + + Most opt types extend this method to customize the behaviour of the + options added to optparse. + + :param group: an optional group + :param kwargs: optional keyword arguments to add to + :returns: a dict of keyword arguments + """ + dest = self.dest + if group is not None: + dest = group.name + '_' + dest + kwargs.update({ + 'dest': dest, + 'metavar': self.metavar, + 'help': self.help, + }) + return kwargs + + def _get_optparse_prefix(self, prefix, group): + """Build a prefix for the CLI option name, if required. + + CLI options in a group are prefixed with the group's name in order + to avoid conflicts between similarly named options in different + groups. + + :param prefix: an existing prefix to append to (e.g. 'no' or '') + :param group: an optional OptGroup object + :returns: a CLI option prefix including the group name, if appropriate + """ + if group is not None: + return group.name + '-' + prefix + else: + return prefix + + +class StrOpt(Opt): + """ + String opts do not have their values transformed and are returned as + str objects. + """ + pass + + +class BoolOpt(Opt): + + """ + Bool opts are set to True or False on the command line using --optname or + --noopttname respectively. + + In config files, boolean values are case insensitive and can be set using + 1/0, yes/no, true/false or on/off. + """ + + def _get_from_config_parser(self, cparser, section): + """Retrieve the opt value as a boolean from ConfigParser.""" + return cparser.getboolean(section, self.dest) + + def _add_to_cli(self, parser, group=None): + """Extends the base class method to add the --nooptname option.""" + super(BoolOpt, self)._add_to_cli(parser, group) + self._add_inverse_to_optparse(parser, group) + + def _add_inverse_to_optparse(self, parser, group): + """Add the --nooptname option to the option parser.""" + container = self._get_optparse_container(parser, group) + kwargs = self._get_optparse_kwargs(group, action='store_false') + prefix = self._get_optparse_prefix('no', group) + self._add_to_optparse(container, self.name, None, kwargs, prefix) + + def _get_optparse_kwargs(self, group, action='store_true', **kwargs): + """Extends the base optparse keyword dict for boolean options.""" + return super(BoolOpt, + self)._get_optparse_kwargs(group, action=action, **kwargs) + + +class IntOpt(Opt): + + """Int opt values are converted to integers using the int() builtin.""" + + def _get_from_config_parser(self, cparser, section): + """Retrieve the opt value as a integer from ConfigParser.""" + return cparser.getint(section, self.dest) + + def _get_optparse_kwargs(self, group, **kwargs): + """Extends the base optparse keyword dict for integer options.""" + return super(IntOpt, + self)._get_optparse_kwargs(group, type='int', **kwargs) + + +class FloatOpt(Opt): + + """Float opt values are converted to floats using the float() builtin.""" + + def _get_from_config_parser(self, cparser, section): + """Retrieve the opt value as a float from ConfigParser.""" + return cparser.getfloat(section, self.dest) + + def _get_optparse_kwargs(self, group, **kwargs): + """Extends the base optparse keyword dict for float options.""" + return super(FloatOpt, + self)._get_optparse_kwargs(group, type='float', **kwargs) + + +class ListOpt(Opt): + + """ + List opt values are simple string values separated by commas. The opt value + is a list containing these strings. + """ + + def _get_from_config_parser(self, cparser, section): + """Retrieve the opt value as a list from ConfigParser.""" + return cparser.get(section, self.dest).split(',') + + def _get_optparse_kwargs(self, group, **kwargs): + """Extends the base optparse keyword dict for list options.""" + return super(ListOpt, + self)._get_optparse_kwargs(group, + type='string', + action='callback', + callback=self._parse_list, + **kwargs) + + def _parse_list(self, option, opt, value, parser): + """An optparse callback for parsing an option value into a list.""" + setattr(parser.values, self.dest, value.split(',')) + + +class MultiStrOpt(Opt): + + """ + Multistr opt values are string opts which may be specified multiple times. + The opt value is a list containing all the string values specified. + """ + + def _get_from_config_parser(self, cparser, section): + """Retrieve the opt value as a multistr from ConfigParser.""" + # FIXME(markmc): values spread across the CLI and multiple + # config files should be appended + value = \ + super(MultiStrOpt, self)._get_from_config_parser(cparser, section) + return value if value is None else [value] + + def _get_optparse_kwargs(self, group, **kwargs): + """Extends the base optparse keyword dict for multi str options.""" + return super(MultiStrOpt, + self)._get_optparse_kwargs(group, action='append') + + +class OptGroup(object): + + """ + Represents a group of opts. + + CLI opts in the group are automatically prefixed with the group name. + + Each group corresponds to a section in config files. + + An OptGroup object has no public methods, but has a number of public string + properties: + + name: + the name of the group + title: + the group title as displayed in --help + help: + the group description as displayed in --help + """ + + def __init__(self, name, title=None, help=None): + """Constructs an OptGroup object. + + :param name: the group name + :param title: the group title for --help + :param help: the group description for --help + """ + self.name = name + if title is None: + self.title = "%s options" % title + else: + self.title = title + self.help = help + + self._opts = {} # dict of dicts of {opt:, override:, default:) + self._optparse_group = None + + def _register_opt(self, opt): + """Add an opt to this group. + + :param opt: an Opt object + :returns: False if previously registered, True otherwise + :raises: DuplicateOptError if a naming conflict is detected + """ + if _is_opt_registered(self._opts, opt): + return False + + self._opts[opt.dest] = {'opt': opt, 'override': None, 'default': None} + + return True + + def _get_optparse_group(self, parser): + """Build an optparse.OptionGroup for this group.""" + if self._optparse_group is None: + self._optparse_group = \ + optparse.OptionGroup(parser, self.title, self.help) + return self._optparse_group + + +class ConfigOpts(object): + + """ + Config options which may be set on the command line or in config files. + + ConfigOpts is a configuration option manager with APIs for registering + option schemas, grouping options, parsing option values and retrieving + the values of options. + """ + + def __init__(self, + project=None, + prog=None, + version=None, + usage=None, + default_config_files=None): + """Construct a ConfigOpts object. + + Automatically registers the --config-file option with either a supplied + list of default config files, or a list from find_config_files(). + + :param project: the toplevel project name, used to locate config files + :param prog: the name of the program (defaults to sys.argv[0] basename) + :param version: the program version (for --version) + :param usage: a usage string (%prog will be expanded) + :param default_config_files: config files to use by default + """ + if prog is None: + prog = os.path.basename(sys.argv[0]) + + if default_config_files is None: + default_config_files = find_config_files(project, prog) + + self.project = project + self.prog = prog + self.version = version + self.usage = usage + self.default_config_files = default_config_files + + self._opts = {} # dict of dicts of (opt:, override:, default:) + self._groups = {} + + self._args = None + self._cli_values = {} + + self._oparser = optparse.OptionParser(prog=self.prog, + version=self.version, + usage=self.usage) + self._cparser = None + + self.register_cli_opt(\ + MultiStrOpt('config-file', + default=self.default_config_files, + metavar='PATH', + help='Path to a config file to use. Multiple config ' + 'files can be specified, with values in later ' + 'files taking precedence. The default files used ' + 'are: %s' % (self.default_config_files, ))) + + def __call__(self, args=None): + """Parse command line arguments and config files. + + Calling a ConfigOpts object causes the supplied command line arguments + and config files to be parsed, causing opt values to be made available + as attributes of the object. + + The object may be called multiple times, each time causing the previous + set of values to be overwritten. + + :params args: command line arguments (defaults to sys.argv[1:]) + :returns: the list of arguments left over after parsing options + :raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError + """ + self.reset() + + self._args = args + + (values, args) = self._oparser.parse_args(self._args) + + self._cli_values = vars(values) + + if self.config_file: + self._parse_config_files(self.config_file) + + return args + + def __getattr__(self, name): + """Look up an option value and perform string substitution. + + :param name: the opt name (or 'dest', more precisely) + :returns: the option value (after string subsititution) or a GroupAttr + :raises: NoSuchOptError,ConfigFileValueError,TemplateSubstitutionError + """ + return self._substitute(self._get(name)) + + def reset(self): + """Reset the state of the object to before it was called.""" + self._args = None + self._cli_values = None + self._cparser = None + + def register_opt(self, opt, group=None): + """Register an option schema. + + Registering an option schema makes any option value which is previously + or subsequently parsed from the command line or config files available + as an attribute of this object. + + :param opt: an instance of an Opt sub-class + :param group: an optional OptGroup object or group name + :return: False if the opt was already register, True otherwise + :raises: DuplicateOptError + """ + if group is not None: + return self._get_group(group)._register_opt(opt) + + if _is_opt_registered(self._opts, opt): + return False + + self._opts[opt.dest] = {'opt': opt, 'override': None, 'default': None} + + return True + + def register_opts(self, opts, group=None): + """Register multiple option schemas at once.""" + for opt in opts: + self.register_opt(opt, group) + + def register_cli_opt(self, opt, group=None): + """Register a CLI option schema. + + CLI option schemas must be registered before the command line and + config files are parsed. This is to ensure that all CLI options are + show in --help and option validation works as expected. + + :param opt: an instance of an Opt sub-class + :param group: an optional OptGroup object or group name + :return: False if the opt was already register, True otherwise + :raises: DuplicateOptError, ArgsAlreadyParsedError + """ + if self._args is not None: + raise ArgsAlreadyParsedError("cannot register CLI option") + + if not self.register_opt(opt, group): + return False + + if group is not None: + group = self._get_group(group) + + opt._add_to_cli(self._oparser, group) + + return True + + def register_cli_opts(self, opts, group=None): + """Register multiple CLI option schemas at once.""" + for opt in opts: + self.register_cli_opt(opt, group) + + def register_group(self, group): + """Register an option group. + + An option group must be registered before options can be registered + with the group. + + :param group: an OptGroup object + """ + if group.name in self._groups: + return + + self._groups[group.name] = copy.copy(group) + + def set_override(self, name, override, group=None): + """Override an opt value. + + Override the command line, config file and default values of a + given option. + + :param name: the name/dest of the opt + :param override: the override value + :param group: an option OptGroup object or group name + :raises: NoSuchOptError, NoSuchGroupError + """ + opt_info = self._get_opt_info(name, group) + opt_info['override'] = override + + def set_default(self, name, default, group=None): + """Override an opt's default value. + + Override the default value of given option. A command line or + config file value will still take precedence over this default. + + :param name: the name/dest of the opt + :param default: the default value + :param group: an option OptGroup object or group name + :raises: NoSuchOptError, NoSuchGroupError + """ + opt_info = self._get_opt_info(name, group) + opt_info['default'] = default + + def log_opt_values(self, logger, lvl): + """Log the value of all registered opts. + + It's often useful for an app to log its configuration to a log file at + startup for debugging. This method dumps to the entire config state to + the supplied logger at a given log level. + + :param logger: a logging.Logger object + :param lvl: the log level (e.g. logging.DEBUG) arg to logger.log() + """ + logger.log(lvl, "*" * 80) + logger.log(lvl, "Configuration options gathered from:") + logger.log(lvl, "command line args: %s", self._args) + logger.log(lvl, "config files: %s", self.config_file) + logger.log(lvl, "=" * 80) + + for opt_name in sorted(self._opts): + logger.log(lvl, "%-30s = %s", opt_name, getattr(self, opt_name)) + + for group_name in self._groups: + group_attr = self.GroupAttr(self, group_name) + for opt_name in sorted(self._groups[group_name]._opts): + logger.log(lvl, "%-30s = %s", + "%s.%s" % (group_name, opt_name), + getattr(group_attr, opt_name)) + + logger.log(lvl, "*" * 80) + + def print_usage(self, file=None): + """Print the usage message for the current program.""" + self._oparser.print_usage(file) + + def _get(self, name, group=None): + """Look up an option value. + + :param name: the opt name (or 'dest', more precisely) + :param group: an option OptGroup + :returns: the option value, or a GroupAttr object + :raises: NoSuchOptError, NoSuchGroupError, ConfigFileValueError, + TemplateSubstitutionError + """ + if group is None and name in self._groups: + return self.GroupAttr(self, name) + + if group is not None: + group = self._get_group(group) + + info = self._get_opt_info(name, group) + default, opt, override = map(lambda k: info[k], sorted(info.keys())) + + if override is not None: + return override + + if self._cparser is not None: + section = group.name if group is not None else 'DEFAULT' + try: + return opt._get_from_config_parser(self._cparser, section) + except (ConfigParser.NoOptionError, + ConfigParser.NoSectionError): + pass + except ValueError, ve: + raise ConfigFileValueError(str(ve)) + + name = name if group is None else group.name + '_' + name + value = self._cli_values.get(name, None) + if value is not None: + return value + + if default is not None: + return default + + return opt.default + + def _substitute(self, value): + """Perform string template substitution. + + Substititue any template variables (e.g. $foo, ${bar}) in the supplied + string value(s) with opt values. + + :param value: the string value, or list of string values + :returns: the substituted string(s) + """ + if isinstance(value, list): + return [self._substitute(i) for i in value] + elif isinstance(value, str): + tmpl = string.Template(value) + return tmpl.safe_substitute(self.StrSubWrapper(self)) + else: + return value + + def _get_group(self, group_or_name): + """Looks up a OptGroup object. + + Helper function to return an OptGroup given a parameter which can + either be the group's name or an OptGroup object. + + The OptGroup object returned is from the internal dict of OptGroup + objects, which will be a copy of any OptGroup object that users of + the API have access to. + + :param group_or_name: the group's name or the OptGroup object itself + :raises: NoSuchGroupError + """ + if isinstance(group_or_name, OptGroup): + group_name = group_or_name.name + else: + group_name = group_or_name + + if not group_name in self._groups: + raise NoSuchGroupError(group_name) + + return self._groups[group_name] + + def _get_opt_info(self, opt_name, group=None): + """Return the (opt, override, default) dict for an opt. + + :param opt_name: an opt name/dest + :param group: an optional group name or OptGroup object + :raises: NoSuchOptError, NoSuchGroupError + """ + if group is None: + opts = self._opts + else: + group = self._get_group(group) + opts = group._opts + + if not opt_name in opts: + raise NoSuchOptError(opt_name, group) + + return opts[opt_name] + + def _parse_config_files(self, config_files): + """Parse the supplied configuration files. + + :raises: ConfigFilesNotFoundError, ConfigFileParseError + """ + self._cparser = ConfigParser.SafeConfigParser() + + try: + read_ok = self._cparser.read(config_files) + except ConfigParser.ParsingError, cpe: + raise ConfigFileParseError(cpe.filename, cpe.message) + + if read_ok != config_files: + not_read_ok = filter(lambda f: f not in read_ok, config_files) + raise ConfigFilesNotFoundError(not_read_ok) + + class GroupAttr(object): + + """ + A helper class representing the option values of a group as attributes. + """ + + def __init__(self, conf, group): + """Construct a GroupAttr object. + + :param conf: a ConfigOpts object + :param group: a group name or OptGroup object + """ + self.conf = conf + self.group = group + + def __getattr__(self, name): + """Look up an option value and perform template substitution.""" + return self.conf._substitute(self.conf._get(name, self.group)) + + class StrSubWrapper(object): + + """ + A helper class exposing opt values as a dict for string substitution. + """ + + def __init__(self, conf): + """Construct a StrSubWrapper object. + + :param conf: a ConfigOpts object + """ + self.conf = conf + + def __getitem__(self, key): + """Look up an opt value from the ConfigOpts object. + + :param key: an opt name + :returns: an opt value + :raises: TemplateSubstitutionError if attribute is a group + """ + value = getattr(self.conf, key) + if isinstance(value, self.conf.GroupAttr): + raise TemplateSubstitutionError( + 'substituting group %s not supported' % key) + return value + + +class CommonConfigOpts(ConfigOpts): + + DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s" + DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" + + common_cli_opts = [ + BoolOpt('debug', + short='d', + default=False, + help='Print debugging output'), + BoolOpt('verbose', + short='v', + default=False, + help='Print more verbose output'), + ] + + logging_cli_opts = [ + StrOpt('log-config', + metavar='PATH', + help='If this option is specified, the logging configuration ' + 'file specified is used and overrides any other logging ' + 'options specified. Please see the Python logging module ' + 'documentation for details on logging configuration ' + 'files.'), + StrOpt('log-format', + default=DEFAULT_LOG_FORMAT, + metavar='FORMAT', + help='A logging.Formatter log message format string which may ' + 'use any of the available logging.LogRecord attributes. ' + 'Default: %default'), + StrOpt('log-date-format', + default=DEFAULT_LOG_DATE_FORMAT, + metavar='DATE_FORMAT', + help='Format string for %(asctime)s in log records. ' + 'Default: %default'), + StrOpt('log-file', + metavar='PATH', + help='(Optional) Name of log file to output to. ' + 'If not set, logging will go to stdout.'), + StrOpt('log-dir', + help='(Optional) The directory to keep log files in ' + '(will be prepended to --logfile)'), + BoolOpt('use-syslog', + default=False, + help='Use syslog for logging.'), + ] + + def __init__(self, **kwargs): + super(CommonConfigOpts, self).__init__(**kwargs) + self.register_cli_opts(self.common_cli_opts) + self.register_cli_opts(self.logging_cli_opts) diff --git a/nova/policy.py b/nova/policy.py index ccf1f4624..09b3ab988 100644 --- a/nova/policy.py +++ b/nova/policy.py @@ -17,10 +17,10 @@ """Policy Engine For Nova""" -from nova.common import cfg from nova.common import policy from nova import exception from nova import flags +from nova.openstack.common import cfg from nova import utils diff --git a/nova/quota.py b/nova/quota.py index d29ba685d..4a5eac4b4 100644 --- a/nova/quota.py +++ b/nova/quota.py @@ -18,8 +18,8 @@ """Quotas for instances, volumes, and floating ips.""" -from nova.common import cfg from nova import db +from nova.openstack.common import cfg from nova import flags diff --git a/nova/rpc/__init__.py b/nova/rpc/__init__.py index a6067432e..7c6ed29d0 100644 --- a/nova/rpc/__init__.py +++ b/nova/rpc/__init__.py @@ -17,10 +17,10 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.common import cfg -from nova.utils import import_object -from nova.rpc.common import RemoteError, LOG from nova import flags +from nova.openstack.common import cfg +from nova.rpc.common import RemoteError, LOG +from nova.utils import import_object rpc_backend_opt = \ diff --git a/nova/rpc/common.py b/nova/rpc/common.py index 70d5d07ba..696639e03 100644 --- a/nova/rpc/common.py +++ b/nova/rpc/common.py @@ -19,10 +19,10 @@ import copy -from nova.common import cfg from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg LOG = logging.getLogger('nova.rpc') diff --git a/nova/rpc/impl_qpid.py b/nova/rpc/impl_qpid.py index 353c7e502..1ed20ba81 100644 --- a/nova/rpc/impl_qpid.py +++ b/nova/rpc/impl_qpid.py @@ -25,8 +25,8 @@ import greenlet import qpid.messaging import qpid.messaging.exceptions -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg from nova.rpc import amqp as rpc_amqp from nova.rpc import common as rpc_common from nova.rpc.common import LOG diff --git a/nova/scheduler/api.py b/nova/scheduler/api.py index c814ad664..814e45c6f 100644 --- a/nova/scheduler/api.py +++ b/nova/scheduler/api.py @@ -22,11 +22,11 @@ import functools from novaclient import v1_1 as novaclient from novaclient import exceptions as novaclient_exceptions -from nova.common import cfg from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import rpc from nova import utils diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py index 5af98485d..f73eebc52 100644 --- a/nova/scheduler/driver.py +++ b/nova/scheduler/driver.py @@ -22,7 +22,6 @@ Scheduler base class that all Schedulers should inherit from """ from nova.api.ec2 import ec2utils -from nova.common import cfg from nova.compute import api as compute_api from nova.compute import power_state from nova.compute import vm_states @@ -30,6 +29,7 @@ from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import rpc from nova.scheduler import host_manager from nova.scheduler import zone_manager diff --git a/nova/scheduler/filters/core_filter.py b/nova/scheduler/filters/core_filter.py index d76eceeef..5afc63c24 100644 --- a/nova/scheduler/filters/core_filter.py +++ b/nova/scheduler/filters/core_filter.py @@ -15,9 +15,9 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.common import cfg from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova.scheduler.filters import abstract_filter diff --git a/nova/scheduler/filters/ram_filter.py b/nova/scheduler/filters/ram_filter.py index 67c9f72b8..8bae04949 100644 --- a/nova/scheduler/filters/ram_filter.py +++ b/nova/scheduler/filters/ram_filter.py @@ -14,9 +14,9 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.common import cfg from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova.scheduler.filters import abstract_filter LOG = logging.getLogger('nova.scheduler.filter.ram_filter') diff --git a/nova/scheduler/host_manager.py b/nova/scheduler/host_manager.py index a56f154fc..925a8637a 100644 --- a/nova/scheduler/host_manager.py +++ b/nova/scheduler/host_manager.py @@ -21,11 +21,11 @@ import datetime import types import UserDict -from nova.common import cfg from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils diff --git a/nova/scheduler/least_cost.py b/nova/scheduler/least_cost.py index 90ba4c2a0..4711ac4f3 100644 --- a/nova/scheduler/least_cost.py +++ b/nova/scheduler/least_cost.py @@ -22,8 +22,8 @@ The cost-function and weights are tabulated, and the host with the least cost is then selected for provisioning. """ -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg from nova import log as logging diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index dc1b2c56a..e4eb08d11 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -23,13 +23,13 @@ Scheduler Service import functools -from nova.common import cfg from nova.compute import vm_states from nova import db from nova import exception from nova import flags from nova import log as logging from nova import manager +from nova.openstack.common import cfg from nova import rpc from nova import utils diff --git a/nova/scheduler/multi.py b/nova/scheduler/multi.py index 3bc67052f..08d4bf0e6 100644 --- a/nova/scheduler/multi.py +++ b/nova/scheduler/multi.py @@ -21,8 +21,8 @@ Scheduler that allows routing some calls to one driver and others to another. """ -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg from nova import utils from nova.scheduler import driver diff --git a/nova/scheduler/scheduler_options.py b/nova/scheduler/scheduler_options.py index 0a6086fc6..63a77d08d 100644 --- a/nova/scheduler/scheduler_options.py +++ b/nova/scheduler/scheduler_options.py @@ -24,9 +24,9 @@ import datetime import json import os -from nova.common import cfg from nova import flags from nova import log as logging +from nova.openstack.common import cfg scheduler_json_config_location_opt = \ diff --git a/nova/scheduler/simple.py b/nova/scheduler/simple.py index e913730c7..94db0a475 100644 --- a/nova/scheduler/simple.py +++ b/nova/scheduler/simple.py @@ -21,10 +21,10 @@ Simple Scheduler """ -from nova.common import cfg from nova import db from nova import flags from nova import exception +from nova.openstack.common import cfg from nova.scheduler import driver from nova.scheduler import chance from nova import utils diff --git a/nova/scheduler/vsa.py b/nova/scheduler/vsa.py index 989841d37..ee50ae978 100644 --- a/nova/scheduler/vsa.py +++ b/nova/scheduler/vsa.py @@ -19,11 +19,11 @@ VSA Simple Scheduler """ -from nova.common import cfg from nova import context from nova import db from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import rpc from nova import utils from nova import exception diff --git a/nova/scheduler/zone_manager.py b/nova/scheduler/zone_manager.py index c27e6bdbe..e94039a6b 100644 --- a/nova/scheduler/zone_manager.py +++ b/nova/scheduler/zone_manager.py @@ -23,10 +23,10 @@ import traceback from eventlet import greenpool from novaclient import v1_1 as novaclient -from nova.common import cfg from nova import db from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils diff --git a/nova/service.py b/nova/service.py index 56f706c4b..fc62a3b08 100644 --- a/nova/service.py +++ b/nova/service.py @@ -25,12 +25,12 @@ import os import eventlet import greenlet -from nova.common import cfg from nova import context from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import rpc from nova import utils from nova import version diff --git a/nova/test.py b/nova/test.py index f8e9c390f..7fe4b4abb 100644 --- a/nova/test.py +++ b/nova/test.py @@ -33,10 +33,10 @@ import mox import nose.plugins.skip import stubout -from nova.common import cfg from nova import flags import nova.image.fake from nova import log +from nova.openstack.common import cfg from nova import utils from nova import service from nova.testing.fake import rabbit diff --git a/nova/tests/declare_flags.py b/nova/tests/declare_flags.py index 9dc578867..cb6726a7c 100644 --- a/nova/tests/declare_flags.py +++ b/nova/tests/declare_flags.py @@ -16,8 +16,8 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg FLAGS = flags.FLAGS FLAGS.add_option(cfg.IntOpt('answer', default=42, help='test flag')) diff --git a/nova/tests/runtime_flags.py b/nova/tests/runtime_flags.py index 1a28f4fbd..279d51162 100644 --- a/nova/tests/runtime_flags.py +++ b/nova/tests/runtime_flags.py @@ -16,8 +16,8 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg FLAGS = flags.FLAGS FLAGS.add_option(cfg.IntOpt('runtime_answer', default=54, help='test flag')) diff --git a/nova/tests/test_cfg.py b/nova/tests/test_cfg.py deleted file mode 100644 index 6d02134e1..000000000 --- a/nova/tests/test_cfg.py +++ /dev/null @@ -1,789 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 Red Hat, Inc. -# -# 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 os -import sys -import StringIO -import tempfile - -import stubout - -from nova import test -from nova.common.cfg import * - - -class BaseTestCase(test.TestCase): - - def setUp(self): - self.conf = ConfigOpts(prog='test', - version='1.0', - usage='%prog FOO BAR', - default_config_files=[]) - self.tempfiles = [] - self.stubs = stubout.StubOutForTesting() - - def tearDown(self): - self.remove_tempfiles() - self.stubs.UnsetAll() - - def create_tempfiles(self, files): - for (basename, contents) in files: - (fd, path) = tempfile.mkstemp(prefix=basename) - self.tempfiles.append(path) - try: - os.write(fd, contents) - finally: - os.close(fd) - return self.tempfiles[-len(files):] - - def remove_tempfiles(self): - for p in self.tempfiles: - os.remove(p) - - -class LeftoversTestCase(BaseTestCase): - - def test_leftovers(self): - self.conf.register_cli_opt(StrOpt('foo')) - self.conf.register_cli_opt(StrOpt('bar')) - - leftovers = self.conf(['those', '--foo', 'this', - 'thems', '--bar', 'that', 'these']) - - self.assertEquals(leftovers, ['those', 'thems', 'these']) - - -class FindConfigFilesTestCase(BaseTestCase): - - def test_find_config_files(self): - config_files = \ - [os.path.expanduser('~/.blaa/blaa.conf'), '/etc/foo.conf'] - - self.stubs.Set(os.path, 'exists', lambda p: p in config_files) - - self.assertEquals(find_config_files(project='blaa', prog='foo'), - config_files) - - -class CliOptsTestCase(BaseTestCase): - - def _do_cli_test(self, opt_class, default, cli_args, value): - self.conf.register_cli_opt(opt_class('foo', default=default)) - - self.conf(cli_args) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, value) - - def test_str_default(self): - self._do_cli_test(StrOpt, None, [], None) - - def test_str_arg(self): - self._do_cli_test(StrOpt, None, ['--foo', 'bar'], 'bar') - - def test_bool_default(self): - self._do_cli_test(BoolOpt, False, [], False) - - def test_bool_arg(self): - self._do_cli_test(BoolOpt, None, ['--foo'], True) - - def test_bool_arg_inverse(self): - self._do_cli_test(BoolOpt, None, ['--foo', '--nofoo'], False) - - def test_int_default(self): - self._do_cli_test(IntOpt, 10, [], 10) - - def test_int_arg(self): - self._do_cli_test(IntOpt, None, ['--foo=20'], 20) - - def test_float_default(self): - self._do_cli_test(FloatOpt, 1.0, [], 1.0) - - def test_float_arg(self): - self._do_cli_test(FloatOpt, None, ['--foo', '2.0'], 2.0) - - def test_list_default(self): - self._do_cli_test(ListOpt, ['bar'], [], ['bar']) - - def test_list_arg(self): - self._do_cli_test(ListOpt, None, - ['--foo', 'blaa,bar'], ['blaa', 'bar']) - - def test_multistr_default(self): - self._do_cli_test(MultiStrOpt, ['bar'], [], ['bar']) - - def test_multistr_arg(self): - self._do_cli_test(MultiStrOpt, None, - ['--foo', 'blaa', '--foo', 'bar'], ['blaa', 'bar']) - - def test_help(self): - self.stubs.Set(sys, 'stdout', StringIO.StringIO()) - self.assertRaises(SystemExit, self.conf, ['--help']) - self.assertTrue('FOO BAR' in sys.stdout.getvalue()) - self.assertTrue('--version' in sys.stdout.getvalue()) - self.assertTrue('--help' in sys.stdout.getvalue()) - self.assertTrue('--config-file=PATH' in sys.stdout.getvalue()) - - def test_version(self): - self.stubs.Set(sys, 'stdout', StringIO.StringIO()) - self.assertRaises(SystemExit, self.conf, ['--version']) - self.assertTrue('1.0' in sys.stdout.getvalue()) - - def test_config_file(self): - paths = self.create_tempfiles([('1.conf', '[DEFAULT]'), - ('2.conf', '[DEFAULT]')]) - - self.conf(['--config-file', paths[0], '--config-file', paths[1]]) - - self.assertEquals(self.conf.config_file, paths) - - -class ConfigFileOptsTestCase(BaseTestCase): - - def test_conf_file_str_default(self): - self.conf.register_opt(StrOpt('foo', default='bar')) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, 'bar') - - def test_conf_file_str_value(self): - self.conf.register_opt(StrOpt('foo')) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, 'bar') - - def test_conf_file_str_value_override(self): - self.conf.register_cli_opt(StrOpt('foo')) - - paths = self.create_tempfiles([('1.conf', - '[DEFAULT]\n' - 'foo = baar\n'), - ('2.conf', - '[DEFAULT]\n' - 'foo = baaar\n')]) - - self.conf(['--foo', 'bar', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, 'baaar') - - def test_conf_file_int_default(self): - self.conf.register_opt(IntOpt('foo', default=666)) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, 666) - - def test_conf_file_int_value(self): - self.conf.register_opt(IntOpt('foo')) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'foo = 666\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, 666) - - def test_conf_file_int_value_override(self): - self.conf.register_cli_opt(IntOpt('foo')) - - paths = self.create_tempfiles([('1.conf', - '[DEFAULT]\n' - 'foo = 66\n'), - ('2.conf', - '[DEFAULT]\n' - 'foo = 666\n')]) - - self.conf(['--foo', '6', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, 666) - - def test_conf_file_float_default(self): - self.conf.register_opt(FloatOpt('foo', default=6.66)) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, 6.66) - - def test_conf_file_float_value(self): - self.conf.register_opt(FloatOpt('foo')) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'foo = 6.66\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, 6.66) - - def test_conf_file_float_value_override(self): - self.conf.register_cli_opt(FloatOpt('foo')) - - paths = self.create_tempfiles([('1.conf', - '[DEFAULT]\n' - 'foo = 6.6\n'), - ('2.conf', - '[DEFAULT]\n' - 'foo = 6.66\n')]) - - self.conf(['--foo', '6', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, 6.66) - - def test_conf_file_list_default(self): - self.conf.register_opt(ListOpt('foo', default=['bar'])) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, ['bar']) - - def test_conf_file_list_value(self): - self.conf.register_opt(ListOpt('foo')) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, ['bar']) - - def test_conf_file_list_value_override(self): - self.conf.register_cli_opt(ListOpt('foo')) - - paths = self.create_tempfiles([('1.conf', - '[DEFAULT]\n' - 'foo = bar,bar\n'), - ('2.conf', - '[DEFAULT]\n' - 'foo = b,a,r\n')]) - - self.conf(['--foo', 'bar', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, ['b', 'a', 'r']) - - def test_conf_file_multistr_default(self): - self.conf.register_opt(MultiStrOpt('foo', default=['bar'])) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, ['bar']) - - def test_conf_file_multistr_value(self): - self.conf.register_opt(MultiStrOpt('foo')) - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, ['bar']) - - def test_conf_file_multistr_values_append(self): - self.conf.register_cli_opt(ListOpt('foo')) - - paths = self.create_tempfiles([('1.conf', - '[DEFAULT]\n' - 'foo = bar\n'), - ('2.conf', - '[DEFAULT]\n' - 'foo = bar\n')]) - - self.conf(['--foo', 'bar', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - - # FIXME(markmc): values spread across the CLI and multiple - # config files should be appended - # self.assertEquals(self.conf.foo, ['bar', 'bar', 'bar']) - - -class OptGroupsTestCase(BaseTestCase): - - def test_arg_group(self): - blaa_group = OptGroup('blaa') - self.conf.register_group(blaa_group) - self.conf.register_cli_opt(StrOpt('foo'), group=blaa_group) - - self.conf(['--blaa-foo', 'bar']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEquals(self.conf.blaa.foo, 'bar') - - def test_arg_group_by_name(self): - self.conf.register_group(OptGroup('blaa')) - self.conf.register_cli_opt(StrOpt('foo'), group='blaa') - - self.conf(['--blaa-foo', 'bar']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEquals(self.conf.blaa.foo, 'bar') - - def test_arg_group_with_default(self): - self.conf.register_group(OptGroup('blaa')) - self.conf.register_cli_opt(StrOpt('foo', default='bar'), group='blaa') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEquals(self.conf.blaa.foo, 'bar') - - def test_arg_group_in_config_file(self): - self.conf.register_group(OptGroup('blaa')) - self.conf.register_opt(StrOpt('foo'), group='blaa') - - paths = self.create_tempfiles([('test.conf', - '[blaa]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEquals(self.conf.blaa.foo, 'bar') - - -class TemplateSubstitutionTestCase(BaseTestCase): - - def _prep_test_str_sub(self, foo_default=None, bar_default=None): - self.conf.register_cli_opt(StrOpt('foo', default=foo_default)) - self.conf.register_cli_opt(StrOpt('bar', default=bar_default)) - - def _assert_str_sub(self): - self.assertTrue(hasattr(self.conf, 'bar')) - self.assertEquals(self.conf.bar, 'blaa') - - def test_str_sub_default_from_default(self): - self._prep_test_str_sub(foo_default='blaa', bar_default='$foo') - - self.conf([]) - - self._assert_str_sub() - - def test_str_sub_default_from_arg(self): - self._prep_test_str_sub(bar_default='$foo') - - self.conf(['--foo', 'blaa']) - - self._assert_str_sub() - - def test_str_sub_default_from_config_file(self): - self._prep_test_str_sub(bar_default='$foo') - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'foo = blaa\n')]) - - self.conf(['--config-file', paths[0]]) - - self._assert_str_sub() - - def test_str_sub_arg_from_default(self): - self._prep_test_str_sub(foo_default='blaa') - - self.conf(['--bar', '$foo']) - - self._assert_str_sub() - - def test_str_sub_arg_from_arg(self): - self._prep_test_str_sub() - - self.conf(['--foo', 'blaa', '--bar', '$foo']) - - self._assert_str_sub() - - def test_str_sub_arg_from_config_file(self): - self._prep_test_str_sub() - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'foo = blaa\n')]) - - self.conf(['--config-file', paths[0], '--bar=$foo']) - - self._assert_str_sub() - - def test_str_sub_config_file_from_default(self): - self._prep_test_str_sub(foo_default='blaa') - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'bar = $foo\n')]) - - self.conf(['--config-file', paths[0]]) - - self._assert_str_sub() - - def test_str_sub_config_file_from_arg(self): - self._prep_test_str_sub() - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'bar = $foo\n')]) - - self.conf(['--config-file', paths[0], '--foo=blaa']) - - self._assert_str_sub() - - def test_str_sub_config_file_from_config_file(self): - self._prep_test_str_sub() - - paths = self.create_tempfiles([('test.conf', - '[DEFAULT]\n' - 'bar = $foo\n' - 'foo = blaa\n')]) - - self.conf(['--config-file', paths[0]]) - - self._assert_str_sub() - - def test_str_sub_group_from_default(self): - self.conf.register_cli_opt(StrOpt('foo', default='blaa')) - self.conf.register_group(OptGroup('ba')) - self.conf.register_cli_opt(StrOpt('r', default='$foo'), group='ba') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'ba')) - self.assertTrue(hasattr(self.conf.ba, 'r')) - self.assertEquals(self.conf.ba.r, 'blaa') - - -class ReparseTestCase(BaseTestCase): - - def test_reparse(self): - self.conf.register_group(OptGroup('blaa')) - self.conf.register_cli_opt(StrOpt('foo', default='r'), group='blaa') - - paths = self.create_tempfiles([('test.conf', - '[blaa]\n' - 'foo = b\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEquals(self.conf.blaa.foo, 'b') - - self.conf(['--blaa-foo', 'a']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEquals(self.conf.blaa.foo, 'a') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEquals(self.conf.blaa.foo, 'r') - - -class OverridesTestCase(BaseTestCase): - - def test_no_default_override(self): - self.conf.register_opt(StrOpt('foo')) - self.conf([]) - self.assertEquals(self.conf.foo, None) - self.conf.set_default('foo', 'bar') - self.assertEquals(self.conf.foo, 'bar') - - def test_default_override(self): - self.conf.register_opt(StrOpt('foo', default='foo')) - self.conf([]) - self.assertEquals(self.conf.foo, 'foo') - self.conf.set_default('foo', 'bar') - self.assertEquals(self.conf.foo, 'bar') - self.conf.set_default('foo', None) - self.assertEquals(self.conf.foo, 'foo') - - def test_override(self): - self.conf.register_opt(StrOpt('foo')) - self.conf.set_override('foo', 'bar') - self.conf([]) - self.assertEquals(self.conf.foo, 'bar') - - def test_group_no_default_override(self): - self.conf.register_group(OptGroup('blaa')) - self.conf.register_opt(StrOpt('foo'), group='blaa') - self.conf([]) - self.assertEquals(self.conf.blaa.foo, None) - self.conf.set_default('foo', 'bar', group='blaa') - self.assertEquals(self.conf.blaa.foo, 'bar') - - def test_group_default_override(self): - self.conf.register_group(OptGroup('blaa')) - self.conf.register_opt(StrOpt('foo', default='foo'), group='blaa') - self.conf([]) - self.assertEquals(self.conf.blaa.foo, 'foo') - self.conf.set_default('foo', 'bar', group='blaa') - self.assertEquals(self.conf.blaa.foo, 'bar') - self.conf.set_default('foo', None, group='blaa') - self.assertEquals(self.conf.blaa.foo, 'foo') - - def test_group_override(self): - self.conf.register_group(OptGroup('blaa')) - self.conf.register_opt(StrOpt('foo'), group='blaa') - self.conf.set_override('foo', 'bar', group='blaa') - self.conf([]) - self.assertEquals(self.conf.blaa.foo, 'bar') - - -class SadPathTestCase(BaseTestCase): - - def test_unknown_attr(self): - self.conf([]) - self.assertFalse(hasattr(self.conf, 'foo')) - self.assertRaises(NoSuchOptError, getattr, self.conf, 'foo') - - def test_unknown_attr_is_attr_error(self): - self.conf([]) - self.assertFalse(hasattr(self.conf, 'foo')) - self.assertRaises(AttributeError, getattr, self.conf, 'foo') - - def test_unknown_group_attr(self): - self.conf.register_group(OptGroup('blaa')) - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertFalse(hasattr(self.conf.blaa, 'foo')) - self.assertRaises(NoSuchOptError, getattr, self.conf.blaa, 'foo') - - def test_ok_duplicate(self): - opt = StrOpt('foo') - self.conf.register_cli_opt(opt) - self.conf.register_cli_opt(opt) - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEquals(self.conf.foo, None) - - def test_error_duplicate(self): - self.conf.register_cli_opt(StrOpt('foo')) - self.assertRaises(DuplicateOptError, - self.conf.register_cli_opt, StrOpt('foo')) - - def test_error_duplicate_with_different_dest(self): - self.conf.register_cli_opt(StrOpt('foo', dest='f')) - self.assertRaises(DuplicateOptError, - self.conf.register_cli_opt, StrOpt('foo')) - - def test_error_duplicate_short(self): - self.conf.register_cli_opt(StrOpt('foo', short='f')) - self.assertRaises(DuplicateOptError, - self.conf.register_cli_opt, StrOpt('bar', short='f')) - - def test_no_such_group(self): - self.assertRaises(NoSuchGroupError, self.conf.register_cli_opt, - StrOpt('foo'), group='blaa') - - def test_already_parsed(self): - self.conf([]) - - self.assertRaises(ArgsAlreadyParsedError, - self.conf.register_cli_opt, StrOpt('foo')) - - def test_bad_cli_arg(self): - self.stubs.Set(sys, 'stderr', StringIO.StringIO()) - - self.assertRaises(SystemExit, self.conf, ['--foo']) - - self.assertTrue('error' in sys.stderr.getvalue()) - self.assertTrue('--foo' in sys.stderr.getvalue()) - - def _do_test_bad_cli_value(self, opt_class): - self.conf.register_cli_opt(opt_class('foo')) - - self.stubs.Set(sys, 'stderr', StringIO.StringIO()) - - self.assertRaises(SystemExit, self.conf, ['--foo', 'bar']) - - self.assertTrue('foo' in sys.stderr.getvalue()) - self.assertTrue('bar' in sys.stderr.getvalue()) - - def test_bad_int_arg(self): - self._do_test_bad_cli_value(IntOpt) - - def test_bad_float_arg(self): - self._do_test_bad_cli_value(FloatOpt) - - def test_conf_file_not_found(self): - paths = self.create_tempfiles([('test.conf', '')]) - os.remove(paths[0]) - self.tempfiles.remove(paths[0]) - - self.assertRaises(ConfigFilesNotFoundError, - self.conf, ['--config-file', paths[0]]) - - def test_conf_file_broken(self): - paths = self.create_tempfiles([('test.conf', 'foo')]) - - self.assertRaises(ConfigFileParseError, - self.conf, ['--config-file', paths[0]]) - - def _do_test_conf_file_bad_value(self, opt_class): - self.conf.register_opt(opt_class('foo')) - - def test_conf_file_bad_bool(self): - self._do_test_conf_file_bad_value(BoolOpt) - - def test_conf_file_bad_int(self): - self._do_test_conf_file_bad_value(IntOpt) - - def test_conf_file_bad_float(self): - self._do_test_conf_file_bad_value(FloatOpt) - - def test_str_sub_from_group(self): - self.conf.register_group(OptGroup('f')) - self.conf.register_cli_opt(StrOpt('oo', default='blaa'), group='f') - self.conf.register_cli_opt(StrOpt('bar', default='$f.oo')) - - self.conf([]) - - self.assertFalse(hasattr(self.conf, 'bar')) - self.assertRaises(TemplateSubstitutionError, getattr, self.conf, 'bar') - - def test_set_default_unknown_attr(self): - self.conf([]) - self.assertRaises(NoSuchOptError, self.conf.set_default, 'foo', 'bar') - - def test_set_default_unknown_group(self): - self.conf([]) - self.assertRaises(NoSuchGroupError, - self.conf.set_default, 'foo', 'bar', group='blaa') - - def test_set_override_unknown_attr(self): - self.conf([]) - self.assertRaises(NoSuchOptError, self.conf.set_override, 'foo', 'bar') - - def test_set_override_unknown_group(self): - self.conf([]) - self.assertRaises(NoSuchGroupError, - self.conf.set_override, 'foo', 'bar', group='blaa') - - -class OptDumpingTestCase(BaseTestCase): - - class FakeLogger: - - def __init__(self, test_case, expected_lvl): - self.test_case = test_case - self.expected_lvl = expected_lvl - self.logged = [] - - def log(self, lvl, fmt, *args): - self.test_case.assertEquals(lvl, self.expected_lvl) - self.logged.append(fmt % args) - - def test_log_opt_values(self): - self.conf.register_cli_opt(StrOpt('foo')) - self.conf.register_group(OptGroup('blaa')) - self.conf.register_cli_opt(StrOpt('bar'), 'blaa') - - self.conf(['--foo', 'this', '--blaa-bar', 'that']) - - logger = self.FakeLogger(self, 666) - - self.conf.log_opt_values(logger, 666) - - self.assertEquals(logger.logged, [ - "*" * 80, - "Configuration options gathered from:", - "command line args: ['--foo', 'this', '--blaa-bar', 'that']", - "config files: []", - "=" * 80, - "config_file = []", - "foo = this", - "blaa.bar = that", - "*" * 80, - ]) - - -class CommonOptsTestCase(BaseTestCase): - - def setUp(self): - super(CommonOptsTestCase, self).setUp() - self.conf = CommonConfigOpts() - - def test_debug_verbose(self): - self.conf(['--debug', '--verbose']) - - self.assertEquals(self.conf.debug, True) - self.assertEquals(self.conf.verbose, True) - - def test_logging_opts(self): - self.conf([]) - - self.assertTrue(self.conf.log_config is None) - self.assertTrue(self.conf.log_file is None) - self.assertTrue(self.conf.log_dir is None) - - self.assertEquals(self.conf.log_format, - CommonConfigOpts.DEFAULT_LOG_FORMAT) - self.assertEquals(self.conf.log_date_format, - CommonConfigOpts.DEFAULT_LOG_DATE_FORMAT) - - self.assertEquals(self.conf.use_syslog, False) diff --git a/nova/tests/test_flags.py b/nova/tests/test_flags.py index 02ee49ef0..bea34007a 100644 --- a/nova/tests/test_flags.py +++ b/nova/tests/test_flags.py @@ -21,8 +21,8 @@ import exceptions import os import tempfile -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg from nova import test FLAGS = flags.FLAGS diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index c8a18f7d8..edede55b3 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -22,11 +22,11 @@ Unit Tests for remote procedure calls using queue import mox -from nova.common import cfg from nova import context from nova import db from nova import exception from nova import flags +from nova.openstack.common import cfg from nova import test from nova import service from nova import manager diff --git a/nova/utils.py b/nova/utils.py index f86b4ff1f..72e1cd3e0 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -46,10 +46,10 @@ from eventlet import semaphore from eventlet.green import subprocess import netaddr -from nova.common import cfg from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg LOG = logging.getLogger("nova.utils") diff --git a/nova/virt/disk/api.py b/nova/virt/disk/api.py index 223f08a2f..929e17a55 100644 --- a/nova/virt/disk/api.py +++ b/nova/virt/disk/api.py @@ -29,10 +29,10 @@ import json import os import tempfile -from nova.common import cfg from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.virt.disk import guestfs from nova.virt.disk import loop diff --git a/nova/virt/disk/nbd.py b/nova/virt/disk/nbd.py index 19904d694..d43fd3250 100644 --- a/nova/virt/disk/nbd.py +++ b/nova/virt/disk/nbd.py @@ -18,8 +18,8 @@ import os import time -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg from nova import utils from nova.virt.disk import mount diff --git a/nova/virt/firewall.py b/nova/virt/firewall.py index 2af28d7f1..48b02e545 100644 --- a/nova/virt/firewall.py +++ b/nova/virt/firewall.py @@ -17,11 +17,11 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.common import cfg from nova import context from nova import db from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.virt import netutils diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 6c3e64692..45af96a0a 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -54,7 +54,6 @@ from xml.etree import ElementTree from nova.auth import manager from nova import block_device -from nova.common import cfg from nova.compute import instance_types from nova.compute import power_state from nova import context as nova_context @@ -63,6 +62,7 @@ from nova import exception from nova import flags import nova.image from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.virt.disk import api as disk from nova.virt import driver diff --git a/nova/virt/libvirt/imagecache.py b/nova/virt/libvirt/imagecache.py index a70842a3b..00c22ab49 100644 --- a/nova/virt/libvirt/imagecache.py +++ b/nova/virt/libvirt/imagecache.py @@ -29,13 +29,13 @@ import os import sys import time -from nova.common import cfg from nova import compute from nova import context as db_context from nova import db from nova import flags from nova import image from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.virt.libvirt import utils as virtutils diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py index 65254936a..4409e6aa6 100644 --- a/nova/virt/libvirt/utils.py +++ b/nova/virt/libvirt/utils.py @@ -23,9 +23,9 @@ import os import random import shutil -from nova.common import cfg from nova import exception from nova import flags +from nova.openstack.common import cfg from nova import utils from nova.virt.disk import api as disk from nova.virt import images diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 503c33d0f..54bc742f8 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -19,11 +19,11 @@ """VIF drivers for libvirt.""" -from nova.common import cfg from nova import exception from nova import flags from nova import log as logging from nova.network import linux_net +from nova.openstack.common import cfg from nova import utils from nova.virt import netutils from nova.virt.vif import VIFDriver diff --git a/nova/virt/vmwareapi/vim.py b/nova/virt/vmwareapi/vim.py index 0ce1be645..648231087 100644 --- a/nova/virt/vmwareapi/vim.py +++ b/nova/virt/vmwareapi/vim.py @@ -26,8 +26,8 @@ try: except ImportError: suds = None -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg from nova.virt.vmwareapi import error_util RESP_NOT_XML_ERROR = 'Response is "text/html", not "text/xml"' diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index 172936def..af867dc6a 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -26,11 +26,11 @@ import urllib import urllib2 import uuid -from nova.common import cfg from nova.compute import power_state from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.virt.vmwareapi import vim_util from nova.virt.vmwareapi import vm_util diff --git a/nova/virt/vmwareapi_conn.py b/nova/virt/vmwareapi_conn.py index d71b922c9..c63f1e9d5 100644 --- a/nova/virt/vmwareapi_conn.py +++ b/nova/virt/vmwareapi_conn.py @@ -36,12 +36,12 @@ import time from eventlet import event -from nova.common import cfg from nova import context from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.virt import driver from nova.virt.vmwareapi import error_util diff --git a/nova/virt/xenapi/vif.py b/nova/virt/xenapi/vif.py index c1b752d5a..e4a5ea973 100644 --- a/nova/virt/xenapi/vif.py +++ b/nova/virt/xenapi/vif.py @@ -19,9 +19,9 @@ """VIF drivers for XenAPI.""" -from nova.common import cfg from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova.virt.vif import VIFDriver from nova.virt.xenapi.network_utils import NetworkHelper from nova.virt.xenapi.vm_utils import VMHelper diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 9ddf8b22a..169bb2b61 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -33,11 +33,11 @@ import uuid from decimal import Decimal, InvalidOperation from xml.dom import minidom -from nova.common import cfg from nova import exception from nova import flags from nova.image import glance from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.compute import instance_types from nova.compute import power_state diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index c7f713ea2..339986519 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -31,7 +31,6 @@ import uuid from eventlet import greenthread -from nova.common import cfg from nova.compute import api as compute from nova.compute import power_state from nova import context as nova_context @@ -39,6 +38,7 @@ from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.virt import driver from nova.virt.xenapi import volume_utils diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 6fda205d0..236bd4762 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -70,13 +70,13 @@ from eventlet import queue from eventlet import tpool from eventlet import timeout -from nova.common import cfg from nova import context from nova import db from nova import exception from nova import utils from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova.virt import driver from nova.virt.xenapi import vm_utils from nova.virt.xenapi.vmops import VMOps diff --git a/nova/vnc/__init__.py b/nova/vnc/__init__.py index 0b2581203..ba7268e97 100644 --- a/nova/vnc/__init__.py +++ b/nova/vnc/__init__.py @@ -18,8 +18,8 @@ """Module for VNC Proxying.""" -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg vnc_opts = [ diff --git a/nova/vnc/xvp_proxy.py b/nova/vnc/xvp_proxy.py index bf9ee5975..dfaf9a47a 100644 --- a/nova/vnc/xvp_proxy.py +++ b/nova/vnc/xvp_proxy.py @@ -26,10 +26,10 @@ import eventlet.green import eventlet.greenio import eventlet.wsgi -from nova.common import cfg from nova import context from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import rpc from nova import version from nova import wsgi diff --git a/nova/volume/driver.py b/nova/volume/driver.py index 0505b89b1..fa2893737 100644 --- a/nova/volume/driver.py +++ b/nova/volume/driver.py @@ -24,10 +24,10 @@ import os import time from xml.etree import ElementTree -from nova.common import cfg from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.volume import iscsi from nova.volume import volume_types diff --git a/nova/volume/iscsi.py b/nova/volume/iscsi.py index 66c293f15..f0934eb96 100644 --- a/nova/volume/iscsi.py +++ b/nova/volume/iscsi.py @@ -20,8 +20,8 @@ Helper code for the iSCSI volume driver. """ -from nova.common import cfg from nova import flags +from nova.openstack.common import cfg from nova import utils diff --git a/nova/volume/manager.py b/nova/volume/manager.py index f22fcc2ca..7e739031b 100644 --- a/nova/volume/manager.py +++ b/nova/volume/manager.py @@ -38,12 +38,12 @@ intact. """ -from nova.common import cfg from nova import context from nova import exception from nova import flags from nova import log as logging from nova import manager +from nova.openstack.common import cfg from nova import rpc from nova import utils from nova.volume import volume_types diff --git a/nova/volume/san.py b/nova/volume/san.py index 25309768e..bc06d7e03 100644 --- a/nova/volume/san.py +++ b/nova/volume/san.py @@ -32,11 +32,10 @@ import string import uuid from xml.etree import ElementTree -from nova.common import cfg - from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import utils from nova.utils import ssh_execute from nova.volume.driver import ISCSIDriver diff --git a/nova/vsa/api.py b/nova/vsa/api.py index 9c2bc0ce2..08b9deb13 100644 --- a/nova/vsa/api.py +++ b/nova/vsa/api.py @@ -25,11 +25,11 @@ For assistance and guidelines pls contact import sys -from nova.common import cfg from nova import compute from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import cfg from nova import rpc from nova import volume from nova.compute import instance_types diff --git a/nova/vsa/manager.py b/nova/vsa/manager.py index 42b5b1032..4dab8e31f 100644 --- a/nova/vsa/manager.py +++ b/nova/vsa/manager.py @@ -22,12 +22,12 @@ Handles all processes relating to Virtual Storage Arrays (VSA). """ -from nova.common import cfg from nova import compute from nova import exception from nova import flags from nova import log as logging from nova import manager +from nova.openstack.common import cfg from nova import volume from nova import vsa from nova import utils -- cgit