Add support for configure-system-feature and cancel-request

Change-Id: Ic39b04c63c5bc977fc856abb705137b0aa0f9288
This commit is contained in:
Vitaliy Kharechko 2016-10-11 10:21:57 +03:00
parent cb9ccd715c
commit c5e8cb991a
3 changed files with 230 additions and 2 deletions

View File

@ -99,7 +99,8 @@ Hole Detection feature.
### bv-ctl.py ### bv-ctl.py
A command line application that can be used to issue general BroadView A command line application that can be used to issue general BroadView
commands for querying the supported features of BroadView, etc. commands for querying the supported features of BroadView, cancelling
requests, etc.
# Classes # Classes
@ -120,7 +121,31 @@ This command is used to retrieve the switch properties.
### GetSystemFeature ### GetSystemFeature
This command is used to retrieve the current configuration of the System This command is used to retrieve the current configuration of the System
module on the Agent. module on the Agent.
### ConfigureSystemFeature
This command can be used to enable or disable heartbeat messages from the
agent, as well as specify a heartbeat interval.
### CancelRequest
All JSON RPC requests to the agent must be identified by a unique integer ID.
The reference implementation of the agent does not provide any support for
managing the ID space, ad it is left to client to ensure that IDs are unique.
broadview-lib supports this by maintaining an ID file that is shared across all
broadview-lib instances on the host and possibly the datacenter should the
ID file be placed in a shared file system. See commit
a72b75082ee961abcdc7da542da6767ee484560e for details on the implementation.
The CancelRequest command takes the ID of a previous request as an argument
and cancels that command on the agent. To obtain this ID, refer to the JSON
output of the corresponding command for the cancellation-id field. Alternately,
Python code using configuration objects can get at this ID for a request by
calling getLastUsedSerial() member function of the object before making another
request with that object (the configuration objects record the last used ID
number within the object, so as long as the object itself is being used in a
thread safe manner, this ID will be correct).
## BST Configuration and Data Gathering ## BST Configuration and Data Gathering

View File

@ -80,6 +80,85 @@ class GetSystemFeature(AgentAPI):
self.__json = res self.__json = res
return status return status
class ConfigureSystemFeature(AgentAPI):
def __init__(self, host, port):
super(ConfigureSystemFeature, self).__init__()
self.setFeature("")
self.setHttpMethod("POST")
self.setHost(host)
self.setPort(port)
self.__asic_id = "1"
self.__json = None
self.__heartbeatEnable = False
self.__msgInterval = 30
def setASIC(self, val):
self.__asic_id = val
def setHeartbeatEnable(self, val):
self.__heartbeatEnable = val
def setMsgInterval(self, val):
self.__msgInterval = val
def toDict(self):
ret = {}
params = {}
params["heartbeat-enable"] = 1 if self.__heartbeatEnable else 0
params["msg-interval"] = self.__msgInterval
ret["asic-id"] = self.__asic_id
ret["params"] = params
ret["method"] = "configure-system-feature"
return ret
def getJSON(self):
return self.__json
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
if status == 200:
self.__version = json["version"]
res = json["result"]
self.__json = res
return status
class CancelRequest(AgentAPI):
def __init__(self, host, port):
super(CancelRequest, self).__init__()
self.setFeature("")
self.setHttpMethod("POST")
self.setHost(host)
self.setPort(port)
self.__asic_id = "1"
self.__json = None
self.__requestId = None
def setASIC(self, val):
self.__asic_id = val
def setRequestId(self, val):
self.__requestId = val
def toDict(self):
ret = {}
params = {}
params["request-id"] = self.__requestId
ret["asic-id"] = self.__asic_id
ret["params"] = params
ret["method"] = "cancel-request"
return ret
def getJSON(self):
return self.__json
def send(self, timeout=30):
status, json = self._send(self.toDict(), timeout)
if status == 200:
self.__version = json["version"]
res = json["result"]
self.__json = res
return status
class TestTAPIParams(unittest.TestCase): class TestTAPIParams(unittest.TestCase):
def setUp(self): def setUp(self):
@ -133,5 +212,59 @@ class TestTAPIParams(unittest.TestCase):
self.assertTrue(d["asic-id"] == "1") self.assertTrue(d["asic-id"] == "1")
self.assertTrue(d["method"] == "get-system-feature") self.assertTrue(d["method"] == "get-system-feature")
def test_ConfigureSystemFeature(self):
sw = BroadViewBSTSwitches()
if len(sw):
for x in sw:
host = x["ip"]
port = x["port"]
break
else:
host = "192.168.3.1"
port = 8080
x = ConfigureSystemFeature(host, port)
x.setHeartbeatEnable(False)
x.setMsgInterval(10)
d = x.toDict()
self.assertTrue("asic-id" in d)
self.assertTrue("params" in d)
self.assertTrue(d["params"]["msg-interval"] == 10)
self.assertTrue(d["params"]["heartbeat-enable"] == 0)
self.assertTrue("method" in d)
self.assertTrue(x.getFeature() == "")
self.assertTrue(x.getHttpMethod() == "POST")
self.assertTrue(x.getHost() == host)
self.assertTrue(x.getPort() == port)
self.assertTrue(d["asic-id"] == "1")
self.assertTrue(d["method"] == "configure-system-feature")
def test_CancelRequest(self):
sw = BroadViewBSTSwitches()
if len(sw):
for x in sw:
host = x["ip"]
port = x["port"]
break
else:
host = "192.168.3.1"
port = 8080
x = CancelRequest(host, port)
x.setRequestId(2)
d = x.toDict()
self.assertTrue("asic-id" in d)
self.assertTrue("params" in d)
self.assertTrue(d["params"]["request-id"] == 2)
self.assertTrue("method" in d)
self.assertTrue(x.getFeature() == "")
self.assertTrue(x.getHttpMethod() == "POST")
self.assertTrue(x.getHost() == host)
self.assertTrue(x.getPort() == port)
self.assertTrue(d["asic-id"] == "1")
self.assertTrue(d["method"] == "cancel-request")
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View File

@ -25,12 +25,16 @@ class BroadViewCommand():
self.__cmds = { self.__cmds = {
"get-switch-properties" : self.handleGetSwitchProperties, "get-switch-properties" : self.handleGetSwitchProperties,
"get-system-feature" : self.handleGetSystemFeature, "get-system-feature" : self.handleGetSystemFeature,
"configure-system-feature" : self.handleConfigureSystemFeature,
"cancel-request" : self.handleCancelRequest,
"help": self.handleHelp, "help": self.handleHelp,
} }
self.__help = { self.__help = {
"get-switch-properties" : self.helpGetSwitchProperties, "get-switch-properties" : self.helpGetSwitchProperties,
"get-system-feature" : self.helpGetSystemFeature, "get-system-feature" : self.helpGetSystemFeature,
"configure-system-feature" : self.helpConfigureSystemFeature,
"cancel-request" : self.helpCancelRequest,
} }
def getTimeout(self, args): def getTimeout(self, args):
@ -140,6 +144,72 @@ class BroadViewCommand():
def helpGetSystemFeature(self, name): def helpGetSystemFeature(self, name):
print name print name
def handleConfigureSystemFeature(self, args):
usage = False
usage, asic, host, port = self.getASICHostPort(args)
usage, self._timeout = self.getTimeout(args)
if not usage:
x = ConfigureSystemFeature(host, port)
x.setASIC(asic)
x.setHeartbeatEnable("heartbeat_enable" in args)
for arg in args:
if "msg_interval:" in arg:
v = arg.split(":")
if len(v) == 2:
x.setMsgInterval(int(v[1]))
else:
print "invalid msg-interval argument"
usage = True
status = x.send(timeout=self._timeout)
if status != 200:
print "failure: {}".format(status)
ret = None
return usage, ret
def helpConfigureSystemFeature(self, name):
print name, "[args]"
print
print "args:"
print
print " heartbeat_enable"
print " msg_interval:interval_in_seconds"
print
print "Note: if heartbeat_enable not specified, heartbeats will be disabled"
def handleCancelRequest(self, args):
usage = False
usage, asic, host, port = self.getASICHostPort(args)
usage, self._timeout = self.getTimeout(args)
if not usage:
x = CancelRequest(host, port)
x.setASIC(asic)
for arg in args:
if "request_id:" in arg:
v = arg.split(":")
if len(v) == 2:
x.setRequestId(int(v[1]))
else:
print "invalid request id argument"
usage = True
status = x.send(timeout=self._timeout)
if status != 200:
print "failure: {}".format(status)
ret = None
return usage, ret
def helpCancelRequest(self, name):
print name, "[args]"
print
print "args:"
print
print " request_id:id"
print ""
print "Note: see the cancellation-id member of the JSON output for the corresponding command for the ID."
def isCmd(self, cmd): def isCmd(self, cmd):
return cmd in self.__cmds return cmd in self.__cmds