Skip to content

Commit 1f7348f

Browse files
committed
Implemented feature to add new attributes to existing Openshift allocations
`validate_allocations` will now check if an Openshift allocation does not have a quota value set on either the Coldfront or Openshift side. In this case, it will set the default quota value for the allocation. Due to the complexity of Openstack quotas, this feature is only implemented for Openshift allocations for now.
1 parent 9242463 commit 1f7348f

File tree

2 files changed

+88
-15
lines changed

2 files changed

+88
-15
lines changed

src/coldfront_plugin_cloud/management/commands/validate_allocations.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ def sync_users(project_id, allocation, allocator, apply):
5252

5353
return failed_validation
5454

55+
@staticmethod
56+
def set_default_quota_on_allocation(allocation, allocator, coldfront_attr):
57+
uqm = tasks.UNIT_QUOTA_MULTIPLIERS[allocator.resource_type]
58+
value = allocation.quantity * uqm.get(coldfront_attr, 0)
59+
value += tasks.STATIC_QUOTA[allocator.resource_type].get(coldfront_attr, 0)
60+
utils.set_attribute_on_allocation(
61+
allocation, coldfront_attr, value
62+
)
63+
return value
64+
5565
def check_institution_specific_code(self, allocation, apply):
5666
attr = attributes.ALLOCATION_INSTITUTION_SPECIFIC_CODE
5767
isc = allocation.get_attribute(attr)
@@ -249,19 +259,37 @@ def handle(self, *args, **options):
249259
)
250260
msg = f"{msg} Attribute set to match current quota."
251261
logger.warning(msg)
252-
elif not (current_value == expected_value):
253-
msg = (
254-
f"Value for quota for {attr} = {current_value} does not match expected"
255-
f" value of {expected_value} on allocation {allocation_str}"
256-
)
257-
logger.warning(msg)
262+
else:
263+
# We just checked the case where the quota value is set in the cluster
264+
# but not in coldfront. This is the only case the cluster value is the
265+
# "source of truth" for the quota value
266+
# If the coldfront value is set, it is always the source of truth.
267+
# But first, we need to check if the quota value is set anywhere at all.
268+
# TODO (Quan): Refactor these if statements so that we can remove this comment block
269+
if current_value is None and expected_value is None:
270+
msg = (
271+
f"Value for quota for {attr} is not set anywhere"
272+
f" on allocation {allocation_str}"
273+
)
274+
logger.warning(msg)
258275

259-
if options["apply"]:
260-
try:
261-
allocator.set_quota(project_id)
262-
logger.warning(
263-
f"Quota for allocation {project_id} was out of date. Reapplied!"
264-
)
265-
except Exception as e:
266-
logger.error(f'setting openshift quota failed: {e}')
267-
continue
276+
if options["apply"]:
277+
expected_value = self.set_default_quota_on_allocation(allocation, allocator, attr)
278+
logger.warning(f"Added default quota for {attr} to allocation {allocation_str} to {expected_value}")
279+
280+
if not (current_value == expected_value):
281+
msg = (
282+
f"Value for quota for {attr} = {current_value} does not match expected"
283+
f" value of {expected_value} on allocation {allocation_str}"
284+
)
285+
logger.warning(msg)
286+
287+
if options["apply"]:
288+
try:
289+
allocator.set_quota(project_id)
290+
logger.warning(
291+
f"Quota for allocation {project_id} was out of date. Reapplied!"
292+
)
293+
except Exception as e:
294+
logger.error(f'setting openshift quota failed: {e}')
295+
continue

src/coldfront_plugin_cloud/tests/functional/openshift/test_allocation.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import time
33
import unittest
4+
from unittest import mock
45
import uuid
56

67
from coldfront_plugin_cloud import attributes, openshift, tasks, utils
@@ -214,3 +215,47 @@ def test_reactivate_allocation(self):
214215
})
215216

216217
allocator._get_role(user.username, project_id)
218+
219+
@mock.patch.object(
220+
tasks,
221+
"UNIT_QUOTA_MULTIPLIERS",
222+
{
223+
'openshift': {
224+
attributes.QUOTA_LIMITS_CPU: 1,
225+
}
226+
}
227+
)
228+
def test_allocation_new_attribute(self):
229+
"""When a new attribute is introduced, but pre-existing allocations don't have it"""
230+
user = self.new_user()
231+
project = self.new_project(pi=user)
232+
allocation = self.new_allocation(project, self.resource, 2)
233+
allocator = openshift.OpenShiftResourceAllocator(self.resource,
234+
allocation)
235+
236+
tasks.activate_allocation(allocation.pk)
237+
allocation.refresh_from_db()
238+
239+
project_id = allocation.get_attribute(attributes.ALLOCATION_PROJECT_ID)
240+
241+
self.assertEqual(allocation.get_attribute(attributes.QUOTA_LIMITS_CPU), 2 * 1)
242+
243+
quota = allocator.get_quota(project_id)
244+
self.assertEqual(quota, {
245+
"limits.cpu": "2",
246+
})
247+
248+
# Add a new attribute for Openshift
249+
tasks.UNIT_QUOTA_MULTIPLIERS['openshift'][attributes.QUOTA_LIMITS_MEMORY] = 4096
250+
251+
call_command('validate_allocations', apply=True)
252+
allocation.refresh_from_db()
253+
254+
self.assertEqual(allocation.get_attribute(attributes.QUOTA_LIMITS_CPU), 2 * 1)
255+
self.assertEqual(allocation.get_attribute(attributes.QUOTA_LIMITS_MEMORY), 2 * 4096)
256+
257+
quota = allocator.get_quota(project_id)
258+
self.assertEqual(quota, {
259+
"limits.cpu": "2",
260+
"limits.memory": "8Gi",
261+
})

0 commit comments

Comments
 (0)