aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSander Vrijders <sander.vrijders@ugent.be>2017-09-13 11:26:53 +0200
committerSander Vrijders <sander.vrijders@ugent.be>2017-09-13 17:18:56 +0200
commit440ab00aa57dd8c7c0076d93011814b7fb25ec76 (patch)
tree3f65d7b4866c4cc6de68929d254fd04c8adb52e7
parente7a0deed26ec4015e783742da0796a77c589ce55 (diff)
downloadrumba-440ab00aa57dd8c7c0076d93011814b7fb25ec76.tar.gz
rumba-440ab00aa57dd8c7c0076d93011814b7fb25ec76.zip
build: Add continuous integration
This adds CI to Rumba.
-rw-r--r--.gitlab-ci.yml9
-rwxr-xr-x[-rw-r--r--]examples/mouse.py16
-rwxr-xr-xexamples/vpn.py56
-rw-r--r--rumba/model.py6
-rw-r--r--rumba/ssh_support.py47
-rw-r--r--rumba/testbeds/jfed.py10
-rw-r--r--rumba/testbeds/qemu.py54
-rwxr-xr-xsetup.py22
8 files changed, 162 insertions, 58 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..10bf999
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,9 @@
+before_script:
+ - apt-get update -qy
+ - apt-get install -y python-dev python-pip bridge-utils qemu
+ - pip install setuptools --upgrade
+ - python setup.py install
+
+irati-test:
+ script:
+ - python examples/vpn.py \ No newline at end of file
diff --git a/examples/mouse.py b/examples/mouse.py
index 25e2487..5ff5c6a 100644..100755
--- a/examples/mouse.py
+++ b/examples/mouse.py
@@ -15,6 +15,10 @@ import rumba.prototypes.ouroboros as our
import rumba.prototypes.rlite as rl
import rumba.prototypes.irati as irati
+
+log.set_logging_level('DEBUG')
+
+
n01 = NormalDIF("n01")
e01 = ShimEthDIF("e01")
@@ -92,14 +96,14 @@ n = Node("n",
difs = [n01, e17],
dif_registrations = {n01 : [e17]})
-tb = jfed.Testbed(exp_name = "mouse2",
- cert_file = "/home/sander/cert.pem",
- username = "sander")
+tb = qemu.Testbed(exp_name = "mouse2")
exp = rl.Experiment(tb, nodes = [a, b, c, d, e, f, g, h, i, j, k, l, m, n])
print(exp)
-exp.swap_in()
-exp.install_prototype()
-exp.bootstrap_prototype()
+try:
+ exp.swap_in()
+ exp.bootstrap_prototype()
+finally:
+ exp.swap_out()
diff --git a/examples/vpn.py b/examples/vpn.py
new file mode 100755
index 0000000..4ad9f6d
--- /dev/null
+++ b/examples/vpn.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+
+# An example script using the rumba package
+
+from rumba.model import *
+
+# import testbed plugins
+import rumba.testbeds.emulab as emulab
+import rumba.testbeds.jfed as jfed
+import rumba.testbeds.faketestbed as fake
+import rumba.testbeds.qemu as qemu
+
+# import prototype plugins
+import rumba.prototypes.ouroboros as our
+import rumba.prototypes.rlite as rl
+import rumba.prototypes.irati as irati
+
+import rumba.log as log
+
+log.set_logging_level('DEBUG')
+
+
+n1 = NormalDIF("n1")
+n2 = NormalDIF("n2")
+e1 = ShimEthDIF("e1")
+e2 = ShimEthDIF("e2")
+e3 = ShimEthDIF("e3")
+
+a = Node("a",
+ difs = [e1, n1, n2],
+ dif_registrations = {n1 : [e1], n2 : [n1]})
+
+b = Node("b",
+ difs = [e1, e2, n1],
+ dif_registrations = {n1 : [e1, e2]})
+
+c = Node("c",
+ difs = [e2, e3, n1],
+ dif_registrations = {n1 : [e2, e3]})
+
+d = Node("d",
+ difs = [e3, n1, n2],
+ dif_registrations = {n1 : [e3], n2 : [n1]})
+
+tb = qemu.Testbed(exp_name = 'example1',
+ username = 'sander')
+
+exp = our.Experiment(tb, nodes = [a, b, c, d])
+
+print(exp)
+
+#try:
+# exp.swap_in()
+# exp.bootstrap_prototype()
+#finally:
+# exp.swap_out()
diff --git a/rumba/model.py b/rumba/model.py
index 6303799..06d45ec 100644
--- a/rumba/model.py
+++ b/rumba/model.py
@@ -55,6 +55,12 @@ except OSError:
# Already there, nothing to do
pass
+cache_parent_dir = os.path.join(os.path.expanduser("~"), '.cache/')
+try:
+ os.mkdir(cache_parent_dir)
+except OSError:
+ # Already there, nothing to do
+ pass
cache_dir = os.path.join(os.path.expanduser("~"), '.cache/rumba/')
try:
os.mkdir(cache_dir)
diff --git a/rumba/ssh_support.py b/rumba/ssh_support.py
index 9261ce0..dfa290a 100644
--- a/rumba/ssh_support.py
+++ b/rumba/ssh_support.py
@@ -32,6 +32,9 @@ import rumba.log as log
logger = log.get_logger(__name__)
+class SSHException(Exception):
+ pass
+
def get_ssh_client():
ssh_client = paramiko.SSHClient()
ssh_client.load_system_host_keys()
@@ -118,23 +121,29 @@ def execute_commands(testbed, ssh_config, commands, time_out=3):
testbed.username, testbed.password,
look_for_keys=True, timeout=time_out,
sock=proxy)
- o = ""
- for command in commands:
- logger.debug("%s@%s:%s >> %s" % (testbed.username,
- ssh_config.hostname,
- ssh_config.port,
- command))
- envars = '. /etc/profile;'
- command = envars + ' ' + command
- stdin, stdout, stderr = ssh_client.exec_command(command)
- o = _print_stream(stdout)
- _print_stream(stderr)
- ssh_client.close()
- return o
+ except paramiko.ssh_exception.SSHException as e:
+ raise SSHException('Failed to connect to host')
- except Exception as e:
- logger.error(str(e))
- return
+ o = ""
+ for command in commands:
+ logger.debug("%s@%s:%s >> %s" % (testbed.username,
+ ssh_config.hostname,
+ ssh_config.port,
+ command))
+ envars = '. /etc/profile;'
+ command = envars + ' ' + command
+ chan = ssh_client.get_transport().open_session()
+ stdout = chan.makefile()
+ try:
+ chan.exec_command(command)
+ except paramiko.ssh_exception.SSHException as e:
+ raise SSHException('Failed to execute command')
+ if (chan.recv_exit_status() != 0):
+ raise SSHException('A remote command returned an error')
+ o = _print_stream(stdout)
+
+ ssh_client.close()
+ return o
def execute_command(testbed, ssh_config, command, time_out=3):
@@ -195,8 +204,8 @@ def write_text_to_file(testbed, ssh_config, text, file_name):
remote_file.write(text)
remote_file.close()
- except Exception as e:
- logger.error(str(e))
+ except SSHException as e:
+ raise SSHException('Failed to write text to remote file')
def copy_files_to_testbed(testbed, ssh_config, paths, destination):
@@ -239,7 +248,7 @@ def copy_files_to_testbed(testbed, ssh_config, paths, destination):
sftp_client.put(path, dest_file)
except Exception as e:
- logger.error(str(e))
+ raise SSHException('Failed to copy files to testbed')
def copy_file_to_testbed(testbed, ssh_config, path, destination):
diff --git a/rumba/testbeds/jfed.py b/rumba/testbeds/jfed.py
index c541037..d938179 100644
--- a/rumba/testbeds/jfed.py
+++ b/rumba/testbeds/jfed.py
@@ -27,10 +27,14 @@ import subprocess
import getpass
import xml.dom.minidom as xml
import os.path
-
import time
-import wget
import tarfile
+import sys
+
+if sys.version_info[0] >= 3:
+ from urllib.request import urlretrieve
+else:
+ from urllib import urlretrieve
import rumba.model as mod
import rumba.log as log
@@ -70,7 +74,7 @@ class Testbed(mod.Testbed):
logger.info("Couldn't find jFed CLI. Downloading.")
tarball = "jfed_cli.tar.gz"
url = "http://jfed.iminds.be/downloads/stable/jar/" + tarball
- wget.download(url)
+ urlretrieve(url, filename=tarball)
tar = tarfile.open(tarball)
tar.extractall()
tar.close()
diff --git a/rumba/testbeds/qemu.py b/rumba/testbeds/qemu.py
index 47f4670..80a3d4c 100644
--- a/rumba/testbeds/qemu.py
+++ b/rumba/testbeds/qemu.py
@@ -27,11 +27,16 @@ import multiprocessing
import time
import subprocess
import os
+import sys
+
+if sys.version_info[0] >= 3:
+ from urllib.request import urlretrieve
+else:
+ from urllib import urlretrieve
import rumba.model as mod
import rumba.log as log
import rumba.ssh_support as ssh_support
-import wget
logger = log.get_logger(__name__)
@@ -48,6 +53,12 @@ class Testbed(mod.Testbed):
self.bzimage_path = bzimage_path
self.initramfs_path = initramfs_path
+ # Prepend sudo to all commands if the user is not 'root'
+ def may_sudo(self, cmds):
+ if os.geteuid() != 0:
+ for i in range(len(cmds)):
+ cmds[i] = "sudo %s" % cmds[i]
+
@staticmethod
def _run_command_chain(commands, results_queue,
error_queue, ignore_errors=False):
@@ -72,7 +83,7 @@ class Testbed(mod.Testbed):
logger.debug('executing >> %s', command)
try:
subprocess.check_call(command.split())
- except subprocess.CalledProcessError as e:
+ except (subprocess.CalledProcessError, IOError) as e:
error_queue.put(str(e))
errors += 1
if not ignore_errors:
@@ -134,14 +145,16 @@ class Testbed(mod.Testbed):
self.bzimage_path = os.path.join(mod.cache_dir, bzimage)
if not os.path.exists(self.bzimage_path):
logger.info("Downloading %s" % (url_prefix + bzimage))
- wget.download(url_prefix + bzimage, out=self.bzimage_path)
+ urlretrieve(url_prefix + bzimage,
+ filename=self.bzimage_path)
print("\n")
if not self.initramfs_path:
initramfs = '%s.rootfs.cpio' % (experiment.prototype_name())
self.initramfs_path = os.path.join(mod.cache_dir, initramfs)
if not os.path.exists(self.initramfs_path):
logger.info("Downloading %s" % (url_prefix + initramfs))
- wget.download(url_prefix + initramfs, out=self.initramfs_path)
+ urlretrieve(url_prefix + initramfs,
+ filename=self.initramfs_path)
print("\n")
logger.info('Setting up interfaces.')
@@ -157,8 +170,8 @@ class Testbed(mod.Testbed):
self.shims.append(shim)
ipcps = shim.ipcps
command_list = []
- command_list += ('sudo brctl addbr %(br)s\n'
- 'sudo ip link set dev %(br)s up'
+ command_list += ('brctl addbr %(br)s\n'
+ 'ip link set dev %(br)s up'
% {'br': shim.name}
).split('\n')
for node in shim.members: # type:mod.Node
@@ -167,9 +180,9 @@ class Testbed(mod.Testbed):
port_id = len(vm['ports']) + 1
tap_id = '%s.%02x' % (name, port_id)
- command_list += ('sudo ip tuntap add mode tap name %(tap)s\n'
- 'sudo ip link set dev %(tap)s up\n'
- 'sudo brctl addif %(br)s %(tap)s'
+ command_list += ('ip tuntap add mode tap name %(tap)s\n'
+ 'ip link set dev %(tap)s up\n'
+ 'brctl addif %(br)s %(tap)s'
% {'tap': tap_id, 'br': shim.name}
).split('\n')
@@ -178,11 +191,11 @@ class Testbed(mod.Testbed):
# Rate limit the traffic transmitted on the TAP interface
command_list += (
- 'sudo tc qdisc add dev %(tap)s handle 1: root '
+ 'tc qdisc add dev %(tap)s handle 1: root '
'htb default 11\n'
- 'sudo tc class add dev %(tap)s parent 1: classid '
+ '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 '
+ 'tc class add dev %(tap)s parent 1:1 classid '
'1:11 htb rate %(speed)s'
% {'tap': tap_id, 'speed': speed}
).split('\n')
@@ -206,6 +219,7 @@ class Testbed(mod.Testbed):
if not e_queue.empty():
break
# Launch commands asynchronously
+ self.may_sudo(command_list)
process = multiprocessing.Process(target=self._run_command_chain,
args=(command_list,
r_queue,
@@ -283,9 +297,10 @@ class Testbed(mod.Testbed):
'-append "console=ttyS0" '
'-initrd %(initramfs)s '
% vars_dict)
+ if os.path.exists('/dev/kvm'):
+ command += '--enable-kvm '
command += ('-vga std '
'-display none '
- '--enable-kvm '
'-smp 1 '
'-m %(memory)sM '
'-device %(frontend)s,mac=%(mac)s,netdev=mgmt '
@@ -367,12 +382,12 @@ class Testbed(mod.Testbed):
shim = port['shim']
commands = []
-
- commands += ('sudo brctl delif %(br)s %(tap)s\n'
- 'sudo ip link set dev %(tap)s down\n'
- 'sudo ip tuntap del mode tap name %(tap)s'
+ commands += ('brctl delif %(br)s %(tap)s\n'
+ 'ip link set dev %(tap)s down\n'
+ 'ip tuntap del mode tap name %(tap)s'
% {'tap': tap, 'br': shim.name}
).split('\n')
+ self.may_sudo(commands)
process = multiprocessing.Process(
target=self._run_command_chain,
args=(commands, results_queue, error_queue),
@@ -407,10 +422,11 @@ class Testbed(mod.Testbed):
for shim in self.shims:
commands = []
- commands += ('sudo ip link set dev %(br)s down\n'
- 'sudo brctl delbr %(br)s'
+ commands += ('ip link set dev %(br)s down\n'
+ 'brctl delbr %(br)s'
% {'br': shim.name}
).split('\n')
+ self.may_sudo(commands)
process = multiprocessing.Process(target=self._run_command_chain,
args=(commands,
results_queue,
diff --git a/setup.py b/setup.py
index 2648f89..02e5aef 100755
--- a/setup.py
+++ b/setup.py
@@ -4,16 +4,16 @@ import setuptools
setuptools.setup(
- name="Rumba",
- version="0.4",
- url="https://gitlab.com/arcfire/rumba",
- keywords="rina measurement testbed",
- author="Sander Vrijders",
- author_email="sander.vrijders@intec.ugent.be",
- license="LGPL",
- description="Rumba measurement framework for RINA",
- packages=["rumba", "rumba.testbeds", "rumba.prototypes"],
- install_requires=["paramiko", "wget", 'repoze.lru; python_version<"3.2"'],
- extras_require={"NumpyAcceleration": ["numpy"]},
+ name='Rumba',
+ version='0.4',
+ url='https://gitlab.com/arcfire/rumba',
+ keywords='rina measurement testbed',
+ author='Sander Vrijders',
+ author_email='sander.vrijders@ugent.be',
+ license='LGPL',
+ description='Rumba measurement framework for RINA',
+ packages=['rumba', 'rumba.testbeds', 'rumba.prototypes'],
+ install_requires=['paramiko', 'repoze.lru; python_version<"3.2"'],
+ extras_require={'NumpyAcceleration': ['numpy']},
scripts=['tools/rumba-access']
)