diff --git a/neutronclient/client.py b/neutronclient/client.py index 2995bcea5..7c8000da4 100644 --- a/neutronclient/client.py +++ b/neutronclient/client.py @@ -46,6 +46,7 @@ else: logging.getLogger("requests").setLevel(_requests_log_level) MAX_URI_LEN = 8192 USER_AGENT = 'python-neutronclient' +REQ_ID_HEADER = 'X-OpenStack-Request-ID' class HTTPClient(object): @@ -64,7 +65,7 @@ class HTTPClient(object): endpoint_url=None, insecure=False, endpoint_type='publicURL', auth_strategy='keystone', ca_cert=None, log_credentials=False, - service_type='network', + service_type='network', global_request_id=None, **kwargs): self.username = username @@ -83,6 +84,7 @@ class HTTPClient(object): self.endpoint_url = endpoint_url self.auth_strategy = auth_strategy self.log_credentials = log_credentials + self.global_request_id = global_request_id if insecure: self.verify_cert = False else: @@ -153,6 +155,9 @@ class HTTPClient(object): if body: headers.setdefault('Content-Type', content_type) + if self.global_request_id: + headers.setdefault(REQ_ID_HEADER, self.global_request_id) + headers['User-Agent'] = USER_AGENT # NOTE(dbelova): osprofiler_web.get_trace_id_headers does not add any # headers in case if osprofiler is not initialized. @@ -299,6 +304,9 @@ class HTTPClient(object): class SessionClient(adapter.Adapter): + def __init__(self, *args, **kwargs): + self.global_request_id = kwargs.pop("global_request_id", None) + super(SessionClient, self).__init__(*args, **kwargs) def request(self, *args, **kwargs): kwargs.setdefault('authenticated', False) @@ -308,6 +316,9 @@ class SessionClient(adapter.Adapter): headers = kwargs.setdefault('headers', {}) headers.setdefault('Accept', content_type) + + if self.global_request_id: + headers.setdefault(REQ_ID_HEADER, self.global_request_id) # NOTE(dbelova): osprofiler_web.get_trace_id_headers does not add any # headers in case if osprofiler is not initialized. if osprofiler_web: @@ -397,6 +408,7 @@ def construct_http_client(username=None, ca_cert=None, service_type='network', session=None, + global_request_id=None, **kwargs): if session: @@ -405,6 +417,7 @@ def construct_http_client(username=None, return SessionClient(session=session, service_type=service_type, region_name=region_name, + global_request_id=global_request_id, **kwargs) else: # FIXME(bklei): username and password are now optional. Need @@ -425,4 +438,5 @@ def construct_http_client(username=None, service_type=service_type, ca_cert=ca_cert, log_credentials=log_credentials, - auth_strategy=auth_strategy) + auth_strategy=auth_strategy, + global_request_id=global_request_id) diff --git a/neutronclient/tests/unit/test_http.py b/neutronclient/tests/unit/test_http.py index 09e1e7a58..a03df0756 100644 --- a/neutronclient/tests/unit/test_http.py +++ b/neutronclient/tests/unit/test_http.py @@ -14,6 +14,7 @@ # under the License. import abc +import uuid import osprofiler.profiler import osprofiler.web @@ -121,3 +122,20 @@ class TestHTTPClient(TestHTTPClientMixin, testtools.TestCase): resp, resp_text = self.http._cs_request(URL, METHOD) self.assertEqual(403, resp.status_code) self.assertEqual(text, resp_text) + + +class TestHTTPClientWithReqId(TestHTTPClientMixin, testtools.TestCase): + """Tests for when global_request_id is set.""" + + def initialize(self): + self.req_id = "req-%s" % uuid.uuid4() + return client.HTTPClient(token=AUTH_TOKEN, endpoint_url=END_URL, + global_request_id=self.req_id) + + def test_request_success(self): + headers = { + 'Accept': 'application/json', + 'X-OpenStack-Request-ID': self.req_id + } + self.requests.register_uri(METHOD, URL, request_headers=headers) + self.http.request(URL, METHOD) diff --git a/releasenotes/notes/global_request_id-56856a93b982a6b3.yaml b/releasenotes/notes/global_request_id-56856a93b982a6b3.yaml new file mode 100644 index 000000000..168987613 --- /dev/null +++ b/releasenotes/notes/global_request_id-56856a93b982a6b3.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Adds a new ``global_request_id`` parameter to the Client + constructors, which will pass that id on all requests as the + ``X-OpenStack-Request-ID`` header.