Add entry-point for oslo.config options and update registering logic

1. The change exposed all options of store and driver by oslo.config
entry-point.
2. Refactor store and driver options registering logic to leverage this
unified option discover function.

Change-Id: Ibbd0f27abd0c0eb9a88d8d30de1e89264a11f53d
Signed-off-by: Zhi Yan Liu <zhiyanl@cn.ibm.com>
This commit is contained in:
Zhi Yan Liu 2014-09-09 16:24:07 +08:00
parent f607390a3e
commit d6a5dde0ea
4 changed files with 149 additions and 26 deletions

View File

@ -18,14 +18,17 @@ import sys
from oslo.config import cfg
from stevedore import driver
from stevedore import extension
from glance_store import exceptions
from glance_store.i18n import _
from glance_store import i18n
from glance_store import location
LOG = logging.getLogger(__name__)
_ = i18n._
_DEPRECATED_STORE_OPTS = [
cfg.DeprecatedOpt('known_stores', group='DEFAULT'),
cfg.DeprecatedOpt('default_store', group='DEFAULT')
@ -46,33 +49,38 @@ CONF = cfg.CONF
_STORE_CFG_GROUP = 'glance_store'
def _oslo_config_options():
return ((opt, _STORE_CFG_GROUP) for opt in _STORE_OPTS)
def _list_opts():
driver_opts = []
mgr = extension.ExtensionManager('glance_store.drivers')
# NOTE(zhiyan): Handle available drivers entry_points provided
drivers = [ext.name for ext in mgr]
handled_drivers = [] # Used to handle backwards-compatible entries
for store_entry in drivers:
driver_cls = _load_store(None, store_entry, False)
if driver_cls and driver_cls not in handled_drivers:
if getattr(driver_cls, 'OPTIONS', None) is not None:
# NOTE(flaper87): To be removed in k-2. This should
# give deployers enough time to migrate their systems
# and move configs under the new section.
for opt in driver_cls.OPTIONS:
opt.deprecated_opts = [cfg.DeprecatedOpt(opt.name,
group='DEFAULT')]
driver_opts.append(opt)
handled_drivers.append(driver_cls)
# NOTE(zhiyan): This separated approach could list
# store options before all driver ones, which easier
# to read and configure by operator.
return ([(_STORE_CFG_GROUP, _STORE_OPTS)] +
[(_STORE_CFG_GROUP, driver_opts)])
def register_opts(conf):
for opt, group in _oslo_config_options():
conf.register_opt(opt, group=group)
register_store_opts(conf)
def register_store_opts(conf):
for store_entry in set(conf.glance_store.stores):
LOG.debug("Registering options for %s" % store_entry)
store_cls = _load_store(conf, store_entry, False)
if store_cls is None:
msg = _('Store %s not found') % store_entry
raise exceptions.GlanceStoreException(message=msg)
if getattr(store_cls, 'OPTIONS', None) is not None:
# NOTE(flaper87): To be removed in k-2. This should
# give deployers enough time to migrate their systems
# and move configs under the new section.
for opt in store_cls.OPTIONS:
opt.deprecated_opts = [cfg.DeprecatedOpt(opt.name,
group='DEFAULT')]
conf.register_opt(opt, group=_STORE_CFG_GROUP)
opts = _list_opts()
for group, opt_list in opts:
LOG.debug("Registering options for group %s" % group)
for opt in opt_list:
conf.register_opt(opt, group=group)
class Indexable(object):

View File

@ -48,6 +48,9 @@ glance_store.drivers =
glance.store.gridfs.Store = glance_store._drivers.gridfs:Store
glance.store.vmware_datastore.Store = glance_store._drivers.vmware_datastore:Store
oslo.config.opts =
glance.store = glance_store.backend:_list_opts
[build_sphinx]
source-dir = doc/source
build-dir = doc/build

112
tests/unit/test_opts.py Normal file
View File

@ -0,0 +1,112 @@
# Copyright 2014 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.
import pkg_resources
from testtools import matchers
from glance_store import backend
from glance_store.tests import base
class OptsTestCase(base.StoreBaseTest):
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 = backend._list_opts()
expected_opt_groups = ['glance_store', 'glance_store']
expected_opt_names = [
'default_store',
'stores',
'cinder_api_insecure',
'cinder_ca_certificates_file',
'cinder_catalog_info',
'cinder_endpoint_template',
'cinder_http_retries',
'filesystem_store_datadir',
'filesystem_store_datadirs',
'filesystem_store_file_perm',
'filesystem_store_metadata_file',
'mongodb_store_db',
'mongodb_store_uri',
'os_region_name',
'rbd_store_ceph_conf',
'rbd_store_chunk_size',
'rbd_store_pool',
'rbd_store_user',
's3_store_access_key',
's3_store_bucket',
's3_store_bucket_url_format',
's3_store_create_bucket_on_put',
's3_store_host',
's3_store_object_buffer_dir',
's3_store_secret_key',
'swift_enable_snet',
'swift_store_admin_tenants',
'swift_store_auth_insecure',
'swift_store_auth_version',
'swift_store_container',
'swift_store_create_container_on_put',
'swift_store_endpoint_type',
'swift_store_large_object_chunk_size',
'swift_store_large_object_size',
'swift_store_multi_tenant',
'swift_store_region',
'swift_store_retry_get_count',
'swift_store_service_type',
'swift_store_ssl_compression',
'vmware_api_insecure',
'vmware_api_retry_count',
'vmware_datacenter_path',
'vmware_datastore_name',
'vmware_server_host',
'vmware_server_password',
'vmware_server_username',
'vmware_store_image_dir',
'vmware_task_poll_interval'
]
self._check_opt_groups(opt_list, expected_opt_groups)
self._check_opt_names(opt_list, expected_opt_names)
self._test_entry_point('glance.store',
expected_opt_groups, expected_opt_names)

View File

@ -86,7 +86,7 @@ class TestStore(base.StoreBaseTest):
vm_store.Store.CHUNKSIZE = 2
self.config(default_store='vmware', stores=['vmware'])
backend.register_store_opts(self.conf)
backend.register_opts(self.conf)
self.config(group='glance_store',
vmware_server_username='admin',
vmware_server_password='admin',