import logging from uuid import uuid4 from django.db import models from django_middleware_global_request.middleware import get_request from lib.db import DateAwareMixin class TaskFactory: def __new__(self, task_uuid=None, request=None, *args, **kwargs): request = request or get_request() if not request: logging.error('No request found while creating task') else: session_uuid = request.session.get('current_task_uuid') form_uuid = request.POST.get('task_uuid', request.GET.get('task_uuid')) if form_uuid: task_uuid = task_uuid or form_uuid request.session['current_task_uuid'] = task_uuid elif session_uuid: task_uuid = task_uuid or session_uuid task_uuid = task_uuid or kwargs.pop('uuid', None) if not task_uuid: task = Task.objects.create() else: task, _created = Task.objects.get_or_create(uuid=task_uuid) if request: request.session['current_task_uuid'] = str(task.uuid) return task @staticmethod def reset_current_task(request=None): request = request or get_request() if request: request.session.pop('current_task_uuid', None) return True class Task(DateAwareMixin): uuid = models.UUIDField(default=uuid4, editable=False, unique=True) proxmox_upid = models.CharField(max_length=150, null=True, blank=True) status = models.CharField(max_length=150, null=True, blank=True, default='running') current_task = None def __del__(self): self.unset_as_current() def unset_as_current(self, request=None): request = request or get_request() if request: uuid = request.session.get('current_task_uuid') if uuid == self.uuid: request.session.pop('current_task_uuid', None) return True else: logging.warning(f'Tried to unset {self.uuid} as current, but it is not the current task ({uuid}') return False def __str__(self): return str(self.uuid) def add_entry(self, message): TaskEntry.objects.create(task=self, message=message) return self def task_is_stopped(self, result): return result.get('status', 'running').lower() in ('ok', 'error', 'stopped') def wrap_proxmox_function(self, proxmox_function, *args, **kwargs): from lib.proxmox import Proxmox self.proxmox_upid = proxmox_function(*args, **kwargs) self.save() if not self.proxmox_upid: logging.warning(f'Could not get upid for {proxmox_function} - {args} {kwargs}') return self while True: with Proxmox() as pm: for message in pm.get_task_status(taskhash=self.proxmox_upid): self.add_entry(message) if self.task_is_stopped(message): return self class TaskEntry(DateAwareMixin): task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name='entries') message = models.JSONField(null=True, blank=True)