Add SoapAdapter request context per instance.
SoapStubAdapter supports adding soap headers using GetRequestContext, but the request context is thread-local. Adding support for a per-instance request context. This is needed e.g. for vSphere SMS API, where only the SMS SoapAdapter needs the additional headers.
This commit is contained in:
parent
b7fa79dc45
commit
a5a3aa996e
|
@ -901,6 +901,8 @@ class SoapStubAdapterBase(StubAdapterBase):
|
||||||
|
|
||||||
# Add request context and samlToken to soap header, if exists
|
# Add request context and samlToken to soap header, if exists
|
||||||
reqContexts = GetRequestContext()
|
reqContexts = GetRequestContext()
|
||||||
|
if self.requestContext:
|
||||||
|
reqContexts.update(self.requestContext)
|
||||||
samlToken = getattr(self, 'samlToken', None)
|
samlToken = getattr(self, 'samlToken', None)
|
||||||
|
|
||||||
if reqContexts or samlToken:
|
if reqContexts or samlToken:
|
||||||
|
@ -1197,7 +1199,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
|
||||||
thumbprint=None, cacertsFile=None, version=None,
|
thumbprint=None, cacertsFile=None, version=None,
|
||||||
acceptCompressedResponses=True,
|
acceptCompressedResponses=True,
|
||||||
connectionPoolTimeout=CONNECTION_POOL_IDLE_TIMEOUT_SEC,
|
connectionPoolTimeout=CONNECTION_POOL_IDLE_TIMEOUT_SEC,
|
||||||
samlToken=None, sslContext=None):
|
samlToken=None, sslContext=None, requestContext=None):
|
||||||
if ns:
|
if ns:
|
||||||
assert(version is None)
|
assert(version is None)
|
||||||
version = versionMap[ns]
|
version = versionMap[ns]
|
||||||
|
@ -1263,6 +1265,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
|
||||||
if sslContext:
|
if sslContext:
|
||||||
self.schemeArgs['context'] = sslContext
|
self.schemeArgs['context'] = sslContext
|
||||||
self.samlToken = samlToken
|
self.samlToken = samlToken
|
||||||
|
self.requestContext = requestContext
|
||||||
self.requestModifierList = []
|
self.requestModifierList = []
|
||||||
self._acceptCompressedResponses = acceptCompressedResponses
|
self._acceptCompressedResponses = acceptCompressedResponses
|
||||||
|
|
||||||
|
|
|
@ -19,41 +19,10 @@ import vcr
|
||||||
from pyVmomi import SoapAdapter
|
from pyVmomi import SoapAdapter
|
||||||
from pyVmomi import SoapStubAdapter
|
from pyVmomi import SoapStubAdapter
|
||||||
from pyVmomi import vim
|
from pyVmomi import vim
|
||||||
|
from pyVmomi.VmomiSupport import GetRequestContext
|
||||||
|
|
||||||
|
|
||||||
class SerializerTests(tests.VCRTestBase):
|
class SerializerTests(tests.VCRTestBase):
|
||||||
|
|
||||||
def test_simple_request_serializer(self):
|
|
||||||
def request_matcher(r1, r2):
|
|
||||||
soap_msg = ('<soapenv:Body>'
|
|
||||||
'<RetrieveServiceContent xmlns="urn:vim25">'
|
|
||||||
'<_this type="ServiceInstance">'
|
|
||||||
'ServiceInstance'
|
|
||||||
'</_this>'
|
|
||||||
'</RetrieveServiceContent>'
|
|
||||||
'</soapenv:Body>')
|
|
||||||
if soap_msg in r1.body.decode("utf-8"):
|
|
||||||
return True
|
|
||||||
raise SystemError('serialization error occurred')
|
|
||||||
|
|
||||||
my_vcr = vcr.VCR()
|
|
||||||
my_vcr.register_matcher('request_matcher', request_matcher)
|
|
||||||
|
|
||||||
with my_vcr.use_cassette(
|
|
||||||
'test_simple_request_serializer.yaml',
|
|
||||||
cassette_library_dir=tests.fixtures_path,
|
|
||||||
record_mode='none',
|
|
||||||
match_on=['request_matcher']) as cass:
|
|
||||||
host = 'vcsa'
|
|
||||||
port = 443
|
|
||||||
stub = SoapStubAdapter(host, port)
|
|
||||||
si = vim.ServiceInstance("ServiceInstance", stub)
|
|
||||||
content = si.RetrieveContent()
|
|
||||||
self.assertTrue(content is not None)
|
|
||||||
self.assertTrue(
|
|
||||||
'<_this type="ServiceInstance">ServiceInstance</_this>'
|
|
||||||
in cass.requests[0].body.decode("utf-8"))
|
|
||||||
|
|
||||||
def test_serialize_object(self):
|
def test_serialize_object(self):
|
||||||
val = vim.vm.device.VirtualDeviceSpec.FileOperation()
|
val = vim.vm.device.VirtualDeviceSpec.FileOperation()
|
||||||
# This line should not raise an exception, especially on Python 3.
|
# This line should not raise an exception, especially on Python 3.
|
||||||
|
@ -68,4 +37,62 @@ class SerializerTests(tests.VCRTestBase):
|
||||||
def test_serialize_float(self):
|
def test_serialize_float(self):
|
||||||
pc = vim.host.VsanInternalSystem.PolicyCost()
|
pc = vim.host.VsanInternalSystem.PolicyCost()
|
||||||
pc.diskSpaceToAddressSpaceRatio = 1.0
|
pc.diskSpaceToAddressSpaceRatio = 1.0
|
||||||
SoapAdapter.Serialize(pc, version='vim.version.version10')
|
SoapAdapter.Serialize(pc, version='vim.version.version10')
|
||||||
|
|
||||||
|
def _base_serialize_test(self, soap_creator, request_matcher):
|
||||||
|
my_vcr = vcr.VCR()
|
||||||
|
my_vcr.register_matcher('request_matcher', request_matcher)
|
||||||
|
|
||||||
|
with my_vcr.use_cassette(
|
||||||
|
'test_simple_request_serializer.yaml',
|
||||||
|
cassette_library_dir=tests.fixtures_path,
|
||||||
|
record_mode='none',
|
||||||
|
match_on=['request_matcher']) as cass:
|
||||||
|
stub = soap_creator()
|
||||||
|
si = vim.ServiceInstance("ServiceInstance", stub)
|
||||||
|
content = si.RetrieveContent()
|
||||||
|
self.assertTrue(content is not None)
|
||||||
|
self.assertTrue(
|
||||||
|
'<_this type="ServiceInstance">ServiceInstance</_this>'
|
||||||
|
in cass.requests[0].body.decode("utf-8"))
|
||||||
|
|
||||||
|
def _body_request_matcher(self, r1, r2):
|
||||||
|
soap_msg = ('<soapenv:Body>'
|
||||||
|
'<RetrieveServiceContent xmlns="urn:vim25">'
|
||||||
|
'<_this type="ServiceInstance">'
|
||||||
|
'ServiceInstance'
|
||||||
|
'</_this>'
|
||||||
|
'</RetrieveServiceContent>'
|
||||||
|
'</soapenv:Body>')
|
||||||
|
if soap_msg in r1.body.decode("utf-8"):
|
||||||
|
return True
|
||||||
|
raise SystemError('serialization error occurred')
|
||||||
|
|
||||||
|
def _request_context_request_matcher(self, r1, r2):
|
||||||
|
request_context = ('<soapenv:Header><vcSessionCookie>123456789</vcSessionCookie></soapenv:Header>')
|
||||||
|
if request_context in r1.body.decode("utf-8"):
|
||||||
|
return True
|
||||||
|
raise SystemError('serialization error occurred')
|
||||||
|
|
||||||
|
def test_simple_request_serializer(self):
|
||||||
|
def soap_creator():
|
||||||
|
return SoapStubAdapter('vcsa', 443)
|
||||||
|
self._base_serialize_test(soap_creator, self._body_request_matcher)
|
||||||
|
|
||||||
|
def test_request_context_serializer_instance(self):
|
||||||
|
def request_matcher(r1, r2):
|
||||||
|
return self._request_context_request_matcher(r1, r2) and self._body_request_matcher(r1, r2)
|
||||||
|
def soap_creator():
|
||||||
|
return SoapStubAdapter('vcsa', 443, requestContext={'vcSessionCookie': '123456789'})
|
||||||
|
self._base_serialize_test(soap_creator, request_matcher)
|
||||||
|
|
||||||
|
def test_request_context_serializer_global(self):
|
||||||
|
def request_matcher(r1, r2):
|
||||||
|
return self._request_context_request_matcher(r1, r2) and self._body_request_matcher(r1, r2)
|
||||||
|
def soap_creator():
|
||||||
|
return SoapStubAdapter('vcsa', 443)
|
||||||
|
GetRequestContext()['vcSessionCookie'] = '123456789'
|
||||||
|
try:
|
||||||
|
self._base_serialize_test(soap_creator, request_matcher)
|
||||||
|
finally:
|
||||||
|
GetRequestContext().pop("vcSessionCookie")
|
||||||
|
|
Loading…
Reference in New Issue