From 627fde88321b67c8ffbb2062dba7a13912f33a74 Mon Sep 17 00:00:00 2001 From: Markus Zoeller Date: Mon, 21 Dec 2015 14:37:15 +0100 Subject: [PATCH] single point of entry for sample config generation To create a "nova.conf.sample" file, we use "tox -e genconfig". This command triggers the generator from "oslo.config" which needs entry points in "setup.cfg". Right now we have multiple entry points to "opts.py" files which are going to be consolidated to one single point of entry "nova/conf/opts.py". Until all config options are moved to that central place, we would often face merge conflicts when multiple contributors commit patches to that one "opts.py". To prevent that, and to make it easier for future config option moduls in "nova/conf/", the new "nova/conf/opts.py" module collects the config options in a dynamic way. Co-Author: EdLeafe bp centralize-config-options Change-Id: I4e5d643cd93bb2822ff59c71669cedf3de7f86fc --- etc/nova/nova-config-generator.conf | 2 +- nova/compute/opts.py | 3 - nova/conf/compute.py | 2 +- nova/conf/ephemeral_storage.py | 2 +- nova/conf/ironic.py | 2 +- nova/conf/opts.py | 89 +++++++++++++++++++++++++++++ nova/conf/scheduler.py | 8 +++ nova/conf/serial_console.py | 2 +- nova/opts.py | 1 - nova/scheduler/opts.py | 25 -------- nova/virt/opts.py | 1 - setup.cfg | 2 +- 12 files changed, 103 insertions(+), 36 deletions(-) create mode 100644 nova/conf/opts.py delete mode 100644 nova/scheduler/opts.py diff --git a/etc/nova/nova-config-generator.conf b/etc/nova/nova-config-generator.conf index 7495670f24..ce4eee8463 100644 --- a/etc/nova/nova-config-generator.conf +++ b/etc/nova/nova-config-generator.conf @@ -2,12 +2,12 @@ output_file = etc/nova/nova.conf.sample wrap_width = 79 namespace = nova +namespace = nova.conf namespace = nova.api namespace = nova.cells namespace = nova.compute namespace = nova.network namespace = nova.network.neutronv2 -namespace = nova.scheduler namespace = nova.virt namespace = nova.openstack.common.memorycache namespace = oslo.log diff --git a/nova/compute/opts.py b/nova/compute/opts.py index 2450afdc6f..53aaa680df 100644 --- a/nova/compute/opts.py +++ b/nova/compute/opts.py @@ -24,7 +24,6 @@ def list_opts(): return [ ('DEFAULT', itertools.chain( - nova.conf.compute.compute_opts, nova.compute.flavors.flavor_opts, nova.compute.manager.compute_opts, nova.compute.manager.instance_cleaning_opts, @@ -36,8 +35,6 @@ def list_opts(): nova.compute.resource_tracker.allocation_ratio_opts, nova.compute.rpcapi.rpcapi_opts, )), - ('ephemeral_storage_encryption', - nova.conf.ephemeral_storage.ephemeral_storage_encryption_opts), ('upgrade_levels', itertools.chain( [nova.compute.rpcapi.rpcapi_cap_opt], diff --git a/nova/conf/compute.py b/nova/conf/compute.py index 625cb77544..31104fe207 100644 --- a/nova/conf/compute.py +++ b/nova/conf/compute.py @@ -63,4 +63,4 @@ def register_opts(conf): def list_opts(): - return compute_opts + return {'DEFAULT': compute_opts} diff --git a/nova/conf/ephemeral_storage.py b/nova/conf/ephemeral_storage.py index 81b59fa79a..1679d15ef7 100644 --- a/nova/conf/ephemeral_storage.py +++ b/nova/conf/ephemeral_storage.py @@ -45,4 +45,4 @@ def register_opts(conf): def list_opts(): - return ephemeral_storage_encryption_opts + return {'ephemeral_storage_encryption': ephemeral_storage_encryption_opts} diff --git a/nova/conf/ironic.py b/nova/conf/ironic.py index aca6d4d5bd..f3cabffb93 100644 --- a/nova/conf/ironic.py +++ b/nova/conf/ironic.py @@ -95,4 +95,4 @@ def list_opts(): # As soon as this bug is fixed is oslo.config and Nova uses the # version which contains this fix, we can pass in the OptGroup instead # of its name. This allows the generation of the group help too. - return (ironic_group.name, ALL_OPTS) + return {ironic_group.name: ALL_OPTS} diff --git a/nova/conf/opts.py b/nova/conf/opts.py new file mode 100644 index 0000000000..6de56058e0 --- /dev/null +++ b/nova/conf/opts.py @@ -0,0 +1,89 @@ +# Copyright 2015 OpenStack Foundation +# All Rights Reserved. +# +# 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. + +""" +This is the single point of entry to generate the sample configuration +file for Nova. It collects all the necessary info from the other modules +in this package. It is assumed that: +* every other module in this package has a 'list_opts' function which + return a dict where + * the keys are strings which are the group names + * the value of each key is a list of config options for that group +* the nova.conf package doesn't have further packages with config options +* this module is only used in the context of sample file generation +""" + +import collections +import importlib +import os +import pkgutil + +LIST_OPTS_FUNC_NAME = "list_opts" + + +def _tupleize(dct): + """Take the dict of options and convert to the 2-tuple format.""" + return [(key, val) for key, val in dct.items()] + + +def list_opts(): + opts = collections.defaultdict(list) + module_names = _list_module_names() + imported_modules = _import_modules(module_names) + _append_config_options(imported_modules, opts) + return _tupleize(opts) + + +def _list_module_names(): + module_names = [] + package_path = os.path.dirname(os.path.abspath(__file__)) + for _, modname, ispkg in pkgutil.iter_modules(path=[package_path]): + if modname == "opts" or ispkg: + continue + else: + module_names.append(modname) + return module_names + + +def _import_modules(module_names): + imported_modules = [] + for modname in module_names: + mod = importlib.import_module("nova.conf." + modname) + if not hasattr(mod, LIST_OPTS_FUNC_NAME): + msg = "The module 'nova.conf.%s' should have a '%s' "\ + "function which returns the config options." % \ + (LIST_OPTS_FUNC_NAME, modname) + raise Exception(msg) + else: + imported_modules.append(mod) + return imported_modules + + +def _process_old_opts(configs): + """Convert old-style 2-tuple configs to dicts.""" + if isinstance(configs, tuple): + configs = [configs] + return {label: options for label, options in configs} + + +def _append_config_options(imported_modules, config_options): + for mod in imported_modules: + configs = mod.list_opts() + # TODO(markus_z): Remove this compatibility shim once all list_opts() + # functions have been updated to return dicts. + if not isinstance(configs, dict): + configs = _process_old_opts(configs) + for key, val in configs.items(): + config_options[key].extend(val) diff --git a/nova/conf/scheduler.py b/nova/conf/scheduler.py index 0f0db26785..2b6b95c1db 100644 --- a/nova/conf/scheduler.py +++ b/nova/conf/scheduler.py @@ -250,3 +250,11 @@ def register_opts(conf): conf.register_group(trust_group) conf.register_opts(trusted_opts, group=trust_group) conf.register_opts(metrics_weight_opts, group="metrics") + + +def list_opts(): + return {"DEFAULT": SIMPLE_OPTS, + "upgrade_levels": [rpcapi_cap_opt], + "trusted_computing": trusted_opts, + "metrics": metrics_weight_opts, + } diff --git a/nova/conf/serial_console.py b/nova/conf/serial_console.py index 39d6f305b0..f0d7b1cf70 100644 --- a/nova/conf/serial_console.py +++ b/nova/conf/serial_console.py @@ -200,4 +200,4 @@ def list_opts(): # As soon as this bug is fixed is oslo.config and Nova uses the # version which contains this fix, we can pass in the OptGroup instead # of its name. This allows the generation of the group help too. - return (serial_opt_group.name, ALL_OPTS) + return {serial_opt_group.name: ALL_OPTS} diff --git a/nova/opts.py b/nova/opts.py index e1f6bb3f2c..99c79dbd20 100644 --- a/nova/opts.py +++ b/nova/opts.py @@ -116,7 +116,6 @@ def list_opts(): nova.keymgr.keymgr_opts, )), ('rdp', nova.rdp.rdp_opts), - nova.conf.serial_console.list_opts(), ('spice', itertools.chain( nova.cmd.spicehtml5proxy.opts, diff --git a/nova/scheduler/opts.py b/nova/scheduler/opts.py deleted file mode 100644 index 3ca4c62358..0000000000 --- a/nova/scheduler/opts.py +++ /dev/null @@ -1,25 +0,0 @@ -# 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. - -import nova.conf.scheduler - - -def list_opts(): - return [ - ('DEFAULT', - nova.conf.scheduler.SIMPLE_OPTS), - ('metrics', nova.conf.scheduler.metrics_weight_opts), - ('trusted_computing', - nova.conf.scheduler.trusted_opts), - ('upgrade_levels', - [nova.conf.scheduler.rpcapi_cap_opt]), - ] diff --git a/nova/virt/opts.py b/nova/virt/opts.py index 86868c79c9..57beae9094 100644 --- a/nova/virt/opts.py +++ b/nova/virt/opts.py @@ -72,7 +72,6 @@ def list_opts(): nova.virt.hyperv.vmops.hyperv_opts, nova.virt.hyperv.volumeops.hyper_volumeops_opts, )), - nova.conf.ironic.list_opts(), ('libvirt', itertools.chain( nova.virt.libvirt.driver.libvirt_opts, diff --git a/setup.cfg b/setup.cfg index 0535f2d478..f81f9007d3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,12 +27,12 @@ packages = [entry_points] oslo.config.opts = nova = nova.opts:list_opts + nova.conf = nova.conf.opts:list_opts nova.api = nova.api.opts:list_opts nova.cells = nova.cells.opts:list_opts nova.compute = nova.compute.opts:list_opts nova.network = nova.network.opts:list_opts nova.network.neutronv2 = nova.network.neutronv2.api:list_opts - nova.scheduler = nova.scheduler.opts:list_opts nova.virt = nova.virt.opts:list_opts nova.openstack.common.memorycache = nova.openstack.common.memorycache:list_opts