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