From f2eeaa0142398f24b4f1577347d3e298bb29fa1a Mon Sep 17 00:00:00 2001 From: Yang Yuechun <younggy1997@outlook.com> Date: Tue, 18 Dec 2018 01:32:53 -0600 Subject: [PATCH] test server --- server/__pycache__/gns3.cpython-36.pyc | Bin 0 -> 5644 bytes .../__pycache__/gns3_function.cpython-36.pyc | Bin 0 -> 5191 bytes server/client.py | 36 ++++ server/gns3.py | 173 ++++++++++++++++++ server/index_instruction.txt | 10 + server/server.py | 62 +++++++ 6 files changed, 281 insertions(+) create mode 100644 server/__pycache__/gns3.cpython-36.pyc create mode 100644 server/__pycache__/gns3_function.cpython-36.pyc create mode 100644 server/client.py create mode 100644 server/gns3.py create mode 100644 server/index_instruction.txt create mode 100644 server/server.py diff --git a/server/__pycache__/gns3.cpython-36.pyc b/server/__pycache__/gns3.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d46a1e4e32c07ca592b45698856de2191a0415a GIT binary patch literal 5644 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 F{2xG(1p@#8 literal 0 HcmV?d00001 diff --git a/server/__pycache__/gns3_function.cpython-36.pyc b/server/__pycache__/gns3_function.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46863f16f95745806f9b081614b86756fe2f65da GIT binary patch literal 5191 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 QjcUD7uc&Vm+p>KA3s`8lf&c&j literal 0 HcmV?d00001 diff --git a/server/client.py b/server/client.py new file mode 100644 index 0000000..54a6846 --- /dev/null +++ b/server/client.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +import socket + +TCP_IP = '127.0.0.1' +TCP_PORT = 5005 +BUFFER_SIZE = 1024 + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect((TCP_IP, TCP_PORT)) + +#print index instruction +f = open('index_instruction.txt', 'r') +file_contents = '' +file_contents += f.read() +print(file_contents) +f.close() + +while 1: + # print('Enter index:') + text = '' + index = input() + while not index: + index = input(file_contents) + s.send(index.encode('utf-8')) + data = s.recv(BUFFER_SIZE).decode('utf-8') + text += data + + while text.find('END') == -1: + data = s.recv(BUFFER_SIZE).decode('utf-8') + text += data + print(text[:-3]) + if text[:-3] == 'close': break +s.close() + +# print("received text:", text) \ No newline at end of file diff --git a/server/gns3.py b/server/gns3.py new file mode 100644 index 0000000..5b4142d --- /dev/null +++ b/server/gns3.py @@ -0,0 +1,173 @@ +import json +import requests +from requests.auth import HTTPBasicAuth + +#GNS3 Information + +GNS3_SERVER_ADDR = '127.0.0.1' +GNS3_SERVER_PORT = '3080' +GNS3_USERNAME = 'admin' +GNS3_PASSWORD = 'cs436' + + +#URL mappings +#Copied and modified from https://gns3-server.readthedocs.io/en/latest/endpoints.html on December 17, 2018 +GNS3_URLS = { + #Appliance + 'appliances': 'v2/appliances', + 'appliance_templates': 'v2/appliances/templates', + 'initialize_node_from_template': 'v2/projects/{project_id}/appliances/{appliance_id}', + #TODO 'implement' later + #Compute + # /v2/computes + # /v2/computes/endpoint/{compute_id}/{emulator}/{action:.+} + # /v2/computes/{compute_id} + # /v2/computes/{compute_id}/auto_idlepc + # /v2/computes/{compute_id}/{emulator}/{action:.+} + # /v2/computes/{compute_id}/{emulator}/images + #Drawing + 'drawings': 'v2/projects/{project_id}/drawings', + 'drawing_instance': 'v2/projects/{project_id}/drawings/{drawing_id}', + #Gns3 vm + 'vm_settings': 'v2/gns3vm', + 'vm_engines_supported': 'v2/gns3vm/engines', + 'engine_vms_supported': '/v2/gns3vm/engines/{engine}/vms', + #Link + 'links': 'v2/projects/{project_id}/links', + 'link_instance': 'v2/projects/{project_id}/links/{link_id}', + 'link_filters': 'v2/projects/{project_id}/links/{link_id}/available_filters', + 'link_pcap': 'v2/projects/{project_id}/links/{link_id}/pcap', + 'link_start_capture': 'v2/projects/{project_id}/links/{link_id}/start_capture', + 'link_stop_capture': 'v2/projects/{project_id}/links/{link_id}/stop_capture', + #Node + 'nodes': 'v2/projects/{project_id}/nodes', + 'node_instance': 'v2/projects/{project_id}/nodes/{node_id}', + 'duplicate_node': 'v2/projects/{project_id}/nodes/{node_id}/duplicate', + 'compute_node_idlepc': 'v2/projects/{project_id}/nodes/{node_id}/dynamips/auto_idlepc', + 'compute_node_potential_idlepcs': 'v2/projects/{project_id}/nodes/{node_id}/dynamips/idlepc_proposals', + #'node_files': 'v2/projects/{project_id}/nodes/{node_id}/files/{path:.+}', + 'node_links': 'v2/projects/{project_id}/nodes/{node_id}/links', + 'reload_node': 'v2/projects/{project_id}/nodes/{node_id}/reload', + 'start_node': 'v2/projects/{project_id}/nodes/{node_id}/start', + 'stop_node': 'v2/projects/{project_id}/nodes/{node_id}/stop', + 'suspend_node': 'v2/projects/{project_id}/nodes/{node_id}/suspend', + 'reload_all_nodes': 'v2/projects/{project_id}/nodes/reload', + 'start_all_nodes': 'v2/projects/{project_id}/nodes/start', + 'stop_all_nodes': 'v2/projects/{project_id}/nodes/stop', + 'suspend__all_nodes': 'v2/projects/{project_id}/nodes/suspend', + #Project + 'projects': 'v2/projects', + 'load_project': 'v2/projects/load', + 'project_instance': 'v2/projects/{project_id}', + 'close_project': 'v2/projects/{project_id}/close', + 'duplicate_project': '/v2/projects/{project_id}/duplicate', + 'export_project': 'v2/projects/{project_id}/export', + #'access_project_file': 'v2/projects/{project_id}/files/{path:.+}', + 'import_project': 'v2/projects/{project_id}/import', + 'project_notifications': 'v2/projects/{project_id}/notifications', + 'project_notifications_websocket': 'v2/projects/{project_id}/notifications/ws', + 'open_project': 'v2/projects/{project_id}/open', + #Server + 'debug': 'v2/debug', + 'settings' : 'v2/settings', + 'shutdown': 'v2/shutdown', + 'version': 'v2/version', + #Snapshot + 'all_snapshots': 'v2/projects/{project_id}/snapshots', + 'snapshot_info': 'v2/projects/{project_id}/snapshots/{snapshot_id}', + 'restore_snapshot': '/v2/projects/{project_id}/snapshots/{snapshot_id}/restore' +} +#TODO implement later? +#Symbol +#/v2/symbols +#/v2/symbols/{symbol_id:.+}/raw + +#Generate GNS3 address for requests +GNS3_ADDR = 'http://{0}:{1}'.format(GNS3_SERVER_ADDR, GNS3_SERVER_PORT) +GNS3_AUTH = HTTPBasicAuth(GNS3_USERNAME, GNS3_PASSWORD) + +################################################################################ +##########Appliance +################################################################################ + +def gns3_get_appliances_list(): + r = requests.get('{0}/{1}'.format(GNS3_ADDR, GNS3_URLS['appliances']), auth=GNS3_AUTH) + return r.json() + +#TODO finish the rest + +################################################################################ +##########Drawing +################################################################################ + +def gns3_get_drawings_list(project_id): + drawings_url = GNS3_URLS['drawings'].format(project_id=project_id) + r = requests.get('{0}/{1}'.format(GNS3_ADDR, drawings_url), auth=GNS3_AUTH) + return r.json() + +def gns3_get_drawing(project_id, drawing_id): + drawing_url = GNS3_URLS['drawing_instance'].format(project_id=project_id, drawing_id=drawing_id) + r = requests.get('{0}/{1}'.format(GNS3_ADDR, drawing_url), auth=GNS3_AUTH) + return r.json() + +def gns3_update_drawing(project_id, drawing_id): + drawing_url = GNS3_URLS['drawing_instance'].format(project_id=project_id, drawing_id=drawing_id) + r = requests.put('{0}/{1}'.format(GNS3_ADDR, drawing_url), auth=GNS3_AUTH) + return r.json() + +def gns3_delete_drawing(project_id, drawing_id): + drawing_url = GNS3_URLS['drawing_instance'].format(project_id=project_id, drawing_id=drawing_id) + r = requests.delete('{0}/{1}'.format(GNS3_ADDR, drawing_url), auth=GNS3_AUTH) + #TODO what do we return? + return r + +#TODO next categories + +################################################################################ +#########Server +################################################################################ + +def gns3_dump_debug_info(): + r = requests.post('{0}/{1}'.format(GNS3_ADDR, GNS3_URLS['debug']), auth=GNS3_AUTH) + #TODO what do we return? + return r + +def gns3_get_settings(): + r = requests.get('{0}/{1}'.format(GNS3_ADDR, GNS3_URLS['settings']), auth=GNS3_AUTH) + return r.json() + +def gns3_shutdown_server(): + r = requests.get('{0}/{1}'.format(GNS3_ADDR, GNS3_URLS['shutdown']), auth=GNS3_AUTH) + #TODO what do we return? + return r + +def gns3_get_version(): + r = requests.get('{0}/{1}'.format(GNS3_ADDR, GNS3_URLS['version']), auth=GNS3_AUTH) + return r.json() + +def gns3_compare_version(version_to_compare): + r = requests.post('{0}/{1}'.format(GNS3_ADDR, GNS3_URLS['version']), auth=GNS3_AUTH, + json={'version': str(version_to_compare)}) + return r + + +################################################################################ +##########Implementation +################################################################################ +def gns3_nodes_information(project_id): + url = GNS3_URLS['nodes'].format(project_id=project_id) + r = requests.get('{0}/{1}'.format(GNS3_ADDR, url), auth=GNS3_AUTH) + return r.json() + +def gns3_links_information(project_id): + url = GNS3_URLS['links'].format(project_id=project_id) + r = requests.get('{0}/{1}'.format(GNS3_ADDR, url), auth=GNS3_AUTH) + return r.json() + + +#Testing +# print(gns3_get_version()) +# gns3_get_settings() +# print(gns3_shutdown_server()) +# print(gns3_compare_version('2.1.12dev1')) +# print(gns3_get_drawings_list('a')) \ No newline at end of file diff --git a/server/index_instruction.txt b/server/index_instruction.txt new file mode 100644 index 0000000..8f2fc13 --- /dev/null +++ b/server/index_instruction.txt @@ -0,0 +1,10 @@ +Provided functionality in GNS3: + +0: version information +1: drawing list +2: setting information +3: nodes information +4: links information +-1: close connection + +Enter index: \ No newline at end of file diff --git a/server/server.py b/server/server.py new file mode 100644 index 0000000..ea4d0b1 --- /dev/null +++ b/server/server.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +import socket +import gns3 + + +TCP_IP = '127.0.0.1' +TCP_PORT = 5005 +BUFFER_SIZE = 1024 # Normally 1024, but we want fast response +project_id ='83b40958-ede6-4dec-9cff-e11bdf38bbcc' + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.bind((TCP_IP, TCP_PORT)) +s.listen(1) + +conn, addr = s.accept() +print('Connection address:', addr) +while 1: + + index = conn.recv(BUFFER_SIZE).decode('utf-8') + + if index == '0': + data = str(gns3.gns3_get_version())+str('END') + + elif index == '1': + data = str(gns3.gns3_get_drawings_list(project_id))+str('END') + + elif index == '2': + data = str(gns3.gns3_get_settings())+str('END') + + elif index == '3': + info = gns3.gns3_nodes_information(project_id) + data = '' + for nodes in info: + data += str('name: ') + str(nodes.get('name')) + '\n' + data += str('node_id: ') + str(nodes.get('node_id')) + '\n' + if nodes.get('properties').get('platform'): + data += str('platform: ') + str(nodes.get('properties').get('platform')) + '\n' + data += '\n' + data += str('END') + + elif index == '4': + info = gns3.gns3_links_information(project_id) + data = '' + for links in info: + data += str('link_id: ') + str(links.get('link_id')) + '\n' + nodes = links.get('nodes') + for node in nodes: + data += str('node_id: ') + str(node.get('node_id')) + '\n' + data += '\n' + data += str('END') + + elif index == '-1': + data = str('close')+str('END') + conn.send(data.encode('utf-8')) # echo + break + else: + data = str('incorrect msg')+str('END') + conn.send(data.encode('utf-8')) # echo + +conn.close() + -- GitLab