2e59d2e0bb77ab067594c15e00976a4fd8f273cf
[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
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                  
167             # retreive slicename
168             for slc in slices:
169                  if slc['slice_id'] == channel['slice_id']:
170                      slicename = slc['slice_name']
171                      break
172
173             if slice_xrn:
174                 slice_urn = slice_xrn
175                 slice_hrn = urn_to_hrn(slice_urn)
176             else:
177                 slice_hrn = slicename_to_hrn(self.driver.hrn, self.driver.testbedInfo['name'], slicename)
178                 slice_urn = hrn_to_urn(slice_hrn, 'slice')
179
180             rspec_channel['slice_id'] = slice_urn
181             rspec_channels.append(rspec_channel)
182
183  
184         rspec_leases = []
185         for lease in leases:
186
187             rspec_lease = Lease()
188             
189             rspec_lease['lease_id'] = lease['reservation_id']
190             # retreive node name
191             for node in nodes:
192                  if node['node_id'] == lease['node_id']:
193                      nodename = node['hostname']
194                      break
195            
196             rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn, self.driver.testbedInfo['name'], nodename)
197             # retreive slicename
198             for slc in slices:
199                  if slc['slice_id'] == lease['slice_id']:
200                      slicename = slc['slice_name']
201                      break
202             
203             if slice_xrn:
204                 slice_urn = slice_xrn
205                 slice_hrn = urn_to_hrn(slice_urn)
206             else:
207                 slice_hrn = slicename_to_hrn(self.driver.hrn, self.driver.testbedInfo['name'], slicename)
208                 slice_urn = hrn_to_urn(slice_hrn, 'slice')
209
210             rspec_lease['slice_id'] = slice_urn
211             rspec_lease['start_time'] = lease['start_time']
212             rspec_lease['duration'] = (int(lease['end_time']) - int(lease['start_time'])) / int(grain)
213             rspec_leases.append(rspec_lease)
214
215         return (rspec_leases, rspec_channels)
216
217
218     def get_channels(self, slice=None, options={}):
219  
220         all_channels = self.driver.shell.getChannels({}, [])
221         channels = []
222         if slice:
223             reserved_channels = self.driver.shell.getReservedChannels()
224             reserved_channel_ids = []
225             for channel in reserved_channels:
226                  if channel['slice_id'] == slice['slice_id']:
227                      reserved_channel_ids.append(channel['channel_id'])
228
229             for channel in all_channels:
230                  if channel['channel_id'] in reserved_channel_ids:
231                      channels.append(channel)
232         else:
233             channels = all_channels
234
235         rspec_channels = []
236         for channel in channels:
237             rspec_channel = Channel()
238             rspec_channel['channel_num'] = channel['channel']
239             rspec_channel['frequency'] = channel['frequency']
240             rspec_channel['standard'] = channel['modulation']
241             rspec_channels.append(rspec_channel)
242         return rspec_channels
243
244
245     
246     def get_rspec(self, slice_xrn=None, version = None, options={}):
247
248         version_manager = VersionManager()
249         version = version_manager.get_version(version)
250
251         if not slice_xrn:
252             rspec_version = version_manager._get_version(version.type, version.version, 'ad')
253         else:
254             rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
255
256         slice, slivers = self.get_slice_and_slivers(slice_xrn)
257
258         rspec = RSpec(version=rspec_version, user_options=options)
259
260         if slice and 'expires' in slice:
261             rspec.xml.set('expires',  datetime_to_string(utcparse(slice['expires'])))
262
263         if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'leases':
264            nodes = self.get_nodes(slice_xrn, slice, slivers, options)
265            rspec.version.add_nodes(nodes)
266            # add sliver defaults
267            default_sliver = slivers.get(None, [])
268            if default_sliver:
269               default_sliver_attribs = default_sliver.get('tags', [])
270               for attrib in default_sliver_attribs:
271                   logger.info(attrib)
272                   rspec.version.add_default_sliver_attribute(attrib['tagname'], attrib['value'])
273            # add wifi channels
274            channels = self.get_channels(slice, options)
275            rspec.version.add_channels(channels)
276
277         if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'resources':
278            leases, channels = self.get_leases_and_channels(slice, slice_xrn)
279            rspec.version.add_leases(leases, channels)
280
281         return rspec.toxml()
282
283