lablink_allocator_service.db.vms¶
lablink_allocator_service.db.vms
¶
Attributes¶
logger = logging.getLogger(__name__)
module-attribute
¶
Classes¶
VmDatabase(dbname, user, password, host, port, table_name, pool_min_size=POOL_MIN_SIZE, pool_max_size=POOL_MAX_SIZE, pool=None)
¶
Persistence for the VM table: rows, client registration and auth, seat assignment, logs, health and heartbeat, and the settings table.
Shares its connection pool with the other classes in this package via
the pool property, rather than each opening its own.
Initialize the database connection pool.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dbname
|
str
|
The name of the database. |
required |
user
|
str
|
The username to connect to the database. |
required |
password
|
str
|
The password for the user. |
required |
host
|
str
|
The host where the database is located. |
required |
port
|
int
|
The port number for the database connection. |
required |
table_name
|
str
|
The name of the table to interact with. |
required |
pool_min_size
|
int
|
Minimum pooled connections. Defaults to
POOL_MIN_SIZE. Ignored when |
POOL_MIN_SIZE
|
pool_max_size
|
int
|
Maximum pooled connections. Defaults to
POOL_MAX_SIZE (which honors LABLINK_DB_POOL_MAX_SIZE).
Ignored when |
POOL_MAX_SIZE
|
pool
|
A pre-built connection pool to use instead of
constructing a new |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If pool sizing is invalid and |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
Attributes¶
dbname = dbname
instance-attribute
¶
host = host
instance-attribute
¶
password = password
instance-attribute
¶
pool
property
¶
The underlying connection pool, shared with other classes that need pooled access to the same database (e.g. OperationsDatabase) rather than opening a second one.
port = port
instance-attribute
¶
table_name = table_name
instance-attribute
¶
user = user
instance-attribute
¶
Methods:¶
admin_reserve_vm(hostname)
¶
Atomically reserve an unassigned VM for admin troubleshooting.
Claims the row by setting AdminReservedAt, but only if it is still unassigned, not already admin-reserved, and running — so a concurrent student assignment or a second admin session can't collide with this one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM to reserve. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if this call claimed the VM, False if it lost the race (or the VM doesn't exist / isn't eligible). |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
allocate_tunnel_alias_octet()
¶
Atomically claim the next unused loopback-alias octet for a reverse-tunnel client.
Used to be a bare SELECT MAX((provider_metadata->>...)::int)
over client rows -- a pure read with no claim, so two concurrent
registrations could observe the same "current max" before either
one's INSERT was even issued and mint the same octet. A classroom
registering many clients at once is the normal case, and this
repo already has a documented VM-assignment race of exactly this
shape (see assign_vm).
Fixed with a counter row in the existing settings table
(still no schema change): INSERT ... ON CONFLICT DO UPDATE is
a single statement that self-initializes the counter on first use
and otherwise increments it, both atomically. Postgres re-checks
the UPDATE arm's SET expression against the row's just-committed
value for any caller that was blocked waiting on it, so two
interleaved calls can never return the same value (verified with
concurrent threads against a real Postgres in
test_allocate_tunnel_alias_octet_concurrent_returns_distinct_octets).
Monotonic and never recycled -- and, unlike the old MAX-based
read, now consumed by every allocation attempt, not just every
distinct live client: a registration that later 409s (hijack
conflict) or IntegrityErrors, and every legitimate
re-registration of the same client, each burn one more integer,
since the counter is claimed before register_client is ever
called. A pool table would let a value be reclaimed when its
client leaves, but needs the migration machinery this codebase
deliberately avoids, so this tops out at 254 allocation attempts
ever for the deployment's lifetime -- not 245 concurrent
clients. Callers MUST range-check the return value before using
it (see routes/registration.py, which returns 503 rather than
calling tunnel_manager.authorize_client with an out-of-range
octet) -- deployments are ephemeral with a fresh DB each time, so
this ceiling resets on redeploy, but a long-lived deployment with
enough registration churn can still exhaust it well before 254
distinct clients were ever simultaneously live.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
append_logs_by_hostname(hostname, new_logs, log_type='cloud_init', max_size=1 * 1024 * 1024)
¶
Atomically append logs for a VM, truncating to max_size.
Uses a single SQL UPDATE to avoid race conditions when multiple log shippers POST concurrently for the same VM.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM. |
required |
new_logs
|
str
|
The new log lines to append. |
required |
log_type
|
str
|
"cloud_init" or "docker". |
'cloud_init'
|
max_size
|
int
|
Maximum log size in bytes (default 1MB). |
1 * 1024 * 1024
|
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
assign_vm(email)
¶
Atomically claim an available VM for a user and return its hostname.
The claim is a single statement: the inner SELECT picks one
unassigned, running, non-Unhealthy row and locks it with
FOR UPDATE SKIP LOCKED, so concurrent callers each lock a
different row instead of racing on the same one. RETURNING
hands back the hostname that was actually claimed, so the caller
never has to re-look it up by email (which is itself racy).
A client heartbeat or another short update can temporarily lock the final free row. If the atomic claim finds nothing but a plain eligibility check still sees a free row, retry briefly rather than reporting a false empty pool.
Skips rows marked Unhealthy so a VM whose agent went dark (rotation failed, etc.) isn't handed to the next student to wedge in turn — the reboot service picks it back up.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
email
|
str
|
The email of the user. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The hostname of the claimed VM. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no VM is available to assign. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 | |
clear_database()
¶
Delete all VMs from the table.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
clear_unhealthy(*, hostname)
¶
Clear an allocator-set Unhealthy flag, returning the VM to the assignable pool.
Sets NULL rather than 'Healthy': the allocator marks a client Unhealthy when it cannot reach it, which says nothing about the GPU, and 'N/A' (no nvidia-smi, the normal case on a BYO box) is a legitimate client-reported value we must not overwrite with a lie. assign_vm treats NULL as assignable ("healthy IS NULL OR healthy <> 'Unhealthy'").
Needed because the flag is otherwise permanent: check_gpu only POSTs on change, and on a GPU-less box it reports 'N/A' once and exits its loop entirely, so the client can never overwrite the allocator's write. Before this, raw SQL was the only way out (lablink#404).
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
ensure_reboot_columns()
¶
Add reboot tracking columns to vm_table if they don't exist.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_all_vm_status()
¶
Get the status of all VMs in the table.
Returns:
| Name | Type | Description |
|---|---|---|
dict |
dict
|
A dictionary containing the hostname and status of each VM. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_all_vms()
¶
Get all VMs from the table, excluding logs.
Returns:
| Name | Type | Description |
|---|---|---|
list |
list
|
A list of all VMs in the table in the form of dictionaries. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_all_vms_for_export(include_logs=False)
¶
Get all VMs with metrics data for export.
Logs are excluded by default since the export targets quantitative metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
include_logs
|
bool
|
Whether to include cloudinitlogs and dockerlogs. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
list |
list
|
A list of VM dicts with metrics columns. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_assigned_vm_for_email(email)
¶
Look up whether an email already has a VM assigned.
Used by /api/request_vm to decide between reassignment (same hostname, new CRD) and fresh assignment (new hostname).
Re-raises on DB error rather than swallowing: "lookup failed" and "no assignment exists" are semantically different states. Treating them identically (by returning None in both cases) would silently route a student with an existing assignment to the fresh-assignment path under a transient DB blip, producing a dual-assignment. The caller's outer try/except handles the raised exception and renders the generic error page.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
email
|
str
|
The student's email address. |
required |
Returns:
| Type | Description |
|---|---|
Optional[dict]
|
A dict with hostname, status, reboot_count if an assignment |
Optional[dict]
|
exists, or None if the email has no VM. |
Raises:
| Type | Description |
|---|---|
Exception
|
on DB connection or query failure. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_client_secret_hash(hostname)
¶
Return the argon2 client_secret_hash for a hostname, or None.
Cached per-hostname (see TtlLruCache). The version token
captured before the SELECT is re-checked on put — a concurrent
register_client or unregister_client that bumps the
version mid-flight rejects the stale write, so the next call
re-queries and serves the freshly rotated hash. TTLs and LRU
eviction are belt-and-suspenders.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_column_names(table_name=None)
¶
Get the column names of a table.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
table_name
|
str
|
The name of the table. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
list |
list
|
A list of column names. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_failed_vms(stale_initializing_minutes=25, stale_rebooting_minutes=10, stale_heartbeat_minutes=3)
¶
Get VMs that need a reboot attempt.
Detects VMs in error state, with unhealthy GPUs, stuck initializing, stuck in rebooting state (failed to come back after a reboot), or running but silent (no heartbeat within the staleness window).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stale_initializing_minutes
|
int
|
Minutes after which an initializing VM is considered stale and eligible for reboot. Default 25 min — VMs can now legitimately sit in 'initializing' for the full duration of custom-startup.sh (ilastik downloads, large tutorial datasets, etc.) because user_data.sh no longer prematurely flips status to 'running'; start.sh does that once client services are about to launch. |
25
|
stale_rebooting_minutes
|
int
|
Minutes after which a rebooting VM is considered stuck and eligible for another reboot attempt. |
10
|
stale_heartbeat_minutes
|
int
|
Minutes after which a running VM is considered silent and eligible for reboot. Default 3 min (6x the 30s heartbeat cadence). Brand-new VMs with last_seen_at IS NULL are not flagged — they must heartbeat at least once to be eligible for staleness detection. |
3
|
Returns:
| Name | Type | Description |
|---|---|---|
list |
List[dict]
|
VMs eligible for reboot with hostname, status, healthy, reboot_count, last_reboot_time, useremail, and last_seen_at. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 | |
get_lan_ip(hostname)
¶
LAN IP for a manual client: provider_metadata->>'lan_ip', falling back to the host part of endpoint_url. None if absent.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_overlay_hostname(hostname)
¶
Overlay hostname for a mesh-overlay client: provider_metadata->>'overlay_hostname'. None if absent.
Unlike get_lan_ip, there is no endpoint_url fallback — mesh-overlay clients don't set endpoint_url (see MeshOverlayClientConnectivity's registration flow).
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_row_count()
¶
Get the number of rows in the table. Returns: int: The number of rows in the table.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_session_for_peek(hostname)
¶
Look up the live session_id for an in-use VM, for admin peek.
Returns None when there's nothing to peek at — unassigned, not running, or no session has been minted yet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM. |
required |
Returns:
| Type | Description |
|---|---|
Optional[dict]
|
Optional[dict]: |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_setting(key)
¶
Return the settings value for key, or None if absent.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_status_by_hostname(hostname)
¶
Get the status of a VM by its hostname.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The status of the VM, or None if not found. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_tunnel_alias(hostname)
¶
Loopback-alias octet for a reverse-tunnel client, or None.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_tunnel_path_prefix(prefix)
¶
(client_id, prefix) for the client owning this tunnel path prefix, or None. The prefix is stored at registration rather than recomputed here so this stays a single indexed-ish lookup.
Ambiguity is None, not a coin flip: this lookup is the only thing
binding a presented secret to an identity (see
routes/internal_proxy_auth.py's tunnel_auth), and the column has no
uniqueness constraint, so fetchone() on a duplicate would pick a
row by undefined ordering and then authenticate against THAT row's
secret. Refusing outright turns it into a 401 someone can find in
the log instead of an intermittent wrong-client attach.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_unassigned_vms()
¶
Get the VMs that are running and have no student assigned.
Returns:
| Name | Type | Description |
|---|---|---|
list |
list
|
hostnames of available VMs. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
get_vm_logs(hostname, log_type=None)
¶
Get the logs of a VM by its hostname.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM. |
required |
log_type
|
str
|
"cloud_init", "docker", or None for both. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
dict |
dict
|
A dict with "cloud_init_logs" and/or "docker_logs", or None if the VM is not found. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
list_hosts_by_provider(provider)
¶
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
list_registered_clients()
¶
Return registered clients as a list of dicts.
Surfaces only operator-safe columns (no secrets, no log blobs). Includes both AWS-provisioned and BYO/manual hosts — they live in the same table; provider distinguishes them.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
list_tunnel_aliases()
¶
Alias octets of every registered reverse-tunnel client.
Used by health to compare registered clients against the set of aliases with a socket actually attached right now (see routes/health.py's tunnel check) -- a registered client isn't necessarily a connected one.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
record_heartbeat(hostname, boot_id, disk_free_pct)
¶
Record a client-VM heartbeat and emit warnings on anomalies.
Updates last_seen_at and the reported health fields. Logs a warning (not an error) when:
- boot_id changed vs the previous value (unexpected host reboot),
- disk_free_pct dropped below 10.
Returns True if the row was updated, False if the hostname is unknown.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 | |
record_reboot(hostname)
¶
Record a reboot attempt for a VM.
Sets status to 'rebooting', increments reboot_count, and updates last_reboot_time.
useremail is preserved so the student keeps their VM slot
across reboots. If reboot attempts are exhausted, the
assignment is explicitly released via release_assignment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM being rebooted. |
required |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
register_client(*, hostname, machine_identity, provider, endpoint_url, provider_metadata, gpu_present, gpu_model, client_secret_hash)
¶
Atomically register (or idempotently re-register) a client.
Single upsert keyed on the hostname primary key:
- hostname row absent -> INSERT (fresh client)
- row exists, machine_identity NULL -> adopt (stamp identity+secret)
- row exists, same machine_identity -> rotate secret (re-register)
- row exists, different machine_identity -> no-hijack: the
conditional DO UPDATE matches 0 rows, RETURNING is empty, this
returns None (the route maps that to 409).
Returns the row's hostname on success, or None on the no-hijack
conflict. May raise psycopg2.IntegrityError if this
machine_identity is already bound to a different hostname
(the partial-unique index on machine_identity) — the route maps
that to 409 as well. The single statement is atomic under the
pool's autocommit isolation, so concurrent/overlapping registers
converge instead of silently corrupting or 500-ing.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
release_assignment(hostname)
¶
Release a VM's student assignment when it is deemed unrecoverable.
Called by the auto-reboot service when reboot_count exceeds max_attempts. Clears useremail and sets status to 'error' so the pool reflects the VM as unassignable until an admin intervenes. reboot_count is preserved for diagnostics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM whose assignment is being released. |
required |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
release_expired_admin_sessions(timeout_minutes)
¶
Release any admin-reserved VM whose reservation has outlived timeout_minutes, returning it to the assignable pool.
Called periodically by AdminSessionExpiryService as the safety-net backstop for admins who close the troubleshooting tab without clicking Release.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timeout_minutes
|
int
|
Age, in minutes, past which a reservation is considered expired. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The number of VMs released. |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
release_seat(*, hostname)
¶
Clear useremail and every per-session column on a VM row, returning the seat to the available pool. Also clears AdminReservedAt — a no-op for ordinary student releases (already NULL there), but what actually frees a VM an admin reserved for troubleshooting.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
set_overlay_hostname(*, hostname, overlay_hostname)
¶
Reconcile a mesh-overlay client's recorded overlay hostname with the name Tailscale actually assigned it.
tailscale up --hostname=X does NOT guarantee the node is named X:
if an earlier (possibly offline) node still holds X, Tailscale
appends a numeric suffix and still exits 0. The name we recorded at
registration is therefore only a request, and after any
re-registration it can point at a dead node — every allocator ->
client dial then black-holes (lablink#404). The client reports the
real name after joining; this persists it.
Guarded on the key already existing so this can only ever correct a
mesh-overlay client: a lan_direct or AWS client cannot have an
overlay_hostname injected into its provider_metadata. Returns True
when a row was updated, False for an unknown or non-overlay host.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
set_setting(key, value)
¶
UPSERT a row in the settings (key, value) table.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
touch_last_seen(hostname)
¶
Bump last_seen_at for a VM without touching other columns.
Called at the top of every authenticated client->allocator endpoint so that any client traffic refreshes the liveness timer. Heartbeat remains the primary signal; this is cheap insurance against false-positive staleness.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
unregister_client(client_id)
¶
Delete the client row keyed on hostname.
Returns True if a row was deleted, False if no such row existed. Single statement under autocommit isolation — no migration.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
update_health(hostname, healthy)
¶
Modify the health status of a VM.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM. |
required |
healthy
|
str
|
The health status to set for the VM. |
required |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
update_tofu_timing(hostname, per_instance_seconds, per_instance_start_time, per_instance_end_time)
¶
Update the OpenTofu timing metrics for a VM. Args: hostname (str): The hostname of the VM. per_instance_seconds (float): The total startup duration in seconds. per_instance_start_time (datetime): The start time of the OpenTofu apply. per_instance_end_time (datetime): The end time of the OpenTofu apply.
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
update_vm_in_use(hostname, in_use)
¶
Update the in-use status of a VM.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM. |
required |
in_use
|
bool
|
The in-use status to set. |
required |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
update_vm_metrics_atomic(hostname, metrics)
¶
Update VM metrics and calculate total startup time in a single transaction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM. |
required |
metrics
|
dict
|
A dictionary containing the timing metrics to update. Supported keys: - cloud_init_start (int): Unix timestamp - cloud_init_end (int): Unix timestamp - cloud_init_duration_seconds (float) - container_start (int): Unix timestamp - container_end (int): Unix timestamp - container_startup_duration_seconds (float) |
required |
Raises:
| Type | Description |
|---|---|
Exception
|
If the database operation fails (re-raised after rollback). |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 | |
update_vm_status(hostname, status)
¶
Update the status of a VM by its hostname.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM. |
required |
status
|
str
|
The new status to set for the VM. |
required |
Source code in packages/allocator/src/lablink_allocator_service/db/vms.py
vm_exists(hostname)
¶
Check if a VM with the given hostname exists in the table.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hostname
|
str
|
The hostname of the VM. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if the VM exists, False otherwise. |