edf3d93327e2ce7c6690a3e2b672c4d1f3a8e451
[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 NodeElement
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.pltag import PLTag
16 from sfa.rspecs.elements.lease import Lease
17 from sfa.rspecs.elements.granularity import Granularity
18 from sfa.rspecs.elements.channel import Channel
19 from sfa.rspecs.version_manager import VersionManager
20
21 from sfa.nitos.nitosxrn import NitosXrn, hostname_to_urn, hrn_to_nitos_slicename, slicename_to_hrn, channel_to_urn
22 from sfa.planetlab.vlink import get_tc_rate
23 from sfa.planetlab.topology import Topology
24
25 import time
26
27 class NitosAggregate:
28
29     def __init__(self, driver):
30         self.driver = driver
31
32
33     def get_slice_and_slivers(self, slice_xrn):
34         """
35         Returns a dict of slivers keyed on the sliver's node_id
36         """
37         slivers = {}
38         slice = None
39         if not slice_xrn:
40             return (slice, slivers)
41         slice_urn = hrn_to_urn(slice_xrn, 'slice')
42         slice_hrn, _ = urn_to_hrn(slice_xrn)
43         slice_name = hrn_to_nitos_slicename(slice_hrn)
44         slices = self.driver.shell.getSlices({'slice_name': slice_name}, [])
45         #filter results
46         for slc in slices:
47              if slc['slice_name'] == slice_name:
48                  slice = slc
49                  break
50
51         if not slice:
52             return (slice, slivers)
53       
54         reserved_nodes = self.driver.shell.getReservedNodes({'slice_id': slice['slice_id']}, [])
55         reserved_node_ids = []
56         # filter on the slice
57         for node in reserved_nodes:
58              if node['slice_id'] == slice['slice_id']:
59                  reserved_node_ids.append(node['node_id'])
60         #get all the nodes
61         all_nodes = self.driver.shell.getNodes({}, [])
62        
63         for node in all_nodes:
64              if node['node_id'] in reserved_node_ids:
65                  slivers[node['node_id']] = node
66         
67         return (slice, slivers)
68        
69
70
71     def get_nodes(self, slice_xrn, slice=None,slivers={}, options={}):
72         # if we are dealing with a slice that has no node just return 
73         # and empty list    
74         if slice_xrn:
75             if not slice or not slivers:
76                 return []
77             else:
78                 nodes = [slivers[sliver] for sliver in slivers]
79         else:
80             nodes = self.driver.shell.getNodes({}, [])
81         
82         # get the granularity in second for the reservation system
83         grain = self.driver.testbedInfo['grain']
84         #grain = 1800
85        
86
87         rspec_nodes = []
88         for node in nodes:
89             rspec_node = NodeElement()
90             site_name = self.driver.testbedInfo['name']
91             rspec_node['component_id'] = hostname_to_urn(self.driver.hrn, site_name, node['hostname'])
92             rspec_node['component_name'] = node['hostname']
93             rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()
94             rspec_node['authority_id'] = hrn_to_urn(NitosXrn.site_hrn(self.driver.hrn, site_name), 'authority+sa')
95             # do not include boot state (<available> element) in the manifest rspec
96             #if not slice:     
97             #    rspec_node['boot_state'] = node['boot_state']
98             rspec_node['exclusive'] = 'true'
99             # site location
100             longitude = self.driver.testbedInfo['longitude']
101             latitude = self.driver.testbedInfo['latitude']  
102             if longitude and latitude:  
103                 location = Location({'longitude': longitude, 'latitude': latitude, 'country': 'unknown'})
104                 rspec_node['location'] = location
105             # 3D position
106             position_3d = Position3D({'x': node['position']['X'], 'y': node['position']['Y'], 'z': node['position']['Z']})
107             #position_3d = Position3D({'x': 1, 'y': 2, 'z': 3})
108             rspec_node['position_3d'] = position_3d 
109             # Granularity
110             granularity = Granularity({'grain': grain})
111             rspec_node['granularity'] = granularity
112
113             # HardwareType
114             rspec_node['hardware_type'] = node['node_type']
115             #rspec_node['hardware_type'] = "orbit"
116             
117             #slivers
118             if node['node_id'] in slivers:
119                 # add sliver info
120                 sliver = slivers[node['node_id']]
121                 rspec_node['sliver_id'] = sliver['node_id']
122                 rspec_node['client_id'] = node['hostname']
123                 rspec_node['slivers'] = [sliver]
124
125                 
126             rspec_nodes.append(rspec_node)
127         return rspec_nodes 
128
129     def get_leases_and_channels(self, slice=None, slice_xrn=None,  options={}):
130         
131         slices = self.driver.shell.getSlices({}, [])
132         nodes = self.driver.shell.getNodes({}, [])
133         leases = self.driver.shell.getReservedNodes({}, [])
134         channels = self.driver.shell.getChannels({}, [])
135         reserved_channels = self.driver.shell.getReservedChannels()
136         grain = self.driver.testbedInfo['grain']
137
138         if slice_xrn and not slice:
139             return ([], [])
140
141         if slice:
142             all_leases = []
143             all_leases.extend(leases)
144             all_reserved_channels = []
145             all_reserved_channels.extend(reserved_channels)
146             for lease in all_leases:
147                  if lease['slice_id'] != slice['slice_id']:
148                      leases.remove(lease)
149             for channel in all_reserved_channels:
150                  if channel['slice_id'] != slice['slice_id']:
151                      reserved_channels.remove(channel)
152
153         rspec_channels = []
154         for channel in reserved_channels:
155              
156             rspec_channel = {}
157             #retrieve channel number  
158             for chl in channels:
159                  if chl['channel_id'] == channel['channel_id']:
160                      channel_number = chl['channel']
161                      break
162
163             rspec_channel['channel_num'] = channel_number
164             rspec_channel['start_time'] = channel['start_time']
165             rspec_channel['duration'] = (int(channel['end_time']) - int(channel['start_time'])) / int(grain)
166             rspec_channel['component_id'] = channel_to_urn(self.driver.hrn, self.driver.testbedInfo['name'], channel_number)
167                  
168             # retreive slicename
169             for slc in slices:
170                  if slc['slice_id'] == channel['slice_id']:
171                      slicename = slc['slice_name']
172                      break
173
174             if slice_xrn:
175                 slice_urn = slice_xrn
176                 slice_hrn = urn_to_hrn(slice_urn)
177             else:
178                 slice_hrn = slicename_to_hrn(self.driver.hrn, self.driver.testbedInfo['name'], slicename)
179                 slice_urn = hrn_to_urn(slice_hrn, 'slice')
180
181             rspec_channel['slice_id'] = slice_urn
182             rspec_channels.append(rspec_channel)
183
184  
185         rspec_leases = []
186         for lease in leases:
187
188             rspec_lease = Lease()
189             
190             rspec_lease['lease_id'] = lease['reservation_id']
191             # retreive node name
192             for node in nodes:
193                  if node['node_id'] == lease['node_id']:
194                      nodename = node['hostname']
195                      break
196            
197             rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn, self.driver.testbedInfo['name'], nodename)
198             # retreive slicename
199             for slc in slices:
200                  if slc['slice_id'] == lease['slice_id']:
201                      slicename = slc['slice_name']
202                      break
203             
204             if slice_xrn:
205                 slice_urn = slice_xrn
206                 slice_hrn = urn_to_hrn(slice_urn)
207             else:
208                 slice_hrn = slicename_to_hrn(self.driver.hrn, self.driver.testbedInfo['name'], slicename)
209                 slice_urn = hrn_to_urn(slice_hrn, 'slice')
210
211             rspec_lease['slice_id'] = slice_urn
212             rspec_lease['start_time'] = lease['start_time']
213             rspec_lease['duration'] = (int(lease['end_time']) - int(lease['start_time'])) / int(grain)
214             rspec_leases.append(rspec_lease)
215
216         return (rspec_leases, rspec_channels)
217
218
219     def get_channels(self, slice=None, options={}):
220  
221         all_channels = self.driver.shell.getChannels({}, [])
222         channels = []
223         if slice:
224             reserved_channels = self.driver.shell.getReservedChannels()
225             reserved_channel_ids = []
226             for channel in reserved_channels:
227                  if channel['slice_id'] == slice['slice_id']:
228                      reserved_channel_ids.append(channel['channel_id'])
229
230             for channel in all_channels:
231                  if channel['channel_id'] in reserved_channel_ids:
232                      channels.append(channel)
233         else:
234             channels = all_channels
235
236         rspec_channels = []
237         for channel in channels:
238             rspec_channel = Channel()
239             rspec_channel['channel_num'] = channel['channel']
240             rspec_channel['frequency'] = channel['frequency']
241             rspec_channel['standard'] = channel['modulation']
242             rspec_channel['component_id'] = channel_to_urn(self.driver.hrn, self.driver.testbedInfo['name'], channel['channel'])
243             rspec_channels.append(rspec_channel)
244         return rspec_channels
245
246
247     
248     def get_rspec(self, slice_xrn=None, version = None, options={}):
249
250         version_manager = VersionManager()
251         version = version_manager.get_version(version)
252
253         if not slice_xrn:
254             rspec_version = version_manager._get_version(version.type, version.version, 'ad')
255         else:
256             rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
257
258         slice, slivers = self.get_slice_and_slivers(slice_xrn)
259
260         rspec = RSpec(version=rspec_version, user_options=options)
261
262         if slice and 'expires' in slice:
263             rspec.xml.set('expires',  datetime_to_string(utcparse(slice['expires'])))
264
265         if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'leases':
266            nodes = self.get_nodes(slice_xrn, slice, slivers, options)
267            rspec.version.add_nodes(nodes)
268            # add sliver defaults
269            default_sliver = slivers.get(None, [])
270            if default_sliver:
271               default_sliver_attribs = default_sliver.get('tags', [])
272               for attrib in default_sliver_attribs:
273                   logger.info(attrib)
274                   rspec.version.add_default_sliver_attribute(attrib['tagname'], attrib['value'])
275            # add wifi channels
276            channels = self.get_channels(slice, options)
277            rspec.version.add_channels(channels)
278
279         if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'resources':
280            leases, channels = self.get_leases_and_channels(slice, slice_xrn)
281            rspec.version.add_leases(leases, channels)
282
283         return rspec.toxml()
284
285