Skip to content

Commit 11587a3

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 7e66279 commit 11587a3

File tree

2 files changed

+95
-13
lines changed

2 files changed

+95
-13
lines changed

src/coldfront_plugin_cloud/management/commands/validate_allocations.py

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ def sync_openshift_project_labels(project_id, allocator, apply):
8282
f"Labels updated for Openshift project {project_id}: {', '.join(missing_or_incorrect_labels)}"
8383
)
8484

85+
@staticmethod
86+
def set_default_quota_on_allocation(allocation, allocator, coldfront_attr):
87+
uqm = tasks.UNIT_QUOTA_MULTIPLIERS[allocator.resource_type]
88+
value = allocation.quantity * uqm.get(coldfront_attr, 0)
89+
value += tasks.STATIC_QUOTA[allocator.resource_type].get(coldfront_attr, 0)
90+
utils.set_attribute_on_allocation(allocation, coldfront_attr, value)
91+
return value
92+
8593
def check_institution_specific_code(self, allocation, apply):
8694
attr = attributes.ALLOCATION_INSTITUTION_SPECIFIC_CODE
8795
isc = allocation.get_attribute(attr)
@@ -299,19 +307,41 @@ def handle(self, *args, **options):
299307
)
300308
msg = f"{msg} Attribute set to match current quota."
301309
logger.warning(msg)
302-
elif not (current_value == expected_value):
303-
msg = (
304-
f"Value for quota for {attr} = {current_value} does not match expected"
305-
f" value of {expected_value} on allocation {allocation_str}"
306-
)
307-
logger.warning(msg)
310+
else:
311+
# We just checked the case where the quota value is set in the cluster
312+
# but not in coldfront. This is the only case the cluster value is the
313+
# "source of truth" for the quota value
314+
# If the coldfront value is set, it is always the source of truth.
315+
# But first, we need to check if the quota value is set anywhere at all.
316+
# TODO (Quan): Refactor these if statements so that we can remove this comment block
317+
if current_value is None and expected_value is None:
318+
msg = (
319+
f"Value for quota for {attr} is not set anywhere"
320+
f" on allocation {allocation_str}"
321+
)
322+
logger.warning(msg)
308323

309-
if options["apply"]:
310-
try:
311-
allocator.set_quota(project_id)
324+
if options["apply"]:
325+
expected_value = self.set_default_quota_on_allocation(
326+
allocation, allocator, attr
327+
)
312328
logger.warning(
313-
f"Quota for allocation {project_id} was out of date. Reapplied!"
329+
f"Added default quota for {attr} to allocation {allocation_str} to {expected_value}"
314330
)
315-
except Exception as e:
316-
logger.error(f"setting openshift quota failed: {e}")
317-
continue
331+
332+
if not (current_value == expected_value):
333+
msg = (
334+
f"Value for quota for {attr} = {current_value} does not match expected"
335+
f" value of {expected_value} on allocation {allocation_str}"
336+
)
337+
logger.warning(msg)
338+
339+
if options["apply"]:
340+
try:
341+
allocator.set_quota(project_id)
342+
logger.warning(
343+
f"Quota for allocation {project_id} was out of date. Reapplied!"
344+
)
345+
except Exception as e:
346+
logger.error(f"setting openshift quota failed: {e}")
347+
continue

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

Lines changed: 52 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
@@ -324,3 +325,54 @@ def test_create_incomplete(self):
324325
user.username, user.username
325326
)
326327
)
328+
329+
@mock.patch.object(
330+
tasks,
331+
"UNIT_QUOTA_MULTIPLIERS",
332+
{
333+
"openshift": {
334+
attributes.QUOTA_LIMITS_CPU: 1,
335+
}
336+
},
337+
)
338+
def test_allocation_new_attribute(self):
339+
"""When a new attribute is introduced, but pre-existing allocations don't have it"""
340+
user = self.new_user()
341+
project = self.new_project(pi=user)
342+
allocation = self.new_allocation(project, self.resource, 2)
343+
allocator = openshift.OpenShiftResourceAllocator(self.resource, allocation)
344+
345+
tasks.activate_allocation(allocation.pk)
346+
allocation.refresh_from_db()
347+
348+
project_id = allocation.get_attribute(attributes.ALLOCATION_PROJECT_ID)
349+
350+
self.assertEqual(allocation.get_attribute(attributes.QUOTA_LIMITS_CPU), 2 * 1)
351+
352+
quota = allocator.get_quota(project_id)
353+
self.assertEqual(
354+
quota,
355+
{
356+
"limits.cpu": "2",
357+
},
358+
)
359+
360+
# Add a new attribute for Openshift
361+
tasks.UNIT_QUOTA_MULTIPLIERS["openshift"][attributes.QUOTA_LIMITS_MEMORY] = 4096
362+
363+
call_command("validate_allocations", apply=True)
364+
allocation.refresh_from_db()
365+
366+
self.assertEqual(allocation.get_attribute(attributes.QUOTA_LIMITS_CPU), 2 * 1)
367+
self.assertEqual(
368+
allocation.get_attribute(attributes.QUOTA_LIMITS_MEMORY), 2 * 4096
369+
)
370+
371+
quota = allocator.get_quota(project_id)
372+
self.assertEqual(
373+
quota,
374+
{
375+
"limits.cpu": "2",
376+
"limits.memory": "8Gi",
377+
},
378+
)

0 commit comments

Comments
 (0)