aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rumba/testbeds/qemu.py115
1 files changed, 75 insertions, 40 deletions
diff --git a/rumba/testbeds/qemu.py b/rumba/testbeds/qemu.py
index 0a2126f..2f5491a 100644
--- a/rumba/testbeds/qemu.py
+++ b/rumba/testbeds/qemu.py
@@ -20,61 +20,62 @@
import multiprocessing
import rumba.model as mod
+from subprocess import Popen
+
-# Fake testbed, useful for testing
class Testbed(mod.Testbed):
- def __init__(self, exp_name, username, proj_name="ARCFIRE", password=""):
+ def __init__(self, exp_name, username, vm_img_folder, proj_name="ARCFIRE", password="", use_vhost=True):
mod.Testbed.__init__(self, exp_name, username, password, proj_name)
+ self.vms = {}
+ self.shims = []
+ self.vm_img_path = vm_img_folder
+ self.vhost = use_vhost
def create_experiment(self, experiment):
"""
:type experiment mod.Experiment
+ :rtype str
:param experiment: The experiment running
+ :return the script to be run to create the experiment's vms
"""
print("[QEMU testbed] swapping in")
command_str = ""
# Building bridges and taps
- vms = {}
-
for shim in experiment.dif_ordering:
if not isinstance(shim, mod.ShimEthDIF):
# Nothing to do here
continue
+ self.shims.append(shim)
command_str += 'sudo brctl addbr %(br)s\n' \
'sudo ip link set %(br)s up\n' \
- '\n' % {'br': shim}
+ '\n' % {'br': shim.name}
for node in shim.members: # type:mod.Node
- # TODO ask: full_name or simply name?
- name = node.full_name
- vm = vms.setdefault(name, {'vm': node, 'ports': []})
+ name = node.name
+ vm = self.vms.setdefault(name, {'vm': node, 'ports': []})
port_id = len(vm['ports']) + 1
tap_id = '%s.%02x' % (name, port_id)
command_str += 'sudo ip tuntap add mode tap name %(tap)s\n' \
'sudo ip link set %(tap)s up\n' \
'sudo brctl addif %(br)s %(tap)s\n\n' \
- % {'tap': tap_id, 'br': shim}
+ % {'tap': tap_id, 'br': shim.name}
if shim.link_speed > 0:
- speed = '%dbit/s' % shim.link_speed
-
- # TODO see what to do here
- # # Rate limit the traffic transmitted on the TAP interface
- # netems[shim][vm]['args'] += ' rate %s' % (speed,)
- #
- # # Rate limit the traffic transmitted on the TAP interface
- # outs += 'sudo tc qdisc add dev %(tap)s handle 1: root ' \
- # 'htb default 11\n' \
- # 'sudo tc class add dev %(tap)s parent 1: classid ' \
- # '1:1 htb rate 10gbit\n' \
- # 'sudo tc class add dev %(tap)s parent 1:1 classid ' \
- # '1:11 htb rate %(speed)s\n' \
- # % {'tap': tap, 'speed': speed}
+ speed = '%dmbit' % shim.link_speed
+
+ # Rate limit the traffic transmitted on the TAP interface
+ command_str += 'sudo tc qdisc add dev %(tap)s handle 1: root ' \
+ 'htb default 11\n' \
+ 'sudo tc class add dev %(tap)s parent 1: classid ' \
+ '1:1 htb rate 10gbit\n' \
+ 'sudo tc class add dev %(tap)s parent 1:1 classid ' \
+ '1:11 htb rate %(speed)s\n' \
+ % {'tap': tap_id, 'speed': speed}
vm['ports'].append({'tap_id': tap_id, 'shim': shim, 'port_id': port_id})
- # TODO ask about IP address. Was there in demo.
+ # TODO deal with Ip address (shim UDP DIF).
# Building vms
@@ -84,38 +85,31 @@ class Testbed(mod.Testbed):
base_port = 2222
vm_memory = 164
vm_frontend = 'virtio-net-pci'
- vm_img_path = '########## TBD ############' # TODO
- vhost = False # TODO
vmid = 1
for node in experiment.nodes:
name = node.full_name
- vm = vms.setdefault(name, {'vm': node, 'ports': []})
+ vm = self.vms.setdefault(name, {'vm': node, 'ports': []})
fwdp = base_port + vmid
fwdc = fwdp + 10000
mac = '00:0a:0a:0a:%02x:%02x' % (vmid, 99)
vm['ssh'] = fwdp
+ vm['id'] = vmid
vars_dict = {'fwdp': fwdp, 'id': vmid, 'mac': mac,
- 'vmimgpath': vm_img_path, 'fwdc': fwdc,
+ 'vmimgpath': self.vm_img_path, 'fwdc': fwdc,
'memory': vm_memory, 'frontend': vm_frontend,
'vmname': name}
host_fwd_str = 'hostfwd=tcp::%(fwdp)s-:22' % vars_dict
- # TODO: will we do this?
- # if name in hostfwds:
- # for fwdr in hostfwds[vmname]:
- # hport, gport = fwdr.split(':')
- # hostfwdstr += ',hostfwd=tcp::%s-:%s' % (hport, gport)
- #
vars_dict['hostfwdstr'] = host_fwd_str
command_str += 'qemu-system-x86_64 '
- # TODO non default images?
- command_str += '-kernel buildroot/bzImage ' \
+ # TODO manage non default images
+ command_str += '-kernel %(vmimgpath)s/bzImage ' \
'-append "console=ttyS0" ' \
- '-initrd %(vmimgpath)s ' % vars_dict
+ '-initrd %(vmimgpath)s/rootfs.cpio ' % vars_dict
command_str += '-nographic ' \
'-display none ' \
'--enable-kvm ' \
@@ -140,7 +134,7 @@ class Testbed(mod.Testbed):
'downscript=no%(vhost)s ' \
% {'mac': mac, 'tap': tap_id, 'idx': port['port_id'],
'frontend': vm_frontend,
- 'vhost': ',vhost=on' if vhost else ''}
+ 'vhost': ',vhost=on' if self.vhost else ''}
command_str += '&\n'
@@ -150,7 +144,48 @@ class Testbed(mod.Testbed):
booting_budget = boot_batch_size
vmid += 1
+ Popen([command_str], shell=True, executable="/bin/bash").wait() # TODO something more elegant maybe?
+ return command_str
+
+ def _make_down_script(self):
+ """
+ :rtype str
+ :return: The script to tear down the experiment
+ """
+ command_str = 'kill_qemu() {\n' \
+ ' PIDFILE=$1\n' \
+ ' PID=$(cat $PIDFILE)\n' \
+ ' if [ -n $PID ]; then\n' \
+ ' kill $PID\n' \
+ ' while [ -n "$(ps -p $PID -o comm=)" ]; do\n' \
+ ' sleep 1\n' \
+ ' done\n' \
+ ' fi\n' \
+ '\n' \
+ ' rm $PIDFILE\n' \
+ '}\n\n'
+
+ for vm_name, vm in self.vms.items():
+ command_str += 'kill_qemu rina-%(id)s.pid\n' % {'id': vm['id']}
+
+ command_str += '\n'
+
+ for vm_name, vm in self.vms.items():
+ for port in vm['ports']:
+ tap = port['tap_id']
+ shim = port['shim']
+
+ command_str += 'sudo brctl delif %(br)s %(tap)s\n' \
+ 'sudo ip link set %(tap)s down\n' \
+ 'sudo ip tuntap del mode tap name %(tap)s\n\n' \
+ % {'tap': tap, 'br': shim.name}
+
+ for shim in self.shims:
+ command_str += 'sudo ip link set %(br)s down\n' \
+ 'sudo brctl delbr %(br)s\n' \
+ '\n' % {'br': shim.name}
+ return command_str
def __del__(self):
- # TODO
- pass
+ script = self._make_down_script()
+ Popen([script], shell=True, executable="/bin/bash")