diff --git a/etc/providers.d/openstack-infra.conf b/etc/providers.d/openstack-infra.conf new file mode 100644 index 00000000..d7aefba6 --- /dev/null +++ b/etc/providers.d/openstack-infra.conf @@ -0,0 +1,9 @@ +[provider] +name = OS Infra Provider +description = This provider uses OpenStack's own services (swift, cinder) as storage +id = cf56bd3e-97a7-4078-b6d5-f36246333fd9 +# TODO(yuvalbr) +# bank = swift +# plugin = cinder_backup +# plugin = glance_backup +# plugin = neutron_backup diff --git a/smaug/common/config.py b/smaug/common/config.py index 1460044e..01e5876d 100644 --- a/smaug/common/config.py +++ b/smaug/common/config.py @@ -80,11 +80,6 @@ global_opts = [ cfg.IntOpt('lease_validity_window', default=100, help='validity_window for bank lease, in seconds'), - cfg.ListOpt('enabled_providers', - default=None, - help='A list of provider names to use. These provider names ' - 'should be backed by a unique [CONFIG] group ' - 'with its options'), ] CONF.register_opts(global_opts) diff --git a/smaug/services/protection/bank_plugin.py b/smaug/services/protection/bank_plugin.py index e4b6be7b..e18c5994 100644 --- a/smaug/services/protection/bank_plugin.py +++ b/smaug/services/protection/bank_plugin.py @@ -45,6 +45,9 @@ class LeasePlugin(object): @six.add_metaclass(abc.ABCMeta) class BankPlugin(object): + def __init__(self, config=None): + self._config = config + @abc.abstractmethod def create_object(self, key, value): return diff --git a/smaug/services/protection/bank_plugins/swift_bank_plugin.py b/smaug/services/protection/bank_plugins/swift_bank_plugin.py index bb356444..ca092867 100644 --- a/smaug/services/protection/bank_plugins/swift_bank_plugin.py +++ b/smaug/services/protection/bank_plugins/swift_bank_plugin.py @@ -60,8 +60,6 @@ swift_client_opts = [ 'making SSL connection to Swift.'), ] -CONF = cfg.CONF -CONF.register_opts(swift_client_opts, "swift_client") LOG = logging.getLogger(__name__) @@ -70,19 +68,24 @@ class SwiftConnectionFailed(exception.SmaugException): class SwiftBankPlugin(BankPlugin, LeasePlugin): - def __init__(self, context, object_container): - super(BankPlugin, self).__init__() + def __init__(self, config, context, object_container): + super(SwiftBankPlugin, self).__init__(config) self.context = context - self.swift_retry_attempts = CONF.swift_client.bank_swift_retry_attempts - self.swift_retry_backoff = CONF.swift_client.bank_swift_retry_backoff - self.swift_auth_insecure = CONF.swift_client.bank_swift_auth_insecure - self.swift_ca_cert_file = CONF.swift_client.bank_swift_ca_cert_file - self.lease_expire_window = CONF.lease_expire_window - self.lease_renew_window = CONF.lease_renew_window + self._config.register_opts(swift_client_opts, "swift_client") + self.swift_retry_attempts = \ + self._config.swift_client.bank_swift_retry_attempts + self.swift_retry_backoff = \ + self._config.swift_client.bank_swift_retry_backoff + self.swift_auth_insecure = \ + self._config.swift_client.bank_swift_auth_insecure + self.swift_ca_cert_file = \ + self._config.swift_client.bank_swift_ca_cert_file + self.lease_expire_window = self._config.lease_expire_window + self.lease_renew_window = self._config.lease_renew_window # TODO(luobin): # init lease_validity_window # according to lease_renew_window if not configured - self.lease_validity_window = CONF.lease_validity_window + self.lease_validity_window = self._config.lease_validity_window # TODO(luobin): create a uuid of this bank_plugin self.owner_id = str(uuid.uuid4()) @@ -113,20 +116,20 @@ class SwiftBankPlugin(BankPlugin, LeasePlugin): initial_delay=self.lease_renew_window) def _setup_connection(self): - if CONF.swift_client.bank_swift_auth == "single_user": + if self._config.swift_client.bank_swift_auth == "single_user": connection = swift.Connection( - authurl=CONF.swift_client.bank_swift_auth_url, - auth_version=CONF.swift_client.bank_swift_auth_version, - tenant_name=CONF.swift_client.bank_swift_tenant_name, - user=CONF.swift_client.bank_swift_user, - key=CONF.swift_client.bank_swift_key, + authurl=self._config.swift_client.bank_swift_auth_url, + auth_version=self._config.swift_client.bank_swift_auth_version, + tenant_name=self._config.swift_client.bank_swift_tenant_name, + user=self._config.swift_client.bank_swift_user, + key=self._config.swift_client.bank_swift_key, retries=self.swift_retry_attempts, starting_backoff=self.swift_retry_backoff, insecure=self.swift_auth_insecure, cacert=self.swift_ca_cert_file) else: connection = swift.Connection( - preauthurl=CONF.swift_client.bank_swift_url, + preauthurl=self._config.swift_client.bank_swift_url, preauthtoken=self.context.auth_token, retries=self.swift_retry_attempts, starting_backoff=self.swift_retry_backoff, diff --git a/smaug/services/protection/client_factory.py b/smaug/services/protection/client_factory.py index 8ade901f..51a528ea 100644 --- a/smaug/services/protection/client_factory.py +++ b/smaug/services/protection/client_factory.py @@ -12,6 +12,7 @@ import os +from oslo_config import cfg from oslo_log import log as logging from oslo_utils import importutils from smaug.i18n import _LE @@ -36,11 +37,11 @@ class ClientFactory(object): yield '%s.clients.%s' % (__package__, name) @classmethod - def create_client(cls, service, context): + def create_client(cls, service, context, conf=cfg.CONF): if not cls._factory: cls._factory = {} for module in cls._list_clients(): module = importutils.import_module(module) cls._factory[module.SERVICE] = module - return cls._factory[service].create(context) + return cls._factory[service].create(context, conf) diff --git a/smaug/services/protection/clients/cinder.py b/smaug/services/protection/clients/cinder.py index 7d367dc5..0d2b5be1 100644 --- a/smaug/services/protection/clients/cinder.py +++ b/smaug/services/protection/clients/cinder.py @@ -35,9 +35,10 @@ cfg.CONF.register_opts(cinder_client_opts, group=SERVICE + '_client') CINDERCLIENT_VERSION = '2' -def create(context): +def create(context, conf): + conf.register_opts(cinder_client_opts, group=SERVICE + '_client') try: - url = utils.get_url(SERVICE, context, append_project=True) + url = utils.get_url(SERVICE, context, conf, append_project=True) except Exception: LOG.error(_LE("Get cinder service endpoint url failed.")) raise diff --git a/smaug/services/protection/clients/glance.py b/smaug/services/protection/clients/glance.py index c2c3cadf..932d4277 100644 --- a/smaug/services/protection/clients/glance.py +++ b/smaug/services/protection/clients/glance.py @@ -35,9 +35,10 @@ cfg.CONF.register_opts(glance_client_opts, group=SERVICE + '_client') GLANCECLIENT_VERSION = '2' -def create(context): +def create(context, conf): + conf.register_opts(glance_client_opts, group=SERVICE + '_client') try: - url = utils.get_url(SERVICE, context) + url = utils.get_url(SERVICE, context, conf) except Exception: LOG.error(_LE("Get glance service endpoint url failed")) raise diff --git a/smaug/services/protection/clients/neutron.py b/smaug/services/protection/clients/neutron.py index 67354669..290102a7 100644 --- a/smaug/services/protection/clients/neutron.py +++ b/smaug/services/protection/clients/neutron.py @@ -33,9 +33,10 @@ neutron_client_opts = [ cfg.CONF.register_opts(neutron_client_opts, group=SERVICE + '_client') -def create(context): +def create(context, conf): + conf.register_opts(neutron_client_opts, group=SERVICE + '_client') try: - url = utils.get_url(SERVICE, context) + url = utils.get_url(SERVICE, context, conf) except Exception: LOG.error(_LE("Get neutron service endpoint url failed")) raise diff --git a/smaug/services/protection/clients/nova.py b/smaug/services/protection/clients/nova.py index e567b7cf..ccb89fba 100644 --- a/smaug/services/protection/clients/nova.py +++ b/smaug/services/protection/clients/nova.py @@ -36,9 +36,10 @@ cfg.CONF.register_opts(nova_client_opts, group=SERVICE + '_client') NOVACLIENT_VERSION = '2' -def create(context): +def create(context, conf): + conf.register_opts(nova_client_opts, group=SERVICE + '_client') try: - url = utils.get_url(SERVICE, context, append_project=True) + url = utils.get_url(SERVICE, context, conf, append_project=True) except Exception: LOG.error(_LE("Get nova service endpoint url failed.")) raise diff --git a/smaug/services/protection/protection_plugin.py b/smaug/services/protection/protection_plugin.py index c170a5e0..a6a69b04 100644 --- a/smaug/services/protection/protection_plugin.py +++ b/smaug/services/protection/protection_plugin.py @@ -24,6 +24,8 @@ LOG = logging.getLogger(__name__) @six.add_metaclass(abc.ABCMeta) class ProtectionPlugin(object): + def __init__(self, config=None): + self._config = config @abc.abstractmethod def get_supported_resources_types(self): diff --git a/smaug/services/protection/provider.py b/smaug/services/protection/provider.py index e24c6758..3242a326 100644 --- a/smaug/services/protection/provider.py +++ b/smaug/services/protection/provider.py @@ -10,22 +10,28 @@ # License for the specific language governing permissions and limitations # under the License. +import os from oslo_config import cfg from oslo_log import log as logging -from smaug.common import constants from smaug.i18n import _LE from smaug.services.protection import checkpoint from smaug import utils -provider_opt = [ +provider_opts = [ cfg.MultiStrOpt('plugin', default='', help='plugins to use for protection'), + cfg.StrOpt('bank', + default='', + help='bank plugin to use for storage'), cfg.StrOpt('description', default='', help='the description of provider'), - cfg.StrOpt('provider_id', + cfg.StrOpt('name', + default='', + help='the name of provider'), + cfg.StrOpt('id', default='', help='the provider id') ] @@ -35,13 +41,20 @@ LOG = logging.getLogger(__name__) PROTECTION_NAMESPACE = 'smaug.protections' +CONF.register_opt(cfg.StrOpt('provider_config_dir', + default='providers.d', + help='Configuration directory for providers.' + ' Absolute path, or relative to smaug ' + ' configuration directory.')) + class PluggableProtectionProvider(object): - def __init__(self, provider_id, provider_name, description, plugins): + def __init__(self, provider_config): super(PluggableProtectionProvider, self).__init__() - self._id = provider_id - self._name = provider_name - self._description = description + self._config = provider_config + self._id = self._config.provider.id + self._name = self._config.provider.name + self._description = self._config.provider.description self._extended_info_schema = {'options_schema': {}, 'restore_schema': {}, 'saved_info_schema': {}} @@ -49,12 +62,21 @@ class PluggableProtectionProvider(object): self._bank_plugin = None self._plugin_map = {} - self._load_plugins(plugins=plugins) + if hasattr(self._config.provider, 'bank') \ + and not self._config.provider.bank: + raise ImportError("Empty bank") + self._load_bank(self._config.provider.bank) + if hasattr(self._config.provider, 'plugin'): + for plugin_name in self._config.provider.plugin: + if not plugin_name: + raise ImportError("Empty protection plugin") + self._load_plugin(plugin_name) + if self._bank_plugin: self.checkpoint_collection = checkpoint.CheckpointCollection( self._bank_plugin) else: - LOG.error(_LE('Bank plugin not exist,check your configuration')) + LOG.error(_LE('Bank plugin not exist, check your configuration')) @property def id(self): @@ -72,27 +94,43 @@ class PluggableProtectionProvider(object): def extended_info_schema(self): return self._extended_info_schema - def _load_plugins(self, plugins): - for plugin_name in plugins: - try: - plugin = utils.load_plugin(PROTECTION_NAMESPACE, plugin_name) - except Exception: - LOG.exception(_LE("Load protection plugin: %s failed."), - plugin_name) - raise - else: - self._plugin_map[plugin_name] = plugin - if constants.PLUGIN_BANK in plugin_name.lower(): - self._bank_plugin = plugin + @property + def bank(self): + return self._bank_plugin + + @property + def plugins(self): + return self._plugin_map + + def _load_bank(self, bank_name): + try: + plugin = utils.load_plugin(PROTECTION_NAMESPACE, bank_name, + self._config) + except Exception: + LOG.error(_LE("Load bank plugin: '%s' failed."), bank_name) + raise + else: + self._bank_plugin = plugin + + def _load_plugin(self, plugin_name): + try: + plugin = utils.load_plugin(PROTECTION_NAMESPACE, plugin_name, + self._config) + except Exception: + LOG.error(_LE("Load protection plugin: '%s' failed."), plugin_name) + raise + else: + self._plugin_map[plugin_name] = plugin + for resource in plugin.get_supported_resources_types(): if hasattr(plugin, 'get_options_schema'): - self._extended_info_schema['options_schema'][plugin_name] \ - = plugin.get_options_schema() + self._extended_info_schema['options_schema'][resource] \ + = plugin.get_options_schema(resource) if hasattr(plugin, 'get_restore_schema'): - self._extended_info_schema['restore_schema'][plugin_name] \ - = plugin.get_restore_schema() + self._extended_info_schema['restore_schema'][resource] \ + = plugin.get_restore_schema(resource) if hasattr(plugin, 'get_saved_info_schema'): - self._extended_info_schema['saved_info_schema'][plugin_name] \ - = plugin.get_saved_info_schema() + self._extended_info_schema['saved_info_schema'][resource] \ + = plugin.get_saved_info_schema(resource) def get_checkpoint_collection(self): return self.checkpoint_collection @@ -109,51 +147,29 @@ class ProviderRegistry(object): self._load_providers() def _load_providers(self): - """load provider + """load provider""" + config_dir = utils.find_config(CONF.provider_config_dir) - smaug.conf example: - [default] - enabled_providers=provider1,provider2 - [provider1] - provider_id='' configured by admin - plugin=BANK define in setup.cfg - plugin=VolumeProtectionPlugin define in setup.cfg - description='the description of provider1' - [provider2] - provider_id='' configured by admin - plugin=BANK define in setup.cfg - plugin=VolumeProtectionPlugin define in setup.cfg - plugin=ServerProtectionPlugin define in setup.cfg - description='the description of provider2' - """ - if CONF.enabled_providers: - for provider_name in CONF.enabled_providers: - CONF.register_opts(provider_opt, group=provider_name) - plugins = getattr(CONF, provider_name).plugin - description = getattr(CONF, provider_name).description - provider_id = getattr(CONF, provider_name).provider_id - if not all([plugins, provider_id]): - LOG.error(_LE("Invalid provider:%s,check provider" - " configuration"), - provider_name) - continue - try: - provider = PluggableProtectionProvider(provider_id, - provider_name, - description, - plugins) - except Exception: - LOG.exception(_LE("Load provider: %s failed."), - provider_name) - else: - self.providers[provider_id] = provider + for config_file in os.listdir(config_dir): + if not config_file.endswith('.conf'): + continue + config_path = os.path.abspath(os.path.join(config_dir, + config_file)) + provider_config = cfg.ConfigOpts() + provider_config(args=['--config-file=' + config_path]) + provider_config.register_opts(provider_opts, 'provider') + try: + provider = PluggableProtectionProvider(provider_config) + except Exception: + LOG.error(_LE("Load provider: %s failed."), + provider_config.provider.name) + else: + self.providers[provider.id] = provider - def list_providers(self, list_option=None): - if not list_option: - return [dict(id=provider.id, name=provider.name, - description=provider.description) - for provider in self.providers.values()] - # It seems that we don't need list_option + def list_providers(self): + return [dict(id=provider.id, name=provider.name, + description=provider.description) + for provider in self.providers.values()] def show_provider(self, provider_id): return self.providers.get(provider_id, None) diff --git a/smaug/services/protection/utils.py b/smaug/services/protection/utils.py index 1f86070b..ef0c7024 100644 --- a/smaug/services/protection/utils.py +++ b/smaug/services/protection/utils.py @@ -10,7 +10,6 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo_config import cfg from smaug import exception from smaug.i18n import _ @@ -39,9 +38,9 @@ def _parse_service_endpoint(endpoint_url, context, append_project=False): else endpoint_url -def get_url(service, context, append_project=False): +def get_url(service, context, conf, append_project=False): '''Return the url of given service endpoint.''' - client_conf = getattr(cfg.CONF, service + '_client') + client_conf = getattr(conf, service + '_client') endpoint = getattr(client_conf, service + '_endpoint') if endpoint is not None: diff --git a/smaug/tests/unit/clients/test_cinder_client.py b/smaug/tests/unit/clients/test_cinder_client.py index 24a27d8e..c4a622f8 100644 --- a/smaug/tests/unit/clients/test_cinder_client.py +++ b/smaug/tests/unit/clients/test_cinder_client.py @@ -35,13 +35,13 @@ class CinderClientTest(base.TestCase): cfg.CONF.set_default('cinder_endpoint', 'http://127.0.0.1:8776/v2', 'cinder_client') - client = cinder.create(self._context) + client = cinder.create(self._context, cfg.CONF) self.assertEqual('volumev2', client.client.service_type) self.assertEqual('http://127.0.0.1:8776/v2/abcd', client.client.management_url) def test_create_client_by_catalog(self): - client = cinder.create(self._context) + client = cinder.create(self._context, cfg.CONF) self.assertEqual('volumev2', client.client.service_type) self.assertEqual('http://127.0.0.1:8776/v2/abcd', client.client.management_url) diff --git a/smaug/tests/unit/clients/test_glance_client.py b/smaug/tests/unit/clients/test_glance_client.py index 9b868270..e98bff86 100644 --- a/smaug/tests/unit/clients/test_glance_client.py +++ b/smaug/tests/unit/clients/test_glance_client.py @@ -40,9 +40,9 @@ class GlanceClientTest(base.TestCase): cfg.CONF.set_default('glance_endpoint', 'http://127.0.0.1:9292', 'glance_client') - gc = glance.create(self._context) + gc = glance.create(self._context, cfg.CONF) self.assertEqual('http://127.0.0.1:9292', gc.http_client.endpoint) def test_create_client_by_catalog(self): - gc = glance.create(self._context) + gc = glance.create(self._context, cfg.CONF) self.assertEqual('http://127.0.0.1:9292', gc.http_client.endpoint) diff --git a/smaug/tests/unit/clients/test_neutron_client.py b/smaug/tests/unit/clients/test_neutron_client.py index 4d468e80..b3248c4b 100644 --- a/smaug/tests/unit/clients/test_neutron_client.py +++ b/smaug/tests/unit/clients/test_neutron_client.py @@ -40,9 +40,9 @@ class NeutronClientTest(base.TestCase): cfg.CONF.set_default('neutron_endpoint', 'http://127.0.0.1:9696', 'neutron_client') - nc = neutron.create(self._context) + nc = neutron.create(self._context, cfg.CONF) self.assertEqual('http://127.0.0.1:9696', nc.httpclient.endpoint_url) def test_create_client_by_catalog(self): - nc = neutron.create(self._context) + nc = neutron.create(self._context, cfg.CONF) self.assertEqual('http://127.0.0.1:9696', nc.httpclient.endpoint_url) diff --git a/smaug/tests/unit/clients/test_nova_client.py b/smaug/tests/unit/clients/test_nova_client.py index 573cdad5..95878d96 100644 --- a/smaug/tests/unit/clients/test_nova_client.py +++ b/smaug/tests/unit/clients/test_nova_client.py @@ -35,13 +35,13 @@ class NovaClientTest(base.TestCase): cfg.CONF.set_default('nova_endpoint', 'http://127.0.0.1:8774/v2.1', 'nova_client') - client = nova.create(self._context) + client = nova.create(self._context, cfg.CONF) self.assertEqual('compute', client.client.service_type) self.assertEqual('http://127.0.0.1:8774/v2.1/abcd', client.client.management_url) def test_create_client_by_catalog(self): - client = nova.create(self._context) + client = nova.create(self._context, cfg.CONF) self.assertEqual('compute', client.client.service_type) self.assertEqual('http://127.0.0.1:8774/v2.1/abcd', client.client.management_url) diff --git a/smaug/tests/unit/conf_fixture.py b/smaug/tests/unit/conf_fixture.py index 79587a84..1f9bbc89 100644 --- a/smaug/tests/unit/conf_fixture.py +++ b/smaug/tests/unit/conf_fixture.py @@ -28,3 +28,5 @@ def set_defaults(conf): conf.set_default('auth_strategy', 'noauth') conf.set_default('state_path', os.path.abspath( os.path.join(os.path.dirname(__file__), '..', '..', '..'))) + conf.set_default('provider_config_dir', + os.path.join(os.path.dirname(__file__), 'fake_providers')) diff --git a/smaug/tests/unit/fake_bank.py b/smaug/tests/unit/fake_bank.py new file mode 100644 index 00000000..57ff6b49 --- /dev/null +++ b/smaug/tests/unit/fake_bank.py @@ -0,0 +1,40 @@ +# 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. + +from oslo_config import cfg + +from smaug.services.protection import bank_plugin + +fake_bank_opts = [ + cfg.StrOpt('fake_host'), +] + + +class FakeBankPlugin(bank_plugin.BankPlugin): + def __init__(self, config=None): + super(FakeBankPlugin, self).__init__(config) + config.register_opts(fake_bank_opts, 'fake_bank') + + def create_object(self, key, value): + return + + def update_object(self, key, value): + return + + def get_object(self, key): + return + + def list_objects(self, prefix=None, limit=None, marker=None): + return + + def delete_object(self, key): + return diff --git a/smaug/tests/unit/fake_protection.py b/smaug/tests/unit/fake_protection.py new file mode 100644 index 00000000..574a9f7d --- /dev/null +++ b/smaug/tests/unit/fake_protection.py @@ -0,0 +1,49 @@ +# 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. + +from oslo_config import cfg + +from smaug.services.protection import protection_plugin + +fake_plugin_opts = [ + cfg.StrOpt('fake_user'), +] + + +class FakeProtectionPlugin(protection_plugin.ProtectionPlugin): + def __init__(self, config=None): + super(FakeProtectionPlugin, self).__init__(config) + config.register_opts(fake_plugin_opts, 'fake_plugin') + + def get_supported_resources_types(self): + return ['Test::Resource'] + + def get_options_schema(self, resource_type): + return [] + + def get_saved_info_schema(self, resource_type): + return [] + + def get_restore_schema(self, resource_type): + return [] + + def get_saved_info(self, metadata_store, resource): + pass + + def get_protection_stats(self, protection_id): + pass + + def on_resource_start(self, context): + pass + + def on_resource_end(self, context): + pass diff --git a/smaug/tests/unit/fake_providers/fake_provider1.conf b/smaug/tests/unit/fake_providers/fake_provider1.conf new file mode 100644 index 00000000..f2a4d6d0 --- /dev/null +++ b/smaug/tests/unit/fake_providers/fake_provider1.conf @@ -0,0 +1,12 @@ +[provider] +name = fake_provider1 +id = fake_id1 +description = Test Provider 1 +bank = smaug.tests.unit.fake_bank.FakeBankPlugin +plugin = smaug.tests.unit.fake_protection.FakeProtectionPlugin + +[fake_plugin] +fake_user = user + +[fake_bank] +fake_host = thor diff --git a/smaug/tests/unit/fake_providers/fake_provider2.conf b/smaug/tests/unit/fake_providers/fake_provider2.conf new file mode 100644 index 00000000..273ba599 --- /dev/null +++ b/smaug/tests/unit/fake_providers/fake_provider2.conf @@ -0,0 +1,4 @@ +[provider] +name = fake_provider2 +id = fake_id2 +description = Test Provider 2 diff --git a/smaug/tests/unit/protection/test_provider.py b/smaug/tests/unit/protection/test_provider.py index c2958ad5..44c5a3c9 100644 --- a/smaug/tests/unit/protection/test_provider.py +++ b/smaug/tests/unit/protection/test_provider.py @@ -1,85 +1,58 @@ -# 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 mock -from oslo_config import cfg -from smaug.services.protection import provider -from smaug.tests import base - -provider_opt = [ - cfg.MultiStrOpt('plugin', - default='', - help='plugins to use for protection'), - cfg.StrOpt('description', - default='', - help='the description of provider'), - cfg.StrOpt('provider_id', - default='', - help='the provider id') -] -CONF = cfg.CONF - - -class ProviderRegistryTest(base.TestCase): - def setUp(self): - super(ProviderRegistryTest, self).setUp() - CONF.set_override('enabled_providers', - ['provider1', 'provider2']) - CONF.register_opts(provider_opt, group='provider1') - CONF.register_opts(provider_opt, group='provider2') - CONF.set_override('plugin', ['SERVER', 'VOLUME'], - group='provider1') - CONF.set_override('plugin', ['SERVER'], - group='provider2') - CONF.set_override('description', 'FAKE1', group='provider1') - CONF.set_override('description', 'FAKE2', group='provider2') - CONF.set_override('provider_id', 'id1', group='provider1') - CONF.set_override('provider_id', 'id2', group='provider2') - - @mock.patch.object(provider.PluggableProtectionProvider, '_load_plugins') - def test_load_providers(self, mock_load_plugins): - CONF.set_override('plugin', ['SERVER'], - group='provider2') - pr = provider.ProviderRegistry() - self.assertTrue(mock_load_plugins.called) - self.assertEqual(len(pr.providers), 2) - - @mock.patch.object(provider.PluggableProtectionProvider, '_load_plugins') - def test_load_providers_with_no_plugins(self, mock_load_plugins): - CONF.set_override('plugin', None, - group='provider2') - pr = provider.ProviderRegistry() - self.assertEqual(mock_load_plugins.call_count, 1) - self.assertEqual(len(pr.providers), 1) - - @mock.patch.object(provider.PluggableProtectionProvider, '_load_plugins') - def test_list_provider(self, mock_load_plugins): - CONF.set_override('plugin', ['SERVER'], - group='provider2') - pr = provider.ProviderRegistry() - self.assertEqual(2, len(pr.list_providers())) - - @mock.patch.object(provider.PluggableProtectionProvider, '_load_plugins') - def test_show_provider(self, mock_load_plugins): - CONF.set_override('plugin', ['SERVER'], - group='provider2') - pr = provider.ProviderRegistry() - provider_list = pr.list_providers() - for provider_node in provider_list: - self.assertTrue(pr.show_provider(provider_node['id'])) - - def tearDown(self): - CONF.register_opts(provider_opt, group='provider1') - CONF.register_opts(provider_opt, group='provider2') - CONF.set_override('enabled_providers', - None) - super(ProviderRegistryTest, self).tearDown() +# 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 mock + +from oslo_config import cfg +from smaug.services.protection import provider +from smaug.tests import base + +CONF = cfg.CONF + + +class ProviderRegistryTest(base.TestCase): + def setUp(self): + super(ProviderRegistryTest, self).setUp() + + @mock.patch.object(provider.PluggableProtectionProvider, '_load_bank') + @mock.patch.object(provider.PluggableProtectionProvider, '_load_plugin') + def test_load_providers(self, mock_load_bank, mock_load_plugin): + pr = provider.ProviderRegistry() + self.assertEqual(mock_load_plugin.call_count, 1) + self.assertEqual(mock_load_bank.call_count, 1) + self.assertEqual(len(pr.providers), 1) + + self.assertEqual(pr.providers['fake_id1'].name, 'fake_provider1') + self.assertNotIn('fake_provider2', pr.providers) + + def test_provider_bank_config(self): + pr = provider.ProviderRegistry() + provider1 = pr.show_provider('fake_id1') + self.assertEqual(provider1.bank._config.fake_bank.fake_host, 'thor') + + def test_provider_plugin_config(self): + pr = provider.ProviderRegistry() + provider1 = pr.show_provider('fake_id1') + plugin_name = 'smaug.tests.unit.fake_protection.FakeProtectionPlugin' + self.assertEqual( + provider1.plugins[plugin_name]._config.fake_plugin.fake_user, + 'user') + + def test_list_provider(self): + pr = provider.ProviderRegistry() + self.assertEqual(1, len(pr.list_providers())) + + def test_show_provider(self): + pr = provider.ProviderRegistry() + provider_list = pr.list_providers() + for provider_node in provider_list: + self.assertTrue(pr.show_provider(provider_node['id'])) diff --git a/smaug/tests/unit/protection/test_swift_bank_plugin.py b/smaug/tests/unit/protection/test_swift_bank_plugin.py index 6e7a0c98..122d13f2 100644 --- a/smaug/tests/unit/protection/test_swift_bank_plugin.py +++ b/smaug/tests/unit/protection/test_swift_bank_plugin.py @@ -41,7 +41,7 @@ class SwiftBankPluginTest(base.TestCase): import_str=import_str) swift.Connection = mock.MagicMock() swift.Connection.return_value = self.fake_connection - self.swift_bank_plugin = swift_bank_plugin_cls(None, + self.swift_bank_plugin = swift_bank_plugin_cls(CONF, None, self.object_container) def test_acquire_lease(self): diff --git a/smaug/utils.py b/smaug/utils.py index 81ddddc3..ec49d45f 100644 --- a/smaug/utils.py +++ b/smaug/utils.py @@ -125,7 +125,7 @@ def get_bool_param(param_string, params): return strutils.bool_from_string(param, strict=True) -def load_plugin(namespace, plugin_name): +def load_plugin(namespace, plugin_name, *args, **kwargs): try: # Try to resolve plugin by name mgr = driver.DriverManager(namespace, plugin_name) @@ -138,4 +138,4 @@ def load_plugin(namespace, plugin_name): LOG.exception(_LE("Error loading plugin by name, %s"), e1) LOG.exception(_LE("Error loading plugin by class, %s"), e2) raise ImportError(_("Class not found.")) - return plugin_class() + return plugin_class(*args, **kwargs)