Files
vmware-api-simulator/app/vsphere/domain/inventory_ops.py
T
inecs f8d3cbdd59 Initial commit: VMware vSphere API simulator scaffold.
Add the FastAPI app, PostgreSQL migrations, Docker/Helm packaging, API
contracts, docs, client examples, and the unit/integration/compatibility
test suite for local client and tooling labs without a real vCenter.
2026-07-18 04:42:11 +03:00

226 lines
6.2 KiB
Python

"""CRUD for folders, datacenters, clusters, resource pools, hosts, DVS."""
from __future__ import annotations
from typing import Any
from app.db.pool import Database
from app.vsphere import inventory
from app.vsphere.errors import invalid_argument, not_found
async def create_folder(
database: Database,
*,
name: str,
parent: str,
folder_type: str = "VIRTUAL_MACHINE",
) -> str:
parent_obj = await inventory.get_object(database, parent)
if parent_obj is None:
raise not_found(f"Parent {parent} not found")
moid = await inventory.next_moid(database, "group")
# next_moid with group- may not work well; use folder- style
import secrets
moid = f"group-{secrets.token_hex(3)}"
await inventory.upsert_object(
database,
moid=moid,
type_name="Folder",
name=name,
parent_moid=parent,
props={"folder_type": folder_type},
)
return moid
async def create_datacenter(database: Database, *, name: str, folder: str = "group-d1") -> str:
import secrets
moid = f"datacenter-{secrets.randbelow(900) + 100}"
host_folder = f"group-h{secrets.randbelow(90) + 10}"
vm_folder = f"group-v{secrets.randbelow(90) + 10}"
ds_folder = f"group-s{secrets.randbelow(90) + 10}"
net_folder = f"group-n{secrets.randbelow(90) + 10}"
await inventory.upsert_object(
database,
moid=moid,
type_name="Datacenter",
name=name,
parent_moid=folder,
props={
"datastore_folder": ds_folder,
"host_folder": host_folder,
"vm_folder": vm_folder,
"network_folder": net_folder,
},
)
for child_moid, child_name, ftype in (
(host_folder, "host", "HOST"),
(vm_folder, "vm", "VIRTUAL_MACHINE"),
(ds_folder, "datastore", "DATASTORE"),
(net_folder, "network", "NETWORK"),
):
await inventory.upsert_object(
database,
moid=child_moid,
type_name="Folder",
name=child_name,
parent_moid=moid,
props={"folder_type": ftype},
)
return moid
async def create_cluster(
database: Database,
*,
name: str,
folder: str = "group-h23",
drs_enabled: bool = True,
ha_enabled: bool = True,
) -> str:
import secrets
moid = f"domain-c{secrets.randbelow(900) + 100}"
rp = f"resgroup-{secrets.randbelow(900) + 100}"
await inventory.upsert_object(
database,
moid=moid,
type_name="ClusterComputeResource",
name=name,
parent_moid=folder,
props={"drs_enabled": drs_enabled, "ha_enabled": ha_enabled, "resource_pool": rp},
)
await inventory.upsert_object(
database,
moid=rp,
type_name="ResourcePool",
name="Resources",
parent_moid=moid,
props={"cpu_limit_mhz": -1, "memory_limit_mib": -1},
)
return moid
async def create_resource_pool(
database: Database,
*,
name: str,
parent: str,
) -> str:
parent_obj = await inventory.get_object(database, parent)
if parent_obj is None:
raise not_found(f"Parent {parent} not found")
import secrets
moid = f"resgroup-{secrets.randbelow(900) + 100}"
await inventory.upsert_object(
database,
moid=moid,
type_name="ResourcePool",
name=name,
parent_moid=parent,
props={"cpu_limit_mhz": -1, "memory_limit_mib": -1},
)
return moid
async def rename_object(database: Database, moid: str, name: str) -> None:
obj = await inventory.get_object(database, moid)
if obj is None:
raise not_found(f"Object {moid} not found")
await inventory.upsert_object(
database,
moid=obj.moid,
type_name=obj.type,
name=name,
parent_moid=obj.parent_moid,
props=obj.props,
)
async def move_object(database: Database, moid: str, parent: str) -> None:
obj = await inventory.get_object(database, moid)
if obj is None:
raise not_found(f"Object {moid} not found")
parent_obj = await inventory.get_object(database, parent)
if parent_obj is None:
raise not_found(f"Parent {parent} not found")
await inventory.upsert_object(
database,
moid=obj.moid,
type_name=obj.type,
name=obj.name,
parent_moid=parent,
props=obj.props,
)
async def delete_managed(database: Database, moid: str) -> None:
obj = await inventory.get_object(database, moid)
if obj is None:
raise not_found(f"Object {moid} not found")
children = [
child for child in await inventory.list_objects(database) if child.parent_moid == moid
]
if children:
raise invalid_argument(f"Object {moid} still has children")
await inventory.delete_object(database, moid)
async def set_host_maintenance(database: Database, host: str, enabled: bool) -> dict[str, Any]:
obj = await inventory.get_object(database, host)
if obj is None or obj.type != "HostSystem":
raise not_found(f"Host {host} not found")
props = dict(obj.props)
props["connection_state"] = "CONNECTED"
props["maintenance_mode"] = enabled
await inventory.update_props(database, host, props)
return {"host": host, "maintenance_mode": enabled}
async def create_dvs(
database: Database,
*,
name: str,
folder: str = "group-n23",
) -> str:
import secrets
moid = f"dvs-{secrets.randbelow(900) + 100}"
await inventory.upsert_object(
database,
moid=moid,
type_name="VmwareDistributedVirtualSwitch",
name=name,
parent_moid=folder,
props={"version": "8.0.0", "num_ports": 128},
)
return moid
async def create_dvpg(
database: Database,
*,
name: str,
dvs: str,
vlan_id: int = 0,
) -> str:
parent = await inventory.get_object(database, dvs)
if parent is None:
raise not_found(f"DVS {dvs} not found")
import secrets
moid = f"dvportgroup-{secrets.randbelow(900) + 100}"
await inventory.upsert_object(
database,
moid=moid,
type_name="DistributedVirtualPortgroup",
name=name,
parent_moid=dvs,
props={"type": "DISTRIBUTED_PORTGROUP", "vlan_id": vlan_id, "dvs": dvs},
)
return moid