From 327b71b05b60a03e56fad618b51fbccd06c3776d Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Fri, 4 Mar 2016 12:33:44 +0100 Subject: Add python servers instalation step. Add systemd config files generation for python servers. --- pyserver/api_server.py | 573 ----------------------------------------- pyserver/html_server.py | 251 ------------------ pyserver/pcilib_api_server.py | 573 +++++++++++++++++++++++++++++++++++++++++ pyserver/pcilib_html_server.py | 251 ++++++++++++++++++ 4 files changed, 824 insertions(+), 824 deletions(-) delete mode 100644 pyserver/api_server.py delete mode 100644 pyserver/html_server.py create mode 100644 pyserver/pcilib_api_server.py create mode 100644 pyserver/pcilib_html_server.py (limited to 'pyserver') diff --git a/pyserver/api_server.py b/pyserver/api_server.py deleted file mode 100644 index 1d486d0..0000000 --- a/pyserver/api_server.py +++ /dev/null @@ -1,573 +0,0 @@ -import os -import sys - -import pcilib - -import time -import json -from optparse import OptionParser -from multiprocessing import Process - -if sys.version_info >= (3,0): - from http.server import HTTPServer, BaseHTTPRequestHandler - from socketserver import ThreadingMixIn -else: - from SocketServer import ThreadingMixIn - from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler - -class MultiThreadedHTTPServer(ThreadingMixIn, HTTPServer): - pass - -class PcilibServerHandler(BaseHTTPRequestHandler): - - def __init__(s, pcilib, *args): - s.pcilib = pcilib - BaseHTTPRequestHandler.__init__(s, *args) - - def do_HEAD(s): - s.send_response(200) - s.send_header('content-type', 'application/json') - s.end_headers() - - def do_GET(s): - #run request in separate process - p = Process(target=s.do_GET_worker, args=()) - p.start() - p.join() - - def do_GET_worker(s): - length = int(s.headers['Content-Length']) - - #deserialize input data - data = json.loads(s.rfile.read(length).decode('utf-8')) - - if 'command' in data: - command = data['command'] - if(command == 'help'): - s.help(data) - - - - #elif(command == 'open'): - # #check required arguments - # if not 'device' in data: - # s.error('message doesnt contains "device" field, ' - # 'which is required for "open" command', data) - # return - # #parse command arguments and convert them to string - # device = str(data.get('device', None)) - # model = data.get('model', None) - # if not model is None: - # model = str(model) - # - # try: - # s.openPcilibInstance(device, model) - # except Exception as e: - # s.error(str(e), data) - # return - # - # #Success! Create and send reply - # out = dict() - # out['status'] = 'ok' - # s.wrapMessageAndSend(out, data) - - - - elif(command == 'get_registers_list'): - #parse command arguments and convert them to string - bank = data.get('bank', None) - if not bank is None: - bank = str(bank) - - registers = dict() - try: - registers = s.pcilib.get_registers_list(bank) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - out = dict() - out['status'] = 'ok' - out['registers'] = registers - s.wrapMessageAndSend(out, data) - - - - elif(command == 'get_register_info'): - #check required arguments - if not 'reg' in data: - s.error('message doesnt contains "reg" field, ' - 'which is required for "get_register_info" command', data) - return - - #parse command arguments and convert them to string - reg = str(data.get('reg', None)) - bank = data.get('bank', None) - if not bank is None: - bank = str(bank) - - register = dict() - try: - register = s.pcilib.get_register_info(reg, bank) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok', 'register': register}, data) - - - - elif(command == 'get_property_list'): - #parse command arguments and convert them to string - branch = data.get('branch', None) - if not branch is None: - branch = str(branch) - - properties = dict() - try: - properties = s.pcilib.get_property_list(branch) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - out = dict() - out['status'] = 'ok' - out['properties'] = properties - s.wrapMessageAndSend(out, data) - - - - elif(command == 'read_register'): - #check required arguments - if not 'reg' in data: - s.error('message doesnt contains "reg" field, ' - 'which is required for "read_register" command', data) - return - - #parse command arguments and convert them to string - reg = str(data.get('reg', None)) - bank = data.get('bank', None) - if(not bank is None): - bank = str(bank) - - value = 0 - try: - value = s.pcilib.read_register(reg, bank) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - out = dict() - out['status'] = 'ok' - out['value'] = value - s.wrapMessageAndSend(out, data) - - - - elif(command == 'write_register'): - #check required arguments - if not 'reg' in data: - s.error('message doesnt contains "reg" field, ' - 'which is required for "write_register" command', data) - return - - if not 'value' in data: - s.error('message doesnt contains "value" field, ' - 'which is required for "write_register" command', data) - return - - #parse command arguments and convert them to string - reg = str(data.get('reg', None)) - value = data.get('value', None) - bank = data.get('bank', None) - if(not bank is None): - bank = str(bank) - - try: - s.pcilib.write_register(value, reg, bank) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - elif(command == 'get_property'): - #check required arguments - if not 'prop' in data: - s.error('message doesnt contains "prop" field, ' - 'which is required for "get_property" command', data) - return - - #parse command arguments and convert them to string - prop = str(data.get('prop', None)) - - value = 0 - try: - value = s.pcilib.get_property(prop) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - out = dict() - out['status'] = 'ok' - out['value'] = value - s.wrapMessageAndSend(out, data) - - - - elif(command == 'set_property'): - #check required arguments - if not 'prop' in data: - s.error('message doesnt contains "prop" field, ' - 'which is required for "set_property" command', data) - return - - if not 'value' in data: - s.error('message doesnt contains "value" field, ' - 'which is required for "set_property" command', data) - return - - #parse command arguments and convert them to string - prop = str(data.get('prop', None)) - value = data.get('value', None) - - try: - s.pcilib.set_property(value, prop) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - elif(command == 'lock'): - #check required arguments - if not 'lock_id' in data: - s.error('message doesnt contains "lock_id" field, ' - 'which is required for "lock" command', data) - return - - #parse command arguments and convert them to string - lock_id = str(data.get('lock_id')) - - try: - s.pcilib.lock_persistent(lock_id) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - elif(command == 'try_lock'): - #check required arguments - if not 'lock_id' in data: - s.error('message doesnt contains "lock_id" field, ' - 'which is required for "try_lock" command', data) - return - - #parse command arguments and convert them to string - lock_id = str(data.get('lock_id')) - persistent = bool(data.get('persistent', False)) - - try: - if persistent: - s.pcilib.try_lock_persistent(lock_id) - else: - s.pcilib.try_lock(lock_id) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - elif(command == 'unlock'): - #check required arguments - if not 'lock_id' in data: - s.error('message doesnt contains "lock_id" field, ' - 'which is required for "unlock" command', data) - return - - #parse command arguments and convert them to string - lock_id = str(data.get('lock_id')) - persistent = bool(data.get('persistent', False)) - - try: - if persistent: - s.pcilib.unlock_persistent(lock_id) - else: - s.pcilib.unlock(lock_id) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - elif(command == 'get_scripts_list'): - scripts = list() - try: - scripts = s.pcilib.get_scripts_list() - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok', 'scripts': scripts}, data) - - - - elif(command == 'run_script'): - #check required arguments - if not 'script_name' in data: - s.error('message doesnt contains "script_name" field, ' - 'which is required for "run_script" command', data) - return - #parse command arguments and convert them to string - script_name = str(data.get('script_name')) - value = data.get('value', None) - - out = None - try: - out = s.pcilib.run_script(script_name, value) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - if(type(out) == bytearray or type(out) == bytes): - s.send_response(200) - s.send_header('content-disposition', 'inline; filename=value') - s.send_header('content-type', 'application/octet-stream') - s.end_headers() - s.wfile.write(out) - else: - s.wrapMessageAndSend({'status': 'ok', 'value': out}, data) - - - - #elif(command == 'lock_global'): - # #check if global_lock already setted by server - # try: - # s.pcilib.lock_global() - # except Exception as e: - # s.error(str(e), data) - # return - # - # #Success! Create and send reply - # s.wrapMessageAndSend({'status': 'ok'}, data) - - - - #elif(command == 'unlock_global'): - # try: - # s.pcilib.unlock_global() - # except Exception as e: - # s.error(str(e), data) - # return - # - # #Success! Create and send reply - # s.wrapMessageAndSend({'status': 'ok'}, data) - - - else: - s.error('command "' + command + '" undefined', data) - return - else: - s.error('message doesnt contains "command" field, which is required', data) - return - - - - #open device context - #def openPcilibInstance(s, device, model): - # s.pcilib = pcipywrap.create_pcilib_instance(device, model) - - #Send help message - def help(s, received_message = None): - usage = str('Usage:\n' - ' Server receive commands via http GET with json packet.\n' - ' content-type should have value "application/json"\n' - ' Server could handle only commands. to set command, you\n' - ' should specify field "command" in packet with command name\n\n' - ' If you use html server, you should call commands via GET request\n' - ' like http://:/json/?=&... \n' - '\n' - ' List of commands:\n' - '\n' - ' command: help - Get help. This will return usage\n' - '\n' - - #' command: open - Opens context of device. It will be reopened if already open.\n' - #' required fields\n' - #' device: - path to the device file [/dev/fpga0]\n' - #' optional fields\n' - #' model: - specifies the model of hardware, autodetected if doesnt exists\n' - #'\n' - - ' command: get_registers_list - Returns the list of registers provided by the hardware model.\n' - ' optional fields\n' - ' bank: - if set, only register within the specified bank will be returned\n' - '\n' - - ' command: get_register_info - Returns the information about the specified register.\n' - ' required fields\n' - ' reg: - the name of the register\n' - ' optional fields\n' - ' bank: - if set, only register within the specified bank will be returned\n' - '\n' - - ' command: get_property_list - Returns the list of properties available under the specified path.\n' - ' optional fields\n' - ' branch: - Path. If not set, will return the top-level properties\n' - '\n' - - ' command: read_register - Reads the specified register.\n' - ' required fields\n' - ' reg: - the name of the register\n' - ' optional fields\n' - ' bank: - if set, only register within the specified bank will be processed\n' - '\n' - - ' command: write_register - Writes to specified register.\n' - ' required fields\n' - ' reg: - the name of the register\n' - ' value: - the register value to write. Should be int, float or string (with number)\n' - ' optional fields\n' - ' bank: - if set, only register within the specified bank will be processed\n' - '\n' - - ' command: get_property - Reads / computes the property value.\n' - ' required fields\n' - ' prop: - full name including path\n' - '\n' - - ' command: set_property - Writes the property value or executes the code associated with property.\n' - ' required fields\n' - ' prop: - full name including path\n' - ' value: - the property value to write. Should be int, float or string (with number)\n' - '\n' - - ' command: lock - function to acquire a lock, and wait till the lock can be acquire.\n' - ' required fields\n' - ' lock_id: - lock id\n' - '\n' - - ' command: try_lock - this function will try to take a lock for the mutex pointed by \n' - ' lockfunction to acquire a lock, but that returns immediatly if the\n' - ' lock can\'t be acquired on first try\n' - ' required fields\n' - ' lock_id: - lock id\n' - ' optional fields\n' - ' persistent: - 1 - lock is persistent, 0 othervise (default: 0)\n' - '\n' - - ' command: unlock - this function unlocks the lock.\n' - ' required fields\n' - ' lock_id: - lock id\n' - ' optional fields\n' - ' persistent: - 1 - lock is persistent, 0 othervise (default: 0)\n' - '\n' - - ' command: get_scripts_list - Get aviable scripts with description\n' - '\n' - - ' command: run_script - Run specified script\n' - ' required fields\n' - ' script_name: - script name (without extension)\n' - ' value: - input value in json format\n' - '\n' - - '\n') - - #send help as plain text - s.send_response(200) - s.send_header('content-type', 'text/plain') - s.end_headers() - if sys.version_info >= (3,0): - s.wfile.write(bytes(usage, 'UTF-8')) - else: - s.wfile.write(usage) - - #Send error message with text description - def error(s, info, received_message = None): - out = dict() - - out['status'] = 'error' - out['description'] = info - out['note'] = 'send {"command" : "help"} to get help' - s.wrapMessageAndSend(out, received_message, 400) - - def wrapMessageAndSend(s, message, received_message = None, response = 200): - s.send_response(response) - s.send_header('content-type', 'application/json') - s.end_headers() - if not received_message is None: - message['received_message'] = received_message - if sys.version_info >= (3,0): - s.wfile.write(bytes(json.dumps(message), 'UTF-8')) - else: - s.wfile.write(json.dumps(message)) - - -class ApiServer(MultiThreadedHTTPServer): - def __init__(self, device='/dev/fpga0', model=None, adress=('0.0.0.0', 9000)): - #redirect logs to exeption - pcilib.redirect_logs_to_exeption() - #pass Pcipywrap to to server handler - self.lib = pcilib.pcilib(device, model) - def handler(*args): - PcilibServerHandler(self.lib, *args) - MultiThreadedHTTPServer.__init__(self, adress, handler) - -if __name__ == '__main__': - - #parce command line options - parser = OptionParser() - parser.add_option("-p", "--port", action="store", - type="int", dest="port", default=9000, - help="Set server port (9000)") - parser.add_option("-d", "--device", action="store", - type="string", dest="device", default=str('/dev/fpga0'), - help="FPGA device (/dev/fpga0)") - parser.add_option("-m", "--model", action="store", - type="string", dest="model", default=None, - help="Memory model (autodetected)") - - opts = parser.parse_args()[0] - - HOST_NAME = '0.0.0.0' - PORT_NUMBER = opts.port - MODEL = opts.model - DEVICE = opts.device - - #start server - httpd = ApiServer(DEVICE, MODEL, (HOST_NAME, PORT_NUMBER)) - - print(time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)) - - try: - httpd.serve_forever() - except KeyboardInterrupt: - pass - - httpd.server_close() - - print(time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER)) diff --git a/pyserver/html_server.py b/pyserver/html_server.py deleted file mode 100644 index 571dc4e..0000000 --- a/pyserver/html_server.py +++ /dev/null @@ -1,251 +0,0 @@ -import json - -from optparse import OptionParser, OptionGroup -from multiprocessing import Process - -import requests -from api_server import ApiServer - -#import flask elements -from flask import render_template -from flask import Flask -from flask import request -from flask import url_for -from flask import redirect -from flask import send_from_directory -from flask import make_response - -app = Flask(__name__) -api_server_port = 9000 -api_server_host = '0.0.0.0' - -@app.route("/json/") -def process_json_command(command): - headers = {'content-type': 'application/json'} - message = {'command': command} - - for arg in request.args: - message[arg] = request.args[arg] - - r = 0; - try: - r = requests.get('http://' + api_server_host + ':' + str(api_server_port), - data=json.dumps(message), - headers=headers) - except Exception as e: - return str(json.dumps({'status':'error', 'description': e})) - - #application/octet-stream - response = make_response(r.content) - for header in r.headers: - response.headers[header] = r.headers[header] - - return response - -#html api -@app.route('/register_info') -def get_register_info(): - #get parameters - name = request.args.get('name') - bank = request.args.get('bank') - - #load register info - reg_info = 0 - value = dict() - try: - r = requests.get(url_for('process_json_command', - command = 'get_register_info', - bank = bank, - reg = name, _external = True)) - if(r.json().get('status') == 'error'): - return 'Error: ' + r.json()['description'] - - reg_info = r.json()['register'] - - #get register value - r = requests.get(url_for('process_json_command', - command = 'read_register', - bank = bank, - reg = name, _external = True)) - if(r.json().get('status') == 'error'): - return 'Error: ' + r.json()['description'] - - value[name] = r.json()['value'] - except Exception as e: - return str(e) - - return render_template('register_info.html', - register=reg_info, - value=value) - -@app.route("/registers_list") -def get_registers_list(): - #get parameters - bank = request.args.get('bank') - if not bank is None: - bank = str(bank) - - #load registers list - reg_list = [] - try: - r = requests.get(url_for('process_json_command', - command = 'get_registers_list', - bank = bank, _external = True)) - if(r.json().get('status') == 'error'): - return 'Error: ' + r.json()['description'] - reg_list = r.json()['registers'] - except Exception as e: - return str(e) - - #get register values - value = dict() - for reg in reg_list: - try: - r = requests.get(url_for('process_json_command', - command = 'read_register', - bank = str(reg['bank']), - reg = str(reg['name']), _external = True)) - if(r.json().get('status') == 'error'): - value[reg['name']] = 'Error: ' + r.json()['description'] - else: - value[reg['name']] = r.json()['value'] - - except Exception as e: - value[reg['name']] = 'Error: ' + str(e) - - #render result - return render_template('registers_list.html', - registers = reg_list, - render_template = render_template, - value = value - ) - -@app.route("/property_info") -def get_property_list(): - #get parameters - branch = request.args.get('branch') - if not branch is None: - branch = str(branch) - - #get properties info - prop_info = 0 - try: - r = requests.get(url_for('process_json_command', - command = 'get_property_list', - branch = branch, _external = True)) - - if(r.json().get('status') == 'error'): - return 'Error: ' + r.json()['description'] - - prop_info = r.json()['properties'] - - except Exception as e: - return str(e) - - value = dict() - for prop in prop_info: - try: - path = prop['path'] - r = requests.get(url_for('process_json_command', - command = 'get_property', - prop = path, _external = True)) - if(r.json().get('status') == 'error'): - value[path] = 'Error: ' + r.json()['description'] - else: - value[path] = r.json()['value'] - - except Exception as e: - value[path] = str(e) - - return render_template('property_info.html', - value = value, - branch = branch, - properties = prop_info - ) - -@app.route("/scripts_info") -def get_scripts_list(): - #get properties info - prop_info = 0 - try: - r = requests.get(url_for('process_json_command', - command = 'get_scripts_list', - _external = True)) - - if(r.json().get('status') == 'error'): - return 'Error: ' + r.json()['description'] - - scripts_info = r.json()['scripts'] - - except Exception as e: - return str(e) - - return render_template('scripts_info.html', - scripts = scripts_info - ) - -@app.route("/") -def greet(): - return render_template('base.html', - device = device, - model = model) - -if __name__ == "__main__": - #parse command line options - parser = OptionParser() - parser.add_option("-p", "--port", action="store", - type="int", dest="port", default=5000, - help="Set server port (5000)") - - pcilib_group = OptionGroup(parser, "Api server", - "Api server options group") - pcilib_group.add_option("-e", "--external", action="store_true", - dest="external_api_server", - default=False, - help="Dont start own api server. Use external" - " server instead"); - pcilib_group.add_option("--api-server-host", action="store", - type="string", dest="api_server_host", - default='0.0.0.0', - help="Api server ip adress (0.0.0.0)") - pcilib_group.add_option("--api-server-port", action="store", - type="int", dest="api_server_port", - default=9000, - help="Api server port (9000)") - pcilib_group.add_option("-d", "--device", action="store", - type="string", dest="device", - default=str('/dev/fpga0'), - help="FPGA device (/dev/fpga0)") - pcilib_group.add_option("-m", "--model", action="store", - type="string", dest="model", default=None, - help="Memory model (autodetected)") - - parser.add_option_group(pcilib_group) - - opts = parser.parse_args()[0] - - HOST_NAME = '0.0.0.0' - PORT_NUMBER = opts.port - - device = opts.device - model = opts.model - - #start api server in separate process - api_server_host = opts.api_server_host - api_server_port = opts.api_server_port - if(not opts.external_api_server): - api_server = ApiServer(device, model, (api_server_host, api_server_port)) - def serve_forever(server): - try: - server.serve_forever() - except KeyboardInterrupt: - pass - - Process(target=serve_forever, args=(api_server,)).start() - - #start Flask html server - app.run(host = HOST_NAME, - port = PORT_NUMBER, - threaded=True, - #debug=True - ) diff --git a/pyserver/pcilib_api_server.py b/pyserver/pcilib_api_server.py new file mode 100644 index 0000000..1d486d0 --- /dev/null +++ b/pyserver/pcilib_api_server.py @@ -0,0 +1,573 @@ +import os +import sys + +import pcilib + +import time +import json +from optparse import OptionParser +from multiprocessing import Process + +if sys.version_info >= (3,0): + from http.server import HTTPServer, BaseHTTPRequestHandler + from socketserver import ThreadingMixIn +else: + from SocketServer import ThreadingMixIn + from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler + +class MultiThreadedHTTPServer(ThreadingMixIn, HTTPServer): + pass + +class PcilibServerHandler(BaseHTTPRequestHandler): + + def __init__(s, pcilib, *args): + s.pcilib = pcilib + BaseHTTPRequestHandler.__init__(s, *args) + + def do_HEAD(s): + s.send_response(200) + s.send_header('content-type', 'application/json') + s.end_headers() + + def do_GET(s): + #run request in separate process + p = Process(target=s.do_GET_worker, args=()) + p.start() + p.join() + + def do_GET_worker(s): + length = int(s.headers['Content-Length']) + + #deserialize input data + data = json.loads(s.rfile.read(length).decode('utf-8')) + + if 'command' in data: + command = data['command'] + if(command == 'help'): + s.help(data) + + + + #elif(command == 'open'): + # #check required arguments + # if not 'device' in data: + # s.error('message doesnt contains "device" field, ' + # 'which is required for "open" command', data) + # return + # #parse command arguments and convert them to string + # device = str(data.get('device', None)) + # model = data.get('model', None) + # if not model is None: + # model = str(model) + # + # try: + # s.openPcilibInstance(device, model) + # except Exception as e: + # s.error(str(e), data) + # return + # + # #Success! Create and send reply + # out = dict() + # out['status'] = 'ok' + # s.wrapMessageAndSend(out, data) + + + + elif(command == 'get_registers_list'): + #parse command arguments and convert them to string + bank = data.get('bank', None) + if not bank is None: + bank = str(bank) + + registers = dict() + try: + registers = s.pcilib.get_registers_list(bank) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + out = dict() + out['status'] = 'ok' + out['registers'] = registers + s.wrapMessageAndSend(out, data) + + + + elif(command == 'get_register_info'): + #check required arguments + if not 'reg' in data: + s.error('message doesnt contains "reg" field, ' + 'which is required for "get_register_info" command', data) + return + + #parse command arguments and convert them to string + reg = str(data.get('reg', None)) + bank = data.get('bank', None) + if not bank is None: + bank = str(bank) + + register = dict() + try: + register = s.pcilib.get_register_info(reg, bank) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok', 'register': register}, data) + + + + elif(command == 'get_property_list'): + #parse command arguments and convert them to string + branch = data.get('branch', None) + if not branch is None: + branch = str(branch) + + properties = dict() + try: + properties = s.pcilib.get_property_list(branch) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + out = dict() + out['status'] = 'ok' + out['properties'] = properties + s.wrapMessageAndSend(out, data) + + + + elif(command == 'read_register'): + #check required arguments + if not 'reg' in data: + s.error('message doesnt contains "reg" field, ' + 'which is required for "read_register" command', data) + return + + #parse command arguments and convert them to string + reg = str(data.get('reg', None)) + bank = data.get('bank', None) + if(not bank is None): + bank = str(bank) + + value = 0 + try: + value = s.pcilib.read_register(reg, bank) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + out = dict() + out['status'] = 'ok' + out['value'] = value + s.wrapMessageAndSend(out, data) + + + + elif(command == 'write_register'): + #check required arguments + if not 'reg' in data: + s.error('message doesnt contains "reg" field, ' + 'which is required for "write_register" command', data) + return + + if not 'value' in data: + s.error('message doesnt contains "value" field, ' + 'which is required for "write_register" command', data) + return + + #parse command arguments and convert them to string + reg = str(data.get('reg', None)) + value = data.get('value', None) + bank = data.get('bank', None) + if(not bank is None): + bank = str(bank) + + try: + s.pcilib.write_register(value, reg, bank) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + elif(command == 'get_property'): + #check required arguments + if not 'prop' in data: + s.error('message doesnt contains "prop" field, ' + 'which is required for "get_property" command', data) + return + + #parse command arguments and convert them to string + prop = str(data.get('prop', None)) + + value = 0 + try: + value = s.pcilib.get_property(prop) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + out = dict() + out['status'] = 'ok' + out['value'] = value + s.wrapMessageAndSend(out, data) + + + + elif(command == 'set_property'): + #check required arguments + if not 'prop' in data: + s.error('message doesnt contains "prop" field, ' + 'which is required for "set_property" command', data) + return + + if not 'value' in data: + s.error('message doesnt contains "value" field, ' + 'which is required for "set_property" command', data) + return + + #parse command arguments and convert them to string + prop = str(data.get('prop', None)) + value = data.get('value', None) + + try: + s.pcilib.set_property(value, prop) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + elif(command == 'lock'): + #check required arguments + if not 'lock_id' in data: + s.error('message doesnt contains "lock_id" field, ' + 'which is required for "lock" command', data) + return + + #parse command arguments and convert them to string + lock_id = str(data.get('lock_id')) + + try: + s.pcilib.lock_persistent(lock_id) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + elif(command == 'try_lock'): + #check required arguments + if not 'lock_id' in data: + s.error('message doesnt contains "lock_id" field, ' + 'which is required for "try_lock" command', data) + return + + #parse command arguments and convert them to string + lock_id = str(data.get('lock_id')) + persistent = bool(data.get('persistent', False)) + + try: + if persistent: + s.pcilib.try_lock_persistent(lock_id) + else: + s.pcilib.try_lock(lock_id) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + elif(command == 'unlock'): + #check required arguments + if not 'lock_id' in data: + s.error('message doesnt contains "lock_id" field, ' + 'which is required for "unlock" command', data) + return + + #parse command arguments and convert them to string + lock_id = str(data.get('lock_id')) + persistent = bool(data.get('persistent', False)) + + try: + if persistent: + s.pcilib.unlock_persistent(lock_id) + else: + s.pcilib.unlock(lock_id) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + elif(command == 'get_scripts_list'): + scripts = list() + try: + scripts = s.pcilib.get_scripts_list() + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok', 'scripts': scripts}, data) + + + + elif(command == 'run_script'): + #check required arguments + if not 'script_name' in data: + s.error('message doesnt contains "script_name" field, ' + 'which is required for "run_script" command', data) + return + #parse command arguments and convert them to string + script_name = str(data.get('script_name')) + value = data.get('value', None) + + out = None + try: + out = s.pcilib.run_script(script_name, value) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + if(type(out) == bytearray or type(out) == bytes): + s.send_response(200) + s.send_header('content-disposition', 'inline; filename=value') + s.send_header('content-type', 'application/octet-stream') + s.end_headers() + s.wfile.write(out) + else: + s.wrapMessageAndSend({'status': 'ok', 'value': out}, data) + + + + #elif(command == 'lock_global'): + # #check if global_lock already setted by server + # try: + # s.pcilib.lock_global() + # except Exception as e: + # s.error(str(e), data) + # return + # + # #Success! Create and send reply + # s.wrapMessageAndSend({'status': 'ok'}, data) + + + + #elif(command == 'unlock_global'): + # try: + # s.pcilib.unlock_global() + # except Exception as e: + # s.error(str(e), data) + # return + # + # #Success! Create and send reply + # s.wrapMessageAndSend({'status': 'ok'}, data) + + + else: + s.error('command "' + command + '" undefined', data) + return + else: + s.error('message doesnt contains "command" field, which is required', data) + return + + + + #open device context + #def openPcilibInstance(s, device, model): + # s.pcilib = pcipywrap.create_pcilib_instance(device, model) + + #Send help message + def help(s, received_message = None): + usage = str('Usage:\n' + ' Server receive commands via http GET with json packet.\n' + ' content-type should have value "application/json"\n' + ' Server could handle only commands. to set command, you\n' + ' should specify field "command" in packet with command name\n\n' + ' If you use html server, you should call commands via GET request\n' + ' like http://:/json/?=&... \n' + '\n' + ' List of commands:\n' + '\n' + ' command: help - Get help. This will return usage\n' + '\n' + + #' command: open - Opens context of device. It will be reopened if already open.\n' + #' required fields\n' + #' device: - path to the device file [/dev/fpga0]\n' + #' optional fields\n' + #' model: - specifies the model of hardware, autodetected if doesnt exists\n' + #'\n' + + ' command: get_registers_list - Returns the list of registers provided by the hardware model.\n' + ' optional fields\n' + ' bank: - if set, only register within the specified bank will be returned\n' + '\n' + + ' command: get_register_info - Returns the information about the specified register.\n' + ' required fields\n' + ' reg: - the name of the register\n' + ' optional fields\n' + ' bank: - if set, only register within the specified bank will be returned\n' + '\n' + + ' command: get_property_list - Returns the list of properties available under the specified path.\n' + ' optional fields\n' + ' branch: - Path. If not set, will return the top-level properties\n' + '\n' + + ' command: read_register - Reads the specified register.\n' + ' required fields\n' + ' reg: - the name of the register\n' + ' optional fields\n' + ' bank: - if set, only register within the specified bank will be processed\n' + '\n' + + ' command: write_register - Writes to specified register.\n' + ' required fields\n' + ' reg: - the name of the register\n' + ' value: - the register value to write. Should be int, float or string (with number)\n' + ' optional fields\n' + ' bank: - if set, only register within the specified bank will be processed\n' + '\n' + + ' command: get_property - Reads / computes the property value.\n' + ' required fields\n' + ' prop: - full name including path\n' + '\n' + + ' command: set_property - Writes the property value or executes the code associated with property.\n' + ' required fields\n' + ' prop: - full name including path\n' + ' value: - the property value to write. Should be int, float or string (with number)\n' + '\n' + + ' command: lock - function to acquire a lock, and wait till the lock can be acquire.\n' + ' required fields\n' + ' lock_id: - lock id\n' + '\n' + + ' command: try_lock - this function will try to take a lock for the mutex pointed by \n' + ' lockfunction to acquire a lock, but that returns immediatly if the\n' + ' lock can\'t be acquired on first try\n' + ' required fields\n' + ' lock_id: - lock id\n' + ' optional fields\n' + ' persistent: - 1 - lock is persistent, 0 othervise (default: 0)\n' + '\n' + + ' command: unlock - this function unlocks the lock.\n' + ' required fields\n' + ' lock_id: - lock id\n' + ' optional fields\n' + ' persistent: - 1 - lock is persistent, 0 othervise (default: 0)\n' + '\n' + + ' command: get_scripts_list - Get aviable scripts with description\n' + '\n' + + ' command: run_script - Run specified script\n' + ' required fields\n' + ' script_name: - script name (without extension)\n' + ' value: - input value in json format\n' + '\n' + + '\n') + + #send help as plain text + s.send_response(200) + s.send_header('content-type', 'text/plain') + s.end_headers() + if sys.version_info >= (3,0): + s.wfile.write(bytes(usage, 'UTF-8')) + else: + s.wfile.write(usage) + + #Send error message with text description + def error(s, info, received_message = None): + out = dict() + + out['status'] = 'error' + out['description'] = info + out['note'] = 'send {"command" : "help"} to get help' + s.wrapMessageAndSend(out, received_message, 400) + + def wrapMessageAndSend(s, message, received_message = None, response = 200): + s.send_response(response) + s.send_header('content-type', 'application/json') + s.end_headers() + if not received_message is None: + message['received_message'] = received_message + if sys.version_info >= (3,0): + s.wfile.write(bytes(json.dumps(message), 'UTF-8')) + else: + s.wfile.write(json.dumps(message)) + + +class ApiServer(MultiThreadedHTTPServer): + def __init__(self, device='/dev/fpga0', model=None, adress=('0.0.0.0', 9000)): + #redirect logs to exeption + pcilib.redirect_logs_to_exeption() + #pass Pcipywrap to to server handler + self.lib = pcilib.pcilib(device, model) + def handler(*args): + PcilibServerHandler(self.lib, *args) + MultiThreadedHTTPServer.__init__(self, adress, handler) + +if __name__ == '__main__': + + #parce command line options + parser = OptionParser() + parser.add_option("-p", "--port", action="store", + type="int", dest="port", default=9000, + help="Set server port (9000)") + parser.add_option("-d", "--device", action="store", + type="string", dest="device", default=str('/dev/fpga0'), + help="FPGA device (/dev/fpga0)") + parser.add_option("-m", "--model", action="store", + type="string", dest="model", default=None, + help="Memory model (autodetected)") + + opts = parser.parse_args()[0] + + HOST_NAME = '0.0.0.0' + PORT_NUMBER = opts.port + MODEL = opts.model + DEVICE = opts.device + + #start server + httpd = ApiServer(DEVICE, MODEL, (HOST_NAME, PORT_NUMBER)) + + print(time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)) + + try: + httpd.serve_forever() + except KeyboardInterrupt: + pass + + httpd.server_close() + + print(time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER)) diff --git a/pyserver/pcilib_html_server.py b/pyserver/pcilib_html_server.py new file mode 100644 index 0000000..893b9d8 --- /dev/null +++ b/pyserver/pcilib_html_server.py @@ -0,0 +1,251 @@ +import json + +from optparse import OptionParser, OptionGroup +from multiprocessing import Process + +import requests +from pcilib_api_server import ApiServer + +#import flask elements +from flask import render_template +from flask import Flask +from flask import request +from flask import url_for +from flask import redirect +from flask import send_from_directory +from flask import make_response + +app = Flask(__name__) +api_server_port = 9000 +api_server_host = '0.0.0.0' + +@app.route("/json/") +def process_json_command(command): + headers = {'content-type': 'application/json'} + message = {'command': command} + + for arg in request.args: + message[arg] = request.args[arg] + + r = 0; + try: + r = requests.get('http://' + api_server_host + ':' + str(api_server_port), + data=json.dumps(message), + headers=headers) + except Exception as e: + return str(json.dumps({'status':'error', 'description': e})) + + #application/octet-stream + response = make_response(r.content) + for header in r.headers: + response.headers[header] = r.headers[header] + + return response + +#html api +@app.route('/register_info') +def get_register_info(): + #get parameters + name = request.args.get('name') + bank = request.args.get('bank') + + #load register info + reg_info = 0 + value = dict() + try: + r = requests.get(url_for('process_json_command', + command = 'get_register_info', + bank = bank, + reg = name, _external = True)) + if(r.json().get('status') == 'error'): + return 'Error: ' + r.json()['description'] + + reg_info = r.json()['register'] + + #get register value + r = requests.get(url_for('process_json_command', + command = 'read_register', + bank = bank, + reg = name, _external = True)) + if(r.json().get('status') == 'error'): + return 'Error: ' + r.json()['description'] + + value[name] = r.json()['value'] + except Exception as e: + return str(e) + + return render_template('register_info.html', + register=reg_info, + value=value) + +@app.route("/registers_list") +def get_registers_list(): + #get parameters + bank = request.args.get('bank') + if not bank is None: + bank = str(bank) + + #load registers list + reg_list = [] + try: + r = requests.get(url_for('process_json_command', + command = 'get_registers_list', + bank = bank, _external = True)) + if(r.json().get('status') == 'error'): + return 'Error: ' + r.json()['description'] + reg_list = r.json()['registers'] + except Exception as e: + return str(e) + + #get register values + value = dict() + for reg in reg_list: + try: + r = requests.get(url_for('process_json_command', + command = 'read_register', + bank = str(reg['bank']), + reg = str(reg['name']), _external = True)) + if(r.json().get('status') == 'error'): + value[reg['name']] = 'Error: ' + r.json()['description'] + else: + value[reg['name']] = r.json()['value'] + + except Exception as e: + value[reg['name']] = 'Error: ' + str(e) + + #render result + return render_template('registers_list.html', + registers = reg_list, + render_template = render_template, + value = value + ) + +@app.route("/property_info") +def get_property_list(): + #get parameters + branch = request.args.get('branch') + if not branch is None: + branch = str(branch) + + #get properties info + prop_info = 0 + try: + r = requests.get(url_for('process_json_command', + command = 'get_property_list', + branch = branch, _external = True)) + + if(r.json().get('status') == 'error'): + return 'Error: ' + r.json()['description'] + + prop_info = r.json()['properties'] + + except Exception as e: + return str(e) + + value = dict() + for prop in prop_info: + try: + path = prop['path'] + r = requests.get(url_for('process_json_command', + command = 'get_property', + prop = path, _external = True)) + if(r.json().get('status') == 'error'): + value[path] = 'Error: ' + r.json()['description'] + else: + value[path] = r.json()['value'] + + except Exception as e: + value[path] = str(e) + + return render_template('property_info.html', + value = value, + branch = branch, + properties = prop_info + ) + +@app.route("/scripts_info") +def get_scripts_list(): + #get properties info + prop_info = 0 + try: + r = requests.get(url_for('process_json_command', + command = 'get_scripts_list', + _external = True)) + + if(r.json().get('status') == 'error'): + return 'Error: ' + r.json()['description'] + + scripts_info = r.json()['scripts'] + + except Exception as e: + return str(e) + + return render_template('scripts_info.html', + scripts = scripts_info + ) + +@app.route("/") +def greet(): + return render_template('base.html', + device = device, + model = model) + +if __name__ == "__main__": + #parse command line options + parser = OptionParser() + parser.add_option("-p", "--port", action="store", + type="int", dest="port", default=5000, + help="Set server port (5000)") + + pcilib_group = OptionGroup(parser, "Api server", + "Api server options group") + pcilib_group.add_option("-e", "--external", action="store_true", + dest="external_api_server", + default=False, + help="Dont start own api server. Use external" + " server instead"); + pcilib_group.add_option("--api-server-host", action="store", + type="string", dest="api_server_host", + default='0.0.0.0', + help="Api server ip adress (0.0.0.0)") + pcilib_group.add_option("--api-server-port", action="store", + type="int", dest="api_server_port", + default=9000, + help="Api server port (9000)") + pcilib_group.add_option("-d", "--device", action="store", + type="string", dest="device", + default=str('/dev/fpga0'), + help="FPGA device (/dev/fpga0)") + pcilib_group.add_option("-m", "--model", action="store", + type="string", dest="model", default=None, + help="Memory model (autodetected)") + + parser.add_option_group(pcilib_group) + + opts = parser.parse_args()[0] + + HOST_NAME = '0.0.0.0' + PORT_NUMBER = opts.port + + device = opts.device + model = opts.model + + #start api server in separate process + api_server_host = opts.api_server_host + api_server_port = opts.api_server_port + if(not opts.external_api_server): + api_server = ApiServer(device, model, (api_server_host, api_server_port)) + def serve_forever(server): + try: + server.serve_forever() + except KeyboardInterrupt: + pass + + Process(target=serve_forever, args=(api_server,)).start() + + #start Flask html server + app.run(host = HOST_NAME, + port = PORT_NUMBER, + threaded=True, + #debug=True + ) -- cgit v1.2.3