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