Commit e3dd3953 authored by SIMONIN Matthieu's avatar SIMONIN Matthieu
Browse files

g5k: support for non tantap deployment (baseline)

parent 8896f194
......@@ -302,11 +302,7 @@ done
type=str,
help="The hostname of the virtual machine",
)
parser.add_argument(
"--mode",
type=str,
help="mode (tap | tantap)",
)
parser.add_argument("--mode", type=str, help="mode (tap | tantap)", default="tap")
parser.add_argument(
"--out",
type=str,
......@@ -396,4 +392,6 @@ done
out = args.out
if not out:
out = f"{vm.hostname}.out"
# gracefully handle the output directory
Path(out).parent.mkdir(parents=True, exist_ok=True)
vm.start(working_dir=Path(tmp), stdout=Path(out).open("w"))
\ No newline at end of file
"""
Some common default.
Intent: gives some consistent settings between different scripts
"""
from pathlib import Path
import os
ROOT_DIR = Path(__file__).parent.parent.resolve()
# fallback on the system one
QEMU = os.environ.get("QEMU", "qemu-system-x86_64")
# fallback on the local built disk
QEMU_IMAGE = os.environ.get(
"IMAGE",
ROOT_DIR
/ "packer"
/ "packer-debian-10.3.0-x86_64-qemu"
/ "debian-10.3.0-x86_64.qcow2",
)
# fallback on our setting
QEMU_ARGS = os.environ.get(
"QEMU_ARGS", "-icount shift=0,sleep=off,align=off -rtc clock=vm"
)
BOOT_CMD = os.environ.get("BOOT_CMD", ROOT_DIR / "examples" / "qemus" / "boot.py")
AUTOCONFIG_NET = False
DEFAULT_DOCKER_IMAGE = "registry.gitlab.inria.fr/quinson/2018-vsg/tansiv:latest"
......@@ -2,14 +2,12 @@ import argparse
import logging
from ipaddress import IPv4Interface
from pathlib import Path
import time
import traceback
import enoslib as en
DEFAULT_DOCKER_IMAGE = "registry.gitlab.inria.fr/quinson/2018-vsg/tansiv:latest"
class TansivHost(en.Host):
"""
A TansivHost is an EnOSlib Host but requires an extra jump to access it
......@@ -85,6 +83,8 @@ def generate_deployment(args) -> str:
ET.SubElement(vm, "argument", dict(value=f"--mode"))
ET.SubElement(vm, "argument", dict(value=f"tantap"))
ET.SubElement(vm, "argument", dict(value=f"--autoconfig_net"))
ET.SubElement(vm, "argument", dict(value=f"--out"))
ET.SubElement(vm, "argument", dict(value=f"tantap/vm-{descriptor}.out"))
ET.SubElement(vm, "argument", dict(value=f"192.168.120.{descriptor}/24"))
ET.SubElement(vm, "argument", dict(value=f"10.0.0.{descriptor}/24"))
element_tree = ElementTree(platform)
......@@ -107,6 +107,8 @@ def deploy(args, env=None):
queue = args.queue
docker_image = args.docker_image
qemu_args = args.qemu_args
mode = args.mode
prod = en.G5kNetworkConf(
id="id",
roles=["prod"],
......@@ -161,6 +163,18 @@ def deploy(args, env=None):
dest="/tmp/tansiv/boot.py",
display_name="copying deployment file",
)
# we also need the notansiv wrapper (baseline tests)
p.synchronize(
src="notansiv.py",
dest="/tmp/tansiv/notansiv.py",
display_name="copying deployment file",
)
# we also need the constants
p.synchronize(
src="constants.py",
dest="/tmp/tansiv/constants.py",
display_name="copying deployment file",
)
# finally start the container
environment = {
"AUTOCONFIG_NET": "true",
......@@ -169,16 +183,36 @@ def deploy(args, env=None):
if qemu_args is not None:
environment.update(QEMU_ARGS=qemu_args)
if mode == "tantap":
# tantap case
# - QEMU is set in the env (Dockerfile)
# - QEMU_ARGS is set in the env
# - IMAGE us set in the env
kwargs = dict(
command="platform.xml deployment.xml --log=vm_interface.threshold:debug --log=vm_coordinator.threshold:debug"
)
elif mode == "tap":
# tap case
# - QEMU is set in the env (Dockerfile)
# - QEMU_ARGS is set in the env
# - IMAGE is passed using the env
kwargs = dict(
command="/srv/notansiv.py --boot_cmd=/srv/boot.py", entrypoint="python3"
)
else:
# FIXME could be handle earlier using a enum...
raise ValueError(f"Unknown mode of operation {mode}")
p.docker_container(
state="started",
network_mode="host",
name="tansiv",
image=docker_image,
command="platform.xml deployment.xml --log=vm_interface.threshold:debug --log=vm_coordinator.threshold:debug",
volumes=["/tmp/id_rsa.pub:/root/.ssh/id_rsa.pub", "/tmp/tansiv:/srv"],
env=environment,
capabilities=["NET_ADMIN"],
devices=["/dev/net/tun"],
**kwargs,
)
# by default packets that needs to be forwarded by the bridge are sent to iptables
......@@ -208,8 +242,6 @@ def deploy(args, env=None):
en.wait_for(roles=tansiv_roles)
env["roles"] = roles
env["tansiv_roles"] = tansiv_roles
env["provider"] = provider
env["args"] = args
......@@ -261,6 +293,7 @@ def flent(args, env=None):
"(tmux ls | grep netserver ) ||tmux new-session -s netserver -d 'netserver -D'"
)
result_dir = env["result_dir"]
for bench in ["tcp_download", "tcp_upload", "udp_flood"]:
import time
......@@ -300,6 +333,11 @@ def destroy(args, env=None):
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
import sys
sys.path.append(".")
from constants import *
parser = argparse.ArgumentParser(description="Tansiv experimentation engine")
# FIXME
......@@ -308,10 +346,6 @@ if __name__ == "__main__":
parser_deploy = subparsers.add_parser(
"deploy", help="Deploy tansiv and the associated VMs"
)
parser_deploy.add_argument(
"image",
help="Base image to use (qcow2)",
)
parser_deploy.add_argument(
"platform",
help="The simgrid plaform file",
......@@ -332,7 +366,16 @@ if __name__ == "__main__":
help="Tansiv docker image to use",
default=DEFAULT_DOCKER_IMAGE,
)
parser_deploy.add_argument("--qemu_args", help="Some qemu_args")
parser_deploy.add_argument(
"--image", help="Base image to use (qcow2)", default=QEMU_IMAGE
)
parser_deploy.add_argument("--qemu_args", help="Some qemu_args", default=QEMU_ARGS)
parser_deploy.add_argument(
"--mode", help="Mode of operation (tap|tantap)", default="tantap"
)
parser_deploy.add_argument(
"--env", help="env directory to use (intercepter by EnOSlib)"
)
parser_deploy.set_defaults(func=deploy)
# --------------------------------------------------------------------------
......
......@@ -13,15 +13,36 @@ import enoslib as en
from g5k import TansivHost
N = 2
VM1 = ip_interface("10.0.0.11/24")
VM2 = ip_interface("10.0.0.12/24")
VMS = [VM1, VM2]
class ExpEnv(object):
"""Context manager that boots n vm."""
def __init__(self, qemu_cmd, qemu_image, qemu_args, result_dir, number: int = 2):
"""Context manager that boots n vm.
The intent is to use it as a drop-in replacement of the tansiv process
to test stuffs without Tansiv in the picture.
So this will fork/exec as many VMs as needed using a call to the boot.py
wrapper (the same as tansiv uses). These VMs will thus use a regular
bridged tap to communicate.
Args:
qemu_cmd: the path to the qemu executable
qemu_image: the disk image to use (e.g. a qcow2 image)
qemu_args: some qemu args to use (-icount sleep=off,shift=0 sounds reasonnable)
result_dir: put some logs (each vm stdout) in this directory
boot_cmd: the path to the boot.py executable that will boot the vms.
number: number of VMs to boot
"""
def __init__(
self,
qemu_cmd: str,
qemu_image: str,
qemu_args: str,
result_dir: str,
boot_cmd: str = "../examples/qemus/boot.py",
number: int = 2,
):
self.boot_cmd = boot_cmd
self.qemu_cmd = qemu_cmd
self.qemu_image = qemu_image
self.qemu_args = qemu_args
......@@ -30,7 +51,7 @@ class ExpEnv(object):
self.child_pids = []
def __enter__(self):
# fork exec 2 vms
# fork exec some VMs
for i in range(self.number):
pid = os.fork()
descriptor = 10 + i
......@@ -43,7 +64,7 @@ class ExpEnv(object):
f"{sys.executable}",
[
sys.executable,
"../examples/qemus/boot.py",
self.boot_cmd,
tantap_ip,
management_ip,
"--qemu_cmd",
......@@ -57,7 +78,6 @@ class ExpEnv(object):
],
env,
)
self.child_pids.append(pid)
tansiv_hosts = []
for i in range(self.number):
......@@ -76,49 +96,6 @@ class ExpEnv(object):
os.killpg(os.getpgrp(), signal.SIGTERM)
def flent(tansiv_roles, result_dir=Path("result"), bench: str = "tcp_download"):
hosts = tansiv_roles["all"]
# split the hosts
masters = hosts[0:2:]
workers = hosts[1:2:]
vm_time = defaultdict(list)
host_time = defaultdict(list)
for machine in hosts:
machine.extra.update(flent_server=masters[0].extra["tansiv_alias"])
with en.play_on(roles=dict(all=masters)) as p:
p.shell(
"(tmux ls | grep netserver ) ||tmux new-session -s netserver -d 'netserver -D'"
)
with en.play_on(roles=dict(all=workers)) as p:
p.shell(
(
f"flent {bench}"
+ " -p totals -l 30 -H {{ flent_server }} "
+ f"-o {bench}.png"
)
)
p.fetch(src=f"{bench}.png", dest=str(result_dir))
return {bench: dict(vm_time=vm_time, host_time=host_time)}
def stress(tansiv_roles, args):
vm_time = defaultdict(list)
host_time = defaultdict(list)
with en.play_on(roles=tansiv_roles) as p:
p.shell(f"stress {args}")
return {args: dict(vm_time=vm_time, host_time=host_time)}
def dump_steps(result_dir: Path, args: str, stepŝ: Dict):
with (result_dir / "check_timers.json").open("w") as f:
json.dump(dict(qemu_args=args, results=steps), f)
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
qemu_argsz = [
......@@ -142,21 +119,4 @@ if __name__ == "__main__":
number=2,
) as tansiv_roles:
steps = dict()
for stress_cmd in [
"--cpu 1 --timeout 30s",
# "--io 1 --timeout 30s",
"--hdd 1 --timeout 30s",
]:
steps.update(stress(tansiv_roles, stress_cmd))
print(steps)
dump_steps(result_dir, qemu_args, steps)
time.sleep(30)
for bench in ["tcp_download", "tcp_upload", "udp_flood"]:
steps.update(flent(tansiv_roles, result_dir, bench=bench))
# wait some time (time as measured on the host system)
dump_steps(result_dir, qemu_args, steps)
time.sleep(30)
time.sleep(60)
time.sleep(60)
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment