diff options
-rw-r--r-- | HACKING.rst | 15 | ||||
-rw-r--r-- | nova/flags.py | 10 | ||||
-rw-r--r-- | nova/openstack/common/README | 13 | ||||
-rw-r--r-- | nova/openstack/common/cfg.py | 112 | ||||
-rw-r--r-- | nova/virt/libvirt/connection.py | 27 | ||||
-rw-r--r-- | openstack-common.conf | 7 |
6 files changed, 148 insertions, 36 deletions
diff --git a/HACKING.rst b/HACKING.rst index 975498a01..b7e2564d6 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -179,3 +179,18 @@ without the patch and passes with the patch. For more information on creating unit tests and utilizing the testing infrastructure in OpenStack Nova, please read nova/testing/README.rst. + + +openstack-common +---------------- + +A number of modules from openstack-common are imported into the project. + +These modules are "incubating" in openstack-common and are kept in sync +with the help of openstack-common's update.py script. See: + + http://wiki.openstack.org/CommonLibrary#Incubation + +The copy of the code should never be directly modified here. Please +always update openstack-common first and then run the script to copy +the changes across. diff --git a/nova/flags.py b/nova/flags.py index 3f3560057..476255afd 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -69,7 +69,7 @@ class FlagValues(object): def __init__(self): self._conf = cfg.ConfigOpts() - self._conf._oparser.disable_interspersed_args() + self._conf.disable_interspersed_args() self._opts = {} self.Reset() @@ -128,7 +128,7 @@ class FlagValues(object): self._conf.set_default(name, default) def __iter__(self): - return self.FlagValuesDict().iterkeys() + return self._conf.iterkeys() def __getitem__(self, name): self._parse() @@ -147,12 +147,12 @@ class FlagValues(object): def FlagValuesDict(self): self._parse() ret = {} - for opt in self._opts.values(): - ret[opt.dest] = getattr(self, opt.dest) + for name in self._conf: + ret[name] = getattr(self, name) return ret def add_option(self, opt): - if opt.dest in self._opts: + if opt.dest in self._conf: return self._opts[opt.dest] = opt diff --git a/nova/openstack/common/README b/nova/openstack/common/README new file mode 100644 index 000000000..def4a172a --- /dev/null +++ b/nova/openstack/common/README @@ -0,0 +1,13 @@ +openstack-common +---------------- + +A number of modules from openstack-common are imported into this project. + +These modules are "incubating" in openstack-common and are kept in sync +with the help of openstack-common's update.py script. See: + + http://wiki.openstack.org/CommonLibrary#Incubation + +The copy of the code should never be directly modified here. Please +always update openstack-common first and then run the script to copy +the changes across. diff --git a/nova/openstack/common/cfg.py b/nova/openstack/common/cfg.py index bfb7b8a19..2562af416 100644 --- a/nova/openstack/common/cfg.py +++ b/nova/openstack/common/cfg.py @@ -134,24 +134,18 @@ Options can be registered as belonging to a group: 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) + # options can be registered under a group in either of these ways: + conf.register_opt(rabbit_host_opt, group=rabbit_group) 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: @@ -171,7 +165,7 @@ files: Command-line options in a group are automatically prefixed with the group name: - --rabbit-host localhost --rabbit-use-ssl False + --rabbit-host localhost --rabbit-port 9999 Option values in the default group are referenced as attributes/properties on the config manager; groups are also attributes on the config manager, with @@ -199,14 +193,31 @@ Option values may reference other values using PEP 292 string substitution: ] Note that interpolation can be avoided by using '$$'. + +For command line utilities that dispatch to other command line utilities, the +disable_interspersed_args() method is available. If this this method is called, +then parsing e.g. + + script --verbose cmd --debug /tmp/mything + +will no longer return: + + ['cmd', '/tmp/mything'] + +as the leftover arguments, but will instead return: + + ['cmd', '--debug', '/tmp/mything'] + +i.e. argument parsing is stopped at the first non-option argument. """ -import sys +import collections import ConfigParser import copy import optparse import os import string +import sys class Error(Exception): @@ -540,6 +551,7 @@ class BoolOpt(Opt): container = self._get_optparse_container(parser, group) kwargs = self._get_optparse_kwargs(group, action='store_false') prefix = self._get_optparse_prefix('no', group) + kwargs["help"] = "The inverse of --" + self.name self._add_to_optparse(container, self.name, None, kwargs, prefix) def _get_optparse_kwargs(self, group, action='store_true', **kwargs): @@ -681,7 +693,7 @@ class OptGroup(object): return self._optparse_group -class ConfigOpts(object): +class ConfigOpts(collections.Mapping, object): """ Config options which may be set on the command line or in config files. @@ -776,6 +788,23 @@ class ConfigOpts(object): """ return self._substitute(self._get(name)) + def __getitem__(self, key): + """Look up an option value and perform string substitution.""" + return self.__getattr__(key) + + def __contains__(self, key): + """Return True if key is the name of a registered opt or group.""" + return key in self._opts or key in self._groups + + def __iter__(self): + """Iterate over all registered opt and group names.""" + for key in self._opts.keys() + self._groups.keys(): + yield key + + def __len__(self): + """Return the number of options and option groups.""" + return len(self._opts) + len(self._groups) + def reset(self): """Reset the state of the object to before it was called.""" self._args = None @@ -880,6 +909,31 @@ class ConfigOpts(object): opt_info = self._get_opt_info(name, group) opt_info['default'] = default + def disable_interspersed_args(self): + """Set parsing to stop on the first non-option. + + If this this method is called, then parsing e.g. + + script --verbose cmd --debug /tmp/mything + + will no longer return: + + ['cmd', '/tmp/mything'] + + as the leftover arguments, but will instead return: + + ['cmd', '--debug', '/tmp/mything'] + + i.e. argument parsing is stopped at the first non-option argument. + """ + self._oparser.disable_interspersed_args() + + def enable_interspersed_args(self): + """Set parsing to not stop on the first non-option. + + This it the default behaviour.""" + self._oparser.enable_interspersed_args() + def log_opt_values(self, logger, lvl): """Log the value of all registered opts. @@ -900,7 +954,7 @@ class ConfigOpts(object): logger.log(lvl, "%-30s = %s", opt_name, getattr(self, opt_name)) for group_name in self._groups: - group_attr = self.GroupAttr(self, group_name) + group_attr = self.GroupAttr(self, self._get_group(group_name)) for opt_name in sorted(self._groups[group_name]._opts): logger.log(lvl, "%-30s = %s", "%s.%s" % (group_name, opt_name), @@ -916,16 +970,13 @@ class ConfigOpts(object): """Look up an option value. :param name: the opt name (or 'dest', more precisely) - :param group: an option OptGroup + :param group: an 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) + return self.GroupAttr(self, self._get_group(name)) info = self._get_opt_info(name, group) default, opt, override = map(lambda k: info[k], sorted(info.keys())) @@ -1027,17 +1078,18 @@ class ConfigOpts(object): not_read_ok = filter(lambda f: f not in read_ok, config_files) raise ConfigFilesNotFoundError(not_read_ok) - class GroupAttr(object): + class GroupAttr(collections.Mapping, object): """ - A helper class representing the option values of a group as attributes. + A helper class representing the option values of a group as a mapping + and attributes. """ def __init__(self, conf, group): """Construct a GroupAttr object. :param conf: a ConfigOpts object - :param group: a group name or OptGroup object + :param group: an OptGroup object """ self.conf = conf self.group = group @@ -1046,6 +1098,23 @@ class ConfigOpts(object): """Look up an option value and perform template substitution.""" return self.conf._substitute(self.conf._get(name, self.group)) + def __getitem__(self, key): + """Look up an option value and perform string substitution.""" + return self.__getattr__(key) + + def __contains__(self, key): + """Return True if key is the name of a registered opt or group.""" + return key in self.group._opts + + def __iter__(self): + """Iterate over all registered opt and group names.""" + for key in self.group._opts.keys(): + yield key + + def __len__(self): + """Return the number of options and option groups.""" + return len(self.group._opts) + class StrSubWrapper(object): """ @@ -1118,6 +1187,9 @@ class CommonConfigOpts(ConfigOpts): BoolOpt('use-syslog', default=False, help='Use syslog for logging.'), + StrOpt('syslog-log-facility', + default='LOG_USER', + help='syslog facility to receive log lines') ] def __init__(self, **kwargs): diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 37ad07736..5400a4fbd 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -210,8 +210,8 @@ class LibvirtConnection(driver.ComputeDriver): else: self._disk_prefix = disk_prefix_map.get(FLAGS.libvirt_type, 'vd') self.default_root_device = self._disk_prefix + 'a' - self.default_ephemeral_device = self._disk_prefix + 'b' - self.default_swap_device = self._disk_prefix + 'c' + self.default_second_device = self._disk_prefix + 'b' + self.default_third_device = self._disk_prefix + 'c' self.image_cache_manager = imagecache.ImageCacheManager() @@ -988,7 +988,8 @@ class LibvirtConnection(driver.ComputeDriver): ephemeral_gb = instance['ephemeral_gb'] if ephemeral_gb and not self._volume_in_mapping( - self.default_ephemeral_device, block_device_info): + self.default_second_device, block_device_info): + swap_device = self.default_third_device fn = functools.partial(self._create_ephemeral, fs_label='ephemeral0', os_type=instance.os_type) @@ -998,6 +999,8 @@ class LibvirtConnection(driver.ComputeDriver): ("0", ephemeral_gb, instance.os_type), cow=FLAGS.use_cow_images, ephemeral_size=ephemeral_gb) + else: + swap_device = self.default_second_device for eph in driver.block_device_info_get_ephemerals(block_device_info): fn = functools.partial(self._create_ephemeral, @@ -1016,8 +1019,7 @@ class LibvirtConnection(driver.ComputeDriver): if driver.swap_is_usable(swap): swap_mb = swap['swap_size'] elif (inst_type['swap'] > 0 and - not self._volume_in_mapping(self.default_swap_device, - block_device_info)): + not self._volume_in_mapping(swap_device, block_device_info)): swap_mb = inst_type['swap'] if swap_mb > 0: @@ -1187,13 +1189,13 @@ class LibvirtConnection(driver.ComputeDriver): block_device_info) ephemeral_device = False - if not (self._volume_in_mapping(self.default_ephemeral_device, + if not (self._volume_in_mapping(self.default_second_device, block_device_info) or 0 in [eph['num'] for eph in driver.block_device_info_get_ephemerals( block_device_info)]): if instance['ephemeral_gb'] > 0: - ephemeral_device = self.default_ephemeral_device + ephemeral_device = self.default_second_device ephemerals = [] for eph in driver.block_device_info_get_ephemerals(block_device_info): @@ -1234,22 +1236,25 @@ class LibvirtConnection(driver.ComputeDriver): {'root_device_name': '/dev/' + self.default_root_device}) if ephemeral_device: + swap_device = self.default_third_device db.instance_update( nova_context.get_admin_context(), instance['id'], {'default_ephemeral_device': - '/dev/' + self.default_ephemeral_device}) + '/dev/' + self.default_second_device}) + else: + swap_device = self.default_second_device swap = driver.block_device_info_get_swap(block_device_info) if driver.swap_is_usable(swap): xml_info['swap_device'] = block_device.strip_dev( swap['device_name']) elif (inst_type['swap'] > 0 and - not self._volume_in_mapping(self.default_swap_device, + not self._volume_in_mapping(swap_device, block_device_info)): - xml_info['swap_device'] = self.default_swap_device + xml_info['swap_device'] = swap_device db.instance_update( nova_context.get_admin_context(), instance['id'], - {'default_swap_device': '/dev/' + self.default_swap_device}) + {'default_swap_device': '/dev/' + swap_device}) config_drive = False if instance.get('config_drive') or instance.get('config_drive_id'): diff --git a/openstack-common.conf b/openstack-common.conf new file mode 100644 index 000000000..ab5c2fa8c --- /dev/null +++ b/openstack-common.conf @@ -0,0 +1,7 @@ +[DEFAULT] + +# The list of modules to copy from openstack-common +modules=cfg + +# The base module to hold the copy of openstack.common +base=nova |