python3 - 2to3 + miscell obvious tweaks
[sfa.git] / sfa / dummy / dummyaggregate.py
1 #!/usr/bin/env python3
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.interface import Interface
14 from sfa.rspecs.elements.services import ServicesElement
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.version_manager import VersionManager
19
20 from sfa.dummy.dummyxrn import DummyXrn, hostname_to_urn, hrn_to_dummy_slicename, slicename_to_hrn
21
22 from sfa.storage.model import SliverAllocation
23 import time
24
25
26 class DummyAggregate:
27
28     def __init__(self, driver):
29         self.driver = driver
30
31     def get_slice_and_slivers(self, slice_xrn):
32         """
33         Returns a dict of slivers keyed on the sliver's node_id
34         """
35         slivers = {}
36         slice = None
37         if not slice_xrn:
38             return (slice, slivers)
39         slice_urn = hrn_to_urn(slice_xrn, 'slice')
40         slice_hrn, _ = urn_to_hrn(slice_xrn)
41         slice_name = hrn_to_dummy_slicename(slice_hrn)
42         slices = self.driver.shell.GetSlices({'slice_name': slice_name})
43         if not slices:
44             return (slice, slivers)
45         slice = slices[0]
46
47         # sort slivers by node id
48         slice_nodes = []
49         if 'node_ids' in list(slice.keys()):
50             slice_nodes = self.driver.shell.GetNodes(
51                 {'node_ids': slice['node_ids']})
52         for node in slice_nodes:
53             slivers[node['node_id']] = node
54
55         return (slice, slivers)
56
57     def get_nodes(self, options=None):
58         if options is None:
59             options = {}
60         filter = {}
61         nodes = self.driver.shell.GetNodes(filter)
62         return nodes
63
64     def get_slivers(self, urns, options=None):
65         if options is None:
66             options = {}
67         slice_names = set()
68         slice_ids = set()
69         node_ids = []
70         for urn in urns:
71             xrn = DummyXrn(xrn=urn)
72             if xrn.type == 'sliver':
73                  # id: slice_id-node_id
74                 try:
75                     sliver_id_parts = xrn.get_sliver_id_parts()
76                     slice_id = int(sliver_id_parts[0])
77                     node_id = int(sliver_id_parts[1])
78                     slice_ids.add(slice_id)
79                     node_ids.append(node_id)
80                 except ValueError:
81                     pass
82             else:
83                 slice_names.add(xrn.dummy_slicename())
84
85         filter = {}
86         if slice_names:
87             filter['slice_name'] = list(slice_names)
88         if slice_ids:
89             filter['slice_id'] = list(slice_ids)
90         # get slices
91         slices = self.driver.shell.GetSlices(filter)
92         if not slices:
93             return []
94         slice = slices[0]
95         slice['hrn'] = DummyXrn(auth=self.driver.hrn,
96                                 slicename=slice['slice_name']).hrn
97
98         # get sliver users
99         users = []
100         user_ids = []
101         for slice in slices:
102             if 'user_ids' in list(slice.keys()):
103                 user_ids.extend(slice['user_ids'])
104         if user_ids:
105             users = self.driver.shell.GetUsers({'user_ids': user_ids})
106
107         # construct user key info
108         users_list = []
109         for user in users:
110             name = user['email'][0:user['email'].index('@')]
111             user = {
112                 'login': slice['slice_name'],
113                 'user_urn': Xrn('%s.%s' % (self.driver.hrn, name), type='user').urn,
114                 'keys': user['keys']
115             }
116             users_list.append(user)
117
118         if node_ids:
119             node_ids = [
120                 node_id for node_id in node_ids if node_id in slice['node_ids']]
121             slice['node_ids'] = node_ids
122         nodes_dict = self.get_slice_nodes(slice, options)
123         slivers = []
124         for node in list(nodes_dict.values()):
125             node.update(slice)
126             sliver_hrn = '%s.%s-%s' % (self.driver.hrn,
127                                        slice['slice_id'], node['node_id'])
128             node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn
129             node['urn'] = node['sliver_id']
130             node['services_user'] = users
131             slivers.append(node)
132         return slivers
133
134     def node_to_rspec_node(self, node, options=None):
135         if options is None:
136             options = {}
137         rspec_node = NodeElement()
138         site = self.driver.testbedInfo
139         rspec_node['component_id'] = hostname_to_urn(
140             self.driver.hrn, site['name'], node['hostname'])
141         rspec_node['component_name'] = node['hostname']
142         rspec_node['component_manager_id'] = Xrn(
143             self.driver.hrn, 'authority+cm').get_urn()
144         rspec_node['authority_id'] = hrn_to_urn(DummyXrn.site_hrn(
145             self.driver.hrn, site['name']), 'authority+sa')
146         # distinguish between Shared and Reservable nodes
147         rspec_node['exclusive'] = 'false'
148
149         rspec_node['hardware_types'] = [HardwareType({'name': 'dummy-pc'}),
150                                         HardwareType({'name': 'pc'})]
151         if site['longitude'] and site['latitude']:
152             location = Location({'longitude': site['longitude'], 'latitude': site[
153                                 'latitude'], 'country': 'unknown'})
154             rspec_node['location'] = location
155         return rspec_node
156
157     def sliver_to_rspec_node(self, sliver, sliver_allocations):
158         rspec_node = self.node_to_rspec_node(sliver)
159         rspec_node['expires'] = datetime_to_string(utcparse(sliver['expires']))
160         # add sliver info
161         rspec_sliver = Sliver({'sliver_id': sliver['urn'],
162                                'name': sliver['slice_name'],
163                                'type': 'dummy-vserver',
164                                'tags': []})
165         rspec_node['sliver_id'] = rspec_sliver['sliver_id']
166         if sliver['urn'] in sliver_allocations:
167             rspec_node['client_id'] = sliver_allocations[
168                 sliver['urn']].client_id
169             if sliver_allocations[sliver['urn']].component_id:
170                 rspec_node['component_id'] = sliver_allocations[
171                     sliver['urn']].component_id
172         rspec_node['slivers'] = [rspec_sliver]
173
174         # slivers always provide the ssh service
175         login = Login({'authentication': 'ssh-keys',
176                        'hostname': sliver['hostname'],
177                        'port': '22',
178                        'username': sliver['slice_name'],
179                        'login': sliver['slice_name']
180                        })
181         return rspec_node
182
183     def get_slice_nodes(self, slice, options=None):
184         if options is None:
185             options = {}
186         nodes_dict = {}
187         filter = {}
188         if slice and slice.get('node_ids'):
189             filter['node_ids'] = slice['node_ids']
190         else:
191             # there are no nodes to look up
192             return nodes_dict
193         nodes = self.driver.shell.GetNodes(filter)
194         for node in nodes:
195             nodes_dict[node['node_id']] = node
196         return nodes_dict
197
198     def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations=None):
199         if sliver_allocations is None:
200             sliver_allocations = {}
201         if rspec_node['sliver_id'] in sliver_allocations:
202             # set sliver allocation and operational status
203             sliver_allocation = sliver_allocations[rspec_node['sliver_id']]
204             if sliver_allocation:
205                 allocation_status = sliver_allocation.allocation_state
206                 if allocation_status == 'geni_allocated':
207                     op_status = 'geni_pending_allocation'
208                 elif allocation_status == 'geni_provisioned':
209                     op_status = 'geni_ready'
210                 else:
211                     op_status = 'geni_unknown'
212             else:
213                 allocation_status = 'geni_unallocated'
214         else:
215             allocation_status = 'geni_unallocated'
216             op_status = 'geni_failed'
217         # required fields
218         geni_sliver = {'geni_sliver_urn': rspec_node['sliver_id'],
219                        'geni_expires': rspec_node['expires'],
220                        'geni_allocation_status': allocation_status,
221                        'geni_operational_status': op_status,
222                        'geni_error': '',
223                        }
224         return geni_sliver
225
226     def list_resources(self, version=None, options=None):
227         if options is None:
228             options = {}
229
230         version_manager = VersionManager()
231         version = version_manager.get_version(version)
232         rspec_version = version_manager._get_version(
233             version.type, version.version, 'ad')
234         rspec = RSpec(version=rspec_version, user_options=options)
235
236         # get nodes
237         nodes = self.get_nodes(options)
238         nodes_dict = {}
239         for node in nodes:
240             nodes_dict[node['node_id']] = node
241
242         # convert nodes to rspec nodes
243         rspec_nodes = []
244         for node in nodes:
245             rspec_node = self.node_to_rspec_node(node)
246             rspec_nodes.append(rspec_node)
247         rspec.version.add_nodes(rspec_nodes)
248
249         return rspec.toxml()
250
251     def describe(self, urns, version=None, options=None):
252         if options is None:
253             options = {}
254         version_manager = VersionManager()
255         version = version_manager.get_version(version)
256         rspec_version = version_manager._get_version(
257             version.type, version.version, 'manifest')
258         rspec = RSpec(version=rspec_version, user_options=options)
259
260         # get slivers
261         geni_slivers = []
262         slivers = self.get_slivers(urns, options)
263         if slivers:
264             rspec_expires = datetime_to_string(utcparse(slivers[0]['expires']))
265         else:
266             rspec_expires = datetime_to_string(utcparse(time.time()))
267         rspec.xml.set('expires',  rspec_expires)
268
269         # lookup the sliver allocations
270         geni_urn = urns[0]
271         sliver_ids = [sliver['sliver_id'] for sliver in slivers]
272         constraint = SliverAllocation.sliver_id.in_(sliver_ids)
273         sliver_allocations = self.driver.api.dbsession().query(
274             SliverAllocation).filter(constraint)
275         sliver_allocation_dict = {}
276         for sliver_allocation in sliver_allocations:
277             geni_urn = sliver_allocation.slice_urn
278             sliver_allocation_dict[
279                 sliver_allocation.sliver_id] = sliver_allocation
280
281         # add slivers
282         nodes_dict = {}
283         for sliver in slivers:
284             nodes_dict[sliver['node_id']] = sliver
285         rspec_nodes = []
286         for sliver in slivers:
287             rspec_node = self.sliver_to_rspec_node(
288                 sliver, sliver_allocation_dict)
289             rspec_nodes.append(rspec_node)
290             geni_sliver = self.rspec_node_to_geni_sliver(
291                 rspec_node, sliver_allocation_dict)
292             geni_slivers.append(geni_sliver)
293         rspec.version.add_nodes(rspec_nodes)
294
295         return {'geni_urn': geni_urn,
296                 'geni_rspec': rspec.toxml(),
297                 'geni_slivers': geni_slivers}