mirror of https://github.com/EdgeVPNio/tools.git
Initial tools commit
parent
66b8210779
commit
962fad8364
|
@ -0,0 +1,23 @@
|
||||||
|
# EdgeVPNio DEBIAN PACKAGE
|
||||||
|
|
||||||
|
The Debian package installs EdgeVPNio (evio) as a systemd service and is supported in Ubuntu 18.04 and Raspberry Pi Raspbian OS. Use the following procedure to create a new installer package.
|
||||||
|
1. Clone the `tools` repo and use `tools/deb-pak` as your base directory.
|
||||||
|
2. Copy the `tincan` executable, and the contents of the `controller` folder into `edge-vpnio/opt/edge-vpnio`.
|
||||||
|
3. Copy `config.json`, the template or completed file, into `edge-vpnio/etc/opt/edge-vpnio`.
|
||||||
|
4. Execute `./deb-gen` to create the `edge-vpnio.deb` installer package.
|
||||||
|
|
||||||
|
By default, the following files and directories are created:
|
||||||
|
1. `/opt/edge-vpnio/tincan`
|
||||||
|
2. `/opt/edge-vpnio/controller/`
|
||||||
|
3. `/etc/opt/edge-vpnio/config.json`
|
||||||
|
4. `/etc/systemd/system`
|
||||||
|
5. `/var/logs/edge-vpnio/tincan_log`
|
||||||
|
6. `/var/logs/edge-vpnio/ctrl.log`
|
||||||
|
|
||||||
|
The installer has dependencies on, and will install `python3`, `python3-pip`, `iproute2`, `openvswitch-switch`, `bridge-utils`.
|
||||||
|
To install EdgeVPNio invoke `sudo apt install -y <path/to/installer>/edge-vpnio.deb`.
|
||||||
|
After installation but before starting evio, complete `config.json` by adding the XMPP credentials, setting the IP address, and applying other configurations as needed.
|
||||||
|
Then start evio using `sudo systemctl start evio`.
|
||||||
|
Additionally, use `systemctl` to start/stop/restart/status evio.
|
||||||
|
|
||||||
|
EdgeVPNio is configured to be started automatically on reboot.
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cat <<! > edge-vpnio/DEBIAN/control
|
||||||
|
Package: edge-vpnio
|
||||||
|
Name: EdgeVPNio
|
||||||
|
Version: 20.7
|
||||||
|
Maintainer: <ip.over.p2p@gmail.com>
|
||||||
|
Architecture: $(dpkg --print-architecture)
|
||||||
|
Homepage: http://edgevpnio.github.io
|
||||||
|
Depends: python3, python3-dev, python3-pip, iproute2, openvswitch-switch, bridge-utils
|
||||||
|
Description: Virtual Overlay Networks.
|
||||||
|
EdgeVPN is an open-source user-centric software virtual network allowing end users to define and create their own virtual private networks (VPNs). EdgeVPNio virtual networks provide end-to-end tunneling of IP or Ethernet over Tincan links setup and managed through a control API to create various software-defined VPN overlays.
|
||||||
|
Tag: P2P Overlay Networking
|
||||||
|
!
|
||||||
|
cp edge-vpnio/opt/edge-vpnio/template-config.json edge-vpnio/etc/opt/edge-vpnio/config.json
|
||||||
|
dpkg-deb --build --root-owner-group edge-vpnio .
|
||||||
|
|
||||||
|
rm edge-vpnio/DEBIAN/control edge-vpnio/etc/opt/edge-vpnio/config.json
|
|
@ -0,0 +1 @@
|
||||||
|
/etc/opt/edge-vpnio/config.json
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd /opt/edge-vpnio
|
||||||
|
pip3 --no-cache-dir install virtualenv
|
||||||
|
virtualenv --python=python3.6 venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip3 --no-cache-dir install psutil sleekxmpp requests simplejson ryu
|
||||||
|
deactivate
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable evio
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
systemctl -q is-active evio && systemctl -q stop evio || true
|
||||||
|
systemctl -q is-enabled evio && systemctl -q disable evio || true
|
||||||
|
rm -rf /opt/edge-vpnio/venv
|
||||||
|
if [ -d /opt/edge-vpnio/controller ]; then
|
||||||
|
for dir in $(find /opt/edge-vpnio/controller -type d -name __pycache__); do
|
||||||
|
rm -rf "$dir"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
[Unit]
|
||||||
|
Description=EdgeVPNio service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/opt/edge-vpnio/evio-start
|
||||||
|
RemainAfterExit=true
|
||||||
|
Restart=no
|
||||||
|
TimeoutStopSec=30
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -0,0 +1,11 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
evio_start() {
|
||||||
|
cd /opt/edge-vpnio
|
||||||
|
./tincan &
|
||||||
|
source venv/bin/activate
|
||||||
|
python Controller.py -c /etc/opt/edge-vpnio/config.json &
|
||||||
|
}
|
||||||
|
|
||||||
|
evio_start
|
||||||
|
exit
|
|
@ -0,0 +1,3 @@
|
||||||
|
Acquire::http::Pipeline-Depth 0;
|
||||||
|
Acquire::http::No-Cache true;
|
||||||
|
Acquire::BrokenProxy true;
|
|
@ -0,0 +1,21 @@
|
||||||
|
FROM solita/ubuntu-systemd:18.04
|
||||||
|
WORKDIR /root/
|
||||||
|
#fix for bad network URL proxy
|
||||||
|
COPY ./99fixbadproxy /etc/apt/apt.conf.d/99fixbadproxy
|
||||||
|
RUN apt-get update -y && apt-get install -y \
|
||||||
|
psmisc \
|
||||||
|
iputils-ping \
|
||||||
|
nano \
|
||||||
|
python3.6 \
|
||||||
|
python3.6-dev \
|
||||||
|
python3-pip \
|
||||||
|
python3-venv \
|
||||||
|
iproute2 \
|
||||||
|
openvswitch-switch \
|
||||||
|
bridge-utils \
|
||||||
|
iperf \
|
||||||
|
tcpdump
|
||||||
|
|
||||||
|
COPY ./setup-prereqs.sh .
|
||||||
|
RUN chmod +x ./setup-prereqs.sh
|
||||||
|
RUN ./setup-prereqs.sh
|
|
@ -0,0 +1,6 @@
|
||||||
|
FROM kcratie/evio-base:1.0
|
||||||
|
WORKDIR /root/
|
||||||
|
COPY ./edge-vpnio_20.7_amd64.deb .
|
||||||
|
RUN apt-get install -y ./edge-vpnio_20.7_amd64.deb && rm -rf /var/lib/apt/lists/* && apt-get autoclean
|
||||||
|
|
||||||
|
CMD ["/sbin/init"]
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
systemctl mask getty@tty1.service && \
|
||||||
|
mkdir -p /opt/edge-vpnio && \
|
||||||
|
cd /opt/edge-vpnio && \
|
||||||
|
python3 -m venv venv && \
|
||||||
|
source venv/bin/activate && \
|
||||||
|
pip3 --no-cache-dir install psutil sleekxmpp requests simplejson ryu && \
|
||||||
|
deactivate
|
|
@ -0,0 +1,141 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CONTROLLER=https://github.com/EdgeVPNio/controller
|
||||||
|
TINCAN=https://github.com/EdgeVPNio/tincan
|
||||||
|
EXLIBS=https://github.com/ipop-project/3rd-Party-Libs.git
|
||||||
|
PYVER=3.6
|
||||||
|
EVIOVER=_20.7_amd64
|
||||||
|
|
||||||
|
function install_build_tools
|
||||||
|
{
|
||||||
|
sudo bash -c "
|
||||||
|
apt-get update -y && \
|
||||||
|
apt-get install -y build-essential
|
||||||
|
"
|
||||||
|
}
|
||||||
|
|
||||||
|
function pull_src
|
||||||
|
{
|
||||||
|
git clone $CONTROLLER ..
|
||||||
|
git clone $TINCAN ..
|
||||||
|
wd=$(pwd)
|
||||||
|
cd ../evio/tincan/external
|
||||||
|
git clone -b ubuntu-x64 --single-branch https://github.com/ipop-project/3rd-Party-Libs.git
|
||||||
|
cd $wd
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_tincan
|
||||||
|
{
|
||||||
|
wd=$(pwd)
|
||||||
|
cd ../evio/tincan/trunk/build
|
||||||
|
make clean; make
|
||||||
|
cd $wd
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_debpak
|
||||||
|
{
|
||||||
|
cp -r ../controller/* debian-package/edge-vpnio/opt/edge-vpnio/ && \
|
||||||
|
cp ../tincan/trunk/out/release/x86_64/tincan debian-package/edge-vpnio/opt/edge-vpnio/ && \
|
||||||
|
chmod +x debian-package/edge-vpnio/opt/edge-vpnio/tincan && \
|
||||||
|
./deb-gen
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_testbed_prereqs
|
||||||
|
{
|
||||||
|
sudo bash -c "
|
||||||
|
apt-get update -y && \
|
||||||
|
apt-get install -y openvswitch-switch \
|
||||||
|
python$PYVER python3-pip python3-venv python3-dev \
|
||||||
|
apt-transport-https \
|
||||||
|
ca-certificates \
|
||||||
|
curl git \
|
||||||
|
software-properties-common && \
|
||||||
|
|
||||||
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
|
||||||
|
add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable\" && \
|
||||||
|
apt-cache policy docker-ce && \
|
||||||
|
apt-get install -y containerd.io \
|
||||||
|
docker-ce-cli \
|
||||||
|
docker-ce && \
|
||||||
|
groupadd -f docker && \
|
||||||
|
usermod -a -G docker $USER \
|
||||||
|
"
|
||||||
|
echo "You must logout and relogin for docker group membership to take effect."
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_venv
|
||||||
|
{
|
||||||
|
wd=$(pwd)
|
||||||
|
cd testbed && \
|
||||||
|
python$PYVER -m venv venv && \
|
||||||
|
source venv/bin/activate && \
|
||||||
|
pip3 install simplejson
|
||||||
|
cd $wd
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_dkrimg
|
||||||
|
{
|
||||||
|
rm -f docker-image/edge-vpnio_20.7_amd64.deb
|
||||||
|
mv debian-package/edge-vpnio_20.7_amd64.deb docker-image/ && \
|
||||||
|
docker build -f ./docker-image/evio-base.Dockerfile -t kcratie/evio-base:1.0 ./docker-image && \
|
||||||
|
docker build -f ./docker-image/evio-node.Dockerfile -t kcratie/evio-node:20.7 ./docker-image
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_openfire
|
||||||
|
{
|
||||||
|
docker run --name openfire -d \
|
||||||
|
-p 9090:9090 -p 5222:5222 \
|
||||||
|
-p 5269:5269 -p 5223:5223 \
|
||||||
|
-p 7443:7443 -p 7777:7777 \
|
||||||
|
-p 7070:7070 -p 5229:5229 \
|
||||||
|
-p 5275:5275 \
|
||||||
|
edgevpnio/openfire_edgevpn_demo
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_netviz
|
||||||
|
{
|
||||||
|
#Todo: visualizer not yet available
|
||||||
|
git clone https://github.com/edgevpnio/portal.git
|
||||||
|
cd portal/setup
|
||||||
|
./setup.sh
|
||||||
|
chown -R $USER /users/$USER/
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_full_setup
|
||||||
|
{
|
||||||
|
install_build_tools
|
||||||
|
pull_src
|
||||||
|
make_tincan
|
||||||
|
make_debpak
|
||||||
|
make_dkrimg
|
||||||
|
make_testbed_prereqs
|
||||||
|
make_venv
|
||||||
|
}
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
testbed)
|
||||||
|
make_testbed_prereqs
|
||||||
|
;;
|
||||||
|
venv)
|
||||||
|
make_venv
|
||||||
|
;;
|
||||||
|
img)
|
||||||
|
make_dkrimg
|
||||||
|
;;
|
||||||
|
tincan)
|
||||||
|
make_tincan
|
||||||
|
;;
|
||||||
|
src)
|
||||||
|
pull_src
|
||||||
|
;;
|
||||||
|
xmpp)
|
||||||
|
install_openfire
|
||||||
|
;;
|
||||||
|
all)
|
||||||
|
do_full_setup
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "no match on input -> $1"
|
||||||
|
;;
|
||||||
|
esac
|
|
@ -0,0 +1,477 @@
|
||||||
|
# pylint: disable=missing-docstring
|
||||||
|
try:
|
||||||
|
import simplejson as json
|
||||||
|
except ImportError:
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import random
|
||||||
|
from distutils import spawn
|
||||||
|
import pickle
|
||||||
|
import argparse
|
||||||
|
import shutil
|
||||||
|
import time
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
|
class Testbed():
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
LAUNCH_WAIT = 60
|
||||||
|
BATCH_SZ = 5
|
||||||
|
VIRT = NotImplemented
|
||||||
|
APT = spawn.find_executable("apt-get")
|
||||||
|
CONTAINER = NotImplemented
|
||||||
|
BF_VIRT_IMG = "kcratie/evio-node:20.7"
|
||||||
|
|
||||||
|
def __init__(self, exp_dir=None):
|
||||||
|
parser = argparse.ArgumentParser(description="Configures and runs EdgeVPN Testbed")
|
||||||
|
parser.add_argument("--clean", action="store_true", default=False, dest="clean",
|
||||||
|
help="Removes all generated files and directories")
|
||||||
|
parser.add_argument("--configure", action="store_true", default=False, dest="configure",
|
||||||
|
help="Generates the config files and directories")
|
||||||
|
parser.add_argument("-v", action="store_true", default=False, dest="verbose",
|
||||||
|
help="Print testbed activity info")
|
||||||
|
parser.add_argument("--range", action="store", dest="range",
|
||||||
|
help="Specifies the testbed start and end range in format #,#")
|
||||||
|
parser.add_argument("--run", action="store_true", default=False, dest="run",
|
||||||
|
help="Runs the currently configured testbed")
|
||||||
|
parser.add_argument("--end", action="store_true", default=False, dest="end",
|
||||||
|
help="End the currently running testbed")
|
||||||
|
parser.add_argument("--info", action="store_true", default=False, dest="info",
|
||||||
|
help="Displays the current testbed configuration")
|
||||||
|
parser.add_argument("--setup", action="store_true", default=False, dest="setup",
|
||||||
|
help="Installs software requirements. Requires run as root.")
|
||||||
|
parser.add_argument("--pull", action="store_true", default=False, dest="pull",
|
||||||
|
help="Pulls the {} image from docker hub"
|
||||||
|
.format(Testbed.BF_VIRT_IMG))
|
||||||
|
parser.add_argument("--lxd", action="store_true", default=False, dest="lxd",
|
||||||
|
help="Uses LXC containers")
|
||||||
|
parser.add_argument("--dkr", action="store_true", default=False, dest="dkr",
|
||||||
|
help="Use docker containers")
|
||||||
|
parser.add_argument("--ping", action="store", dest="ping",
|
||||||
|
help="Ping the specified address from each container")
|
||||||
|
parser.add_argument("--arp", action="store", dest="arp",
|
||||||
|
help="arPing the specified address from each container")
|
||||||
|
parser.add_argument("--evio", action="store", dest="evio",
|
||||||
|
help="Perform the specified service action: stop/start/restart")
|
||||||
|
parser.add_argument("--churn", action="store", dest="churn",
|
||||||
|
help="Restarts the specified amount of nodes in the overlay,"
|
||||||
|
"one every interval")
|
||||||
|
parser.add_argument("--test", action="store", dest="test",
|
||||||
|
help="Performs latency and bandwidth test between random pairs of "
|
||||||
|
"nodes. Ex test=<test_name>")
|
||||||
|
|
||||||
|
self.args = parser.parse_args()
|
||||||
|
self.exp_dir = exp_dir
|
||||||
|
if not self.exp_dir:
|
||||||
|
self.exp_dir = os.path.abspath(".")
|
||||||
|
self.template_file = "{0}/template-config.json".format(self.exp_dir)
|
||||||
|
self.config_dir = "{0}/config".format(self.exp_dir)
|
||||||
|
self.log_dir = "{0}/log".format(self.exp_dir)
|
||||||
|
self.data_dir = "{0}/data".format(self.exp_dir)
|
||||||
|
self.cert_dir = "{0}/cert".format(self.exp_dir)
|
||||||
|
self.config_file_base = "{0}/config-".format(self.config_dir)
|
||||||
|
self.seq_file = "{0}/startup.list".format(self.exp_dir)
|
||||||
|
self.range_file = "{0}/range_file".format(self.exp_dir)
|
||||||
|
|
||||||
|
if self.args.range:
|
||||||
|
rng = self.args.range.rsplit(",", 2)
|
||||||
|
self.range_end = int(rng[1])
|
||||||
|
self.range_start = int(rng[0])
|
||||||
|
elif not self.args.range and os.path.isfile("range_file"):
|
||||||
|
with open(self.range_file) as rng_fle:
|
||||||
|
rng = rng_fle.read().strip().rsplit(",", 2)
|
||||||
|
self.range_end = int(rng[1])
|
||||||
|
self.range_start = int(rng[0])
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Range unspecified")
|
||||||
|
self.total_inst = self.range_end - self.range_start
|
||||||
|
self.seq_list = None #[range(self.range_end, self.range_start)]
|
||||||
|
self.load_seq_list()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def runshell(cls, cmd):
|
||||||
|
""" Run a shell command. if fails, raise an exception. """
|
||||||
|
if cmd[0] is None:
|
||||||
|
raise ValueError("No executable specified to run")
|
||||||
|
resp = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def gen_config(self, range_start, range_end):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def start_instance(self, instance):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def end(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def clean_config(self):
|
||||||
|
if os.path.isdir(self.config_dir):
|
||||||
|
shutil.rmtree(self.config_dir)
|
||||||
|
if self.args.verbose:
|
||||||
|
print("Removed dir {}".format(self.config_dir))
|
||||||
|
if os.path.isfile(self.seq_file):
|
||||||
|
os.remove(self.seq_file)
|
||||||
|
if self.args.verbose:
|
||||||
|
print("Removed file {}".format(self.seq_file))
|
||||||
|
|
||||||
|
def make_clean(self):
|
||||||
|
self.clean_config()
|
||||||
|
if os.path.isdir(self.log_dir):
|
||||||
|
shutil.rmtree(self.log_dir)
|
||||||
|
if self.args.verbose:
|
||||||
|
print("Removed dir {}".format(self.log_dir))
|
||||||
|
|
||||||
|
def configure(self):
|
||||||
|
with open(self.range_file, "w") as rng_fle:
|
||||||
|
rng_fle.write(self.args.range)
|
||||||
|
self.gen_config(self.range_start, self.range_end)
|
||||||
|
self.save_seq_list()
|
||||||
|
|
||||||
|
def save_seq_list(self):
|
||||||
|
with open(self.seq_file, "wb") as seq_fle:
|
||||||
|
pickle.dump(self.seq_list, seq_fle)
|
||||||
|
seq_fle.flush()
|
||||||
|
if self.args.verbose:
|
||||||
|
print("Instance sequence saved with {0} entries\n{1}"
|
||||||
|
.format(self.total_inst, self.seq_list))
|
||||||
|
|
||||||
|
def load_seq_list(self):
|
||||||
|
if os.path.isfile(self.seq_file):
|
||||||
|
with open(self.seq_file, "rb") as seq_fle:
|
||||||
|
self.seq_list = pickle.load(seq_fle)
|
||||||
|
if self.args.verbose:
|
||||||
|
print("Sequence list loaded from existing file - {0} entries\n{1}".
|
||||||
|
format(len(self.seq_list), self.seq_list))
|
||||||
|
else:
|
||||||
|
self.seq_list = list(range(self.range_start, self.range_end))
|
||||||
|
random.shuffle(self.seq_list)
|
||||||
|
|
||||||
|
def start_range(self, num, wait):
|
||||||
|
cnt = 0
|
||||||
|
sequence = self.seq_list[self.range_start-1:self.range_end]
|
||||||
|
for inst in sequence:
|
||||||
|
self.start_instance(inst)
|
||||||
|
cnt += 1
|
||||||
|
if cnt % num == 0 and cnt < len(sequence):
|
||||||
|
#if self.args.verbose:
|
||||||
|
print("{0}/{1} container(s) instantiated".format(cnt, len(sequence)))
|
||||||
|
time.sleep(wait)
|
||||||
|
print("{0} container(s) instantiated".format(cnt))
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.start_range(Testbed.BATCH_SZ, Testbed.LAUNCH_WAIT)
|
||||||
|
|
||||||
|
def display_current_config(self):
|
||||||
|
print("----Testbed Configuration----")
|
||||||
|
print("{0} instances range {1}-{2}".format(self.total_inst, self.range_start,
|
||||||
|
self.range_end))
|
||||||
|
print("Config dir {0}".format(self.config_dir))
|
||||||
|
print("Config base filename {0}".format(self.config_file_base))
|
||||||
|
print("Log dir {0}".format(self.log_dir))
|
||||||
|
print("Contianer image {0}".format(Testbed.BF_VIRT_IMG))
|
||||||
|
print("".format())
|
||||||
|
|
||||||
|
def setup_system(self):
|
||||||
|
setup_cmds = [["./setup-system.sh"]]
|
||||||
|
for cmd_list in setup_cmds:
|
||||||
|
if self.args.verbose:
|
||||||
|
print(cmd_list)
|
||||||
|
resp = Testbed.runshell(cmd_list)
|
||||||
|
print(resp.stdout.decode("utf-8") if resp.returncode == 0 else
|
||||||
|
resp.stderr.decode("utf-8"))
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def run_container_cmd(self, cmd_line, instance_num):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def churn(self, param):
|
||||||
|
params = param.rsplit(",", 2)
|
||||||
|
iters = int(params[0])
|
||||||
|
inval = int(params[1])
|
||||||
|
self._churn(iters, inval)
|
||||||
|
|
||||||
|
def _churn(self, churn_count=0, interval=30):
|
||||||
|
if churn_count == 0:
|
||||||
|
churn_count = self.total_inst
|
||||||
|
cnt = 0
|
||||||
|
restarted_nds = set()
|
||||||
|
while cnt < churn_count:
|
||||||
|
inst = random.choice(range(self.range_start, self.range_end))
|
||||||
|
print("Stopping node", inst)
|
||||||
|
self.run_container_cmd(["systemctl", "stop", "evio"], inst)
|
||||||
|
if self.args.verbose:
|
||||||
|
print("Waiting", interval, "seconds")
|
||||||
|
time.sleep(interval)
|
||||||
|
print("Resuming node", inst)
|
||||||
|
self.run_container_cmd(["systemctl", "start", "evio"], inst)
|
||||||
|
restarted_nds.add(inst)
|
||||||
|
cnt += 1
|
||||||
|
if self.args.verbose:
|
||||||
|
print("Waiting", interval, "seconds")
|
||||||
|
time.sleep(interval)
|
||||||
|
if self.args.verbose:
|
||||||
|
print("{0} nodes restarted\n{1}".format(cnt, str(restarted_nds)))
|
||||||
|
|
||||||
|
def run_test(self):
|
||||||
|
# test = None
|
||||||
|
# if self.args.test == "lui":
|
||||||
|
# test = TestLinkUtilization()
|
||||||
|
# test.create_input_files()
|
||||||
|
# if self.args.test == "lur":
|
||||||
|
# test = TestLinkUtilization()
|
||||||
|
# test.create_result_report()
|
||||||
|
print("Test case not implemented")
|
||||||
|
|
||||||
|
class DockerTestbed(Testbed):
|
||||||
|
VIRT = spawn.find_executable("docker")
|
||||||
|
CONTAINER = "evio-dkr{0}"
|
||||||
|
|
||||||
|
def __init__(self, exp_dir=None):
|
||||||
|
super().__init__(exp_dir=exp_dir)
|
||||||
|
self.network_name = "dkrnet"
|
||||||
|
|
||||||
|
#def configure(self):
|
||||||
|
# super().configure()
|
||||||
|
# self.pull_image()
|
||||||
|
|
||||||
|
def create_network(self):
|
||||||
|
#netid=docker network ls | grep dkrnet | awk 'BEGIN { FS=" "} {print $2}'
|
||||||
|
#docker network create dkrnet
|
||||||
|
pass
|
||||||
|
|
||||||
|
def gen_config(self, range_start, range_end):
|
||||||
|
with open(self.template_file) as cfg_tmpl:
|
||||||
|
template = json.load(cfg_tmpl)
|
||||||
|
olid = template["CFx"].get("Overlays", None)
|
||||||
|
olid = olid[0]
|
||||||
|
node_id = template["CFx"].get("NodeId", "a000###feb6040628e5fb7e70b04f###")
|
||||||
|
node_name = template["OverlayVisualizer"].get("NodeName", "dkr###")
|
||||||
|
netwk = template["BridgeController"]["Overlays"][olid]["NetDevice"]["AppBridge"].get("NetworkAddress", "10.10.1.0/24")
|
||||||
|
netwk = ipaddress.IPv4Network(netwk)
|
||||||
|
for val in range(range_start, range_end):
|
||||||
|
rng_str = "{0:03}".format(val)
|
||||||
|
cfg_file = "{0}{1}.json".format(self.config_file_base, rng_str)
|
||||||
|
node_id = "{0}{1}{2}{1}{3}".format(node_id[:4], rng_str, node_id[7:29], node_id[32:])
|
||||||
|
node_name = "{0}{1}".format(node_name[:3], rng_str)
|
||||||
|
node_ip = str(netwk[val])
|
||||||
|
template["CFx"]["NodeId"] = node_id
|
||||||
|
template["OverlayVisualizer"]["NodeName"] = node_name
|
||||||
|
template["BridgeController"]["Overlays"][olid]["NetDevice"]["AppBridge"]["IP4"] = node_ip
|
||||||
|
template["BridgeController"]["Overlays"][olid]["NetDevice"]["AppBridge"]["PrefixLen"] = netwk.prefixlen
|
||||||
|
os.makedirs(self.config_dir, exist_ok=True)
|
||||||
|
with open(cfg_file, "w") as cfg_fle:
|
||||||
|
json.dump(template, cfg_fle, indent=2)
|
||||||
|
cfg_fle.flush()
|
||||||
|
if self.args.verbose:
|
||||||
|
print("{0} config file(s) generated".format(range_end-range_start))
|
||||||
|
|
||||||
|
def start_instance(self, instance):
|
||||||
|
instance = "{0:03}".format(instance)
|
||||||
|
container = DockerTestbed.CONTAINER.format(instance)
|
||||||
|
log_dir = "{0}/dkr{1}".format(self.log_dir, instance)
|
||||||
|
os.makedirs(log_dir, exist_ok=True)
|
||||||
|
|
||||||
|
cfg_file = "{0}{1}.json".format(self.config_file_base, instance)
|
||||||
|
if not os.path.isfile(cfg_file):
|
||||||
|
self.gen_config(instance, instance+1)
|
||||||
|
|
||||||
|
mount_cfg = "{0}:/etc/opt/edge-vpnio/config.json".format(cfg_file)
|
||||||
|
mount_log = "{0}/:/var/log/edge-vpnio/".format(log_dir)
|
||||||
|
#mount_data = "{0}/:/var/edge-vpnio/".format(self.data_dir)
|
||||||
|
mount_cert = "{0}/:/var/edge-vpnio/cert/".format(self.cert_dir)
|
||||||
|
args = ["--rm", "--privileged"]
|
||||||
|
opts = "-d"
|
||||||
|
img = Testbed.BF_VIRT_IMG
|
||||||
|
cmd = "/sbin/init"
|
||||||
|
cmd_list = [DockerTestbed.VIRT, "run", opts, "-v", mount_cfg, "-v", mount_log, "-v", mount_cert,
|
||||||
|
args[0], args[1], "--name", container, "--network", self.network_name,
|
||||||
|
img, cmd]
|
||||||
|
if self.args.verbose:
|
||||||
|
print(cmd_list)
|
||||||
|
resp = Testbed.runshell(cmd_list)
|
||||||
|
print(resp.stdout.decode("utf-8") if resp.returncode == 0 else resp.stderr.decode("utf-8"))
|
||||||
|
|
||||||
|
def run_container_cmd(self, cmd_line, instance_num):
|
||||||
|
#report = dict(fail_count=0, fail_node=[])
|
||||||
|
cmd_list = [DockerTestbed.VIRT, "exec", "-it"]
|
||||||
|
inst = "{0:03}".format(instance_num)
|
||||||
|
container = DockerTestbed.CONTAINER.format(inst)
|
||||||
|
cmd_list.append(container)
|
||||||
|
cmd_list += cmd_line
|
||||||
|
resp = Testbed.runshell(cmd_list)
|
||||||
|
if self.args.verbose:
|
||||||
|
print(cmd_list)
|
||||||
|
print(resp.stdout.decode("utf-8"))
|
||||||
|
#if resp.returncode != 0:
|
||||||
|
# report["fail_count"] += 1
|
||||||
|
# report["fail_node"].append("node-{0}".format(inst))
|
||||||
|
#rpt_msg = "{0}: {1}/{2} failed\n{3}".format(cmd_line, report["fail_count"],
|
||||||
|
# self.range_end - self.range_start,
|
||||||
|
# report["fail_node"])
|
||||||
|
#print(rpt_msg)
|
||||||
|
|
||||||
|
def run_cmd_on_range(self, cmd_line, delay=0):
|
||||||
|
report = dict(fail_count=0, fail_node=[])
|
||||||
|
for inst in self.seq_list[self.range_start-1:self.range_end]:
|
||||||
|
cmd_list = [DockerTestbed.VIRT, "exec", "-it"]
|
||||||
|
inst = "{0:03}".format(inst)
|
||||||
|
container = DockerTestbed.CONTAINER.format(inst)
|
||||||
|
cmd_list.append(container)
|
||||||
|
cmd_list += cmd_line
|
||||||
|
resp = Testbed.runshell(cmd_list)
|
||||||
|
if self.args.verbose:
|
||||||
|
print(cmd_list)
|
||||||
|
print(resp.stdout.decode("utf-8"))
|
||||||
|
if resp.returncode != 0:
|
||||||
|
report["fail_count"] += 1
|
||||||
|
report["fail_node"].append("node-{0}".format(inst))
|
||||||
|
if delay > 0:
|
||||||
|
time.sleep(delay)
|
||||||
|
rpt_msg = "{0}: {1}/{2} failed\n{3}".format(cmd_line, report["fail_count"],
|
||||||
|
self.range_end - self.range_start,
|
||||||
|
report["fail_node"])
|
||||||
|
print(rpt_msg)
|
||||||
|
|
||||||
|
|
||||||
|
def pull_image(self):
|
||||||
|
cmd_list = [DockerTestbed.VIRT, "pull", Testbed.BF_VIRT_IMG]
|
||||||
|
resp = Testbed.runshell(cmd_list)
|
||||||
|
if self.args.verbose:
|
||||||
|
print(resp)
|
||||||
|
|
||||||
|
def stop_range(self):
|
||||||
|
cnt = 0
|
||||||
|
cmd_list = [DockerTestbed.VIRT, "kill"]
|
||||||
|
sequence = self.seq_list[self.range_start-1:self.range_end]
|
||||||
|
for inst in sequence:
|
||||||
|
cnt += 1
|
||||||
|
inst = "{0:03}".format(inst)
|
||||||
|
container = DockerTestbed.CONTAINER.format(inst)
|
||||||
|
cmd_list.append(container)
|
||||||
|
if self.args.verbose:
|
||||||
|
print(cmd_list)
|
||||||
|
resp = Testbed.runshell(cmd_list)
|
||||||
|
print(resp.stdout.decode("utf-8") if resp.returncode == 0 else
|
||||||
|
resp.stderr.decode("utf-8"))
|
||||||
|
print("{0} Docker container(s) terminated".format(cnt))
|
||||||
|
|
||||||
|
def end(self):
|
||||||
|
self.run_cmd_on_range(["systemctl", "stop", "evio"])
|
||||||
|
self.stop_range()
|
||||||
|
|
||||||
|
def run_ping(self, target_address):
|
||||||
|
report = dict(fail_count=0, fail_node=[])
|
||||||
|
for inst in range(self.range_start, self.range_end):
|
||||||
|
cmd_list = [DockerTestbed.VIRT, "exec", "-it"]
|
||||||
|
inst = "{0:03}".format(inst)
|
||||||
|
container = DockerTestbed.CONTAINER.format(inst)
|
||||||
|
cmd_list.append(container)
|
||||||
|
cmd_list += ["ping", "-c1"]
|
||||||
|
cmd_list.append(target_address)
|
||||||
|
resp = Testbed.runshell(cmd_list)
|
||||||
|
if self.args.verbose:
|
||||||
|
print(cmd_list)
|
||||||
|
print("ping ", target_address, "\n", resp.stdout.decode("utf-8"))
|
||||||
|
if resp.returncode != 0:
|
||||||
|
report["fail_count"] += 1
|
||||||
|
report["fail_node"].append("node-{0}".format(inst))
|
||||||
|
rpt_msg = "ping {0}: {1}/{2} failed\n{3}".format(target_address, report["fail_count"],
|
||||||
|
self.range_end - self.range_start,
|
||||||
|
report["fail_node"])
|
||||||
|
print(rpt_msg)
|
||||||
|
|
||||||
|
def run_arp(self, target_address):
|
||||||
|
for inst in range(self.range_start, self.range_end):
|
||||||
|
cmd_list = [DockerTestbed.VIRT, "exec", "-it"]
|
||||||
|
inst = "{0:03}".format(inst)
|
||||||
|
container = DockerTestbed.CONTAINER.format(inst)
|
||||||
|
cmd_list.append(container)
|
||||||
|
cmd_list += ["arping", "-C1"]
|
||||||
|
cmd_list.append(target_address)
|
||||||
|
if self.args.verbose:
|
||||||
|
print(cmd_list)
|
||||||
|
resp = Testbed.runshell(cmd_list)
|
||||||
|
print(resp.stdout.decode("utf-8") if resp.returncode == 0 else
|
||||||
|
resp.stderr.decode("utf-8"))
|
||||||
|
|
||||||
|
def run_svc_ctl(self, svc_ctl):
|
||||||
|
if svc_ctl == "stop":
|
||||||
|
self.run_cmd_on_range(["systemctl", "stop", "evio"])
|
||||||
|
elif svc_ctl == "start":
|
||||||
|
self.run_cmd_on_range(["systemctl", "start", "evio"], 10)
|
||||||
|
elif svc_ctl == "restart":
|
||||||
|
self.run_cmd_on_range(["systemctl", "restart", "evio"], 1)
|
||||||
|
else:
|
||||||
|
print("Invalid service control specified, only accepts start/stop/restart")
|
||||||
|
|
||||||
|
def main(): # pylint: disable=too-many-return-statements
|
||||||
|
exp = DockerTestbed()
|
||||||
|
|
||||||
|
|
||||||
|
if exp.args.run and exp.args.end:
|
||||||
|
print("Error! Both run and end were specified.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.info:
|
||||||
|
exp.display_current_config()
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.setup:
|
||||||
|
exp.setup_system()
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.pull:
|
||||||
|
exp.pull_image()
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.clean:
|
||||||
|
exp.make_clean()
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.range_end - exp.range_start <= 0:
|
||||||
|
print("Invalid range, please fix RANGE_START={0} RANGE_END={1}".
|
||||||
|
format(exp.range_start, exp.range_end))
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.configure:
|
||||||
|
exp.configure()
|
||||||
|
|
||||||
|
if exp.args.run:
|
||||||
|
exp.run()
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.end:
|
||||||
|
exp.end()
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.ping:
|
||||||
|
exp.run_ping(exp.args.ping)
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.arp:
|
||||||
|
exp.run_arp(exp.args.arp)
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.evio:
|
||||||
|
exp.run_svc_ctl(exp.args.evio)
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.churn:
|
||||||
|
exp.churn(exp.args.churn)
|
||||||
|
return
|
||||||
|
|
||||||
|
if exp.args.test:
|
||||||
|
exp.run_test()
|
||||||
|
return
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function do_update
|
||||||
|
{
|
||||||
|
cp /etc/sysctl.conf /etc/sysctl.conf.`date +%F-%H%M%S`
|
||||||
|
echo "kernel.keys.maxkeys=2000" >> /etc/sysctl.conf
|
||||||
|
echo "fs.inotify.max_queued_events=1048576" >> /etc/sysctl.conf
|
||||||
|
echo "fs.inotify.max_user_instances=1048576" >> /etc/sysctl.conf
|
||||||
|
echo "fs.inotify.max_user_watches=1048576" >> /etc/sysctl.conf
|
||||||
|
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
|
||||||
|
echo "net.ipv4.neigh.default.gc_thresh3=8192" >> /etc/sysctl.conf
|
||||||
|
|
||||||
|
cp /etc/security/limits.conf /etc/security/limits.conf.`date +%F-%H%M%S`
|
||||||
|
echo "* soft nofile 1048576" >> /etc/security/limits.conf
|
||||||
|
echo "* hard nofile 1048576" >> /etc/security/limits.conf
|
||||||
|
echo "root soft nofile 1048576" >> /etc/security/limits.conf
|
||||||
|
echo "root hard nofile 1048576" >> /etc/security/limits.conf
|
||||||
|
echo "* soft memlock unlimited" >> /etc/security/limits.conf
|
||||||
|
echo "* hard memlock unlimited" >> /etc/security/limits.conf
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "This script enables runing lots of containers on a single host."
|
||||||
|
echo "Note it must be run as root, sudo is insufficient."
|
||||||
|
echo "Do you wish to proceed?"
|
||||||
|
select yn in "Yes" "No"; do
|
||||||
|
case $yn in
|
||||||
|
Yes ) do_update; break;;
|
||||||
|
No ) exit;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
reboot
|
Loading…
Reference in New Issue