diff --git a/broadview_lib/config/agentapi.py b/broadview_lib/config/agentapi.py index 7b2e160..7f7f752 100644 --- a/broadview_lib/config/agentapi.py +++ b/broadview_lib/config/agentapi.py @@ -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): diff --git a/broadview_lib/config/agentconnection.py b/broadview_lib/config/agentconnection.py index 9eb2d05..6490f37 100644 --- a/broadview_lib/config/agentconnection.py +++ b/broadview_lib/config/agentconnection.py @@ -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) diff --git a/broadview_lib/config/bst.py b/broadview_lib/config/bst.py index b2d83e0..73a9335 100644 --- a/broadview_lib/config/bst.py +++ b/broadview_lib/config/bst.py @@ -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"] diff --git a/broadview_lib/tools/bv-bstctl.py b/broadview_lib/tools/bv-bstctl.py index 3d9ea93..7c07751 100644 --- a/broadview_lib/tools/bv-bstctl.py +++ b/broadview_lib/tools/bv-bstctl.py @@ -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 diff --git a/broadview_lib/tools/examples.sh b/broadview_lib/tools/examples.sh index 5a27728..602f271 100644 --- a/broadview_lib/tools/examples.sh +++ b/broadview_lib/tools/examples.sh @@ -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 #