1#!/usr/bin/env python3 2 3import base64 4import errno 5import json 6import socket 7import sys 8try: 9 from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler 10except ImportError: 11 from http.server import HTTPServer 12 from http.server import BaseHTTPRequestHandler 13 14rpc_sock = None 15 16 17def print_usage_and_exit(status): 18 print('Usage: rpc_http_proxy.py <server IP> <server port> <user name>' + 19 ' <password> <SPDK RPC socket (optional, default: /var/tmp/spdk.sock)>') 20 sys.exit(status) 21 22 23def rpc_call(req): 24 global rpc_sock 25 26 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 27 sock.connect(rpc_sock) 28 sock.sendall(req) 29 30 if 'id' not in json.loads(req.decode('ascii')): 31 sock.close() 32 return None 33 34 buf = '' 35 closed = False 36 response = None 37 38 while not closed: 39 newdata = sock.recv(1024) 40 if (newdata == b''): 41 closed = True 42 buf += newdata.decode('ascii') 43 try: 44 response = json.loads(buf) 45 except ValueError: 46 continue # incomplete response; keep buffering 47 break 48 49 sock.close() 50 51 if not response and len(buf) > 0: 52 raise 53 54 return buf 55 56 57class ServerHandler(BaseHTTPRequestHandler): 58 59 key = "" 60 61 def do_HEAD(self): 62 self.send_response(200) 63 self.send_header('Content-type', 'text/html') 64 self.end_headers() 65 66 def do_AUTHHEAD(self): 67 self.send_response(401) 68 self.send_header('WWW-Authenticate', 'text/html') 69 self.send_header('Content-type', 'text/html') 70 self.end_headers() 71 72 def do_INTERNALERROR(self): 73 self.send_response(500) 74 self.send_header('Content-type', 'text/html') 75 self.end_headers() 76 77 def do_POST(self): 78 if self.headers['Authorization'] != 'Basic ' + self.key: 79 self.do_AUTHHEAD() 80 else: 81 data_string = self.rfile.read(int(self.headers['Content-Length'])) 82 83 try: 84 response = rpc_call(data_string) 85 if response is not None: 86 self.do_HEAD() 87 self.wfile.write(bytes(response.encode(encoding='ascii'))) 88 except ValueError: 89 self.do_INTERNALERROR() 90 91 92def main(): 93 global rpc_sock 94 95 if len(sys.argv) == 1 or sys.argv[1] == '-h': 96 print_usage_and_exit(0) 97 elif len(sys.argv) < 5: 98 print('Not enough arguments') 99 print_usage_and_exit(errno.EINVAL) 100 elif len(sys.argv) > 6: 101 print('Too many arguments') 102 print_usage_and_exit(errno.E2BIG) 103 104 if len(sys.argv) == 6: 105 rpc_sock = sys.argv[5] 106 else: 107 rpc_sock = '/var/tmp/spdk.sock' 108 109 # encoding user name and password 110 key = base64.b64encode((sys.argv[3]+':'+sys.argv[4]).encode(encoding='ascii')).decode('ascii') 111 112 try: 113 ServerHandler.key = key 114 httpd = HTTPServer((sys.argv[1], int(sys.argv[2])), ServerHandler) 115 print('Started RPC http proxy server') 116 httpd.serve_forever() 117 except KeyboardInterrupt: 118 print('Shutting down server') 119 httpd.socket.close() 120 121 122if __name__ == '__main__': 123 main() 124