Big Switch: fix capabilities retrieval code

References the raw REST response in the capabilities
parsing code so json.loads doesn't get an object
that may already be decoded and fail.

Conflicts:
	neutron/tests/unit/bigswitch/test_capabilities.py
	neutron/tests/unit/bigswitch/test_servermanager.py

Closes-Bug: #1326173
Change-Id: Ia3179b7499f35a6ab2e9ce1631ab15ed27d64647
This commit is contained in:
Kevin Benton 2014-06-02 21:39:51 -07:00
parent 2b42dd3eab
commit 5285164260
3 changed files with 36 additions and 5 deletions

View File

@ -110,11 +110,11 @@ class ServerProxy(object):
def get_capabilities(self):
try:
body = self.rest_call('GET', CAPABILITIES_PATH)[3]
body = self.rest_call('GET', CAPABILITIES_PATH)[2]
self.capabilities = json.loads(body)
except Exception:
LOG.error(_("Couldn't retrieve capabilities. "
"Newer API calls won't be supported."))
LOG.exception(_("Couldn't retrieve capabilities. "
"Newer API calls won't be supported."))
LOG.info(_("The following capabilities were received "
"for %(server)s: %(cap)s"), {'server': self.server,
'cap': self.capabilities})

View File

@ -33,7 +33,7 @@ class CapabilitiesTests(test_router_db.RouterDBTestCase):
def test_floating_ip_capability(self):
with nested(
mock.patch(SERVERRESTCALL,
return_value=(200, None, None, '["floatingip"]')),
return_value=(200, None, '["floatingip"]', None)),
mock.patch(SERVERPOOL + '.rest_create_floatingip',
return_value=(200, None, None, None)),
mock.patch(SERVERPOOL + '.rest_delete_floatingip',
@ -52,7 +52,7 @@ class CapabilitiesTests(test_router_db.RouterDBTestCase):
def test_floating_ip_capability_neg(self):
with nested(
mock.patch(SERVERRESTCALL,
return_value=(200, None, None, '[""]')),
return_value=(200, None, '[""]', None)),
mock.patch(SERVERPOOL + '.rest_update_network',
return_value=(200, None, None, None))
) as (mock_rest, mock_netupdate):

View File

@ -103,6 +103,37 @@ class ServerManagerTests(test_rp.BigSwitchProxyPluginV2TestCase):
mock.call.write('certdata')
])
def test_capabilities_retrieval(self):
sp = servermanager.ServerPool()
with mock.patch(HTTPCON) as conmock:
rv = conmock.return_value.getresponse.return_value
rv.getheader.return_value = 'HASHHEADER'
# each server will get different capabilities
rv.read.side_effect = ['["a","b","c"]', '["b","c","d"]']
# pool capabilities is intersection between both
self.assertEqual(set(['b', 'c']), sp.get_capabilities())
self.assertEqual(2, rv.read.call_count)
# the pool should cache after the first call so no more
# HTTP calls should be made
rv.read.side_effect = ['["w","x","y"]', '["x","y","z"]']
self.assertEqual(set(['b', 'c']), sp.get_capabilities())
self.assertEqual(2, rv.read.call_count)
def test_capabilities_retrieval_failure(self):
sp = servermanager.ServerPool()
with mock.patch(HTTPCON) as conmock:
rv = conmock.return_value.getresponse.return_value
rv.getheader.return_value = 'HASHHEADER'
# a failure to parse should result in an empty capability set
rv.read.return_value = 'XXXXX'
self.assertEqual([], sp.servers[0].get_capabilities())
# One broken server should affect all capabilities
rv.read.side_effect = ['{"a": "b"}', '["b","c","d"]']
self.assertEqual(set(), sp.get_capabilities())
def test_reconnect_cached_connection(self):
sp = servermanager.ServerPool()
with mock.patch(HTTPCON) as conmock: