Add support for global_request_id
Added support for setting global_request_id on a Connection. If done, this will cause all requests sent to send the request id header to the OpenStack services. Since Connection can otherwise be used multi-threaded, add a method global_request that returns a new Connection based on the old Connection but on which the new global_request_id has been set. Since a Connection can be used as a context manager, this also means the global_request method can be used in with statements. Change-Id: I70964cdd79741703c0b9b911b3b2f27c248130f0
This commit is contained in:
parent
57b634b0e0
commit
95bf14908e
@ -14,7 +14,7 @@ jmespath==0.9.0
|
||||
jsonpatch==1.16
|
||||
jsonpointer==1.13
|
||||
jsonschema==2.6.0
|
||||
keystoneauth1==3.14.0
|
||||
keystoneauth1==3.15.0
|
||||
linecache2==1.0.0
|
||||
mock==2.0.0
|
||||
mox3==0.20.0
|
||||
|
@ -33,6 +33,7 @@ from openstack.cloud import _object_store
|
||||
from openstack.cloud import meta
|
||||
from openstack.cloud import _utils
|
||||
import openstack.config
|
||||
from openstack.config import cloud_region as cloud_region_mod
|
||||
from openstack import proxy
|
||||
|
||||
DEFAULT_SERVER_AGE = 5
|
||||
@ -226,16 +227,16 @@ class _OpenStackCloudMixin(object):
|
||||
for key, value in kwargs.items():
|
||||
params['auth'][key] = value
|
||||
|
||||
cloud_config = config.get_one(**params)
|
||||
cloud_region = config.get_one(**params)
|
||||
# Attach the discovery cache from the old session so we won't
|
||||
# double discover.
|
||||
cloud_config._discovery_cache = self.session._discovery_cache
|
||||
cloud_region._discovery_cache = self.session._discovery_cache
|
||||
# Override the cloud name so that logging/location work right
|
||||
cloud_config._name = self.name
|
||||
cloud_config.config['profile'] = self.name
|
||||
cloud_region._name = self.name
|
||||
cloud_region.config['profile'] = self.name
|
||||
# Use self.__class__ so that we return whatever this if, like if it's
|
||||
# a subclass in the case of shade wrapping sdk.
|
||||
return self.__class__(config=cloud_config)
|
||||
return self.__class__(config=cloud_region)
|
||||
|
||||
def connect_as_project(self, project):
|
||||
"""Make a new OpenStackCloud object with a new project.
|
||||
@ -267,6 +268,53 @@ class _OpenStackCloudMixin(object):
|
||||
auth['project_name'] = project
|
||||
return self.connect_as(**auth)
|
||||
|
||||
def global_request(self, global_request_id):
|
||||
"""Make a new Connection object with a global request id set.
|
||||
|
||||
Take the existing settings from the current Connection and construct a
|
||||
new Connection object with the global_request_id overridden.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from oslo_context import context
|
||||
cloud = openstack.connect(cloud='example')
|
||||
# Work normally
|
||||
servers = cloud.list_servers()
|
||||
cloud2 = cloud.global_request(context.generate_request_id())
|
||||
# cloud2 sends all requests with global_request_id set
|
||||
servers = cloud2.list_servers()
|
||||
|
||||
Additionally, this can be used as a context manager:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from oslo_context import context
|
||||
c = openstack.connect(cloud='example')
|
||||
# Work normally
|
||||
servers = c.list_servers()
|
||||
with c.global_request(context.generate_request_id()) as c2:
|
||||
# c2 sends all requests with global_request_id set
|
||||
servers = c2.list_servers()
|
||||
|
||||
:param global_request_id: The `global_request_id` to send.
|
||||
"""
|
||||
params = copy.deepcopy(self.config.config)
|
||||
cloud_region = cloud_region_mod.from_session(
|
||||
session=self.session,
|
||||
app_name=self.config._app_name,
|
||||
app_version=self.config._app_version,
|
||||
discovery_cache=self.session._discovery_cache,
|
||||
**params)
|
||||
|
||||
# Override the cloud name so that logging/location work right
|
||||
cloud_region._name = self.name
|
||||
cloud_region.config['profile'] = self.name
|
||||
# Use self.__class__ so that we return whatever this is, like if it's
|
||||
# a subclass in the case of shade wrapping sdk.
|
||||
new_conn = self.__class__(config=cloud_region)
|
||||
new_conn.set_global_request_id(global_request_id)
|
||||
return new_conn
|
||||
|
||||
def _make_cache(self, cache_class, expiration_time, arguments):
|
||||
return dogpile.cache.make_region(
|
||||
function_key_generator=self._make_cache_key
|
||||
|
@ -272,6 +272,7 @@ class Connection(six.with_metaclass(_meta.ConnectionMeta,
|
||||
rate_limit=None,
|
||||
oslo_conf=None,
|
||||
service_types=None,
|
||||
global_request_id=None,
|
||||
**kwargs):
|
||||
"""Create a connection to a cloud.
|
||||
|
||||
@ -328,6 +329,7 @@ class Connection(six.with_metaclass(_meta.ConnectionMeta,
|
||||
other service types will be disabled (will error if used).
|
||||
**Currently only supported in conjunction with the ``oslo_conf``
|
||||
kwarg.**
|
||||
:param global_request_id: A Request-id to send with all interactions.
|
||||
:param kwargs: If a config is not provided, the rest of the parameters
|
||||
provided are assumed to be arguments to be passed to the
|
||||
CloudRegion constructor.
|
||||
@ -363,6 +365,7 @@ class Connection(six.with_metaclass(_meta.ConnectionMeta,
|
||||
self._session = None
|
||||
self._proxies = {}
|
||||
self.__pool_executor = None
|
||||
self._global_request_id = global_request_id
|
||||
self.use_direct_get = use_direct_get
|
||||
self.strict_mode = strict
|
||||
# Call the _*CloudMixin constructors while we work on
|
||||
@ -479,6 +482,9 @@ class Connection(six.with_metaclass(_meta.ConnectionMeta,
|
||||
if self.__pool_executor:
|
||||
self.__pool_executor.shutdown()
|
||||
|
||||
def set_global_request_id(self, global_request_id):
|
||||
self._global_request_id = global_request_id
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
|
@ -144,10 +144,17 @@ class Proxy(adapter.Adapter):
|
||||
|
||||
def request(
|
||||
self, url, method, error_message=None,
|
||||
raise_exc=False, connect_retries=1, *args, **kwargs):
|
||||
raise_exc=False, connect_retries=1,
|
||||
global_request_id=None, *args, **kwargs):
|
||||
if not global_request_id:
|
||||
conn = self._get_connection()
|
||||
if conn:
|
||||
# Per-request setting should take precedence
|
||||
global_request_id = conn._global_request_id
|
||||
response = super(Proxy, self).request(
|
||||
url, method,
|
||||
connect_retries=connect_retries, raise_exc=False,
|
||||
global_request_id=global_request_id,
|
||||
**kwargs)
|
||||
for h in response.history:
|
||||
self._report_stats(h)
|
||||
|
@ -106,6 +106,44 @@ class TestShade(base.TestCase):
|
||||
r = self.cloud.get_image('doesNotExist')
|
||||
self.assertIsNone(r)
|
||||
|
||||
def test_global_request_id(self):
|
||||
request_id = uuid.uuid4().hex
|
||||
self.register_uris([
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']),
|
||||
json={'servers': []},
|
||||
validate=dict(
|
||||
headers={'X-Openstack-Request-Id': request_id}),
|
||||
),
|
||||
])
|
||||
|
||||
cloud2 = self.cloud.global_request(request_id)
|
||||
self.assertEqual([], cloud2.list_servers())
|
||||
|
||||
self.assert_calls()
|
||||
|
||||
def test_global_request_id_context(self):
|
||||
request_id = uuid.uuid4().hex
|
||||
self.register_uris([
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']),
|
||||
json={'servers': []},
|
||||
validate=dict(
|
||||
headers={'X-Openstack-Request-Id': request_id}),
|
||||
),
|
||||
])
|
||||
|
||||
with self.cloud.global_request(request_id) as c2:
|
||||
self.assertEqual([], c2.list_servers())
|
||||
|
||||
self.assert_calls()
|
||||
|
||||
def test_get_server(self):
|
||||
server1 = fakes.make_fake_server('123', 'mickey')
|
||||
server2 = fakes.make_fake_server('345', 'mouse')
|
||||
|
11
releasenotes/notes/global-request-id-d7c0736f43929165.yaml
Normal file
11
releasenotes/notes/global-request-id-d7c0736f43929165.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added support for setting ``global_request_id`` on a ``Connection``.
|
||||
If done, this will cause all requests sent to send the request id
|
||||
header to the OpenStack services. Since ``Connection`` can otherwise
|
||||
be used multi-threaded, add a method ``global_request`` that returns
|
||||
a new ``Connection`` based on the old ``Connection`` but on which
|
||||
the new ``global_request_id`` has been set. Since a ``Connection``
|
||||
can be used as a context manager, this also means the ``global_request``
|
||||
method can be used in ``with`` statements.
|
@ -8,7 +8,7 @@ requestsexceptions>=1.2.0 # Apache-2.0
|
||||
jsonpatch!=1.20,>=1.16 # BSD
|
||||
six>=1.10.0 # MIT
|
||||
os-service-types>=1.7.0 # Apache-2.0
|
||||
keystoneauth1>=3.14.0 # Apache-2.0
|
||||
keystoneauth1>=3.15.0 # Apache-2.0
|
||||
|
||||
munch>=2.1.0 # MIT
|
||||
decorator>=3.4.0 # BSD
|
||||
|
Loading…
x
Reference in New Issue
Block a user