Initial commit: stateful OpenStack API laboratory simulator.
Ship Keystone auth, multi-service handlers (Yoga→Dalmatian), Compose/Helm packaging, API contract packs, and pytest/Pulumi coverage labs.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
"""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}
|
||||
Reference in New Issue
Block a user