python3 - 2to3 + miscell obvious tweaks
[sfa.git] / sfa / dummy / dummyslices.py
1 import time
2 from collections import defaultdict
3
4 from sfa.util.sfatime import utcparse, datetime_to_epoch
5 from sfa.util.sfalogging import logger
6 from sfa.util.xrn import Xrn, get_leaf, get_authority, urn_to_hrn
7
8 from sfa.rspecs.rspec import RSpec
9 from sfa.storage.model import SliverAllocation
10
11 from sfa.dummy.dummyxrn import DummyXrn, hrn_to_dummy_slicename
12
13 MAXINT = 2**31 - 1
14
15
16 class DummySlices:
17
18     def __init__(self, driver):
19         self.driver = driver
20
21     def get_slivers(self, xrn, node=None):
22         hrn, type = urn_to_hrn(xrn)
23
24         slice_name = hrn_to_dummy_slicename(hrn)
25
26         slices = self.driver.shell.GetSlices({'slice_name': slice_name})
27         slice = slices[0]
28         # Build up list of users and slice attributes
29         user_ids = slice['user_ids']
30         # Get user information
31         all_users_list = self.driver.shell.GetUsers({'user_id': user_ids})
32         all_users = {}
33         for user in all_users_list:
34             all_users[user['user_id']] = user
35
36         # Build up list of keys
37         all_keys = set()
38         for user in all_users_list:
39             all_keys.extend(user['keys'])
40
41         slivers = []
42         for slice in slices:
43             keys = all_keys
44             # XXX Sanity check; though technically this should be a system invariant
45             # checked with an assertion
46             if slice['expires'] > MAXINT:
47                 slice['expires'] = MAXINT
48
49             slivers.append({
50                 'hrn': hrn,
51                 'name': slice['name'],
52                 'slice_id': slice['slice_id'],
53                 'expires': slice['expires'],
54                 'keys': keys,
55             })
56
57         return slivers
58
59     def verify_slice_nodes(self, slice_urn, slice, rspec_nodes):
60
61         slivers = {}
62         for node in rspec_nodes:
63             hostname = node.get('component_name')
64             client_id = node.get('client_id')
65             component_id = node.get('component_id').strip()
66             if hostname:
67                 hostname = hostname.strip()
68             elif component_id:
69                 hostname = xrn_to_hostname(component_id)
70             if hostname:
71                 slivers[hostname] = {
72                     'client_id': client_id, 'component_id': component_id}
73         all_nodes = self.driver.shell.GetNodes()
74         requested_slivers = []
75         for node in all_nodes:
76             if node['hostname'] in list(slivers.keys()):
77                 requested_slivers.append(node['node_id'])
78
79         if 'node_ids' not in list(slice.keys()):
80             slice['node_ids'] = []
81         nodes = self.driver.shell.GetNodes({'node_ids': slice['node_ids']})
82         current_slivers = [node['node_id'] for node in nodes]
83
84         # remove nodes not in rspec
85         deleted_nodes = list(
86             set(current_slivers).difference(requested_slivers))
87
88         # add nodes from rspec
89         added_nodes = list(set(requested_slivers).difference(current_slivers))
90
91         try:
92             self.driver.shell.AddSliceToNodes(
93                 {'slice_id': slice['slice_id'], 'node_ids': added_nodes})
94             self.driver.shell.DeleteSliceFromNodes(
95                 {'slice_id': slice['slice_id'], 'node_ids': deleted_nodes})
96
97         except:
98             logger.log_exc('Failed to add/remove slice from nodes')
99
100         slices = self.driver.shell.GetSlices(
101             {'slice_name': slice['slice_name']})
102         resulting_nodes = self.driver.shell.GetNodes(
103             {'node_ids': slices[0]['node_ids']})
104
105         # update sliver allocations
106         for node in resulting_nodes:
107             client_id = slivers[node['hostname']]['client_id']
108             component_id = slivers[node['hostname']]['component_id']
109             sliver_hrn = '%s.%s-%s' % (self.driver.hrn,
110                                        slice['slice_id'], node['node_id'])
111             sliver_id = Xrn(sliver_hrn, type='sliver').urn
112             record = SliverAllocation(sliver_id=sliver_id, client_id=client_id,
113                                       component_id=component_id,
114                                       slice_urn=slice_urn,
115                                       allocation_state='geni_allocated')
116             record.sync(self.driver.api.dbsession())
117         return resulting_nodes
118
119     def verify_slice(self, slice_hrn, slice_record, expiration, options=None):
120         if options is None:
121             options = {}
122         slicename = hrn_to_dummy_slicename(slice_hrn)
123         parts = slicename.split("_")
124         login_base = parts[0]
125         slices = self.driver.shell.GetSlices({'slice_name': slicename})
126         if not slices:
127             slice = {'slice_name': slicename}
128             # add the slice
129             slice['slice_id'] = self.driver.shell.AddSlice(slice)
130             slice['node_ids'] = []
131             slice['user_ids'] = []
132         else:
133             slice = slices[0]
134             if slice_record and slice_record.get('expires'):
135                 requested_expires = int(datetime_to_epoch(
136                     utcparse(slice_record['expires'])))
137                 if requested_expires and slice['expires'] != requested_expires:
138                     self.driver.shell.UpdateSlice(
139                         {'slice_id': slice['slice_id'], 'fields': {'expires': expiration}})
140
141         return slice
142
143     def verify_users(self, slice_hrn, slice_record, users, options=None):
144         if options is None:
145             options = {}
146         slice_name = hrn_to_dummy_slicename(slice_hrn)
147         users_by_email = {}
148         for user in users:
149             user['urn'] = user['urn'].lower()
150             hrn, type = urn_to_hrn(user['urn'])
151             username = get_leaf(hrn)
152             user['username'] = username
153
154             if 'email' in user:
155                 user['email'] = user['email'].lower()
156                 users_by_email[user['email']] = user
157
158         # start building a list of existing users
159         existing_users_by_email = {}
160         existing_slice_users_by_email = {}
161         existing_users = self.driver.shell.GetUsers()
162         existing_slice_users_ids = self.driver.shell.GetSlices(
163             {'slice_name': slice_name})[0]['user_ids']
164         for user in existing_users:
165             existing_users_by_email[user['email']] = user
166             if user['user_id'] in existing_slice_users_ids:
167                 existing_slice_users_by_email[user['email']] = user
168
169         add_users_by_email = set(users_by_email).difference(
170             existing_slice_user_by_email)
171         delete_users_by_email = set(
172             existing_slice_user_by_email).difference(users_by_email)
173         try:
174             for user in add_users_by_email:
175                 self.driver.shell.AddUser()
176         except:
177             pass
178
179     def verify_keys(self, old_users, new_users, options=None):
180         if options is None:
181             options = {}
182         # existing keys
183         existing_keys = []
184         for user in old_users:
185             existing_keys.append(user['keys'])
186         userdict = {}
187         for user in old_users:
188             userdict[user['email']] = user
189
190         # add new keys
191         requested_keys = []
192         updated_users = []
193         for user in new_users:
194             user_keys = user.get('keys', [])
195             updated_users.append(user)
196             for key_string in user_keys:
197                 requested_keys.append(key_string)
198                 if key_string not in existing_keys:
199                     key = key_string
200                     try:
201                         self.driver.shell.AddUserKey(
202                             {'user_id': user['user_id'], 'key': key})
203
204                     except:
205                         pass
206         # remove old keys (only if we are not appending)
207         append = options.get('append', True)
208         if append == False:
209             removed_keys = set(existing_keys).difference(requested_keys)
210             for key in removed_keys:
211                 try:
212                     self.driver.shell.DeleteKey({'key': key})
213                 except:
214                     pass