From 7a9138ce5c6bacd00dcffcc33940399167312d48 Mon Sep 17 00:00:00 2001 From: Oliver Stolpe Date: Wed, 7 Aug 2024 14:07:02 +0200 Subject: [PATCH] fix: handle corner cases for quota emails (#319) --- adminsec/tests/test_tasks.py | 54 ++++++++++++++++++++++++++++++++++++ usersec/models.py | 21 ++++++++++++-- usersec/tests/test_models.py | 34 +++++++++++++++++++++++ 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/adminsec/tests/test_tasks.py b/adminsec/tests/test_tasks.py index d5909c2..3b569ee 100644 --- a/adminsec/tests/test_tasks.py +++ b/adminsec/tests/test_tasks.py @@ -353,6 +353,60 @@ def test_send_quota_email_yellow(self): send_quota_email_yellow() self.assertEqual(len(mail.outbox), 1) + @override_settings(SEND_QUOTA_EMAILS=True) + def test_send_quota_email_red_quota_zero(self): + # From 100% to 0% used -> one email less expected + self.hpc_owner.resources_requested = {TIER_USER_HOME: 0} + self.hpc_owner.resources_used = {TIER_USER_HOME: 0} + self.hpc_owner.save() + send_quota_email_red() + self.assertEqual(len(mail.outbox), 1) + + @override_settings(SEND_QUOTA_EMAILS=True) + def test_send_quota_email_yellow_quota_zero(self): + # From 100% to 0% used -> not affected + self.hpc_owner.resources_requested = {TIER_USER_HOME: 0} + self.hpc_owner.resources_used = {TIER_USER_HOME: 0} + self.hpc_owner.save() + send_quota_email_yellow() + self.assertEqual(len(mail.outbox), 1) + + @override_settings(SEND_QUOTA_EMAILS=True) + def test_send_quota_email_green_quota_zero(self): + # From 100% to 0% used -> one email more expected + self.hpc_owner.resources_requested = {TIER_USER_HOME: 0} + self.hpc_owner.resources_used = {TIER_USER_HOME: 0} + self.hpc_owner.save() + _send_quota_email(HpcQuotaStatus.GREEN) + self.assertEqual(len(mail.outbox), 2) + + @override_settings(SEND_QUOTA_EMAILS=True) + def test_send_quota_email_red_quota_missing(self): + # From 100% to missing -> one email less expected + self.hpc_owner.resources_requested = {} + self.hpc_owner.resources_used = {} + self.hpc_owner.save() + send_quota_email_red() + self.assertEqual(len(mail.outbox), 1) + + @override_settings(SEND_QUOTA_EMAILS=True) + def test_send_quota_email_yellow_quota_missing(self): + # From 100% to missing -> not affected + self.hpc_owner.resources_requested = {} + self.hpc_owner.resources_used = {} + self.hpc_owner.save() + send_quota_email_yellow() + self.assertEqual(len(mail.outbox), 1) + + @override_settings(SEND_QUOTA_EMAILS=True) + def test_send_quota_email_green_quota_missing(self): + # From 100% to missing -> not affected + self.hpc_owner.resources_requested = {} + self.hpc_owner.resources_used = {} + self.hpc_owner.save() + _send_quota_email(HpcQuotaStatus.GREEN) + self.assertEqual(len(mail.outbox), 1) + class DisableUsersWithoutConsent(TestCase): """Tests for disable_users_without_consent.""" diff --git a/usersec/models.py b/usersec/models.py index b53aee9..c3ebb86 100644 --- a/usersec/models.py +++ b/usersec/models.py @@ -304,6 +304,15 @@ def generate_quota_report(self): requested = set((self.resources_requested or {}).keys()) used = set((self.resources_used or {}).keys()) available = requested & used + if not available: + return { + "used": {}, + "requested": {}, + "percentage": {}, + "status": {}, + "folders": {}, + "warnings": ["No resources available."], + } folders = ( {TIER_USER_HOME: self.home_directory} if isinstance(self, get_model(APP_NAME, "HpcUser")) @@ -331,9 +340,15 @@ def generate_quota_report(self): for key in available: used_val = self.resources_used.get(key) requested_val = self.resources_requested.get(key) - result["percentage"][key] = round( - (100 * used_val / requested_val) if not requested_val == 0 else 0 - ) + + if requested_val == 0 or used_val == 0: + # if requested_val is 0, CEPHFS provides unlimited quota => status always green + # if used_val is 0, the user has not used any resources => cut short + result["percentage"][key] = 0 + result["status"][key] = HpcQuotaStatus.GREEN + continue + + result["percentage"][key] = round(100 * used_val / requested_val) if used_val >= requested_val: result["status"][key] = HpcQuotaStatus.RED diff --git a/usersec/tests/test_models.py b/usersec/tests/test_models.py index 019ca6a..a5a6cc7 100644 --- a/usersec/tests/test_models.py +++ b/usersec/tests/test_models.py @@ -506,6 +506,40 @@ def test_generate_quota_report_red(self): self.assertDictEqual(user.generate_quota_report(), expected) + def test_generate_quota_report_zero_quota(self): + user = self.factory( + resources_requested={TIER_USER_HOME: 0}, + resources_used={TIER_USER_HOME: 0}, + home_directory="/home/users", + ) + expected = { + "used": {TIER_USER_HOME: 0}, + "requested": {TIER_USER_HOME: 0}, + "percentage": {TIER_USER_HOME: 0}, + "status": {TIER_USER_HOME: HpcQuotaStatus.GREEN}, + "folders": {TIER_USER_HOME: "/home/users"}, + "warnings": [], + } + + self.assertDictEqual(user.generate_quota_report(), expected) + + def test_generate_quota_report_no_resources(self): + user = self.factory( + resources_requested={}, + resources_used={}, + home_directory="/home/users", + ) + expected = { + "used": {}, + "requested": {}, + "percentage": {}, + "status": {}, + "folders": {}, + "warnings": ["No resources available."], + } + + self.assertDictEqual(user.generate_quota_report(), expected) + def test_parse_email(self): email = parse_email("valid@example.com") self.assertEqual(email, "valid@example.com")