support global_request_id in constructor
This allows a global_request_id to be created in the constructor which will be passed on all subsequent calls to support cross service request tracking. oslo spec I65de8261746b25d45e105394f4eeb95b9cb3bd42 Change-Id: Ib271ac01c2a4a36e611ae9181ae93305f2318680
This commit is contained in:
@@ -63,6 +63,7 @@ V1_SERVICE_TYPE = 'volume'
|
|||||||
SERVICE_TYPES = {'1': V1_SERVICE_TYPE,
|
SERVICE_TYPES = {'1': V1_SERVICE_TYPE,
|
||||||
'2': V2_SERVICE_TYPE,
|
'2': V2_SERVICE_TYPE,
|
||||||
'3': V3_SERVICE_TYPE}
|
'3': V3_SERVICE_TYPE}
|
||||||
|
REQ_ID_HEADER = 'X-OpenStack-Request-ID'
|
||||||
|
|
||||||
# tell keystoneclient that we can ignore the /v1|v2/{project_id} component of
|
# tell keystoneclient that we can ignore the /v1|v2/{project_id} component of
|
||||||
# the service catalog when doing discovery lookups
|
# the service catalog when doing discovery lookups
|
||||||
@@ -125,10 +126,12 @@ def _log_request_id(logger, resp, service_name):
|
|||||||
|
|
||||||
|
|
||||||
class SessionClient(adapter.LegacyJsonAdapter):
|
class SessionClient(adapter.LegacyJsonAdapter):
|
||||||
|
global_request_id = None
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.api_version = kwargs.pop('api_version', None)
|
self.api_version = kwargs.pop('api_version', None)
|
||||||
self.api_version = self.api_version or api_versions.APIVersion()
|
self.api_version = self.api_version or api_versions.APIVersion()
|
||||||
|
self.global_request_id = kwargs.pop('global_request_id', None)
|
||||||
self.retries = kwargs.pop('retries', 0)
|
self.retries = kwargs.pop('retries', 0)
|
||||||
self._logger = logging.getLogger(__name__)
|
self._logger = logging.getLogger(__name__)
|
||||||
super(SessionClient, self).__init__(*args, **kwargs)
|
super(SessionClient, self).__init__(*args, **kwargs)
|
||||||
@@ -137,6 +140,10 @@ class SessionClient(adapter.LegacyJsonAdapter):
|
|||||||
kwargs.setdefault('headers', kwargs.get('headers', {}))
|
kwargs.setdefault('headers', kwargs.get('headers', {}))
|
||||||
api_versions.update_headers(kwargs["headers"], self.api_version)
|
api_versions.update_headers(kwargs["headers"], self.api_version)
|
||||||
kwargs.setdefault('authenticated', False)
|
kwargs.setdefault('authenticated', False)
|
||||||
|
|
||||||
|
if self.global_request_id:
|
||||||
|
kwargs['headers'].setdefault(REQ_ID_HEADER, self.global_request_id)
|
||||||
|
|
||||||
# Note(tpatil): The standard call raises errors from
|
# Note(tpatil): The standard call raises errors from
|
||||||
# keystoneauth, here we need to raise the cinderclient errors.
|
# keystoneauth, here we need to raise the cinderclient errors.
|
||||||
raise_exc = kwargs.pop('raise_exc', True)
|
raise_exc = kwargs.pop('raise_exc', True)
|
||||||
@@ -231,12 +238,13 @@ class HTTPClient(object):
|
|||||||
http_log_debug=False, cacert=None,
|
http_log_debug=False, cacert=None,
|
||||||
auth_system='keystone', auth_plugin=None, api_version=None,
|
auth_system='keystone', auth_plugin=None, api_version=None,
|
||||||
logger=None, user_domain_name='Default',
|
logger=None, user_domain_name='Default',
|
||||||
project_domain_name='Default'):
|
project_domain_name='Default', global_request_id=None):
|
||||||
self.user = user
|
self.user = user
|
||||||
self.password = password
|
self.password = password
|
||||||
self.projectid = projectid
|
self.projectid = projectid
|
||||||
self.tenant_id = tenant_id
|
self.tenant_id = tenant_id
|
||||||
self.api_version = api_version or api_versions.APIVersion()
|
self.api_version = api_version or api_versions.APIVersion()
|
||||||
|
self.global_request_id = global_request_id
|
||||||
|
|
||||||
if auth_system and auth_system != 'keystone' and not auth_plugin:
|
if auth_system and auth_system != 'keystone' and not auth_plugin:
|
||||||
raise exceptions.AuthSystemNotFound(auth_system)
|
raise exceptions.AuthSystemNotFound(auth_system)
|
||||||
@@ -335,6 +343,9 @@ class HTTPClient(object):
|
|||||||
kwargs['data'] = json.dumps(kwargs.pop('body'))
|
kwargs['data'] = json.dumps(kwargs.pop('body'))
|
||||||
api_versions.update_headers(kwargs["headers"], self.api_version)
|
api_versions.update_headers(kwargs["headers"], self.api_version)
|
||||||
|
|
||||||
|
if self.global_request_id:
|
||||||
|
kwargs['headers'].setdefault(REQ_ID_HEADER, self.global_request_id)
|
||||||
|
|
||||||
if self.timeout:
|
if self.timeout:
|
||||||
kwargs.setdefault('timeout', self.timeout)
|
kwargs.setdefault('timeout', self.timeout)
|
||||||
self.http_log_req((url, method,), kwargs)
|
self.http_log_req((url, method,), kwargs)
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
import json
|
import json
|
||||||
import mock
|
import mock
|
||||||
import requests
|
import requests
|
||||||
|
import uuid
|
||||||
|
|
||||||
from cinderclient import client
|
from cinderclient import client
|
||||||
from cinderclient import exceptions
|
from cinderclient import exceptions
|
||||||
@@ -69,14 +70,15 @@ timeout_error_request = mock.Mock(
|
|||||||
side_effect=requests.exceptions.Timeout)
|
side_effect=requests.exceptions.Timeout)
|
||||||
|
|
||||||
|
|
||||||
def get_client(retries=0):
|
def get_client(retries=0, **kwargs):
|
||||||
cl = client.HTTPClient("username", "password",
|
cl = client.HTTPClient("username", "password",
|
||||||
"project_id", "auth_test", retries=retries)
|
"project_id", "auth_test", retries=retries,
|
||||||
|
**kwargs)
|
||||||
return cl
|
return cl
|
||||||
|
|
||||||
|
|
||||||
def get_authed_client(retries=0):
|
def get_authed_client(retries=0, **kwargs):
|
||||||
cl = get_client(retries=retries)
|
cl = get_client(retries=retries, **kwargs)
|
||||||
cl.management_url = "http://example.com"
|
cl.management_url = "http://example.com"
|
||||||
cl.auth_token = "token"
|
cl.auth_token = "token"
|
||||||
cl.get_service_url = mock.Mock(return_value="http://example.com")
|
cl.get_service_url = mock.Mock(return_value="http://example.com")
|
||||||
@@ -114,6 +116,29 @@ class ClientTest(utils.TestCase):
|
|||||||
|
|
||||||
test_get_call()
|
test_get_call()
|
||||||
|
|
||||||
|
def test_get_global_id(self):
|
||||||
|
global_id = "req-%s" % uuid.uuid4()
|
||||||
|
cl = get_authed_client(global_request_id=global_id)
|
||||||
|
|
||||||
|
@mock.patch.object(requests, "request", mock_request)
|
||||||
|
@mock.patch('time.time', mock.Mock(return_value=1234))
|
||||||
|
def test_get_call():
|
||||||
|
resp, body = cl.get("/hi")
|
||||||
|
headers = {"X-Auth-Token": "token",
|
||||||
|
"X-Auth-Project-Id": "project_id",
|
||||||
|
"X-OpenStack-Request-ID": global_id,
|
||||||
|
"User-Agent": cl.USER_AGENT,
|
||||||
|
'Accept': 'application/json', }
|
||||||
|
mock_request.assert_called_with(
|
||||||
|
"GET",
|
||||||
|
"http://example.com/hi",
|
||||||
|
headers=headers,
|
||||||
|
**self.TEST_REQUEST_BASE)
|
||||||
|
# Automatic JSON parsing
|
||||||
|
self.assertEqual({"hi": "there"}, body)
|
||||||
|
|
||||||
|
test_get_call()
|
||||||
|
|
||||||
def test_get_reauth_0_retries(self):
|
def test_get_reauth_0_retries(self):
|
||||||
cl = get_authed_client(retries=0)
|
cl = get_authed_client(retries=0)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user