Adding authors and correcting licence information
[nepi.git] / src / nepi / util / sfa_sfav1.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 #         Lucia Guevgeozian Odizzio <lucia.guevgeozian_odizzio@inria.fr>
20
21
22 from lxml import etree
23 #import collections
24 import sys
25
26 class SFAResourcesParser(object):
27     # Maybe this init method is not necessary, it was aim to check that the
28     # aggregate was supported by nepi
29
30     def __init__(self, aggr_pattern):
31         if not isinstance(aggr_pattern, list):
32             self._aggr_pattern = [aggr_pattern]
33         else:
34             self._aggr_pattern = aggr_pattern
35     
36     def resources_from_xml(self, xml, sliver = False, resources = False):
37         rdata = dict()
38         ldata = dict()
39         stags = dict()
40         RSpec = etree.fromstring(xml)
41         RSpec_attr = dict(RSpec.attrib)
42         network = RSpec.findall('.//network')
43         for net in network:
44             aggr = net.get('name') 
45             if aggr == 'ple' and resources:
46                 node_tree = net.iterfind('node')
47                 for node in list(node_tree): 
48                     if isinstance(node.tag, basestring):
49                         data_ple = dict(node.attrib)
50                         data_ple['aggregate'] = aggr
51                         data_ple['resource_type'] = 'node'
52                         data_ple = self._get_node_info(node, data_ple)
53                         hostname = node.find('hostname')
54                         rdata[hostname.text] = data_ple
55                 if sliver:
56                     sliver_defaults = net.find('sliver_defaults')
57                     if len(sliver_defaults):
58                         stags = self._get_sliver_tags(sliver_defaults, stags)
59             elif aggr == 'omf' and resources:
60                 node_tree = net.iterfind('node')
61                 for node in node_tree:
62                     if isinstance(node.tag, basestring):
63                         data_omf = dict(node.attrib)
64                         data_omf['aggregate'] = aggr
65                         data_omf['resource_type'] = 'node'
66                         data_omf = self._get_node_info(node, data_omf)
67                         hostname = node.find('hostname')
68                         rdata[hostname.text] = data_omf
69                 spectrum = net.find('spectrum')
70                 for channel in list(spectrum):
71                     if isinstance(channel.tag, basestring):
72                         data_omf = dict(channel.attrib)
73                         data_omf['aggregate'] = aggr
74                         data_omf['resource_type'] = 'channel'
75                         channelnum = data_omf['channel_num']
76                         rdata[channelnum] = data_omf
77                 leases = net.iterfind('lease')
78                 for lease in list(leases):
79                     if isinstance(lease.tag, basestring):
80                         (st, duration) = lease.attrib['start_time'], lease.attrib['duration']
81                         data_lease = dict(lease.attrib)
82                         data_lease['aggregate'] = aggr
83                         data_lease['resource_type'] = 'lease'
84                         data_lease = self._get_leases_info(lease, data_lease)
85                         ldata[(st, duration)] = data_lease
86             elif aggr == 'omf' and not resources:
87                 leases = net.iterfind('lease')
88                 for lease in list(leases):
89                     if isinstance(lease.tag, basestring):
90                         (st, duration) = lease.attrib['start_time'], lease.attrib['duration']
91                         data_lease = dict(lease.attrib)
92                         data_lease['aggregate'] = aggr
93                         data_lease['resource_type'] = 'lease'
94                         data_lease = self._get_leases_info(lease, data_lease)
95                         ldata[(st, duration)] = data_lease
96             else:
97                 pass
98         if sliver:
99             return rdata, ldata, stags
100         elif resources:
101             return rdata, ldata
102         elif not resources:
103             return ldata
104
105     def _get_node_info(self, node_tag, data_dict):
106         for n in list(node_tag):
107             if isinstance(n.tag, basestring):
108                 if n.attrib:
109                     data_dict[n.tag] = dict(n.attrib)
110                 else:
111                     data_dict[n.tag] = n.text
112         return data_dict
113
114     def _get_leases_info(self, lease_tag, data_dict):
115         nodes = list()
116         channels = list()
117         for l in list(lease_tag):
118             if l.tag == 'node':
119                 node = l.attrib['component_id'].split('+').pop()
120                 nodes.append(node)
121             if l.tag == 'channel':
122                 #TODO: find out key when channel reservation
123                 #channels.append(l.attrib['averiguar']) channel_num
124                 pass
125             data_dict['nodes'] = nodes
126             data_dict['channels'] = channels
127         return data_dict
128
129     def _get_sliver_tags(self, sliverdefaults_tag, sliver_tag_dict):
130         vsys = list()
131         for info in list(sliverdefaults_tag):
132             if info.tag == 'vsys_vnet':
133                 sliver_tag_dict['vsys_vnet'] = info.text
134             elif info.tag == 'vsys':
135                 vsys.append(info.text)
136         sliver_tag_dict['vsys'] = vsys
137         return sliver_tag_dict
138             
139     def create_reservation_xml(self, xml, slice_hrn, new_resource, start_time, duration, aggregate):
140         aggrs = []
141         RSpec = etree.fromstring(xml)
142         network = RSpec.findall('.//network')
143         for net in network:
144             aggr = net.get('name')
145             aggrs.append(aggr)
146             if aggr == aggregate:
147                 new_xml = self._create_tags(RSpec, net, slice_hrn, new_resource, start_time, duration)
148         if aggregate not in aggrs:
149             new_net = etree.SubElement(RSpec, 'network', name = aggregate)
150             new_xml = self._create_tags(RSpec, new_net, slice_hrn, new_resource, start_time, duration)
151         return new_xml
152
153     def _create_tags(self, RSpec, net, slice_hrn, new_resource, start_time, duration):
154         resource = new_resource.keys()[0]
155         res_type = new_resource[resource]['resource_type']
156         if res_type == 'node':
157             node = etree.SubElement(net, res_type, \
158             component_manager_id = new_resource[resource]['component_manager_id'],\
159             component_id = new_resource[resource]['component_id'],\
160             component_name = new_resource[resource]['component_name'], \
161             site_id = new_resource[resource]['site_id'])
162             sliver_tag = etree.SubElement(node, 'sliver')
163         elif res_type == 'channel':
164             spectrum = etree.SubElement(net, spectrum)
165             channel = etree.SubElement(spectrum, channel,\
166             channel_num = new_resource[resource]['channel_num'],\
167             frequency = new_resource[resource]['frequency'],\
168             standard = new_resource[resource]['standard'])
169         if start_time is not None and duration is not None:
170             slice_id = "urn:publicid:IDN+" + slice_hrn.split('.')[0] + ':' + slice_hrn.split('.')[1]\
171             + '+slice+' + slice_hrn.split('.')[2]
172             lease = etree.SubElement(net, 'lease', slice_id = slice_id,\
173             start_time = str(start_time), duration = str(duration))
174             if res_type == 'node':
175                 res = etree.SubElement(lease, res_type,\
176                 component_id = new_resource[resource]['component_id'])
177             elif res_type == 'channel':
178                 res = etree.SubElement(lease, res_type,\
179                 channel_num = new_resource[resource]['channel_num'])
180         new_xml = etree.tostring(RSpec, xml_declaration=True)
181         return new_xml
182                 
183     def verify_reservation_xml(self, xml, slice_hrn, new_resource, start_time, duration, aggregate):
184         slice_id = "urn:publicid:IDN+" + slice_hrn.split('.')[0] + ':' + slice_hrn.split('.')[1]\
185         + '+slice+' + slice_hrn.split('.')[2]
186         rdata, ldata, stags = self.resources_from_xml(xml, sliver = True, resources = True)
187         res_name = new_resource.keys()[0]
188         if res_name in rdata.keys():
189             if start_time and duration:
190                 if ldata[(start_time, duration)]:
191                     nodes = ldata[(start_time, duration)]['nodes']
192                     sliceid = ldata[(start_time, duration)]['slice_id']
193                     if res_name in nodes and sliceid == slice_id:
194                         return True
195                     else: return False
196                 else: return False
197             else: return True
198         else: return False
199
200     def release_reservation_xml(self, xml, slice_hrn, resource, start_time, duration, aggregate):
201         RSpec = etree.fromstring(xml)
202         network = RSpec.findall('.//network')
203         for net in network:
204             aggr = net.get('name')
205             if aggr == aggregate:
206                 new_xml = self._delete_tag(RSpec, net, slice_hrn, resource, start_time, duration)
207                 return new_xml
208
209     def _delete_tag(self, RSpec, net, slice_hrn, resource, start_time, duration):
210         resource_name = resource.keys()[0]
211         res_type = resource[resource_name]['resource_type']
212         if res_type == 'node':
213             node_tree = net.iterfind('node')
214             for node in list(node_tree):
215                 if isinstance(node.tag, basestring):
216                     data_node = dict(node.attrib)
217                     if data_node['component_name'] == resource_name:
218                         net.remove(node)
219         elif res_type == 'channel':
220             spectrum = net.find('spectrum')
221             for channel in list(spectrum):
222                 if isinstance(channel.tag, basestring):
223                     data_channel = dict(channel.attrib)
224                     if data_channel['channel_num'] == resource_name:
225                         spectrum.remove(channel)
226         if start_time is not None and duration is not None:
227             slice_id = "urn:publicid:IDN+" + slice_hrn.split('.')[0] + ':' + slice_hrn.split('.')[1]\
228             + '+slice+' + slice_hrn.split('.')[2]
229             leases = net.iterfind('lease')
230             for lease in list(leases):
231                 if isinstance(lease.tag, basestring):
232                     (st, duration) = lease.attrib['start_time'], lease.attrib['duration']
233                     sliceid = lease.attrib['slice_id']
234                     if st == str(start_time) and duration == str(duration) and sliceid == slice_id:
235                         for l in list(lease):
236                             if l.tag == 'node' and res_type == 'node':
237                                 if l.attrib['component_id'].split('+').pop() == resource_name:
238                                     lease.remove(l)
239                             elif l.tag == 'channel' and res_type == 'channel':
240                                 if l.attrib['channel_num'] == resource_name:
241                                     lease.remove(l)
242         new_xml = etree.tostring(RSpec, xml_declaration=True)
243         return new_xml
244
245