scripts/rpc: split JSONRPCClient.call into send and recv

Sending multiple request is doable now. Note that, stream of responses
is not supported yet.

Change-Id: I9c49dbf033c67074e603f2e48a469142c3c63653
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/435481
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-by: Pawel Kaminski <pawelx.kaminski@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
This commit is contained in:
Pawel Wodkowski 2018-11-29 13:42:32 +01:00 committed by Jim Harris
parent 8353d56e77
commit 336faf1074

View File

@ -15,6 +15,7 @@ class JSONRPCException(Exception):
class JSONRPCClient(object): class JSONRPCClient(object):
def __init__(self, addr, port=None, verbose=False, timeout=60.0): def __init__(self, addr, port=None, verbose=False, timeout=60.0):
self.sock = None
self.verbose = verbose self.verbose = verbose
self.timeout = timeout self.timeout = timeout
self.request_id = 0 self.request_id = 0
@ -35,69 +36,69 @@ class JSONRPCClient(object):
"Error details: %s" % (addr, ex)) "Error details: %s" % (addr, ex))
def __del__(self): def __del__(self):
self.sock.close() if self.sock:
self.sock.close()
def call(self, method, params={}, verbose=False): def send(self, method, params=None):
self.request_id += 1 self.request_id += 1
req = {} req = {
req['jsonrpc'] = '2.0' 'jsonrpc': '2.0',
req['method'] = method 'method': method,
req['id'] = self.request_id 'id': self.request_id
if (params): }
if params:
req['params'] = params req['params'] = params
reqstr = json.dumps(req) reqstr = json.dumps(req)
if self.verbose:
verbose = verbose or self.verbose
if verbose:
print("request:") print("request:")
print(json.dumps(req, indent=2)) print(json.dumps(req, indent=2))
self.sock.sendall(reqstr.encode("utf-8")) self.sock.sendall(reqstr.encode("utf-8"))
buf = '' return req
closed = False
response = {}
start_time = time.clock()
while not closed: def recv(self):
start_time = time.clock()
response = None
buf = ''
while not response:
try: try:
timeout = self.timeout - (time.clock() - start_time) timeout = self.timeout - (time.clock() - start_time)
if timeout <= 0.0:
break
self.sock.settimeout(timeout) self.sock.settimeout(timeout)
newdata = self.sock.recv(4096) newdata = self.sock.recv(4096)
if (newdata == b''): if not newdata:
closed = True self.sock.close()
self.sock = None
raise JSONRPCException("Connection closed with partial response:\n%s\n" % buf)
buf += newdata.decode("utf-8") buf += newdata.decode("utf-8")
response = json.loads(buf) response = json.loads(buf)
except socket.timeout: except socket.timeout:
break break # throw exception after loop to avoid Python freaking out about nested exceptions
except ValueError: except ValueError:
continue # incomplete response; keep buffering continue # incomplete response; keep buffering
break
if not response: if not response:
if method == "kill_instance": raise JSONRPCException("Timeout while waiting for response:\n%s\n" % buf)
return {}
if closed:
msg = "Connection closed with partial response:"
else:
msg = "Timeout while waiting for response:"
msg = "\n".join([msg, buf])
raise JSONRPCException(msg)
if verbose: if self.verbose:
print("response:") print("response:")
print(json.dumps(response, indent=2)) print(json.dumps(response, indent=2))
if 'error' in response: if 'error' in response:
msg = "\n".join(["Got JSON-RPC error response", msg = "\n".join(["Got JSON-RPC error response",
"request:",
json.dumps(req, indent=2),
"response:", "response:",
json.dumps(response['error'], indent=2)]) json.dumps(response['error'], indent=2)])
raise JSONRPCException(msg) raise JSONRPCException(msg)
return response
return response['result'] def call(self, method, params=None):
self.send(method, params)
try:
return self.recv()['result']
except JSONRPCException as e:
""" Don't expect response to kill """
if not self.sock and method == "kill_instance":
return {}
else:
raise e