diff options
author | Victor Sergeyev <vsergeyev@mirantis.com> | 2014-02-18 16:54:55 +0200 |
---|---|---|
committer | Victor Sergeyev <vsergeyev@mirantis.com> | 2014-02-25 11:13:06 +0200 |
commit | 1fd5b44425646ddcc8801e57f65a1974f30e4330 (patch) | |
tree | a61ffd0ddb4343b55d52461b338f9057696e992b /ironic/openstack | |
parent | 3a4e732985a6bda4472eadf5abc596d19148d51a (diff) | |
download | ironic-1fd5b44425646ddcc8801e57f65a1974f30e4330.tar.gz |
Sync common config module from Oslo
List of changes
1a6dfb9 Sanitize FQDN in config generator
e839886 Config generator fails with lazy messages
763eedf Fix DictOpt support in config sample generator
e3dddd7 generator: use EXTRA_* env vars in the bash script
e8e636c generator: add an EXTRA_LIBRARIES env variable
5dce17b Use entry points to discover options in libraries
dd9aa2b Remove unused variables
ad17a69 Fix filter() usage due to python 3 compability
7c18261 Temporary workaround for config generator
4b3e32b Sort the output of config/generator.py by group name
12bcdb7 Remove vim header
806272e Improve error reporting on import failures
6cd1c33 Clean up extra modules code
Updated ironic.conf.sample using new config generator.
Closes-Bug: #1282481
Change-Id: Ice3e527589bbf0e881d21f55229264513ea445d2
Diffstat (limited to 'ironic/openstack')
-rw-r--r-- | ironic/openstack/common/config/generator.py | 85 |
1 files changed, 59 insertions, 26 deletions
diff --git a/ironic/openstack/common/config/generator.py b/ironic/openstack/common/config/generator.py index 4b6ce87b7..3bd053d12 100644 --- a/ironic/openstack/common/config/generator.py +++ b/ironic/openstack/common/config/generator.py @@ -1,6 +1,5 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - # Copyright 2012 SINA Corporation +# Copyright 2014 Cisco Systems, Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -20,6 +19,7 @@ from __future__ import print_function +import argparse import imp import os import re @@ -29,6 +29,7 @@ import textwrap from oslo.config import cfg import six +import stevedore.named from ironic.openstack.common import gettextutils from ironic.openstack.common import importutils @@ -40,6 +41,7 @@ BOOLOPT = "BoolOpt" INTOPT = "IntOpt" FLOATOPT = "FloatOpt" LISTOPT = "ListOpt" +DICTOPT = "DictOpt" MULTISTROPT = "MultiStrOpt" OPT_TYPES = { @@ -48,11 +50,12 @@ OPT_TYPES = { INTOPT: 'integer value', FLOATOPT: 'floating point value', LISTOPT: 'list value', + DICTOPT: 'dict value', MULTISTROPT: 'multi valued', } OPTION_REGEX = re.compile(r"(%s)" % "|".join([STROPT, BOOLOPT, INTOPT, - FLOATOPT, LISTOPT, + FLOATOPT, LISTOPT, DICTOPT, MULTISTROPT])) PY_EXT = ".py" @@ -61,30 +64,54 @@ BASEDIR = os.path.abspath(os.path.join(os.path.dirname(__file__), WORDWRAP_WIDTH = 60 -def generate(srcfiles): +def generate(argv): + parser = argparse.ArgumentParser( + description='generate sample configuration file', + ) + parser.add_argument('-m', dest='modules', action='append') + parser.add_argument('-l', dest='libraries', action='append') + parser.add_argument('srcfiles', nargs='*') + parsed_args = parser.parse_args(argv) + mods_by_pkg = dict() - for filepath in srcfiles: + for filepath in parsed_args.srcfiles: pkg_name = filepath.split(os.sep)[1] mod_str = '.'.join(['.'.join(filepath.split(os.sep)[:-1]), os.path.basename(filepath).split('.')[0]]) mods_by_pkg.setdefault(pkg_name, list()).append(mod_str) # NOTE(lzyeval): place top level modules before packages - pkg_names = filter(lambda x: x.endswith(PY_EXT), mods_by_pkg.keys()) - pkg_names.sort() - ext_names = filter(lambda x: x not in pkg_names, mods_by_pkg.keys()) - ext_names.sort() + pkg_names = sorted(pkg for pkg in mods_by_pkg if pkg.endswith(PY_EXT)) + ext_names = sorted(pkg for pkg in mods_by_pkg if pkg not in pkg_names) pkg_names.extend(ext_names) # opts_by_group is a mapping of group name to an options list # The options list is a list of (module, options) tuples opts_by_group = {'DEFAULT': []} - for module_name in os.getenv( - "IRONIC_CONFIG_GENERATOR_EXTRA_MODULES", "").split(','): - module = _import_module(module_name) - if module: - for group, opts in _list_opts(module): - opts_by_group.setdefault(group, []).append((module_name, opts)) + if parsed_args.modules: + for module_name in parsed_args.modules: + module = _import_module(module_name) + if module: + for group, opts in _list_opts(module): + opts_by_group.setdefault(group, []).append((module_name, + opts)) + + # Look for entry points defined in libraries (or applications) for + # option discovery, and include their return values in the output. + # + # Each entry point should be a function returning an iterable + # of pairs with the group name (or None for the default group) + # and the list of Opt instances for that group. + if parsed_args.libraries: + loader = stevedore.named.NamedExtensionManager( + 'oslo.config.opts', + names=list(set(parsed_args.libraries)), + invoke_on_load=False, + ) + for ext in loader: + for group, opts in ext.plugin(): + opt_list = opts_by_group.setdefault(group or 'DEFAULT', []) + opt_list.append((ext.name, opts)) for pkg_name in pkg_names: mods = mods_by_pkg.get(pkg_name) @@ -101,8 +128,8 @@ def generate(srcfiles): opts_by_group.setdefault(group, []).append((mod_str, opts)) print_group_opts('DEFAULT', opts_by_group.pop('DEFAULT', [])) - for group, opts in opts_by_group.items(): - print_group_opts(group, opts) + for group in sorted(opts_by_group.keys()): + print_group_opts(group, opts_by_group[group]) def _import_module(mod_str): @@ -112,17 +139,17 @@ def _import_module(mod_str): return sys.modules[mod_str[4:]] else: return importutils.import_module(mod_str) - except ImportError as ie: - sys.stderr.write("%s\n" % str(ie)) - return None - except Exception: + except Exception as e: + sys.stderr.write("Error importing module %s: %s\n" % (mod_str, str(e))) return None def _is_in_group(opt, group): "Check if opt is in group." - for key, value in group._opts.items(): - if value['opt'] == opt: + for value in group._opts.values(): + # NOTE(llu): Temporary workaround for bug #1262148, wait until + # newly released oslo.config support '==' operator. + if not(value['opt'] != opt): return True return False @@ -133,7 +160,7 @@ def _guess_groups(opt, mod_obj): return 'DEFAULT' # what other groups is it in? - for key, value in cfg.CONF.items(): + for value in cfg.CONF.values(): if isinstance(value, cfg.CONF.GroupAttr): if _is_in_group(opt, value._group): return value._group.name @@ -202,7 +229,7 @@ def _sanitize_default(name, value): return value.replace(BASEDIR, '') elif value == _get_my_ip(): return '10.0.0.1' - elif value == socket.gethostname() and 'host' in name: + elif value in (socket.gethostname(), socket.getfqdn()) and 'host' in name: return 'ironic' elif value.strip() != value: return '"%s"' % value @@ -220,7 +247,8 @@ def _print_opt(opt): except (ValueError, AttributeError) as err: sys.stderr.write("%s\n" % str(err)) sys.exit(1) - opt_help += ' (' + OPT_TYPES[opt_type] + ')' + opt_help = u'%s (%s)' % (opt_help, + OPT_TYPES[opt_type]) print('#', "\n# ".join(textwrap.wrap(opt_help, WORDWRAP_WIDTH))) if opt.deprecated_opts: for deprecated_opt in opt.deprecated_opts: @@ -250,6 +278,11 @@ def _print_opt(opt): elif opt_type == LISTOPT: assert(isinstance(opt_default, list)) print('#%s=%s' % (opt_name, ','.join(opt_default))) + elif opt_type == DICTOPT: + assert(isinstance(opt_default, dict)) + opt_default_strlist = [str(key) + ':' + str(value) + for (key, value) in opt_default.items()] + print('#%s=%s' % (opt_name, ','.join(opt_default_strlist))) elif opt_type == MULTISTROPT: assert(isinstance(opt_default, list)) if not opt_default: |