bugs fixing
[sfa.git] / sfa / nitos / nitosaggregate.py
1 #!/usr/bin/python
2 from sfa.util.xrn import Xrn, hrn_to_urn, urn_to_hrn
3 from sfa.util.sfatime import utcparse, datetime_to_string
4 from sfa.util.sfalogging import logger
5
6 from sfa.rspecs.rspec import RSpec
7 from sfa.rspecs.elements.hardware_type import HardwareType
8 from sfa.rspecs.elements.node import Node
9 from sfa.rspecs.elements.link import Link
10 from sfa.rspecs.elements.sliver import Sliver
11 from sfa.rspecs.elements.login import Login
12 from sfa.rspecs.elements.location import Location
13 from sfa.rspecs.elements.position_3d import Position3D
14 from sfa.rspecs.elements.interface import Interface
15 from sfa.rspecs.elements.services import Services
16 from sfa.rspecs.elements.pltag import PLTag
17 from sfa.rspecs.elements.lease import Lease
18 from sfa.rspecs.elements.granularity import Granularity
19 from sfa.rspecs.elements.channel import Channel
20 from sfa.rspecs.version_manager import VersionManager
21
22 from sfa.nitos.nitosxrn import NitosXrn, hostname_to_urn, hrn_to_nitos_slicename, slicename_to_hrn
23 from sfa.planetlab.vlink import get_tc_rate
24 from sfa.planetlab.topology import Topology
25
26 import time
27
28 class NitosAggregate:
29
30     def __init__(self, driver):
31         self.driver = driver
32  
33     def get_sites(self, filter={}):
34         sites = {}
35         for site in self.driver.shell.GetSites(filter):
36             sites[site['site_id']] = site
37         return sites
38
39     def get_interfaces(self, filter={}):
40         interfaces = {}
41         for interface in self.driver.shell.GetInterfaces(filter):
42             iface = Interface()
43             if interface['bwlimit']:
44                 interface['bwlimit'] = str(int(interface['bwlimit'])/1000)
45             interfaces[interface['interface_id']] = interface
46         return interfaces
47
48     def get_links(self, sites, nodes, interfaces):
49         
50         topology = Topology() 
51         links = []
52         for (site_id1, site_id2) in topology:
53             site_id1 = int(site_id1)
54             site_id2 = int(site_id2)
55             link = Link()
56             if not site_id1 in sites or site_id2 not in sites:
57                 continue
58             site1 = sites[site_id1]
59             site2 = sites[site_id2]
60             # get hrns
61             site1_hrn = self.driver.hrn + '.' + site1['login_base']
62             site2_hrn = self.driver.hrn + '.' + site2['login_base']
63
64             for s1_node_id in site1['node_ids']:
65                 for s2_node_id in site2['node_ids']:
66                     if s1_node_id not in nodes or s2_node_id not in nodes:
67                         continue
68                     node1 = nodes[s1_node_id]
69                     node2 = nodes[s2_node_id]
70                     # set interfaces
71                     # just get first interface of the first node
72                     if1_xrn = PlXrn(auth=self.driver.hrn, interface='node%s:eth0' % (node1['node_id']))
73                     if1_ipv4 = interfaces[node1['interface_ids'][0]]['ip']
74                     if2_xrn = PlXrn(auth=self.driver.hrn, interface='node%s:eth0' % (node2['node_id']))
75                     if2_ipv4 = interfaces[node2['interface_ids'][0]]['ip']
76
77                     if1 = Interface({'component_id': if1_xrn.urn, 'ipv4': if1_ipv4} )
78                     if2 = Interface({'component_id': if2_xrn.urn, 'ipv4': if2_ipv4} )
79
80                     # set link
81                     link = Link({'capacity': '1000000', 'latency': '0', 'packet_loss': '0', 'type': 'ipv4'})
82                     link['interface1'] = if1
83                     link['interface2'] = if2
84                     link['component_name'] = "%s:%s" % (site1['login_base'], site2['login_base'])
85                     link['component_id'] = PlXrn(auth=self.driver.hrn, interface=link['component_name']).get_urn()
86                     link['component_manager_id'] =  hrn_to_urn(self.driver.hrn, 'authority+am')
87                     links.append(link)
88
89         return links
90
91     def get_node_tags(self, filter={}):
92         node_tags = {}
93         for node_tag in self.driver.shell.GetNodeTags(filter):
94             node_tags[node_tag['node_tag_id']] = node_tag
95         return node_tags
96
97     def get_pl_initscripts(self, filter={}):
98         pl_initscripts = {}
99         filter.update({'enabled': True})
100         for initscript in self.driver.shell.GetInitScripts(filter):
101             pl_initscripts[initscript['initscript_id']] = initscript
102         return pl_initscripts
103
104
105     def get_slice_and_slivers(self, slice_xrn):
106         """
107         Returns a dict of slivers keyed on the sliver's node_id
108         """
109         slivers = {}
110         slice = None
111         if not slice_xrn:
112             return (slice, slivers)
113         slice_urn = hrn_to_urn(slice_xrn, 'slice')
114         slice_hrn, _ = urn_to_hrn(slice_xrn)
115         slice_name = hrn_to_nitos_slicename(slice_hrn)
116         slices = self.driver.shell.getSlices({'slice_name': slice_name}, [])
117         # filter results
118         #for slc in slices:
119         #     if slc['slice_name'] == slice_name:
120         #         slice = slc
121         #          break
122
123         if not slice:
124             return (slice, slivers)
125       
126         reserved_nodes = self.driver.shell.getReservedNodes({'slice_id': slice['slice_id']}, [])
127        
128         for node in reserved_nodes:
129              slivers[node['id']] = node
130
131         return (slice, slivers)
132        
133
134
135     def get_nodes_and_links(self, slice_xrn, slice=None,slivers={}, options={}):
136         # if we are dealing with a slice that has no node just return 
137         # and empty list    
138         if slice_xrn:
139             if not slice or not slivers:
140                 return ([],[])
141             else:
142                 nodes = [slivers[sliver] for sliver in slivers]
143         else:
144             nodes = self.driver.shell.getNodes({}, [])
145         
146         # get the granularity in second for the reservation system
147         grain = self.driver.testbedInfo['grain']
148         #grain = 1800
149        
150  
151
152         rspec_nodes = []
153         for node in nodes:
154             rspec_node = Node()
155             site_name = self.driver.testbedInfo['name']
156             rspec_node['component_id'] = hostname_to_urn(self.driver.hrn, site_name, node['name'])
157             rspec_node['component_name'] = node['name']
158             rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()
159             rspec_node['authority_id'] = hrn_to_urn(NitosXrn.site_hrn(self.driver.hrn, site_name), 'authority+sa')
160             # do not include boot state (<available> element) in the manifest rspec
161             #if not slice:     
162             #    rspec_node['boot_state'] = node['boot_state']
163             rspec_node['exclusive'] = 'true'
164             # site location
165             longitude = self.driver.testbedInfo['longitude']
166             latitude = self.driver.testbedInfo['latitude']  
167             if longitude and latitude:  
168                 location = Location({'longitude': longitude, 'latitude': latitude, 'country': 'unknown'})
169                 rspec_node['location'] = location
170             # 3D position
171             position_3d = Position3D({'x': node['X'], 'y': node['Y'], 'z': node['Z']})
172             #position_3d = Position3D({'x': 1, 'y': 2, 'z': 3})
173             rspec_node['position_3d'] = position_3d 
174             # Granularity
175             granularity = Granularity({'grain': grain})
176             rspec_node['granularity'] = granularity
177
178             # HardwareType
179             rspec_node['hardware_type'] = node['type']
180             #rspec_node['hardware_type'] = "orbit"
181
182                 
183             rspec_nodes.append(rspec_node)
184         return (rspec_nodes, []) 
185
186     def get_leases_and_channels(self, slice=None, options={}):
187         
188         slices = self.driver.shell.getSlices({}, [])
189         nodes = self.driver.shell.getNodes({}, [])
190         leases = self.driver.shell.getReservedNodes({}, [])
191         channels = self.driver.shell.getChannels({}, [])
192         reserved_channels = self.driver.shell.getReservedChannels()
193         grain = self.driver.testbedInfo['grain']
194
195         if slice:
196             for lease in leases:
197                  if lease['slice_id'] != slice['slice_id']:
198                      leases.remove(lease)
199             for channel in reserved_channels:
200                  if channel['slice_id'] != slice['slice_id']:
201                      reserved_channels.remove(channel)
202
203         rspec_channels = []
204         for channel in reserved_channels:
205              
206             rspec_channel = {}
207             #retrieve channel number  
208             for chl in channels:
209                  if chl['channel_id'] == channel['channel_id']:
210                      channel_number = chl['channel']
211                      break
212
213             rspec_channel['channel_num'] = channel_number
214             rspec_channel['start_time'] = channel['start_time']
215             rspec_channel['duration'] = (int(channel['end_time']) - int(channel['start_time'])) / int(grain)
216                  
217             # retreive slicename
218             for slc in slices:
219                  if slc['slice_id'] == channel['slice_id']:
220                      slicename = slc['slice_name']
221                      break
222
223             slice_hrn = slicename_to_hrn(self.driver.hrn, self.driver.testbedInfo['name'], slicename)
224             slice_urn = hrn_to_urn(slice_hrn, 'slice')
225             rspec_channel['slice_id'] = slice_urn
226             rspec_channels.append(rspec_channel)
227
228  
229         rspec_leases = []
230         for lease in leases:
231
232             rspec_lease = Lease()
233             
234             rspec_lease['lease_id'] = lease['reservation_id']
235             # retreive node name
236             for node in nodes:
237                  if node['id'] == lease['node_id']:
238                      nodename = node['name']
239                      break
240            
241             rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn, self.driver.testbedInfo['name'], nodename)
242             # retreive slicename
243             for slc in slices:
244                  if slc['slice_id'] == lease['slice_id']:
245                      slicename = slc['slice_name']
246                      break
247             
248             slice_hrn = slicename_to_hrn(self.driver.hrn, self.driver.testbedInfo['name'], slicename)
249             slice_urn = hrn_to_urn(slice_hrn, 'slice')
250             rspec_lease['slice_id'] = slice_urn
251             rspec_lease['start_time'] = lease['start_time']
252             rspec_lease['duration'] = (int(lease['end_time']) - int(lease['start_time'])) / int(grain)
253             rspec_leases.append(rspec_lease)
254
255         return (rspec_leases, rspec_channels)
256
257
258     def get_channels(self, options={}):
259         
260         filter = {}
261         channels = self.driver.shell.getChannels({}, [])
262         rspec_channels = []
263         for channel in channels:
264             rspec_channel = Channel()
265             rspec_channel['channel_num'] = channel['channel']
266             rspec_channel['frequency'] = channel['frequency']
267             rspec_channel['standard'] = channel['modulation']
268             rspec_channels.append(rspec_channel)
269         return rspec_channels
270
271
272     
273     def get_rspec(self, slice_xrn=None, version = None, options={}):
274
275         version_manager = VersionManager()
276         version = version_manager.get_version(version)
277
278         if not slice_xrn:
279             rspec_version = version_manager._get_version(version.type, version.version, 'ad')
280         else:
281             rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
282
283         slice, slivers = self.get_slice_and_slivers(slice_xrn)
284
285         rspec = RSpec(version=rspec_version, user_options=options)
286
287         if slice and 'expires' in slice:
288             rspec.xml.set('expires',  datetime_to_string(utcparse(slice['expires'])))
289
290         if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'leases':
291            nodes, links = self.get_nodes_and_links(slice_xrn, slice, slivers, options)
292            rspec.version.add_nodes(nodes)
293            rspec.version.add_links(links)
294            # add sliver defaults
295            default_sliver = slivers.get(None, [])
296            if default_sliver:
297               default_sliver_attribs = default_sliver.get('tags', [])
298               for attrib in default_sliver_attribs:
299                   logger.info(attrib)
300                   rspec.version.add_default_sliver_attribute(attrib['tagname'], attrib['value'])
301            # add wifi channels
302            channels = self.get_channels()
303            rspec.version.add_channels(channels)
304
305         if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'resources':
306            leases, channels = self.get_leases_and_channels(slice)
307            rspec.version.add_leases(leases, channels)
308
309         return rspec.toxml()
310
311