Nitos: Enforce slice check within get_leases_and_channels
[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, slice_xrn=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_xrn and not slice:
140             return ([], [])
141
142         if slice:
143             all_leases = []
144             all_leases.extend(leases)
145             all_reserved_channels = []
146             all_reserved_channels.extend(reserved_channels)
147             for lease in all_leases:
148                  if lease['slice_id'] != slice['slice_id']:
149                      leases.remove(lease)
150             for channel in all_reserved_channels:
151                  if channel['slice_id'] != slice['slice_id']:
152                      reserved_channels.remove(channel)
153
154         rspec_channels = []
155         for channel in reserved_channels:
156              
157             rspec_channel = {}
158             #retrieve channel number  
159             for chl in channels:
160                  if chl['channel_id'] == channel['channel_id']:
161                      channel_number = chl['channel']
162                      break
163
164             rspec_channel['channel_num'] = channel_number
165             rspec_channel['start_time'] = channel['start_time']
166             rspec_channel['duration'] = (int(channel['end_time']) - int(channel['start_time'])) / int(grain)
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             slice_hrn = slicename_to_hrn(self.driver.hrn, self.driver.testbedInfo['name'], slicename)
175             slice_urn = hrn_to_urn(slice_hrn, 'slice')
176             rspec_channel['slice_id'] = slice_urn
177             rspec_channels.append(rspec_channel)
178
179  
180         rspec_leases = []
181         for lease in leases:
182
183             rspec_lease = Lease()
184             
185             rspec_lease['lease_id'] = lease['reservation_id']
186             # retreive node name
187             for node in nodes:
188                  if node['node_id'] == lease['node_id']:
189                      nodename = node['hostname']
190                      break
191            
192             rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn, self.driver.testbedInfo['name'], nodename)
193             # retreive slicename
194             for slc in slices:
195                  if slc['slice_id'] == lease['slice_id']:
196                      slicename = slc['slice_name']
197                      break
198             
199             slice_hrn = slicename_to_hrn(self.driver.hrn, self.driver.testbedInfo['name'], slicename)
200             slice_urn = hrn_to_urn(slice_hrn, 'slice')
201             rspec_lease['slice_id'] = slice_urn
202             rspec_lease['start_time'] = lease['start_time']
203             rspec_lease['duration'] = (int(lease['end_time']) - int(lease['start_time'])) / int(grain)
204             rspec_leases.append(rspec_lease)
205
206         return (rspec_leases, rspec_channels)
207
208
209     def get_channels(self, slice=None, options={}):
210  
211         all_channels = self.driver.shell.getChannels({}, [])
212         channels = []
213         if slice:
214             reserved_channels = self.driver.shell.getReservedChannels()
215             reserved_channel_ids = []
216             for channel in reserved_channels:
217                  if channel['slice_id'] == slice['slice_id']:
218                      reserved_channel_ids.append(channel['channel_id'])
219
220             for channel in all_channels:
221                  if channel['channel_id'] in reserved_channel_ids:
222                      channels.append(channel)
223         else:
224             channels = all_channels
225
226         rspec_channels = []
227         for channel in channels:
228             rspec_channel = Channel()
229             rspec_channel['channel_num'] = channel['channel']
230             rspec_channel['frequency'] = channel['frequency']
231             rspec_channel['standard'] = channel['modulation']
232             rspec_channels.append(rspec_channel)
233         return rspec_channels
234
235
236     
237     def get_rspec(self, slice_xrn=None, version = None, options={}):
238
239         version_manager = VersionManager()
240         version = version_manager.get_version(version)
241
242         if not slice_xrn:
243             rspec_version = version_manager._get_version(version.type, version.version, 'ad')
244         else:
245             rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
246
247         slice, slivers = self.get_slice_and_slivers(slice_xrn)
248
249         rspec = RSpec(version=rspec_version, user_options=options)
250
251         if slice and 'expires' in slice:
252             rspec.xml.set('expires',  datetime_to_string(utcparse(slice['expires'])))
253
254         if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'leases':
255            nodes = self.get_nodes(slice_xrn, slice, slivers, options)
256            rspec.version.add_nodes(nodes)
257            # add sliver defaults
258            default_sliver = slivers.get(None, [])
259            if default_sliver:
260               default_sliver_attribs = default_sliver.get('tags', [])
261               for attrib in default_sliver_attribs:
262                   logger.info(attrib)
263                   rspec.version.add_default_sliver_attribute(attrib['tagname'], attrib['value'])
264            # add wifi channels
265            channels = self.get_channels(slice, options)
266            rspec.version.add_channels(channels)
267
268         if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'resources':
269            leases, channels = self.get_leases_and_channels(slice, slice_xrn)
270            rspec.version.add_leases(leases, channels)
271
272         return rspec.toxml()
273
274