X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fnepi%2Futil%2Fparsers%2Fxml_parser.py;h=18b7a7daee2d0eaa36ccf27d09b0570dce4c69bd;hb=039fbd9629d7570d4c175a5448d24badcd0f3aba;hp=7dc00c0a88b8eec146ce598a84f9427b7169034e;hpb=561719f7cb8a42f139905c33e75ec5071c321170;p=nepi.git diff --git a/src/nepi/util/parsers/xml_parser.py b/src/nepi/util/parsers/xml_parser.py index 7dc00c0a..18b7a7da 100644 --- a/src/nepi/util/parsers/xml_parser.py +++ b/src/nepi/util/parsers/xml_parser.py @@ -3,9 +3,8 @@ # Copyright (C) 2013 INRIA # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation; # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,8 +16,14 @@ # # Author: Alina Quereilhac +from __future__ import print_function + +from nepi.util.netgraph import NetGraph, TopologyType +from nepi.util.timefuncs import stformat, tsformat + from xml.dom import minidom +import datetime import sys import os @@ -30,21 +35,22 @@ DOUBLE = "float" def xmlencode(s): if isinstance(s, str): rv = s.decode("latin1") + if isinstance(s, datetime.datetime): + rv = tsformat(s) elif not isinstance(s, unicode): rv = unicode(s) else: rv = s return rv.replace(u'\x00',u'�') -def xmldecode(s): - return s.replace(u'�',u'\x00').encode("utf8") +def xmldecode(s, cast = str): + ret = s.replace(u'�',u'\x00').encode("ascii") + ret = cast(ret) + if s == "None": + return None + return ret def from_type(value): - if value == None: - return str("None") - - if isinstance(value, str): - return STRING if isinstance(value, bool): return BOOL if isinstance(value, int): @@ -52,10 +58,13 @@ def from_type(value): if isinstance(value, float): return DOUBLE + return STRING + def to_type(type, value): + if not value: + return value + if type == STRING: - if value == "None": - return None return str(value) if type == BOOL: return value == "True" @@ -74,7 +83,7 @@ class ECXMLParser(object): try: xml = doc.toprettyxml(indent=" ", encoding="UTF-8") except: - print >>sys.stderr, "Oops: generating XML from %s" % (data,) + print("Oops: generating XML from %s" % (data,), file=sys.stderr) raise return xml @@ -84,14 +93,88 @@ class ECXMLParser(object): ecnode.setAttribute("exp_id", xmlencode(ec.exp_id)) ecnode.setAttribute("run_id", xmlencode(ec.run_id)) ecnode.setAttribute("nthreads", xmlencode(ec.nthreads)) + ecnode.setAttribute("local_dir", xmlencode(ec.local_dir)) doc.appendChild(ecnode) + if ec.netgraph != None: + self._netgraph_to_xml(doc, ecnode, ec) + + rmsnode = doc.createElement("rms") + ecnode.appendChild(rmsnode) + for guid, rm in ec._resources.iteritems(): - self._rm_to_xml(doc, ecnode, ec, guid, rm) + self._rm_to_xml(doc, rmsnode, ec, guid, rm) return doc - - def _rm_to_xml(self, doc, ecnode, ec, guid, rm): + + def _netgraph_to_xml(self, doc, ecnode, ec): + ngnode = doc.createElement("topology") + ngnode.setAttribute("topo-type", xmlencode(ec.netgraph.topo_type)) + ecnode.appendChild(ngnode) + + self. _netgraph_nodes_to_xml(doc, ngnode, ec) + self. _netgraph_edges_to_xml(doc, ngnode, ec) + + def _netgraph_nodes_to_xml(self, doc, ngnode, ec): + ngnsnode = doc.createElement("nodes") + ngnode.appendChild(ngnsnode) + + for nid in ec.netgraph.nodes(): + ngnnode = doc.createElement("node") + ngnnode.setAttribute("nid", xmlencode(nid)) + ngnnode.setAttribute("nid-type", from_type(nid)) + ngnsnode.appendChild(ngnnode) + + # Mark ources and targets + if ec.netgraph.is_source(nid): + ngnnode.setAttribute("source", xmlencode(True)) + + if ec.netgraph.is_target(nid): + ngnnode.setAttribute("target", xmlencode(True)) + + # Node annotations + annosnode = doc.createElement("node-annotations") + add_annotations = False + for name in ec.netgraph.node_annotations(nid): + add_annotations = True + value = ec.netgraph.node_annotation(nid, name) + annonode = doc.createElement("node-annotation") + annonode.setAttribute("name", xmlencode(name)) + annonode.setAttribute("value", xmlencode(value)) + annonode.setAttribute("type", from_type(value)) + annosnode.appendChild(annonode) + + if add_annotations: + ngnnode.appendChild(annosnode) + + def _netgraph_edges_to_xml(self, doc, ngnode, ec): + ngesnode = doc.createElement("edges") + ngnode.appendChild(ngesnode) + + for nid1, nid2 in ec.netgraph.edges(): + ngenode = doc.createElement("edge") + ngenode.setAttribute("nid1", xmlencode(nid1)) + ngenode.setAttribute("nid1-type", from_type(nid1)) + ngenode.setAttribute("nid2", xmlencode(nid2)) + ngenode.setAttribute("nid2-type", from_type(nid2)) + ngesnode.appendChild(ngenode) + + # Edge annotations + annosnode = doc.createElement("edge-annotations") + add_annotations = False + for name in ec.netgraph.edge_annotations(nid1, nid2): + add_annotations = True + value = ec.netgraph.edge_annotation(nid1, nid2, name) + annonode = doc.createElement("edge-annotation") + annonode.setAttribute("name", xmlencode(name)) + annonode.setAttribute("value", xmlencode(value)) + annonode.setAttribute("type", from_type(value)) + annosnode.appendChild(annonode) + + if add_annotations: + ngenode.appendChild(annosnode) + + def _rm_to_xml(self, doc, rmsnode, ec, guid, rm): rmnode = doc.createElement("rm") rmnode.setAttribute("guid", xmlencode(guid)) rmnode.setAttribute("rtype", xmlencode(rm._rtype)) @@ -110,7 +193,7 @@ class ECXMLParser(object): rmnode.setAttribute("release_time", xmlencode(rm._release_time)) if rm._failed_time: rmnode.setAttribute("failed_time", xmlencode(rm._failed_time)) - ecnode.appendChild(rmnode) + rmsnode.appendChild(rmnode) anode = doc.createElement("attributes") attributes = False @@ -145,7 +228,7 @@ class ECXMLParser(object): for action, conds in rm._conditions.iteritems(): conditions = True for (group, state, time) in conds: - cnnode = doc.createElement("condition") + ccnnode = doc.createElement("condition") ccnnode.setAttribute("action", xmlencode(action)) ccnnode.setAttribute("group", xmlencode(group)) ccnnode.setAttribute("state", xmlencode(state)) @@ -179,19 +262,36 @@ class ECXMLParser(object): ecnode_list = doc.getElementsByTagName("experiment") for ecnode in ecnode_list: if ecnode.nodeType == doc.ELEMENT_NODE: - exp_id = ecnode.getAttribute("exp_id") - run_id = ecnode.getAttribute("run_id") - nthreads = int(ecnode.getAttribute("nthreads")) - - os.environ["NEPI_NTHREADS"] = str(nthreads) - ec = ExperimentController(exp_id = exp_id) + exp_id = xmldecode(ecnode.getAttribute("exp_id")) + run_id = xmldecode(ecnode.getAttribute("run_id")) + local_dir = xmldecode(ecnode.getAttribute("local_dir")) + + # Configure number of preocessing threads + nthreads = xmldecode(ecnode.getAttribute("nthreads")) + os.environ["NEPI_NTHREADS"] = nthreads + + # Deserialize netgraph + topology = None + topo_type = None + + netgraph = self._netgraph_from_xml(doc, ecnode) + + if netgraph: + topo_type = netgraph.topo_type + topology = netgraph.topology + + # Instantiate EC + ec = ExperimentController(exp_id = exp_id, local_dir = local_dir, + topology = topology, topo_type = topo_type) connections = set() - rmnode_list = ecnode.getElementsByTagName("rm") - for rmnode in rmnode_list: - if rmnode.nodeType == doc.ELEMENT_NODE: - self._rm_from_xml(doc, rmnode, ec, connections) + rmsnode_list = ecnode.getElementsByTagName("rms") + if rmsnode_list: + rmnode_list = rmsnode_list[0].getElementsByTagName("rm") + for rmnode in rmnode_list: + if rmnode.nodeType == doc.ELEMENT_NODE: + self._rm_from_xml(doc, rmnode, ec, connections) for (guid1, guid2) in connections: ec.register_connection(guid1, guid2) @@ -200,6 +300,78 @@ class ECXMLParser(object): return ec + def _netgraph_from_xml(self, doc, ecnode): + netgraph = None + + topology = ecnode.getElementsByTagName("topology") + if topology: + topology = topology[0] + topo_type = xmldecode(topology.getAttribute("topo-type")) + + netgraph = NetGraph(topo_type = topo_type) + + ngnsnode_list = topology.getElementsByTagName("nodes") + if ngnsnode_list: + ngnsnode = ngnsnode_list[0].getElementsByTagName("node") + for ngnnode in ngnsnode: + nid = xmldecode(ngnnode.getAttribute("nid")) + tipe = xmldecode(ngnnode.getAttribute("nid-type")) + nid = to_type(tipe, nid) + netgraph.add_node(nid) + + if ngnnode.hasAttribute("source"): + netgraph.set_source(nid) + if ngnnode.hasAttribute("target"): + netgraph.set_target(nid) + + annosnode_list = ngnnode.getElementsByTagName("node-annotations") + + if annosnode_list: + annosnode = annosnode_list[0].getElementsByTagName("node-annotation") + for annonode in annosnode: + name = xmldecode(annonode.getAttribute("name")) + + if name == "ips": + ips = xmldecode(annonode.getAttribute("value"), eval) # list + for ip in ips: + netgraph.annotate_node_ip(nid, ip) + else: + value = xmldecode(annonode.getAttribute("value")) + tipe = xmldecode(annonode.getAttribute("type")) + value = to_type(tipe, value) + netgraph.annotate_node(nid, name, value) + + ngesnode_list = topology.getElementsByTagName("edges") + if ngesnode_list: + ngesnode = ngesnode_list[0].getElementsByTagName("edge") + for ngenode in ngesnode: + nid1 = xmldecode(ngenode.getAttribute("nid1")) + tipe1 = xmldecode(ngenode.getAttribute("nid1-type")) + nid1 = to_type(tipe1, nid1) + + nid2 = xmldecode(ngenode.getAttribute("nid2")) + tipe2 = xmldecode(ngenode.getAttribute("nid2-type")) + nid2 = to_type(tipe2, nid2) + + netgraph.add_edge(nid1, nid2) + + annosnode_list = ngenode.getElementsByTagName("edge-annotations") + if annosnode_list: + annosnode = annosnode_list[0].getElementsByTagName("edge-annotation") + for annonode in annosnode: + name = xmldecode(annonode.getAttribute("name")) + + if name == "net": + net = xmldecode(annonode.getAttribute("value"), eval) # dict + netgraph.annotate_edge_net(nid1, nid2, net[nid1], net[nid2], + net["mask"], net["network"], net["prefix"]) + else: + value = xmldecode(annonode.getAttribute("value")) + tipe = xmldecode(annonode.getAttribute("type")) + value = to_type(tipe, value) + netgraph.annotate_edge(nid1, nid2, name, value) + return netgraph + def _rm_from_xml(self, doc, rmnode, ec, connections): start_time = None stop_time = None @@ -209,24 +381,36 @@ class ECXMLParser(object): release_time = None failed_time = None - guid = int(rmnode.getAttribute("guid")) + guid = xmldecode(rmnode.getAttribute("guid"), int) rtype = xmldecode(rmnode.getAttribute("rtype")) - state = int(rmnode.getAttribute("state")) + + # FOR NOW ONLY STATE NEW IS ALLOWED + state = 0 + """ + state = xmldecode(rmnode.getAttribute("state"), int) if rmnode.hasAttribute("start_time"): - start_time = xmldecode(rmnode.getAttribute("start_time")) + start_time = xmldecode(rmnode.getAttribute("start_time"), + datetime.datetime) if rmnode.hasAttribute("stop_time"): - stop_time = xmldecode(rmnode.getAttribute("stop_time")) + stop_time = xmldecode(rmnode.getAttribute("stop_time"), + datetime.datetime) if rmnode.hasAttribute("discover_time"): - dicover_time = xmldecode(rmnode.getAttribute("discover_time")) + dicover_time = xmldecode(rmnode.getAttribute("discover_time"), + datetime.datetime) if rmnode.hasAttribute("provision_time"): - provision_time = xmldecode(rmnode.getAttribute("provision_time")) + provision_time = xmldecode(rmnode.getAttribute("provision_time"), + datetime.datetime) if rmnode.hasAttribute("ready_time"): - ready_time = xmldecode(rmnode.getAttribute("ready_time")) + ready_time = xmldecode(rmnode.getAttribute("ready_time"), + datetime.datetime) if rmnode.hasAttribute("release_time"): - release_time = xmldecode(rmnode.getAttribute("release_time")) + release_time = xmldecode(rmnode.getAttribute("release_time"), + datetime.datetime) if rmnode.hasAttribute("failed_time"): - failed_time = xmldecode(rmnode.getAttribute("failed_time")) + failed_time = xmldecode(rmnode.getAttribute("failed_time"), + datetime.datetime) + """ ec.register_resource(rtype, guid = guid) rm = ec.get_resource(guid) @@ -244,15 +428,15 @@ class ECXMLParser(object): for aanode in aanode_list: name = xmldecode(aanode.getAttribute("name")) value = xmldecode(aanode.getAttribute("value")) - type = xmldecode(aanode.getAttribute("type")) - value = to_type(type, value) + tipe = xmldecode(aanode.getAttribute("type")) + value = to_type(tipe, value) rm.set(name, value) cnode_list = rmnode.getElementsByTagName("connections") if cnode_list: ccnode_list = cnode_list[0].getElementsByTagName("connection") for ccnode in ccnode_list: - guid2 = int(ccnode.getAttribute("guid")) + guid2 = xmldecode(ccnode.getAttribute("guid"), int) connections.add((guid, guid2)) tnode_list = rmnode.getElementsByTagName("traces") @@ -266,9 +450,10 @@ class ECXMLParser(object): if cnnode_list: ccnnode_list = cnnode_list[0].getElementsByTagName("condition") for ccnnode in ccnnode_list: - action = int(ccnnode.getAttribute("action")) - group = int(ccnnode.getAttribute("group")) - state = int(ccnnode.getAttribute("state")) - time = ccnnode.getAttribute("time") + action = xmldecode(ccnnode.getAttribute("action"), int) + group = xmldecode(ccnnode.getAttribute("group"), eval) # list + state = xmldecode(ccnnode.getAttribute("state"), int) + time = xmldecode(ccnnode.getAttribute("time")) + time = to_type('STRING', time) ec.register_condition(guid, action, group, state, time = time)