Skip to content

Commit a86da68

Browse files
committed
Refactored validate_allocations to be resource-agnostic
Quota validation will now behave the same for both resource types. OpenStack's particular use of default quotas is reflected in a new test in `openstack/test_allocation.py` OpenStack integration code is slightly changed to better handle missing object storage quotas Much of the validation logic has been pushed into `base.py`, `openshift.py`, and `openstack.py`
1 parent 772cd9f commit a86da68

File tree

7 files changed

+265
-278
lines changed

7 files changed

+265
-278
lines changed

src/coldfront_plugin_cloud/base.py

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import abc
22
import functools
3+
import logging
34
from typing import NamedTuple
45

56
from coldfront.core.allocation import models as allocation_models
67
from 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

1115
class 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

Comments
 (0)