11import abc
22import functools
3+ import logging
34from typing import NamedTuple
45
56from coldfront .core .allocation import models as allocation_models
67from coldfront .core .resource import models as resource_models
78
8- from coldfront_plugin_cloud import attributes
9+ from coldfront_plugin_cloud import attributes , tasks , utils
10+
11+
12+ logger = logging .getLogger (__name__ )
913
1014
1115class ResourceAllocator (abc .ABC ):
@@ -30,6 +34,91 @@ def get_or_create_federated_user(self, username):
3034 user = self .create_federated_user (username )
3135 return user
3236
37+ def set_default_quota_on_allocation (self , coldfront_attr ):
38+ uqm = tasks .UNIT_QUOTA_MULTIPLIERS [self .resource_type ]
39+ value = self .allocation .quantity * uqm .get (coldfront_attr , 0 )
40+ value += tasks .STATIC_QUOTA [self .resource_type ].get (coldfront_attr , 0 )
41+ utils .set_attribute_on_allocation (self .allocation , coldfront_attr , value )
42+ return value
43+
44+ def set_users (self , project_id , apply ):
45+ coldfront_users = allocation_models .AllocationUser .objects .filter (
46+ allocation = self .allocation , status__name = "Active"
47+ )
48+ allocation_users = self .get_users (project_id )
49+ failed_validation = False
50+
51+ # Create users that exist in coldfront but not in the resource
52+ for coldfront_user in coldfront_users :
53+ if coldfront_user .user .username not in allocation_users :
54+ failed_validation = True
55+ logger .info (
56+ f"{ coldfront_user .user .username } is not part of { project_id } "
57+ )
58+ if apply :
59+ tasks .add_user_to_allocation (coldfront_user .pk )
60+
61+ # remove users that are in the resource but not in coldfront
62+ users = set (
63+ [coldfront_user .user .username for coldfront_user in coldfront_users ]
64+ )
65+ for allocation_user in allocation_users :
66+ if allocation_user not in users :
67+ failed_validation = True
68+ logger .info (
69+ f"{ allocation_user } exists in the resource { project_id } but not in coldfront"
70+ )
71+ if apply :
72+ self .remove_role_from_user (allocation_user , project_id )
73+
74+ return failed_validation
75+
76+ def check_and_apply_quota_attr (
77+ self , project_id , attr , expected_quota , current_quota , apply
78+ ):
79+ if current_quota is None and expected_quota is None :
80+ msg = (
81+ f"Value for quota for { attr } is not set anywhere"
82+ f" on { self .allocation_str } "
83+ )
84+
85+ if apply :
86+ expected_quota = self .set_default_quota_on_allocation (attr )
87+ msg = f"Added default quota for { attr } to { self .allocation_str } to { expected_quota } "
88+ logger .info (msg )
89+ elif current_quota is not None and expected_quota is None :
90+ msg = (
91+ f'Attribute "{ attr } " expected on { self .allocation_str } but not set.'
92+ f" Current quota is { current_quota } ."
93+ )
94+
95+ if apply :
96+ utils .set_attribute_on_allocation (self .allocation , attr , current_quota )
97+ expected_quota = (
98+ current_quota # To pass `current_quota != expected_quota` check
99+ )
100+ msg = f"{ msg } Attribute set to match current quota."
101+ logger .info (msg )
102+
103+ if current_quota != expected_quota :
104+ msg = (
105+ f"Value for quota for { attr } = { current_quota } does not match expected"
106+ f" value of { expected_quota } on { self .allocation_str } "
107+ )
108+ logger .info (msg )
109+
110+ if apply :
111+ try :
112+ self .set_quota (project_id )
113+ logger .info (f"Quota for { project_id } was out of date. Reapplied!" )
114+ except Exception as e :
115+ logger .info (f"setting openshift quota failed: { e } " )
116+ return
117+
118+ @functools .cached_property
119+ def allocation_str (self ):
120+ return f'allocation { self .allocation .pk } of project "{ self .allocation .project .title } "'
121+
33122 @functools .cached_property
34123 def auth_url (self ):
35124 return self .resource .get_attribute (attributes .RESOURCE_AUTH_URL ).rstrip ("/" )
@@ -39,7 +128,11 @@ def member_role_name(self):
39128 return self .resource .get_attribute (attributes .RESOURCE_ROLE ) or "member"
40129
41130 @abc .abstractmethod
42- def set_project_configuration (self , project_id , dry_run = False ):
131+ def set_project_configuration (self , project_id , apply = True ):
132+ pass
133+
134+ @abc .abstractmethod
135+ def get_project (self , project_id ):
43136 pass
44137
45138 @abc .abstractmethod
@@ -70,6 +163,10 @@ def get_quota(self, project_id):
70163 def create_federated_user (self , unique_id ):
71164 pass
72165
166+ @abc .abstractmethod
167+ def get_users (self , unique_id ):
168+ pass
169+
73170 @abc .abstractmethod
74171 def get_federated_user (self , unique_id ):
75172 pass
0 commit comments