diff options
author | Marco Capitani <m.capitani@nextworks.it> | 2017-04-11 13:08:30 +0200 |
---|---|---|
committer | Marco Capitani <m.capitani@nextworks.it> | 2017-04-11 13:08:30 +0200 |
commit | a7fbb7237f63c4c0d09cfd35c93fbe2e126bc471 (patch) | |
tree | a8838f0bfac8bd6854568b880443e031bb07600c /rumba/prototypes/irati.py | |
parent | 8797eff49aede4ad06ba668e4cee59accc12d1af (diff) | |
download | rumba-a7fbb7237f63c4c0d09cfd35c93fbe2e126bc471.tar.gz rumba-a7fbb7237f63c4c0d09cfd35c93fbe2e126bc471.zip |
IRATI config file generation
Diffstat (limited to 'rumba/prototypes/irati.py')
-rw-r--r-- | rumba/prototypes/irati.py | 168 |
1 files changed, 166 insertions, 2 deletions
diff --git a/rumba/prototypes/irati.py b/rumba/prototypes/irati.py index 37a6fbe..df963c5 100644 --- a/rumba/prototypes/irati.py +++ b/rumba/prototypes/irati.py @@ -17,14 +17,17 @@ # 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 copy +import json 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 class Experiment(mod.Experiment): - def __init__(self, testbed, nodes=None): - mod.Experiment.__init__(self, testbed, nodes) + def __init__(self, testbed, nodes=None, config_file=None): + mod.Experiment.__init__(self, testbed, nodes, config_file) def setup(self): cmds = list() @@ -46,3 +49,164 @@ class Experiment(mod.Experiment): print("Setting up IRATI on the nodes...") self.setup() print("[IRATI experiment] end") + + +class ConfBuilder(object): + + def __init__(self, experiment): + self.write_conf(experiment) + + @staticmethod + def write_conf(experiment): + """ + :type experiment: Experiment + :param experiment: the experiment to be configured + """ + ipcmconfs = dict() + + # 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... + app_mappings = [] + + # If some app directives were specified, use those to build da.map. + # Otherwise, assume the standard applications are to be mapped in + # the DIF with the highest rank. + if len(app_mappings) == 0: + if len(experiment.dif_ordering) > 0: + 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']) + # }) + + # TODO ask: I guess this will need to be added, and in that case we should add it to the qemu plugin too... + # Where should we take it in input? + manager = False + mgmt_dif_name = 'NMS' + + if manager: + # Add MAD/Manager configuration + irati_templates.ipcmconf_base["addons"] = { + "mad": { + "managerAppName": "", + "NMSDIFs": [{"DIF": "%s" % mgmt_dif_name}], + "managerConnections": [{ + "managerAppName": "manager-1--", + "DIF": "%s" % mgmt_dif_name + }] + } + } + + for node in experiment.nodes: # type: mod.Node + ipcmconfs[node.name] = copy.deepcopy(irati_templates.ipcmconf_base) + if manager: + ipcmconfs[node.name]["addons"]["mad"]["managerAppName"] = "%s.mad-1--" % (node.name) + + difconfs = dict() + ipcp2shim_map = {} # We will need it in a sec + for dif in experiment.dif_ordering: # type: mod.DIF + if isinstance(dif, mod.ShimEthDIF): + ipcp2shim_map.update({ipcp.name: dif for ipcp in dif.ipcps}) + elif isinstance(dif, mod.NormalDIF): + difconfs[dif.name] = dict() + for node in dif.members: + difconfs[dif.name][node.name] = copy.deepcopy(irati_templates.normal_dif_base) + + for node in experiment.nodes: # type: mod.Node + ipcmconf = ipcmconfs[node.name] + + for ipcp in node.ipcps: # type: mod.ShimEthIPCP + if isinstance(ipcp, mod.ShimEthIPCP): + node_name, port_id = ipcp.ifname.split('.') + shim = ipcp2shim_map[ipcp.name] # type: mod.ShimEthDIF + ipcmconf["ipcProcessesToCreate"].append({ + "apName": "eth.%d.IPCP" % int(port_id), + "apInstance": "1", + "difName": shim.name + }) + + template_file_name = 'shimeth.%s.%s.dif' % (node_name, shim.name) + ipcmconf["difConfigurations"].append({ + "name": shim.name, + "template": template_file_name + }) + + fout = open(template_file_name, 'w') + fout.write(json.dumps({"difType": "shim-eth-vlan", + "configParameters": { + "interface-name": "ifc%d" % (int(port_id),) + } + }, + indent=4, sort_keys=True)) + fout.close() + + # Run over dif_ordering array, to make sure each IPCM config has + # the correct ordering for the ipcProcessesToCreate list of operations. + # If we iterated over the difs map, the order would be randomic, and so + # some IPCP registrations in lower DIFs may fail. This would happen because + # at the moment of registration, it may be that the IPCP of the lower DIF + # has not been created yet. + shims = ipcp2shim_map.values() + for dif in experiment.dif_ordering: # type: mod.NormalDIF + + if dif in shims: + # Shims are managed separately, in the previous loop + continue + + for node in dif.members: # type: mod.Node + node_name = node.name + node_id = int(node.full_name.split(':')[1]) - 2222 + ipcmconf = ipcmconfs[node_name] + + # TODO ask: here was vm['id']. Does the name work or does it have to be the id (sequential from 1)? + normal_ipcp = {"apName": "%s.%s.IPCP" % (dif.name, node_name), + "apInstance": "1", + "difName": "%s" % (dif.name,), + "difsToRegisterAt": []} + + for lower_dif in node.dif_registrations[dif]: # type: mod.DIF + normal_ipcp["difsToRegisterAt"].append(lower_dif.name) + + ipcmconf["ipcProcessesToCreate"].append(normal_ipcp) + + ipcmconf["difConfigurations"].append({ + "name": "%s" % (dif.name,), + "template": "normal.%s.%s.dif" % (node_name, dif.name,) + }) + + # Fill in the map of IPCP addresses. This could be moved at difconfs + # deepcopy-time + # TODO what to do for id? Get it from full_name (i.e.: address:port)? Ugly, but might work + for other_node in dif.members: # type: mod.Node + difconfs[dif.name][other_node.name]["knownIPCProcessAddresses"].append({ + "apName": "%s.%s.IPCP" % (dif.name, node_name), + "apInstance": "1", + "address": 16 + node_id + }) + 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)? With what syntax? + irati_templates.translate_policy(difconfs[dif.name][node_name], path, + ps, parms=[]) + # TODO: what is the syntax for the policy parameters? + + # Dump the DIF Allocator map + with open('da.map', 'w') as da_map_file: + json.dump(irati_templates.da_map_base, da_map_file, indent=4, sort_keys=True) + + for node in experiment.nodes: + # Dump the IPCM configuration files + with open('%s.ipcm.conf' % (node.name,), 'w') as node_file: + json.dump(ipcmconfs[node.name], node_file, indent=4, sort_keys=True) + + for dif in experiment.dif_ordering: # type: mod.DIF + dif_conf = difconfs.get(dif.name, None) + if dif_conf: + # Dump the normal DIF configuration files + for node in dif.members: + with open('normal.%s.%s.dif' % (node.name, dif.name), 'w') as dif_conf_file: + json.dump(dif_conf[node.name], dif_conf_file, indent=4, sort_keys=True) |