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