bus-api-provider-vm — VM API provider
bus-api-provider-vm — VM API provider
bus-api-provider-vm is the server-side provider for cloud-neutral VM/runtime
APIs.
In events mode, the provider sends VM lifecycle requests through the Bus Events
API. A deployment can pair it with bus-integration-upcloud when the backing
runtime is UpCloud.
LLM deployments can use this provider behind bus-api-provider-llm runtime
wake-up. The LLM provider should wake or check runtime readiness only for
execution requests; model catalog reads can stay local and avoid waking GPU
backends.
Authentication
Requests use Bearer JWT authentication with audience ai.hg.fi/api.
Status reads require vm:read. Lifecycle writes require vm:write.
Send the token as Authorization: Bearer <jwt>. End users normally obtain the
token with bus auth token --scope "vm:read vm:write" after their account is
verified and approved; services use deployment-managed service tokens.
The curl examples below target the root compose.yaml nginx gateway at
LOCAL_AI_PLATFORM_PORT, which proxies to the provider. For a standalone
provider started directly on 127.0.0.1:8085, replace the base URL with
http://127.0.0.1:8085.
bus auth token --scope "vm:read vm:write"
TOKEN="$(cat ~/.config/bus/auth/api-token)"
GET /api/v1/vm/status
Returns user-visible runtime status.
Status reads are not quota-gated and are not treated as billable lifecycle
events.
The request body is empty. Success returns 200 OK with
{"status":{"state":"ready","provider":"...","details":{}}}.
The response object contains status.state (known values include ready,
starting, stopped, and unavailable), status.provider, and optional
status.details. Clients should display unknown future states as-is and treat
them as not ready unless the deployment documents otherwise.
curl -fsS \
-H "Authorization: Bearer $TOKEN" \
http://127.0.0.1:${LOCAL_AI_PLATFORM_PORT:-8080}/api/v1/vm/status
POST /api/v1/vm/start
Requests runtime start.
With billing enabled, the provider checks vm:write entitlement before sending
worker requests or recording lifecycle usage.
The request body is empty. Success returns 202 Accepted with
{"accepted":true,"action":"start"}.
curl -fsS -X POST \
-H "Authorization: Bearer $TOKEN" \
http://127.0.0.1:${LOCAL_AI_PLATFORM_PORT:-8080}/api/v1/vm/start
POST /api/v1/vm/stop
Requests runtime stop.
Use this only for runtime products where the caller is allowed to control the
target runtime.
The request body is empty. Success returns 202 Accepted with
{"accepted":true,"action":"stop"}.
curl -fsS -X POST \
-H "Authorization: Bearer $TOKEN" \
http://127.0.0.1:${LOCAL_AI_PLATFORM_PORT:-8080}/api/v1/vm/stop
GET /readyz
Reports provider readiness.
When BUS_EVENTS_LISTENER_REQUIRED=1, readiness is unhealthy until required
VM, usage, and billing response streams are connected.
curl -fsS http://127.0.0.1:8085/readyz
A ready provider returns 200 OK with {"ok":true}. If required Events
listeners are unavailable, readiness returns a non-2xx status with a JSON error
body.
--backend <static|events>
Selects the VM backend.
Use static for deterministic local checks. Use events for Bus Events
request/reply mode. The default is deployment-configured; standalone local
checks usually use static, while production runtime control uses events.
Static local provider:
BUS_VM_JWT_SECRET=not-a-secret-local-development-hs256-key \
bus-api-provider-vm --addr 127.0.0.1:8085 --backend static
For direct standalone curl checks against that static provider, mint the local token with the same HS256 secret and scopes:
TOKEN="$(BUS_AUTH_HS256_SECRET=not-a-secret-local-development-hs256-key bus operator token --format token issue --local --audience ai.hg.fi/api --scope 'vm:read vm:write')"
Events-backed provider:
BUS_VM_JWT_SECRET=dev-secret \
BUS_API_TOKEN="$(cat ./local/vm-provider.token)" \
bus-api-provider-vm \
--addr 127.0.0.1:8085 \
--backend events \
--events-url http://127.0.0.1:8081 \
--usage-backend events \
--billing-backend events
The provider token needs vm:read and vm:write for VM request/reply events.
Add usage:write when --usage-backend events is enabled and
billing:entitlement:check when --billing-backend events is enabled.
--events-url <url>
Sets the Bus Events API URL when Events mode is enabled.
Provide the provider token through deployment-managed configuration such as
BUS_API_TOKEN.
--backend events, --billing-backend events, and --usage-backend events
require --events-url or BUS_EVENTS_API_URL plus a provider token with the
matching VM, billing, and usage event scopes.
--billing-backend <none|events>
Enables billing entitlement checks for lifecycle write requests.
Denied requests return HTTP 402 with billing setup or quota guidance.
Default is none; use events for paid VM lifecycle plans.
--usage-backend <none|events|memory>
Enables runtime lifecycle usage records through bus-integration-usage.
Start and stop requests can record requested, finished, and failed lifecycle
events with the stable account UUID.
Default is none. Use events when usage should flow to
bus-integration-usage, or memory for deterministic local checks that should
not publish usage records to a shared Events API.
Common errors use {"error":{"type":"...","message":"..."}}. Missing or
invalid bearer tokens return 401 invalid_auth, missing scopes return
401/403 depending gateway policy, entitlement denial returns 402, event
backend unavailability returns 503, and malformed integration responses
return 502.
For GET /api/v1/vm/status, callers should fix authentication or vm:read scope errors
and retry later on backend 503. For POST /api/v1/vm/start and
POST /api/v1/vm/stop, callers
also need vm:write; 402 means billing setup or quota action is required
before retrying the lifecycle request.
Local Compose Stack
The BusDK superproject compose.yaml starts this provider as bus-vm with
--backend static, --usage-backend memory, and --billing-backend none.
Nginx exposes it at /api/v1/vm/* on the local API port. The static backend is
for deterministic local AI Platform checks, including /api/v1/vm/status
returning provider static; deployments that control real runtimes should use
Events mode with a VM integration backend.