{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Project Evaluation\n", "\n", "This file interfaces with a Proxmox server to automatically generate VM structures and graphs 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", "\n", "import runners\n", "from structure import Bridge, Interface, IpMethod\n", "from structure import RemotePortal, LocalPortal, SpeedTestServer\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 = {}\n", "directionOutbound = {}" ] }, { "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.get_interfaces()[0].get_address())\n", " st1.server()\n", " directionOutbound['One1MBNotProxied'] = st2.client(st1.get_interfaces()[0].get_address())\n", "\n", " st2.get_interfaces()[0].set_rate(1)\n", " st2.server()\n", " directionInbound['One2MBNotProxied'] = st1.client(st2.get_interfaces()[0].get_address())\n", " st1.server()\n", " directionOutbound['One2MBNotProxied'] = st2.client(st1.get_interfaces()[0].get_address())\n", "finally:\n", " runner.teardown()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "rp = RemotePortal([Interface(IpMethod.Auto4)], setup_params=setup_params)\n", "\n", "st = SpeedTestServer()\n", "cl = SpeedTestServer(clone_interface=rp.get_interfaces()[0])\n", "\n", "lp = LocalPortal([\n", " Interface(IpMethod.Auto4),\n", " Interface(IpMethod.Auto4),\n", "], cl, setup_params=setup_params)\n", "\n", "rp.set_local_portal(lp)\n", "lp.set_remote_portal(rp)\n", "\n", "top_level_bridge = Bridge(*[\n", " st.get_interfaces()[0],\n", " rp.get_interfaces()[0],\n", " *lp.get_interfaces()[0:2],\n", "])\n", "\n", "try:\n", " runner.build(top_level_bridge)\n", "\n", " lp.get_interfaces()[0].set_rate(1)\n", " lp.get_interfaces()[1].set_rate(1)\n", "\n", " cl.server()\n", " directionInbound['Two1MBProxied'] = st.client(cl.get_interfaces()[0].get_address())\n", " st.server()\n", " directionOutbound['Two1MBProxied'] = cl.client(st.get_interfaces()[0].get_address())\n", "\n", " lp.get_interfaces()[0].set_rate(2)\n", " lp.get_interfaces()[1].set_rate(2)\n", "\n", " cl.server()\n", " directionInbound['Two2MBProxied'] = st.client(cl.get_interfaces()[0].get_address())\n", " st.server()\n", " directionOutbound['Two2MBProxied'] = cl.client(st.get_interfaces()[0].get_address())\n", "\n", " lp.get_interfaces()[0].set_rate(1)\n", " lp.get_interfaces()[1].set_rate(2)\n", "\n", " cl.server()\n", " directionInbound['One1MBOne2MBProxied'] = st.client(cl.get_interfaces()[0].get_address())\n", " st.server()\n", " directionOutbound['One1MBOne2MBProxied'] = cl.client(st.get_interfaces()[0].get_address())\n", "\n", " lp.get_interfaces()[0].set_rate(2)\n", " lp.get_interfaces()[1].set_rate(2)\n", "\n", " cl.server()\n", " threading.Timer(5+15, lambda: lp.get_interfaces()[1].set_rate(1)).start()\n", " threading.Timer(5+30, lambda: lp.get_interfaces()[1].set_rate(2)).start()\n", " directionInbound['One2MBOneYMBProxiedSlow15Return30']\\\n", " = st.client(cl.get_interfaces()[0].get_address(), time=60)\n", "\n", " st.server()\n", " threading.Timer(5+15, lambda: lp.get_interfaces()[1].set_rate(1)).start()\n", " threading.Timer(5+30, lambda: lp.get_interfaces()[1].set_rate(2)).start()\n", " directionOutbound['One2MBOneYMBProxiedSlow15Return30'] =\\\n", " cl.client(st.get_interfaces()[0].get_address(), time=60)\n", "finally:\n", " runner.teardown()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "rp = RemotePortal([Interface(IpMethod.Auto4)], setup_params=setup_params)\n", "\n", "st = SpeedTestServer()\n", "cl = SpeedTestServer(clone_interface=rp.get_interfaces()[0])\n", "\n", "lp = LocalPortal([\n", " Interface(IpMethod.Auto4),\n", " Interface(IpMethod.Auto4),\n", " Interface(IpMethod.Auto4),\n", "], cl, setup_params=setup_params)\n", "\n", "rp.set_local_portal(lp)\n", "lp.set_remote_portal(rp)\n", "\n", "top_level_bridge = Bridge(*[\n", " st.get_interfaces()[0],\n", " rp.get_interfaces()[0],\n", " *lp.get_interfaces()[0:3],\n", "])\n", "\n", "try:\n", " runner.build(top_level_bridge)\n", "\n", " lp.get_interfaces()[0].set_rate(1)\n", " lp.get_interfaces()[1].set_rate(1)\n", " lp.get_interfaces()[2].set_rate(1)\n", "\n", " cl.server()\n", " directionInbound['Three1MBProxied'] = st.client(cl.get_interfaces()[0].get_address())\n", " st.server()\n", " directionOutbound['Three1MBProxied'] = cl.client(st.get_interfaces()[0].get_address())\n", "finally:\n", " runner.teardown()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "rp = RemotePortal([Interface(IpMethod.Auto4)], setup_params=setup_params)\n", "\n", "st = SpeedTestServer()\n", "cl = SpeedTestServer(clone_interface=rp.get_interfaces()[0])\n", "\n", "lp = LocalPortal([\n", " Interface(IpMethod.Auto4),\n", " Interface(IpMethod.Auto4),\n", " Interface(IpMethod.Auto4),\n", " Interface(IpMethod.Auto4),\n", "], cl, setup_params=setup_params)\n", "\n", "rp.set_local_portal(lp)\n", "lp.set_remote_portal(rp)\n", "\n", "top_level_bridge = Bridge(*[\n", " st.get_interfaces()[0],\n", " rp.get_interfaces()[0],\n", " *lp.get_interfaces()[0:4],\n", "])\n", "\n", "try:\n", " runner.build(top_level_bridge)\n", "\n", " lp.get_interfaces()[0].set_rate(1)\n", " lp.get_interfaces()[1].set_rate(1)\n", " lp.get_interfaces()[2].set_rate(1)\n", " lp.get_interfaces()[3].set_rate(1)\n", "\n", " cl.server()\n", " directionInbound['Four1MBProxied'] = st.client(cl.get_interfaces()[0].get_address())\n", " st.server()\n", " directionOutbound['Four1MBProxied'] = cl.client(st.get_interfaces()[0].get_address())\n", "finally:\n", " runner.teardown()\n" ] }, { "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": { "collapsed": false, "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", " '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", ")" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "## Criteria\n", "This section automatically verifies some criteria with assertions." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "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 }