414202923de8589569ca032ac40575f6d407430f
[nepi.git] / src / nepi / resources / omf / omf6_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 #         Julien Tribino <julien.tribino@inria.fr>
20
21 from nepi.util.logger import Logger
22
23 import traceback
24 import xml.etree.ElementTree as ET
25
26 # inherit from BaseXmpp and XMLstream classes
27 class OMF6Parser(Logger): 
28     """
29     .. class:: Class Args :
30       
31         :param jid: Jabber Id (= Xmpp Slice + Date)
32         :type jid: str
33         :param password: Jabber Password (= Xmpp Password)
34         :type password: str
35
36     .. note::
37
38        This class is an XMPP Client with customized method
39
40     """
41
42     def __init__(self):
43         """
44
45         :param jid: Jabber Id (= Xmpp Slice + Date)
46         :type jid: str
47         :param password: Jabber Password (= Xmpp Password)
48         :type password: str
49
50
51         """
52         super(OMF6Parser, self).__init__("OMF6API")
53         self.mailbox={}
54
55         self.init_mailbox()
56
57     def init_mailbox(self):
58         self.mailbox['create'] = []
59         self.mailbox['configure'] = []
60         self.mailbox['request'] = []
61         self.mailbox['release'] = []
62         self.mailbox['inform'] = []
63   
64     def _check_for_tag(self, root, namespaces, tag):
65         """  Check if an element markup is in the ElementTree
66
67         :param root: Root of the tree
68         :type root: ElementTree Element
69         :param namespaces: Namespaces of the element
70         :type namespaces: str
71         :param tag: Tag that will search in the tree
72         :type tag: str
73
74         """
75         for element in root.iter(namespaces+tag):
76             if element.text:
77                 return element.text
78             else : 
79                 return None
80
81     def _check_for_props(self, root, namespaces):
82         """  Check if an element markup is in the ElementTree
83
84         :param root: Root of the tree
85         :type root: ElementTree Element
86         :param namespaces: Namespaces of the element
87         :type namespaces: str
88
89         """
90         props = {}
91         for properties in root.iter(namespaces+'props'):
92             for element in properties.iter():
93                 if element.tag and element.text:
94                     props[element.tag] = element.text
95         return props
96
97     def _check_for_membership(self, root, namespaces):
98         """  Check if an element markup is in the ElementTree
99
100         :param root: Root of the tree
101         :type root: ElementTree Element
102         :param namespaces: Namespaces of the element
103         :type namespaces: str
104
105         """
106         for element in root.iter(namespaces+'membership'):
107             for elt in element.iter(namespaces+'it'):
108                 ##XXX : change
109                 return elt.text
110
111
112     def _check_output(self, root, namespaces):
113         """ Check the significative element in the answer and display it
114
115         :param root: Root of the tree
116         :type root: ElementTree Element
117         :param namespaces: Namespaces of the tree
118         :type namespaces: str
119
120         """
121         fields = ["TARGET", "REASON", "PATH", "APPID", "VALUE"]
122         response = ""
123         for elt in fields:
124             msg = self._check_for_tag(root, namespaces, elt)
125             if msg is not None:
126                 response = response + " " + msg.text + " :"
127         deb = self._check_for_tag(root, namespaces, "MESSAGE")
128         if deb is not None:
129             msg = response + " " + deb.text
130             self.debug(msg)
131         else :
132             self.info(response)
133
134
135     def _inform_creation_ok(self, root, namespaces):
136         #ET.dump(root)
137         uid = self._check_for_tag(root, namespaces, "uid")
138         cid = self._check_for_tag(root, namespaces, "cid")
139         member = self._check_for_membership(root, namespaces)
140         binary_path = self._check_for_tag(root, namespaces, "binary_path")
141         msg = "CREATION OK -- "
142         if binary_path :
143             msg = msg + "The resource : '"+binary_path
144         if uid :
145             msg = msg + "' is listening to the topics : '"+ uid
146         if member :
147             msg = msg + "' and '"+ member +"'"
148         if cid:
149             self.info(msg)
150             self.mailbox['create'].append([cid, uid ])
151
152     def _inform_creation_failed(self, root, namespaces):
153         reason = self._check_for_tag(root, namespaces, "reason")
154         cid = self._check_for_tag(root, namespaces, "cid")
155         msg = "CREATION FAILED - The reason : "+reason
156         if cid:
157             self.error(msg)
158             self.mailbox['create'].append([cid, uid ])
159
160     def _inform_status(self, root, namespaces):
161         props = self._check_for_props(root, namespaces)
162         msg = "STATUS -- "
163         for elt in props.keys():
164             ns, tag = elt.split('}')
165             if tag == "it":
166                 msg = msg + "membership : " + props[elt]+" -- "
167             else:
168                 msg = msg + tag +" : " + props[elt]+" -- "
169         msg = msg + " STATUS "
170         self.info(msg)
171
172     def _inform_released(self, root, namespaces):
173         #ET.dump(root)
174         parent_id = self._check_for_tag(root, namespaces, "src")
175         child_id = self._check_for_tag(root, namespaces, "res_id")
176         cid = self._check_for_tag(root, namespaces, "cid")
177         if cid :
178             msg = "RELEASED - The resource : '"+child_id+ \
179               "' has been released by : '"+ parent_id
180             self.info(msg)
181             self.mailbox['release'].append(cid)
182
183     def _inform_error(self, root, namespaces):
184         reason = self._check_for_tag(root, namespaces, "reason")
185         msg = "The reason : "+reason
186         self.error(msg)
187
188     def _inform_warn(self, root, namespaces):
189         reason = self._check_for_tag(root, namespaces, "reason")
190         msg = "The reason : "+reason
191         self.warn(msg)
192
193     def _parse_inform(self, root, namespaces):
194         """ Check the significative element in the answer and display it
195
196         :param root: Root of the tree
197         :type root: ElementTree Element
198         :param namespaces: Namespaces of the tree
199         :type namespaces: str
200
201         """
202         itype = self._check_for_tag(root, namespaces, "itype")
203         if itype :
204             method_name = '_inform_'+ itype.replace('.', '_').lower()
205             method = getattr(self, method_name)
206             if method :
207                 method(root, namespaces)
208             else :
209                 msg = "There is no method to parse the response of the type " + itype
210                 self.info(msg)
211                 return
212         
213
214     def check_mailbox(self, itype, attr):
215         if itype == "create":
216             for res in self.mailbox[itype]:
217                 binary, uid = res
218                 if binary == attr:
219                     self.mailbox[itype].remove(res)
220                     return uid
221         elif itype == "release":
222             for res in self.mailbox[itype]:
223                 if attr == res:
224                     self.mailbox[itype].remove(res)
225                     return res
226            
227                
228
229     def handle(self, iq):
230         namespaces = "{http://schema.mytestbed.net/omf/6.0/protocol}"
231         for i in iq['pubsub_event']['items']:
232             root = ET.fromstring(str(i))
233             #ET.dump(root)
234             self._parse_inform(root, namespaces)
235