'Service Clients provider
Instantiate a `ServiceClients` object, from a set of credentials and an
identity URI. The identity version is inferred from the credentials
object. Optionally auth scope can be provided.
A few parameters can be given a value which is applied as default
for all service clients: region, dscv, ca_certs, trace_requests.
Parameters dscv, ca_certs and trace_requests all apply to the auth
provider as well as any service clients provided by this manager.
Any other client parameter should be set via ClientsRegistry.
Client parameter used to be set via client_parameters, but this is
deprecated, and it is actually already not honoured
anymore: https://launchpad.net/bugs/1680915.
The list of available parameters is defined in the service clients
interfaces. For reference, most clients will accept \'region\',
\'service\', \'endpoint_type\', \'build_timeout\' and \'build_interval\', which
are all inherited from RestClient.
The `config` module in Tempest exposes an helper function
`service_client_config` that can be used to extract from configuration
a dictionary ready to be injected in kwargs.
Exceptions are:
- Token clients for \'identity\' must be given an \'auth_url\' parameter
- Volume client for \'volume\' accepts \'default_volume_size\'
- Servers client from \'compute\' accepts \'enable_instance_password\'
If Tempest configuration is used, parameters will be loaded in the
Registry automatically for all service client (Tempest stable ones
and plugins).
Examples::
identity_params = config.service_client_config(\'identity\')
params = {
\'identity\': identity_params,
\'compute\': {\'region\': \'region2\'}}
manager = lib_manager.Manager(
my_creds, identity_uri, client_parameters=params)
:param credentials: An instance of `auth.Credentials`
:param identity_uri: URI of the identity API. This should be a
mandatory parameter, and it will so soon.
:param region: Default value of region for service clients.
:param scope: default scope for tokens produced by the auth provider
:param disable_ssl_certificate_validation: Applies to auth and to all
service clients.
:param ca_certs: Applies to auth and to all service clients.
:param trace_requests: Applies to auth and to all service clients.
:param client_parameters: Dictionary with parameters for service
clients. Keys of the dictionary are the service client service
name, as declared in `service_clients.available_modules()` except
for the version. Values are dictionaries of parameters that are
going to be passed to all clients in the service client module.'

@removals.removed_kwarg('client_parameters')
def __init__(self, credentials, identity_uri, region=None, scope='project', disable_ssl_certificate_validation=True, ca_certs=None, trace_requests='', client_parameters=None):

    self._registered_services = set([])
    self.credentials = credentials
    self.identity_uri = identity_uri
    if (not identity_uri):
        raise exceptions.InvalidCredentials('ServiceClients    requires    a    non-empty    identity_uri.')
    self.region = region
    if (not self.credentials.is_valid()):
        raise exceptions.InvalidCredentials()
    identity = [(k, auth.IDENTITY_VERSION[k][1]) for k in auth.IDENTITY_VERSION.keys() if isinstance(self.credentials, auth.IDENTITY_VERSION[k][0])]
    if (len(identity) != 1):
        raise exceptions.InvalidCredentials()
    (self.auth_version, auth_provider_class) = identity[0]
    self.dscv = disable_ssl_certificate_validation
    self.ca_certs = ca_certs
    self.trace_requests = trace_requests
    self.auth_provider = auth_provider_class(self.credentials, self.identity_uri, scope=scope, disable_ssl_certificate_validation=self.dscv, ca_certs=self.ca_certs, trace_requests=self.trace_requests)
    client_parameters = (client_parameters or {})
    self.parameters = {}
    all_modules = (available_modules() | _tempest_internal_modules())
    unversioned_services = set([x.split('.')[0] for x in all_modules])
    for service in unversioned_services:
        self.parameters[service] = self._setup_parameters(client_parameters.pop(service, {}))
    if client_parameters:
        raise exceptions.UnknownServiceClient(services=list(client_parameters.keys()))
    clients_registry = ClientsRegistry()
    plugin_service_clients = clients_registry.get_service_clients()
    registration_errors = []
    for plugin in plugin_service_clients:
        service_clients = plugin_service_clients[plugin]
        for service_client in service_clients:
            try:
                self.register_service_client_module(**service_client)
            except Exception:
                registration_errors.append(sys.exc_info())
                LOG.exception('Failed    to    register    service    client    from    plugin    %s    with    parameters    %s', plugin, service_client)
    if registration_errors:
        raise testtools.MultipleExceptions(*registration_errors)
