diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | rumba/testbeds/qemu.py | 126 |
2 files changed, 128 insertions, 1 deletions
@@ -93,3 +93,6 @@ ENV/ *rspec *.pem + +# PyCharm metadata folder +.idea diff --git a/rumba/testbeds/qemu.py b/rumba/testbeds/qemu.py index 158f360..0a2126f 100644 --- a/rumba/testbeds/qemu.py +++ b/rumba/testbeds/qemu.py @@ -17,6 +17,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA +import multiprocessing import rumba.model as mod @@ -26,7 +27,130 @@ class Testbed(mod.Testbed): mod.Testbed.__init__(self, exp_name, username, password, proj_name) def create_experiment(self, experiment): - print("[QEMU testbed] experiment swapped in") + """ + :type experiment mod.Experiment + :param experiment: The experiment running + """ + 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 + command_str += 'sudo brctl addbr %(br)s\n' \ + 'sudo ip link set %(br)s up\n' \ + '\n' % {'br': shim} + 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': []}) + 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} + + 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} + + vm['ports'].append({'tap_id': tap_id, 'shim': shim, 'port_id': port_id}) + # TODO ask about IP address. Was there in demo. + + # Building vms + + boot_batch_size = max(1, multiprocessing.cpu_count() // 2) + booting_budget = boot_batch_size + boot_backoff = 12 + 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': []}) + fwdp = base_port + vmid + fwdc = fwdp + 10000 + mac = '00:0a:0a:0a:%02x:%02x' % (vmid, 99) + vm['ssh'] = fwdp + + vars_dict = {'fwdp': fwdp, 'id': vmid, 'mac': mac, + 'vmimgpath': 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 ' \ + '-append "console=ttyS0" ' \ + '-initrd %(vmimgpath)s ' % vars_dict + command_str += '-nographic ' \ + '-display none ' \ + '--enable-kvm ' \ + '-smp 1 ' \ + '-m %(memory)sM ' \ + '-device %(frontend)s,mac=%(mac)s,netdev=mgmt ' \ + '-netdev user,id=mgmt,%(hostfwdstr)s ' \ + '-vga std ' \ + '-pidfile rina-%(id)s.pid ' \ + '-serial file:%(vmname)s.log ' \ + % vars_dict + + del vars_dict + + for port in vm['ports']: + tap_id = port['tap_id'] + mac = '00:0a:0a:0a:%02x:%02x' % (vmid, port['port_id']) + port['mac'] = mac + + command_str += '-device %(frontend)s,mac=%(mac)s,netdev=data%(idx)s ' \ + '-netdev tap,ifname=%(tap)s,id=data%(idx)s,script=no,' \ + 'downscript=no%(vhost)s ' \ + % {'mac': mac, 'tap': tap_id, 'idx': port['port_id'], + 'frontend': vm_frontend, + 'vhost': ',vhost=on' if vhost else ''} + + command_str += '&\n' + + booting_budget -= 1 + if booting_budget <= 0: + command_str += 'sleep %s\n' % boot_backoff + booting_budget = boot_batch_size + + vmid += 1 def __del__(self): + # TODO pass |