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