コード例 #1
0
    def url_for(self, **kwargs):
        kwargs.setdefault('interface', 'public')
        kwargs.setdefault('service_type', None)

        if kwargs['service_type'] == 'object-store':
            return self.storage_url

        # Although our "catalog" includes an identity entry, nothing that uses
        # url_for() (including `openstack endpoint list`) will know what to do
        # with it. Better to just raise the exception, cribbing error messages
        # from keystoneauth1/access/service_catalog.py

        if 'service_name' in kwargs and 'region_name' in kwargs:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'named %(service_name)s in %(region_name)s region not '
                   'found' % kwargs)
        elif 'service_name' in kwargs:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'named %(service_name)s not found' % kwargs)
        elif 'region_name' in kwargs:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'in %(region_name)s region not found' % kwargs)
        else:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'not found' % kwargs)

        raise exceptions.EndpointNotFound(msg)
コード例 #2
0
    def url_for(self, service_type=None, interface='public',
                region_name=None, service_name=None,
                service_id=None, endpoint_id=None):
        """Fetch an endpoint from the service catalog.

        Fetch the specified endpoint from the service catalog for
        a particular endpoint attribute. If no attribute is given, return
        the first endpoint of the specified type.

        Valid endpoint types: `public` or `publicURL`,
                              `internal` or `internalURL`,
                              `admin` or 'adminURL`

        :param string service_type: Service type of the endpoint.
        :param string interface: Type of endpoint.
        :param string region_name: Region of the endpoint.
        :param string service_name: The assigned name of the service.
        :param string service_id: The identifier of a service.
        :param string endpoint_id: The identifier of an endpoint.
        """
        if not self._catalog:
            raise exceptions.EmptyCatalog('The service catalog is empty.')

        urls = self.get_urls(service_type=service_type,
                             interface=interface,
                             region_name=region_name,
                             service_name=service_name,
                             service_id=service_id,
                             endpoint_id=endpoint_id)

        try:
            return urls[0]
        except Exception:
            pass

        if service_name and region_name:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'named %(service_name)s in %(region_name)s region not '
                   'found' %
                   {'interface': interface,
                    'service_type': service_type, 'service_name': service_name,
                    'region_name': region_name})
        elif service_name:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'named %(service_name)s not found' %
                   {'interface': interface,
                    'service_type': service_type,
                    'service_name': service_name})
        elif region_name:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'in %(region_name)s region not found' %
                   {'interface': interface,
                    'service_type': service_type, 'region_name': region_name})
        else:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'not found' %
                   {'interface': interface,
                    'service_type': service_type})

        raise exceptions.EndpointNotFound(msg)
コード例 #3
0
ファイル: client_plugin.py プロジェクト: gfidente/heat
    def url_for(self, **kwargs):
        keystone_session = self.context.keystone_session

        def get_endpoint():
            return keystone_session.get_endpoint(**kwargs)

        # NOTE(jamielennox): use the session defined by the keystoneclient
        # options as traditionally the token was always retrieved from
        # keystoneclient.
        try:
            kwargs.setdefault('interface', kwargs.pop('endpoint_type'))
        except KeyError:
            pass

        reg = self.context.region_name or cfg.CONF.region_name_for_services
        kwargs.setdefault('region_name', reg)
        url = None
        try:
            url = get_endpoint()
        except exceptions.EmptyCatalog:
            endpoint = keystone_session.get_endpoint(
                None, interface=plugin.AUTH_INTERFACE)
            token = keystone_session.get_token(None)
            token_obj = generic.Token(endpoint, token)
            auth_ref = token_obj.get_access(keystone_session)
            if auth_ref.has_service_catalog():
                self.context.reload_auth_plugin()
                url = get_endpoint()

        # NOTE(jamielennox): raising exception maintains compatibility with
        # older keystoneclient service catalog searching.
        if url is None:
            raise exceptions.EndpointNotFound()

        return url
コード例 #4
0
    def test_check_cinder_exists(self, mock_url_for):
        mock_url_for.return_value = None
        self.assertTrue(cinder.check_cinder_exists())

        mock_url_for.reset_mock()

        mock_url_for.side_effect = keystone_exceptions.EndpointNotFound()
        self.assertFalse(cinder.check_cinder_exists())
コード例 #5
0
    def test_endpoint_not_found(self):
        self.session.get_endpoint.side_effect = exceptions.EndpointNotFound()
        self.assertRaises(http.EndpointNotFound, self.get_client)

        self.session.get_endpoint.assert_called_once_with(
            service_type='baremetal-introspection',
            interface=None,
            region_name=None)
コード例 #6
0
ファイル: test_keystone.py プロジェクト: cskimura/ironic
 def test_get_service_url_internal_fail(self):
     session = mock.Mock()
     session.get_endpoint.side_effect = [ksexception.EndpointNotFound(),
                                         'spam']
     params = {'ham': 'eggs'}
     self.assertEqual('spam', keystone.get_service_url(session, **params))
     session.get_endpoint.assert_has_calls([
         mock.call(interface='internal', **params),
         mock.call(interface='public', **params)])
コード例 #7
0
def _get_identity_endpoint_from_sc(context):
    # Search for the identity endpoint in the service catalog
    for service in context.service_catalog:
        if service.get('type') != 'identity':
            continue
        for endpoint in service['endpoints']:
            if (not CONF[NOVA_GROUP].region_name
                    or endpoint.get('region') == CONF[NOVA_GROUP].region_name):
                return endpoint.get(CONF[NOVA_GROUP].interface + 'URL')
    raise ks_exc.EndpointNotFound()
コード例 #8
0
ファイル: test_status.py プロジェクト: zhouronghua/nova
    def test_invalid_endpoint(self, get):
        """Test failure when no endpoint exists.

        Replicate in devstack: start devstack without placement
        engine, but create valid placement service user and specify it
        in auth section of [placement] in nova.conf.
        """
        get.side_effect = ks_exc.EndpointNotFound()
        res = self.cmd._check_placement()
        self.assertEqual(status.UpgradeCheckCode.FAILURE, res.code)
        self.assertIn('Placement API endpoint not found', res.details)
コード例 #9
0
    def test_wrong_version(self, get):
        """Test endpoint not found.

        EndpointNotFound will be made when the keystone v3 API is not
        found in the service catalog, or if the v2.0 endpoint was
        registered as the root endpoint. We treat this the same as 404.

        """
        get.side_effect = kse.EndpointNotFound()
        self.assertRaises(webob.exc.HTTPBadRequest, identity.verify_project_id,
                          mock.MagicMock(), "foo")
コード例 #10
0
def get_endpoint(ksa_adapter):
    """Get the endpoint URL represented by a keystoneauth1 Adapter.

    This method is equivalent to what

        ksa_adapter.get_endpoint()

    should do, if it weren't for a panoply of bugs.

    :param ksa_adapter: keystoneauth1.adapter.Adapter, appropriately set up
                        with an endpoint_override; or service_type, interface
                        (list) and auth/service_catalog.
    :return: String endpoint URL.
    :raise EndpointNotFound: If endpoint discovery fails.
    """
    # TODO(efried): This will be unnecessary once bug #1707993 is fixed.
    # (At least for the non-image case, until 1707995 is fixed.)
    if ksa_adapter.endpoint_override:
        return ksa_adapter.endpoint_override
    # TODO(efried): Remove this once bug #1707995 is fixed.
    if ksa_adapter.service_type == 'image':
        try:
            # LOG.warning(ksa_adapter.__dict__)
            return ksa_adapter.get_endpoint_data().catalog_url
        except AttributeError:
            # ksa_adapter.auth is a _ContextAuthPlugin, which doesn't have
            # get_endpoint_data.  Fall through to using get_endpoint().
            pass
    # TODO(efried): The remainder of this method reduces to
    # TODO(efried):     return ksa_adapter.get_endpoint()
    # TODO(efried): once bug #1709118 is fixed.
    # NOTE(efried): Id9bd19cca68206fc64d23b0eaa95aa3e5b01b676 may also do the
    #               trick, once it's in a ksa release.
    # The EndpointNotFound exception happens when _ContextAuthPlugin is in play
    # because its get_endpoint() method isn't yet set up to handle interface as
    # a list.  (It could also happen with a real auth if the endpoint isn't
    # there; but that's covered below.)
    try:
        return ksa_adapter.get_endpoint()
    except ks_exc.EndpointNotFound:
        pass

    interfaces = list(ksa_adapter.interface)
    for interface in interfaces:
        ksa_adapter.interface = interface
        try:
            return ksa_adapter.get_endpoint()
        except ks_exc.EndpointNotFound:
            pass
    raise ks_exc.EndpointNotFound(
        "Could not find requested endpoint for any of the following "
        "interfaces: %s" % interfaces)
コード例 #11
0
    def test_ok_endpoint_not_found(self):
        self.session.get_endpoint.side_effect = exceptions.EndpointNotFound()
        res = self.get_client().request('get', '/foo/bar')

        self.assertIs(self.req.return_value, res)
        self.req.assert_called_once_with(self.base_url + '/foo/bar',
                                         'get',
                                         raise_exc=False,
                                         headers=self.headers)
        self.session.get_endpoint.assert_called_once_with(
            service_type='baremetal-introspection',
            interface=None,
            region_name=None)
コード例 #12
0
ファイル: test_report.py プロジェクト: xx312022850/nova
    def test_missing_endpoint(self, req):
        """Test EndpointNotFound behavior.

        A missing endpoint entry should permanently disable the
        client. And make future calls to it not happen.
        """
        req.side_effect = ks_exc.EndpointNotFound()
        self.client._get_resource_provider("fake")
        self.assertTrue(self.client._disabled)

        # reset the call count to demonstrate that future calls don't
        # work
        req.reset_mock()
        self.client._get_resource_provider("fake")
        req.assert_not_called()
コード例 #13
0
ファイル: test_identity.py プロジェクト: bopopescu/NOVA-7
 def test_early_fail(self, get):
     get.side_effect = kse.EndpointNotFound()
     self.assertTrue(identity.verify_project_id(mock.MagicMock(), "foo"))
コード例 #14
0
    def request(self,
                url,
                method,
                json=None,
                original_ip=None,
                user_agent=None,
                redirect=None,
                authenticated=None,
                endpoint_filter=None,
                auth=None,
                requests_auth=None,
                raise_exc=True,
                allow_reauth=True,
                log=True,
                endpoint_override=None,
                connect_retries=0,
                logger=_logger,
                allow={},
                client_name=None,
                client_version=None,
                microversion=None,
                microversion_service_type=None,
                **kwargs):
        """Send an HTTP request with the specified characteristics.

        Wrapper around `requests.Session.request` to handle tasks such as
        setting headers, JSON encoding/decoding, and error handling.

        Arguments that are not handled are passed through to the requests
        library.

        :param str url: Path or fully qualified URL of HTTP request. If only a
                        path is provided then endpoint_filter must also be
                        provided such that the base URL can be determined. If a
                        fully qualified URL is provided then endpoint_filter
                        will be ignored.
        :param str method: The http method to use. (e.g. 'GET', 'POST')
        :param str original_ip: Mark this request as forwarded for this ip.
                                (optional)
        :param dict headers: Headers to be included in the request. (optional)
        :param json: Some data to be represented as JSON. (optional)
        :param str user_agent: A user_agent to use for the request. If present
                               will override one present in headers. (optional)
        :param int/bool redirect: the maximum number of redirections that
                                  can be followed by a request. Either an
                                  integer for a specific count or True/False
                                  for forever/never. (optional)
        :param int connect_retries: the maximum number of retries that should
                                    be attempted for connection errors.
                                    (optional, defaults to 0 - never retry).
        :param bool authenticated: True if a token should be attached to this
                                   request, False if not or None for attach if
                                   an auth_plugin is available.
                                   (optional, defaults to None)
        :param dict endpoint_filter: Data to be provided to an auth plugin with
                                     which it should be able to determine an
                                     endpoint to use for this request. If not
                                     provided then URL is expected to be a
                                     fully qualified URL. (optional)
        :param str endpoint_override: The URL to use instead of looking up the
                                      endpoint in the auth plugin. This will be
                                      ignored if a fully qualified URL is
                                      provided but take priority over an
                                      endpoint_filter. This string may contain
                                      the values ``%(project_id)s`` and
                                      ``%(user_id)s`` to have those values
                                      replaced by the project_id/user_id of the
                                      current authentication. (optional)
        :param auth: The auth plugin to use when authenticating this request.
                     This will override the plugin that is attached to the
                     session (if any). (optional)
        :type auth: keystoneauth1.plugin.BaseAuthPlugin
        :param requests_auth: A requests library auth plugin that cannot be
                              passed via kwarg because the `auth` kwarg
                              collides with our own auth plugins. (optional)
        :type requests_auth: :py:class:`requests.auth.AuthBase`
        :param bool raise_exc: If True then raise an appropriate exception for
                               failed HTTP requests. If False then return the
                               request object. (optional, default True)
        :param bool allow_reauth: Allow fetching a new token and retrying the
                                  request on receiving a 401 Unauthorized
                                  response. (optional, default True)
        :param bool log: If True then log the request and response data to the
                         debug log. (optional, default True)
        :param logger: The logger object to use to log request and responses.
                       If not provided the keystoneauth1.session default
                       logger will be used.
        :type logger: logging.Logger
        :param dict allow: Extra filters to pass when discovering API
                           versions. (optional)
        :param microversion: Microversion to send for this request.
                       microversion can be given as a string or a tuple.
                       (optional)
        :param str microversion_service_type: The service_type to be sent in
                       the microversion header, if a microversion is given.
                       Defaults to the value of service_type from
                       endpoint_filter if one exists. If endpoint_filter is not
                       provided or does not have a service_type, microversion
                       is given and microversion_service_type is not provided,
                       an exception will be raised.
        :param kwargs: any other parameter that can be passed to
                       :meth:`requests.Session.request` (such as `headers`).
                       Except:

                       - `data` will be overwritten by the data in the `json`
                         param.
                       - `allow_redirects` is ignored as redirects are handled
                         by the session.

        :raises keystoneauth1.exceptions.base.ClientException: For connection
            failure, or to indicate an error response code.

        :returns: The response to the request.
        """
        headers = kwargs.setdefault('headers', dict())
        if microversion:
            self._set_microversion_headers(headers, microversion,
                                           microversion_service_type,
                                           endpoint_filter)

        if authenticated is None:
            authenticated = bool(auth or self.auth)

        if authenticated:
            auth_headers = self.get_auth_headers(auth)

            if auth_headers is None:
                msg = 'No valid authentication is available'
                raise exceptions.AuthorizationFailure(msg)

            headers.update(auth_headers)

        if osprofiler_web:
            headers.update(osprofiler_web.get_trace_id_headers())

        # if we are passed a fully qualified URL and an endpoint_filter we
        # should ignore the filter. This will make it easier for clients who
        # want to overrule the default endpoint_filter data added to all client
        # requests. We check fully qualified here by the presence of a host.
        if not urllib.parse.urlparse(url).netloc:
            base_url = None

            if endpoint_override:
                base_url = endpoint_override % _StringFormatter(self, auth)
            elif endpoint_filter:
                base_url = self.get_endpoint(auth,
                                             allow=allow,
                                             **endpoint_filter)

            if not base_url:
                raise exceptions.EndpointNotFound()

            url = '%s/%s' % (base_url.rstrip('/'), url.lstrip('/'))

        if self.cert:
            kwargs.setdefault('cert', self.cert)

        if self.timeout is not None:
            kwargs.setdefault('timeout', self.timeout)

        if user_agent:
            headers['User-Agent'] = user_agent
        elif self.user_agent:
            user_agent = headers.setdefault('User-Agent', self.user_agent)
        else:
            # Per RFC 7231 Section 5.5.3, identifiers in a user-agent should be
            # ordered by decreasing significance.  If a user sets their product
            # that value will be used. Otherwise we attempt to derive a useful
            # product value. The value will be prepended it to the KSA version,
            # requests version, and then the Python version.

            agent = []

            if self.app_name and self.app_version:
                agent.append('%s/%s' % (self.app_name, self.app_version))
            elif self.app_name:
                agent.append(self.app_name)

            for additional in self.additional_user_agent:
                agent.append('%s/%s' % additional)

            if client_name and client_version:
                agent.append('%s/%s' % (client_name, client_version))
            elif client_name:
                agent.append(client_name)

            if not agent:
                # NOTE(jamielennox): determine_user_agent will return an empty
                # string on failure so checking for None will ensure it is only
                # called once even on failure.
                if self._determined_user_agent is None:
                    self._determined_user_agent = _determine_user_agent()

                if self._determined_user_agent:
                    agent.append(self._determined_user_agent)

            agent.append(DEFAULT_USER_AGENT)
            user_agent = headers.setdefault('User-Agent', ' '.join(agent))

        if self.original_ip:
            headers.setdefault('Forwarded',
                               'for=%s;by=%s' % (self.original_ip, user_agent))

        if json is not None:
            headers.setdefault('Content-Type', 'application/json')
            kwargs['data'] = self._json.encode(json)

        for k, v in self.additional_headers.items():
            headers.setdefault(k, v)

        kwargs.setdefault('verify', self.verify)

        if requests_auth:
            kwargs['auth'] = requests_auth

        # Query parameters that are included in the url string will
        # be logged properly, but those sent in the `params` parameter
        # (which the requests library handles) need to be explicitly
        # picked out so they can be included in the URL that gets loggged.
        query_params = kwargs.get('params', dict())

        if log:
            self._http_log_request(url,
                                   method=method,
                                   data=kwargs.get('data'),
                                   headers=headers,
                                   query_params=query_params,
                                   logger=logger)

        # Force disable requests redirect handling. We will manage this below.
        kwargs['allow_redirects'] = False

        if redirect is None:
            redirect = self.redirect

        send = functools.partial(self._send_request, url, method, redirect,
                                 log, logger, connect_retries)

        try:
            connection_params = self.get_auth_connection_params(auth=auth)
        except exceptions.MissingAuthPlugin:
            # NOTE(jamielennox): If we've gotten this far without an auth
            # plugin then we should be happy with allowing no additional
            # connection params. This will be the typical case for plugins
            # anyway.
            pass
        else:
            if connection_params:
                kwargs.update(connection_params)

        resp = send(**kwargs)

        # log callee and caller request-id for each api call
        if log:
            # service_name should be fetched from endpoint_filter if it is not
            # present then use service_type as service_name.
            service_name = None
            if endpoint_filter:
                service_name = endpoint_filter.get('service_name')
                if not service_name:
                    service_name = endpoint_filter.get('service_type')

            # Nova uses 'x-compute-request-id' and other services like
            # Glance, Cinder etc are using 'x-openstack-request-id' to store
            # request-id in the header
            request_id = (resp.headers.get('x-openstack-request-id')
                          or resp.headers.get('x-compute-request-id'))
            if request_id:
                logger.debug(
                    '%(method)s call to %(service_name)s for '
                    '%(url)s used request id '
                    '%(response_request_id)s', {
                        'method': resp.request.method,
                        'service_name': service_name,
                        'url': resp.url,
                        'response_request_id': request_id
                    })

        # handle getting a 401 Unauthorized response by invalidating the plugin
        # and then retrying the request. This is only tried once.
        if resp.status_code == 401 and authenticated and allow_reauth:
            if self.invalidate(auth):
                auth_headers = self.get_auth_headers(auth)

                if auth_headers is not None:
                    headers.update(auth_headers)
                    resp = send(**kwargs)

        if raise_exc and resp.status_code >= 400:
            logger.debug('Request returned failure status: %s',
                         resp.status_code)
            raise exceptions.from_response(resp, method, url)

        return resp
コード例 #15
0
    def request(self,
                url,
                method,
                json=None,
                original_ip=None,
                user_agent=None,
                redirect=None,
                endpoint_filter=None,
                raise_exc=True,
                log=True,
                microversion=None,
                endpoint_override=None,
                connect_retries=0,
                allow=None,
                client_name=None,
                client_version=None,
                **kwargs):
        self._determined_user_agent = None
        headers = kwargs.setdefault('headers', dict())
        auth_headers = self.get_auth_headers()
        if auth_headers is None:
            msg = 'No valid authentication is available'
            raise exceptions.AuthorizationFailure(msg)
        headers.update(auth_headers)
        base_url = ""
        if not urllib.parse.urlparse(url).netloc:
            if endpoint_override:
                base_url = endpoint_override
                # base_url = endpoint_override % {"project_id": self.project_id}
            elif endpoint_filter:
                base_url = self.get_endpoint(
                    interface=endpoint_filter.interface,
                    service_type=endpoint_filter.service_type)
            if not urllib.parse.urlparse(base_url).netloc:
                raise exceptions.EndpointNotFound()
            url = '%s/%s' % (base_url.rstrip('/'), url.lstrip('/'))
        headers.setdefault("Host", urllib.parse.urlparse(url).netloc)
        if self.cert:
            kwargs.setdefault('cert', self.cert)
        if self.timeout is not None:
            kwargs.setdefault('timeout', self.timeout)
        if user_agent:
            headers['User-Agent'] = user_agent
        elif self.user_agent:
            user_agent = headers.setdefault('User-Agent', self.user_agent)
        else:
            agent = []
            if self.app_name and self.app_version:
                agent.append('%s/%s' % (self.app_name, self.app_version))
            elif self.app_name:
                agent.append(self.app_name)

            if client_name and client_version:
                agent.append('%s/%s' % (client_name, client_version))
            elif client_name:
                agent.append(client_name)

            for additional in self.additional_user_agent:
                agent.append('%s/%s' % additional)

            if not agent:
                # NOTE(jamielennox): determine_user_agent will return an empty
                # string on failure so checking for None will ensure it is only
                # called once even on failure.
                if self._determined_user_agent is None:
                    self._determined_user_agent = _determine_user_agent()

                if self._determined_user_agent:
                    agent.append(self._determined_user_agent)

            agent.append(DEFAULT_USER_AGENT)
            user_agent = headers.setdefault('User-Agent', ' '.join(agent))

        if self.original_ip:
            headers.setdefault('Forwarded',
                               'for=%s;by=%s' % (self.original_ip, user_agent))

        if json is not None:
            kwargs['data'] = self._json.encode(json)
        headers.setdefault('Content-Type', 'application/json')
        if self.additional_headers:
            for k, v in self.additional_headers.items():
                headers.setdefault(k, v)

        kwargs.setdefault('verify', self.verify)

        # if requests_auth:
        #     kwargs['auth'] = requests_auth

        # Query parameters that are included in the url string will
        # be logged properly, but those sent in the `params` parameter
        # (which the requests library handles) need to be explicitly
        # picked out so they can be included in the URL that gets loggged.
        query_params = kwargs.get('params', dict())

        if log:
            self._http_log_request(url,
                                   method=method,
                                   data=kwargs.get('data'),
                                   headers=headers,
                                   query_params=query_params,
                                   logger=_logger)

        # Force disable requests redirect handling. We will manage this below.
        kwargs['allow_redirects'] = False

        if redirect is None:
            redirect = self.redirect

        send = functools.partial(self._send_request, url, method, redirect,
                                 log, _logger, connect_retries)

        resp = send(**kwargs)

        # log callee and caller request-id for each api call
        if log:
            # service_name should be fetched from endpoint_filter if it is not
            # present then use service_type as service_name.
            service_name = None
            if endpoint_filter:
                service_name = endpoint_filter.get('service_name')
                if not service_name:
                    service_name = endpoint_filter.get('service_type')

            # Nova uses 'x-compute-request-id' and other services like
            # Glance, Cinder etc are using 'x-openstack-request-id' to store
            # request-id in the header
            request_id = (resp.headers.get('x-openstack-request-id')
                          or resp.headers.get('x-compute-request-id'))
            if request_id:
                _logger.debug(
                    '%(method)s call to %(service_name)s for '
                    '%(url)s used request id '
                    '%(response_request_id)s', {
                        'method': resp.request.method,
                        'service_name': service_name,
                        'url': resp.url,
                        'response_request_id': request_id
                    })

        if raise_exc and resp.status_code >= 400:
            _logger.debug('Request returned failure status: %s',
                          resp.status_code)
            raise exceptions.from_response(resp, method, url)
        return resp
コード例 #16
0
 def fake_get_kwapi_client(ksclient, endpoint):
     raise exceptions.EndpointNotFound("fake keystone exception")
コード例 #17
0
    def request(self, url, method, json=None, original_ip=None,
                user_agent=None, redirect=None, endpoint_filter=None,
                raise_exc=True, log=True, microversion=None,
                endpoint_override=None, connect_retries=0,
                allow=None, client_name=None, client_version=None,
                **kwargs):
        headers = kwargs.setdefault('headers', dict())

        if microversion:
            self._set_microversion_headers(headers, microversion, None, endpoint_filter)
        if self._securitytoken:
            headers.setdefault("X-Security-Token", self._securitytoken)
        if not urllib.parse.urlparse(url).netloc:
            if endpoint_override:
                base_url = endpoint_override % {"project_id": self.project_id}
            elif endpoint_filter:
                base_url = self.get_endpoint(interface=endpoint_filter.interface,
                                             service_type=endpoint_filter.service_type)
            if not urllib.parse.urlparse(base_url).netloc:
                raise exceptions.EndpointNotFound()
            url = '%s/%s' % (base_url.rstrip('/'), url.lstrip('/'))
        headers.setdefault("Host", urllib.parse.urlparse(url).netloc)
        if self.cert:
            kwargs.setdefault('cert', self.cert)
        if self.timeout is not None:
            kwargs.setdefault('timeout', self.timeout)
        if user_agent:
            headers['User-Agent'] = user_agent
        elif self.user_agent:
            user_agent = headers.setdefault('User-Agent', self.user_agent)
        else:
            # Per RFC 7231 Section 5.5.3, identifiers in a user-agent should be
            # ordered by decreasing significance.  If a user sets their product
            # that value will be used. Otherwise we attempt to derive a useful
            # product value. The value will be prepended it to the KSA version,
            # requests version, and then the Python version.

            agent = []

            if self.app_name and self.app_version:
                agent.append('%s/%s' % (self.app_name, self.app_version))
            elif self.app_name:
                agent.append(self.app_name)

            if client_name and client_version:
                agent.append('%s/%s' % (client_name, client_version))
            elif client_name:
                agent.append(client_name)

            for additional in self.additional_user_agent:
                agent.append('%s/%s' % additional)

            if not agent:
                # NOTE(jamielennox): determine_user_agent will return an empty
                # string on failure so checking for None will ensure it is only
                # called once even on failure.
                if self._determined_user_agent is None:
                    self._determined_user_agent = _determine_user_agent()

                if self._determined_user_agent:
                    agent.append(self._determined_user_agent)

            agent.append(DEFAULT_USER_AGENT)
            user_agent = headers.setdefault('User-Agent', ' '.join(agent))

        if self.original_ip:
            headers.setdefault('Forwarded',
                               'for=%s;by=%s' % (self.original_ip, user_agent))

        if json is not None:
            kwargs['data'] = self._json.encode(json)
        # surpport  maas,map_reduce when without request body
        headers.setdefault('Content-Type', 'application/json')
        if self.domain_id:
            headers.setdefault('X-Domain-Id', self.domain_id)
        # surpport sub-project id for some service the endpoint contain project id
        elif self.project_id:
            headers.setdefault('X-Project-Id', self.project_id)

        if self.additional_headers:
            for k, v in self.additional_headers.items():
                headers.setdefault(k, v)

        kwargs.setdefault('verify', self.verify)

        # if requests_auth:
        #     kwargs['auth'] = requests_auth

        # Query parameters that are included in the url string will
        # be logged properly, but those sent in the `params` parameter
        # (which the requests library handles) need to be explicitly
        # picked out so they can be included in the URL that gets loggged.
        query_params = kwargs.get('params', dict())
        headers.setdefault("X-Sdk-Date", datetime.datetime.strftime(datetime.datetime.utcnow(), "%Y%m%dT%H%M%SZ"))
        signedstring = self.signer.signature(method=method,
                                             url=url,
                                             headers=headers,
                                             svr=endpoint_filter.service_type if endpoint_filter else '',
                                             params=query_params,
                                             data=kwargs.get("data", None))
        # print(signedstring)
        headers.setdefault("Authorization", signedstring)
        if log:
            self._http_log_request(url, method=method,
                                   data=kwargs.get('data'),
                                   headers=headers,
                                   query_params=query_params,
                                   logger=_logger)

        # Force disable requests redirect handling. We will manage this below.
        kwargs['allow_redirects'] = False

        if redirect is None:
            redirect = self.redirect

        send = functools.partial(self._send_request,
                                 url, method, redirect, log, _logger,
                                 connect_retries)

        resp = send(**kwargs)

        # log callee and caller request-id for each api call
        if log:
            # service_name should be fetched from endpoint_filter if it is not
            # present then use service_type as service_name.
            service_name = None
            if endpoint_filter:
                service_name = endpoint_filter.get('service_name')
                if not service_name:
                    service_name = endpoint_filter.get('service_type')

            # Nova uses 'x-compute-request-id' and other services like
            # Glance, Cinder etc are using 'x-openstack-request-id' to store
            # request-id in the header
            request_id = (resp.headers.get('x-openstack-request-id') or
                          resp.headers.get('x-compute-request-id'))
            if request_id:
                _logger.debug('%(method)s call to %(service_name)s for '
                              '%(url)s used request id '
                              '%(response_request_id)s',
                              {'method': resp.request.method,
                               'service_name': service_name,
                               'url': resp.url,
                               'response_request_id': request_id})

        if raise_exc and resp.status_code >= 400:
            _logger.debug('Request returned failure status: %s',
                          resp.status_code)
            raise exceptions.from_response(resp, method, url)
        return resp
コード例 #18
0
    def endpoint_data_for(self,
                          service_type=None,
                          interface='public',
                          region_name=None,
                          service_name=None,
                          service_id=None,
                          endpoint_id=None):
        """Fetch endpoint data from the service catalog.

        Fetch the specified endpoint data from the service catalog for
        a particular endpoint attribute. If no attribute is given, return
        the first endpoint of the specified type.

        Valid interface types: `public` or `publicURL`,
                               `internal` or `internalURL`,
                               `admin` or 'adminURL`

        :param string service_type: Service type of the endpoint.
        :param interface: Type of endpoint. Can be a single value or a list
                          of values. If it's a list of values, they will be
                          looked for in order of preference.
        :param string region_name: Region of the endpoint.
        :param string service_name: The assigned name of the service.
        :param string service_id: The identifier of a service.
        :param string endpoint_id: The identifier of an endpoint.
        """
        if not self._catalog:
            raise exceptions.EmptyCatalog('The service catalog is empty.')

        endpoint_data_list = self.get_endpoint_data_list(
            service_type=service_type,
            interface=interface,
            region_name=region_name,
            service_name=service_name,
            service_id=service_id,
            endpoint_id=endpoint_id)

        if endpoint_data_list:
            return endpoint_data_list[0]

        if service_name and region_name:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'named %(service_name)s in %(region_name)s region not '
                   'found' % {
                       'interface': interface,
                       'service_type': service_type,
                       'service_name': service_name,
                       'region_name': region_name
                   })
        elif service_name:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'named %(service_name)s not found' % {
                       'interface': interface,
                       'service_type': service_type,
                       'service_name': service_name
                   })
        elif region_name:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'in %(region_name)s region not found' % {
                       'interface': interface,
                       'service_type': service_type,
                       'region_name': region_name
                   })
        else:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'not found' % {
                       'interface': interface,
                       'service_type': service_type
                   })

        raise exceptions.EndpointNotFound(msg)
コード例 #19
0
 def fake_ks_service_catalog_url_for(*args, **kwargs):
     raise exceptions.EndpointNotFound("Fake keystone exception")
コード例 #20
0
ファイル: session.py プロジェクト: rajagopalx/product
    def request(self,
                url,
                method,
                json=None,
                original_ip=None,
                user_agent=None,
                redirect=None,
                authenticated=None,
                endpoint_filter=None,
                auth=None,
                requests_auth=None,
                raise_exc=True,
                allow_reauth=True,
                log=True,
                endpoint_override=None,
                connect_retries=0,
                logger=_logger,
                **kwargs):
        """Send an HTTP request with the specified characteristics.

        Wrapper around `requests.Session.request` to handle tasks such as
        setting headers, JSON encoding/decoding, and error handling.

        Arguments that are not handled are passed through to the requests
        library.

        :param str url: Path or fully qualified URL of HTTP request. If only a
                        path is provided then endpoint_filter must also be
                        provided such that the base URL can be determined. If a
                        fully qualified URL is provided then endpoint_filter
                        will be ignored.
        :param str method: The http method to use. (e.g. 'GET', 'POST')
        :param str original_ip: Mark this request as forwarded for this ip.
                                (optional)
        :param dict headers: Headers to be included in the request. (optional)
        :param json: Some data to be represented as JSON. (optional)
        :param str user_agent: A user_agent to use for the request. If present
                               will override one present in headers. (optional)
        :param int/bool redirect: the maximum number of redirections that
                                  can be followed by a request. Either an
                                  integer for a specific count or True/False
                                  for forever/never. (optional)
        :param int connect_retries: the maximum number of retries that should
                                    be attempted for connection errors.
                                    (optional, defaults to 0 - never retry).
        :param bool authenticated: True if a token should be attached to this
                                   request, False if not or None for attach if
                                   an auth_plugin is available.
                                   (optional, defaults to None)
        :param dict endpoint_filter: Data to be provided to an auth plugin with
                                     which it should be able to determine an
                                     endpoint to use for this request. If not
                                     provided then URL is expected to be a
                                     fully qualified URL. (optional)
        :param str endpoint_override: The URL to use instead of looking up the
                                      endpoint in the auth plugin. This will be
                                      ignored if a fully qualified URL is
                                      provided but take priority over an
                                      endpoint_filter. This string may contain
                                      the values ``%(project_id)s`` and
                                      ``%(user_id)s`` to have those values
                                      replaced by the project_id/user_id of the
                                      current authentication. (optional)
        :param auth: The auth plugin to use when authenticating this request.
                     This will override the plugin that is attached to the
                     session (if any). (optional)
        :type auth: keystoneauth1.plugin.BaseAuthPlugin
        :param requests_auth: A requests library auth plugin that cannot be
                              passed via kwarg because the `auth` kwarg
                              collides with our own auth plugins. (optional)
        :type requests_auth: :py:class:`requests.auth.AuthBase`
        :param bool raise_exc: If True then raise an appropriate exception for
                               failed HTTP requests. If False then return the
                               request object. (optional, default True)
        :param bool allow_reauth: Allow fetching a new token and retrying the
                                  request on receiving a 401 Unauthorized
                                  response. (optional, default True)
        :param bool log: If True then log the request and response data to the
                         debug log. (optional, default True)
        :param logger: The logger object to use to log request and responses.
                       If not provided the keystoneauth1.session default
                       logger will be used.
        :type logger: logging.Logger
        :param kwargs: any other parameter that can be passed to
                       :meth:`requests.Session.request` (such as `headers`).
                       Except:

                       - `data` will be overwritten by the data in the `json`
                         param.
                       - `allow_redirects` is ignored as redirects are handled
                         by the session.

        :raises keystoneauth1.exceptions.base.ClientException: For connection
            failure, or to indicate an error response code.

        :returns: The response to the request.
        """
        headers = kwargs.setdefault('headers', dict())

        if authenticated is None:
            authenticated = bool(auth or self.auth)

        if authenticated:
            auth_headers = self.get_auth_headers(auth)

            if auth_headers is None:
                msg = 'No valid authentication is available'
                raise exceptions.AuthorizationFailure(msg)

            headers.update(auth_headers)

        if osprofiler_web:
            headers.update(osprofiler_web.get_trace_id_headers())

        # if we are passed a fully qualified URL and an endpoint_filter we
        # should ignore the filter. This will make it easier for clients who
        # want to overrule the default endpoint_filter data added to all client
        # requests. We check fully qualified here by the presence of a host.
        if not urllib.parse.urlparse(url).netloc:
            base_url = None

            if endpoint_override:
                base_url = endpoint_override % _StringFormatter(self, auth)
            elif endpoint_filter:
                base_url = self.get_endpoint(auth, **endpoint_filter)

            if not base_url:
                raise exceptions.EndpointNotFound()

            url = '%s/%s' % (base_url.rstrip('/'), url.lstrip('/'))

        if self.cert:
            kwargs.setdefault('cert', self.cert)

        if self.timeout is not None:
            kwargs.setdefault('timeout', self.timeout)

        if user_agent:
            headers['User-Agent'] = user_agent
        elif self.user_agent:
            user_agent = headers.setdefault('User-Agent', self.user_agent)
        else:
            user_agent = headers.setdefault('User-Agent', DEFAULT_USER_AGENT)

        if self.original_ip:
            headers.setdefault('Forwarded',
                               'for=%s;by=%s' % (self.original_ip, user_agent))

        if json is not None:
            headers['Content-Type'] = 'application/json'
            kwargs['data'] = self._json.encode(json)

        kwargs.setdefault('verify', self.verify)

        if requests_auth:
            kwargs['auth'] = requests_auth

        if log:
            self._http_log_request(url,
                                   method=method,
                                   data=kwargs.get('data'),
                                   headers=headers,
                                   logger=logger)

        # Force disable requests redirect handling. We will manage this below.
        kwargs['allow_redirects'] = False

        if redirect is None:
            redirect = self.redirect

        send = functools.partial(self._send_request, url, method, redirect,
                                 log, logger, connect_retries)

        try:
            connection_params = self.get_auth_connection_params(auth=auth)
        except exceptions.MissingAuthPlugin:
            # NOTE(jamielennox): If we've gotten this far without an auth
            # plugin then we should be happy with allowing no additional
            # connection params. This will be the typical case for plugins
            # anyway.
            pass
        else:
            if connection_params:
                kwargs.update(connection_params)

        resp = send(**kwargs)

        # handle getting a 401 Unauthorized response by invalidating the plugin
        # and then retrying the request. This is only tried once.
        if resp.status_code == 401 and authenticated and allow_reauth:
            if self.invalidate(auth):
                auth_headers = self.get_auth_headers(auth)

                if auth_headers is not None:
                    headers.update(auth_headers)
                    resp = send(**kwargs)

        if raise_exc and resp.status_code >= 400:
            logger.debug('Request returned failure status: %s',
                         resp.status_code)
            raise exceptions.from_response(resp, method, url)

        return resp