#!/usr/bin/env python3 import os import sys import telnetlib import time from datetime import datetime import requests ######################################################################### # # parameters # ######################################################################### # echo -e "usage: $0 [debug level], e.g.,\n" # echo "$0 /home/virl/git-virl-hs-fulda/GIT-VIRL-HS-Fulda/advcompnet-lab2-dcn-fabricpath.virl 6 guest password 0.5 500" BASE_API_URL = "http://192.168.76.209:13080/v2" TELNET_HOST = "192.168.76.209" USERNAME = sys.argv[3] PORT = 13080 # PASSWORD = getpass.getpass() PASSWORD = sys.argv[4] TIMEOUT = int(sys.argv[5]) GLOBAL_TIMEOUT = 1000 PROJECT_NAME = sys.argv[1] # PROJECT_ID = "69e293ac-a339-4d1d-b2e3-047dc2da8566" NUMBER_OF_CONCURRENT_BENCHMARK_PROJECTS = int(sys.argv[2]) NUMBER_OF_BENCHMARK_RUNS = 1 ######################################################################### # # start of script # ######################################################################### # delete all stale benchmark projects left over from previous runs r = requests.get(BASE_API_URL + '/projects', auth=(USERNAME, PASSWORD)) if r.status_code == 200: for entry in r.json(): if str(entry['name']).startswith("benchmark"): r = requests.delete(BASE_API_URL + '/projects/' + entry["project_id"], auth=(USERNAME, PASSWORD)) if r.status_code == 204: print("Deleted stale project %s (%s)..." % (entry["project_id"], entry["name"])) else: sys.exit("Could not delete project") else: sys.exit("Could not get stale benchmark projects") for run in range(1, NUMBER_OF_BENCHMARK_RUNS + 1): print("Starting run %i..." % run) # array containing the results of each run results = [] # create timestamp on script start time_start = time.time() date_start = datetime.fromtimestamp(time_start).ctime() print("Start at: %s " % date_start) r = requests.get(BASE_API_URL + '/projects', auth=(USERNAME, PASSWORD)) if r.status_code == 200: for entry in r.json(): if entry['name'] == PROJECT_NAME: # print(entry['project_id']) PROJECT_ID = entry['project_id'] else: sys.exit("Could not get projects") # array containing all created temporary benchmark projects benchmarks = [] # duplicate project to create multiple temporary benchmark projects for benchNumber in range(1, NUMBER_OF_CONCURRENT_BENCHMARK_PROJECTS + 1): print("Adding benchmark %i" % benchNumber) data = "{ \"name\": \"benchmark" + str(benchNumber) + "\"}" r = requests.post(BASE_API_URL + '/projects/' + PROJECT_ID + '/duplicate', data, auth=(USERNAME, PASSWORD)) if r.status_code == 201: entry = r.json() print("Created benchmark project %s (%s) from %s (%s)" % ( entry['project_id'], entry['name'], PROJECT_ID, PROJECT_NAME)) benchmarks.append(entry) data = "{}" r = requests.post(BASE_API_URL + '/projects/' + entry['project_id'] + '/open', data, auth=(USERNAME, PASSWORD)) if r.status_code == 201: print("Opened benchmark project %s (%s)" % (entry['project_id'], entry['name'])) else: sys.exit("Could not open benchmark project") else: sys.exit("Could not duplicate project") # time.sleep(5) # start all nodes in all projects for benchmark in benchmarks: data = "{}" r = requests.post(BASE_API_URL + '/projects/' + benchmark["project_id"] + '/nodes/start', data, auth=(USERNAME, PASSWORD)) if r.status_code == 204: print("Started all nodes in project %s (%s) ..." % (benchmark["project_id"], benchmark["name"])) else: sys.exit("Could not start nodes") # create timestamp when nodes are started time_started = time.time() date_started = datetime.fromtimestamp(time_started).ctime() print("Started at: %s " % date_started) # collect all active nodes in all projects to the nodes[] array nodes = [] for benchmark in benchmarks: print("Getting nodes from " + benchmark["name"] + "...") r = requests.get(BASE_API_URL + '/projects/' + benchmark["project_id"] + '/nodes', auth=(USERNAME, PASSWORD)) if r.status_code == 200: for entry in r.json(): print("Found node: " + entry["name"] + " state: " + entry["status"] + " console: " + str( entry["console"])) if entry["status"] == "started": nodes.append(entry) print("Added node...") else: sys.exit("Not all nodes active") else: sys.exit("Could get state to count nodes") nodeCount = len(nodes) print("Found %i nodes in all benchmarks..." % (len(nodes))) # create timestamp when nodes are active time_active = time.time() date_active = datetime.fromtimestamp(time_active).ctime() print("Active at: %s " % datetime.fromtimestamp(time_active).ctime()) # check if nodes are usable usable_nodes = [] while len(nodes) > 0: # perf output # print(os.popen("top -b -n 1 | head -20 >> gns3bench-perf.log")) time_globalTimeout = time.time() print("(check duration: {:d} sec, timeout: {:d} sec)".format(int((time_globalTimeout - time_active)), int(GLOBAL_TIMEOUT))) # if usability of nodes is checked longer than global timeout, exit # this can happen if nodes get stuck, e.g., due to high load, missing resources etc. if time_globalTimeout - time_active > GLOBAL_TIMEOUT: date_usable = 0 durationUsable = 0 avgConsoleDelay = 0 durationStart = time_started - time_start durationActive = time_active - time_start results.append("%s;%i;%i;%s;%s;%s;%s;%i;%i;%i;%f" % ( (PROJECT_NAME + ": TIMEOUT"), NUMBER_OF_CONCURRENT_BENCHMARK_PROJECTS, nodeCount, date_start, date_started, date_active, date_usable, durationStart, durationActive, durationUsable, avgConsoleDelay)) results.append(" Occurred while still checking nodes: " + str(nodes)) f = open("gns3bench-error.log", "a") f.writelines(results) f.write("\r\n") f.close() sys.exit("global timeout") for entry in nodes: print("Checking node %s in %s..." % (entry["name"], entry["project_id"])) try: tn = telnetlib.Telnet(TELNET_HOST, entry["console"]) tn.write(b"\n" + b"\n" + b"\n") response = tn.read_until(b" login:", timeout=TIMEOUT) # print(response) if response.find("login:".encode()) != -1: print("Found usable node %s" % entry["name"]) usable_nodes.append(entry) nodes.remove(entry) except TimeoutError: print("Connection to %s in project %s timed out" % (entry["name"], entry["project_id"])) print(str(len(usable_nodes)) + " usable nodes...") # create timestamp when all nodes are usable time_usable = time.time() date_usable = datetime.fromtimestamp(time_usable).ctime() print("Usable at: %s " % datetime.fromtimestamp(time_usable).ctime()) durationStart = time_started - time_start durationActive = time_active - time_start durationUsable = time_usable - time_start # print results print("\n\n\nResult:") print("Start: %f " % durationStart) print("Active: %f " % durationActive) print("Usable: %f " % durationUsable) # file output # Topology;ConcurrentSims;Nodes;Script-Start;Started;Active;Usable;Start Time (sec);Active Time (sec);Usable Time (sec);Average Console Delay (sec) # advcompnet-lab-1-dcn-scenario1.virl;10;50;Mon Jun 12 12:48:51 GMT 2017;Mon Jun 12 12:51:49 GMT 2017;Mon Jun 12 12:55:33 GMT 2017;Mon Jun 12 12:56:23 GMT 2017;178;402;452;0,3453 avgConsoleDelay = 0 results.append("%s;%i;%i;%s;%s;%s;%s;%i;%i;%i;%f" % ( PROJECT_NAME, NUMBER_OF_CONCURRENT_BENCHMARK_PROJECTS, nodeCount, date_start, date_started, date_active, date_usable, durationStart, durationActive, durationUsable, avgConsoleDelay)) f = open("gns3bench.log", "a") f.writelines(results) f.write("\r\n") f.close() print("Appended output to %s" % os.path.join(os.getcwd(), str(f.name))) # stop here, if we don't won't to stop and delete benchmark projects # sys.exit(0) # print("waiting...") # time.sleep(1) # stop all nodes in all projects # for benchmark in benchmarks: # data = "{}" # r = requests.post(BASE_API_URL + '/projects/' + benchmark["project_id"] + '/nodes/stop', data, # auth=(USERNAME, PASSWORD)) # if r.status_code == 204: # print("Stopped all nodes in project " + benchmark["project_id"] + "...") # else: # sys.exit("Could not stop nodes") # delete the created benchmark projects for benchmark in benchmarks: r = requests.delete(BASE_API_URL + '/projects/' + benchmark["project_id"], auth=(USERNAME, PASSWORD)) if r.status_code == 204: print("Deleted project " + benchmark["name"] + "...") else: sys.exit("Could not delete project") print("%i runs finished" % NUMBER_OF_BENCHMARK_RUNS) sys.exit(0)