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

237 lines
7.9 KiB
Python

"""Legacy `/rest/...` JSON wrappers mirroring Automation API `/api` paths."""
from __future__ import annotations
from typing import Any
from fastapi import APIRouter, Depends, Query, Request, Response
from app.db.pool import Database
from app.dependencies import get_database
from app.vsphere.domain import vm_ops
from app.vsphere.errors import invalid_argument
from app.vsphere.rest import router as core
from app.vsphere.rest import tagging_rest
from app.vsphere.security.authz import require_privilege, require_read
from app.vsphere.security.session import SessionInfo
router = APIRouter(tags=["vSphere Legacy REST"])
def _value(payload: Any) -> dict[str, Any]:
return {"value": payload}
@router.get("/rest/vcenter/vm")
async def rest_list_vms(
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
names: list[str] | None = Query(default=None),
power_states: list[str] | None = Query(default=None),
hosts: list[str] | None = Query(default=None),
folders: list[str] | None = Query(default=None),
limit: int | None = Query(default=None, ge=1, le=5000),
cursor: int = Query(default=0, ge=0),
) -> dict[str, Any]:
payload = await core.list_vms(
database=database,
_=session,
names=names,
power_states=power_states,
hosts=hosts,
folders=folders,
datacenters=None,
clusters=None,
resource_pools=None,
limit=limit,
cursor=cursor,
)
return _value(payload)
@router.get("/rest/vcenter/vm/{vm}")
async def rest_get_vm(
vm: str,
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await core.get_vm(vm=vm, database=database, _=session))
@router.get("/rest/vcenter/host")
async def rest_list_hosts(
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await core.list_hosts(database=database, _=session))
@router.get("/rest/vcenter/datastore")
async def rest_list_datastores(
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await core.list_datastores(database=database, _=session))
@router.get("/rest/vcenter/network")
async def rest_list_networks(
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await core.list_networks(database=database, _=session))
@router.get("/rest/vcenter/datacenter")
async def rest_list_datacenters(
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await core.list_datacenters(database=database, _=session))
@router.get("/rest/vcenter/cluster")
async def rest_list_clusters(
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await core.list_clusters(database=database, _=session))
@router.get("/rest/appliance/system/version")
async def rest_appliance_version(
request: Request,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await core.appliance_version(request=request, database=database))
@router.post("/rest/vcenter/vm/{vm}/power")
async def rest_power_vm(
vm: str,
action: str = Query(...),
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("VirtualMachine.Interact.PowerOn")),
) -> dict[str, Any]:
task_id = await vm_ops.set_power(database, vm, action.lower())
return _value({"task": task_id})
# --- CIS tagging (govmomi / terraform-provider-vsphere / pulumi-vsphere) ---
@router.get("/rest/com/vmware/cis/tagging/category")
async def rest_list_categories(
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await tagging_rest.list_categories(database=database, _=session))
@router.post("/rest/com/vmware/cis/tagging/category")
async def rest_category_action(
body: dict[str, Any] | None = None,
action: str | None = Query(default=None, alias="~action"),
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.CreateCategory")),
) -> Any:
payload = body or {}
act = (action or "create").lower()
if act == "create":
return _value(
await tagging_rest.create_category(body=payload, database=database, _=session)
)
raise invalid_argument(f"unsupported ~action {act}")
@router.get("/rest/com/vmware/cis/tagging/category/{category_id}")
async def rest_get_category(
category_id: str,
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(
await tagging_rest.get_category(category_id=category_id, database=database, _=session)
)
@router.delete("/rest/com/vmware/cis/tagging/category/{category_id}")
async def rest_delete_category(
category_id: str,
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.CreateCategory")),
) -> Response:
return await tagging_rest.delete_category(category_id=category_id, database=database, _=session)
@router.get("/rest/com/vmware/cis/tagging/tag")
async def rest_list_tags(
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await tagging_rest.list_tags(database=database, _=session))
@router.post("/rest/com/vmware/cis/tagging/tag")
async def rest_tag_action(
body: dict[str, Any] | None = None,
action: str | None = Query(default=None, alias="~action"),
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.CreateTag")),
) -> Any:
payload = body or {}
act = (action or "create").lower()
if act == "create":
return _value(await tagging_rest.create_tag(body=payload, database=database, _=session))
raise invalid_argument(f"unsupported ~action {act}")
@router.get("/rest/com/vmware/cis/tagging/tag/{tag_id}")
async def rest_get_tag(
tag_id: str,
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_read),
) -> dict[str, Any]:
return _value(await tagging_rest.get_tag(tag_id=tag_id, database=database, _=session))
@router.delete("/rest/com/vmware/cis/tagging/tag/{tag_id}")
async def rest_delete_tag(
tag_id: str,
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.CreateTag")),
) -> Response:
return await tagging_rest.delete_tag(tag_id=tag_id, database=database, _=session)
@router.post("/rest/com/vmware/cis/tagging/tag-association")
async def rest_tag_association(
request: Request,
body: dict[str, Any] | None = None,
action: str | None = Query(default=None, alias="~action"),
database: Database = Depends(get_database),
session: SessionInfo = Depends(require_privilege("InventoryService.Tagging.AttachTag")),
) -> Any:
"""govmomi/terraform use ``?~action=`` instead of JSON ``action``."""
payload = dict(body or {})
# Some clients send ``?~action=``; FastAPI alias can miss ``~`` — also read raw query.
resolved = (
action
or request.query_params.get("~action")
or request.query_params.get("action")
or payload.get("action")
)
if resolved:
payload["action"] = resolved
result = await tagging_rest.tag_association(
body=payload,
action=str(resolved) if resolved else None,
database=database,
_=session,
)
if isinstance(result, Response):
return result
return _value(result)