2 # NEPI, a framework to manage network experiments
3 # Copyright (C) 2013 INRIA
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.
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.
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/>.
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19 # Julien Tribino <julien.tribino@inria.fr>
21 from nepi.util.logger import Logger
25 import xml.etree.ElementTree as ET
27 # inherit from BaseXmpp and XMLstream classes
28 class OMF6Parser(Logger):
30 .. class:: Class Args :
32 :param jid: Jabber Id (= Xmpp Slice + Date)
34 :param password: Jabber Password (= Xmpp Password)
39 This class is an XMPP Client with customized method
46 :param jid: Jabber Id (= Xmpp Slice + Date)
48 :param password: Jabber Password (= Xmpp Password)
53 super(OMF6Parser, self).__init__("OMF6API")
61 def init_mailbox(self):
62 self.mailbox['create'] = []
63 self.mailbox['started'] = []
64 self.mailbox['release'] = []
66 def _check_for_tag(self, root, namespaces, tag):
67 """ Check if an element markup is in the ElementTree
69 :param root: Root of the tree
70 :type root: ElementTree Element
71 :param namespaces: Namespaces of the element
73 :param tag: Tag that will search in the tree
77 for element in root.iter(namespaces+tag):
83 def _check_for_props(self, root, namespaces):
84 """ Check if an element markup is in the ElementTree
86 :param root: Root of the tree
87 :type root: ElementTree Element
88 :param namespaces: Namespaces of the element
93 for properties in root.iter(namespaces+'props'):
94 for element in properties.iter():
95 if element.tag and element.text:
96 props[element.tag] = element.text
99 def _check_for_membership(self, root, namespaces):
100 """ Check if an element markup is in the ElementTree
102 :param root: Root of the tree
103 :type root: ElementTree Element
104 :param namespaces: Namespaces of the element
105 :type namespaces: str
108 for element in root.iter(namespaces+'membership'):
109 for elt in element.iter(namespaces+'it'):
114 def _check_output(self, root, namespaces):
115 """ Check the significative element in the answer and display it
117 :param root: Root of the tree
118 :type root: ElementTree Element
119 :param namespaces: Namespaces of the tree
120 :type namespaces: str
123 fields = ["TARGET", "REASON", "PATH", "APPID", "VALUE"]
126 msg = self._check_for_tag(root, namespaces, elt)
128 response = response + " " + msg.text + " :"
129 deb = self._check_for_tag(root, namespaces, "MESSAGE")
131 msg = response + " " + deb.text
137 def _inform_creation_ok(self, root, namespaces):
138 """ Parse and Display CREATION OK message
142 uid = self._check_for_tag(root, namespaces, "uid")
143 cid = self._check_for_tag(root, namespaces, "cid")
144 member = self._check_for_membership(root, namespaces)
145 binary_path = self._check_for_tag(root, namespaces, "binary_path")
146 msg = "CREATION OK -- "
148 msg = msg + "The resource : '"+binary_path
150 msg = msg + "The interface"
152 msg = msg + "' is listening to the topics : '"+ uid
154 msg = msg + "' and '"+ member +"'"
157 self.mailbox['create'].append([cid, uid ])
159 def _inform_creation_failed(self, root, namespaces):
160 """ Parse and Display CREATION FAILED message
163 reason = self._check_for_tag(root, namespaces, "reason")
164 cid = self._check_for_tag(root, namespaces, "cid")
165 msg = "CREATION FAILED - The reason : "+reason
168 self.mailbox['create'].append([cid, uid ])
170 def _inform_status(self, root, namespaces):
171 """ Parse and Display STATUS message
174 props = self._check_for_props(root, namespaces)
175 uid = self._check_for_tag(root, namespaces, "uid")
176 event = self._check_for_tag(root, namespaces, "event")
179 for elt in props.keys():
180 ns, tag = elt.split('}')
182 log = log + "membership : " + props[elt]+" -- "
184 self.mailbox['started'].append(uid)
185 log = log + "event : " + props[elt]+" -- "
187 if event == "STDOUT" :
188 filename = os.path.join("/tmp", "%s.out" % uid)
189 f = open(filename,'a+')
190 # XXX: Adding fake \n for visual formatting
191 msg = props[elt] + "\n"
194 elif event == "STDERR" :
195 filename = os.path.join("/tmp", "%s.err" % uid)
196 f = open(filename,'a+')
197 # XXX: Adding fake \n for visual formatting
198 msg = props[elt] + "\n"
201 log = log + tag +" : " + props[elt]+" -- "
203 log = log + tag +" : " + props[elt]+" -- "
204 log = log + " STATUS "
207 def _inform_released(self, root, namespaces):
208 """ Parse and Display RELEASED message
212 parent_id = self._check_for_tag(root, namespaces, "src")
213 child_id = self._check_for_tag(root, namespaces, "res_id")
214 cid = self._check_for_tag(root, namespaces, "cid")
216 msg = "RELEASED - The resource : '"+child_id+ \
217 "' has been released by : '"+ parent_id
219 self.mailbox['release'].append(cid)
221 def _inform_error(self, root, namespaces):
222 """ Parse and Display ERROR message
225 reason = self._check_for_tag(root, namespaces, "reason")
226 msg = "The reason : "+reason
229 def _inform_warn(self, root, namespaces):
230 """ Parse and Display WARN message
233 reason = self._check_for_tag(root, namespaces, "reason")
234 msg = "The reason : "+reason
237 def _parse_inform(self, root, namespaces):
238 """ Check the significative element in the answer
239 Then Parse it and display using specific method
241 :param root: Root of the tree
242 :type root: ElementTree Element
243 :param namespaces: Namespaces of the tree
244 :type namespaces: str
247 itype = self._check_for_tag(root, namespaces, "itype")
249 method_name = '_inform_'+ itype.replace('.', '_').lower()
250 method = getattr(self, method_name)
252 method(root, namespaces)
254 msg = "There is no method to parse the response of the type " + itype
259 def check_mailbox(self, itype, attr):
260 """ Check the mail box
262 :param itype: type of mail
264 :param attr: value wanted
268 if itype == "create":
269 for res in self.mailbox[itype]:
272 self.mailbox[itype].remove(res)
275 for res in self.mailbox[itype]:
277 self.mailbox[itype].remove(res)
281 def handle(self, iq):
282 """ Check the mail box
284 :param iq: message received
287 namespaces = "{http://schema.mytestbed.net/omf/6.0/protocol}"
288 for i in iq['pubsub_event']['items']:
289 root = ET.fromstring(str(i))
291 self._parse_inform(root, namespaces)