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