Add option to ignore backend HTTP error in BigSwitch plugin
This patch fixes the way the BigSwitch plugin ignores 404 errors from the backend controller by allowing HTTP codes to be selectively ignored on REST calls. This prevents unnecessary exception handling and failover logic in calls where 404 codes are acceptable. Change-Id: Ia1118c039af3b45d96fb3f8a5fb5d3febdf50f4f Fixes: bug #1200023
This commit is contained in:
@@ -268,13 +268,13 @@ class ServerPool(object):
|
|||||||
return ServerProxy(server, port, self.ssl, self.auth, self.neutron_id,
|
return ServerProxy(server, port, self.ssl, self.auth, self.neutron_id,
|
||||||
self.timeout, self.base_uri, self.name)
|
self.timeout, self.base_uri, self.name)
|
||||||
|
|
||||||
def server_failure(self, resp):
|
def server_failure(self, resp, ignore_codes=[]):
|
||||||
"""Define failure codes as required.
|
"""Define failure codes as required.
|
||||||
|
|
||||||
Note: We assume 301-303 is a failure, and try the next server in
|
Note: We assume 301-303 is a failure, and try the next server in
|
||||||
the server pool.
|
the server pool.
|
||||||
"""
|
"""
|
||||||
return resp[0] in FAILURE_CODES
|
return (resp[0] in FAILURE_CODES and resp[0] not in ignore_codes)
|
||||||
|
|
||||||
def action_success(self, resp):
|
def action_success(self, resp):
|
||||||
"""Defining success codes as required.
|
"""Defining success codes as required.
|
||||||
@@ -283,12 +283,12 @@ class ServerPool(object):
|
|||||||
"""
|
"""
|
||||||
return resp[0] in SUCCESS_CODES
|
return resp[0] in SUCCESS_CODES
|
||||||
|
|
||||||
def rest_call(self, action, resource, data, headers):
|
def rest_call(self, action, resource, data, headers, ignore_codes):
|
||||||
failed_servers = []
|
failed_servers = []
|
||||||
while self.servers:
|
while self.servers:
|
||||||
active_server = self.servers[0]
|
active_server = self.servers[0]
|
||||||
ret = active_server.rest_call(action, resource, data, headers)
|
ret = active_server.rest_call(action, resource, data, headers)
|
||||||
if not self.server_failure(ret):
|
if not self.server_failure(ret, ignore_codes):
|
||||||
self.servers.extend(failed_servers)
|
self.servers.extend(failed_servers)
|
||||||
return ret
|
return ret
|
||||||
else:
|
else:
|
||||||
@@ -308,17 +308,17 @@ class ServerPool(object):
|
|||||||
self.servers.extend(failed_servers)
|
self.servers.extend(failed_servers)
|
||||||
return (0, None, None, None)
|
return (0, None, None, None)
|
||||||
|
|
||||||
def get(self, resource, data='', headers=None):
|
def get(self, resource, data='', headers=None, ignore_codes=[]):
|
||||||
return self.rest_call('GET', resource, data, headers)
|
return self.rest_call('GET', resource, data, headers, ignore_codes)
|
||||||
|
|
||||||
def put(self, resource, data, headers=None):
|
def put(self, resource, data, headers=None, ignore_codes=[]):
|
||||||
return self.rest_call('PUT', resource, data, headers)
|
return self.rest_call('PUT', resource, data, headers, ignore_codes)
|
||||||
|
|
||||||
def post(self, resource, data, headers=None):
|
def post(self, resource, data, headers=None, ignore_codes=[]):
|
||||||
return self.rest_call('POST', resource, data, headers)
|
return self.rest_call('POST', resource, data, headers, ignore_codes)
|
||||||
|
|
||||||
def delete(self, resource, data='', headers=None):
|
def delete(self, resource, data='', headers=None, ignore_codes=[]):
|
||||||
return self.rest_call('DELETE', resource, data, headers)
|
return self.rest_call('DELETE', resource, data, headers, ignore_codes)
|
||||||
|
|
||||||
|
|
||||||
class RpcProxy(dhcp_rpc_base.DhcpRpcCallbackMixin):
|
class RpcProxy(dhcp_rpc_base.DhcpRpcCallbackMixin):
|
||||||
@@ -790,12 +790,13 @@ class NeutronRestProxyV2(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
# delete from network ctrl. Remote error on delete is ignored
|
# delete from network ctrl. Remote error on delete is ignored
|
||||||
try:
|
try:
|
||||||
resource = ATTACHMENT_PATH % (tenant_id, net_id, port_id)
|
resource = ATTACHMENT_PATH % (tenant_id, net_id, port_id)
|
||||||
ret = self.servers.delete(resource)
|
ret = self.servers.delete(resource, ignore_codes=[404])
|
||||||
if not self.servers.action_success(ret):
|
if self.servers.server_failure(ret, ignore_codes=[404]):
|
||||||
raise RemoteRestError(ret[2])
|
raise RemoteRestError(ret[2])
|
||||||
except RemoteRestError as e:
|
except RemoteRestError as e:
|
||||||
LOG.error(_("NeutronRestProxyV2: Unable to update remote port: "
|
LOG.error(_("NeutronRestProxyV2: Unable to update remote port: "
|
||||||
"%s"), e.message)
|
"%s"), e.message)
|
||||||
|
raise
|
||||||
|
|
||||||
def create_subnet(self, context, subnet):
|
def create_subnet(self, context, subnet):
|
||||||
LOG.debug(_("NeutronRestProxyV2: create_subnet() called"))
|
LOG.debug(_("NeutronRestProxyV2: create_subnet() called"))
|
||||||
|
|||||||
@@ -43,16 +43,33 @@ class HTTPResponseMock():
|
|||||||
return "{'status': '200 OK'}"
|
return "{'status': '200 OK'}"
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPResponseMock404():
|
||||||
|
status = 404
|
||||||
|
reason = 'Not Found'
|
||||||
|
|
||||||
|
def __init__(self, sock, debuglevel=0, strict=0, method=None,
|
||||||
|
buffering=False):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
return "{'status': '404 Not Found'}"
|
||||||
|
|
||||||
|
|
||||||
class HTTPConnectionMock():
|
class HTTPConnectionMock():
|
||||||
|
|
||||||
def __init__(self, server, port, timeout):
|
def __init__(self, server, port, timeout):
|
||||||
|
self.response = None
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def request(self, action, uri, body, headers):
|
def request(self, action, uri, body, headers):
|
||||||
|
if uri.endswith('attachment') and action == 'DELETE':
|
||||||
|
self.response = HTTPResponseMock404(None)
|
||||||
|
else:
|
||||||
|
self.response = HTTPResponseMock(None)
|
||||||
return
|
return
|
||||||
|
|
||||||
def getresponse(self):
|
def getresponse(self):
|
||||||
return HTTPResponseMock(None)
|
return self.response
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
pass
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user