aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Capitani <[email protected]>2017-03-30 15:27:10 +0200
committerMarco Capitani <[email protected]>2017-03-30 15:27:10 +0200
commitdf352f052244362fdb035be7a5d6a2cc44c06f1c (patch)
tree5d931a37e62bf93a7379f07046ecc0a2216790d0
parente4406285047631caabbb50082d6e4fcafe27697e (diff)
downloadrumba-df352f052244362fdb035be7a5d6a2cc44c06f1c.tar.gz
rumba-df352f052244362fdb035be7a5d6a2cc44c06f1c.zip
qemu testbed first draft
-rw-r--r--.gitignore3
-rw-r--r--rumba/testbeds/qemu.py126
2 files changed, 128 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 146de1b..dc1959d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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