aboutsummaryrefslogtreecommitdiff
path: root/rumba/prototypes/irati.py
diff options
context:
space:
mode:
authorMarco Capitani <m.capitani@nextworks.it>2017-04-11 13:08:30 +0200
committerMarco Capitani <m.capitani@nextworks.it>2017-04-11 13:08:30 +0200
commita7fbb7237f63c4c0d09cfd35c93fbe2e126bc471 (patch)
treea8838f0bfac8bd6854568b880443e031bb07600c /rumba/prototypes/irati.py
parent8797eff49aede4ad06ba668e4cee59accc12d1af (diff)
downloadrumba-a7fbb7237f63c4c0d09cfd35c93fbe2e126bc471.tar.gz
rumba-a7fbb7237f63c4c0d09cfd35c93fbe2e126bc471.zip
IRATI config file generation
Diffstat (limited to 'rumba/prototypes/irati.py')
-rw-r--r--rumba/prototypes/irati.py168
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)