diff --git a/examples/common.py b/examples/common.py index 70ce5af2..11a07566 100755 --- a/examples/common.py +++ b/examples/common.py @@ -119,6 +119,9 @@ class ProfileAction(argparse.Action): @classmethod def set_option(cls, var, values): + if var == '--os-extensions': + cls.prof.load_extension(values) + return if var == 'OS_REGION_NAME': var = 'region' var = var.replace('--os-api-', '') @@ -246,6 +249,15 @@ def option_parser(): default=env('OS_ACCESS_INFO'), help='Access info (Env: OS_ACCESS_INFO)', ) + parser.add_argument( + '--os-extensions', + dest='user_preferences', + metavar='', + action=ProfileAction, + default=ProfileAction.env('OS_EXTENSIONS'), + help='Entry point for namespace for service extensions' + ' env[OS_EXTENSIONS]', + ) parser.add_argument( '--os-api-name', dest='preferences', diff --git a/openstack/module_loader.py b/openstack/module_loader.py index b11f2c11..d99a4965 100644 --- a/openstack/module_loader.py +++ b/openstack/module_loader.py @@ -18,6 +18,19 @@ from stevedore import extension from openstack import exceptions +def load_service_extensions(namespace): + service_extensions = extension.ExtensionManager( + namespace=namespace, + invoke_on_load=True, + ) + services = {} + for service in service_extensions: + service = service.obj + service.set_visibility(None) + services[service.service_type] = service + return services + + class ModuleLoader(object): def __init__(self): diff --git a/openstack/profile.py b/openstack/profile.py index be1db392..6a034e0e 100644 --- a/openstack/profile.py +++ b/openstack/profile.py @@ -51,6 +51,7 @@ The resulting preference print out would look something like:: service_type=identity,region=zion,version=v3 """ +import logging import six from openstack.block_store import block_store_service @@ -63,19 +64,24 @@ from openstack.image import image_service from openstack.key_management import key_management_service from openstack.message import message_service from openstack.metric import metric_service +from openstack import module_loader from openstack.network import network_service from openstack.object_store import object_store_service from openstack.orchestration import orchestration_service from openstack.telemetry import telemetry_service +_logger = logging.getLogger(__name__) + class Profile(object): ALL = "*" """Wildcard service identifier representing all services.""" - def __init__(self): - """Preferences for each service. + def __init__(self, extensions=None): + """User preference for each service. + + :param list extensions: List of entry point namespace to load. Create a new :class:`~openstack.profile.Profile` object with no preferences defined, but knowledge of the services. @@ -129,11 +135,27 @@ class Profile(object): serv.set_visibility(None) self._services[serv.service_type] = serv + if extensions: + for extension in extensions: + self.load_extension(extension) self.service_names = sorted(self._services.keys()) def __repr__(self): return repr(self._preferences) + def load_extension(self, namespace): + """Load a service extension. + + :param str namespace: Entry point namespace + """ + services = module_loader.load_service_extensions(namespace) + for service_type in services: + if service_type in self._services: + _logger.debug("Overriding %s with %s", service_type, + services[service_type]) + self._services[service_type] = services[service_type] + self.service_names = sorted(self._services.keys()) + def get_preference(self, service): """Get a service preference.