Files
vmware-api-simulator/app/vsphere/rest/content_rest.py
T

275 lines
9.4 KiB
Python

"""Content library, OVF deploy, storage policies, privileges."""
from __future__ import annotations
from typing import Any
from fastapi import APIRouter, Depends, Query, Response
from app.db.pool import Database
from app.dependencies import get_database
from app.vsphere.domain import api_state, content
from app.vsphere.security.authz import require_privilege, require_read
from app.vsphere.security.session import SessionInfo
router = APIRouter(tags=["vSphere Content"])
@router.get("/api/content/library")
async def list_libraries(
database: Database = Depends(get_database), _: SessionInfo = Depends(require_read)
) -> list[str]:
return [item["id"] for item in await content.list_libraries(database)]
@router.get("/api/content/local-library")
async def list_local_libraries(
database: Database = Depends(get_database), _: SessionInfo = Depends(require_read)
) -> list[str]:
return [
item["id"]
for item in await content.list_libraries(database)
if str(item.get("type") or "LOCAL").upper() == "LOCAL"
]
@router.post("/api/content/local-library")
async def create_library(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("ContentLibrary.CreateLocalLibrary")),
) -> str:
from app.vsphere.errors import invalid_argument
spec = body.get("create_spec") or body
name = spec.get("name") if isinstance(spec, dict) else None
if not name:
raise invalid_argument("create_spec.name is required")
return await content.create_library(
database, name=str(name), description=str(spec.get("description") or "")
)
# Static /library/item* paths must win over /library/{library_id}.
@router.get("/api/content/library/item")
async def list_items(
library_id: str = Query(...),
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> list[str]:
return [item["id"] for item in await content.list_library_items(database, library_id)]
@router.post("/api/content/library/item")
async def create_item(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> str:
from app.vsphere.errors import invalid_argument
spec = body.get("create_spec") or body
if not isinstance(spec, dict):
raise invalid_argument("create_spec is required")
library_id = spec.get("library_id")
name = spec.get("name")
if not library_id:
raise invalid_argument("create_spec.library_id is required")
if not name:
raise invalid_argument("create_spec.name is required")
return await content.create_library_item(
database,
library_id=str(library_id),
name=str(name),
item_type=str(spec.get("type") or "ovf"),
description=str(spec.get("description") or ""),
)
@router.post("/api/content/library/item/update-session")
async def create_update_session(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> str:
create_spec = body.get("create_spec") or body
library_item_id = str(create_spec.get("library_item_id") or create_spec.get("item_id") or "")
if not library_item_id:
from app.vsphere.errors import invalid_argument
raise invalid_argument("create_spec.library_item_id is required")
return await content.create_update_session(database, library_item_id=library_item_id)
@router.get("/api/content/library/item/update-session/{session_id}")
async def get_update_session(
session_id: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return await content.get_update_session(database, session_id)
@router.post("/api/content/library/item/update-session/{session_id}/file")
async def add_update_session_file(
session_id: str,
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> dict[str, Any]:
file_spec = body.get("file_spec") or body
return await content.add_update_session_file(
database,
session_id,
name=str(file_spec.get("name") or "upload.bin"),
source_type=str(file_spec.get("source_type") or "PUSH"),
size=int(file_spec.get("size") or 0),
content=str(file_spec.get("content") or ""),
)
@router.post("/api/content/library/item/update-session/{session_id}")
async def complete_update_session(
session_id: str,
action: str = Query("complete"),
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> None:
del action
await content.complete_update_session(database, session_id)
@router.post("/api/content/library/item/download-session")
async def create_download_session(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> str:
create_spec = body.get("create_spec") or body
library_item_id = str(create_spec.get("library_item_id") or create_spec.get("item_id") or "")
if not library_item_id:
from app.vsphere.errors import invalid_argument
raise invalid_argument("create_spec.library_item_id is required")
return await content.create_download_session(database, library_item_id=library_item_id)
@router.get("/api/content/library/item/download-session/{session_id}")
async def get_download_session(
session_id: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return await content.get_download_session(database, session_id)
@router.get("/api/content/library/item/download-session/{session_id}/file")
async def list_download_session_files(
session_id: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> list[dict[str, Any]]:
return await content.list_download_session_files(database, session_id)
@router.get("/api/content/library/item/{library_item_id}")
async def get_item(
library_item_id: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return await content.get_library_item(database, library_item_id)
@router.delete("/api/content/library/item/{library_item_id}")
async def delete_item(
library_item_id: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("ContentLibrary.AddLibraryItem")),
) -> Response:
await content.delete_library_item(database, library_item_id)
return Response(status_code=204)
@router.get("/api/content/library/{library_id}")
async def get_library(
library_id: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return await content.get_library(database, library_id)
@router.get("/api/content/local-library/{library_id}")
async def get_local_library(
library_id: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
info = await content.get_library(database, library_id)
if str(info.get("type") or "").upper() not in {"LOCAL", ""}:
from app.vsphere.errors import not_found
raise not_found(f"Local library {library_id} not found")
return info
@router.delete("/api/content/local-library/{library_id}")
async def delete_local_library(
library_id: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("ContentLibrary.CreateLocalLibrary")),
) -> Response:
await content.delete_library(database, library_id)
return Response(status_code=204)
@router.post("/api/vcenter/ovf/library-item/{item_id}")
async def deploy_ovf(
item_id: str,
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("VirtualMachine.Provisioning.DeployTemplate")),
) -> dict[str, Any]:
target = body.get("target") or {}
deployment = body.get("deployment_spec") or body
folder = (
target.get("folder_id")
or target.get("folder")
or deployment.get("folder")
or "group-v23"
)
host = target.get("host_id") or target.get("host") or "host-11"
datastore = (
target.get("datastore_id")
or target.get("datastore")
or deployment.get("datastore")
or "datastore-31"
)
resource_pool = (
target.get("resource_pool_id")
or target.get("resource_pool")
or deployment.get("resource_pool")
)
moid, task_id = await content.deploy_ovf_from_library(
database,
item_id=item_id,
name=str(deployment.get("name") or f"ovf-{item_id[-6:]}"),
folder=str(folder),
host=str(host),
datastore=str(datastore),
resource_pool=str(resource_pool) if resource_pool else None,
)
return {"resource_id": {"id": moid, "type": "VirtualMachine"}, "task": task_id}
@router.get("/api/vcenter/storage/policies")
async def storage_policies(
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> list[dict[str, Any]]:
payload = await api_state.get_payload(database, "GET", "/api/vcenter/storage/policies")
if isinstance(payload, list):
return payload
return []