Use cfg's new global CONF object
Implements blueprint cfg-global-object Replace nova.flags.FLAGS with openstack.common.cfg.CONF. In future, we can do a s/FLAGS/CONF/ across the codebase. Change-Id: Ib293873089a5399febd7a3b0410f66e9bef115f1
This commit is contained in:
@@ -46,7 +46,6 @@ from nova import flags
|
|||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
from nova.openstack.common import cfg
|
from nova.openstack.common import cfg
|
||||||
from nova import rpc
|
from nova import rpc
|
||||||
from nova import utils
|
|
||||||
|
|
||||||
|
|
||||||
delete_exchange_opt = \
|
delete_exchange_opt = \
|
||||||
@@ -71,8 +70,7 @@ def delete_queues(queues):
|
|||||||
x.queue_delete(q)
|
x.queue_delete(q)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
args = flags.parse_args(sys.argv)
|
||||||
args = flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
rpc.register_opts(flags.FLAGS)
|
rpc.register_opts(flags.FLAGS)
|
||||||
delete_queues(args[1:])
|
delete_queues(args[1:])
|
||||||
|
|||||||
@@ -65,8 +65,7 @@ FLAGS = flags.FLAGS
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
rpc.register_opts(FLAGS)
|
rpc.register_opts(FLAGS)
|
||||||
admin_context = context.get_admin_context()
|
admin_context = context.get_admin_context()
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
begin, end = utils.last_completed_audit_period()
|
begin, end = utils.last_completed_audit_period()
|
||||||
print "Starting instance usage audit"
|
print "Starting instance usage audit"
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ from nova.vnc import xvp_proxy
|
|||||||
LOG = logging.getLogger('nova.all')
|
LOG = logging.getLogger('nova.all')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
servers = []
|
servers = []
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
servers = []
|
servers = []
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = service.WSGIService('ec2')
|
server = service.WSGIService('ec2')
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = service.WSGIService('metadata')
|
server = service.WSGIService('metadata')
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = service.WSGIService('osapi_compute')
|
server = service.WSGIService('osapi_compute')
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = service.WSGIService('osapi_volume')
|
server = service.WSGIService('osapi_volume')
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = service.Service.create(binary='nova-cert')
|
server = service.Service.create(binary='nova-cert')
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = service.Service.create(binary='nova-compute')
|
server = service.Service.create(binary='nova-compute')
|
||||||
|
|||||||
@@ -36,11 +36,9 @@ if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
|||||||
from nova import flags
|
from nova import flags
|
||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
from nova import service
|
from nova import service
|
||||||
from nova import utils
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
server = service.Service.create(binary='nova-console')
|
server = service.Service.create(binary='nova-console')
|
||||||
service.serve(server)
|
service.serve(server)
|
||||||
|
|||||||
@@ -35,12 +35,10 @@ from nova.consoleauth import manager
|
|||||||
from nova import flags
|
from nova import flags
|
||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
from nova import service
|
from nova import service
|
||||||
from nova import utils
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
|
|
||||||
server = service.Service.create(binary='nova-consoleauth')
|
server = service.Service.create(binary='nova-consoleauth')
|
||||||
|
|||||||
@@ -96,8 +96,7 @@ def init_leases(network_id):
|
|||||||
def main():
|
def main():
|
||||||
"""Parse environment and arguments and call the approproate action."""
|
"""Parse environment and arguments and call the approproate action."""
|
||||||
flagfile = os.environ.get('FLAGFILE', FLAGS.dhcpbridge_flagfile)
|
flagfile = os.environ.get('FLAGFILE', FLAGS.dhcpbridge_flagfile)
|
||||||
utils.default_cfgfile(flagfile)
|
argv = flags.parse_args(sys.argv)
|
||||||
argv = FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
|
|
||||||
rpc.register_opts(FLAGS)
|
rpc.register_opts(FLAGS)
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ from nova.db import migration
|
|||||||
from nova import exception
|
from nova import exception
|
||||||
from nova import flags
|
from nova import flags
|
||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
|
from nova.openstack.common import cfg
|
||||||
from nova.openstack.common import importutils
|
from nova.openstack.common import importutils
|
||||||
from nova import quota
|
from nova import quota
|
||||||
from nova import rpc
|
from nova import rpc
|
||||||
@@ -1668,26 +1669,24 @@ def methods_of(obj):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Parse options and call the appropriate class/method."""
|
"""Parse options and call the appropriate class/method."""
|
||||||
cfgfile = utils.default_cfgfile()
|
|
||||||
|
|
||||||
if cfgfile and not os.access(cfgfile, os.R_OK):
|
|
||||||
st = os.stat(cfgfile)
|
|
||||||
print "Could not read %s. Re-running with sudo" % cfgfile
|
|
||||||
try:
|
|
||||||
os.execvp('sudo', ['sudo', '-u', '#%s' % st.st_uid] + sys.argv)
|
|
||||||
except Exception:
|
|
||||||
print 'sudo failed, continuing as if nothing happened'
|
|
||||||
|
|
||||||
rpc.register_opts(FLAGS)
|
rpc.register_opts(FLAGS)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
argv = FLAGS(sys.argv)
|
argv = flags.parse_args(sys.argv)
|
||||||
logging.setup()
|
logging.setup()
|
||||||
except IOError, e:
|
except cfg.ConfigFilesNotFoundError:
|
||||||
if e.errno == errno.EACCES:
|
cfgfile = FLAGS.config_file[-1] if FLAGS.config_file else None
|
||||||
print _('Please re-run nova-manage as root.')
|
if cfgfile and not os.access(cfgfile, os.R_OK):
|
||||||
sys.exit(2)
|
st = os.stat(cfgfile)
|
||||||
raise
|
print _("Could not read %s. Re-running with sudo") % cfgfile
|
||||||
|
try:
|
||||||
|
os.execvp('sudo', ['sudo', '-u', '#%s' % st.st_uid] + sys.argv)
|
||||||
|
except Exception:
|
||||||
|
print _('sudo failed, continuing as if nothing happened')
|
||||||
|
|
||||||
|
print _('Please re-run nova-manage as root.')
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
script_name = argv.pop(0)
|
script_name = argv.pop(0)
|
||||||
if len(argv) < 1:
|
if len(argv) < 1:
|
||||||
print _("\nOpenStack Nova version: %(version)s (%(vcs)s)\n") % \
|
print _("\nOpenStack Nova version: %(version)s (%(vcs)s)\n") % \
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = service.Service.create(binary='nova-network')
|
server = service.Service.create(binary='nova-network')
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ from nova import utils
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = s3server.get_wsgi_server()
|
server = s3server.get_wsgi_server()
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = service.Service.create(binary='nova-scheduler')
|
server = service.Service.create(binary='nova-scheduler')
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ from nova import service
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
utils.monkey_patch()
|
utils.monkey_patch()
|
||||||
server = service.Service.create(binary='nova-volume')
|
server = service.Service.create(binary='nova-volume')
|
||||||
|
|||||||
@@ -35,15 +35,13 @@ from nova import flags
|
|||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
from nova import rpc
|
from nova import rpc
|
||||||
from nova import service
|
from nova import service
|
||||||
from nova import utils
|
|
||||||
from nova.vnc import xvp_proxy
|
from nova.vnc import xvp_proxy
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
rpc.register_opts(FLAGS)
|
rpc.register_opts(FLAGS)
|
||||||
utils.default_cfgfile()
|
flags.parse_args(sys.argv)
|
||||||
flags.FLAGS(sys.argv)
|
|
||||||
logging.setup()
|
logging.setup()
|
||||||
|
|
||||||
wsgi_server = xvp_proxy.get_wsgi_server()
|
wsgi_server = xvp_proxy.get_wsgi_server()
|
||||||
|
|||||||
@@ -33,19 +33,14 @@ import sys
|
|||||||
from nova.openstack.common import cfg
|
from nova.openstack.common import cfg
|
||||||
|
|
||||||
|
|
||||||
class NovaConfigOpts(cfg.CommonConfigOpts):
|
FLAGS = cfg.CONF
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
if 'project' not in kwargs:
|
|
||||||
kwargs['project'] = 'nova'
|
|
||||||
super(NovaConfigOpts, self).__init__(*args, **kwargs)
|
|
||||||
self.disable_interspersed_args()
|
|
||||||
|
|
||||||
def __call__(self, argv):
|
|
||||||
return argv[:1] + super(NovaConfigOpts, self).__call__(argv[1:])
|
|
||||||
|
|
||||||
|
|
||||||
FLAGS = NovaConfigOpts()
|
def parse_args(argv, default_config_files=None):
|
||||||
|
FLAGS.disable_interspersed_args()
|
||||||
|
return argv[:1] + FLAGS(argv[1:],
|
||||||
|
project='nova',
|
||||||
|
default_config_files=default_config_files)
|
||||||
|
|
||||||
|
|
||||||
class UnrecognizedFlag(Exception):
|
class UnrecognizedFlag(Exception):
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ and --config-dir::
|
|||||||
|
|
||||||
class ConfigOpts(object):
|
class ConfigOpts(object):
|
||||||
|
|
||||||
def __init__(self, ...):
|
def __call__(self, ...):
|
||||||
|
|
||||||
opts = [
|
opts = [
|
||||||
MultiStrOpt('config-file',
|
MultiStrOpt('config-file',
|
||||||
@@ -233,6 +233,22 @@ log files:
|
|||||||
...
|
...
|
||||||
]
|
]
|
||||||
|
|
||||||
|
This module also contains a global instance of the CommonConfigOpts class
|
||||||
|
in order to support a common usage pattern in OpenStack:
|
||||||
|
|
||||||
|
from openstack.common import cfg
|
||||||
|
|
||||||
|
opts = [
|
||||||
|
cfg.StrOpt('bind_host' default='0.0.0.0'),
|
||||||
|
cfg.IntOpt('bind_port', default=9292),
|
||||||
|
]
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
CONF.register_opts(opts)
|
||||||
|
|
||||||
|
def start(server, app):
|
||||||
|
server.start(app, CONF.bind_port, CONF.bind_host)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
@@ -768,6 +784,14 @@ class OptGroup(object):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _unregister_opt(self, opt):
|
||||||
|
"""Remove an opt from this group.
|
||||||
|
|
||||||
|
:param opt: an Opt object
|
||||||
|
"""
|
||||||
|
if opt.dest in self._opts:
|
||||||
|
del self._opts[opt.dest]
|
||||||
|
|
||||||
def _get_optparse_group(self, parser):
|
def _get_optparse_group(self, parser):
|
||||||
"""Build an optparse.OptionGroup for this group."""
|
"""Build an optparse.OptionGroup for this group."""
|
||||||
if self._optparse_group is None:
|
if self._optparse_group is None:
|
||||||
@@ -775,6 +799,10 @@ class OptGroup(object):
|
|||||||
self.help)
|
self.help)
|
||||||
return self._optparse_group
|
return self._optparse_group
|
||||||
|
|
||||||
|
def _clear(self):
|
||||||
|
"""Clear this group's option parsing state."""
|
||||||
|
self._optparse_group = None
|
||||||
|
|
||||||
|
|
||||||
class ParseError(iniparser.ParseError):
|
class ParseError(iniparser.ParseError):
|
||||||
def __init__(self, msg, lineno, line, filename):
|
def __init__(self, msg, lineno, line, filename):
|
||||||
@@ -849,57 +877,41 @@ class ConfigOpts(collections.Mapping):
|
|||||||
the values of options.
|
the values of options.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self):
|
||||||
project=None,
|
"""Construct a ConfigOpts object."""
|
||||||
prog=None,
|
self._opts = {} # dict of dicts of (opt:, override:, default:)
|
||||||
version=None,
|
self._groups = {}
|
||||||
usage=None,
|
|
||||||
default_config_files=None):
|
|
||||||
"""Construct a ConfigOpts object.
|
|
||||||
|
|
||||||
Automatically registers the --config-file option with either a supplied
|
self._args = None
|
||||||
list of default config files, or a list from find_config_files().
|
self._oparser = None
|
||||||
|
self._cparser = None
|
||||||
|
self._cli_values = {}
|
||||||
|
self.__cache = {}
|
||||||
|
self._config_opts = []
|
||||||
|
self._disable_interspersed_args = False
|
||||||
|
|
||||||
:param project: the toplevel project name, used to locate config files
|
def _setup(self, project, prog, version, usage, default_config_files):
|
||||||
:param prog: the name of the program (defaults to sys.argv[0] basename)
|
"""Initialize a ConfigOpts object for option parsing."""
|
||||||
: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:
|
if prog is None:
|
||||||
prog = os.path.basename(sys.argv[0])
|
prog = os.path.basename(sys.argv[0])
|
||||||
|
|
||||||
if default_config_files is None:
|
if default_config_files is None:
|
||||||
default_config_files = find_config_files(project, prog)
|
default_config_files = find_config_files(project, prog)
|
||||||
|
|
||||||
self.project = project
|
self._oparser = optparse.OptionParser(prog=prog,
|
||||||
self.prog = prog
|
version=version,
|
||||||
self.version = version
|
usage=usage)
|
||||||
self.usage = usage
|
if self._disable_interspersed_args:
|
||||||
self.default_config_files = default_config_files
|
self._oparser.disable_interspersed_args()
|
||||||
|
|
||||||
self._opts = {} # dict of dicts of (opt:, override:, default:)
|
self._config_opts = [
|
||||||
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.__cache = {}
|
|
||||||
|
|
||||||
opts = [
|
|
||||||
MultiStrOpt('config-file',
|
MultiStrOpt('config-file',
|
||||||
default=self.default_config_files,
|
default=default_config_files,
|
||||||
metavar='PATH',
|
metavar='PATH',
|
||||||
help='Path to a config file to use. Multiple config '
|
help='Path to a config file to use. Multiple config '
|
||||||
'files can be specified, with values in later '
|
'files can be specified, with values in later '
|
||||||
'files taking precedence. The default files '
|
'files taking precedence. The default files '
|
||||||
' used are: %s' %
|
' used are: %s' % (default_config_files, )),
|
||||||
(self.default_config_files, )),
|
|
||||||
StrOpt('config-dir',
|
StrOpt('config-dir',
|
||||||
metavar='DIR',
|
metavar='DIR',
|
||||||
help='Path to a config directory to pull *.conf '
|
help='Path to a config directory to pull *.conf '
|
||||||
@@ -910,7 +922,13 @@ class ConfigOpts(collections.Mapping):
|
|||||||
'hence over-ridden options in the directory take '
|
'hence over-ridden options in the directory take '
|
||||||
'precedence.'),
|
'precedence.'),
|
||||||
]
|
]
|
||||||
self.register_cli_opts(opts)
|
self.register_cli_opts(self._config_opts)
|
||||||
|
|
||||||
|
self.project = project
|
||||||
|
self.prog = prog
|
||||||
|
self.version = version
|
||||||
|
self.usage = usage
|
||||||
|
self.default_config_files = default_config_files
|
||||||
|
|
||||||
def __clear_cache(f):
|
def __clear_cache(f):
|
||||||
@functools.wraps(f)
|
@functools.wraps(f)
|
||||||
@@ -921,7 +939,13 @@ class ConfigOpts(collections.Mapping):
|
|||||||
|
|
||||||
return __inner
|
return __inner
|
||||||
|
|
||||||
def __call__(self, args=None):
|
def __call__(self,
|
||||||
|
args=None,
|
||||||
|
project=None,
|
||||||
|
prog=None,
|
||||||
|
version=None,
|
||||||
|
usage=None,
|
||||||
|
default_config_files=None):
|
||||||
"""Parse command line arguments and config files.
|
"""Parse command line arguments and config files.
|
||||||
|
|
||||||
Calling a ConfigOpts object causes the supplied command line arguments
|
Calling a ConfigOpts object causes the supplied command line arguments
|
||||||
@@ -931,35 +955,34 @@ class ConfigOpts(collections.Mapping):
|
|||||||
The object may be called multiple times, each time causing the previous
|
The object may be called multiple times, each time causing the previous
|
||||||
set of values to be overwritten.
|
set of values to be overwritten.
|
||||||
|
|
||||||
|
Automatically registers the --config-file option with either a supplied
|
||||||
|
list of default config files, or a list from find_config_files().
|
||||||
|
|
||||||
If the --config-dir option is set, any *.conf files from this
|
If the --config-dir option is set, any *.conf files from this
|
||||||
directory are pulled in, after all the file(s) specified by the
|
directory are pulled in, after all the file(s) specified by the
|
||||||
--config-file option.
|
--config-file option.
|
||||||
|
|
||||||
:params args: command line arguments (defaults to sys.argv[1:])
|
:param args: command line arguments (defaults to sys.argv[1:])
|
||||||
|
: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
|
||||||
:returns: the list of arguments left over after parsing options
|
:returns: the list of arguments left over after parsing options
|
||||||
:raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError,
|
:raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError,
|
||||||
RequiredOptError
|
RequiredOptError, DuplicateOptError
|
||||||
"""
|
"""
|
||||||
self.clear()
|
self.clear()
|
||||||
|
|
||||||
self._args = args
|
self._setup(project, prog, version, usage, default_config_files)
|
||||||
|
|
||||||
(values, args) = self._oparser.parse_args(self._args)
|
self._cli_values, leftovers = self._parse_cli_opts(args)
|
||||||
|
|
||||||
self._cli_values = vars(values)
|
self._parse_config_files()
|
||||||
|
|
||||||
def _list_config_dir():
|
|
||||||
return sorted(glob.glob(os.path.join(self.config_dir, '*.conf')))
|
|
||||||
|
|
||||||
from_file = list(self.config_file)
|
|
||||||
|
|
||||||
from_dir = _list_config_dir() if self.config_dir else []
|
|
||||||
|
|
||||||
self._parse_config_files(from_file + from_dir)
|
|
||||||
|
|
||||||
self._check_required_opts()
|
self._check_required_opts()
|
||||||
|
|
||||||
return args
|
return leftovers
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
"""Look up an option value and perform string substitution.
|
"""Look up an option value and perform string substitution.
|
||||||
@@ -996,8 +1019,12 @@ class ConfigOpts(collections.Mapping):
|
|||||||
def clear(self):
|
def clear(self):
|
||||||
"""Clear the state of the object to before it was called."""
|
"""Clear the state of the object to before it was called."""
|
||||||
self._args = None
|
self._args = None
|
||||||
self._cli_values = {}
|
self._cli_values.clear()
|
||||||
|
self._oparser = None
|
||||||
self._cparser = None
|
self._cparser = None
|
||||||
|
self.unregister_opts(self._config_opts)
|
||||||
|
for group in self._groups.values():
|
||||||
|
group._clear()
|
||||||
|
|
||||||
@__clear_cache
|
@__clear_cache
|
||||||
def register_opt(self, opt, group=None):
|
def register_opt(self, opt, group=None):
|
||||||
@@ -1044,15 +1071,7 @@ class ConfigOpts(collections.Mapping):
|
|||||||
if self._args is not None:
|
if self._args is not None:
|
||||||
raise ArgsAlreadyParsedError("cannot register CLI option")
|
raise ArgsAlreadyParsedError("cannot register CLI option")
|
||||||
|
|
||||||
if not self.register_opt(opt, group, clear_cache=False):
|
return self.register_opt(opt, group, clear_cache=False)
|
||||||
return False
|
|
||||||
|
|
||||||
if group is not None:
|
|
||||||
group = self._get_group(group, autocreate=True)
|
|
||||||
|
|
||||||
opt._add_to_cli(self._oparser, group)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
@__clear_cache
|
@__clear_cache
|
||||||
def register_cli_opts(self, opts, group=None):
|
def register_cli_opts(self, opts, group=None):
|
||||||
@@ -1073,6 +1092,28 @@ class ConfigOpts(collections.Mapping):
|
|||||||
|
|
||||||
self._groups[group.name] = copy.copy(group)
|
self._groups[group.name] = copy.copy(group)
|
||||||
|
|
||||||
|
@__clear_cache
|
||||||
|
def unregister_opt(self, opt, group=None):
|
||||||
|
"""Unregister an option.
|
||||||
|
|
||||||
|
:param opt: an Opt object
|
||||||
|
:param group: an optional OptGroup object or group name
|
||||||
|
:raises: ArgsAlreadyParsedError, NoSuchGroupError
|
||||||
|
"""
|
||||||
|
if self._args is not None:
|
||||||
|
raise ArgsAlreadyParsedError("reset before unregistering options")
|
||||||
|
|
||||||
|
if group is not None:
|
||||||
|
self._get_group(group)._unregister_opt(opt)
|
||||||
|
elif opt.dest in self._opts:
|
||||||
|
del self._opts[opt.dest]
|
||||||
|
|
||||||
|
@__clear_cache
|
||||||
|
def unregister_opts(self, opts, group=None):
|
||||||
|
"""Unregister multiple CLI option schemas at once."""
|
||||||
|
for opt in opts:
|
||||||
|
self.unregister_opt(opt, group, clear_cache=False)
|
||||||
|
|
||||||
@__clear_cache
|
@__clear_cache
|
||||||
def set_override(self, name, override, group=None):
|
def set_override(self, name, override, group=None):
|
||||||
"""Override an opt value.
|
"""Override an opt value.
|
||||||
@@ -1103,16 +1144,24 @@ class ConfigOpts(collections.Mapping):
|
|||||||
opt_info = self._get_opt_info(name, group)
|
opt_info = self._get_opt_info(name, group)
|
||||||
opt_info['default'] = default
|
opt_info['default'] = default
|
||||||
|
|
||||||
|
def _all_opt_infos(self):
|
||||||
|
"""A generator function for iteration opt infos."""
|
||||||
|
for info in self._opts.values():
|
||||||
|
yield info, None
|
||||||
|
for group in self._groups.values():
|
||||||
|
for info in group._opts.values():
|
||||||
|
yield info, group
|
||||||
|
|
||||||
|
def _all_opts(self):
|
||||||
|
"""A generator function for iteration opts."""
|
||||||
|
for info, group in self._all_opt_infos():
|
||||||
|
yield info['opt'], group
|
||||||
|
|
||||||
def _unset_defaults_and_overrides(self):
|
def _unset_defaults_and_overrides(self):
|
||||||
"""Unset any default or override on all options."""
|
"""Unset any default or override on all options."""
|
||||||
def unset(opts):
|
for info, group in self._all_opt_infos():
|
||||||
for info in opts.values():
|
info['default'] = None
|
||||||
info['default'] = None
|
info['override'] = None
|
||||||
info['override'] = None
|
|
||||||
|
|
||||||
unset(self._opts)
|
|
||||||
for group in self._groups.values():
|
|
||||||
unset(group._opts)
|
|
||||||
|
|
||||||
def disable_interspersed_args(self):
|
def disable_interspersed_args(self):
|
||||||
"""Set parsing to stop on the first non-option.
|
"""Set parsing to stop on the first non-option.
|
||||||
@@ -1131,13 +1180,13 @@ class ConfigOpts(collections.Mapping):
|
|||||||
|
|
||||||
i.e. argument parsing is stopped at the first non-option argument.
|
i.e. argument parsing is stopped at the first non-option argument.
|
||||||
"""
|
"""
|
||||||
self._oparser.disable_interspersed_args()
|
self._disable_interspersed_args = True
|
||||||
|
|
||||||
def enable_interspersed_args(self):
|
def enable_interspersed_args(self):
|
||||||
"""Set parsing to not stop on the first non-option.
|
"""Set parsing to not stop on the first non-option.
|
||||||
|
|
||||||
This it the default behaviour."""
|
This it the default behaviour."""
|
||||||
self._oparser.enable_interspersed_args()
|
self._disable_interspersed_args = False
|
||||||
|
|
||||||
def find_file(self, name):
|
def find_file(self, name):
|
||||||
"""Locate a file located alongside the config files.
|
"""Locate a file located alongside the config files.
|
||||||
@@ -1331,11 +1380,17 @@ class ConfigOpts(collections.Mapping):
|
|||||||
|
|
||||||
return opts[opt_name]
|
return opts[opt_name]
|
||||||
|
|
||||||
def _parse_config_files(self, config_files):
|
def _parse_config_files(self):
|
||||||
"""Parse the supplied configuration files.
|
"""Parse the config files from --config-file and --config-dir.
|
||||||
|
|
||||||
:raises: ConfigFilesNotFoundError, ConfigFileParseError
|
:raises: ConfigFilesNotFoundError, ConfigFileParseError
|
||||||
"""
|
"""
|
||||||
|
config_files = list(self.config_file)
|
||||||
|
|
||||||
|
if self.config_dir:
|
||||||
|
config_dir_glob = os.path.join(self.config_dir, '*.conf')
|
||||||
|
config_files += sorted(glob.glob(config_dir_glob))
|
||||||
|
|
||||||
self._cparser = MultiConfigParser()
|
self._cparser = MultiConfigParser()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -1347,8 +1402,12 @@ class ConfigOpts(collections.Mapping):
|
|||||||
not_read_ok = filter(lambda f: f not in read_ok, config_files)
|
not_read_ok = filter(lambda f: f not in read_ok, config_files)
|
||||||
raise ConfigFilesNotFoundError(not_read_ok)
|
raise ConfigFilesNotFoundError(not_read_ok)
|
||||||
|
|
||||||
def _do_check_required_opts(self, opts, group=None):
|
def _check_required_opts(self):
|
||||||
for info in opts.values():
|
"""Check that all opts marked as required have values specified.
|
||||||
|
|
||||||
|
:raises: RequiredOptError
|
||||||
|
"""
|
||||||
|
for info, group in self._all_opt_infos():
|
||||||
default, opt, override = [info[k] for k in sorted(info.keys())]
|
default, opt, override = [info[k] for k in sorted(info.keys())]
|
||||||
|
|
||||||
if opt.required:
|
if opt.required:
|
||||||
@@ -1359,15 +1418,25 @@ class ConfigOpts(collections.Mapping):
|
|||||||
if self._get(opt.name, group) is None:
|
if self._get(opt.name, group) is None:
|
||||||
raise RequiredOptError(opt.name, group)
|
raise RequiredOptError(opt.name, group)
|
||||||
|
|
||||||
def _check_required_opts(self):
|
def _parse_cli_opts(self, args):
|
||||||
"""Check that all opts marked as required have values specified.
|
"""Parse command line options.
|
||||||
|
|
||||||
|
Initializes the command line option parser and parses the supplied
|
||||||
|
command line arguments.
|
||||||
|
|
||||||
|
:param args: the command line arguments
|
||||||
|
:returns: a dict of parsed option values
|
||||||
|
:raises: SystemExit, DuplicateOptError
|
||||||
|
|
||||||
:raises: RequiredOptError
|
|
||||||
"""
|
"""
|
||||||
self._do_check_required_opts(self._opts)
|
self._args = args
|
||||||
|
|
||||||
for group in self._groups.values():
|
for opt, group in self._all_opts():
|
||||||
self._do_check_required_opts(group._opts, group)
|
opt._add_to_cli(self._oparser, group)
|
||||||
|
|
||||||
|
values, leftovers = self._oparser.parse_args(args)
|
||||||
|
|
||||||
|
return vars(values), leftovers
|
||||||
|
|
||||||
class GroupAttr(collections.Mapping):
|
class GroupAttr(collections.Mapping):
|
||||||
|
|
||||||
@@ -1483,7 +1552,10 @@ class CommonConfigOpts(ConfigOpts):
|
|||||||
help='syslog facility to receive log lines')
|
help='syslog facility to receive log lines')
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self):
|
||||||
super(CommonConfigOpts, self).__init__(**kwargs)
|
super(CommonConfigOpts, self).__init__()
|
||||||
self.register_cli_opts(self.common_cli_opts)
|
self.register_cli_opts(self.common_cli_opts)
|
||||||
self.register_cli_opts(self.logging_cli_opts)
|
self.register_cli_opts(self.logging_cli_opts)
|
||||||
|
|
||||||
|
|
||||||
|
CONF = CommonConfigOpts()
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ class TestCase(unittest.TestCase):
|
|||||||
super(TestCase, self).setUp()
|
super(TestCase, self).setUp()
|
||||||
|
|
||||||
fake_flags.set_defaults(FLAGS)
|
fake_flags.set_defaults(FLAGS)
|
||||||
|
flags.parse_args([], default_config_files=[])
|
||||||
|
|
||||||
# NOTE(vish): We need a better method for creating fixtures for tests
|
# NOTE(vish): We need a better method for creating fixtures for tests
|
||||||
# now that we have some required db setup for the system
|
# now that we have some required db setup for the system
|
||||||
|
|||||||
@@ -34,54 +34,50 @@ class FlagsTestCase(test.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(FlagsTestCase, self).setUp()
|
super(FlagsTestCase, self).setUp()
|
||||||
self.FLAGS = flags.NovaConfigOpts()
|
|
||||||
self.global_FLAGS = flags.FLAGS
|
|
||||||
self.flags(config_file=[])
|
|
||||||
|
|
||||||
def test_declare(self):
|
def test_declare(self):
|
||||||
self.assert_('answer' not in self.global_FLAGS)
|
self.assert_('answer' not in FLAGS)
|
||||||
flags.DECLARE('answer', 'nova.tests.declare_flags')
|
flags.DECLARE('answer', 'nova.tests.declare_flags')
|
||||||
self.assert_('answer' in self.global_FLAGS)
|
self.assert_('answer' in FLAGS)
|
||||||
self.assertEqual(self.global_FLAGS.answer, 42)
|
self.assertEqual(FLAGS.answer, 42)
|
||||||
|
|
||||||
# Make sure we don't overwrite anything
|
# Make sure we don't overwrite anything
|
||||||
self.global_FLAGS.set_override('answer', 256)
|
FLAGS.set_override('answer', 256)
|
||||||
self.assertEqual(self.global_FLAGS.answer, 256)
|
self.assertEqual(FLAGS.answer, 256)
|
||||||
flags.DECLARE('answer', 'nova.tests.declare_flags')
|
flags.DECLARE('answer', 'nova.tests.declare_flags')
|
||||||
self.assertEqual(self.global_FLAGS.answer, 256)
|
self.assertEqual(FLAGS.answer, 256)
|
||||||
|
|
||||||
def test_getopt_non_interspersed_args(self):
|
def test_getopt_non_interspersed_args(self):
|
||||||
self.assert_('runtime_answer' not in self.global_FLAGS)
|
self.assert_('runtime_answer' not in FLAGS)
|
||||||
|
|
||||||
argv = ['flags_test', 'extra_arg', '--runtime_answer=60']
|
argv = ['flags_test', 'extra_arg', '--runtime_answer=60']
|
||||||
args = self.global_FLAGS(argv)
|
args = flags.parse_args(argv, default_config_files=[])
|
||||||
self.assertEqual(len(args), 3)
|
self.assertEqual(len(args), 3)
|
||||||
self.assertEqual(argv, args)
|
self.assertEqual(argv, args)
|
||||||
|
|
||||||
def test_runtime_and_unknown_flags(self):
|
def test_runtime_and_unknown_flags(self):
|
||||||
self.assert_('runtime_answer' not in self.global_FLAGS)
|
self.assert_('runtime_answer' not in FLAGS)
|
||||||
import nova.tests.runtime_flags
|
import nova.tests.runtime_flags
|
||||||
self.assert_('runtime_answer' in self.global_FLAGS)
|
self.assert_('runtime_answer' in FLAGS)
|
||||||
self.assertEqual(self.global_FLAGS.runtime_answer, 54)
|
self.assertEqual(FLAGS.runtime_answer, 54)
|
||||||
|
|
||||||
def test_long_vs_short_flags(self):
|
def test_long_vs_short_flags(self):
|
||||||
self.global_FLAGS.clear()
|
FLAGS.clear()
|
||||||
self.global_FLAGS.register_cli_opt(cfg.StrOpt('duplicate_answer_long',
|
FLAGS.register_cli_opt(cfg.StrOpt('duplicate_answer_long',
|
||||||
default='val',
|
default='val',
|
||||||
help='desc'))
|
help='desc'))
|
||||||
argv = ['flags_test', '--duplicate_answer=60', 'extra_arg']
|
argv = ['flags_test', '--duplicate_answer=60', 'extra_arg']
|
||||||
args = self.global_FLAGS(argv)
|
args = flags.parse_args(argv, default_config_files=[])
|
||||||
|
|
||||||
self.assert_('duplicate_answer' not in self.global_FLAGS)
|
self.assert_('duplicate_answer' not in FLAGS)
|
||||||
self.assert_(self.global_FLAGS.duplicate_answer_long, 60)
|
self.assert_(FLAGS.duplicate_answer_long, 60)
|
||||||
|
|
||||||
self.global_FLAGS.clear()
|
FLAGS.clear()
|
||||||
self.global_FLAGS.register_cli_opt(cfg.IntOpt('duplicate_answer',
|
FLAGS.register_cli_opt(cfg.IntOpt('duplicate_answer',
|
||||||
default=60,
|
default=60, help='desc'))
|
||||||
help='desc'))
|
args = flags.parse_args(argv, default_config_files=[])
|
||||||
args = self.global_FLAGS(argv)
|
self.assertEqual(FLAGS.duplicate_answer, 60)
|
||||||
self.assertEqual(self.global_FLAGS.duplicate_answer, 60)
|
self.assertEqual(FLAGS.duplicate_answer_long, 'val')
|
||||||
self.assertEqual(self.global_FLAGS.duplicate_answer_long, 'val')
|
|
||||||
|
|
||||||
def test_flag_leak_left(self):
|
def test_flag_leak_left(self):
|
||||||
self.assertEqual(FLAGS.flags_unittest, 'foo')
|
self.assertEqual(FLAGS.flags_unittest, 'foo')
|
||||||
@@ -99,17 +95,3 @@ class FlagsTestCase(test.TestCase):
|
|||||||
self.assertEqual(FLAGS.flags_unittest, 'bar')
|
self.assertEqual(FLAGS.flags_unittest, 'bar')
|
||||||
FLAGS.reset()
|
FLAGS.reset()
|
||||||
self.assertEqual(FLAGS.flags_unittest, 'foo')
|
self.assertEqual(FLAGS.flags_unittest, 'foo')
|
||||||
|
|
||||||
def test_defaults(self):
|
|
||||||
self.FLAGS.register_opt(cfg.StrOpt('foo', default='bar', help='desc'))
|
|
||||||
self.assertEqual(self.FLAGS.foo, 'bar')
|
|
||||||
|
|
||||||
self.FLAGS.set_default('foo', 'blaa')
|
|
||||||
self.assertEqual(self.FLAGS.foo, 'blaa')
|
|
||||||
|
|
||||||
def test_templated_values(self):
|
|
||||||
self.FLAGS.register_opt(cfg.StrOpt('foo', default='foo', help='desc'))
|
|
||||||
self.FLAGS.register_opt(cfg.StrOpt('bar', default='bar', help='desc'))
|
|
||||||
self.FLAGS.register_opt(cfg.StrOpt('blaa',
|
|
||||||
default='$foo$bar', help='desc'))
|
|
||||||
self.assertEqual(self.FLAGS.blaa, 'foobar')
|
|
||||||
|
|||||||
@@ -284,27 +284,6 @@ def novadir():
|
|||||||
return os.path.abspath(nova.__file__).split('nova/__init__.py')[0]
|
return os.path.abspath(nova.__file__).split('nova/__init__.py')[0]
|
||||||
|
|
||||||
|
|
||||||
def default_cfgfile(filename='nova.conf', args=None):
|
|
||||||
if args is None:
|
|
||||||
args = sys.argv
|
|
||||||
for arg in args:
|
|
||||||
if arg.find('config-file') != -1:
|
|
||||||
return arg[arg.index('config-file') + len('config-file') + 1:]
|
|
||||||
else:
|
|
||||||
if not os.path.isabs(filename):
|
|
||||||
# turn relative filename into an absolute path
|
|
||||||
script_dir = os.path.dirname(inspect.stack()[-1][1])
|
|
||||||
filename = os.path.abspath(os.path.join(script_dir, filename))
|
|
||||||
if not os.path.exists(filename):
|
|
||||||
filename = "./nova.conf"
|
|
||||||
if not os.path.exists(filename):
|
|
||||||
filename = '/etc/nova/nova.conf'
|
|
||||||
if os.path.exists(filename):
|
|
||||||
cfgfile = '--config-file=%s' % filename
|
|
||||||
args.insert(1, cfgfile)
|
|
||||||
return filename
|
|
||||||
|
|
||||||
|
|
||||||
def debug(arg):
|
def debug(arg):
|
||||||
LOG.debug(_('debug in callback: %s'), arg)
|
LOG.debug(_('debug in callback: %s'), arg)
|
||||||
return arg
|
return arg
|
||||||
|
|||||||
Reference in New Issue
Block a user