Create session for XSRF token

To avoid CSRF attacks, the requests to the NSX manager should have
X-XSRF-TOKEN header.
To get it, and the JSESSIONID, the cluster will issue a session/create
request for each endpoint at init, and retrieve the values from the response
header.
Those values will later be used for each request to this endpoint.

Change-Id: I24cf6416e38dc7f57d7d8ceece48a1d3d5815112
This commit is contained in:
Adit Sarfaty 2017-08-03 14:26:04 +03:00
parent 2a68ede0c0
commit 5467ac673a
5 changed files with 192 additions and 62 deletions

View File

@ -20,6 +20,7 @@ import mock
from oslo_serialization import jsonutils
from oslo_utils import uuidutils
from requests import exceptions as requests_exceptions
from requests import models
from vmware_nsxlib import v3
from vmware_nsxlib.v3 import client as nsx_client
@ -47,6 +48,8 @@ PLUGIN_VER = "plugin ver"
DNS_NAMESERVERS = ['1.1.1.1']
DNS_DOMAIN = 'openstacklocal'
JSESSIONID = 'my_sess_id'
def _mock_nsxlib():
def _return_id_key(*args, **kwargs):
@ -316,8 +319,28 @@ class NsxClientTestCase(NsxLibTestCase):
assert conn is not None
def mock_nsx_clustered_api(self, session_response=None, **kwargs):
return NsxClientTestCase.MockNSXClusteredAPI(
session_response=session_response, **kwargs)
orig_request = nsx_cluster.TimeoutSession.request
def mocked_request(*args, **kwargs):
if args[2].endswith('api/session/create'):
response = models.Response()
response.status_code = 200
response.headers = {
'Set-Cookie': 'JSESSIONID=%s;junk' % JSESSIONID}
return response
return orig_request(*args, **kwargs)
with mock.patch.object(nsx_cluster.TimeoutSession, 'request',
new=mocked_request):
cluster = NsxClientTestCase.MockNSXClusteredAPI(
session_response=session_response, **kwargs)
return cluster
@staticmethod
def default_headers():
return {'Content-Type': 'application/json',
'Accept': 'application/json',
'Cookie': 'JSESSIONID=%s;' % JSESSIONID}
def mocked_resource(self, resource_class, mock_validate=True,
session_response=None):
@ -368,12 +391,14 @@ class NsxClientTestCase(NsxLibTestCase):
return nsx_cluster.NSXClusteredAPI(nsxlib_config)
def assert_json_call(self, method, client, url,
headers=nsx_client.JSONRESTClient._DEFAULT_HEADERS,
headers=None,
timeout=(NSX_HTTP_TIMEOUT, NSX_HTTP_READ_TIMEOUT),
data=None):
cluster = client._conn
if data:
data = jsonutils.dumps(data, sort_keys=True)
if not headers:
headers = self.default_headers()
cluster.assert_called_once(
method,
**{'url': url, 'verify': NSX_CERT, 'body': data,

View File

@ -30,7 +30,14 @@ LOG = log.getLogger(__name__)
CLIENT_PKG = 'vmware_nsxlib.v3.client'
DFT_ACCEPT_HEADERS = {
'Accept': '*/*'
'Accept': '*/*',
'Cookie': 'JSESSIONID=%s;' % nsxlib_testcase.JSESSIONID
}
JSON_DFT_ACCEPT_HEADERS = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Cookie': 'JSESSIONID=%s;' % nsxlib_testcase.JSESSIONID
}
@ -65,7 +72,7 @@ def assert_call(verb, client_or_resource,
def assert_json_call(verb, client_or_resource, url,
verify=nsxlib_testcase.NSX_CERT,
data=None,
headers=client.JSONRESTClient._DEFAULT_HEADERS,
headers=JSON_DFT_ACCEPT_HEADERS,
single_call=True):
return assert_call(verb, client_or_resource, url,
verify=verify, data=data,

View File

@ -18,6 +18,7 @@ import unittest
import mock
from oslo_serialization import jsonutils
from requests import exceptions as requests_exceptions
from requests import models
import six.moves.urllib.parse as urlparse
from vmware_nsxlib.tests.unit.v3 import mocks
@ -36,6 +37,13 @@ def _validate_conn_down(*args, **kwargs):
raise requests_exceptions.ConnectionError()
def get_sess_create_resp():
sess_create_response = models.Response()
sess_create_response.status_code = 200
sess_create_response.headers = {'Set-Cookie': 'JSESSIONID=abc;'}
return sess_create_response
class RequestsHTTPProviderTestCase(unittest.TestCase):
def test_new_connection(self):
@ -50,15 +58,18 @@ class RequestsHTTPProviderTestCase(unittest.TestCase):
mock_api.nsxlib_config.conn_idle_timeout = 39
mock_api.nsxlib_config.client_cert_provider = None
provider = cluster.NSXRequestsHTTPProvider()
session = provider.new_connection(
mock_api, cluster.Provider('9.8.7.6', 'https://9.8.7.6',
'nsxuser', 'nsxpassword', None))
with mock.patch.object(cluster.TimeoutSession, 'request',
return_value=get_sess_create_resp()):
session = provider.new_connection(
mock_api, cluster.Provider('9.8.7.6', 'https://9.8.7.6',
'nsxuser', 'nsxpassword', None))
self.assertEqual(('nsxuser', 'nsxpassword'), session.auth)
self.assertFalse(session.verify)
self.assertIsNone(session.cert)
self.assertEqual(100, session.adapters['https://'].max_retries.total)
self.assertEqual(99, session.timeout)
self.assertEqual(('nsxuser', 'nsxpassword'), session.auth)
self.assertFalse(session.verify)
self.assertIsNone(session.cert)
self.assertEqual(100,
session.adapters['https://'].max_retries.total)
self.assertEqual(99, session.timeout)
def test_new_connection_with_client_auth(self):
mock_api = mock.Mock()
@ -72,14 +83,16 @@ class RequestsHTTPProviderTestCase(unittest.TestCase):
'/etc/cert.pem')
mock_api.nsxlib_config.client_cert_provider = cert_provider_inst
provider = cluster.NSXRequestsHTTPProvider()
session = provider.new_connection(
mock_api, cluster.Provider('9.8.7.6', 'https://9.8.7.6',
None, None, None))
with mock.patch.object(cluster.TimeoutSession, 'request',
return_value=get_sess_create_resp()):
session = provider.new_connection(
mock_api, cluster.Provider('9.8.7.6', 'https://9.8.7.6',
None, None, None))
self.assertIsNone(session.auth)
self.assertFalse(session.verify)
self.assertEqual(cert_provider_inst, session.cert_provider)
self.assertEqual(99, session.timeout)
self.assertIsNone(session.auth)
self.assertFalse(session.verify)
self.assertEqual(cert_provider_inst, session.cert_provider)
self.assertEqual(99, session.timeout)
def test_validate_connection(self):
self.skipTest("Revist")
@ -231,6 +244,8 @@ class ClusteredAPITestCase(nsxlib_testcase.NsxClientTestCase):
self.assertEqual(_get_schedule(4), [eps[0], eps[2], eps[0], eps[2]])
def test_reinitialize_cluster(self):
api = self.mock_nsx_clustered_api()
# just make sure this api is defined, and does not crash
api._reinit_cluster()
with mock.patch.object(cluster.TimeoutSession, 'request',
return_value=get_sess_create_resp()):
api = self.mock_nsx_clustered_api()
# just make sure this api is defined, and does not crash
api._reinit_cluster()

View File

@ -53,7 +53,8 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
'resource_type': profile_types.PORT_MIRRORING,
'display_name': 'pm-profile',
'description': 'port mirror prof'
}, sort_keys=True))
}, sort_keys=True),
headers=self.default_headers())
def test_switching_profile_update(self):
@ -79,7 +80,8 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
data=jsonutils.dumps({
'resource_type': profile_types.PORT_MIRRORING,
'tags': tags
}, sort_keys=True))
}, sort_keys=True),
headers=self.default_headers())
def test_spoofgaurd_profile_create(self):
@ -109,7 +111,8 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
'description': 'spoofguard-for-plugin',
'white_list_providers': ['LPORT_BINDINGS'],
'tags': tags
}, sort_keys=True))
}, sort_keys=True),
headers=self.default_headers())
def test_create_dhcp_profile(self):
@ -154,7 +157,8 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
'tx_multicast': 0
},
'block_non_ip_traffic': True
}, sort_keys=True))
}, sort_keys=True),
headers=self.default_headers())
def test_create_mac_learning_profile(self):
@ -187,7 +191,8 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
'description': 'mac-learning-for-plugin',
'tags': tags,
'mac_change_allowed': True,
}, sort_keys=True))
}, sort_keys=True),
headers=self.default_headers())
def test_find_by_display_name(self):
resp_resources = {
@ -230,7 +235,8 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
'get', mocked_resource,
'https://1.2.3.4/api/v1/switching-profiles/'
'?include_system_owned=True',
data=None)
data=None,
headers=self.default_headers())
class LogicalPortTestCase(nsxlib_testcase.NsxClientTestCase):
@ -300,7 +306,8 @@ class LogicalPortTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', mocked_resource,
'https://1.2.3.4/api/v1/logical-ports',
data=jsonutils.dumps(resp_body, sort_keys=True))
data=jsonutils.dumps(resp_body, sort_keys=True),
headers=self.default_headers())
def test_create_logical_port_with_attachtype_cif(self):
"""Test creating a port returns the correct response and 200 status
@ -353,7 +360,8 @@ class LogicalPortTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', mocked_resource,
'https://1.2.3.4/api/v1/logical-ports',
data=jsonutils.dumps(resp_body, sort_keys=True))
data=jsonutils.dumps(resp_body, sort_keys=True),
headers=self.default_headers())
def test_create_logical_port_admin_down(self):
"""Test creating port with admin_state down."""
@ -379,7 +387,8 @@ class LogicalPortTestCase(nsxlib_testcase.NsxClientTestCase):
mocked_resource.delete(uuid)
test_client.assert_json_call(
'delete', mocked_resource,
'https://1.2.3.4/api/v1/logical-ports/%s?detach=true' % uuid)
'https://1.2.3.4/api/v1/logical-ports/%s?detach=true' % uuid,
headers=self.default_headers())
def test_get_logical_port_by_attachment(self):
"""Test deleting port."""
@ -390,7 +399,8 @@ class LogicalPortTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'get', mocked_resource,
"https://1.2.3.4/api/v1/logical-ports/?attachment_type=%s"
"&attachment_id=%s" % (attachment_type, attachment_id))
"&attachment_id=%s" % (attachment_type, attachment_id),
headers=self.default_headers())
def test_clear_port_bindings(self):
fake_port = copy.copy(test_constants.FAKE_PORT)
@ -408,7 +418,8 @@ class LogicalPortTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'put', mocked_resource,
'https://1.2.3.4/api/v1/logical-ports/%s' % fake_port['id'],
data=jsonutils.dumps(fake_port, sort_keys=True))
data=jsonutils.dumps(fake_port, sort_keys=True),
headers=self.default_headers())
def test_create_logical_port_fail(self):
"""Test the failure of port creation."""
@ -464,7 +475,8 @@ class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', router,
'https://1.2.3.4/api/v1/logical-routers',
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_delete_logical_router(self):
"""Test deleting router"""
@ -473,7 +485,8 @@ class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
router.delete(uuid)
test_client.assert_json_call(
'delete', router,
'https://1.2.3.4/api/v1/logical-routers/%s' % uuid)
'https://1.2.3.4/api/v1/logical-routers/%s' % uuid,
headers=self.default_headers())
def test_force_delete_logical_router(self):
"""Test force deleting router"""
@ -482,7 +495,8 @@ class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
router.delete(uuid, True)
test_client.assert_json_call(
'delete', router,
'https://1.2.3.4/api/v1/logical-routers/%s?force=True' % uuid)
'https://1.2.3.4/api/v1/logical-routers/%s?force=True' % uuid,
headers=self.default_headers())
def test_get_logical_router_fw_section(self):
fake_router = test_constants.FAKE_ROUTER.copy()
@ -520,7 +534,8 @@ class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
'post', router,
('https://1.2.3.4/api/v1/logical-routers/%s/nat/rules' %
test_constants.FAKE_ROUTER_UUID),
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_nat_rule_create_v1(self):
# Ignoring 'bypass_firewall' with version 1.1
@ -536,7 +551,8 @@ class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'get', router,
('https://1.2.3.4/api/v1/logical-routers/%s/nat/rules' %
test_constants.FAKE_ROUTER_UUID))
test_constants.FAKE_ROUTER_UUID),
headers=self.default_headers())
def test_nat_rule_update(self):
router = self._mocked_lrouter()
@ -550,7 +566,8 @@ class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
'put', router,
('https://1.2.3.4/api/v1/logical-routers/%s/nat/rules/%s' %
(test_constants.FAKE_ROUTER_UUID, rule_id)),
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_delete_nat_rule_by_gw(self):
router = self._mocked_lrouter()
@ -569,7 +586,8 @@ class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'delete', router,
('https://1.2.3.4/api/v1/logical-routers/%s/nat/rules/%s' %
(test_constants.FAKE_ROUTER_UUID, rule_id)))
(test_constants.FAKE_ROUTER_UUID, rule_id)),
headers=self.default_headers())
def test_delete_nat_rule_by_gw_and_source(self):
router = self._mocked_lrouter()
@ -591,7 +609,8 @@ class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'delete', router,
('https://1.2.3.4/api/v1/logical-routers/%s/nat/rules/%s' %
(test_constants.FAKE_ROUTER_UUID, rule_id)))
(test_constants.FAKE_ROUTER_UUID, rule_id)),
headers=self.default_headers())
class LogicalRouterPortTestCase(nsxlib_testcase.NsxClientTestCase):
@ -631,7 +650,8 @@ class LogicalRouterPortTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', lrport,
'https://1.2.3.4/api/v1/logical-router-ports',
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_logical_router_port_max_attempts(self):
"""Test a router port api has the configured retries."""
@ -648,7 +668,8 @@ class LogicalRouterPortTestCase(nsxlib_testcase.NsxClientTestCase):
lrport.delete(uuid)
test_client.assert_json_call(
'delete', lrport,
'https://1.2.3.4/api/v1/logical-router-ports/%s' % uuid)
'https://1.2.3.4/api/v1/logical-router-ports/%s' % uuid,
headers=self.default_headers())
def test_update_logical_router_port(self):
fake_router_port = test_constants.FAKE_ROUTER_PORT.copy()
@ -674,7 +695,8 @@ class LogicalRouterPortTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'put', lrport,
'https://1.2.3.4/api/v1/logical-router-ports/%s' % uuid,
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_get_logical_router_port_by_router_id(self):
"""Test getting a router port by router id."""
@ -691,7 +713,8 @@ class LogicalRouterPortTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'get', lrport,
'https://1.2.3.4/api/v1/logical-router-ports/?'
'logical_router_id=%s' % router_id)
'logical_router_id=%s' % router_id,
headers=self.default_headers())
def test_get_logical_router_port_by_switch_id(self):
"""Test getting a router port by switch id."""
@ -710,7 +733,8 @@ class LogicalRouterPortTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'get', lrport,
'https://1.2.3.4/api/v1/logical-router-ports/?'
'logical_switch_id=%s' % switch_id)
'logical_switch_id=%s' % switch_id,
headers=self.default_headers())
class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
@ -753,7 +777,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', pool,
'https://1.2.3.4/api/v1/pools/ip-pools',
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_create_ip_pool_minimal_args(self):
pool = self._mocked_pool()
@ -773,7 +798,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', pool,
'https://1.2.3.4/api/v1/pools/ip-pools',
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_create_ip_pool_no_ranges_with_gateway(self):
pool = self._mocked_pool()
@ -794,7 +820,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', pool,
'https://1.2.3.4/api/v1/pools/ip-pools',
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_create_ip_pool_no_ranges_no_gateway(self):
pool = self._mocked_pool()
@ -812,7 +839,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', pool,
'https://1.2.3.4/api/v1/pools/ip-pools',
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_create_ip_pool_no_cidr(self):
pool = self._mocked_pool()
@ -844,7 +872,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'put', pool,
'https://1.2.3.4/api/v1/pools/ip-pools/%s' % uuid,
data=jsonutils.dumps(fake_ip_pool, sort_keys=True))
data=jsonutils.dumps(fake_ip_pool, sort_keys=True),
headers=self.default_headers())
def test_update_ip_pool_gateway(self):
fake_ip_pool = test_constants.FAKE_IP_POOL.copy()
@ -860,7 +889,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'put', pool,
'https://1.2.3.4/api/v1/pools/ip-pools/%s' % uuid,
data=jsonutils.dumps(fake_ip_pool, sort_keys=True))
data=jsonutils.dumps(fake_ip_pool, sort_keys=True),
headers=self.default_headers())
def test_update_ip_pool_delete_gateway(self):
fake_ip_pool = test_constants.FAKE_IP_POOL.copy()
@ -875,7 +905,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'put', pool,
'https://1.2.3.4/api/v1/pools/ip-pools/%s' % uuid,
data=jsonutils.dumps(fake_ip_pool, sort_keys=True))
data=jsonutils.dumps(fake_ip_pool, sort_keys=True),
headers=self.default_headers())
def test_get_ip_pool(self):
"""Test getting a router port by router id"""
@ -891,7 +922,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
self.assertEqual(fake_ip_pool, result)
test_client.assert_json_call(
'get', pool,
'https://1.2.3.4/api/v1/pools/ip-pools/%s' % uuid)
'https://1.2.3.4/api/v1/pools/ip-pools/%s' % uuid,
headers=self.default_headers())
def test_delete_ip_pool(self):
"""Test deleting router port"""
@ -901,7 +933,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
pool.delete(uuid)
test_client.assert_json_call(
'delete', pool,
'https://1.2.3.4/api/v1/pools/ip-pools/%s' % uuid)
'https://1.2.3.4/api/v1/pools/ip-pools/%s' % uuid,
headers=self.default_headers())
def test_allocate_ip_from_pool(self):
pool = self._mocked_pool()
@ -914,7 +947,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', pool,
'https://1.2.3.4/api/v1/pools/ip-pools/%s?action=ALLOCATE' % uuid,
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_release_ip_to_pool(self):
pool = self._mocked_pool()
@ -927,7 +961,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
test_client.assert_json_call(
'post', pool,
'https://1.2.3.4/api/v1/pools/ip-pools/%s?action=RELEASE' % uuid,
data=jsonutils.dumps(data, sort_keys=True))
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_get_ip_pool_allocations(self):
"""Test getting a router port by router id"""
@ -943,7 +978,8 @@ class IpPoolTestCase(nsxlib_testcase.NsxClientTestCase):
self.assertEqual(fake_ip_pool, result)
test_client.assert_json_call(
'get', pool,
'https://1.2.3.4/api/v1/pools/ip-pools/%s/allocations' % uuid)
'https://1.2.3.4/api/v1/pools/ip-pools/%s/allocations' % uuid,
headers=self.default_headers())
class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):

View File

@ -19,6 +19,7 @@ import copy
import datetime
import itertools
import logging
import re
import eventlet
from eventlet import greenpool
@ -105,8 +106,8 @@ class TimeoutSession(requests.Session):
def request(self, *args, **kwargs):
if 'timeout' not in kwargs:
kwargs['timeout'] = (self.timeout, self.read_timeout)
if not self._cert_provider:
skip_cert = kwargs.pop('skip_cert', False)
if not self._cert_provider or skip_cert:
return super(TimeoutSession, self).request(*args, **kwargs)
if self.cert is not None:
@ -145,6 +146,12 @@ class NSXRequestsHTTPProvider(AbstractHTTPProvider):
using requests.Session() as the underlying connection.
"""
SESSION_CREATE_URL = '/api/session/create'
COOKIE_FIELD = 'Cookie'
SET_COOKIE_FIELD = 'Set-Cookie'
XSRF_TOKEN = 'X-XSRF-TOKEN'
JSESSIONID = 'JSESSIONID'
@property
def provider_id(self):
return "%s-%s" % (requests.__title__, requests.__version__)
@ -152,7 +159,8 @@ class NSXRequestsHTTPProvider(AbstractHTTPProvider):
def validate_connection(self, cluster_api, endpoint, conn):
client = nsx_client.NSX3Client(
conn, url_prefix=endpoint.provider.url,
url_path_base=cluster_api.nsxlib_config.url_base)
url_path_base=cluster_api.nsxlib_config.url_base,
default_headers=conn.default_headers)
keepalive_section = cluster_api.nsxlib_config.keepalive_section
result = client.get(keepalive_section, silent=True)
# If keeplive section returns a list, it is assumed to be non-empty
@ -189,11 +197,45 @@ class NSXRequestsHTTPProvider(AbstractHTTPProvider):
session.mount('http://', adapter)
session.mount('https://', adapter)
self.get_default_headers(session, provider)
return session
def is_connection_exception(self, exception):
return isinstance(exception, requests_exceptions.ConnectionError)
def get_default_headers(self, session, provider):
"""Get the default headers that should be added to future requests"""
session.default_headers = {}
# Perform the initial session create and get the relevant jsessionid &
# X-XSRF-TOKEN for future requests
req_data = 'j_username=%s&j_password=%s' % (provider.username,
provider.password)
req_headers = {'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'}
# Cannot use the certificate at this stage, because it is used for
# the certificate generation
resp = session.request('post', provider.url + self.SESSION_CREATE_URL,
data=req_data, headers=req_headers,
skip_cert=True)
if resp.status_code != 200:
LOG.error("Session create failed for endpoint %s", provider.url)
# this will later cause the endpoint to be Down
else:
for header_name in resp.headers:
if self.SET_COOKIE_FIELD.lower() == header_name.lower():
m = re.match('%s=.*?\;' % self.JSESSIONID,
resp.headers[header_name])
if m:
session.default_headers[self.COOKIE_FIELD] = m.group()
if self.XSRF_TOKEN.lower() == header_name.lower():
session.default_headers[self.XSRF_TOKEN] = resp.headers[
header_name]
LOG.info("Session create succeeded for endpoint %(url)s with "
"headers %(hdr)s",
{'url': provider.url, 'hdr': session.default_headers})
class ClusterHealth(object):
"""Indicator of overall cluster health.
@ -494,6 +536,11 @@ class ClusteredAPI(object):
try:
LOG.debug("API cluster proxy %s %s to %s",
proxy_for.upper(), uri, url)
# Add the connection default headers
if conn.default_headers:
kwargs['headers'] = kwargs.get('headers', {})
kwargs['headers'].update(conn.default_headers)
# call the actual connection method to do the
# http request/response over the wire
response = do_request(url, *args, **kwargs)