dissertation-3-evaluation/evaluation.ipynb

385 lines
9.4 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Project Evaluation\n",
"\n",
"This file interfaces with a Proxmox server to automatically generate VM structures and plots for testing the\n",
"success criteria of my project."
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"## Setup\n",
"This section sets up the required variables for the Proxmox server."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import ipaddress\n",
"import threading\n",
"from typing import Dict\n",
"\n",
"import runners\n",
"from structure import Bridge, Interface, IpMethod\n",
"from structure import RemotePortal, LocalPortal, SpeedTestServer\n",
"from structure import StandardEnvironment, StandardTest, IperfResult\n",
"\n",
"%load_ext dotenv\n",
"%dotenv"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"## Testing\n",
"This section gathers the required data from the different structures for later graphs."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"runner = runners.ProxmoxRunner(\n",
" host=os.getenv('PROXMOX_HOST'),\n",
" node=os.getenv('PROXMOX_NODE'),\n",
" user=os.getenv('PROXMOX_USER'),\n",
" token_name=os.getenv('PROXMOX_TOKEN_NAME'),\n",
" token_value=os.getenv('PROXMOX_TOKEN_VALUE'),\n",
"\n",
" template_id=9000,\n",
" initial_vm_id=21002,\n",
"\n",
" internet_bridge=os.getenv('INTERNET_BRIDGE'),\n",
"\n",
" management_bridge=os.getenv('MANAGEMENT_BRIDGE'),\n",
" management_initial_ip=ipaddress.ip_address(os.getenv('MANAGEMENT_INITIAL_IP')),\n",
")\n",
"\n",
"setup_params = {\n",
" 'access_key': os.getenv('S3_ACCESS_KEY'),\n",
" 'secret_key': os.getenv('S3_SECRET_KEY'),\n",
" 'branch': os.getenv('TARGET_BRANCH'),\n",
"}\n",
"\n",
"directionInbound: Dict[str, IperfResult] = {}\n",
"directionOutbound: Dict[str, IperfResult] = {}\n",
"\n",
"def run_and_save_test(env: StandardEnvironment, test: StandardTest):\n",
" (directionInbound[test.name()], directionOutbound[test.name()]) = env.test(test)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"### Direct Server to Server Testing"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"st1 = SpeedTestServer()\n",
"st2 = SpeedTestServer()\n",
"\n",
"top_level_bridge = Bridge(\n",
" st1.get_interfaces()[0],\n",
" st2.get_interfaces()[0],\n",
")\n",
"\n",
"try:\n",
" runner.build(top_level_bridge)\n",
"\n",
" st2.get_interfaces()[0].set_rate(1)\n",
" st2.server()\n",
" directionInbound['One1MBNotProxied'] = st1.client(st2)\n",
" st1.server()\n",
" directionOutbound['One1MBNotProxied'] = st2.client(st1)\n",
"\n",
" st2.get_interfaces()[0].set_rate(2)\n",
" st2.server()\n",
" directionInbound['One2MBNotProxied'] = st1.client(st2)\n",
" st1.server()\n",
" directionOutbound['One2MBNotProxied'] = st2.client(st1)\n",
"finally:\n",
" runner.teardown()"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"### Local Portal with 2 Interfaces"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"with StandardEnvironment(2, runner, setup_params) as env:\n",
" run_and_save_test(env, StandardTest([1,1]))\n",
" run_and_save_test(env, StandardTest([1,2]))\n",
" run_and_save_test(env, StandardTest([2,2]))\n",
" run_and_save_test(env, StandardTest([2,2], events={10: (0,1), 15: (0,2)}, duration=30))\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"### Local Portal with 3 Interfaces"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"with StandardEnvironment(3, runner, setup_params) as env:\n",
" run_and_save_test(env, StandardTest([1,1,1]))\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"### Local Portal with 4 Interfaces"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"with StandardEnvironment(4, runner, setup_params) as env:\n",
" run_and_save_test(env, StandardTest([1,1,1,1]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Graphs\n",
"This section produces graphs from the collected data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"from itertools import cycle\n",
"import matplotlib.pyplot as plt\n",
"\n",
"def plot_iperf_results(data, title, events=None, filename=None, start_at_zero=True):\n",
" cycol = cycle('brgy')\n",
"\n",
" fig = plt.figure()\n",
" axes = fig.add_axes([0,0,1,1])\n",
"\n",
" axes.set_title(title, pad=20.0 if events is not None else None)\n",
" axes.set_xlabel('Time (s)')\n",
" axes.set_ylabel('Throughput (Mbps)')\n",
"\n",
" for k, v in data.items():\n",
" intervals = [x['sum'] for x in v['intervals'] if not x['sum']['omitted']]\n",
"\n",
" x_axis = [((x['start'] + x['end'])/2) for x in intervals]\n",
" y_axis = [x['bits_per_second']/1e6 for x in intervals]\n",
" axes.plot(x_axis, y_axis, next(cycol), label=k)\n",
"\n",
" legend = axes.legend()\n",
"\n",
" if start_at_zero:\n",
" axes.set_ylim(bottom=0)\n",
" axes.set_xlim(left=0)\n",
"\n",
" if events is not None:\n",
" for k, v in events.items():\n",
" axes.axvline(k, linestyle='--', color='grey')\n",
" axes.annotate(v, (k, 1.02), xycoords=axes.get_xaxis_transform(), ha='center')\n",
"\n",
" if filename is not None:\n",
" fig.savefig(filename, bbox_extra_artists=(legend,), bbox_inches='tight', pad_inches=0.3)"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"### Equal Connection Scaling\n",
"This section shows equal connections scaling at various speeds and number of connections."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"plot_iperf_results(\n",
" {\n",
" '1x2MB Connection (not proxied)': directionInbound['One2MBNotProxied'],\n",
" '2x1MB Connections (proxied)': directionInbound['Two1MBProxied'],\n",
" '1x1MB Connection (not proxied)': directionInbound['One1MBNotProxied'],\n",
" },\n",
" 'Two Equal 1MB Connections',\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"plot_iperf_results(\n",
" {\n",
" '2x2MB Connections (proxied)': directionInbound['Two2MBProxied'],\n",
" '1x2MB Connection (not proxied)': directionInbound['One2MBNotProxied'],\n",
" },\n",
" 'Two Equal 2MB Connections',\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"plot_iperf_results(\n",
" {\n",
" '4x1MBps Connections (proxied)': directionInbound['Four1MBProxied'],\n",
" '3x1MBps Connections (proxied)': directionInbound['Three1MBProxied'],\n",
" '2x1MBps Connections (proxied)': directionInbound['Two1MBProxied'],\n",
" },\n",
" 'More Equal Connections',\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"plot_iperf_results(\n",
" {\n",
" '1x2MBps + 1xYMBps Connections (proxied)': directionInbound['One2MBOneYMBProxiedSlow15Return30'],\n",
" },\n",
" 'Network Slow',\n",
" events={0: 'Y=2', 15: 'Y=1', 30: 'Y=2'}\n",
")\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
}
},
"nbformat": 4,
"nbformat_minor": 1
}