Source code for oioioi.ipauthsync.management.commands.ipauthsyncd

import time
import traceback

from django.core.mail import mail_admins
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils import timezone
import requests

from oioioi.ipauthsync.models import (
    IpAuthSyncConfig,
    IpAuthSyncedUser,
    IpAuthSyncRegionMessages,
)
from oioioi.ipdnsauth.models import IpToUser
from oioioi.participants.models import OnsiteRegistration


[docs]class Command(BaseCommand):
[docs] help = "Synchronizes the IP authentication database with region servers."
[docs] def add_arguments(self, parser): parser.add_argument( '--interval', default=60, type=int, help="Time between synchronization rounds", ) parser.add_argument( '--timeout', metavar='SECONDS', default=15, type=int, help="Connection timeout", )
[docs] def handle_config(self, config): rc = config.contest.controller.registration_controller() for region in config.contest.regions.all(): try: r = requests.get( f'http://{region.region_server}/ipauthsync/list', headers=dict(Host='oireg'), ) r.raise_for_status() warnings = [] mapping = [] for item in r.json()['mappings']: zaw_id = item['user_id'] ip = item['ip_address'] try: reg = OnsiteRegistration.objects.select_related( 'participant__user' ).get(number=zaw_id, region=region) user = reg.participant.user except OnsiteRegistration.DoesNotExist: warnings.append( "* No user found for ZAW=%s (IP=%s)" % (zaw_id, ip) ) continue try: rc.ipauthsync_validate_ip(region, ip, user) # pylint: disable=broad-except except Exception as e: warnings.append("Invalid IP=%s (ZAW=%s): %s" % (ip, zaw_id, e)) mapping.append('%s %s %s' % (zaw_id, ip, user.username)) yield user, ip warnings = '\n'.join(warnings) mapping = '\n'.join(mapping) msgs, created = IpAuthSyncRegionMessages.objects.get_or_create( region=region ) if warnings != msgs.warnings: msgs.warnings = warnings msgs.save() mail_admins( "ipauthsyncd: Warnings for region %s" % (region.short_name,), warnings, ) if mapping != msgs.mapping: msgs.mapping = mapping msgs.save() mail_admins( "ipauthsyncd: Mapping for region %s" % (region.short_name,), mapping, ) if region.short_name in self.failing_regions: self.failing_regions.remove(region.short_name) mail_admins( "ipauthsyncd: Sync now OK for region %s" % (region.short_name,), "(Intentionally left blank)", ) # pylint: disable=broad-except except Exception: if region.short_name in self.failing_regions: continue self.failing_regions.add(region.short_name) mail_admins( "ipauthsyncd: Sync failing for region %s" % (region.short_name,), traceback.format_exc(), )
[docs] def handle(self, *args, **options): # pylint: disable=attribute-defined-outside-init self.options = options # pylint: disable=attribute-defined-outside-init self.failing_regions = set() while True: configs = ( IpAuthSyncConfig.objects.get_active(timezone.now()) .select_related('contest') .prefetch_related('contest__regions') ) mappings = [] for c in configs: mappings.extend(self.handle_config(c)) with transaction.atomic(): IpToUser.objects.filter(ipauthsynceduser__isnull=False).delete() IpAuthSyncedUser.objects.all().delete() for user, ip in mappings: entry = IpToUser(user=user, ip_addr=ip) entry.save() IpAuthSyncedUser(entry=entry).save() time.sleep(options['interval'])