diff options
Diffstat (limited to 'src/spdk/scripts/rpc/client.py')
-rw-r--r-- | src/spdk/scripts/rpc/client.py | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/spdk/scripts/rpc/client.py b/src/spdk/scripts/rpc/client.py new file mode 100644 index 00000000..6a71ab51 --- /dev/null +++ b/src/spdk/scripts/rpc/client.py @@ -0,0 +1,100 @@ +import json +import socket +import time + + +def print_dict(d): + print(json.dumps(d, indent=2)) + + +class JSONRPCException(Exception): + def __init__(self, message): + self.message = message + + +class JSONRPCClient(object): + def __init__(self, addr, port=None, verbose=False, timeout=60.0): + self.verbose = verbose + self.timeout = timeout + try: + if addr.startswith('/'): + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.sock.connect(addr) + elif ':' in addr: + for res in socket.getaddrinfo(addr, port, socket.AF_INET6, socket.SOCK_STREAM, socket.SOL_TCP): + af, socktype, proto, canonname, sa = res + self.sock = socket.socket(af, socktype, proto) + self.sock.connect(sa) + else: + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.connect((addr, port)) + except socket.error as ex: + raise JSONRPCException("Error while connecting to %s\n" + "Error details: %s" % (addr, ex)) + + def __del__(self): + self.sock.close() + + def call(self, method, params={}, verbose=False): + req = {} + req['jsonrpc'] = '2.0' + req['method'] = method + req['id'] = 1 + if (params): + req['params'] = params + reqstr = json.dumps(req) + + verbose = verbose or self.verbose + + if verbose: + print("request:") + print(json.dumps(req, indent=2)) + + self.sock.sendall(reqstr.encode("utf-8")) + buf = '' + closed = False + response = {} + start_time = time.clock() + + while not closed: + try: + timeout = self.timeout - (time.clock() - start_time) + if timeout <= 0.0: + break + + self.sock.settimeout(timeout) + newdata = self.sock.recv(4096) + if (newdata == b''): + closed = True + + buf += newdata.decode("utf-8") + response = json.loads(buf) + except socket.timeout: + break + except ValueError: + continue # incomplete response; keep buffering + break + + if not response: + if method == "kill_instance": + 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: + print("response:") + print(json.dumps(response, indent=2)) + + if 'error' in response: + msg = "\n".join(["Got JSON-RPC error response", + "request:", + json.dumps(req, indent=2), + "response:", + json.dumps(response['error'], indent=2)]) + raise JSONRPCException(msg) + + return response['result'] |