diff --git a/coldfront/core/utils/management/commands/add_scheduled_tasks.py b/coldfront/core/utils/management/commands/add_scheduled_tasks.py index 108baf5fc4..9a24a26b34 100644 --- a/coldfront/core/utils/management/commands/add_scheduled_tasks.py +++ b/coldfront/core/utils/management/commands/add_scheduled_tasks.py @@ -25,7 +25,9 @@ def handle(self, *args, **options): # if plugins are installed, add their tasks kwargs = {"repeats": -1,} plugins_tasks = { - 'fasrc': ['id_import_allocations', 'import_quotas', 'pull_resource_data'], + 'fasrc': [ + 'id_import_allocations', 'import_quotas', 'pull_resource_data', 'run_ifx_updates' + ], 'sftocf': ['import_allocation_filepaths', 'pull_sf_push_cf', 'update_zones'], # 'lfs': ['pull_lfs_filesystem_stats'], 'ldap': ['update_group_membership_ldap', 'id_add_projects'], diff --git a/coldfront/plugins/fasrc/tasks.py b/coldfront/plugins/fasrc/tasks.py index 1c63b37ec7..9114465699 100644 --- a/coldfront/plugins/fasrc/tasks.py +++ b/coldfront/plugins/fasrc/tasks.py @@ -1,7 +1,15 @@ from coldfront.plugins.fasrc.utils import pull_push_quota_data import logging -from django.core import management +import io +import traceback +from contextlib import redirect_stdout, redirect_stderr +from django.core.management import call_command +from django.core.mail import send_mail + +from coldfront.core.utils.common import import_from_settings + +logger = logging.getLogger('coldfront.run_ifx_updates') def import_quotas(volumes=None): """ @@ -12,15 +20,92 @@ def import_quotas(volumes=None): ---------- volumes : string of volume names separated by commas. Optional, default None """ - logger = logging.getLogger('coldfront.import_quotas') if volumes: volumes = volumes.split(",") pull_push_quota_data() def id_import_allocations(): """ID and import new allocations using ATT and Starfish data""" - management.call_command('id_import_new_allocations') + call_command('id_import_new_allocations') def pull_resource_data(): - management.call_command('pull_resource_data') + call_command('pull_resource_data') + +def run_ifx_updates(emails=None): + out = io.StringIO() + err = io.StringIO() + + success = True + exception_info = [] + + with redirect_stdout(out), redirect_stderr(err): + print("=== Starting coldfront updates ===") + try: + print("=== Starting updateOrganizations ===") + call_command( + "updateOrganizations", "-t", "Harvard,Research Computing Storage Billing" + ) + print("=== updateOrganizations completed successfully ===") + except Exception as e: + success = False + exception_info.append(("=== updateOrganizations EXCEPTION OCCURRED ===")) + exception_info.append(traceback.format_exc()) + except SystemExit as e: + success = False + exception_info.append(f"updateOrganizations exited with code {e.code}") + try: + print("=== Starting updateApplicationUsers ===") + call_command("updateApplicationUsers") + print("=== updateApplicationUsers completed successfully ===") + except Exception as e: + success = False + exception_info.append(("=== updateApplicationUsers EXCEPTION OCCURRED ===")) + exception_info.append(traceback.format_exc()) + except SystemExit as e: + success = False + exception_info.append(f"updateApplicationUsers exited with code {e.code}") + try: + print("=== Starting updateUserAccounts ===") + call_command("updateUserAccounts") + print("=== updateUserAccounts completed successfully ===") + except Exception as e: + success = False + exception_info.append(("=== updateOrganizations EXCEPTION OCCURRED ===")) + exception_info.append(traceback.format_exc()) + except SystemExit as e: + success = False + exception_info.append(f"updateUserAccounts exited with code {e.code}") + print("=== All commands completed (with errors)" if not success + else "=== All commands completed successfully ===") + + stdout_content = out.getvalue() + stderr_content = err.getvalue() + + subject_status = "SUCCESS" if success else "FAILURE" + subject = f"coldfront ifx update [{subject_status}]" + + body_parts = [ + "This is the output from the scheduled coldfront update.\n", + "=== STDOUT ===", + stdout_content or "(no stdout output)", + "\n=== STDERR ===", + stderr_content or "(no stderr output)", + ] + if exception_info: + body_parts.append("\n=== EXIT/EXCEPTION INFO ===") + body_parts.extend(exception_info) + + body = "\n".join(body_parts) + if emails: + send_mail( + subject=subject, + message=body, + from_email=import_from_settings('EMAIL_SENDER'), + recipient_list=emails, + fail_silently=False, + ) + else: + logger.info("No email recipients provided, logging output instead.") + logger.info(subject) + logger.info(body)