diff options
-rw-r--r-- | rumba/testbeds/qemu.py | 115 |
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") |