6033967e6a
Ship Keystone auth, multi-service handlers (Yoga→Dalmatian), Compose/Helm packaging, API contract packs, and pytest/Pulumi coverage labs.
92 lines
3.4 KiB
Python
92 lines
3.4 KiB
Python
"""Placement API (lab subset + demo inventory)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Annotated, Any
|
|
|
|
from asyncpg import Connection
|
|
from fastapi import APIRouter, Depends
|
|
|
|
from app.openstack.auth import TokenContext
|
|
from app.openstack.db_docs import fetch_doc
|
|
from app.openstack.deps import get_conn, require_token
|
|
|
|
router = APIRouter(tags=["Placement"])
|
|
|
|
|
|
@router.get("/resource_providers")
|
|
async def list_resource_providers(
|
|
conn: Annotated[Connection, Depends(get_conn)],
|
|
_ctx: Annotated[TokenContext, Depends(require_token)],
|
|
) -> dict[str, object]:
|
|
defaults = await fetch_doc(
|
|
conn, service="placement", resource_type="resource_provider_defaults", name="default"
|
|
)
|
|
default_generation = int((defaults or {}).get("generation") or 0)
|
|
rows = await conn.fetch(
|
|
"""SELECT * FROM os_api_objects
|
|
WHERE service='placement' AND resource_type='resource_provider'
|
|
ORDER BY created_at, name"""
|
|
)
|
|
providers: list[dict[str, Any]] = []
|
|
for row in rows:
|
|
data = row["data"]
|
|
if isinstance(data, str):
|
|
data = json.loads(data)
|
|
data = dict(data or {})
|
|
providers.append(
|
|
{
|
|
"id": str(row["id"]),
|
|
"uuid": str(row["id"]),
|
|
"name": row["name"] or data.get("name") or str(row["id"]),
|
|
"generation": int(
|
|
data.get("generation")
|
|
if data.get("generation") is not None
|
|
else default_generation
|
|
),
|
|
"parent_provider_uuid": data.get("parent_provider_uuid"),
|
|
}
|
|
)
|
|
return {"resource_providers": providers}
|
|
|
|
|
|
@router.get("/allocations/{consumer_uuid}")
|
|
async def show_allocations(
|
|
consumer_uuid: str,
|
|
conn: Annotated[Connection, Depends(get_conn)],
|
|
_ctx: Annotated[TokenContext, Depends(require_token)],
|
|
) -> dict[str, object]:
|
|
defaults = await fetch_doc(
|
|
conn, service="placement", resource_type="allocation_defaults", name="default"
|
|
)
|
|
default_resources = dict((defaults or {}).get("resources") or {})
|
|
consumer_generation = int((defaults or {}).get("consumer_generation") or 0)
|
|
rows = await conn.fetch(
|
|
"""SELECT * FROM os_api_objects
|
|
WHERE service='placement' AND resource_type='allocation'
|
|
AND (data->>'consumer_uuid'=$1 OR id::text=$1 OR name=$1)
|
|
ORDER BY created_at""",
|
|
consumer_uuid,
|
|
)
|
|
allocations: dict[str, Any] = {}
|
|
for row in rows:
|
|
data = row["data"]
|
|
if isinstance(data, str):
|
|
data = json.loads(data)
|
|
data = dict(data or {})
|
|
rp = str(data.get("resource_provider") or data.get("resource_provider_id") or row["id"])
|
|
resources = (
|
|
data.get("resources") if isinstance(data.get("resources"), dict) else default_resources
|
|
)
|
|
allocations[rp] = {"resources": resources}
|
|
if data.get("consumer_generation") is not None:
|
|
consumer_generation = int(data["consumer_generation"])
|
|
if not allocations and default_resources:
|
|
allocations["00000000-0000-0000-0000-000000000001"] = {"resources": default_resources}
|
|
elif not allocations:
|
|
allocations["00000000-0000-0000-0000-000000000001"] = {
|
|
"resources": {"VCPU": 1, "MEMORY_MB": 512}
|
|
}
|
|
return {"allocations": allocations, "consumer_generation": consumer_generation}
|