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

215 lines
6.9 KiB
Python

"""Inventory CRUD, host maintenance, datastore files, DVS."""
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 import inventory
from app.vsphere.domain import content, inventory_ops
from app.vsphere.errors import invalid_argument
from app.vsphere.security.authz import require_privilege, require_read
from app.vsphere.security.session import SessionInfo
router = APIRouter(tags=["vSphere Inventory Ext"])
def _require_name(body: dict[str, Any]) -> str:
name = body.get("name")
if not name:
raise invalid_argument("name is required")
return str(name)
@router.post("/api/vcenter/datacenter")
async def create_dc(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Datacenter.Create")),
) -> str:
return await inventory_ops.create_datacenter(
database, name=_require_name(body), folder=str(body.get("folder") or "group-d1")
)
@router.delete("/api/vcenter/datacenter/{datacenter}")
async def delete_dc(
datacenter: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Datacenter.Delete")),
) -> Response:
await inventory_ops.delete_managed(database, datacenter)
return Response(status_code=204)
@router.post("/api/vcenter/cluster")
async def create_cluster(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Cluster.Create")),
) -> str:
return await inventory_ops.create_cluster(
database,
name=_require_name(body),
folder=str(body.get("folder") or "group-h23"),
drs_enabled=bool((body.get("drs") or {}).get("enabled", True)),
ha_enabled=bool((body.get("ha") or {}).get("enabled", True)),
)
@router.delete("/api/vcenter/cluster/{cluster}")
async def delete_cluster(
cluster: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Cluster.Delete")),
) -> Response:
await inventory_ops.delete_managed(database, cluster)
return Response(status_code=204)
@router.post("/api/vcenter/folder")
async def create_folder(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Folder.Create")),
) -> str:
spec = body.get("create_spec") if isinstance(body.get("create_spec"), dict) else body
return await inventory_ops.create_folder(
database,
name=_require_name(spec),
parent=str(spec.get("parent") or spec.get("folder") or "group-v23"),
folder_type=str(spec.get("type") or "VIRTUAL_MACHINE"),
)
@router.post("/api/vcenter/folder/{folder}")
async def folder_action(
folder: str,
action: str = Query(...),
body: dict[str, Any] | None = None,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Folder.Rename")),
) -> Response:
body = body or {}
if action == "rename":
await inventory_ops.rename_object(database, folder, _require_name(body))
elif action == "move":
parent = body.get("parent")
if not parent:
raise invalid_argument("parent is required")
await inventory_ops.move_object(database, folder, str(parent))
else:
raise invalid_argument(f"unsupported action {action}")
return Response(status_code=204)
@router.delete("/api/vcenter/folder/{folder}")
async def delete_folder(
folder: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Folder.Delete")),
) -> Response:
await inventory_ops.delete_managed(database, folder)
return Response(status_code=204)
@router.post("/api/vcenter/resource-pool")
async def create_rp(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Resource.CreatePool")),
) -> str:
return await inventory_ops.create_resource_pool(
database, name=_require_name(body), parent=str(body.get("parent") or "resgroup-22")
)
@router.delete("/api/vcenter/resource-pool/{resource_pool}")
async def delete_rp(
resource_pool: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Resource.DeletePool")),
) -> Response:
await inventory_ops.delete_managed(database, resource_pool)
return Response(status_code=204)
@router.post("/api/vcenter/host/{host}/maintenance")
async def host_maintenance(
host: str,
action: str = Query(...),
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Host.Config.Maintenance")),
) -> dict[str, Any]:
if action not in {"enter", "exit"}:
raise invalid_argument("action must be enter|exit")
return await inventory_ops.set_host_maintenance(database, host, enabled=(action == "enter"))
@router.get("/api/vcenter/datastore/{datastore}/files")
async def ds_files(
datastore: str,
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_read),
) -> list[dict[str, Any]]:
return await content.list_datastore_files(database, datastore)
@router.post("/api/vcenter/datastore/{datastore}/files")
async def ds_put_file(
datastore: str,
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Datastore.FileManagement")),
) -> Response:
path = body.get("path")
if not path:
raise invalid_argument("path is required")
await content.put_datastore_file(
database,
datastore,
str(path),
size=int(body.get("size") or 0),
file_type=str(body.get("type") or "FILE"),
)
return Response(status_code=204)
@router.get("/api/vcenter/network/dvs")
async def list_dvs(
database: Database = Depends(get_database), _: SessionInfo = Depends(require_read)
) -> list[dict[str, Any]]:
objects = await inventory.list_objects(database, type_name="VmwareDistributedVirtualSwitch")
return [{"dvs": o.moid, "name": o.name} for o in objects]
@router.post("/api/vcenter/network/dvs")
async def create_dvs(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Network.Assign")),
) -> str:
return await inventory_ops.create_dvs(
database, name=_require_name(body), folder=str(body.get("folder") or "group-n23")
)
@router.post("/api/vcenter/network/dvpg")
async def create_dvpg(
body: dict[str, Any],
database: Database = Depends(get_database),
_: SessionInfo = Depends(require_privilege("Network.Assign")),
) -> str:
dvs = body.get("dvs")
if not dvs:
raise invalid_argument("dvs is required")
return await inventory_ops.create_dvpg(
database,
name=_require_name(body),
dvs=str(dvs),
vlan_id=int(body.get("vlan_id") or 0),
)