diff options
author | Dan Klein <danklei@cisco.com> | 2015-08-24 17:28:17 +0300 |
---|---|---|
committer | Dan Klein <danklei@cisco.com> | 2015-08-24 17:28:17 +0300 |
commit | 7d3be8c612e295820649779335288c197b80ccb2 (patch) | |
tree | 78e9636bc8780dedc919c30378a621f425e1cbfc /scripts/automation/trex_control_plane/client_utils | |
parent | dab741a80699f86e86c91718872a052cca9bbb25 (diff) |
Changes location of console and fixed dependencies
Diffstat (limited to 'scripts/automation/trex_control_plane/client_utils')
3 files changed, 241 insertions, 2 deletions
diff --git a/scripts/automation/trex_control_plane/client_utils/general_utils.py b/scripts/automation/trex_control_plane/client_utils/general_utils.py index 5544eabc..b5912628 100755 --- a/scripts/automation/trex_control_plane/client_utils/general_utils.py +++ b/scripts/automation/trex_control_plane/client_utils/general_utils.py @@ -1,6 +1,9 @@ #!/router/bin/python -import sys,site +import sys +import site +import string +import random import os try: @@ -50,7 +53,27 @@ def find_path_to_pardir (pardir, base_path = os.getcwd() ): """ components = base_path.split(os.sep) return str.join(os.sep, components[:components.index(pardir)+1]) - + + +def random_id_gen(length=8): + """ + A generator for creating a random chars id of specific length + + :parameters: + length : int + the desired length of the generated id + + default: 8 + + :return: + a random id with each next() request. + """ + id_chars = string.ascii_lowercase + string.digits + while True: + return_id = '' + for i in range(length): + return_id += random.choice(id_chars) + yield return_id if __name__ == "__main__": diff --git a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py new file mode 100644 index 00000000..1631c494 --- /dev/null +++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py @@ -0,0 +1,186 @@ +#!/router/bin/python + +import outer_packages +import zmq +import json +import general_utils +from time import sleep + +class JsonRpcClient(object): + + def __init__ (self, default_server, default_port): + self.verbose = False + self.connected = False + + # default values + self.port = default_port + self.server = default_server + self.id_gen = general_utils.random_id_gen() + + def get_connection_details (self): + rc = {} + rc['server'] = self.server + rc['port'] = self.port + + return rc + + def pretty_json (self, json_str): + return json.dumps(json.loads(json_str), indent = 4, separators=(',', ': '), sort_keys = True) + + def verbose_msg (self, msg): + if not self.verbose: + return + + print "[verbose] " + msg + + + def create_jsonrpc_v2 (self, method_name, params = {}, id = None): + msg = {} + msg["jsonrpc"] = "2.0" + msg["method"] = method_name + + msg["params"] = params + + msg["id"] = id + + return json.dumps(msg) + + def invoke_rpc_method (self, method_name, params = {}, block = False): + rc, msg = self._invoke_rpc_method(method_name, params, block) + if not rc: + self.disconnect() + + return rc, msg + + def _invoke_rpc_method (self, method_name, params = {}, block = False): + if not self.connected: + return False, "Not connected to server" + + id = self.id_gen.next() + msg = self.create_jsonrpc_v2(method_name, params, id = id) + + self.verbose_msg("Sending Request To Server:\n\n" + self.pretty_json(msg) + "\n") + + if block: + self.socket.send(msg) + else: + try: + self.socket.send(msg, flags = zmq.NOBLOCK) + except zmq.error.ZMQError as e: + return False, "Failed To Get Send Message" + + got_response = False + + if block: + response = self.socket.recv() + got_response = True + else: + for i in xrange(0 ,10): + try: + response = self.socket.recv(flags = zmq.NOBLOCK) + got_response = True + break + except zmq.Again: + sleep(0.2) + + if not got_response: + return False, "Failed To Get Server Response" + + self.verbose_msg("Server Response:\n\n" + self.pretty_json(response) + "\n") + + # decode + response_json = json.loads(response) + + if (response_json.get("jsonrpc") != "2.0"): + return False, "Malfromed Response ({0})".format(str(response)) + + if (response_json.get("id") != id): + return False, "Server Replied With Bad ID ({0})".format(str(response)) + + # error reported by server + if ("error" in response_json): + return True, response_json["error"]["message"] + + # if no error there should be a result + if ("result" not in response_json): + return False, "Malfromed Response ({0})".format(str(response)) + + return True, response_json["result"] + + + def ping_rpc_server(self): + + return self.invoke_rpc_method("ping", block = False) + + def get_rpc_server_status (self): + return self.invoke_rpc_method("get_status") + + def query_rpc_server(self): + return self.invoke_rpc_method("get_reg_cmds") + + + def set_verbose(self, mode): + self.verbose = mode + + def disconnect (self): + if self.connected: + self.socket.close(linger = 0) + self.context.destroy(linger = 0) + self.connected = False + return True, "" + else: + return False, "Not connected to server" + + def connect(self, server = None, port = None): + if self.connected: + self.disconnect() + + self.context = zmq.Context() + + self.server = (server if server else self.server) + self.port = (port if port else self.port) + + # Socket to talk to server + self.transport = "tcp://{0}:{1}".format(self.server, self.port) + + print "\nConnecting To RPC Server On {0}".format(self.transport) + + self.socket = self.context.socket(zmq.REQ) + try: + self.socket.connect(self.transport) + except zmq.error.ZMQError as e: + return False, "ZMQ Error: Bad server or port name: " + str(e) + + + self.connected = True + + # ping the server + rc, err = self.ping_rpc_server() + if not rc: + self.disconnect() + return rc, err + + return True, "" + + + def reconnect(self): + # connect using current values + return self.connect() + + if not self.connected: + return False, "Not connected to server" + + # reconnect + return self.connect(self.server, self.port) + + + def is_connected(self): + return self.connected + + + def __del__(self): + print "Shutting down RPC client\n" + self.context.destroy(linger=0) + +if __name__ == "__main__": + pass diff --git a/scripts/automation/trex_control_plane/client_utils/outer_packages.py b/scripts/automation/trex_control_plane/client_utils/outer_packages.py new file mode 100644 index 00000000..53cce991 --- /dev/null +++ b/scripts/automation/trex_control_plane/client_utils/outer_packages.py @@ -0,0 +1,30 @@ +#!/router/bin/python + +import sys +import site +import os + +CURRENT_PATH = os.path.dirname(os.path.realpath(__file__)) +ROOT_PATH = os.path.abspath(os.path.join(CURRENT_PATH, os.pardir)) # path to trex_control_plane directory +PATH_TO_PYTHON_LIB = os.path.abspath(os.path.join(ROOT_PATH, os.pardir, os.pardir, + os.pardir, 'external_libs', 'python')) + +CLIENT_UTILS_MODULES = ['zmq'] + + +def import_client_utils_modules(): + # must be in a higher priority + sys.path.insert(0, PATH_TO_PYTHON_LIB) + sys.path.append(ROOT_PATH) + import_module_list(CLIENT_UTILS_MODULES) + + +def import_module_list(modules_list): + assert(isinstance(modules_list, list)) + for p in modules_list: + full_path = os.path.join(PATH_TO_PYTHON_LIB, p) + fix_path = os.path.normcase(full_path) + site.addsitedir(full_path) + +import_client_utils_modules() + |