Enabling separated sample config file generation

As a common approach most projects used now and Oslo preferred, this
change enabled sample configuration file generation mechanism for
each Glance services.

This change, as an enhancement, allows generating separated sample
configuration files for each Glance major services, e.g.:

    etc/glance-api.conf.sample
    etc/glance-cache.conf.sample
    etc/glance-manage.conf.sample
    etc/glance-registry.conf.sample
    etc/glance-scrubber.conf.sample

It is different than I94d486d6686815c45705a7a9b00fb26062e1eb63
which only supports generating an unified sample configuration
file to including all Glance available options.

This mechanism  not only can help auditing by packager, milestone
maintainer or developer as a function (testenv) of tox, but also
those separated configuration files could make deployment be easy.
And it helps keeping sample configuration files be update with
code change.

The change added "genconfigs" function as a tox testenv (-egenconfigs),
and it dependes on oslo-config-generator function of oslo.config.

The change doesn't introduce those sample files Glance repo, so
next step is to investigate if we can generate them in gate
automatically when a change was merged.

Related-Change-Id: I15686708fc9460948a58cfea3d18dae40ba1fda9
Related-Change-Id: Iae31856d5886ee78786972d80c7c103c3460a2b3
Related-Change-Id: I76043b08e2872867e5af2a5ac902e4d092fda5c8
Closes-Bug: #1300546
Closes-Bug: #1361963

Change-Id: Ibe03a3fe80b96ca32acb1a6bea7e38e6075951bb
Signed-off-by: Zhi Yan Liu <zhiyanl@cn.ibm.com>
This commit is contained in:
Zhi Yan Liu 2014-03-27 17:39:14 +08:00 committed by Zhi Yan Liu
parent 7374d9347e
commit 819f28a0b8
14 changed files with 612 additions and 29 deletions

View File

@ -0,0 +1,8 @@
[DEFAULT]
output_file = etc/glance-api.conf.sample
namespace = glance.api
namespace = glance.store
namespace = oslo.messaging
namespace = oslo.db
namespace = oslo.db.concurrency
namespace = keystoneclient.middleware.auth_token

View File

@ -0,0 +1,3 @@
[DEFAULT]
output_file = etc/glance-cache.conf.sample
namespace = glance.cache

View File

@ -0,0 +1,5 @@
[DEFAULT]
output_file = etc/glance-manage.conf.sample
namespace = glance.manage
namespace = oslo.db
namespace = oslo.db.concurrency

View File

@ -0,0 +1,8 @@
[DEFAULT]
output_file = etc/glance-registry.conf.sample
namespace = glance.registry
namespace = glance.store
namespace = oslo.messaging
namespace = oslo.db
namespace = oslo.db.concurrency
namespace = keystoneclient.middleware.auth_token

View File

@ -0,0 +1,5 @@
[DEFAULT]
output_file = etc/glance-scrubber.conf.sample
namespace = glance.scrubber
namespace = oslo.db
namespace = oslo.db.concurrency

View File

@ -55,19 +55,8 @@ from glance.openstack.common import strutils
LOG = log.getLogger(__name__)
_LW = gettextutils._LW
manager_opts = [
cfg.BoolOpt('db_enforce_mysql_charset',
default=True,
help=_('DEPRECATED. TO BE REMOVED IN THE JUNO RELEASE. '
'Whether or not to enforce that all DB tables have '
'charset utf8. If your database tables do not have '
'charset utf8 you will need to convert before this '
'option is removed. This option is only relevant if '
'your database engine is MySQL.'))
]
CONF = cfg.CONF
CONF.register_opts(manager_opts)
CONF.import_opt('db_enforce_mysql_charset', 'glance.common.config')
# Decorators for actions

View File

@ -42,19 +42,10 @@ CONF = cfg.CONF
def main():
CONF.register_cli_opt(
cfg.BoolOpt('daemon',
short='D',
default=False,
help='Run as a long-running process. When not '
'specified (the default) run the scrub operation '
'once and then exits. When specified do not exit '
'and run scrub on wakeup_time interval as '
'specified in the config.'))
CONF.register_opt(cfg.IntOpt('wakeup_time', default=300))
CONF.register_cli_opts(scrubber.scrubber_cmd_cli_opts)
CONF.register_opts(scrubber.scrubber_cmd_opts)
try:
config.parse_args()
log.setup('glance')

View File

@ -71,6 +71,16 @@ task_opts = [
"can be spun up by the eventlet based task executor to "
"perform execution of Glance tasks.")),
]
manage_opts = [
cfg.BoolOpt('db_enforce_mysql_charset',
default=True,
help=_('DEPRECATED. TO BE REMOVED IN THE JUNO RELEASE. '
'Whether or not to enforce that all DB tables have '
'charset utf8. If your database tables do not have '
'charset utf8 you will need to convert before this '
'option is removed. This option is only relevant if '
'your database engine is MySQL.'))
]
common_opts = [
cfg.BoolOpt('allow_additional_image_properties', default=True,
help=_('Whether to allow users to specify image properties '
@ -141,6 +151,7 @@ CONF = cfg.CONF
CONF.register_opts(paste_deploy_opts, group='paste_deploy')
CONF.register_opts(image_format_opts, group='image_format')
CONF.register_opts(task_opts, group='task')
CONF.register_opts(manage_opts)
CONF.register_opts(common_opts)

160
glance/opts.py Normal file
View File

@ -0,0 +1,160 @@
# Copyright (c) 2014 OpenStack Foundation.
#
# 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.
__all__ = [
'list_api_opts',
'list_registry_opts',
'list_scrubber_opts',
'list_cache_opts',
'list_manage_opts'
]
import copy
import itertools
from glance.openstack.common import gettextutils
# TODO(zhiyan): Remove translation from in-line
# help message of option definition code.
gettextutils.install('glance', lazy=False)
import glance.api.middleware.context
import glance.api.policy
import glance.common.config
import glance.common.location_strategy
import glance.common.location_strategy.store_type
import glance.common.property_utils
import glance.common.rpc
import glance.common.wsgi
import glance.image_cache
import glance.image_cache.drivers.sqlite
import glance.notifier
import glance.openstack.common.lockutils
import glance.openstack.common.log
import glance.registry
import glance.registry.client
import glance.registry.client.v1.api
import glance.scrubber
_global_opt_lists = [
glance.openstack.common.log.common_cli_opts,
glance.openstack.common.log.logging_cli_opts,
]
_api_opts = [
(None, list(itertools.chain(*(_global_opt_lists + [
glance.api.middleware.context.context_opts,
glance.api.policy.policy_opts,
glance.common.config.common_opts,
glance.common.location_strategy.location_strategy_opts,
glance.common.property_utils.property_opts,
glance.common.rpc.rpc_opts,
glance.common.wsgi.bind_opts,
glance.common.wsgi.eventlet_opts,
glance.common.wsgi.socket_opts,
glance.image_cache.drivers.sqlite.sqlite_opts,
glance.image_cache.image_cache_opts,
glance.notifier.notifier_opts,
glance.registry.registry_addr_opts,
glance.registry.client.registry_client_ctx_opts,
glance.registry.client.registry_client_opts,
glance.registry.client.v1.api.registry_client_ctx_opts,
glance.openstack.common.lockutils.util_opts,
glance.scrubber.scrubber_opts])))),
('image_format', glance.common.config.image_format_opts),
('task', glance.common.config.task_opts),
('store_type_location_strategy',
glance.common.location_strategy.store_type.store_type_opts),
('paste_deploy', glance.common.config.paste_deploy_opts)
]
_registry_opts = [
(None, list(itertools.chain(*(_global_opt_lists + [
glance.api.middleware.context.context_opts,
glance.api.policy.policy_opts,
glance.common.config.common_opts,
glance.common.wsgi.bind_opts,
glance.common.wsgi.socket_opts,
glance.common.wsgi.eventlet_opts])))),
('paste_deploy', glance.common.config.paste_deploy_opts)
]
_scrubber_opts = [
(None, list(itertools.chain(*(_global_opt_lists + [
glance.api.policy.policy_opts,
glance.common.config.common_opts,
glance.openstack.common.lockutils.util_opts,
glance.scrubber.scrubber_opts,
glance.scrubber.scrubber_cmd_opts,
glance.scrubber.scrubber_cmd_cli_opts,
glance.registry.client.registry_client_ctx_opts,
glance.registry.registry_addr_opts])))),
]
_cache_opts = [
(None, list(itertools.chain(*(_global_opt_lists + [
glance.api.policy.policy_opts,
glance.common.config.common_opts,
glance.image_cache.drivers.sqlite.sqlite_opts,
glance.image_cache.image_cache_opts,
glance.registry.registry_addr_opts,
glance.registry.client.registry_client_ctx_opts])))),
]
_manage_opts = [
(None, list(itertools.chain(*(_global_opt_lists + [
glance.common.config.manage_opts]))))
]
def list_api_opts():
"""Return a list of oslo.config options available in Glance API service.
Each element of the list is a tuple. The first element is the name of the
group under which the list of elements in the second element will be
registered. A group name of None corresponds to the [DEFAULT] group in
config files.
This function is also discoverable via the 'glance.api' entry point
under the 'oslo.config.opts' namespace.
The purpose of this is to allow tools like the Oslo sample config file
generator to discover the options exposed to users by Glance.
:returns: a list of (group_name, opts) tuples
"""
return [(g, copy.deepcopy(o)) for g, o in _api_opts]
def list_registry_opts():
"""Return a list of oslo.config options available in Glance Registry
service.
"""
return [(g, copy.deepcopy(o)) for g, o in _registry_opts]
def list_scrubber_opts():
"""Return a list of oslo.config options available in Glance Scrubber
service.
"""
return [(g, copy.deepcopy(o)) for g, o in _scrubber_opts]
def list_cache_opts():
"""Return a list of oslo.config options available in Glance Cache
service.
"""
return [(g, copy.deepcopy(o)) for g, o in _cache_opts]
def list_manage_opts():
"""Return a list of oslo.config options available in Glance manage."""
return [(g, copy.deepcopy(o)) for g, o in _manage_opts]

View File

@ -43,17 +43,31 @@ registry_client_ctx_opts = [
help=_('Whether to pass through the user token when '
'making requests to the registry.')),
cfg.StrOpt('admin_user', secret=True,
help=_('The administrators user name.')),
help=_('The administrators user name. '
'If "use_user_token" is not in effect, then '
'admin credentials can be specified.')),
cfg.StrOpt('admin_password', secret=True,
help=_('The administrators password.')),
help=_('The administrators password. '
'If "use_user_token" is not in effect, then '
'admin credentials can be specified.')),
cfg.StrOpt('admin_tenant_name', secret=True,
help=_('The tenant name of the administrative user.')),
help=_('The tenant name of the administrative user. '
'If "use_user_token" is not in effect, then '
'admin tenant name can be specified.')),
cfg.StrOpt('auth_url',
help=_('The URL to the keystone service.')),
help=_('The URL to the keystone service. '
'If "use_user_token" is not in effect and '
'using keystone auth, then URL of keystone '
'can be specified.')),
cfg.StrOpt('auth_strategy', default='noauth',
help=_('The strategy to use for authentication.')),
help=_('The strategy to use for authentication. '
'If "use_user_token" is not in effect, then '
'auth strategy can be specified.')),
cfg.StrOpt('auth_region',
help=_('The region for the authentication service.')),
help=_('The region for the authentication service. '
'If "use_user_token" is not in effect and '
'using keystone auth, then region name can '
'be specified.')),
]
CONF = cfg.CONF

View File

@ -60,6 +60,23 @@ scrubber_opts = [
'this value in order to be candidates for cleanup.'))
]
scrubber_cmd_opts = [
cfg.IntOpt('wakeup_time', default=300,
help=_('Loop time between checking for new '
'items to schedule for delete.'))
]
scrubber_cmd_cli_opts = [
cfg.BoolOpt('daemon',
short='D',
default=False,
help=_('Run as a long-running process. When not '
'specified (the default) run the scrub operation '
'once and then exits. When specified do not exit '
'and run scrub on wakeup_time interval as '
'specified in the config.'))
]
CONF = cfg.CONF
CONF.register_opts(scrubber_opts)
CONF.import_opt('metadata_encryption_key', 'glance.common.config')

View File

@ -0,0 +1,358 @@
# Copyright (c) 2014 OpenStack Foundation.
#
# 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 pkg_resources
from testtools import matchers
from glance import opts
from glance.tests import utils
class OptsTestCase(utils.BaseTestCase):
def _check_opt_groups(self, opt_list, expected_opt_groups):
self.assertThat(opt_list, matchers.HasLength(len(expected_opt_groups)))
groups = [g for (g, _l) in opt_list]
self.assertThat(groups, matchers.HasLength(len(expected_opt_groups)))
for idx, group in enumerate(groups):
self.assertEqual(expected_opt_groups[idx], group)
def _check_opt_names(self, opt_list, expected_opt_names):
opt_names = [o.name for (g, l) in opt_list for o in l]
self.assertThat(opt_names, matchers.HasLength(len(expected_opt_names)))
for opt in opt_names:
self.assertIn(opt, expected_opt_names)
def _test_entry_point(self, namespace,
expected_opt_groups, expected_opt_names):
opt_list = None
for ep in pkg_resources.iter_entry_points('oslo.config.opts'):
if ep.name == namespace:
list_fn = ep.load()
opt_list = list_fn()
break
self.assertIsNotNone(opt_list)
self._check_opt_groups(opt_list, expected_opt_groups)
self._check_opt_names(opt_list, expected_opt_names)
def test_list_api_opts(self):
opt_list = opts.list_api_opts()
expected_opt_groups = [
None,
'image_format',
'task',
'store_type_location_strategy',
'paste_deploy'
]
expected_opt_names = [
'debug',
'verbose',
'log-config-append',
'log-format',
'log-date-format',
'log-file',
'log-dir',
'use-syslog',
'use-syslog-rfc-format',
'syslog-log-facility',
'owner_is_tenant',
'admin_role',
'allow_anonymous_access',
'policy_file',
'policy_default_rule',
'allow_additional_image_properties',
'image_member_quota',
'image_property_quota',
'image_tag_quota',
'image_location_quota',
'data_api',
'limit_param_default',
'api_limit_max',
'show_image_direct_url',
'show_multiple_locations',
'image_size_cap',
'user_storage_quota',
'enable_v1_api',
'enable_v2_api',
'enable_v1_registry',
'enable_v2_registry',
'pydev_worker_debug_host',
'pydev_worker_debug_port',
'metadata_encryption_key',
'location_strategy',
'property_protection_file',
'property_protection_rule_format',
'allowed_rpc_exception_modules',
'bind_host',
'bind_port',
'workers',
'eventlet_hub',
'max_header_line',
'backlog',
'tcp_keepidle',
'ca_file',
'cert_file',
'key_file',
'image_cache_sqlite_db',
'image_cache_driver',
'image_cache_max_size',
'image_cache_stall_time',
'image_cache_dir',
'default_publisher_id',
'registry_host',
'registry_port',
'use_user_token',
'admin_user',
'admin_password',
'admin_tenant_name',
'auth_url',
'auth_strategy',
'auth_region',
'registry_client_protocol',
'registry_client_key_file',
'registry_client_cert_file',
'registry_client_ca_file',
'registry_client_insecure',
'registry_client_timeout',
'send_identity_headers',
'disable_process_locking',
'lock_path',
'scrubber_datadir',
'scrub_time',
'cleanup_scrubber',
'delayed_delete',
'cleanup_scrubber_time',
'container_formats',
'disk_formats',
'task_time_to_live',
'task_executor',
'eventlet_executor_pool_size',
'store_type_preference',
'flavor',
'config_file'
]
self._check_opt_groups(opt_list, expected_opt_groups)
self._check_opt_names(opt_list, expected_opt_names)
self._test_entry_point('glance.api',
expected_opt_groups, expected_opt_names)
def test_list_registry_opts(self):
opt_list = opts.list_registry_opts()
expected_opt_groups = [
None,
'paste_deploy'
]
expected_opt_names = [
'debug',
'verbose',
'log-config-append',
'log-format',
'log-date-format',
'log-file',
'log-dir',
'use-syslog',
'use-syslog-rfc-format',
'syslog-log-facility',
'owner_is_tenant',
'admin_role',
'allow_anonymous_access',
'policy_file',
'policy_default_rule',
'allow_additional_image_properties',
'image_member_quota',
'image_property_quota',
'image_tag_quota',
'image_location_quota',
'data_api',
'limit_param_default',
'api_limit_max',
'show_image_direct_url',
'show_multiple_locations',
'image_size_cap',
'user_storage_quota',
'enable_v1_api',
'enable_v2_api',
'enable_v1_registry',
'enable_v2_registry',
'pydev_worker_debug_host',
'pydev_worker_debug_port',
'metadata_encryption_key',
'bind_host',
'bind_port',
'backlog',
'tcp_keepidle',
'ca_file',
'cert_file',
'key_file',
'workers',
'eventlet_hub',
'max_header_line',
'flavor',
'config_file'
]
self._check_opt_groups(opt_list, expected_opt_groups)
self._check_opt_names(opt_list, expected_opt_names)
self._test_entry_point('glance.registry',
expected_opt_groups, expected_opt_names)
def test_list_scrubber_opts(self):
opt_list = opts.list_scrubber_opts()
expected_opt_groups = [
None
]
expected_opt_names = [
'debug',
'verbose',
'log-config-append',
'log-format',
'log-date-format',
'log-file',
'log-dir',
'use-syslog',
'use-syslog-rfc-format',
'syslog-log-facility',
'policy_file',
'policy_default_rule',
'allow_additional_image_properties',
'image_member_quota',
'image_property_quota',
'image_tag_quota',
'image_location_quota',
'data_api',
'limit_param_default',
'api_limit_max',
'show_image_direct_url',
'show_multiple_locations',
'image_size_cap',
'user_storage_quota',
'enable_v1_api',
'enable_v2_api',
'enable_v1_registry',
'enable_v2_registry',
'pydev_worker_debug_host',
'pydev_worker_debug_port',
'metadata_encryption_key',
'disable_process_locking',
'lock_path',
'scrubber_datadir',
'scrub_time',
'cleanup_scrubber',
'delayed_delete',
'cleanup_scrubber_time',
'wakeup_time',
'daemon',
'use_user_token',
'admin_user',
'admin_password',
'admin_tenant_name',
'auth_url',
'auth_strategy',
'auth_region',
'registry_host',
'registry_port'
]
self._check_opt_groups(opt_list, expected_opt_groups)
self._check_opt_names(opt_list, expected_opt_names)
self._test_entry_point('glance.scrubber',
expected_opt_groups, expected_opt_names)
def test_list_cache_opts(self):
opt_list = opts.list_cache_opts()
expected_opt_groups = [
None
]
expected_opt_names = [
'debug',
'verbose',
'log-config-append',
'log-format',
'log-date-format',
'log-file',
'log-dir',
'use-syslog',
'use-syslog-rfc-format',
'syslog-log-facility',
'policy_file',
'policy_default_rule',
'allow_additional_image_properties',
'image_member_quota',
'image_property_quota',
'image_tag_quota',
'image_location_quota',
'data_api',
'limit_param_default',
'api_limit_max',
'show_image_direct_url',
'show_multiple_locations',
'image_size_cap',
'user_storage_quota',
'enable_v1_api',
'enable_v2_api',
'enable_v1_registry',
'enable_v2_registry',
'pydev_worker_debug_host',
'pydev_worker_debug_port',
'metadata_encryption_key',
'image_cache_sqlite_db',
'image_cache_driver',
'image_cache_max_size',
'image_cache_stall_time',
'image_cache_dir',
'registry_host',
'registry_port',
'use_user_token',
'admin_user',
'admin_password',
'admin_tenant_name',
'auth_url',
'auth_strategy',
'auth_region'
]
self._check_opt_groups(opt_list, expected_opt_groups)
self._check_opt_names(opt_list, expected_opt_names)
self._test_entry_point('glance.cache',
expected_opt_groups, expected_opt_names)
def test_list_manage_opts(self):
opt_list = opts.list_manage_opts()
expected_opt_groups = [
None,
]
expected_opt_names = [
'debug',
'verbose',
'log-config-append',
'log-format',
'log-date-format',
'log-file',
'log-dir',
'use-syslog',
'use-syslog-rfc-format',
'syslog-log-facility',
'db_enforce_mysql_charset'
]
self._check_opt_groups(opt_list, expected_opt_groups)
self._check_opt_names(opt_list, expected_opt_names)
self._test_entry_point('glance.manage',
expected_opt_groups, expected_opt_names)

View File

@ -37,6 +37,12 @@ console_scripts =
glance.common.image_location_strategy.modules =
location_order_strategy = glance.common.location_strategy.location_order
store_type_strategy = glance.common.location_strategy.store_type
oslo.config.opts =
glance.api = glance.opts:list_api_opts
glance.registry = glance.opts:list_registry_opts
glance.scrubber = glance.opts:list_scrubber_opts
glance.cache= glance.opts:list_cache_opts
glance.manage = glance.opts:list_manage_opts
[build_sphinx]
all_files = 1

View File

@ -29,6 +29,14 @@ commands = python setup.py testr --coverage --testr-args='^(?!.*test.*coverage).
[testenv:venv]
commands = {posargs}
[testenv:genconfig]
commands =
oslo-config-generator --config-file etc/oslo-config-generator/glance-api.conf
oslo-config-generator --config-file etc/oslo-config-generator/glance-registry.conf
oslo-config-generator --config-file etc/oslo-config-generator/glance-scrubber.conf
oslo-config-generator --config-file etc/oslo-config-generator/glance-cache.conf
oslo-config-generator --config-file etc/oslo-config-generator/glance-manage.conf
[flake8]
# TODO(dmllr): Analyze or fix the warnings blacklisted below
# E711 comparison to None should be 'if cond is not None:'