def _get_microversion_for(self, session, action): """Get microversion to use for the given action. The base version uses :meth:`_get_microversion_for_list`. Subclasses can override this method if more complex logic is needed. :param session: :class`keystoneauth1.adapter.Adapter` :param action: One of "fetch", "commit", "create", "delete", "patch". Unused in the base implementation. :return: microversion as string or ``None`` """ if action not in ('fetch', 'commit', 'create', 'delete', 'patch'): raise ValueError('Invalid action: %s' % action) microversion = self._get_microversion_for_list(session) if action == 'create': # `policy` and `rules` are added with mv=2.64. In it also # `policies` are removed. if utils.supports_microversion(session, '2.64'): if self.policies: if not self.policy and isinstance(self.policies, list): self.policy = self.policies[0] self._body.clean(only={'policies'}) microversion = self._max_microversion else: if self.rules: message = ("API version %s is required to set rules, but " "it is not available.") % 2.64 raise exceptions.NotSupported(message) if self.policy: if not self.policies: self.policies = [self.policy] self._body.clean(only={'policy'}) return microversion
def _make_proxy(self, instance): """Create a Proxy for the service in question. :param instance: The `openstack.connection.Connection` we're working with. """ config = instance.config if not config.has_service(self.service_type): return _ServiceDisabledProxyShim( self.service_type, config.get_disabled_reason(self.service_type)) # First, check to see if we've got config that matches what we # understand in the SDK. version_string = config.get_api_version(self.service_type) endpoint_override = config.get_endpoint(self.service_type) # If the user doesn't give a version in config, but we only support # one version, then just use that version. if not version_string and len(self.supported_versions) == 1: version_string = list(self.supported_versions)[0] proxy_obj = None if endpoint_override and version_string and self.supported_versions: # Both endpoint override and version_string are set, we don't # need to do discovery - just trust the user. proxy_class = self.supported_versions.get(version_string[0]) if proxy_class: proxy_obj = config.get_session_client( self.service_type, constructor=proxy_class, ) else: warnings.warn( "The configured version, {version} for service" " {service_type} is not known or supported by" " openstacksdk. The resulting Proxy object will only" " have direct passthrough REST capabilities.".format( version=version_string, service_type=self.service_type), category=exceptions.UnsupportedServiceVersion) elif endpoint_override and self.supported_versions: temp_adapter = config.get_session_client( self.service_type ) api_version = temp_adapter.get_endpoint_data().api_version proxy_class = self.supported_versions.get(str(api_version[0])) if proxy_class: proxy_obj = config.get_session_client( self.service_type, constructor=proxy_class, ) else: warnings.warn( "Service {service_type} has an endpoint override set" " but the version discovered at that endpoint, {version}" " is not supported by openstacksdk. The resulting Proxy" " object will only have direct passthrough REST" " capabilities.".format( version=api_version, service_type=self.service_type), category=exceptions.UnsupportedServiceVersion) if proxy_obj: if getattr(proxy_obj, 'skip_discovery', False): # Some services, like swift, don't have discovery. While # keystoneauth will behave correctly and handle such # scenarios, it's not super efficient as it involves trying # and falling back a few times. return proxy_obj data = proxy_obj.get_endpoint_data() # If we've gotten here with a proxy object it means we have # an endpoint_override in place. If the catalog_url and # service_url don't match, which can happen if there is a # None plugin and auth.endpoint like with standalone ironic, # we need to be explicit that this service has an endpoint_override # so that subsequent discovery calls don't get made incorrectly. if data.catalog_url != data.service_url: ep_key = '{service_type}_endpoint_override'.format( service_type=self.service_type) config.config[ep_key] = data.service_url proxy_obj = config.get_session_client( self.service_type, constructor=proxy_class, ) return proxy_obj # Make an adapter to let discovery take over version_kwargs = {} if version_string: version_kwargs['version'] = version_string elif self.supported_versions: supported_versions = sorted([ int(f) for f in self.supported_versions]) version_kwargs['min_version'] = str(supported_versions[0]) version_kwargs['max_version'] = '{version}.latest'.format( version=str(supported_versions[-1])) temp_adapter = config.get_session_client( self.service_type, allow_version_hack=True, **version_kwargs ) found_version = temp_adapter.get_api_major_version() if found_version is None: region_name = instance.config.get_region_name(self.service_type) if version_kwargs: raise exceptions.NotSupported( "The {service_type} service for {cloud}:{region_name}" " exists but does not have any supported versions.".format( service_type=self.service_type, cloud=instance.name, region_name=region_name)) else: raise exceptions.NotSupported( "The {service_type} service for {cloud}:{region_name}" " exists but no version was discoverable.".format( service_type=self.service_type, cloud=instance.name, region_name=region_name)) proxy_class = self.supported_versions.get(str(found_version[0])) if not proxy_class: # Maybe openstacksdk is being used for the passthrough # REST API proxy layer for an unknown service in the # service catalog that also doesn't have any useful # version discovery? warnings.warn( "Service {service_type} has no discoverable version." " The resulting Proxy object will only have direct" " passthrough REST capabilities.".format( service_type=self.service_type), category=exceptions.UnsupportedServiceVersion) return temp_adapter proxy_class = self.supported_versions.get(str(found_version[0])) if proxy_class: version_kwargs['constructor'] = proxy_class return config.get_session_client( self.service_type, allow_version_hack=True, **version_kwargs )