mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-11 04:36:48 +00:00
feat(operations): job, claim and worker lease models
This commit is contained in:
parent
5f8f7a8643
commit
99b9aa2a3c
9 changed files with 305 additions and 0 deletions
76
operations/models.py
Normal file
76
operations/models.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
"""Long-running operations: the queue, the history and the resources jobs
|
||||
hold (spec 2026-10-13, sections 1-2)."""
|
||||
|
||||
import uuid
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Operation(models.Model):
|
||||
QUEUED = "queued"
|
||||
RUNNING = "running"
|
||||
CANCELLING = "cancelling"
|
||||
SUCCEEDED = "succeeded"
|
||||
FAILED = "failed"
|
||||
CANCELLED = "cancelled"
|
||||
UNCERTAIN = "uncertain"
|
||||
ACTIVE = (QUEUED, RUNNING, CANCELLING)
|
||||
TERMINAL = (SUCCEEDED, FAILED, CANCELLED, UNCERTAIN)
|
||||
STATES = [(s, s) for s in ACTIVE + TERMINAL]
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
kind = models.CharField(max_length=64, db_index=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL, related_name="operations")
|
||||
username = models.CharField(max_length=150) # kept when the user is deleted
|
||||
submission_key = models.CharField(max_length=64)
|
||||
resource = models.CharField(max_length=255, db_index=True) # the page that shows the job
|
||||
resource_label = models.CharField(max_length=255)
|
||||
state = models.CharField(max_length=16, choices=STATES, default=QUEUED, db_index=True)
|
||||
params = models.JSONField(default=dict)
|
||||
intent = models.JSONField(default=dict) # plan facts, then what run is about to change
|
||||
# set with the intent committed right before the first libvirt effect:
|
||||
# recovery fails a job without it, it never reached libvirt
|
||||
effects_started = models.BooleanField(default=False)
|
||||
phase = models.CharField(max_length=255, blank=True)
|
||||
progress_done = models.BigIntegerField(null=True)
|
||||
progress_total = models.BigIntegerField(null=True)
|
||||
result = models.JSONField(default=dict)
|
||||
error = models.TextField(blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
|
||||
started_at = models.DateTimeField(null=True)
|
||||
finished_at = models.DateTimeField(null=True)
|
||||
heartbeat_at = models.DateTimeField(null=True)
|
||||
worker = models.CharField(max_length=128, blank=True) # identity of the worker that owns it
|
||||
time_limit = models.PositiveIntegerField(null=True) # seconds, fixed at admission
|
||||
cancel_requested = models.BooleanField(default=False)
|
||||
resolved_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL, related_name="+")
|
||||
resolved_at = models.DateTimeField(null=True)
|
||||
resolution = models.CharField(max_length=16, blank=True)
|
||||
resolution_note = models.TextField(blank=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["-created_at"]
|
||||
constraints = [models.UniqueConstraint(fields=["user", "submission_key"], name="unique_submission")]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.kind} {self.id}"
|
||||
|
||||
|
||||
class Claim(models.Model):
|
||||
SHARED = "shared"
|
||||
EXCLUSIVE = "exclusive"
|
||||
|
||||
operation = models.ForeignKey(Operation, null=True, on_delete=models.CASCADE, related_name="claims")
|
||||
resource = models.CharField(max_length=255, db_index=True)
|
||||
mode = models.CharField(max_length=9, choices=[(SHARED, SHARED), (EXCLUSIVE, EXCLUSIVE)])
|
||||
holder = models.CharField(max_length=128, blank=True) # transient: host:pid:thread
|
||||
expires_at = models.DateTimeField(null=True) # transient only
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
|
||||
class WorkerLease(models.Model):
|
||||
name = models.CharField(primary_key=True, max_length=16, default="worker")
|
||||
holder = models.CharField(max_length=128)
|
||||
host = models.CharField(max_length=255)
|
||||
heartbeat_at = models.DateTimeField()
|
||||
Loading…
Add table
Add a link
Reference in a new issue