diff options
author | Marco Capitani <m.capitani@nextworks.it> | 2017-04-13 10:32:10 +0200 |
---|---|---|
committer | Marco Capitani <m.capitani@nextworks.it> | 2017-04-13 10:32:10 +0200 |
commit | af692809383b55ec3b9d7cb96e50b553ffbcd496 (patch) | |
tree | cf32ed1a1e046cc9c98fb8c5c46140a6d4ceb4d3 | |
parent | c83ea6f4b791cd85cd248b039b353c522f2f1f3e (diff) | |
download | rumba-af692809383b55ec3b9d7cb96e50b553ffbcd496.tar.gz rumba-af692809383b55ec3b9d7cb96e50b553ffbcd496.zip |
IRATI prototype: bootstrap_network method. Now complete & to be tested.
-rw-r--r-- | rumba/prototypes/irati.py | 147 | ||||
-rw-r--r-- | rumba/testbeds/qemu.py | 5 |
2 files changed, 132 insertions, 20 deletions
diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index e06610d..ba8a152 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -21,16 +21,38 @@ import copy import json +import subprocess + import rumba.ssh_support as ssh import rumba.model as mod import rumba.prototypes.irati_templates as irati_templates + # An experiment over the IRATI implementation +from rumba import ssh_support + + class Experiment(mod.Experiment): + + @staticmethod + def real_sudo(s): + return 'sudo ' + s + + @staticmethod + def fake_sudo(s): + return s + def __init__(self, testbed, nodes=None): mod.Experiment.__init__(self, testbed, nodes) + self.manager = False + + if self.testbed.username == 'root': + self.sudo = self.fake_sudo + else: + self.sudo = self.real_sudo def setup(self): + """Installs IRATI on the vms.""" cmds = list() cmds.append("sudo apt-get update") @@ -45,36 +67,129 @@ class Experiment(mod.Experiment): ssh.execute_commands(self.testbed, node.ssh_config, cmds, time_out=None) + def bootstrap_network(self): + """Creates the network by enrolling and configuring the nodes""" + for node in self.nodes: + self.process_node(node) + self.enroll_nodes() + def run_prototype(self): print("[IRATI experiment] start") print("Setting up IRATI on the nodes...") self.setup() print("[IRATI experiment] end") + def process_node(self, node): + """ + Installs the configuration and boots up rina on a node + :type node: mod.Node + :param node: + :return: + """ + name = node.name + gen_files_conf = 'shimeth.%(name)s.*.dif da.map %(name)s.ipcm.conf' % { + 'name': name} + if any(name in dif.members for dif in self.dif_ordering): + gen_files_conf = ' '.join( + [gen_files_conf, 'normal.%(name)s.*.dif' % {'name': name}]) + gen_files_bin = 'enroll.py' + + ipcm_components = ['scripting', 'console'] + if self.manager: + ipcm_components.append('mad') + ipcm_components = ', '.join(ipcm_components) + + gen_files = ' '.join([gen_files_conf, gen_files_bin]) + + sshopts = ('-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' + ' -o IdentityFile=buildroot/irati_rsa') + format_args = {'name': name, + 'ssh': node.ssh_config.port, + 'username': self.testbed.username, + 'genfiles': gen_files, + 'genfilesconf': gen_files_conf, + 'genfilesbin': gen_files_bin, + 'sshopts': sshopts, + 'installpath': '/usr', + 'verb': 'DBG', + 'ipcmcomps': ipcm_components} + try: + subprocess.check_call(('scp %(sshopts)s -r -P %(ssh)s ' + '%(genfiles)s %(username)s@localhost:' + % format_args).split()) + except subprocess.CalledProcessError as e: + raise Exception(str(e)) + + # TODO: review ssh opts through ssh support + + cmds = [self.sudo('hostname %(name)s' % format_args), + self.sudo('chmd a+rw /dev/irati'), + self.sudo('mv %(genfilesconf)s /etc' % format_args), + self.sudo('mv %(genfilesbin)s /usr/bin') % format_args] + + # TODO: is the port up on the VM at this point? + + cmds += [self.sudo('modprobe rina-default-plugin'), + self.sudo('%(installpath)s/bin/ipcm -a \"%(ipcmcomps)s\" ' + '-c /etc/%(name)s.ipcm.conf -l %(verb)s &> log &' + % format_args)] + + ssh_support.execute_commands(self.testbed, node.ssh_config, cmds) + + def enroll_nodes(self): + """Runs the enrollments one by one, respecting dependencies""" + for enrollment_list in self.enrollments: + for e in enrollment_list: + print( + 'I am going to enroll %s to DIF %s against neighbor %s,' + ' through lower DIF %s' + % (e['enrollee'], + e['dif'].name, + e['enroller'], + e['lower_dif'].name)) + + subprocess.check_call('sleep 2'. split()) # Important! + + e_args = {'ldif': e['lower_dif'].name, + 'dif': e['dif'].name, + 'name': e['enrollee'].name, + 'o_name': e['enroller'].name} + + cmd = self.sudo('enroll.py --lower-dif %(ldif)s --dif %(dif)s ' + '--ipcm-conf /etc/%(name)s.ipcm.conf ' + '--enrollee-name %(dif)s.%(name)s.IPCP ' + '--enroller-name %(dif)s.%(o_name)s.IPCP' + % e_args) + ssh_support.execute_command(self.testbed, + e['enrollee'].ssh_config, + cmd) + class ConfBuilder(object): - def __init__(self, experiment): - self.write_conf(experiment) + def __init__(self, experiment, manager): + self.write_conf(experiment, manager) @staticmethod - def write_conf(experiment): + def write_conf(experiment, manager): """ :type experiment: Experiment :param experiment: the experiment to be configured + :param manager: boolean indicating if a manager is requested """ # Constants and initializations ipcmconfs = dict() difconfs = dict() ipcp2shim_map = {} node2id_map = {} - manager = False mgmt_dif_name = 'NMS' - # TODO ask: what are these, and how are they represented in experiment? - # Are these bindings or registration (in node)? - # In gen.py these are given on a per-dif basis... + # TODO: what format are the mappings registered in? Is this ok? app_mappings = [] + for node in experiment.nodes: + app_mappings += [{'name': app, 'dif': dif.name} + for app in node.registrations + for dif in node.registrations[app]] # If some app directives were specified, use those to build da.map. # Otherwise, assume the standard applications are to be mapped in @@ -84,14 +199,13 @@ class ConfBuilder(object): for adm in \ irati_templates.da_map_base["applicationToDIFMappings"]: adm["difName"] = "%s" % (experiment.dif_ordering[-1],) - # else: - # irati_templates.da_map_base["applicationToDIFMappings"] = [] - # for apm in app_mappings: - # irati_templates.da_map_base["applicationToDIFMappings"]\ - # .append({ - # "encodedAppName": apm['name'], - # "difName": "%s.DIF" % (apm['dif']) - # }) + else: + irati_templates.da_map_base["applicationToDIFMappings"] = [] + for apm in app_mappings: + irati_templates.da_map_base["applicationToDIFMappings"]\ + .append({"encodedAppName": apm['name'], + "difName": "%s" % (apm['dif']) + }) # TODO ask: I guess this will need to be added, # and in that case we should add it to the qemu plugin too... @@ -201,8 +315,7 @@ class ConfBuilder(object): "address": 16 + node2id_map[node_name]}) for path, ps in dif.policies.items(): # if policy['nodes'] == [] or vmname in policy['nodes']: - # TODO: policies can be applied per-node - # (and not just per-dif) in rumba? With what syntax? + # TODO: manage per-node-policies irati_templates.translate_policy( difconfs[dif.name][node_name], path, ps, parms=[]) diff --git a/rumba/testbeds/qemu.py b/rumba/testbeds/qemu.py index 7255b3c..da3c7b9 100644 --- a/rumba/testbeds/qemu.py +++ b/rumba/testbeds/qemu.py @@ -180,9 +180,9 @@ class Testbed(mod.Testbed): boot_batch_size = max(1, multiprocessing.cpu_count() // 2) booting_budget = boot_batch_size - boot_backoff = 12 # in seconds + boot_backoff = 12 # in seconds base_port = 2222 - vm_memory = 164 # in megabytes + vm_memory = 164 # in megabytes vm_frontend = 'virtio-net-pci' vmid = 1 @@ -266,7 +266,6 @@ class Testbed(mod.Testbed): print('Sleeping %s secs waiting for the last VMs to boot' % tsleep) time.sleep(tsleep) - def swap_out(self, experiment): """ :rtype str |