From 783e3243f98a90550a8b7ec8ce279709ab8db372 Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Thu, 12 Dec 2013 14:22:49 +0100 Subject: [PATCH] Switch to Oslo's config generator This fixes the sample configuration to contain proper config groups alongway. Regenerate sample config with oslo's config generator. DocImpact: Removes the deprecated memcached_server option from DEFAULT (now in keystone_authtoken group) Closes-Bug: #1206650 Closes-Bug: #1260322 Change-Id: I170715bfe6ec7dad9f7317e7bb56cbb68034c4ec --- cinder/common/config.py | 3 - cinder/openstack/common/config/generator.py | 268 +++++++++++++++ etc/cinder/cinder.conf.sample | 352 +++++++++++++------- openstack-common.conf | 1 + tools/conf/extract_opts.py | 193 ----------- tools/conf/generate_sample.sh | 45 +-- tools/conf/oslo.config.generator.rc | 1 + 7 files changed, 511 insertions(+), 352 deletions(-) create mode 100755 cinder/openstack/common/config/generator.py delete mode 100644 tools/conf/extract_opts.py create mode 100644 tools/conf/oslo.config.generator.rc diff --git a/cinder/common/config.py b/cinder/common/config.py index d3ce0cb35..4e9c6207d 100644 --- a/cinder/common/config.py +++ b/cinder/common/config.py @@ -167,9 +167,6 @@ global_opts = [ 'If this is not set then we use the value from the ' 'storage_availability_zone option as the default ' 'availability_zone for new volumes.'), - cfg.ListOpt('memcached_servers', - default=None, - help='Memcached servers or None for in process cache.'), cfg.StrOpt('default_volume_type', default=None, help='default volume type to use'), diff --git a/cinder/openstack/common/config/generator.py b/cinder/openstack/common/config/generator.py new file mode 100755 index 000000000..f72baab36 --- /dev/null +++ b/cinder/openstack/common/config/generator.py @@ -0,0 +1,268 @@ +# Copyright 2012 SINA Corporation +# 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. +# + +"""Extracts OpenStack config option info from module(s).""" + +from __future__ import print_function + +import imp +import os +import re +import socket +import sys +import textwrap + +from oslo.config import cfg +import six + +from cinder.openstack.common import gettextutils +from cinder.openstack.common import importutils + +gettextutils.install('cinder') + +STROPT = "StrOpt" +BOOLOPT = "BoolOpt" +INTOPT = "IntOpt" +FLOATOPT = "FloatOpt" +LISTOPT = "ListOpt" +MULTISTROPT = "MultiStrOpt" + +OPT_TYPES = { + STROPT: 'string value', + BOOLOPT: 'boolean value', + INTOPT: 'integer value', + FLOATOPT: 'floating point value', + LISTOPT: 'list value', + MULTISTROPT: 'multi valued', +} + +OPTION_REGEX = re.compile(r"(%s)" % "|".join([STROPT, BOOLOPT, INTOPT, + FLOATOPT, LISTOPT, + MULTISTROPT])) + +PY_EXT = ".py" +BASEDIR = os.path.abspath(os.path.join(os.path.dirname(__file__), + "../../../../")) +WORDWRAP_WIDTH = 60 + + +def generate(srcfiles): + mods_by_pkg = dict() + for filepath in 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.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': []} + + extra_modules = os.getenv("OSLO_CONFIG_GENERATOR_EXTRA_MODULES", "") + if extra_modules: + for module_name in extra_modules.split(','): + module_name = module_name.strip() + module = _import_module(module_name) + if module: + for group, opts in _list_opts(module): + opts_by_group.setdefault(group, []).append((module_name, + opts)) + + for pkg_name in pkg_names: + mods = mods_by_pkg.get(pkg_name) + mods.sort() + for mod_str in mods: + if mod_str.endswith('.__init__'): + mod_str = mod_str[:mod_str.rfind(".")] + + mod_obj = _import_module(mod_str) + if not mod_obj: + raise RuntimeError("Unable to import module %s" % mod_str) + + for group, opts in _list_opts(mod_obj): + 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) + + +def _import_module(mod_str): + try: + if mod_str.startswith('bin.'): + imp.load_source(mod_str[4:], os.path.join('bin', mod_str[4:])) + return sys.modules[mod_str[4:]] + else: + return importutils.import_module(mod_str) + 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: + return True + return False + + +def _guess_groups(opt, mod_obj): + # is it in the DEFAULT group? + if _is_in_group(opt, cfg.CONF): + return 'DEFAULT' + + # what other groups is it in? + for key, value in cfg.CONF.items(): + if isinstance(value, cfg.CONF.GroupAttr): + if _is_in_group(opt, value._group): + return value._group.name + + raise RuntimeError( + "Unable to find group for option %s, " + "maybe it's defined twice in the same group?" + % opt.name + ) + + +def _list_opts(obj): + def is_opt(o): + return (isinstance(o, cfg.Opt) and + not isinstance(o, cfg.SubCommandOpt)) + + opts = list() + for attr_str in dir(obj): + attr_obj = getattr(obj, attr_str) + if is_opt(attr_obj): + opts.append(attr_obj) + elif (isinstance(attr_obj, list) and + all(map(lambda x: is_opt(x), attr_obj))): + opts.extend(attr_obj) + + ret = {} + for opt in opts: + ret.setdefault(_guess_groups(opt, obj), []).append(opt) + return ret.items() + + +def print_group_opts(group, opts_by_module): + print("[%s]" % group) + print('') + for mod, opts in opts_by_module: + print('#') + print('# Options defined in %s' % mod) + print('#') + print('') + for opt in opts: + _print_opt(opt) + print('') + + +def _get_my_ip(): + try: + csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + csock.connect(('8.8.8.8', 80)) + (addr, port) = csock.getsockname() + csock.close() + return addr + except socket.error: + return None + + +def _sanitize_default(name, value): + """Set up a reasonably sensible default for pybasedir, my_ip and host.""" + if value.startswith(sys.prefix): + # NOTE(jd) Don't use os.path.join, because it is likely to think the + # second part is an absolute pathname and therefore drop the first + # part. + value = os.path.normpath("/usr/" + value[len(sys.prefix):]) + elif value.startswith(BASEDIR): + return value.replace(BASEDIR, '/usr/lib/python/site-packages') + elif BASEDIR in value: + return value.replace(BASEDIR, '') + elif value == _get_my_ip(): + return '10.0.0.1' + elif value == socket.gethostname() and 'host' in name: + return 'cinder' + elif value.strip() != value: + return '"%s"' % value + return value + + +def _print_opt(opt): + opt_name, opt_default, opt_help = opt.dest, opt.default, opt.help + if not opt_help: + sys.stderr.write('WARNING: "%s" is missing help string.\n' % opt_name) + opt_help = "" + opt_type = None + try: + opt_type = OPTION_REGEX.search(str(type(opt))).group(0) + except (ValueError, AttributeError) as err: + sys.stderr.write("%s\n" % str(err)) + sys.exit(1) + 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: + if deprecated_opt.name: + deprecated_group = (deprecated_opt.group if + deprecated_opt.group else "DEFAULT") + print('# Deprecated group/name - [%s]/%s' % + (deprecated_group, + deprecated_opt.name)) + try: + if opt_default is None: + print('#%s=' % opt_name) + elif opt_type == STROPT: + assert(isinstance(opt_default, six.string_types)) + print('#%s=%s' % (opt_name, _sanitize_default(opt_name, + opt_default))) + elif opt_type == BOOLOPT: + assert(isinstance(opt_default, bool)) + print('#%s=%s' % (opt_name, str(opt_default).lower())) + elif opt_type == INTOPT: + assert(isinstance(opt_default, int) and + not isinstance(opt_default, bool)) + print('#%s=%s' % (opt_name, opt_default)) + elif opt_type == FLOATOPT: + assert(isinstance(opt_default, float)) + print('#%s=%s' % (opt_name, opt_default)) + elif opt_type == LISTOPT: + assert(isinstance(opt_default, list)) + print('#%s=%s' % (opt_name, ','.join(opt_default))) + elif opt_type == MULTISTROPT: + assert(isinstance(opt_default, list)) + if not opt_default: + opt_default = [''] + for default in opt_default: + print('#%s=%s' % (opt_name, default)) + print('') + except Exception: + sys.stderr.write('Error in option "%s"\n' % opt_name) + sys.exit(1) + + +def main(): + generate(sys.argv[1:]) + +if __name__ == '__main__': + main() diff --git a/etc/cinder/cinder.conf.sample b/etc/cinder/cinder.conf.sample index 2b206cee3..415640ba5 100644 --- a/etc/cinder/cinder.conf.sample +++ b/etc/cinder/cinder.conf.sample @@ -1,7 +1,3 @@ -#################### -# cinder.conf sample # -#################### - [DEFAULT] # @@ -127,6 +123,7 @@ # Base URL that will be presented to users in links to the # OpenStack Volume API (string value) +# Deprecated group/name - [DEFAULT]/osapi_compute_link_prefix #osapi_volume_base_URL= @@ -231,6 +228,7 @@ # # Driver to use for backups. (string value) +# Deprecated group/name - [DEFAULT]/backup_service #backup_driver=cinder.backup.drivers.swift @@ -344,9 +342,6 @@ # availability_zone for new volumes. (string value) #default_availability_zone= -# Memcached servers or None for in process cache. (list value) -#memcached_servers= - # default volume type to use (string value) #default_volume_type= @@ -492,76 +487,10 @@ #image_conversion_dir=$state_path/conversion -# -# Options defined in cinder.keymgr -# - -# The full class name of the key manager API class (string -# value) -#api_class=cinder.keymgr.conf_key_mgr.ConfKeyManager - - -# -# Options defined in cinder.keymgr.conf_key_mgr -# - -# Fixed key returned by key manager, specified in hex (string -# value) -#fixed_key= - - -# -# Options defined in cinder.openstack.common.db.api -# - -# The backend to use for db (string value) -#backend=sqlalchemy - -# Enable the experimental use of thread pooling for all DB API -# calls (boolean value) -#use_tpool=false - - # # Options defined in cinder.openstack.common.db.sqlalchemy.session # -# The SQLAlchemy connection string used to connect to the -# database (string value) -#connection=sqlite:////cinder/openstack/common/db/$sqlite_db - -# timeout before idle sql connections are reaped (integer -# value) -#idle_timeout=3600 - -# Minimum number of SQL connections to keep open in a pool -# (integer value) -#min_pool_size=1 - -# Maximum number of SQL connections to keep open in a pool -# (integer value) -#max_pool_size=5 - -# maximum db connection retries during startup. (setting -1 -# implies an infinite retry count) (integer value) -#max_retries=10 - -# interval between retries of opening a sql connection -# (integer value) -#retry_interval=10 - -# If set, use this value for max_overflow with sqlalchemy -# (integer value) -#max_overflow= - -# Verbosity of SQL debugging information. 0=None, -# 100=Everything (integer value) -#connection_debug=0 - -# Add python stack traces to SQL as comment strings (boolean -# value) -#connection_trace=false - # the filename to use with sqlite (string value) #sqlite_db=cinder.sqlite @@ -649,6 +578,7 @@ # configuration to any other existing logging options. Please # see the Python logging module documentation for details on # logging configuration files. (string value) +# Deprecated group/name - [DEFAULT]/log_config #log_config_append= # DEPRECATED. A logging.Formatter log message format string @@ -664,10 +594,12 @@ # (Optional) Name of log file to output to. If no default is # set, logging will go to stdout. (string value) +# Deprecated group/name - [DEFAULT]/logfile #log_file= # (Optional) The base directory used for relative --log-file # paths (string value) +# Deprecated group/name - [DEFAULT]/logdir #log_dir= # Use syslog for logging. (boolean value) @@ -702,14 +634,6 @@ #notification_topics=notifications -# -# Options defined in cinder.openstack.common.notifier.rpc_notifier2 -# - -# AMQP topic(s) used for OpenStack notifications (list value) -#topics=notifications - - # # Options defined in cinder.openstack.common.periodic_task # @@ -762,6 +686,7 @@ #amqp_rpc_single_reply_queue=false # Use durable queues in amqp. (boolean value) +# Deprecated group/name - [DEFAULT]/rabbit_durable_queues #amqp_durable_queues=false # Auto-delete queues in amqp. (boolean value) @@ -915,28 +840,6 @@ #matchmaker_heartbeat_ttl=600 -# -# Options defined in cinder.openstack.common.rpc.matchmaker_redis -# - -# Host to locate redis (string value) -#host=127.0.0.1 - -# Use this port to connect to redis host. (integer value) -#port=6379 - -# Password for Redis server. (optional) (string value) -#password= - - -# -# Options defined in cinder.openstack.common.rpc.matchmaker_ring -# - -# Matchmaker ring file (JSON) (string value) -#ringfile=/etc/oslo/matchmaker_ring.json - - # # Options defined in cinder.scheduler.driver # @@ -1077,6 +980,7 @@ # The maximum number of times to rescan targets to find volume # (integer value) +# Deprecated group/name - [DEFAULT]/num_iscsi_scan_tries #num_volume_device_scan_tries=3 # The backend name for a given driver implementation (string @@ -1840,32 +1744,240 @@ #volume_service_inithost_offload=false +[database] + +# +# Options defined in cinder.openstack.common.db.api +# + +# The backend to use for db (string value) +# Deprecated group/name - [DEFAULT]/db_backend +#backend=sqlalchemy + +# Enable the experimental use of thread pooling for all DB API +# calls (boolean value) +# Deprecated group/name - [DEFAULT]/dbapi_use_tpool +#use_tpool=false + + +# +# Options defined in cinder.openstack.common.db.sqlalchemy.session +# + +# The SQLAlchemy connection string used to connect to the +# database (string value) +# Deprecated group/name - [DEFAULT]/sql_connection +#connection=sqlite:///$state_path/$sqlite_db + +# timeout before idle sql connections are reaped (integer +# value) +# Deprecated group/name - [DEFAULT]/sql_idle_timeout +#idle_timeout=3600 + +# Minimum number of SQL connections to keep open in a pool +# (integer value) +# Deprecated group/name - [DEFAULT]/sql_min_pool_size +#min_pool_size=1 + +# Maximum number of SQL connections to keep open in a pool +# (integer value) +# Deprecated group/name - [DEFAULT]/sql_max_pool_size +#max_pool_size=5 + +# maximum db connection retries during startup. (setting -1 +# implies an infinite retry count) (integer value) +# Deprecated group/name - [DEFAULT]/sql_max_retries +#max_retries=10 + +# interval between retries of opening a sql connection +# (integer value) +# Deprecated group/name - [DEFAULT]/sql_retry_interval +#retry_interval=10 + +# If set, use this value for max_overflow with sqlalchemy +# (integer value) +# Deprecated group/name - [DEFAULT]/sql_max_overflow +#max_overflow= + +# Verbosity of SQL debugging information. 0=None, +# 100=Everything (integer value) +# Deprecated group/name - [DEFAULT]/sql_connection_debug +#connection_debug=0 + +# Add python stack traces to SQL as comment strings (boolean +# value) +# Deprecated group/name - [DEFAULT]/sql_connection_trace +#connection_trace=false + + +[keymgr] + +# +# Options defined in cinder.keymgr +# + +# The full class name of the key manager API class (string +# value) +#api_class=cinder.keymgr.conf_key_mgr.ConfKeyManager + + +# +# Options defined in cinder.keymgr.conf_key_mgr +# + +# Fixed key returned by key manager, specified in hex (string +# value) +#fixed_key= + + +[rpc_notifier2] + +# +# Options defined in cinder.openstack.common.notifier.rpc_notifier2 +# + +# AMQP topic(s) used for OpenStack notifications (list value) +#topics=notifications + + +[matchmaker_redis] + +# +# Options defined in cinder.openstack.common.rpc.matchmaker_redis +# + +# Host to locate redis (string value) +#host=127.0.0.1 + +# Use this port to connect to redis host. (integer value) +#port=6379 + +# Password for Redis server. (optional) (string value) +#password= + + [keystone_authtoken] # -# Options defined in keystoneclient's authtoken middleware +# Options defined in keystoneclient.middleware.auth_token # -# Host providing the admin Identity API endpoint -auth_host = 127.0.0.1 +# Prefix to prepend at the beginning of the path (string +# value) +#auth_admin_prefix= + +# Host providing the admin Identity API endpoint (string +# value) +#auth_host=127.0.0.1 + +# Port of the admin Identity API endpoint (integer value) +#auth_port=35357 + +# Protocol of the admin Identity API endpoint(http or https) +# (string value) +#auth_protocol=https + +# Complete public Identity API endpoint (string value) +#auth_uri= + +# API version of the admin Identity API endpoint (string +# value) +#auth_version= + +# Do not handle authorization requests within the middleware, +# but delegate the authorization decision to downstream WSGI +# components (boolean value) +#delay_auth_decision=false + +# Request timeout value for communicating with Identity API +# server. (boolean value) +#http_connect_timeout= + +# How many times are we trying to reconnect when communicating +# with Identity API Server. (integer value) +#http_request_max_retries=3 -# Port of the admin Identity API endpoint -auth_port = 35357 +# Allows to pass in the name of a fake http_handler callback +# function used instead of httplib.HTTPConnection or +# httplib.HTTPSConnection. Useful for unit testing where +# network is not available. (string value) +#http_handler= -# Protocol of the admin Identity API endpoint -auth_protocol = http +# Single shared secret with the Keystone configuration used +# for bootstrapping a Keystone installation, or otherwise +# bypassing the normal authentication process. (string value) +#admin_token= + +# Keystone account username (string value) +#admin_user= + +# Keystone account password (string value) +#admin_password= # Keystone service account tenant name to validate user tokens -admin_tenant_name = %SERVICE_TENANT_NAME% +# (string value) +#admin_tenant_name=admin + +# Env key for the swift cache (string value) +#cache= + +# Required if Keystone server requires client certificate +# (string value) +#certfile= + +# Required if Keystone server requires client certificate +# (string value) +#keyfile= + +# A PEM encoded Certificate Authority to use when verifying +# HTTPs connections. Defaults to system CAs. (string value) +#cafile= + +# Verify HTTPS connections. (boolean value) +#insecure=false + +# Directory used to cache files related to PKI tokens (string +# value) +#signing_dir= + +# If defined, the memcache server(s) to use for caching (list +# value) +# Deprecated group/name - [DEFAULT]/memcache_servers +#memcached_servers= -# Keystone account username -admin_user = %SERVICE_USER% +# In order to prevent excessive requests and validations, the +# middleware uses an in-memory cache for the tokens the +# Keystone API returns. This is only valid if memcache_servers +# is defined. Set to -1 to disable caching completely. +# (integer value) +#token_cache_time=300 + +# Value only used for unit testing (integer value) +#revocation_cache_time=1 + +# (optional) if defined, indicate whether token data should be +# authenticated or authenticated and encrypted. Acceptable +# values are MAC or ENCRYPT. If MAC, token data is +# authenticated (with HMAC) in the cache. If ENCRYPT, token +# data is encrypted and authenticated in the cache. If the +# value is not one of these options or empty, auth_token will +# raise an exception on initialization. (string value) +#memcache_security_strategy= + +# (optional, mandatory if memcache_security_strategy is +# defined) this string is used for key derivation. (string +# value) +#memcache_secret_key= + + +[matchmaker_ring] + +# +# Options defined in cinder.openstack.common.rpc.matchmaker_ring +# + +# Matchmaker ring file (JSON) (string value) +# Deprecated group/name - [DEFAULT]/matchmaker_ringfile +#ringfile=/etc/oslo/matchmaker_ring.json -# Keystone account password -admin_password = %SERVICE_PASSWORD% -# Directory used to cache files related to PKI tokens -# signing_dir is configurable, but the default behavior of the authtoken -# middleware should be sufficient. It will create a temporary directory -# in the home directory for the user the cinder process is running as. -#signing_dir = /var/lib/cinder/keystone-signing diff --git a/openstack-common.conf b/openstack-common.conf index da7ed46c6..555cd1efe 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -2,6 +2,7 @@ # The list of modules to copy from openstack-common module=context +module=config.generator module=db module=db.sqlalchemy module=excutils diff --git a/tools/conf/extract_opts.py b/tools/conf/extract_opts.py deleted file mode 100644 index 5ff577629..000000000 --- a/tools/conf/extract_opts.py +++ /dev/null @@ -1,193 +0,0 @@ -# Copyright 2012 SINA Corporation -# All Rights Reserved. -# Author: Zhongyue Luo -# -# 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. - -"""Extracts OpenStack config option info from module(s).""" - -from __future__ import print_function - -import __builtin__ -setattr(__builtin__, '_', lambda x: x) -import os -import re -import socket -import sys -import textwrap - -from oslo.config import cfg - -from cinder.openstack.common import importutils - -STROPT = "StrOpt" -BOOLOPT = "BoolOpt" -INTOPT = "IntOpt" -FLOATOPT = "FloatOpt" -LISTOPT = "ListOpt" -MULTISTROPT = "MultiStrOpt" - -OPTION_REGEX = re.compile(r"(%s)" % "|".join([STROPT, BOOLOPT, INTOPT, - FLOATOPT, LISTOPT, - MULTISTROPT])) -OPTION_HELP_INDENT = "####" - -PY_EXT = ".py" -BASEDIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")) -WORDWRAP_WIDTH = 60 - - -def main(srcfiles): - print('\n'.join(['#' * 20, '# cinder.conf sample #', '#' * 20, - '', '[DEFAULT]', ''])) - _list_opts(cfg.ConfigOpts, - cfg.__name__ + ':' + cfg.ConfigOpts.__name__) - mods_by_pkg = dict() - for filepath in 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.extend(ext_names) - for pkg_name in pkg_names: - mods = mods_by_pkg.get(pkg_name) - mods.sort() - for mod_str in mods: - _print_module(mod_str) - - -def _print_module(mod_str): - mod_obj = None - if mod_str.endswith('.__init__'): - mod_str = mod_str[:mod_str.rfind(".")] - try: - mod_obj = importutils.import_module(mod_str) - except Exception as e: - sys.stderr.write("Failed to collect options from module %s: %s\n" % ( - mod_str, str(e))) - return - _list_opts(mod_obj, mod_str) - - -def _list_opts(obj, name): - opts = list() - for attr_str in dir(obj): - attr_obj = getattr(obj, attr_str) - if isinstance(attr_obj, cfg.Opt): - opts.append(attr_obj) - elif (isinstance(attr_obj, list) and - all(map(lambda x: isinstance(x, cfg.Opt), attr_obj))): - opts.extend(attr_obj) - if not opts: - return - print('#') - print('# Options defined in %s' % name) - print('#') - print() - for opt in opts: - _print_opt(opt) - print() - - -def _get_my_ip(): - try: - csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - csock.connect(('8.8.8.8', 80)) - (addr, port) = csock.getsockname() - csock.close() - return addr - except socket.error: - return None - - -MY_IP = _get_my_ip() -HOST = socket.gethostname() - - -def _sanitize_default(s): - """Set up a reasonably sensible default for pybasedir, my_ip and host.""" - if s.startswith(BASEDIR): - return s.replace(BASEDIR, '/usr/lib/python/site-packages') - elif s == MY_IP: - return '10.0.0.1' - elif s == HOST: - return 'cinder' - elif s.strip() != s: - return '"%s"' % s - return s - - -OPT_TYPES = { - 'StrOpt': 'string value', - 'BoolOpt': 'boolean value', - 'IntOpt': 'integer value', - 'FloatOpt': 'floating point value', - 'ListOpt': 'list value', - 'MultiStrOpt': 'multi valued', -} - - -def _print_opt(opt): - opt_name, opt_default, opt_help = opt.dest, opt.default, opt.help - if not opt_help: - sys.stderr.write('WARNING: "%s" is missing help string.\n' % opt_name) - opt_type = None - try: - opt_type = OPTION_REGEX.search(str(type(opt))).group(0) - except (ValueError, AttributeError) as err: - sys.stderr.write("%s\n" % str(err)) - sys.exit(1) - opt_help += ' (' + OPT_TYPES[opt_type] + ')' - print('#', "\n# ".join(textwrap.wrap(opt_help, WORDWRAP_WIDTH))) - try: - if opt_default is None: - print('#%s=' % opt_name) - elif opt_type == STROPT: - assert(isinstance(opt_default, basestring)) - print('#%s=%s' % (opt_name, _sanitize_default(opt_default))) - elif opt_type == BOOLOPT: - assert(isinstance(opt_default, bool)) - print('#%s=%s' % (opt_name, str(opt_default).lower())) - elif opt_type == INTOPT: - assert(isinstance(opt_default, int) and - not isinstance(opt_default, bool)) - print('#%s=%s' % (opt_name, opt_default)) - elif opt_type == FLOATOPT: - assert(isinstance(opt_default, float)) - print('#%s=%s' % (opt_name, opt_default)) - elif opt_type == LISTOPT: - assert(isinstance(opt_default, list)) - print('#%s=%s' % (opt_name, ','.join(opt_default))) - elif opt_type == MULTISTROPT: - assert(isinstance(opt_default, list)) - if opt_default: - for default in opt_default: - print('#%s=%s' % (opt_name, default)) - else: - print('#%s=' % (opt_name)) - print() - except Exception: - sys.stderr.write('Error in option "%s"\n' % opt_name) - sys.exit(1) - - -if __name__ == '__main__': - if len(sys.argv) < 2: - print("usage: python %s [srcfile]...\n" % sys.argv[0]) - sys.exit(0) - main(sys.argv[1:]) diff --git a/tools/conf/generate_sample.sh b/tools/conf/generate_sample.sh index e0f954210..92730798b 100755 --- a/tools/conf/generate_sample.sh +++ b/tools/conf/generate_sample.sh @@ -43,41 +43,14 @@ OUTPUTFILE=$OUTPUTDIR/cinder.conf.sample FILES=$(find cinder -type f -name "*.py" ! -path "cinder/tests/*" -exec \ grep -l "Opt(" {} \; | sort -u) -PYTHONPATH=./:${PYTHONPATH} \ - python $(dirname "$0")/extract_opts.py ${FILES} > \ - $OUTPUTFILE - -# When we use openstack.common.config.generate we won't need this any more -sed -i 's/^#connection=sqlite.*/#connection=sqlite:\/\/\/\/cinder\/openstack\/common\/db\/$sqlite_db/' $OUTPUTFILE - -cat >> $OUTPUTFILE <<-EOF_CAT -[keystone_authtoken] - -# -# Options defined in keystoneclient's authtoken middleware -# - -# Host providing the admin Identity API endpoint -auth_host = 127.0.0.1 - -# Port of the admin Identity API endpoint -auth_port = 35357 - -# Protocol of the admin Identity API endpoint -auth_protocol = http - -# Keystone service account tenant name to validate user tokens -admin_tenant_name = %SERVICE_TENANT_NAME% - -# Keystone account username -admin_user = %SERVICE_USER% +EXTRA_MODULES_FILE="`dirname $0`/oslo.config.generator.rc" +if test -r "$EXTRA_MODULES_FILE" +then + source "$EXTRA_MODULES_FILE" +fi -# Keystone account password -admin_password = %SERVICE_PASSWORD% +export EVENTLET_NO_GREENDNS=yes -# Directory used to cache files related to PKI tokens -# signing_dir is configurable, but the default behavior of the authtoken -# middleware should be sufficient. It will create a temporary directory -# in the home directory for the user the cinder process is running as. -#signing_dir = /var/lib/cinder/keystone-signing -EOF_CAT +PYTHONPATH=./:${PYTHONPATH} \ + python $(dirname "$0")/../../cinder/openstack/common/config/generator.py ${FILES} > \ + $OUTPUTFILE diff --git a/tools/conf/oslo.config.generator.rc b/tools/conf/oslo.config.generator.rc new file mode 100644 index 000000000..a5ee3e619 --- /dev/null +++ b/tools/conf/oslo.config.generator.rc @@ -0,0 +1 @@ +export OSLO_CONFIG_GENERATOR_EXTRA_MODULES=keystoneclient.middleware.auth_token \ No newline at end of file -- 2.45.2