diff --git a/bin/nova-rootwrap b/bin/nova-rootwrap index 72a8c6309950..35e2f47f3964 100755 --- a/bin/nova-rootwrap +++ b/bin/nova-rootwrap @@ -20,14 +20,17 @@ Filters which commands a service is allowed to run as another user. - To use this with nova, you should set the following in nova.conf: + To use this with nova, you should set the following in + nova.conf: rootwrap_config=/etc/nova/rootwrap.conf - You also need to let the nova user run nova-rootwrap as root in sudoers: - nova ALL = (root) NOPASSWD: /usr/bin/nova-rootwrap /etc/nova/rootwrap.conf * + You also need to let the nova user run nova-rootwrap + as root in sudoers: + nova ALL = (root) NOPASSWD: /usr/bin/nova-rootwrap + /etc/nova/rootwrap.conf * - Service packaging should deploy .filters files only on nodes where they are - needed, to avoid allowing more than is necessary. + Service packaging should deploy .filters files only on nodes where + they are needed, to avoid allowing more than is necessary. """ import ConfigParser @@ -102,8 +105,8 @@ if __name__ == '__main__': exec_dirs=config.exec_dirs) if config.use_syslog: logging.info("(%s > %s) Executing %s (filter match = %s)" % ( - os.getlogin(), pwd.getpwuid(os.getuid())[0], - command, filtermatch.name)) + os.getlogin(), pwd.getpwuid(os.getuid())[0], + command, filtermatch.name)) obj = subprocess.Popen(command, stdin=sys.stdin, diff --git a/nova/openstack/__init__.py b/nova/openstack/__init__.py index 0a3b98867a26..e69de29bb2d1 100644 --- a/nova/openstack/__init__.py +++ b/nova/openstack/__init__.py @@ -1,15 +0,0 @@ -# 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 index 0a3b98867a26..e69de29bb2d1 100644 --- a/nova/openstack/common/__init__.py +++ b/nova/openstack/common/__init__.py @@ -1,15 +0,0 @@ -# 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 index 534a610c0694..baecc0c3b8dd 100644 --- a/nova/openstack/common/cfg.py +++ b/nova/openstack/common/cfg.py @@ -863,7 +863,7 @@ class SubCommandOpt(Opt): description=self.description, help=self.help) - if not self.handler is None: + if self.handler is not None: self.handler(subparsers) @@ -1297,6 +1297,24 @@ class ConfigOpts(collections.Mapping): __import__(module_str) self._get_opt_info(name, group) + def import_group(self, group, module_str): + """Import an option group from a module. + + Import a module and check that a given option group is registered. + + This is intended for use with global configuration objects + like cfg.CONF where modules commonly register options with + CONF at module load time. If one module requires an option group + defined by another module it can use this method to explicitly + declare the dependency. + + :param group: an option OptGroup object or group name + :param module_str: the name of a module to import + :raises: ImportError, NoSuchGroupError + """ + __import__(module_str) + self._get_group(group) + @__clear_cache def set_override(self, name, override, group=None): """Override an opt value. @@ -1547,8 +1565,8 @@ class ConfigOpts(collections.Mapping): group = group_or_name if isinstance(group_or_name, OptGroup) else None group_name = group.name if group else group_or_name - if not group_name in self._groups: - if not group is None or not autocreate: + if group_name not in self._groups: + if group is not None or not autocreate: raise NoSuchGroupError(group_name) self.register_group(OptGroup(name=group_name)) @@ -1568,7 +1586,7 @@ class ConfigOpts(collections.Mapping): group = self._get_group(group) opts = group._opts - if not opt_name in opts: + if opt_name not in opts: raise NoSuchOptError(opt_name, group) return opts[opt_name] @@ -1606,7 +1624,7 @@ class ConfigOpts(collections.Mapping): opt = info['opt'] if opt.required: - if ('default' in info or 'override' in info): + if 'default' in info or 'override' in info: continue if self._get(opt.dest, group) is None: @@ -1625,7 +1643,7 @@ class ConfigOpts(collections.Mapping): """ self._args = args - for opt, group in self._all_cli_opts(): + for opt, group in sorted(self._all_cli_opts()): opt._add_to_cli(self._oparser, group) return vars(self._oparser.parse_args(args)) diff --git a/nova/openstack/common/cliutils.py b/nova/openstack/common/cliutils.py index 8f4dc44dd995..411bd58f3756 100644 --- a/nova/openstack/common/cliutils.py +++ b/nova/openstack/common/cliutils.py @@ -15,7 +15,6 @@ # under the License. import inspect -import string class MissingArgs(Exception): @@ -25,12 +24,10 @@ class MissingArgs(Exception): def __str__(self): if len(self.missing) == 1: - return ("An argument is missing: %(missing)s" % - dict(missing=self.missing[0])) + return "An argument is missing" else: - return ("%(num)d arguments are missing: %(missing)s" % - dict(num=len(self.missing), - missing=string.join(self.missing, ', '))) + return ("%(num)d arguments are missing" % + dict(num=len(self.missing))) def validate_args(fn, *args, **kwargs): @@ -39,11 +36,11 @@ def validate_args(fn, *args, **kwargs): >>> validate_args(lambda a: None) Traceback (most recent call last): ... - MissingArgs: An argument is missing: a + MissingArgs: An argument is missing >>> validate_args(lambda a, b, c, d: None, 0, c=1) Traceback (most recent call last): ... - MissingArgs: 2 arguments are missing: b, d + MissingArgs: 2 arguments are missing :param fn: the function to check :param arg: the positional arguments supplied diff --git a/nova/openstack/common/excutils.py b/nova/openstack/common/excutils.py index 5dd48301760e..e507efceda80 100644 --- a/nova/openstack/common/excutils.py +++ b/nova/openstack/common/excutils.py @@ -24,6 +24,8 @@ import logging import sys import traceback +from nova.openstack.common.gettextutils import _ + @contextlib.contextmanager def save_and_reraise_exception(): @@ -43,7 +45,7 @@ def save_and_reraise_exception(): try: yield except Exception: - logging.error('Original exception being dropped: %s' % - (traceback.format_exception(type_, value, tb))) + logging.error(_('Original exception being dropped: %s'), + traceback.format_exception(type_, value, tb)) raise raise type_, value, tb diff --git a/nova/openstack/common/plugin/pluginmanager.py b/nova/openstack/common/plugin/pluginmanager.py index 51d06d851a6b..157ecbf445c2 100644 --- a/nova/openstack/common/plugin/pluginmanager.py +++ b/nova/openstack/common/plugin/pluginmanager.py @@ -16,6 +16,7 @@ import pkg_resources from nova.openstack.common import cfg +from nova.openstack.common.gettextutils import _ from nova.openstack.common import log as logging from nova.openstack.common.notifier import api as notifier_api diff --git a/nova/openstack/common/policy.py b/nova/openstack/common/policy.py index 496ed972db66..626a61aa50a3 100644 --- a/nova/openstack/common/policy.py +++ b/nova/openstack/common/policy.py @@ -574,19 +574,19 @@ class ParseState(object): for reduction, methname in self.reducers: if (len(self.tokens) >= len(reduction) and - self.tokens[-len(reduction):] == reduction): - # Get the reduction method - meth = getattr(self, methname) + self.tokens[-len(reduction):] == reduction): + # Get the reduction method + meth = getattr(self, methname) - # Reduce the token stream - results = meth(*self.values[-len(reduction):]) + # Reduce the token stream + results = meth(*self.values[-len(reduction):]) - # Update the tokens and values - self.tokens[-len(reduction):] = [r[0] for r in results] - self.values[-len(reduction):] = [r[1] for r in results] + # Update the tokens and values + self.tokens[-len(reduction):] = [r[0] for r in results] + self.values[-len(reduction):] = [r[1] for r in results] - # Check for any more reductions - return self.reduce() + # Check for any more reductions + return self.reduce() def shift(self, tok, value): """Adds one more token to the state. Calls reduce().""" diff --git a/nova/openstack/common/rpc/impl_zmq.py b/nova/openstack/common/rpc/impl_zmq.py index 2c06315481ed..d562b932ff68 100644 --- a/nova/openstack/common/rpc/impl_zmq.py +++ b/nova/openstack/common/rpc/impl_zmq.py @@ -772,8 +772,9 @@ def _get_ctxt(): return ZMQ_CTX -def _get_matchmaker(): +def _get_matchmaker(*args, **kwargs): global matchmaker if not matchmaker: - matchmaker = importutils.import_object(CONF.rpc_zmq_matchmaker) + matchmaker = importutils.import_object( + CONF.rpc_zmq_matchmaker, *args, **kwargs) return matchmaker diff --git a/nova/openstack/common/rpc/matchmaker.py b/nova/openstack/common/rpc/matchmaker.py index 8b2c67a44785..9eec1df83c04 100644 --- a/nova/openstack/common/rpc/matchmaker.py +++ b/nova/openstack/common/rpc/matchmaker.py @@ -201,24 +201,25 @@ class FanoutRingExchange(RingExchange): class LocalhostExchange(Exchange): """Exchange where all direct topics are local.""" - def __init__(self): + def __init__(self, host='localhost'): + self.host = host super(Exchange, self).__init__() def run(self, key): - return [(key.split('.')[0] + '.localhost', 'localhost')] + return [('.'.join((key.split('.')[0], self.host)), self.host)] class DirectExchange(Exchange): """ Exchange where all topic keys are split, sending to second half. - i.e. "compute.host" sends a message to "compute" running on "host" + i.e. "compute.host" sends a message to "compute.host" running on "host" """ def __init__(self): super(Exchange, self).__init__() def run(self, key): - b, e = key.split('.', 1) - return [(b, e)] + e = key.split('.', 1)[1] + return [(key, e)] class MatchMakerRing(MatchMakerBase): @@ -237,11 +238,11 @@ class MatchMakerLocalhost(MatchMakerBase): Match Maker where all bare topics resolve to localhost. Useful for testing. """ - def __init__(self): + def __init__(self, host='localhost'): super(MatchMakerLocalhost, self).__init__() - self.add_binding(FanoutBinding(), LocalhostExchange()) + self.add_binding(FanoutBinding(), LocalhostExchange(host)) self.add_binding(DirectBinding(), DirectExchange()) - self.add_binding(TopicBinding(), LocalhostExchange()) + self.add_binding(TopicBinding(), LocalhostExchange(host)) class MatchMakerStub(MatchMakerBase): diff --git a/nova/openstack/common/setup.py b/nova/openstack/common/setup.py index fb187fff4654..35680b30485b 100644 --- a/nova/openstack/common/setup.py +++ b/nova/openstack/common/setup.py @@ -274,7 +274,7 @@ def _get_revno(): return len(revlist.splitlines()) -def get_version_from_git(pre_version): +def _get_version_from_git(pre_version): """Return a version which is equal to the tag that's on the current revision if there is one, or tag plus number of additional revisions if the current revision has no tag.""" @@ -294,7 +294,7 @@ def get_version_from_git(pre_version): return None -def get_version_from_pkg_info(package_name): +def _get_version_from_pkg_info(package_name): """Get the version from PKG-INFO file if we can.""" try: pkg_info_file = open('PKG-INFO', 'r') @@ -325,10 +325,10 @@ def get_version(package_name, pre_version=None): version = os.environ.get("OSLO_PACKAGE_VERSION", None) if version: return version - version = get_version_from_pkg_info(package_name) + version = _get_version_from_pkg_info(package_name) if version: return version - version = get_version_from_git(pre_version) + version = _get_version_from_git(pre_version) if version: return version raise Exception("Versioning for this project requires either an sdist" diff --git a/nova/openstack/common/timeutils.py b/nova/openstack/common/timeutils.py index 0f346087f78d..e2c274057312 100644 --- a/nova/openstack/common/timeutils.py +++ b/nova/openstack/common/timeutils.py @@ -98,6 +98,11 @@ def utcnow(): return datetime.datetime.utcnow() +def iso8601_from_timestamp(timestamp): + """Returns a iso8601 formated date from timestamp""" + return isotime(datetime.datetime.utcfromtimestamp(timestamp)) + + utcnow.override_time = None @@ -162,3 +167,16 @@ def delta_seconds(before, after): except AttributeError: return ((delta.days * 24 * 3600) + delta.seconds + float(delta.microseconds) / (10 ** 6)) + + +def is_soon(dt, window): + """ + Determines if time is going to happen in the next window seconds. + + :params dt: the time + :params window: minimum seconds to remain to consider the time not soon + + :return: True if expiration is within the given duration + """ + soon = (utcnow() + datetime.timedelta(seconds=window)) + return normalize_time(dt) <= soon diff --git a/nova/openstack/common/version.py b/nova/openstack/common/version.py index b16ef4bca0ae..57803b3d5db3 100644 --- a/nova/openstack/common/version.py +++ b/nova/openstack/common/version.py @@ -33,6 +33,14 @@ class VersionInfo(object): self.version = None self._cached_version = None + def __str__(self): + """Make the VersionInfo object behave like a string.""" + return self.version_string() + + def __repr__(self): + """Include the name.""" + return "VersionInfo(%s:%s)" % (self.package, self.version_string()) + def _get_version_from_pkg_resources(self): """Get the version of the package from the pkg_resources record associated with the package.""" @@ -41,11 +49,11 @@ class VersionInfo(object): provider = pkg_resources.get_provider(requirement) return provider.version except pkg_resources.DistributionNotFound: - # The most likely cause for this is running tests in a tree with + # The most likely cause for this is running tests in a tree # produced from a tarball where the package itself has not been - # installed into anything. Check for a PKG-INFO file. + # installed into anything. Revert to setup-time logic. from nova.openstack.common import setup - return setup.get_version_from_pkg_info(self.package) + return setup.get_version(self.package) def release_string(self): """Return the full version of the package including suffixes indicating