7dc00c0a88b8eec146ce598a84f9427b7169034e
[nepi.git] / src / nepi / util / parsers / xml_parser.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
5 #    This program is free software: you can redistribute it and/or modify
6 #    it under the terms of the GNU General Public License as published by
7 #    the Free Software Foundation, either version 3 of the License, or
8 #    (at your option) any later version.
9 #
10 #    This program is distributed in the hope that it will be useful,
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #    GNU General Public License for more details.
14 #
15 #    You should have received a copy of the GNU General Public License
16 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19
20 from xml.dom import minidom
21
22 import sys
23 import os
24
25 STRING = "string"
26 BOOL = "bool"
27 INTEGER = "integer"
28 DOUBLE = "float"
29
30 def xmlencode(s):
31     if isinstance(s, str):
32         rv = s.decode("latin1")
33     elif not isinstance(s, unicode):
34         rv = unicode(s)
35     else:
36         rv = s
37     return rv.replace(u'\x00',u'&#0000;')
38
39 def xmldecode(s):
40     return s.replace(u'&#0000',u'\x00').encode("utf8")
41
42 def from_type(value):
43     if value == None:
44         return str("None")
45
46     if isinstance(value, str):
47         return STRING
48     if isinstance(value, bool):
49         return BOOL
50     if isinstance(value, int):
51         return INTEGER
52     if isinstance(value, float):
53         return DOUBLE
54
55 def to_type(type, value):
56     if type == STRING:
57         if value == "None":
58             return None
59         return str(value)
60     if type == BOOL:
61         return value == "True"
62     if type == INTEGER:
63         return int(value)
64     if type == DOUBLE:
65         return float(value)
66
67 class ECXMLParser(object):
68     def to_xml(self, ec):
69         
70         doc = minidom.Document()
71         
72         self._ec_to_xml(doc, ec)
73        
74         try:
75             xml = doc.toprettyxml(indent="    ", encoding="UTF-8")
76         except:
77             print >>sys.stderr, "Oops: generating XML from %s" % (data,)
78             raise
79         
80         return xml
81
82     def _ec_to_xml(self, doc, ec):
83         ecnode = doc.createElement("experiment")
84         ecnode.setAttribute("exp_id", xmlencode(ec.exp_id))
85         ecnode.setAttribute("run_id", xmlencode(ec.run_id))
86         ecnode.setAttribute("nthreads", xmlencode(ec.nthreads))
87         doc.appendChild(ecnode)
88
89         for guid, rm in ec._resources.iteritems():
90             self._rm_to_xml(doc, ecnode, ec, guid, rm)
91
92         return doc
93
94     def _rm_to_xml(self, doc, ecnode, ec, guid, rm):
95         rmnode = doc.createElement("rm")
96         rmnode.setAttribute("guid", xmlencode(guid))
97         rmnode.setAttribute("rtype", xmlencode(rm._rtype))
98         rmnode.setAttribute("state", xmlencode(rm._state))
99         if rm._start_time:
100             rmnode.setAttribute("start_time", xmlencode(rm._start_time))
101         if rm._stop_time:
102             rmnode.setAttribute("stop_time", xmlencode(rm._stop_time))
103         if rm._discover_time:
104             rmnode.setAttribute("discover_time", xmlencode(rm._discover_time))
105         if rm._provision_time:    
106             rmnode.setAttribute("provision_time", xmlencode(rm._provision_time))
107         if rm._ready_time:
108             rmnode.setAttribute("ready_time", xmlencode(rm._ready_time))
109         if rm._release_time:
110             rmnode.setAttribute("release_time", xmlencode(rm._release_time))
111         if rm._failed_time:
112             rmnode.setAttribute("failed_time", xmlencode(rm._failed_time))
113         ecnode.appendChild(rmnode)
114
115         anode = doc.createElement("attributes")
116         attributes = False
117
118         for attr in rm._attrs.values():
119             if attr.has_changed:
120                 attributes = True
121                 aanode = doc.createElement("attribute")
122                 aanode.setAttribute("name", xmlencode(attr.name))
123                 aanode.setAttribute("value", xmlencode(attr.value))
124                 aanode.setAttribute("type", from_type(attr.value))
125                 anode.appendChild(aanode)
126     
127         if attributes: 
128             rmnode.appendChild(anode)
129
130         cnode = doc.createElement("connections")
131         connections = False
132         
133         for guid in rm._connections:
134             connections = True
135             ccnode = doc.createElement("connection")
136             ccnode.setAttribute("guid", xmlencode(guid))
137             cnode.appendChild(ccnode)
138         
139         if connections:
140            rmnode.appendChild(cnode)
141
142         cnnode = doc.createElement("conditions")
143         conditions = False
144
145         for action, conds in rm._conditions.iteritems():
146             conditions = True
147             for (group, state, time) in conds:
148                 cnnode = doc.createElement("condition")
149                 ccnnode.setAttribute("action", xmlencode(action))
150                 ccnnode.setAttribute("group", xmlencode(group))
151                 ccnnode.setAttribute("state", xmlencode(state))
152                 ccnnode.setAttribute("time", xmlencode(time))
153                 cnnode.appendChild(ccnnode)
154         
155         if conditions:
156            rmnode.appendChild(cnnode)
157
158         tnode = doc.createElement("traces")
159         traces = False
160
161         for trace in rm._trcs.values():
162             if trace.enabled:
163                 traces = True
164                 ttnode = doc.createElement("trace")
165                 ttnode.setAttribute("name", xmlencode(trace.name))
166                 tnode.appendChild(ttnode)
167     
168         if traces: 
169             rmnode.appendChild(tnode)
170
171     def from_xml(self, xml):
172         doc = minidom.parseString(xml)
173         return self._ec_from_xml(doc)
174
175     def _ec_from_xml(self, doc):
176         from nepi.execution.ec import ExperimentController
177         ec = None
178         
179         ecnode_list = doc.getElementsByTagName("experiment")
180         for ecnode in ecnode_list:
181             if ecnode.nodeType == doc.ELEMENT_NODE:
182                 exp_id = ecnode.getAttribute("exp_id")
183                 run_id = ecnode.getAttribute("run_id")
184                 nthreads = int(ecnode.getAttribute("nthreads"))
185             
186                 os.environ["NEPI_NTHREADS"] = str(nthreads)
187                 ec = ExperimentController(exp_id = exp_id)
188
189                 connections = set()
190
191                 rmnode_list = ecnode.getElementsByTagName("rm")
192                 for rmnode in rmnode_list:
193                     if rmnode.nodeType == doc.ELEMENT_NODE:
194                         self._rm_from_xml(doc, rmnode, ec, connections)
195
196                 for (guid1, guid2) in connections:
197                     ec.register_connection(guid1, guid2)
198
199                 break
200
201         return ec
202
203     def _rm_from_xml(self, doc, rmnode, ec, connections):
204         start_time = None
205         stop_time = None
206         discover_time = None
207         provision_time = None
208         ready_time = None
209         release_time = None
210         failed_time = None
211
212         guid = int(rmnode.getAttribute("guid"))
213         rtype = xmldecode(rmnode.getAttribute("rtype"))
214         state = int(rmnode.getAttribute("state"))
215
216         if rmnode.hasAttribute("start_time"):
217             start_time = xmldecode(rmnode.getAttribute("start_time"))
218         if rmnode.hasAttribute("stop_time"):
219             stop_time = xmldecode(rmnode.getAttribute("stop_time"))
220         if rmnode.hasAttribute("discover_time"):
221             dicover_time = xmldecode(rmnode.getAttribute("discover_time"))
222         if rmnode.hasAttribute("provision_time"):
223             provision_time = xmldecode(rmnode.getAttribute("provision_time"))
224         if rmnode.hasAttribute("ready_time"):
225             ready_time = xmldecode(rmnode.getAttribute("ready_time"))
226         if rmnode.hasAttribute("release_time"):
227             release_time = xmldecode(rmnode.getAttribute("release_time"))
228         if rmnode.hasAttribute("failed_time"):
229             failed_time = xmldecode(rmnode.getAttribute("failed_time"))
230
231         ec.register_resource(rtype, guid = guid)
232         rm = ec.get_resource(guid)
233         rm.set_state_time(state, "_start_time", start_time)
234         rm.set_state_time(state, "_stop_time", stop_time)
235         rm.set_state_time(state, "_discover_time", discover_time)
236         rm.set_state_time(state, "_provision_time", provision_time)
237         rm.set_state_time(state, "_ready_time", ready_time)
238         rm.set_state_time(state, "_release_time", release_time)
239         rm.set_state_time(state, "_failed_time", failed_time)
240         
241         anode_list = rmnode.getElementsByTagName("attributes")
242         if anode_list:
243             aanode_list = anode_list[0].getElementsByTagName("attribute") 
244             for aanode in aanode_list:
245                 name = xmldecode(aanode.getAttribute("name"))
246                 value = xmldecode(aanode.getAttribute("value"))
247                 type = xmldecode(aanode.getAttribute("type"))
248                 value = to_type(type, value)
249                 rm.set(name, value)
250
251         cnode_list = rmnode.getElementsByTagName("connections")
252         if cnode_list:
253             ccnode_list = cnode_list[0].getElementsByTagName("connection") 
254             for ccnode in ccnode_list:
255                 guid2 = int(ccnode.getAttribute("guid"))
256                 connections.add((guid, guid2))
257
258         tnode_list = rmnode.getElementsByTagName("traces")
259         if tnode_list:
260             ttnode_list = tnode_list[0].getElementsByTagName("trace") 
261             for ttnode in ttnode_list:
262                 name = xmldecode(ttnode.getAttribute("name"))
263                 ec.enable_trace(guid, name)
264
265         cnnode_list = rmnode.getElementsByTagName("conditions")
266         if cnnode_list:
267             ccnnode_list = cnnode_list[0].getElementsByTagName("condition") 
268             for ccnnode in ccnnode_list:
269                 action = int(ccnnode.getAttribute("action"))
270                 group = int(ccnnode.getAttribute("group"))
271                 state = int(ccnnode.getAttribute("state"))
272                 time = ccnnode.getAttribute("time")
273                 ec.register_condition(guid, action, group, state, time = time)
274