Merge "BSN: Add context to backend request for debugging"
This commit is contained in:
commit
ae59c35ef9
@ -448,7 +448,9 @@ class NeutronRestProxyV2Base(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
def put_context_in_serverpool(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(self, context, *args, **kwargs):
|
||||
self.servers.set_context(context)
|
||||
# core plugin: context is top level object
|
||||
# ml2: keeps context in _plugin_context
|
||||
self.servers.set_context(getattr(context, '_plugin_context', context))
|
||||
return f(self, context, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
@ -72,6 +72,7 @@ FAILURE_CODES = [0, 301, 302, 303, 400, 401, 403, 404, 500, 501, 502, 503,
|
||||
BASE_URI = '/networkService/v1.1'
|
||||
ORCHESTRATION_SERVICE_ID = 'Neutron v2.0'
|
||||
HASH_MATCH_HEADER = 'X-BSN-BVS-HASH-MATCH'
|
||||
REQ_CONTEXT_HEADER = 'X-REQ-CONTEXT'
|
||||
# error messages
|
||||
NXNETWORK = 'NXVNS'
|
||||
HTTP_SERVICE_UNAVAILABLE_RETRY_COUNT = 3
|
||||
@ -125,12 +126,11 @@ class ServerProxy(object):
|
||||
'cap': self.capabilities})
|
||||
return self.capabilities
|
||||
|
||||
def rest_call(self, action, resource, data='', headers={}, timeout=False,
|
||||
reconnect=False, hash_handler=None):
|
||||
def rest_call(self, action, resource, data='', headers=None,
|
||||
timeout=False, reconnect=False, hash_handler=None):
|
||||
uri = self.base_uri + resource
|
||||
body = jsonutils.dumps(data)
|
||||
if not headers:
|
||||
headers = {}
|
||||
headers = headers or {}
|
||||
headers['Content-type'] = 'application/json'
|
||||
headers['Accept'] = 'application/json'
|
||||
headers['NeutronProxy-Agent'] = self.name
|
||||
@ -425,7 +425,15 @@ class ServerPool(object):
|
||||
@utils.synchronized('bsn-rest-call')
|
||||
def rest_call(self, action, resource, data, headers, ignore_codes,
|
||||
timeout=False):
|
||||
hash_handler = cdb.HashHandler(context=self.get_context_ref())
|
||||
context = self.get_context_ref()
|
||||
if context:
|
||||
# include the requesting context information if available
|
||||
cdict = context.to_dict()
|
||||
# remove the auth token so it's not present in debug logs on the
|
||||
# backend controller
|
||||
cdict.pop('auth_token', None)
|
||||
headers[REQ_CONTEXT_HEADER] = jsonutils.dumps(cdict)
|
||||
hash_handler = cdb.HashHandler(context=context)
|
||||
good_first = sorted(self.servers, key=lambda x: x.failed)
|
||||
first_response = None
|
||||
for active_server in good_first:
|
||||
@ -479,13 +487,15 @@ class ServerPool(object):
|
||||
return first_response
|
||||
|
||||
def rest_action(self, action, resource, data='', errstr='%s',
|
||||
ignore_codes=[], headers={}, timeout=False):
|
||||
ignore_codes=None, headers=None, timeout=False):
|
||||
"""
|
||||
Wrapper for rest_call that verifies success and raises a
|
||||
RemoteRestError on failure with a provided error string
|
||||
By default, 404 errors on DELETE calls are ignored because
|
||||
they already do not exist on the backend.
|
||||
"""
|
||||
ignore_codes = ignore_codes or []
|
||||
headers = headers or {}
|
||||
if not ignore_codes and action == 'DELETE':
|
||||
ignore_codes = [404]
|
||||
resp = self.rest_call(action, resource, data, headers, ignore_codes,
|
||||
|
@ -36,6 +36,7 @@ from neutron.plugins.ml2 import driver_api as api
|
||||
|
||||
EXTERNAL_PORT_OWNER = 'neutron:external_port'
|
||||
LOG = log.getLogger(__name__)
|
||||
put_context_in_serverpool = plugin.put_context_in_serverpool
|
||||
|
||||
# time in seconds to maintain existence of vswitch response
|
||||
CACHE_VSWITCH_TIME = 60
|
||||
@ -71,18 +72,22 @@ class BigSwitchMechanismDriver(plugin.NeutronRestProxyV2Base,
|
||||
|
||||
LOG.debug(_("Initialization done"))
|
||||
|
||||
@put_context_in_serverpool
|
||||
def create_network_postcommit(self, context):
|
||||
# create network on the network controller
|
||||
self._send_create_network(context.current)
|
||||
|
||||
@put_context_in_serverpool
|
||||
def update_network_postcommit(self, context):
|
||||
# update network on the network controller
|
||||
self._send_update_network(context.current)
|
||||
|
||||
@put_context_in_serverpool
|
||||
def delete_network_postcommit(self, context):
|
||||
# delete network on the network controller
|
||||
self._send_delete_network(context.current)
|
||||
|
||||
@put_context_in_serverpool
|
||||
def create_port_postcommit(self, context):
|
||||
# create port on the network controller
|
||||
port = self._prepare_port_for_controller(context)
|
||||
@ -90,6 +95,7 @@ class BigSwitchMechanismDriver(plugin.NeutronRestProxyV2Base,
|
||||
self.async_port_create(port["network"]["tenant_id"],
|
||||
port["network"]["id"], port)
|
||||
|
||||
@put_context_in_serverpool
|
||||
def update_port_postcommit(self, context):
|
||||
# update port on the network controller
|
||||
port = self._prepare_port_for_controller(context)
|
||||
@ -113,6 +119,7 @@ class BigSwitchMechanismDriver(plugin.NeutronRestProxyV2Base,
|
||||
triggered_by_tenant=port["network"]["tenant_id"]
|
||||
)
|
||||
|
||||
@put_context_in_serverpool
|
||||
def delete_port_postcommit(self, context):
|
||||
# delete port on the network controller
|
||||
port = context.current
|
||||
|
@ -22,8 +22,10 @@ import ssl
|
||||
import mock
|
||||
from oslo.config import cfg
|
||||
|
||||
from neutron import context
|
||||
from neutron import manager
|
||||
from neutron.openstack.common import importutils
|
||||
from neutron.openstack.common import jsonutils
|
||||
from neutron.plugins.bigswitch import servermanager
|
||||
from neutron.tests.unit.bigswitch import test_restproxy_plugin as test_rp
|
||||
|
||||
@ -211,6 +213,23 @@ class ServerManagerTests(test_rp.BigSwitchProxyPluginV2TestCase):
|
||||
self.assertIn('EXTRA-HEADER', callheaders)
|
||||
self.assertEqual(callheaders['EXTRA-HEADER'], 'HI')
|
||||
|
||||
def test_req_context_header(self):
|
||||
sp = manager.NeutronManager.get_plugin().servers
|
||||
ncontext = context.Context('uid', 'tid')
|
||||
sp.set_context(ncontext)
|
||||
with mock.patch(HTTPCON) as conmock:
|
||||
rv = conmock.return_value
|
||||
rv.getresponse.return_value.getheader.return_value = 'HASHHEADER'
|
||||
sp.rest_action('GET', '/')
|
||||
callheaders = rv.request.mock_calls[0][1][3]
|
||||
self.assertIn(servermanager.REQ_CONTEXT_HEADER, callheaders)
|
||||
ctxdct = ncontext.to_dict()
|
||||
# auth token is not included
|
||||
ctxdct.pop('auth_token')
|
||||
self.assertEqual(
|
||||
ctxdct, jsonutils.loads(
|
||||
callheaders[servermanager.REQ_CONTEXT_HEADER]))
|
||||
|
||||
def test_capabilities_retrieval(self):
|
||||
sp = servermanager.ServerPool()
|
||||
with mock.patch(HTTPCON) as conmock:
|
||||
|
@ -35,7 +35,8 @@ from neutron.tests.unit import test_db_plugin
|
||||
PHYS_NET = 'physnet1'
|
||||
VLAN_START = 1000
|
||||
VLAN_END = 1100
|
||||
SERVER_POOL = 'neutron.plugins.bigswitch.servermanager.ServerPool'
|
||||
SERVER_MANAGER = 'neutron.plugins.bigswitch.servermanager'
|
||||
SERVER_POOL = SERVER_MANAGER + '.ServerPool'
|
||||
DRIVER_MOD = 'neutron.plugins.ml2.drivers.mech_bigswitch.driver'
|
||||
DRIVER = DRIVER_MOD + '.BigSwitchMechanismDriver'
|
||||
|
||||
@ -212,3 +213,11 @@ class TestBigSwitchMechDriverPortsV2(test_db_plugin.TestPortsV2,
|
||||
create_body = rmock.mock_calls[-1][1][2]
|
||||
self.assertIsNotNone(create_body['bound_segment'])
|
||||
self.assertEqual(create_body[portbindings.HOST_ID], ext_id)
|
||||
|
||||
def test_req_context_header_present(self):
|
||||
with contextlib.nested(
|
||||
mock.patch(SERVER_MANAGER + '.ServerProxy.rest_call'),
|
||||
self.port(**{'device_id': 'devid', 'binding:host_id': 'host'})
|
||||
) as (mock_rest, p):
|
||||
headers = mock_rest.mock_calls[0][1][3]
|
||||
self.assertIn('X-REQ-CONTEXT', headers)
|
||||
|
Loading…
x
Reference in New Issue
Block a user