237 lines
7.9 KiB
Python
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)
|