Exemple #1
0
    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
Exemple #2
0
    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
        )