summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--HACKING.rst15
-rw-r--r--nova/flags.py10
-rw-r--r--nova/openstack/common/README13
-rw-r--r--nova/openstack/common/cfg.py112
-rw-r--r--nova/virt/libvirt/connection.py27
-rw-r--r--openstack-common.conf7
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