control node
- GET /controlnode/bmc/{bmc_ip}/disks
Get available disks and NICs for a BMC
Fetch disk and NIC information from NetBox database for UI selection
- Parameters:
bmc_ip (string) – BMC IP Address
- Status Codes:
200 OK – OK
404 Not Found – BMC not found
500 Internal Server Error – Internal Server Error
- GET /controlnode/bmc/{bmc_ip}/gpus
Get available GPUs for a BMC
Fetch GPU inventory information from NetBox for UI selection
- Parameters:
bmc_ip (string) – BMC IP Address
- Status Codes:
200 OK – OK
400 Bad Request – BMC IP required
500 Internal Server Error – Internal Server Error
- DELETE /controlnode/fabric-config
Delete network fabric configuration
Deletes the cluster-wide network fabric configuration (hard delete).
- Status Codes:
200 OK – Config deleted
204 No Content – No config to delete (idempotent)
503 Service Unavailable – Database not available
- GET /controlnode/fabric-config
Get the current network fabric config
Returns the cluster-wide FabricConfig row.
- Status Codes:
200 OK – OK
204 No Content – No fabric configured (no FabricConfig row)
503 Service Unavailable – Database not available
- Response JSON Object:
acked_by (string) – operator identity for audit log
advertise_all_vni (boolean)
as (integer) – BGP core
bfd_enabled (boolean)
bgp_mode (string) – read-only derived: “ibgp” | “ebgp”
bgp_password (string) – inbound plaintext (POST/PUT only)
bgp_password_is_set (boolean) – read-only: a secret is configured
clear_bgp_password (boolean) – explicit removal (empty input = “unchanged”)
clear_ospf_auth_key (boolean)
expected_nodes (integer) – Sizing hints. Drive VTEP pool calc + capacity warnings. Validated 1..1000 / 1..10000. 0 = unset, validation skipped on POST/apply when entire row predates the field (legacy rows). Plan path requires.
expected_vms (integer)
external_route_reflector (boolean) – ExternalRouteReflector — when true, the BGP route-reflector lives on the fabric switch (PICA8 / Cumulus / Cisco / Arista with RR config rendered via switch_templates.go). Cube software-RR on the GW Linux node is dropped: cube GW becomes a regular iBGP peer of the external switch RR. When false (default), the existing cube GW software-RR model remains. Defaults false to preserve existing-deployment behaviour. Validator (validate.go) requires fabric_switch_peering_ip + fabric_switch_as + a BGP-EVPN-capable NOS when this is true.
fabric_switch_as (integer)
fabric_switch_name (string) – Fabric switch — only what’s needed for BGP peering
fabric_switch_nos (string) – sonic, cumulus, nxos, eos
fabric_switch_peering_ip (string) – Loopback IP = BGP peer address
fabric_switch_role (string) – spine, leaf, border-leaf
frr_hmac_sha_capable (boolean) – FRRHMACShaCapable is the result of the preflight HMAC-SHA capability probe (controlnode/fabric/preflight.go). Tri-state pointer: nil = never probed (HMAC blocked by validation until proven), false = probed unsupported, true = probed supported. Read-only to the API.
last_job (any) – LastJob carries the latest fabric_apply / fabric_teardown job view inline when RolloutStatus is failed or degraded. Populated by GetNetworkFabricConfig from configure.Jobs via fabric.GetLatestFabricJob so a single GET shows both the declared intent and the last observed failure reason (including first_fail_node + first_fail_error and the per-node Nodes[] slice). UI renders without a second round-trip to /fabric-config/latest. Type is any rather than *fabric.FabricJobView to avoid a controlnode/models → controlnode/fabric import cycle (fabric already imports controlnode/models). The handler assigns the FabricJobView pointer directly; JSON marshal preserves the same shape FabricJobView serialises to today.
management_cidr (string) – VTEP IP allocation (managed by evpn_setup at runtime)
ospf_area (string)
ospf_auth_key (string) – inbound plaintext (POST/PUT only)
ospf_auth_key_id (integer)
ospf_auth_key_is_set (boolean) – read-only: a key is configured
ospf_auth_type (string) – OSPF underlay authentication. Type ∈ {”” / “none”, “message-digest”, “hmac-sha-256”}. FRR OSPF auth is PER-INTERFACE, so a non-none type requires OSPFFabricInterface (enforced in validate.go). hmac-sha-256 is gated by the preflight FRR-capability probe (FRRHMACShaCapable). OSPFAuthKey is the secret, stored AES-256-GCM (same scheme as BGPPassword); write-only with input/is_set transient fields.
ospf_auto_ref_bw (integer)
ospf_dead_interval (integer)
ospf_enabled (boolean) – OSPF underlay
ospf_fabric_interface (string) – Interface facing the fabric switch (e.g., “eth1”)
ospf_hello_interval (integer)
physnet (any) – PhysnetStatus is a read-only projection of the VXLAN fabric physical network (present / has-Guest-traffic-type / id). Not persisted (gorm:”-“); populated only on GET by GetNetworkFabricConfig. Mirrors the LastJob transient-field pattern so the UI response shape stays FabricConfig. Defined locally (not network/utils.VXLANPhysnetStatus) because network/utils imports controlnode — a direct import here would close a cycle. The handler converts.
public_mtu (integer)
rollout_status (string) – RolloutStatus tracks propagation of this fabric to compute nodes. Values: “pending” | “rolling_out” | “ready” | “failed” | “degraded”. Empty string is treated as “ready” for rows predating this column. Used by controlnode/fabric.CheckVXLANAllowed to gate VXLAN physnet and L2 guest-network creation — both require status=ready.
router_id_base (string) – VTEP loopback start IP (e.g., “10.255.0.1”)
router_id_cidr (string) – RouterIDCIDR is a transient convenience: a single “A.B.C.D/N” the UI sends instead of base+prefixlen. When present it is decoded server-side into the authoritative RouterIDBase + RouterIDPrefixLen. GET re-emits it (derived) so the UI can render one field. Never persisted (gorm:”-“).
router_id_prefix_len (integer) – Subnet prefix length (e.g., 24 for /24)
skip_switch_ack (boolean) – lab/CI bypass — production should require FABRIC_ADMIN perm
switch_acked (boolean) – Switch-side ack-gate fields for VTEP-pool resize. Transient — accepted on the POST request body, never persisted (gorm:”-“). When the operator changes RouterIDBase / RouterIDPrefixLen, karios-core returns 409 REQUIRES_SWITCH_RECONFIG_ACK with per-NOS BGP listen-range diff snippets. Operator pastes the snippet on the fabric switch, runs the verify command, then re-POSTs with these fields populated.
switch_nos (string) – NOS being acked (defaults to FabricSwitchNOS)
switch_snippet_hash (string) – sha256 echoed from the 409 response
vxlan_mtu (integer) – VXLAN
- POST /controlnode/fabric-config
Store network fabric configuration
Stores or updates the cluster-wide network fabric configuration (BGP AS, OSPF, fabric switch info, VTEP settings, BFD, etc.). Called by karios-bootstrap during initial setup. Uses upsert semantics — creates on first call, updates on subsequent. This config is later read by configureFRRForNode during compute node setup to generate frr.conf and allocate VTEP IPs.
- Request JSON Object:
acked_by (string) – operator identity for audit log
advertise_all_vni (boolean)
as (integer) – BGP core
bfd_enabled (boolean)
bgp_mode (string) – read-only derived: “ibgp” | “ebgp”
bgp_password (string) – inbound plaintext (POST/PUT only)
bgp_password_is_set (boolean) – read-only: a secret is configured
clear_bgp_password (boolean) – explicit removal (empty input = “unchanged”)
clear_ospf_auth_key (boolean)
expected_nodes (integer) – Sizing hints. Drive VTEP pool calc + capacity warnings. Validated 1..1000 / 1..10000. 0 = unset, validation skipped on POST/apply when entire row predates the field (legacy rows). Plan path requires.
expected_vms (integer)
external_route_reflector (boolean) – ExternalRouteReflector — when true, the BGP route-reflector lives on the fabric switch (PICA8 / Cumulus / Cisco / Arista with RR config rendered via switch_templates.go). Cube software-RR on the GW Linux node is dropped: cube GW becomes a regular iBGP peer of the external switch RR. When false (default), the existing cube GW software-RR model remains. Defaults false to preserve existing-deployment behaviour. Validator (validate.go) requires fabric_switch_peering_ip + fabric_switch_as + a BGP-EVPN-capable NOS when this is true.
fabric_switch_as (integer)
fabric_switch_name (string) – Fabric switch — only what’s needed for BGP peering
fabric_switch_nos (string) – sonic, cumulus, nxos, eos
fabric_switch_peering_ip (string) – Loopback IP = BGP peer address
fabric_switch_role (string) – spine, leaf, border-leaf
frr_hmac_sha_capable (boolean) – FRRHMACShaCapable is the result of the preflight HMAC-SHA capability probe (controlnode/fabric/preflight.go). Tri-state pointer: nil = never probed (HMAC blocked by validation until proven), false = probed unsupported, true = probed supported. Read-only to the API.
last_job (any) – LastJob carries the latest fabric_apply / fabric_teardown job view inline when RolloutStatus is failed or degraded. Populated by GetNetworkFabricConfig from configure.Jobs via fabric.GetLatestFabricJob so a single GET shows both the declared intent and the last observed failure reason (including first_fail_node + first_fail_error and the per-node Nodes[] slice). UI renders without a second round-trip to /fabric-config/latest. Type is any rather than *fabric.FabricJobView to avoid a controlnode/models → controlnode/fabric import cycle (fabric already imports controlnode/models). The handler assigns the FabricJobView pointer directly; JSON marshal preserves the same shape FabricJobView serialises to today.
management_cidr (string) – VTEP IP allocation (managed by evpn_setup at runtime)
ospf_area (string)
ospf_auth_key (string) – inbound plaintext (POST/PUT only)
ospf_auth_key_id (integer)
ospf_auth_key_is_set (boolean) – read-only: a key is configured
ospf_auth_type (string) – OSPF underlay authentication. Type ∈ {”” / “none”, “message-digest”, “hmac-sha-256”}. FRR OSPF auth is PER-INTERFACE, so a non-none type requires OSPFFabricInterface (enforced in validate.go). hmac-sha-256 is gated by the preflight FRR-capability probe (FRRHMACShaCapable). OSPFAuthKey is the secret, stored AES-256-GCM (same scheme as BGPPassword); write-only with input/is_set transient fields.
ospf_auto_ref_bw (integer)
ospf_dead_interval (integer)
ospf_enabled (boolean) – OSPF underlay
ospf_fabric_interface (string) – Interface facing the fabric switch (e.g., “eth1”)
ospf_hello_interval (integer)
physnet (any) – PhysnetStatus is a read-only projection of the VXLAN fabric physical network (present / has-Guest-traffic-type / id). Not persisted (gorm:”-“); populated only on GET by GetNetworkFabricConfig. Mirrors the LastJob transient-field pattern so the UI response shape stays FabricConfig. Defined locally (not network/utils.VXLANPhysnetStatus) because network/utils imports controlnode — a direct import here would close a cycle. The handler converts.
public_mtu (integer)
rollout_status (string) – RolloutStatus tracks propagation of this fabric to compute nodes. Values: “pending” | “rolling_out” | “ready” | “failed” | “degraded”. Empty string is treated as “ready” for rows predating this column. Used by controlnode/fabric.CheckVXLANAllowed to gate VXLAN physnet and L2 guest-network creation — both require status=ready.
router_id_base (string) – VTEP loopback start IP (e.g., “10.255.0.1”)
router_id_cidr (string) – RouterIDCIDR is a transient convenience: a single “A.B.C.D/N” the UI sends instead of base+prefixlen. When present it is decoded server-side into the authoritative RouterIDBase + RouterIDPrefixLen. GET re-emits it (derived) so the UI can render one field. Never persisted (gorm:”-“).
router_id_prefix_len (integer) – Subnet prefix length (e.g., 24 for /24)
skip_switch_ack (boolean) – lab/CI bypass — production should require FABRIC_ADMIN perm
switch_acked (boolean) – Switch-side ack-gate fields for VTEP-pool resize. Transient — accepted on the POST request body, never persisted (gorm:”-“). When the operator changes RouterIDBase / RouterIDPrefixLen, karios-core returns 409 REQUIRES_SWITCH_RECONFIG_ACK with per-NOS BGP listen-range diff snippets. Operator pastes the snippet on the fabric switch, runs the verify command, then re-POSTs with these fields populated.
switch_nos (string) – NOS being acked (defaults to FabricSwitchNOS)
switch_snippet_hash (string) – sha256 echoed from the 409 response
vxlan_mtu (integer) – VXLAN
- Status Codes:
200 OK – Config updated
201 Created – Config created
400 Bad Request – Invalid request
500 Internal Server Error – Database error
503 Service Unavailable – Database not available
- POST /controlnode/fabric-config/apply
Manually trigger a fabric rollout to compute nodes
Re-runs the EVPN setup steps (FRR install, dpkg-divert, vtep0, BGP config, MTU sync) on every registered compute node. Use after recovering from a failed/degraded rollout, or to force re-apply when a new compute node has joined. Returns 202 with apply_job_id; SSE channel “fabric” event_type “fabric_switch” streams per-node progress.
- Status Codes:
202 Accepted – Apply job scheduled
403 Forbidden – No fabric configured
409 Conflict – Apply already in progress
503 Service Unavailable – Database not available
- Response JSON Object:
apply_job_id (string)
created (boolean) – true if new record, false if updated
id (integer)
message (string)
- POST /controlnode/fabric-config/apply/{job_id}/cancel
Cancel an in-flight fabric apply
Aborts the currently running fabric apply job and rolls the cluster back to baseline (same teardown path strict-mode uses on per-node failure). Returns 202 immediately; the cancellation completes asynchronously via the apply_cancelling → apply_cancelled SSE sequence. Idempotent — multiple cancel calls for the same job_id are safe. Returns 404 when the job_id does not match the in-flight apply (already terminal, wrong id, or never existed).
- Parameters:
job_id (string) – Apply job UUID
- Status Codes:
202 Accepted – Cancellation initiated
404 Not Found – Job not found or already terminal
- GET /controlnode/fabric-config/batches/{id}/postdeploy
Post-deployment aggregate for a provisioning batch
- Parameters:
id (string) – provision batch id
- Status Codes:
200 OK – OK
503 Service Unavailable – runtime not initialised
- GET /controlnode/fabric-config/latest
Get the most recent fabric lifecycle job
Returns the latest fabric_apply or fabric_teardown job row — used by the UI on page refresh to replay the last rollout or teardown state when SSE connection is fresh and missed prior events. JobType field distinguishes apply vs teardown.
- Status Codes:
200 OK – OK
204 No Content – No fabric job yet (nothing to replay)
500 Internal Server Error – DB error loading latest fabric job
503 Service Unavailable – Database not available
- Response JSON Object:
completed_nodes (integer)
created_at (string)
error (string)
fabric_id (string)
failed_nodes (integer)
first_fail_error (string)
first_fail_node (string) – FirstFailNode + FirstFailError surface the first per-node failure verbatim so a UI rendering only the headline shows the real reason (e.g. “BGP neighbor 172.30.10.254 not Established”) without walking Nodes[]. Populated by finalizeApply on failed/degraded outcomes.
job_id (string)
job_status (string) – running|completed|failed|partial
job_type (string) – fabric_apply | fabric_teardown
nodes[].error (string)
nodes[].fqdn (string)
nodes[].node_ip (string)
nodes[].ok (boolean)
nodes[].reachable (boolean) – false = SSH dial failed before EVPN step ran
progress (integer) – 0..100
state (string) – last SSE state: apply_*/teardown_*/node_*
total_nodes (integer)
updated_at (string)
- DELETE /controlnode/fabric-config/node/{node_ip}
Tear down EVPN/FRR on a single node
- Parameters:
node_ip (string) – OS IP of the target node
- Status Codes:
200 OK – OK
400 Bad Request – invalid node_ip
403 Forbidden – no fabric configured
502 Bad Gateway – node teardown failed
- Response JSON Object:
message (string)
removed (boolean)
steps[] (string)
- POST /controlnode/fabric-config/node/{node_ip}/apply
Apply EVPN/FRR config to a single node
- Parameters:
node_ip (string) – OS IP of the target node
- Status Codes:
202 Accepted – apply scheduled — watch fabric_switch SSE by apply_job_id
400 Bad Request – invalid node_ip / node not found
403 Forbidden – no fabric configured
503 Service Unavailable – post-deploy runtime not initialised on this node
- GET /controlnode/fabric-config/node/{node_ip}/postdeploy
Post-deployment step checklist for one node
- Parameters:
node_ip (string) – OS IP of the node
- Status Codes:
200 OK – OK
400 Bad Request – invalid node_ip
503 Service Unavailable – runtime not initialised
- Response JSON Object:
[].batch_id (string)
[].bmc_ip (string) – BMCIP is carried because the ENTIRE web batch surface keys by bmc_ip (store key bmc:${bmc_ip}, batch rows carry only bmc_ip) and has no os_ip↔bmc_ip bridge — the backend owns the wire shape, so it ships both identities rather than forcing a UI-side lookup that does not exist.
[].created_at (string)
[].message (string)
[].node_ip (string)
[].progress (integer)
[].status (string)
[].step_id (string)
[].updated_at (string)
- POST /controlnode/fabric-config/plan
Dry-run a fabric configuration
Returns a preview FabricConfig with auto-sized VTEP pool, suggested switch ASN/peering IP, VNI range, plan_hash, and operator-actionable risks/notes. No DB write — operator commits via POST /controlnode/fabric-config.
- Request JSON Object:
expected_nodes (integer) – sizing hint only — planner auto-picks default VTEP prefix when unset
expected_vms (integer) – sizing hint for tenant subnets (notes only)
fabric_switch_as (integer) – 0 => planner suggests
fabric_switch_name (string)
fabric_switch_nos (string) – sonic|cumulus|nxos|eos|other (required)
fabric_switch_peering_ip (string) – empty => planner suggests
fabric_switch_role (string) – spine|leaf|border-leaf
local_as (integer) – 0 => auto-pick
management_cidr (string) – e.g. “192.168.111.0/24” (required)
public_mtu (integer) – VR public-side MTU — required in DC mode, ignored in Cube (no VR)
router_id_base (string) – empty => 10.255.0.0 default
router_id_prefix_len (integer) – 0 => auto-size; operator value honored verbatim
underlay_mode (string) – “” / “ospf” (default) | “bgp” (no-OSPF: one iBGP session over the mgmt subnet carries ipv4-unicast loopback /32s + EVPN — lab-proven env05/env06)
vxlan_mtu (integer) – fabric/data-plane MTU (1500 default; 9216 max for jumbo on 100GbE) (required)
- Status Codes:
200 OK – OK
400 Bad Request – Invalid payload
- Response JSON Object:
config.advertise_all_vni (boolean)
config.as (integer)
config.bfd_enabled (boolean)
config.bgp_password (string)
config.fabric_switch_as (integer)
config.fabric_switch_name (string)
config.fabric_switch_nos (string)
config.fabric_switch_peering_ip (string)
config.fabric_switch_role (string)
config.management_cidr (string)
config.ospf_area (string)
config.ospf_auto_ref_bw (integer)
config.ospf_dead_interval (integer)
config.ospf_enabled (boolean)
config.ospf_fabric_interface (string)
config.ospf_hello_interval (integer)
config.public_mtu (integer)
config.rollout_status (string)
config.router_id_base (string)
config.router_id_prefix_len (integer)
config.vxlan_mtu (integer)
deployment_mode (string)
notes[] (string)
plan_hash (string)
risks[] (string)
switch_config (string) – rendered for cfg.FabricSwitchNOS only; use “other” for vendor-neutral reference
vtep_capacity (integer)
- POST /controlnode/fabric-config/preflight
Preflight underlay resolution per compute node
POST (not GET) because (a) future iterations carry a node_overrides[] array that doesn’t fit cleanly in a query string, (b) preflight does an SSH fan-out which is not “safe” in the HTTP-method sense, and (c) GET responses risk being cached by intermediaries while preflight is live cluster state. Matches the pattern used by GraphQL, Elasticsearch _search, and k8s dry-run. Read-only: scans every compute node’s bridges and returns whether each one has a bridge with an IPv4 address inside the supplied underlay_cidr. Nodes resolving via an existing bridge enter mode=reuse (no operator input needed). Nodes that don’t resolve return mode=needs_override. Used by the UI to gate the Save&Apply button and to populate the per-node bridge field. No kernel mutation occurs.
- Request JSON Object:
expected_nodes (integer) – override stored sizing hint for capacity warn
node_overrides[].node_ip (string) – (required)
node_overrides[].underlay_bridge_name (string) – optional, derive from CIDR when empty
node_overrides[].underlay_iface_hint (string) – (required)
node_overrides[].underlay_ip (string) – host/CIDR, e.g. “10.60.200.5/24” (required)
router_id_base (string) – VTEP pool base, falls back to stored FabricConfig
router_id_prefix_len (integer) – VTEP pool prefix, falls back to stored FabricConfig
underlay_cidr (string) – IPv4 CIDR, e.g. “10.60.200.0/24” (required)
- Status Codes:
200 OK – OK
400 Bad Request – Missing or invalid underlay_cidr
503 Service Unavailable – Database not available
- Response JSON Object:
matched_bridges[] (string)
mtu_drift[].bridge (string)
mtu_drift[].bridge_mtu (integer)
mtu_drift[].fqdn (string)
mtu_drift[].node_ip (string)
nodes[].bridge (string) – populated when Mode=reuse
nodes[].bridge_mtu (integer) – live kernel MTU of the matched bridge (Mode=reuse only). 0 when iface absent or non-reuse.
nodes[].fqdn (string)
nodes[].mode (string)
nodes[].needs_override (boolean)
nodes[].node_ip (string)
nodes[].reason (string) – human-readable explanation when Mode=needs_override or unreachable
nodes[].underlay_ip (string) – existing IP/CIDR on the bridge, populated when Mode=reuse
ready (boolean) – true ⟺ every node ∈ {reuse}; needs_override or unreachable flips this to false
underlay_cidr (string)
underlay_mtu (integer) – UnderlayMTU is the cluster-wide consensus MTU across reuse-mode nodes’ matched underlay bridges. It is the value the UI should auto-populate into the fabric-config form’s vxlan_mtu field and the value the backend rejects drift against (see ErrMTUDriftRejected in validate.go). Resolution: - All reuse-mode nodes agree on MTU N (>0) → UnderlayMTU = N, MTUDrift empty - Reuse-mode nodes disagree → UnderlayMTU = 0, MTUDrift populated with every observed (node, mtu) pair - No reuse-mode nodes (cold-start cluster) → UnderlayMTU = 0, MTUDrift empty
vtep_pool.capacity (integer) – usable host count in the pool
vtep_pool.expected_nodes (integer) – operator-declared sizing hint (FabricConfig.ExpectedNodes)
vtep_pool.headroom (integer) – capacity - expected_nodes
vtep_pool.overalloc_warn (boolean) – true when headroom < 0
vtep_pool.router_id_base (string)
vtep_pool.router_id_prefix_len (integer)
- GET /controlnode/fabric-config/vtep-pool
Get VTEP IP pool status
Returns the current capacity of the VTEP loopback IP pool: total, allocated, remaining, and whether the pool is exhausted. Reads from FabricConfig in DB.
- Status Codes:
200 OK – Pool snapshot
204 No Content – No fabric config yet (greenfield) — UI hides the pool banner
503 Service Unavailable – Database not available
- Response JSON Object:
allocated (integer) – Number of IPs already assigned
exhausted (boolean) – True if no IPs remain
last_allocated_ip (string) – Most recently assigned IP
prefix_length (integer) – Subnet prefix (e.g. 24)
remaining (integer) – IPs still available
router_id_base (string) – Base IP (e.g. “10.255.0.1”)
start_ip (string) – First usable IP in the pool
subnet_cidr (string) – Network CIDR (e.g. “10.255.0.0/24”)
total_usable (integer) – Total usable IPs (excluding .0 and .255 per /24 block)
- POST /controlnode/firstboot
Receive first boot OS IP report
Called by installed OS on first boot to report its IP address
- Request JSON Object:
bmc_ip (string) – (required)
os_ip (string) – (required)
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
500 Internal Server Error – Internal Server Error
- GET /controlnode/job/{id}
Get Job Status
Retrieve job status and details by job ID
- Parameters:
id (string) – Job-Id
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
404 Not Found – Not Found
- Response JSON Object:
created_at (string)
id (string)
job_status (string)
job_type (string)
metadata (string)
node_ip (string)
parent_id (string)
progress (integer)
resource_name (string)
status (string)
total_jobs (integer)
updated_at (string)
- PATCH /controlnode/job/{id}
Patch Job Status
Patch job related status with given id
- Parameters:
id (string) – Job-Id
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
401 Unauthorized – Unauthorized
404 Not Found – Not Found
500 Internal Server Error – Internal Server Error
- Response JSON Object:
created_at (string)
id (string)
job_status (string)
job_type (string)
metadata (string)
node_ip (string)
parent_id (string)
progress (integer)
resource_name (string)
status (string)
total_jobs (integer)
updated_at (string)
- POST /controlnode/job/{id}/cancel
Cancel a running provision job
Cancels a running provision job by job ID
- Parameters:
id (string) – Job ID (UUID)
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
404 Not Found – Not Found
500 Internal Server Error – Internal Server Error
- POST /controlnode/job/{id}/complete
Mark job as installation complete
HTTP callback from installation script to signal that OS installation is complete
- Parameters:
id (string) – Job ID
- Request JSON Object:
os_ip (string)
os_password (string)
- Status Codes:
200 OK – OK
404 Not Found – Job not found
500 Internal Server Error – Internal Server Error
- POST /controlnode/job/{id}/step
Receive an install step status report from the live ISO
Called by the provisioning script running on the target node to report each OS installation step. Broadcasts step progress via SSE, updates job status, and resets the stuck-detection timer. No auth required.
- Parameters:
id (string) – Job ID
- Request JSON Object:
percent (integer)
state (string) – “active” | “done” | “failed” (required)
step (string) – (required)
- Status Codes:
200 OK – OK
400 Bad Request – Invalid payload
404 Not Found – Job not found
- POST /controlnode/provision
Provision a node with Debian OS
Build custom Debian ISO with preseed and provision via Redfish
- Request JSON Object:
arch (string)
bmc_IP (string) – (required)
branch (string)
cache_dir (string)
controlnode_host (string)
controlnode_port (string)
debian_version (string)
device_id (integer) – NetBox Device ID for tracking
gpu_passthrough (any) – GPU passthrough config for IOMMU/vfio-pci
hostname (string)
kubernetes_cluster_name (string)
kubernetes_cluster_type (string)
location (string)
mac_address (string)
network_role (string) – IPAM fields for static IP allocation
os_password (string) – OS password (default: adminadmin)
os_username (string) – OS credentials for provisioned system
output_iso (string)
pool_type (string) – “mirror”, “raidz1”, “raidz2”, “stripe”, “single”
prefix_id (integer) – Prefix ID from VLAN query response
pxe_path (string)
pxe_server (string)
rack_number (string)
root_pass (string)
selected_disks[] (string)
selected_nic (string) – e.g., “enp0s3” - DHCP enabled on this interface
selected_nic_legacy (string) – Legacy kernel name for the NIC (e.g., “eth0”)
selected_nic_mac (string) – MAC address of the selected NIC
sys_iuri (string)
vendor (string) – (required)
vm_slot (string)
zone (string)
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
404 Not Found – Not Found
500 Internal Server Error – Internal Server Error
- POST /controlnode/provision/cisco
Provision a Cisco node with Debian OS
Build custom Debian ISO with preseed and provision via Cisco CIMC Redfish
- Request JSON Object:
arch (string)
bmc_IP (string) – (required)
branch (string)
cache_dir (string)
controlnode_host (string)
controlnode_port (string)
debian_version (string)
device_id (integer) – NetBox Device ID for tracking
gpu_passthrough (any) – GPU passthrough config for IOMMU/vfio-pci
hostname (string)
kubernetes_cluster_name (string)
kubernetes_cluster_type (string)
location (string)
mac_address (string)
network_role (string) – IPAM fields for static IP allocation
os_password (string) – OS password (default: adminadmin)
os_username (string) – OS credentials for provisioned system
output_iso (string)
pool_type (string) – “mirror”, “raidz1”, “raidz2”, “stripe”, “single”
prefix_id (integer) – Prefix ID from VLAN query response
pxe_path (string)
pxe_server (string)
rack_number (string)
root_pass (string)
selected_disks[] (string)
selected_nic (string) – e.g., “enp0s3” - DHCP enabled on this interface
selected_nic_legacy (string) – Legacy kernel name for the NIC (e.g., “eth0”)
selected_nic_mac (string) – MAC address of the selected NIC
sys_iuri (string)
vendor (string) – (required)
vm_slot (string)
zone (string)
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
404 Not Found – Not Found
500 Internal Server Error – Internal Server Error
- POST /controlnode/provision/dell
Provision a Dell node with Debian OS
Build custom Debian ISO with preseed and provision via Dell iDRAC Redfish
- Request JSON Object:
arch (string)
bmc_IP (string) – (required)
branch (string)
cache_dir (string)
controlnode_host (string)
controlnode_port (string)
debian_version (string)
device_id (integer) – NetBox Device ID for tracking
gpu_passthrough (any) – GPU passthrough config for IOMMU/vfio-pci
hostname (string)
kubernetes_cluster_name (string)
kubernetes_cluster_type (string)
location (string)
mac_address (string)
network_role (string) – IPAM fields for static IP allocation
os_password (string) – OS password (default: adminadmin)
os_username (string) – OS credentials for provisioned system
output_iso (string)
pool_type (string) – “mirror”, “raidz1”, “raidz2”, “stripe”, “single”
prefix_id (integer) – Prefix ID from VLAN query response
pxe_path (string)
pxe_server (string)
rack_number (string)
root_pass (string)
selected_disks[] (string)
selected_nic (string) – e.g., “enp0s3” - DHCP enabled on this interface
selected_nic_legacy (string) – Legacy kernel name for the NIC (e.g., “eth0”)
selected_nic_mac (string) – MAC address of the selected NIC
sys_iuri (string)
vendor (string) – (required)
vm_slot (string)
zone (string)
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
404 Not Found – Not Found
500 Internal Server Error – Internal Server Error
- POST /controlnode/provision/hp
Provision an HP node with Debian OS
Build custom Debian ISO with preseed and provision via HPE iLO Redfish
- Request JSON Object:
arch (string)
bmc_IP (string) – (required)
branch (string)
cache_dir (string)
controlnode_host (string)
controlnode_port (string)
debian_version (string)
device_id (integer) – NetBox Device ID for tracking
gpu_passthrough (any) – GPU passthrough config for IOMMU/vfio-pci
hostname (string)
kubernetes_cluster_name (string)
kubernetes_cluster_type (string)
location (string)
mac_address (string)
network_role (string) – IPAM fields for static IP allocation
os_password (string) – OS password (default: adminadmin)
os_username (string) – OS credentials for provisioned system
output_iso (string)
pool_type (string) – “mirror”, “raidz1”, “raidz2”, “stripe”, “single”
prefix_id (integer) – Prefix ID from VLAN query response
pxe_path (string)
pxe_server (string)
rack_number (string)
root_pass (string)
selected_disks[] (string)
selected_nic (string) – e.g., “enp0s3” - DHCP enabled on this interface
selected_nic_legacy (string) – Legacy kernel name for the NIC (e.g., “eth0”)
selected_nic_mac (string) – MAC address of the selected NIC
sys_iuri (string)
vendor (string) – (required)
vm_slot (string)
zone (string)
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
404 Not Found – Not Found
500 Internal Server Error – Internal Server Error
- POST /controlnode/provision/lenovo
Provision a Lenovo node with Debian OS
Build custom Debian ISO with preseed and provision via Lenovo XCC virtual media
- Request JSON Object:
arch (string)
bmc_IP (string) – (required)
branch (string)
cache_dir (string)
controlnode_host (string)
controlnode_port (string)
debian_version (string)
device_id (integer) – NetBox Device ID for tracking
gpu_passthrough (any) – GPU passthrough config for IOMMU/vfio-pci
hostname (string)
kubernetes_cluster_name (string)
kubernetes_cluster_type (string)
location (string)
mac_address (string)
network_role (string) – IPAM fields for static IP allocation
os_password (string) – OS password (default: adminadmin)
os_username (string) – OS credentials for provisioned system
output_iso (string)
pool_type (string) – “mirror”, “raidz1”, “raidz2”, “stripe”, “single”
prefix_id (integer) – Prefix ID from VLAN query response
pxe_path (string)
pxe_server (string)
rack_number (string)
root_pass (string)
selected_disks[] (string)
selected_nic (string) – e.g., “enp0s3” - DHCP enabled on this interface
selected_nic_legacy (string) – Legacy kernel name for the NIC (e.g., “eth0”)
selected_nic_mac (string) – MAC address of the selected NIC
sys_iuri (string)
vendor (string) – (required)
vm_slot (string)
zone (string)
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
404 Not Found – Not Found
500 Internal Server Error – Internal Server Error
- POST /controlnode/provision/progress
Get latest provision progress for a BMC IP
Fetches the most recent provisioning state from provision_progresses table. Useful for UI recovery after timeout/logout.
- Request JSON Object:
bmc_ip (string)
- Status Codes:
200 OK – OK
400 Bad Request – Bad request
404 Not Found – No progress found
500 Internal Server Error – Internal Server Error
- Response JSON Object:
bmc_ip (string)
created_at (string)
id (integer)
job_id (string) – active queue job id for UI cancel recovery
message (string) – detailed status message
percent_complete (integer) – 0-100
stage (string) – e.g., “Building ISO”, “Mounting ISO”, “Installing OS”
status (string) – running, completed, failed, cancelled
updated_at (string)
- POST /controlnode/provision/progress/all
Get all provision progress records for a BMC IP
Fetches all provisioning states from provision_progresses table for a specific BMC IP, ordered by timestamp.
- Request JSON Object:
bmc_ip (string)
- Status Codes:
200 OK – OK
400 Bad Request – Bad request
404 Not Found – No progress found
500 Internal Server Error – Internal Server Error
- Response JSON Object:
[].bmc_ip (string)
[].created_at (string)
[].id (integer)
[].job_id (string) – active queue job id for UI cancel recovery
[].message (string) – detailed status message
[].percent_complete (integer) – 0-100
[].stage (string) – e.g., “Building ISO”, “Mounting ISO”, “Installing OS”
[].status (string) – running, completed, failed, cancelled
[].updated_at (string)
- GET /controlnode/provision/queue
Get provision queue status
Returns all pending and active ISO-build queue entries
- Status Codes:
200 OK – OK
- POST /controlnode/provision/supermicro
Provision a Supermicro node with Debian OS
Build custom Debian ISO with preseed and provision via Supermicro BMC Redfish
- Request JSON Object:
arch (string)
bmc_IP (string) – (required)
branch (string)
cache_dir (string)
controlnode_host (string)
controlnode_port (string)
debian_version (string)
device_id (integer) – NetBox Device ID for tracking
gpu_passthrough (any) – GPU passthrough config for IOMMU/vfio-pci
hostname (string)
kubernetes_cluster_name (string)
kubernetes_cluster_type (string)
location (string)
mac_address (string)
network_role (string) – IPAM fields for static IP allocation
os_password (string) – OS password (default: adminadmin)
os_username (string) – OS credentials for provisioned system
output_iso (string)
pool_type (string) – “mirror”, “raidz1”, “raidz2”, “stripe”, “single”
prefix_id (integer) – Prefix ID from VLAN query response
pxe_path (string)
pxe_server (string)
rack_number (string)
root_pass (string)
selected_disks[] (string)
selected_nic (string) – e.g., “enp0s3” - DHCP enabled on this interface
selected_nic_legacy (string) – Legacy kernel name for the NIC (e.g., “eth0”)
selected_nic_mac (string) – MAC address of the selected NIC
sys_iuri (string)
vendor (string) – (required)
vm_slot (string)
zone (string)
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
404 Not Found – Not Found
500 Internal Server Error – Internal Server Error
- POST /controlnode/register
Register the control node (1st node) in bmc_infos
Registers the management/control node in the bmc_infos table with is_control_node=true
- Request JSON Object:
atlas_device_id (integer) – NetBox Device ID
atlas_location_id (integer) – NetBox Location ID
atlas_rack_id (integer) – NetBox Rack ID
atlas_site_id (integer) – Optional Atlas/NetBox IDs (populated from NetBox sync result during bootstrap)
bmc_ip (string) – Required field - BMC IP is the primary key (required)
bmc_password (string) – BMC password
bmc_username (string) – Optional BMC credentials
fqdn (string) – Fully qualified domain name
os_hostname (string) – Hostname (e.g., mgmt-01)
os_ip (string) – Optional OS info
os_password (string) – SSH password (will be hex encoded)
os_username (string) – SSH username (default: root)
primary_mac (string) – Primary NIC MAC address
serial_number (string) – Used as UUID
vendor (string) – Optional hardware info
- Status Codes:
200 OK – Control node updated successfully
201 Created – Control node registered successfully
400 Bad Request – Bad Request
500 Internal Server Error – Internal Server Error
- Response JSON Object:
created (boolean) – true if new record, false if updated existing
hostname (string)
message (string)
node_ip (string)
success (boolean)
created – true if new record, false if updated existing
hostname
message
node_ip
success
- POST /controlnode/unprovision
Unprovision a node
Unprovision a node by wiping storage using Debian live-build wipe ISO
- Request JSON Object:
bmc_ip (string) – (required)
bmc_pass (string)
bmc_user (string)
vendor (string)
- Status Codes:
200 OK – OK
400 Bad Request – Bad Request
404 Not Found – Not Found
500 Internal Server Error – Internal Server Error