Add timeouts to broadview-lib requests, update bv-bstctl with timeout command line argument

Change-Id: Ie6d1aaca84b1a1be8c325b722263c0b037e3e3a0
This commit is contained in:
Volodymyr Samotiy 2016-03-24 11:16:55 +02:00
parent 40312dca93
commit 6b636f6215
5 changed files with 116 additions and 76 deletions

View File

@ -49,7 +49,7 @@ class AgentAPI(object):
def getFeature(self):
return self.__feature
def _send(self, o):
def _send(self, o, timeout):
self.__payload = {}
self.__payload["jsonrpc"] = "2.0"
self.__payload["asic-id"] = o["asic-id"]
@ -57,7 +57,7 @@ class AgentAPI(object):
self.__payload["params"] = o["params"]
self.__payload["id"] = AgentAPI.__serial
AgentAPI.__serial = AgentAPI.__serial + 1
conn = AgentConnection(self.__host, self.__port, self.__feature)
conn = AgentConnection(self.__host, self.__port, self.__feature, timeout)
return conn.makeRequest(self)
def getjson(self):

View File

@ -22,6 +22,9 @@ import urllib
from xml.etree import ElementTree
import json
class RequestObj():
pass
class RequestFailed(Exception):
'''
class to represent a failed RESTful call
@ -36,35 +39,42 @@ class RequestFailed(Exception):
return repr((self._url, self._http_code, self._open_code, self._open_msg))
class AgentConnection():
def __init__(self, host, port, feature):
def __init__(self, host, port, feature, timeout):
self.host = host
self.port = port
self.feature = feature # e.g., "bst"
self._timeout = timeout
def _is_ok(self, r):
return r.status_code == 200
def _raise_fail_if(self, url, r):
def _raise_fail_if(self, url, r, timeout):
if not self._is_ok(r):
try:
j = r.json()["status"]
except:
if timeout:
j = {"response_code": r.status_code,
"error_code": 0,
"msg": "Connection timeout"}
else:
try:
t = ElementTree.fromstring(r)
j = {"response_code": r.status_code,
"error_code": 0,
"msg": "XML failure response from web server"}
j = r.json()["status"]
except:
j = {"response_code": r.status_code,
"error_code": 0,
"msg": "Unparsable response from web server"}
try:
t = ElementTree.fromstring(r)
j = {"response_code": r.status_code,
"error_code": 0,
"msg": "XML failure response from web server"}
except:
j = {"response_code": r.status_code,
"error_code": 0,
"msg": "Unparsable response from web server"}
raise RequestFailed(url, j["response_code"], j["error_code"], j["msg"])
def makeRequest(self, request):
headers = {"Content-Type": "application/json"}
timeout = False
isGet = False
if request.getHttpMethod() == "GET":
@ -76,7 +86,10 @@ class AgentConnection():
url = "http://%s:%d/broadview/%s/%s%s%s" % (self.host, self.port, self.feature, request.getHttpMethod(), "?req=", payload)
else:
url = "http://%s:%d/broadview/%s%s%s" % (self.host, self.port, request.getHttpMethod(), "?req=", payload)
r = requests.get(url, headers=headers)
try:
r = requests.get(url, timeout=self._timeout, headers=headers)
except requests.exceptions.Timeout:
timeout = True
else:
payload = request.getjson().encode("utf-8")
if self.feature:
@ -84,11 +97,21 @@ class AgentConnection():
else:
url = "http://%s:%d/broadview/%s" % (self.host, self.port, request.getHttpMethod())
if isGet:
r = requests.get(url, data=payload, headers=headers)
try:
r = requests.get(url, timeout=self._timeout, data=payload, headers=headers)
except requests.exceptions.Timeout:
timeout = True
else:
r = requests.post(url, data=payload, headers=headers)
try:
r = requests.post(url, timeout=self._timeout, data=payload, headers=headers)
except requests.exceptions.Timeout:
timeout = True
json_data = {}
if timeout:
r = RequestObj()
r.status_code = 500
if r.status_code == 200:
try:
# Data can come back with leading.trailing spaces, which trips
@ -99,6 +122,6 @@ class AgentConnection():
except:
pass
self._raise_fail_if(url, r)
self._raise_fail_if(url, r, timeout)
return (r.status_code, json_data)

View File

@ -65,8 +65,8 @@ class ConfigureBSTFeature(AgentAPI):
def setASIC(self, val):
self.__asic_id = val
def send(self):
status, json = self._send(self.toDict())
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
return status
@ -147,8 +147,8 @@ class ConfigureBSTTracking(AgentAPI):
def setASIC(self, val):
self.__asic_id = val
def send(self):
status, json = self._send(self.toDict())
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
return status
def toDict(self):
@ -186,8 +186,8 @@ class ConfigureBSTThresholds(AgentAPI):
def setParams(self, params):
self.__params = params
def send(self):
status, json = self._send(self.toDict())
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
return status
def toDict(self):
@ -402,8 +402,8 @@ class ClearBSTStatistics(AgentAPI):
def setASIC(self, val):
self.__asic_id = val
def send(self):
status, json = self._send(self.toDict())
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
return status
def toDict(self):
@ -426,8 +426,8 @@ class ClearBSTThresholds(AgentAPI):
def setASIC(self, val):
self.__asic_id = val
def send(self):
status, json = self._send(self.toDict())
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
return status
def toDict(self):
@ -499,8 +499,8 @@ class GetBSTFeature(AgentAPI):
def getJSON(self):
return self.__json
def send(self):
status, json = self._send(self.toDict())
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
if status == 200:
self.__version = json["version"]
res = json["result"]
@ -590,8 +590,8 @@ class GetBSTTracking(AgentAPI):
def getJSON(self):
return self.__json
def send(self):
status, json = self._send(self.toDict())
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
if status == 200:
self.__version = json["version"]
res = json["result"]
@ -677,9 +677,9 @@ class GetBSTThresholds(AgentAPI):
def getJSON(self):
return self.__json
def send(self):
def send(self, timeout=30):
rep = None
status, json = self._send(self.toDict())
status, json = self._send(self.toDict(), timeout)
if status == 200:
rep = BSTParser()
self.__json = json["report"]
@ -766,8 +766,8 @@ class GetBSTReport(AgentAPI):
def getJSON(self):
return self.__json
def send(self):
status, json = self._send(self.toDict())
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
rep = None
if status == 200:
self.__json = json["report"]

View File

@ -22,6 +22,7 @@ import json
class BSTConfigCommand():
def __init__(self):
self._timeout = 30
self.__cmds = {
"cfg-feature" : self.handleCfgFeature,
"cfg-tracking" : self.handleCfgTracking,
@ -47,6 +48,19 @@ class BSTConfigCommand():
"get-report" : self.helpGetReport,
}
def getTimeout(self, args):
timeout = 30
usage = False
for x in args:
if "timeout:" in x:
v = x.split(":")
if len(v) == 2:
timeout = int(v[1])
else:
print "invalid timeout"
usage = True
return usage, timeout
def getASICHostPort(self, args):
usage = False
asic = "1"
@ -84,7 +98,7 @@ class BSTConfigCommand():
return usage, asic, host, port
def usage(self):
print "usage: %s cmd host:ipv4 [port:port] [asic-id:id] [args]" % (sys.argv[0])
print "usage: %s cmd host:ipv4 [timeout:seconds] [port:port] [asic-id:id] [args]" % (sys.argv[0])
print
print "Commands:"
print
@ -106,6 +120,7 @@ class BSTConfigCommand():
def handleCfgFeature(self, args):
usage = False
usage, asic, host, port = self.getASICHostPort(args)
usage, self._timeout = self.getTimeout(args)
if not usage:
x = ConfigureBSTFeature(host, port)
x.setASIC(asic)
@ -138,7 +153,7 @@ class BSTConfigCommand():
x.setStatUnitsInCells("stat_units_in_cells" in args)
x.setSendSnapshotOnTrigger("send_snapshot_on_trigger" in args)
x.setAsyncFullReports("async_full_reports" in args)
status = x.send()
status = x.send(timeout=self._timeout)
if status != 200:
print "failure: %d" % (status)
@ -178,7 +193,7 @@ class BSTConfigCommand():
x.setTrackEgressCPUQueue("track_egress_cpu_queue" in args)
x.setTrackEgressRQEQueue("track_egress_rqe_queue" in args)
x.setTrackDevice("track_device" in args)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
@ -213,7 +228,7 @@ class BSTConfigCommand():
if len(v) == 2:
x = ConfigureDeviceThreshold(host, port, int(v[1]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -226,7 +241,7 @@ class BSTConfigCommand():
int(v[1]),
int(v[2]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -239,7 +254,7 @@ class BSTConfigCommand():
int(v[1]),
int(v[2]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -256,7 +271,7 @@ class BSTConfigCommand():
int(v[5]),
int(v[6]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -271,7 +286,7 @@ class BSTConfigCommand():
int(v[3]),
int(v[4]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -284,7 +299,7 @@ class BSTConfigCommand():
int(v[1]),
int(v[2]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -297,7 +312,7 @@ class BSTConfigCommand():
int(v[1]),
int(v[2]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -311,7 +326,7 @@ class BSTConfigCommand():
int(v[2]),
int(v[3]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -326,7 +341,7 @@ class BSTConfigCommand():
int(v[3]),
int(v[4]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -340,7 +355,7 @@ class BSTConfigCommand():
int(v[2]),
int(v[3]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -353,7 +368,7 @@ class BSTConfigCommand():
int(v[1]),
int(v[2]))
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
else:
@ -389,7 +404,7 @@ class BSTConfigCommand():
if not usage:
x = ClearBSTStatistics(host, port)
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
@ -405,7 +420,7 @@ class BSTConfigCommand():
if not usage:
x = ClearBSTThresholds(host, port)
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status != 200:
print "failure: %d" % (status)
@ -422,7 +437,7 @@ class BSTConfigCommand():
if not usage:
x = GetBSTFeature(host, port)
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status == 200:
ret = json.dumps(x.getJSON())
print ret
@ -441,7 +456,7 @@ class BSTConfigCommand():
if not usage:
x = GetBSTTracking(host, port)
x.setASIC(asic)
status = x.send()
status = x.send(self._timeout)
if status == 200:
ret = x.getJSON()
print ret
@ -471,7 +486,7 @@ class BSTConfigCommand():
x.setIncludeEgressRQEQueue("include_egress_rqe_queue" in args)
x.setIncludeDevice("include_device" in args)
status, rep = x.send()
status, rep = x.send(self._timeout)
if status == 200:
ret = json.dumps(x.getJSON())
print ret
@ -517,7 +532,7 @@ class BSTConfigCommand():
x.setIncludeEgressRQEQueue("include_egress_rqe_queue" in args)
x.setIncludeDevice("include_device" in args)
status, rep = x.send()
status, rep = x.send(self._timeout)
if status == 200:
ret = json.dumps(x.getJSON())
print ret

View File

@ -12,42 +12,44 @@
# See the License for the specific language governing permissions and
# limitations under the License.
host=10.14.244.128
echo "********** cfg-feature **********"
python bv-bstctl.py cfg-feature host:10.14.244.128 enable send_async_reports
python bv-bstctl.py cfg-feature timeout:30 host:$host enable send_async_reports
echo "********** get-feature **********"
python bv-bstctl.py get-feature host:10.14.244.128
python bv-bstctl.py get-feature host:$host
echo "********** cfg-tracking **********"
python bv-bstctl.py cfg-tracking host:10.14.244.128 track_ingress_port_priority_group
python bv-bstctl.py cfg-tracking host:$host track_ingress_port_priority_group
echo "********** get-tracking **********"
python bv-bstctl.py get-tracking host:10.14.244.128
python bv-bstctl.py get-tracking host:$host
echo "********** clr-statistics **********"
python bv-bstctl.py clr-statistics host:10.14.244.128
python bv-bstctl.py clr-statistics host:$host
echo "********** clr-thresholds **********"
python bv-bstctl.py clr-thresholds host:10.14.244.128
python bv-bstctl.py clr-thresholds host:$host
echo "********** cfg-thresholds **********"
python bv-bstctl.py get-thresholds host:10.14.244.128 include_ingress_port_priority_group include_ingress_port_service_pool include_ingress_service_pool include_egress_port_service_pool include_egress_service_pool
python bv-bstctl.py get-thresholds host:$host include_ingress_port_priority_group include_ingress_port_service_pool include_ingress_service_pool include_egress_port_service_pool include_egress_service_pool
echo "********** get-report **********"
python bv-bstctl.py get-report host:10.14.244.128 include_ingress_port_priority_group include_ingress_port_service_pool include_ingress_service_pool include_egress_port_service_pool include_egress_service_pool
python bv-bstctl.py get-report host:$host include_ingress_port_priority_group include_ingress_port_service_pool include_ingress_service_pool include_egress_port_service_pool include_egress_service_pool
echo "********** cfg-thresholds device **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 device:10100
python bv-bstctl.py cfg-thresholds host:$host device:10100
echo "********** cfg-thresholds egress-cpu-queue **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 egress-cpu-queue:5:20202
python bv-bstctl.py cfg-thresholds host:$host egress-cpu-queue:5:20202
echo "********** cfg-thresholds egress-rqe-queue **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 egress-rqe-queue:6:30130
python bv-bstctl.py cfg-thresholds host:$host egress-rqe-queue:6:30130
echo "********** cfg-thresholds egress-port-service-pool **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 egress-port-service-pool:"2":2:204556:30000:40000:5000
python bv-bstctl.py cfg-thresholds host:$host egress-port-service-pool:"2":2:204556:30000:40000:5000
echo "********** cfg-thresholds egress-service-pool **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 egress-service-pool:2:30:40:50
python bv-bstctl.py cfg-thresholds host:$host egress-service-pool:2:30:40:50
echo "********** cfg-thresholds egress-uc-queue **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 egress-uc-queue:5:20200
python bv-bstctl.py cfg-thresholds host:$host egress-uc-queue:5:20200
echo "********** cfg-thresholds egress-uc-queue-group **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 egress-uc-queue-group:5:204
python bv-bstctl.py cfg-thresholds host:$host egress-uc-queue-group:5:204
echo "********** cfg-thresholds egress-mc-queue **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 egress-mc-queue:5:204:10500
python bv-bstctl.py cfg-thresholds host:$host egress-mc-queue:5:204:10500
echo "********** cfg-thresholds ingress-port-priority-group **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 ingress-port-priority-group:"5":2:20456:40404
python bv-bstctl.py cfg-thresholds host:$host ingress-port-priority-group:"5":2:20456:40404
echo "********** cfg-thresholds ingress-port-service-pool **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 ingress-port-service-pool:"4":2:50505
python bv-bstctl.py cfg-thresholds host:$host ingress-port-service-pool:"4":2:50505
echo "********** cfg-thresholds ingress-service-pool **********"
python bv-bstctl.py cfg-thresholds host:10.14.244.128 ingress-service-pool:2:56783
python bv-bstctl.py cfg-thresholds host:$host ingress-service-pool:2:56783
#