feat: add basic QEMU and task vertical slice
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
"""Worker semantics for asynchronous QEMU transitions."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from app.simulation.clock import Clock
|
||||
from app.simulation.transitions import VmState, plan_transition
|
||||
from app.tasks.repository import Task, TaskRepository
|
||||
from app.tasks.worker import TaskHandler
|
||||
|
||||
|
||||
def qemu_handler(repository: TaskRepository, clock: Clock) -> TaskHandler:
|
||||
async def execute(task: Task) -> dict[str, str]:
|
||||
operation = task.task_type.removeprefix("qemu-")
|
||||
resource_id = uuid.UUID(str(task.payload["resource_id"]))
|
||||
async with repository.pool.acquire() as connection:
|
||||
row = await connection.fetchrow("SELECT state FROM resources WHERE id=$1", resource_id)
|
||||
if row is None:
|
||||
raise ValueError("resource disappeared")
|
||||
raw = row["state"]
|
||||
state = json.loads(raw) if isinstance(raw, str) else dict(raw)
|
||||
transition = plan_transition(VmState(str(state["status"])), operation)
|
||||
state["status"] = transition.intermediate
|
||||
await connection.execute(
|
||||
"UPDATE resources SET state=$2::jsonb WHERE id=$1",
|
||||
resource_id,
|
||||
json.dumps(state),
|
||||
)
|
||||
await repository.append_log(task.id, f"VM {operation} started")
|
||||
await clock.sleep(1.0)
|
||||
async with repository.pool.acquire() as connection:
|
||||
state["status"] = transition.after
|
||||
await connection.execute(
|
||||
"UPDATE resources SET state=$2::jsonb WHERE id=$1",
|
||||
resource_id,
|
||||
json.dumps(state),
|
||||
)
|
||||
await repository.append_log(task.id, f"VM {operation} completed")
|
||||
return {"status": str(transition.after)}
|
||||
|
||||
return execute
|
||||
@@ -178,6 +178,18 @@ class TaskRepository:
|
||||
row = await self.pool.fetchrow("SELECT * FROM tasks WHERE id=$1", task_id)
|
||||
return _task(row) if row is not None else None
|
||||
|
||||
async def get_by_upid(self, upid: str) -> Task | None:
|
||||
row = await self.pool.fetchrow("SELECT * FROM tasks WHERE upid=$1", upid)
|
||||
return _task(row) if row is not None else None
|
||||
|
||||
async def list_for_node(self, node: str) -> tuple[Task, ...]:
|
||||
rows = await self.pool.fetch(
|
||||
"""SELECT * FROM tasks WHERE payload->>'node'=$1
|
||||
ORDER BY created_at DESC LIMIT 1000""",
|
||||
node,
|
||||
)
|
||||
return tuple(_task(row) for row in rows)
|
||||
|
||||
async def logs(self, task_id: uuid.UUID) -> tuple[str, ...]:
|
||||
rows = await self.pool.fetch(
|
||||
"SELECT message FROM task_logs WHERE task_id=$1 ORDER BY sequence", task_id
|
||||
|
||||
Reference in New Issue
Block a user