Skip to content

API Reference

Every banlieue Custom Resource Definition, generated from the Rust types that are the schema's source of truth. Field descriptions are the rustdoc comments on those types.

banlieue.io

infrastructure.banlieue.io


Provider

API: banlieue.io/v1alpha1 · Kind: Provider · Scope: Namespaced · Short names: prov

Provider — one backend instance registered with banlieue.

A Provider represents a single place VMs can run: one vCenter, one Proxmox cluster, or one libvirt host. It carries the connection details and an admin-curated declaration of the storage classes, network classes, and features that backend exposes. Its controller logs in, verifies those capabilities, and publishes the reachable status.failureDomains[].

Why create one

  • Make a backend schedulable. A VirtualMachine can only be placed on a Provider — no Provider, nowhere to run.
  • Declare capabilities explicitly. spec.capabilities maps abstract class names (the ones VMClass / VMImage request) to concrete backend targets (a datastore, a port group). That mapping is the contract the scheduler matches against — capabilities are declared, not guessed.
  • Model many backends, including duplicates. A cluster can hold many Providers of the same class (prod-vsphere, dr-vsphere) and mix classes freely.

The provider's controller talks to the backend; banlieue's main controller never does. Communication between them is CRD-only.

Printer columns (kubectl get):

Name Type JSON path Priority
Class string .spec.providerClassRef.name 0
Endpoint string .spec.connection.endpoint 1
Ready string .status.conditions[?(@.type=='Ready')].status 0
Heartbeat string .status.workload.heartbeat 0
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
attestation object Attestation trust anchors for this backend's vTPMs (ADR-0049 Decision 10). Admin-supplied, never discovered: an anchor read off the hypervisor would let whoever controls the hypervisor choose the anchor that vouches for its own guests. Optional — a Provider that runs no tpmEnabled classes has no reason to set it.
capabilities object Admin-defined capability mappings. Every storage / network class that VMClass and VMImage may request MUST be listed here for this provider to be considered by the scheduler.
connection object Yes Connection details for the backend.
failureDomainNameOverrides object[] Explicit overrides for individual discovered failure domains' generated name. The auto-computed, collision-safe name (<provider>-<datacenter>-<cluster>, hashed when too long) is always the fallback for any (datacenter, cluster) pair with no matching entry here — this is opt-in, never required. See ADR-0023.
paused boolean Suspend reconciliation. Equivalent to setting the cluster.x-k8s.io/paused annotation but in-band.
providerClassRef object Yes Reference to a ProviderClass that identifies the backend type.
scheduling object How the scheduler places VMs on this backend (ADR-0107). Optional: without it the defaults apply.
useContentLibrary boolean vSphere only: import Url-kind VMImages through a vCenter Content Library rather than the default datastore-upload + MarkAsTemplate path. Defaults to false (no Content Library required), matching environments where CL is not enabled. Ignored by non-vSphere classes. See ADR-0020.

.spec.attestation

Attestation trust anchors for this backend's vTPMs (ADR-0049 Decision 10). Admin-supplied, never discovered: an anchor read off the hypervisor would let whoever controls the hypervisor choose the anchor that vouches for its own guests. Optional — a Provider that runs no tpmEnabled classes has no reason to set it.

Field Type Required Description
ekTrustBundle object Yes PEM bundle of CA certificates trusted to issue this backend's vTPM endorsement-key certificates. Provenance differs per backend (ADR-0045): on vSphere the issuing CA is vCenter's; on libvirt it is each host's swtpm_localca issuer certificate, one entry per host.
.spec.attestation.ekTrustBundle

PEM bundle of CA certificates trusted to issue this backend's vTPM endorsement-key certificates. Provenance differs per backend (ADR-0045): on vSphere the issuing CA is vCenter's; on libvirt it is each host's swtpm_localca issuer certificate, one entry per host.

Same value-or-source shape as connection.caBundle: exactly one of inline, configMapRef, secretRef must be set (see [CABundleSource]); references resolve in the Provider's namespace. Removal of an issuer from this bundle is the revocation mechanism on libvirt — swtpm EK certificates never expire.

Field Type Required Description
configMapRef object Key in a ConfigMap in the referrer's namespace (key defaults to ca.crt).
inline string Inline PEM (one or more concatenated certificates).
secretRef object Key in a Secret in the referrer's namespace (key defaults to ca.crt).
.spec.attestation.ekTrustBundle.configMapRef

Key in a ConfigMap in the referrer's namespace (key defaults to ca.crt).

Field Type Required Description
key string Key within the object's data. Defaults are caller-defined.
name string Yes Name of the ConfigMap / Secret in the referrer's namespace.
.spec.attestation.ekTrustBundle.secretRef

Key in a Secret in the referrer's namespace (key defaults to ca.crt).

Field Type Required Description
key string Key within the object's data. Defaults are caller-defined.
name string Yes Name of the ConfigMap / Secret in the referrer's namespace.

.spec.capabilities

Admin-defined capability mappings. Every storage / network class that VMClass and VMImage may request MUST be listed here for this provider to be considered by the scheduler.

Field Type Required Description
features string[] Feature flags admin asserts are available. Provider's controller may downgrade these in status if introspection finds otherwise. Well-known values: hotAddCPU, hotAddMemory, efiSecureBoot, nestedVirtualization, gpuPassthrough.
networkClasses object[] Network classes the admin asserts are available on this backend.
storageClasses object[] Storage classes the admin asserts are available on this backend. Each entry maps an abstract class name to a provider-interpreted concrete target.
.spec.capabilities.networkClasses[]

Network classes the admin asserts are available on this backend.

Field Type Required Description
name string Yes Abstract name referenced by VMClass.network.interfaces[].networkClass.
perZone object[] Per-(datacenter, cluster) overrides of target (ADR-0030).
perZoneSubnet object[] Per-(datacenter, cluster) overrides of subnet (ADR-0032).
subnet object Default subnet shape (gateway/nameservers/domain) for this network class, used in any zone per_zone_subnet does not cover. A port group implies a subnet, so this lives alongside target/per_zone rather than on VMClass — it lets a static-addressing VirtualMachine omit gateway/nameservers/domain entirely and have them resolved from whichever zone the scheduler picked (ADR-0032).
target map[string]string Default concrete target, used in any zone per_zone does not cover. None means this class resolves ONLY in the zones per_zone lists. Free-form per provider class. Examples: vsphere: { portGroup: "vmnet-prod" } { distributedPortGroup: "dvs-prod-vlan100" } proxmox: { bridge: "vmbr0", vlan: "100" } libvirt: { network: "br-prod" }
.spec.capabilities.networkClasses[].perZone[]

Per-(datacenter, cluster) overrides of target (ADR-0030).

Field Type Required Description
cluster string Yes Cluster name as vCenter reports it.
datacenter string Yes Datacenter name as vCenter reports it.
target map[string]string Yes Concrete backend target for this zone, same shape as [StorageClassMapping::target] / [NetworkClassMapping::target].
.spec.capabilities.networkClasses[].perZoneSubnet[]

Per-(datacenter, cluster) overrides of subnet (ADR-0032).

Field Type Required Description
cluster string Yes Cluster name as vCenter reports it.
datacenter string Yes Datacenter name as vCenter reports it.
subnet object Yes Subnet shape for this zone.
# .spec.capabilities.networkClasses[].perZoneSubnet[].subnet

Subnet shape for this zone.

Field Type Required Description
domain string
gateway string
nameservers string[]
.spec.capabilities.networkClasses[].subnet

Default subnet shape (gateway/nameservers/domain) for this network class, used in any zone per_zone_subnet does not cover. A port group implies a subnet, so this lives alongside target/per_zone rather than on VMClass — it lets a static-addressing VirtualMachine omit gateway/nameservers/domain entirely and have them resolved from whichever zone the scheduler picked (ADR-0032).

Field Type Required Description
domain string
gateway string
nameservers string[]
.spec.capabilities.storageClasses[]

Storage classes the admin asserts are available on this backend. Each entry maps an abstract class name to a provider-interpreted concrete target.

Field Type Required Description
name string Yes Abstract name referenced by VMClass.hardware.disks[].storageClass.
perZone object[] Per-(datacenter, cluster) overrides of target (ADR-0030).
target map[string]string Default concrete target, used in any zone per_zone does not cover. None means this class resolves ONLY in the zones per_zone lists. Free-form per provider class; the provider's controller interprets it. Examples by provider class: vsphere: { datastore: "ds-fast-01" } { datastoreCluster: "dsc-gold" } { tagCategory: "tier", tag: "gold" } proxmox: { storage: "ceph-pool-1" } libvirt: { pool: "nvme-pool" }
.spec.capabilities.storageClasses[].perZone[]

Per-(datacenter, cluster) overrides of target (ADR-0030).

Field Type Required Description
cluster string Yes Cluster name as vCenter reports it.
datacenter string Yes Datacenter name as vCenter reports it.
target map[string]string Yes Concrete backend target for this zone, same shape as [StorageClassMapping::target] / [NetworkClassMapping::target].

.spec.connection

Connection details for the backend.

Field Type Required Description
caBundle object Optional CA bundle to validate the endpoint's TLS certificate.
credentialsRef object Reference to a Secret in the Provider's namespace containing the credentials. Required keys depend on provider class: vsphere: username, password proxmox: username (the full API token id, user@realm!tokenid), tokenValue (API tokens only; password/ticket auth is not supported, ADR-0074) libvirt: tls.crt, tls.key (mutual TLS, ADR-0011)
endpoint string Yes Endpoint URL or URI. Format depends on provider class: vsphere: https://vcenter.example.com/sdk proxmox: https://pve.example.com:8006 libvirt: qemu+ssh://kvm-host.example.com/system
insecureSkipTLSVerify boolean Skip TLS verification. Applies to vsphere and proxmox.
.spec.connection.caBundle

Optional CA bundle to validate the endpoint's TLS certificate.

A value-or-source: inline PEM, or a configMapRef / secretRef naming a key (default ca.crt) in the Provider's namespace. Exactly one source must be set; see [CABundleSource]. Resolved by the provider controller and injected into the HTTP client (ADR-0008, BYOC). When unset, the system trust roots are used.

Field Type Required Description
configMapRef object Key in a ConfigMap in the referrer's namespace (key defaults to ca.crt).
inline string Inline PEM (one or more concatenated certificates).
secretRef object Key in a Secret in the referrer's namespace (key defaults to ca.crt).
.spec.connection.caBundle.configMapRef

Key in a ConfigMap in the referrer's namespace (key defaults to ca.crt).

Field Type Required Description
key string Key within the object's data. Defaults are caller-defined.
name string Yes Name of the ConfigMap / Secret in the referrer's namespace.
.spec.connection.caBundle.secretRef

Key in a Secret in the referrer's namespace (key defaults to ca.crt).

Field Type Required Description
key string Key within the object's data. Defaults are caller-defined.
name string Yes Name of the ConfigMap / Secret in the referrer's namespace.
.spec.connection.credentialsRef

Reference to a Secret in the Provider's namespace containing the credentials. Required keys depend on provider class: vsphere: username, password proxmox: username (the full API token id, user@realm!tokenid), tokenValue (API tokens only; password/ticket auth is not supported, ADR-0074) libvirt: tls.crt, tls.key (mutual TLS, ADR-0011)

Required by every backend that authenticates to a remote endpoint, and refused by cloud-hypervisor, whose provider runs on the hypervisor host and must read no Secret at all (ADR-0060 Decision 4). When unset the operator grants no Secret access whatsoever.

Field Type Required Description
name string Yes

.spec.failureDomainNameOverrides[]

Explicit overrides for individual discovered failure domains' generated name. The auto-computed, collision-safe name (<provider>-<datacenter>-<cluster>, hashed when too long) is always the fallback for any (datacenter, cluster) pair with no matching entry here — this is opt-in, never required. See ADR-0023.

Field Type Required Description
cluster string Yes Cluster name as vCenter reports it.
datacenter string Yes Datacenter name as vCenter reports it (matches discover_inventory's walk, not an operator-chosen alias).
name string Yes The name to use instead of the auto-computed one, e.g. cluster-01. Slugified the same way auto-computed names are, so Cluster 01 still produces a valid Kubernetes name.

.spec.providerClassRef

Reference to a ProviderClass that identifies the backend type.

For v1alpha1 the ProviderClass CRD is deferred; treat this as a name drawn from a well-known set: vsphere, proxmox, libvirt. A future ProviderClass CRD will provide install metadata (image, RBAC) without changing this reference.

Field Type Required Description
name string Yes

.spec.scheduling

How the scheduler places VMs on this backend (ADR-0107). Optional: without it the defaults apply.

Field Type Required Description
cpuOvercommitRatio integer vCPUs the scheduler may place per CPU a failure domain publishes in attributes.capacity.cpus. 1 means no overcommit. CPU contention only slows guests, so the default allows 4; memory is never overcommitted. Unset: 4.

.status

Observed state of a Provider: the failure domains its controller discovered and the health / reachability conditions.

Field Type Required Description
conditions object[] Standard Kubernetes conditions. The Ready condition reflects overall provider health. The ProviderReachable condition reflects connection state to the backend.
ekCaCertificates string[] PEM certificates of the CAs that issue this backend's vTPM endorsement key certificates: on a Cloud Hypervisor host, the host's own swtpm_localca (ADR-0065 Decision 6). A verifier trusts a guest's EK only through the host that created it; this is the input ekTrustBundle needs (ADR-0049). Empty when the backend offers no vTPM or publishes no anchor.
failureDomains object[] Failure domains ("availability zones" — the terms are synonyms; failureDomain was kept to align with CAPI v1beta2's own vocabulary) discovered by the provider's controller within this backend. The scheduler matches against labels and filters by attributes.availableStorageClasses / availableNetworkClasses.
observedGeneration integer The generation of the spec that the controller has reconciled.
workload object The provider workload banlieue-operator created for this Provider.

.status.conditions[]

Standard Kubernetes conditions. The Ready condition reflects overall provider health. The ProviderReachable condition reflects connection state to the backend.

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

.status.failureDomains[]

Failure domains ("availability zones" — the terms are synonyms; failureDomain was kept to align with CAPI v1beta2's own vocabulary) discovered by the provider's controller within this backend. The scheduler matches against labels and filters by attributes.availableStorageClasses / availableNetworkClasses.

Field Type Required Description
attributes object Attributes the provider's controller resolved for this domain, including the subset of admin-listed classes that are actually reachable from here.
labels map[string]string Labels used by the scheduler's failureDomainSelector and by VirtualMachine anti-affinity topologyKey matching. Recommended keys: datacenter, cluster, rack, env. Every provider also sets name to this failure domain's own resolved name above (auto-computed, or an ADR-0023 override) — name above is a top-level field a LabelSelector cannot match directly, so without this mirror, targeting a specific zone by its friendly override name (rather than a raw backend-reported label like cluster) would be impossible.
name string Yes Stable name. Conventionally <provider>-<cluster-or-zone>.
.status.failureDomains[].attributes

Attributes the provider's controller resolved for this domain, including the subset of admin-listed classes that are actually reachable from here.

Field Type Required Description
availableNetworkClasses string[] Subset of spec.capabilities.networkClasses[].name reachable here.
availableStorageClasses string[] Subset of spec.capabilities.storageClasses[].name reachable here.
capacity object What guests may use in this failure domain, as the provider measured it (ADR-0107). The scheduler fits each VM against it; a domain that publishes none is not filtered on capacity.
features string[] Feature flags actually present here. Always a subset of spec.capabilities.features.
raw map[string]string Provider-specific resolved attributes; for vSphere this typically includes datacenter, cluster, resourcePool. Used by the provider's controller when filling in the infrastructure CR.
.status.failureDomains[].attributes.capacity

What guests may use in this failure domain, as the provider measured it (ADR-0107). The scheduler fits each VM against it; a domain that publishes none is not filtered on capacity.

Field Type Required Description
cpus integer Logical CPUs guests may use. vCPUs are placed up to this times the Provider's scheduling.cpuOvercommitRatio.
memoryMiB integer Memory guests may use, MiB: the host's, or a smaller budget the host declares for guests (a Cloud Hypervisor host's guests' slice, ADR-0105). Never overcommitted.
memoryOverheadMiBPerVM integer Memory each VM costs beyond its class's memoryMiB (its VMM), MiB.

.status.workload

The provider workload banlieue-operator created for this Provider.

Written only by the operator's field manager (banlieue.io/operator); the provider's own controller never touches it. This split is deliberate: conditions is a plain list with no x-kubernetes-list-type: map marker, so two field managers writing into it would contend over the whole array rather than merging per entry. Giving the operator a disjoint field keeps server-side apply conflict-free (ADR-0012).

Field Type Required Description
deploymentName string Name of the Deployment running this Provider's controller. Conventionally banlieue-provider-<class>-<provider-name>. Unset for External: there is no Deployment.
heartbeat string A provider's liveness, from its leader-election Lease (ADR-0102). Allowed: Alive, Stale, Absent.
lastHeartbeatTime string The Lease's last renewTime, when there is a Lease.
mode string Whether the operator runs this provider (Managed) or only gave it an identity (External, ADR-0060 Decision 3). Absent on objects written before the field existed, which were all Managed. Allowed: Managed, External.
namespace string Yes Namespace the Deployment was created in — the ProviderClass's workloadNamespace, or the operator's own namespace when unset.
observedGeneration integer The Provider generation the operator had observed when it last applied this workload.
readyReplicas integer Ready replicas reported by that Deployment. Zero means the backend's controller is not currently running, whatever the Provider's other conditions say. Unset for External: there is no Deployment, and whether the provider is running is heartbeat (ADR-0102).

ProviderClass

API: banlieue.io/v1alpha1 · Kind: ProviderClass · Scope: Cluster · Short names: pc

ProviderClass — what banlieue runs for a class of backends.

A ProviderClass carries the install metadata for one backend type: which banlieue provider <backend> role to run, from which image, with what pod shape and extra permissions. It names no endpoint and holds no credentials — that is a Provider's job.

Why create one

  • Make backends self-provisioning. With a ProviderClass in place, registering a backend is kubectl apply of a Provider CR: banlieue-operator creates that Provider's Deployment, ServiceAccount, Role and RoleBinding for you. No manifest editing, no helm values.
  • Decide the image once. Every Provider of this class runs the image pinned here, so upgrading a fleet of backends is a one-object edit instead of one edit per backend.
  • Separate the two jobs. Deciding what banlieue runs (a platform owner, cluster-scoped) is not the same as registering a vCenter (a backend admin, namespaced) — different people, different privileges.

How it is used

Provider.spec.providerClassRef.name points at a ProviderClass by name. The operator resolves it, then applies one workload set per Provider, each owned by its Provider CR so deleting the Provider garbage-collects the workload. Each spawned pod runs a server-side filtered watch scoped to its own Provider, so one hung backend cannot stall another (ADR-0003).

Cluster-scoped: one ProviderClass serves Providers in any namespace.

Printer columns (kubectl get):

Name Type JSON path Priority
Backend string .spec.backend 0
Image string .spec.image.tag 0
Deployment string .spec.deployment 0
Providers integer .status.providers 0
Ready string .status.conditions[?(@.type=='Ready')].status 0
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
additionalRules object[] Extra RBAC rules appended to the per-instance Role the operator generates for each Provider of this class.
backend string Yes Which provider backend this class instantiates — the banlieue provider <backend> subcommand spawned Deployments run.
deployment string How a class's providers run (ADR-0060 Decision 3). Allowed: Managed, External.
image object Container image every provider workload of this class runs.
logging object Log level and format passed to spawned workloads.
nodeSelector map[string]string Node selector applied to provider pods. Useful when backend access is only routable from particular nodes.
paused boolean Suspend lifecycle reconciliation for every Provider of this class. Existing workloads are left running untouched.
replicas integer Replicas for each provider Deployment. Defaults to [DEFAULT_PROVIDER_REPLICAS]. Provider controllers are leader-elected, so values above one provide failover, not parallelism.
resources object Resource requests and limits for the provider container. When unset the operator applies its own conservative defaults.
tolerations object[] Tolerations applied to provider pods.
workloadNamespace string Namespace to create provider workloads in.

.spec.additionalRules[]

Extra RBAC rules appended to the per-instance Role the operator generates for each Provider of this class.

Note that Kubernetes forbids granting permissions the grantor does not itself hold: a rule listed here also has to be present in the operator's own ClusterRole, or the RoleBinding is rejected (ADR-0012).

Field Type Required Description
apiGroups string[] apiGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
nonResourceURLs string[] nonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
resourceNames string[] resourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.
resources string[] resources is a list of resources this rule applies to. '*' represents all resources.
verbs string[] Yes verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs.

.spec.image

Container image every provider workload of this class runs.

Required when deployment is Managed (the default), and must be unset when it is External: nothing is deployed, so there is no image to run. The operator and the admission policy both enforce this (ADR-0060 Decision 3).

Field Type Required Description
digest string Image digest, e.g. sha256:0f756fa0…. When set it is what actually gets pulled, and any tag becomes documentation of intent.
pullPolicy string Image pull policy, spelled exactly as Kubernetes spells it. Allowed: Always, IfNotPresent, Never.
pullSecrets object[] Secrets used to pull the image, for private or mirrored registries.
repository string Yes Image repository without a tag, e.g. ghcr.io/firestoned/banlieue.
tag string Yes Image tag, e.g. v0.1.0. Never use latest in production — a mutable tag makes the running version unknowable and defeats rollback.
.spec.image.pullSecrets[]

Secrets used to pull the image, for private or mirrored registries.

Field Type Required Description
name string Yes

.spec.logging

Log level and format passed to spawned workloads.

Field Type Required Description
format string Log format: json for SIEM-friendly structured output, anything else for the human-readable text formatter.
level string Log level, e.g. info or debug,kube=warn. Passed through as the workload's log-level flag.

.spec.resources

Resource requests and limits for the provider container. When unset the operator applies its own conservative defaults.

Field Type Required Description
claims object[] Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.
limits map[string]object Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
requests map[string]object Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
.spec.resources.claims[]

Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.

This field depends on the DynamicResourceAllocation feature gate.

This field is immutable. It can only be set for containers.

Field Type Required Description
name string Yes Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container.
request string Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request.

.spec.tolerations[]

Tolerations applied to provider pods.

Field Type Required Description
effect string Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
key string Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys.
operator string Operator represents a key's relationship to the value. Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
tolerationSeconds integer TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.
value string Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string.

.status

Observed state of a ProviderClass.

Field Type Required Description
conditions object[] Standard Kubernetes conditions. Ready reflects whether the class is usable: its backend is compiled into the running operator and its image reference is well-formed.
observedGeneration integer The generation of the spec the operator has reconciled.
providers integer Number of Provider CRs currently referencing this class.

.status.conditions[]

Standard Kubernetes conditions. Ready reflects whether the class is usable: its backend is compiled into the running operator and its image reference is well-formed.

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

VirtualMachine

API: banlieue.io/v1alpha1 · Kind: VirtualMachine · Scope: Namespaced · Short names: vm

VirtualMachine — the user-facing request for a running VM.

This is the one resource end users create. It expresses intent: which VMClass (shape) and VMImage (OS) to use, optional placement constraints, the desired power state, and optional guest user-data. banlieue's controller schedules it onto a Provider + failure domain, creates the matching provider infrastructure CR (e.g. VSphereMachine), and mirrors that CR's status back here.

Why create one

  • Declare a VM the Kubernetes way. Describe the VM you want; the controller reconciles reality toward it, including power state.
  • Stay backend-agnostic. You reference a class and an image by name, not a datastore or a port group. Where it lands is the scheduler's job.
  • Compose with policy. Label / anti-affinity selectors and a migration policy steer placement and drift handling without coupling to a specific Provider.

Independent of Cluster API: a VirtualMachine is not a clusterv1. Machine. It can coexist with CAPI but does not depend on it.

Namespaced: candidate Providers are drawn from the VM's own namespace.

Printer columns (kubectl get):

Name Type JSON path Priority
Class string .spec.classRef.name 0
Image string .spec.imageRef.name 0
Provider string .status.scheduled.providerName 0
FailureDomain string .status.scheduled.failureDomain 1
Power string .status.observedPowerState 0
Ready string .status.conditions[?(@.type=='Ready')].status 0
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
classRef object Yes Reference to a (cluster-scoped) VMClass.
desiredPowerState string Desired power state. Defaults to PoweredOn. Allowed: PoweredOn, PoweredOff, Suspended.
folder string Destination folder for the provisioned VM (e.g. apps/prod on vSphere). When unset, the provider defaults to organizing the VM the same way it organizes its source template — on vSphere, the same per-zone folder the template lives in (ADR-0020 Decision #5).
hardwareOverride object Per-VM override for the VMClass's hardware shape — CPUs, memory, and disk sizes.
imageRef object Yes Reference to a (cluster-scoped) VMImage.
migrationPolicy string What to do when current placement no longer satisfies the spec. Allowed: automatic, manual, never.
networkOverrides object[] Per-VM overrides for specific VMClass-declared network interfaces (ADR-0024). Keyed by NetworkInterfaceSpec.name; an interface with no entry here uses its VMClass's own ipam verbatim (commonly dhcp). Lets many VMs share one VMClass while each still gets its own static address — a VMClass-level ipam.static cannot express that, since a class is shared by design.
paused boolean Suspend reconciliation in-band.
placement object Placement intent. If unset, the scheduler considers every Provider in the VM's namespace and every failure domain.
userData object Optional user-data delivered to the guest via the image's guestAgent (cloud-init / ignition / sysprep).

.spec.classRef

Reference to a (cluster-scoped) VMClass.

Field Type Required Description
name string Yes

.spec.hardwareOverride

Per-VM override for the VMClass's hardware shape — CPUs, memory, and disk sizes.

This is a delta, not the primary definition. The VMClass is the authoritative source for a VM's hardware shape: its spec.hardware is fixed and shared by every VM that references the class. This field applies on top of the class — only the fields you set here replace the class value; everything else is inherited verbatim.

Use this sparingly. Its primary purpose is to accommodate the rare VM that genuinely needs a different CPU, memory, or disk budget than its class defines — for example, a database primary bumped to 16 CPUs while all other replicas use the 4-CPU class shape, or one VM that needs a larger data disk. If you find yourself setting the same override on every VM of a given class, create a new VMClass instead.

Field Type Required Description
cpus integer Override the VMClass's spec.hardware.cpus. If absent, the class value is used unchanged.
diskOverrides object[] Per-disk size overrides, keyed by DiskSpec.name. Only sizeGiB can be overridden per VM; the disk's storageClass and provisioning are class-level concerns.
memoryMiB integer Override the VMClass's spec.hardware.memoryMiB. If absent, the class value is used unchanged.
.spec.hardwareOverride.diskOverrides[]

Per-disk size overrides, keyed by DiskSpec.name. Only sizeGiB can be overridden per VM; the disk's storageClass and provisioning are class-level concerns.

This is a delta, not the primary definition. A disk with no entry here inherits the VMClass's size verbatim.

Field Type Required Description
name string Yes Matches a VMClass.spec.hardware.disks[].name.
sizeGiB integer Yes Override the disk's sizeGiB. Must be ≥ the class value (the provider will reject a shrink). If absent, the class size is used.

.spec.imageRef

Reference to a (cluster-scoped) VMImage.

Field Type Required Description
name string Yes

.spec.networkOverrides[]

Per-VM overrides for specific VMClass-declared network interfaces (ADR-0024). Keyed by NetworkInterfaceSpec.name; an interface with no entry here uses its VMClass's own ipam verbatim (commonly dhcp). Lets many VMs share one VMClass while each still gets its own static address — a VMClass-level ipam.static cannot express that, since a class is shared by design.

This is a delta, not the primary definition. The VMClass is the authoritative source for the VM's network shape. Entries here are layered on top: only the named interface's ipam is replaced; every other interface is inherited from the class unchanged.

Field Type Required Description
name string Yes Matches a VMClass.spec.network.interfaces[].name.
static object Yes The static address to use for this interface, overriding whatever the VMClass's own ipam declares.
.spec.networkOverrides[].static

The static address to use for this interface, overriding whatever the VMClass's own ipam declares.

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes

.spec.placement

Placement intent. If unset, the scheduler considers every Provider in the VM's namespace and every failure domain.

Field Type Required Description
antiAffinity object[] Anti-affinity rules against other VirtualMachines in the same namespace. Evaluated at scheduling time.
failureDomainSelector object Match failure domains by their status.failureDomains[].labels. Across all candidate Providers, only failure domains whose labels match are considered.
providerSelector object Match Providers by their metadata.labels. A Provider is a candidate only if its labels match this selector.
.spec.placement.antiAffinity[]

Anti-affinity rules against other VirtualMachines in the same namespace. Evaluated at scheduling time.

Field Type Required Description
labelSelector object Yes Other VMs (by their own metadata.labels) to spread away from.
mode string Strictness. required filters candidates; preferred is best-effort. Allowed: required, preferred.
topologyKey string Yes A label key from the failure domain's labels. Spreading is required across distinct values of this key. Common keys: cluster, rack, host, dc.
.spec.placement.antiAffinity[].labelSelector

Other VMs (by their own metadata.labels) to spread away from.

Field Type Required Description
matchExpressions object[]
matchLabels map[string]string
# .spec.placement.antiAffinity[].labelSelector.matchExpressions[]
Field Type Required Description
key string Yes
operator string Yes Allowed: In, NotIn, Exists, DoesNotExist.
values string[]
.spec.placement.failureDomainSelector

Match failure domains by their status.failureDomains[].labels. Across all candidate Providers, only failure domains whose labels match are considered.

Field Type Required Description
matchExpressions object[]
matchLabels map[string]string
.spec.placement.failureDomainSelector.matchExpressions[]
Field Type Required Description
key string Yes
operator string Yes Allowed: In, NotIn, Exists, DoesNotExist.
values string[]
.spec.placement.providerSelector

Match Providers by their metadata.labels. A Provider is a candidate only if its labels match this selector.

Field Type Required Description
matchExpressions object[]
matchLabels map[string]string
.spec.placement.providerSelector.matchExpressions[]
Field Type Required Description
key string Yes
operator string Yes Allowed: In, NotIn, Exists, DoesNotExist.
values string[]

.spec.userData

Optional user-data delivered to the guest via the image's guestAgent (cloud-init / ignition / sysprep).

Field Type Required Description
configMapRef object Key in a ConfigMap in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]).
secretRef object Key in a Secret in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]).
.spec.userData.configMapRef

Key in a ConfigMap in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]).

Field Type Required Description
key string Key within the object's data. Defaults are caller-defined.
name string Yes Name of the ConfigMap / Secret in the referrer's namespace.
.spec.userData.secretRef

Key in a Secret in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]).

Field Type Required Description
key string Key within the object's data. Defaults are caller-defined.
name string Yes Name of the ConfigMap / Secret in the referrer's namespace.

.status

Observed state of a VirtualMachine: the scheduling decision, the infra CR it owns, mirrored provisioning / address / power state, and conditions.

Field Type Required Description
addresses object[] Mirrored from the infra CR's status.addresses.
conditions object[] Standard Kubernetes conditions. Required types: Ready — overall readiness Scheduled — placement decision exists and is current PlacementValid — current placement satisfies the spec InfrastructureReady — mirrors the infra CR's Ready condition Optional: Migrating — true while a migration is in progress Paused — present (True) only while spec.paused suspends reconciliation
heldAddresses object[] Static addresses this VM's infrastructure CR was last applied with (ADR-0083). Written by the controller only when it applies the infra CR, and carried forward unchanged otherwise, so it records what the guest is configured with: it survives guest reboots and is the same on every backend. A held address is never given to another VM.
infrastructureRef object Reference to the provider-specific infrastructure CR (e.g. infrastructure.banlieue.io/v1alpha1/VSphereMachine). Set after scheduling, owned by this VirtualMachine.
initialization object Mirrored from the infra CR's status.initialization.
observedGeneration integer
observedPowerState string Observed power state from the provider. Allowed: PoweredOn, PoweredOff, Suspended, null.
scheduled object Current scheduling decision. Absent until first successful schedule.
tpmEndorsementCertificates string[] Mirrored from the infra CR's status.tpmEndorsementCertificates (ADR-0045). The anchor a verifier checks an attestation quote against; mirrored onward onto a bound VirtualMachineClaim so a consumer needs one GET.

.status.addresses[]

Mirrored from the infra CR's status.addresses.

Field Type Required Description
address string Yes The address itself.
type string Yes Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS.

.status.conditions[]

Standard Kubernetes conditions. Required types: Ready — overall readiness Scheduled — placement decision exists and is current PlacementValid — current placement satisfies the spec InfrastructureReady — mirrors the infra CR's Ready condition Optional: Migrating — true while a migration is in progress Paused — present (True) only while spec.paused suspends reconciliation

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

.status.heldAddresses[]

Static addresses this VM's infrastructure CR was last applied with (ADR-0083). Written by the controller only when it applies the infra CR, and carried forward unchanged otherwise, so it records what the guest is configured with: it survives guest reboots and is the same on every backend. A held address is never given to another VM.

Field Type Required Description
address string Yes The address, normalised (an IP is re-printed in canonical form).
interface string Yes The VMClass interface the address is on.
networkClass string Yes That interface's networkClass: the network the address is unique on.

.status.infrastructureRef

Reference to the provider-specific infrastructure CR (e.g. infrastructure.banlieue.io/v1alpha1/VSphereMachine). Set after scheduling, owned by this VirtualMachine.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string

.status.initialization

Mirrored from the infra CR's status.initialization.

Field Type Required Description
provisioned boolean True when the infrastructure provider reports that the resource's infrastructure is fully provisioned.

.status.scheduled

Current scheduling decision. Absent until first successful schedule.

Field Type Required Description
failureDomain string Yes Failure domain name (one of the Provider's status.failureDomains[].name).
providerClass string Yes Provider's ProviderClass (denormalized for convenience in printer columns).
providerName string Yes Provider name (in the VM's namespace).
resolvedNetworks object[] Resolved network class → concrete backend identifier mappings.
resolvedStorage object[] Resolved storage class → concrete backend identifier mappings.
scheduledAt string Time the placement decision was made.
.status.scheduled.resolvedNetworks[]

Resolved network class → concrete backend identifier mappings.

Field Type Required Description
backendId string Yes Backend identifier the provider resolved to (e.g. "ds-fast-01", "vmnet-prod").
className string Yes Class name as referenced in the VMClass (e.g. "gold", "prod").
.status.scheduled.resolvedStorage[]

Resolved storage class → concrete backend identifier mappings.

Field Type Required Description
backendId string Yes Backend identifier the provider resolved to (e.g. "ds-fast-01", "vmnet-prod").
className string Yes Class name as referenced in the VMClass (e.g. "gold", "prod").

VirtualMachinePool

API: banlieue.io/v1alpha1 · Kind: VirtualMachinePool · Scope: Namespaced · Short names: vmpool

VirtualMachinePool: a self-refilling set of warm, single-use VMs.

Why create one

  • Hide install latency. A tpmEnabled class must pair with an installMode: Deferred image, so every VM pays a full install on first boot. The pool pays that ahead of time.
  • Single use by construction. Members are handed out through VirtualMachineClaim and destroyed when the claim ends. There is no code path that returns a used member to the warm set.
  • Follow the image. When the referenced VMImage is rebuilt, warm members from the old build are replaced surge-style without dropping claimable capacity.

Namespaced: members are created in the pool's own namespace, which is also where the scheduler looks for candidate Providers.

Printer columns (kubectl get):

Name Type JSON path Priority
Warm integer .spec.warmReplicas 0
Available integer .status.available 0
Provisioning integer .status.provisioning 0
Claimed integer .status.claimed 0
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
addressing object Per-member static addressing. Omit for DHCP or class-level IPAM. Interim until the CAPI IPAM contract lands (ADR-0033); at that point this gains a poolRef alternative and the inline range stays as the zero-dependency option.
maxIdleSeconds integer Replace a Ready member that has sat unclaimed this long. Bounds how stale an unpatched warm VM can get between image rebuilds.
maxReplicas integer Yes Hard ceiling on members of any phase, claimed ones included. Leave headroom above warmReplicas plus expected concurrent claims, or image rollouts have to trade warm capacity for replacements.
maxSurge integer Most members allowed to be provisioning at once. Bounds the install load a refill puts on the hosts that claimed members are running on.
provisioningTimeoutSeconds integer A member still provisioning after this long is treated as poisoned and deleted, never repaired.
readiness string Yes Which member condition makes it claimable. See [PoolReadiness]. Allowed: GuestReady, InfrastructureReady.
recycleOnImageChange boolean Replace warm members when the referenced VMImage's build changes.
template object Yes Template for each member. spec.networkOverrides entries for the interface named in addressing are replaced per member; everything else is copied verbatim.
warmReplicas integer Yes How many Ready, unclaimed members to keep available.

.spec.addressing

Per-member static addressing. Omit for DHCP or class-level IPAM. Interim until the CAPI IPAM contract lands (ADR-0033); at that point this gains a poolRef alternative and the inline range stays as the zero-dependency option.

Field Type Required Description
domain string
gateway string
interface string Yes Name of the VMClass network interface to stamp, matching NetworkInterfaceOverride.name.
nameservers string[]
pool string[] Yes The addresses members are drawn from, in the order to draw them (ADR-0056). Each entry is one of:
prefix integer Yes

.spec.template

Template for each member. spec.networkOverrides entries for the interface named in addressing are replaced per member; everything else is copied verbatim.

Field Type Required Description
annotations map[string]string Extra annotations stamped on each member.
labels map[string]string Extra labels stamped on each member, in addition to the pool's own.
spec object Yes VirtualMachine — the user-facing request for a running VM.
.spec.template.spec

VirtualMachine — the user-facing request for a running VM.

This is the one resource end users create. It expresses intent: which VMClass (shape) and VMImage (OS) to use, optional placement constraints, the desired power state, and optional guest user-data. banlieue's controller schedules it onto a Provider + failure domain, creates the matching provider infrastructure CR (e.g. VSphereMachine), and mirrors that CR's status back here.

Why create one

  • Declare a VM the Kubernetes way. Describe the VM you want; the controller reconciles reality toward it, including power state.
  • Stay backend-agnostic. You reference a class and an image by name, not a datastore or a port group. Where it lands is the scheduler's job.
  • Compose with policy. Label / anti-affinity selectors and a migration policy steer placement and drift handling without coupling to a specific Provider.

Independent of Cluster API: a VirtualMachine is not a clusterv1. Machine. It can coexist with CAPI but does not depend on it.

Namespaced: candidate Providers are drawn from the VM's own namespace.

Field Type Required Description
classRef object Yes Reference to a (cluster-scoped) VMClass.
desiredPowerState string Desired power state. Defaults to PoweredOn. Allowed: PoweredOn, PoweredOff, Suspended.
folder string Destination folder for the provisioned VM (e.g. apps/prod on vSphere). When unset, the provider defaults to organizing the VM the same way it organizes its source template — on vSphere, the same per-zone folder the template lives in (ADR-0020 Decision #5).
hardwareOverride object Per-VM override for the VMClass's hardware shape — CPUs, memory, and disk sizes.
imageRef object Yes Reference to a (cluster-scoped) VMImage.
migrationPolicy string What to do when current placement no longer satisfies the spec. Allowed: automatic, manual, never.
networkOverrides object[] Per-VM overrides for specific VMClass-declared network interfaces (ADR-0024). Keyed by NetworkInterfaceSpec.name; an interface with no entry here uses its VMClass's own ipam verbatim (commonly dhcp). Lets many VMs share one VMClass while each still gets its own static address — a VMClass-level ipam.static cannot express that, since a class is shared by design.
paused boolean Suspend reconciliation in-band.
placement object Placement intent. If unset, the scheduler considers every Provider in the VM's namespace and every failure domain.
userData object Optional user-data delivered to the guest via the image's guestAgent (cloud-init / ignition / sysprep).
.spec.template.spec.classRef

Reference to a (cluster-scoped) VMClass.

Field Type Required Description
name string Yes
.spec.template.spec.hardwareOverride

Per-VM override for the VMClass's hardware shape — CPUs, memory, and disk sizes.

This is a delta, not the primary definition. The VMClass is the authoritative source for a VM's hardware shape: its spec.hardware is fixed and shared by every VM that references the class. This field applies on top of the class — only the fields you set here replace the class value; everything else is inherited verbatim.

Use this sparingly. Its primary purpose is to accommodate the rare VM that genuinely needs a different CPU, memory, or disk budget than its class defines — for example, a database primary bumped to 16 CPUs while all other replicas use the 4-CPU class shape, or one VM that needs a larger data disk. If you find yourself setting the same override on every VM of a given class, create a new VMClass instead.

Field Type Required Description
cpus integer Override the VMClass's spec.hardware.cpus. If absent, the class value is used unchanged.
diskOverrides object[] Per-disk size overrides, keyed by DiskSpec.name. Only sizeGiB can be overridden per VM; the disk's storageClass and provisioning are class-level concerns.
memoryMiB integer Override the VMClass's spec.hardware.memoryMiB. If absent, the class value is used unchanged.
# .spec.template.spec.hardwareOverride.diskOverrides[]

Per-disk size overrides, keyed by DiskSpec.name. Only sizeGiB can be overridden per VM; the disk's storageClass and provisioning are class-level concerns.

This is a delta, not the primary definition. A disk with no entry here inherits the VMClass's size verbatim.

Field Type Required Description
name string Yes Matches a VMClass.spec.hardware.disks[].name.
sizeGiB integer Yes Override the disk's sizeGiB. Must be ≥ the class value (the provider will reject a shrink). If absent, the class size is used.
.spec.template.spec.imageRef

Reference to a (cluster-scoped) VMImage.

Field Type Required Description
name string Yes
.spec.template.spec.networkOverrides[]

Per-VM overrides for specific VMClass-declared network interfaces (ADR-0024). Keyed by NetworkInterfaceSpec.name; an interface with no entry here uses its VMClass's own ipam verbatim (commonly dhcp). Lets many VMs share one VMClass while each still gets its own static address — a VMClass-level ipam.static cannot express that, since a class is shared by design.

This is a delta, not the primary definition. The VMClass is the authoritative source for the VM's network shape. Entries here are layered on top: only the named interface's ipam is replaced; every other interface is inherited from the class unchanged.

Field Type Required Description
name string Yes Matches a VMClass.spec.network.interfaces[].name.
static object Yes The static address to use for this interface, overriding whatever the VMClass's own ipam declares.
# .spec.template.spec.networkOverrides[].static

The static address to use for this interface, overriding whatever the VMClass's own ipam declares.

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes
.spec.template.spec.placement

Placement intent. If unset, the scheduler considers every Provider in the VM's namespace and every failure domain.

Field Type Required Description
antiAffinity object[] Anti-affinity rules against other VirtualMachines in the same namespace. Evaluated at scheduling time.
failureDomainSelector object Match failure domains by their status.failureDomains[].labels. Across all candidate Providers, only failure domains whose labels match are considered.
providerSelector object Match Providers by their metadata.labels. A Provider is a candidate only if its labels match this selector.
# .spec.template.spec.placement.antiAffinity[]

Anti-affinity rules against other VirtualMachines in the same namespace. Evaluated at scheduling time.

Field Type Required Description
labelSelector object Yes Other VMs (by their own metadata.labels) to spread away from.
mode string Strictness. required filters candidates; preferred is best-effort. Allowed: required, preferred.
topologyKey string Yes A label key from the failure domain's labels. Spreading is required across distinct values of this key. Common keys: cluster, rack, host, dc.
## .spec.template.spec.placement.antiAffinity[].labelSelector

Other VMs (by their own metadata.labels) to spread away from.

Field Type Required Description
matchExpressions object[]
matchLabels map[string]string
### .spec.template.spec.placement.antiAffinity[].labelSelector.matchExpressions[]
Field Type Required Description
key string Yes
operator string Yes Allowed: In, NotIn, Exists, DoesNotExist.
values string[]
# .spec.template.spec.placement.failureDomainSelector

Match failure domains by their status.failureDomains[].labels. Across all candidate Providers, only failure domains whose labels match are considered.

Field Type Required Description
matchExpressions object[]
matchLabels map[string]string
## .spec.template.spec.placement.failureDomainSelector.matchExpressions[]
Field Type Required Description
key string Yes
operator string Yes Allowed: In, NotIn, Exists, DoesNotExist.
values string[]
# .spec.template.spec.placement.providerSelector

Match Providers by their metadata.labels. A Provider is a candidate only if its labels match this selector.

Field Type Required Description
matchExpressions object[]
matchLabels map[string]string
## .spec.template.spec.placement.providerSelector.matchExpressions[]
Field Type Required Description
key string Yes
operator string Yes Allowed: In, NotIn, Exists, DoesNotExist.
values string[]
.spec.template.spec.userData

Optional user-data delivered to the guest via the image's guestAgent (cloud-init / ignition / sysprep).

Field Type Required Description
configMapRef object Key in a ConfigMap in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]).
secretRef object Key in a Secret in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]).
# .spec.template.spec.userData.configMapRef

Key in a ConfigMap in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]).

Field Type Required Description
key string Key within the object's data. Defaults are caller-defined.
name string Yes Name of the ConfigMap / Secret in the referrer's namespace.
# .spec.template.spec.userData.secretRef

Key in a Secret in the VirtualMachine's namespace (key defaults to [DEFAULT_USER_DATA_KEY]).

Field Type Required Description
key string Key within the object's data. Defaults are caller-defined.
name string Yes Name of the ConfigMap / Secret in the referrer's namespace.

.status

Field Type Required Description
available integer Ready and unclaimed: what a claim can bind right now.
claimed integer
conditions object[]
imageRevision string Image revision new members are currently being built from.
observedGeneration integer
provisioning integer
replicas integer Members of any phase, excluding ones already being deleted.

.status.conditions[]

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

VirtualMachineClaim

API: banlieue.io/v1alpha1 · Kind: VirtualMachineClaim · Scope: Namespaced · Short names: vmclaim

VirtualMachineClaim: one subject's exclusive, time-boxed hold on one pool member.

What a claim guarantees

  • Bound once, ever. The member it binds is never handed to another subject, never returned to the warm set, and never reused. Release is always destruction.
  • Deleting the claim destroys the VM, and the claim object does not disappear until it has.
  • ttlSeconds is a hard deadline, not a grace period. At expiry the member is deleted whether or not the consumer is finished.

What a claim is not

It is not a credential channel. spec.subject records who the member is for so the binding is auditable in the API server's own audit log; it is opaque to banlieue, and a token must never be placed in it. Delivering the subject's token to the guest is the consumer's job, over its own attested channel, anchored on the bound member's EK certificate (status.tpmEndorsementCertificates, ADR-0045, ADR-0049).

Printer columns (kubectl get):

Name Type JSON path Priority
Pool string .spec.poolRef.name 0
VM string .status.virtualMachineRef.name 0
Phase string .status.phase 0
Expires string .status.expiresAt 0
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
poolRef object Yes The pool to take a member from. Same namespace as the claim.
subject object Yes Who this member is for. Opaque to banlieue: recorded, mirrored onto the member as annotations, and never interpreted.
ttlSeconds integer Yes Hard lifetime in seconds, counted from binding rather than from creation — a claim that waited ten minutes for capacity still gets its full TTL. Required, with no default: a claim without a deadline is a leaked VM, and the right value is a property of the workload.

.spec.poolRef

The pool to take a member from. Same namespace as the claim.

Field Type Required Description
name string Yes

.spec.subject

Who this member is for. Opaque to banlieue: recorded, mirrored onto the member as annotations, and never interpreted.

Field Type Required Description
id string Yes Stable subject identifier within that issuer (the sub / oid claim), not a display name or e-mail.
issuer string Yes Token issuer the subject was authenticated by, e.g. an OIDC issuer URL.

.status

Field Type Required Description
addresses object[] Mirrored from the bound member so a consumer needs one GET.
boundAt string Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers.
conditions object[]
expiresAt string bound_at + spec.ttlSeconds. The member is deleted at this instant.
nonce string Deprecated, never set since v0.4.14. It was a per-claim value for ADR-0049's quote-over-nonce handshake, which SPIRE's TPM node attestation superseded (ADR-0049, amended 2026-11-05). Kept so an existing claim's status still parses; removed with the next API version.
observedGeneration integer
phase string Where a claim is in its one-way lifecycle. Allowed: Pending, Bound, Releasing, Failed.
tpmEndorsementCertificates string[] PEM vTPM endorsement key certificate(s) of the bound member, mirrored from the infra CR (ADR-0045). Lets a verifier check that an attestation comes from the VM banlieue itself created for this claim. Populated since ADR-0045, from the bound member's VirtualMachine.status, which mirrors its infrastructure CR. Empty for a member with no vTPM.
virtualMachineRef object The bound member. Set once, at bind time, and never rewritten.

.status.addresses[]

Mirrored from the bound member so a consumer needs one GET.

Field Type Required Description
address string Yes The address itself.
type string Yes Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS.

.status.conditions[]

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

.status.virtualMachineRef

The bound member. Set once, at bind time, and never rewritten.

Field Type Required Description
name string Yes

VMClass

API: banlieue.io/v1alpha1 · Kind: VMClass · Scope: Cluster · Short names: vmc

VMClass — a reusable, cluster-scoped catalog of VM "shapes".

A VMClass is to a VirtualMachine what a Kubernetes StorageClass is to a PersistentVolumeClaim: a named, admin-curated template that captures how much machine you get and what the backend must support, without naming any particular backend. A VirtualMachine references a VMClass by name (spec.classRef) instead of restating CPU / memory / disk / network on every VM.

Why create one

  • Standardize sizing. Define a small set of tiers (small, db-prod, gpu-trainer) once; users pick a tier instead of hand-tuning hardware.
  • Decouple intent from backend. A VMClass requests abstract storage and network classes plus feature flags (e.g. efiSecureBoot). The scheduler only places a VM on a Provider + failure domain that actually advertises those capabilities, so a class stays portable across vSphere, Proxmox, and libvirt.
  • Govern capabilities. Because requirements live on the class, cluster admins control which hardware shapes and features tenants may request.

How it is used

At schedule time the controller intersects this class's requirements with each candidate Provider's spec.capabilities and each failure domain's resolved attributes. A Provider that lacks the requested storage class, network class, firmware, or a required feature is filtered out.

Cluster-scoped: a VMClass is shared by VirtualMachines in any namespace.

Printer columns (kubectl get):

Name Type JSON path Priority
CPUs integer .spec.hardware.cpus 0
MemoryMiB integer .spec.hardware.memoryMiB 0
Firmware string .spec.firmware 0
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
features string[] Required feature flags. The scheduler will only select a Provider + failure domain whose features is a superset of this list.
firmware string Firmware. Providers / failure domains that lack support for the requested firmware are filtered out by the scheduler. Allowed: bios, efi, efi-secure.
hardware object Yes Virtual hardware shape — CPU, memory, and disks — every VM of this class is given.
network object Yes Network shape — the ordered interfaces (and their abstract network classes) every VM of this class is given.
tpmEnabled boolean Attach a virtual TPM (vTPM) device to every VM of this class (ADR-0039). A class-level capability, like firmware — not a per-VM override (VirtualMachineSpec.hardwareOverride has no tpmEnabled counterpart, for the same reason it has none for firmware). The scheduler only selects a Provider/failure domain advertising the vtpm feature when this is true. Used by Kairos's kcrypt to seal LUKS keys to the VM's own TPM at install time; the device must exist before first boot, which the vSphere provider guarantees by attaching it between clone and power-on.

.spec.hardware

Virtual hardware shape — CPU, memory, and disks — every VM of this class is given.

Field Type Required Description
cpus integer Yes Number of virtual CPUs.
disks object[] Yes Disks in attachment order. The first disk is the OS disk and is backed by the VMImage resolved for the VirtualMachine; subsequent disks are blank and created with the requested size and storage class.
memoryMiB integer Yes Memory in MiB.
.spec.hardware.disks[]

Disks in attachment order. The first disk is the OS disk and is backed by the VMImage resolved for the VirtualMachine; subsequent disks are blank and created with the requested size and storage class.

Field Type Required Description
name string Yes Stable name within the VM; used in status to report resolved backend identifiers.
provisioning string Disk provisioning hint. Providers honor on a best-effort basis. Allowed: thin, thick, eagerZeroed.
sizeGiB integer Yes Size in GiB. For the OS disk this is the minimum size; if the image is larger, the provider grows accordingly.
storageClass string Yes Abstract storage class name. MUST be advertised in the chosen Provider's spec.capabilities.storageClasses.

.spec.network

Network shape — the ordered interfaces (and their abstract network classes) every VM of this class is given.

Field Type Required Description
interfaces object[] Yes Network interfaces in attachment order.
.spec.network.interfaces[]

Network interfaces in attachment order.

Field Type Required Description
ipam object Yes IPAM configuration. Uses [IpamShape] (not [IpamSpec]) because a VMClass is shared by many VMs — there is no per-VM address at this level. Per-VM static addresses are provided via VirtualMachine.spec.networkOverrides.
mtu integer Optional MTU override. Provider may ignore if unsupported.
name string Yes Stable name within the VM.
networkClass string Yes Abstract network class name. MUST be advertised in the chosen Provider's spec.capabilities.networkClasses.
.spec.network.interfaces[].ipam

IPAM configuration. Uses [IpamShape] (not [IpamSpec]) because a VMClass is shared by many VMs — there is no per-VM address at this level. Per-VM static addresses are provided via VirtualMachine.spec.networkOverrides.

Field Type Required Description
pool object Pool-based IPAM parameters.
static object Shared subnet parameters (prefix, gateway, nameservers, domain) — not a per-VM address.
# .spec.network.interfaces[].ipam.pool

Pool-based IPAM parameters.

Field Type Required Description
poolRef object Yes Typed reference (apiGroup + kind + name + optional namespace).
## .spec.network.interfaces[].ipam.pool.poolRef

Typed reference (apiGroup + kind + name + optional namespace).

Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's default) or future banlieue-native pool types.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string
# .spec.network.interfaces[].ipam.static

Shared subnet parameters (prefix, gateway, nameservers, domain) — not a per-VM address.

Field Type Required Description
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer

VMImage

API: banlieue.io/v1alpha1 · Kind: VMImage · Scope: Cluster · Short names: vmi

VMImage — a cluster-scoped, backend-agnostic catalog entry for a bootable guest image.

A VMImage names an operating system (family / distribution / version / architecture) once, then lists — per provider class — where that image actually lives on each backend (spec.sources). A VirtualMachine references a VMImage by name (spec.imageRef); the scheduler and the chosen provider resolve it to a concrete template / backing file / import URL at provisioning time.

Why create one

  • One name, many backends. "ubuntu-22.04" can map to a vSphere template, a Proxmox template VMID, and a libvirt qcow2 — users reference a single VMImage regardless of where the VM lands.
  • Explicit, auditable image sourcing. Sources (and optional checksums) are declared, not auto-discovered, so what actually boots is reviewable.
  • Readiness gating. The image controller records per-Provider readiness in status; the scheduler refuses to place a VM until the image is confirmed available (or importable) on a candidate Provider.

Cluster-scoped: a VMImage is shared by VirtualMachines in any namespace.

Printer columns (kubectl get):

Name Type JSON path Priority
OS string .spec.osDistribution 0
Version string .spec.osVersion 0
Arch string .spec.architecture 0
Ready string .status.conditions[?(@.type=='Ready')].status 0
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
architecture string Yes Guest CPU architecture. Failure domains whose hosts cannot run this architecture are filtered out by the scheduler. Allowed: amd64, arm64.
cloudConfigs object[] Layered cloud-configs baked into the built artifact for Url-kind sources (ADR-0037). banlieue-imagebuilder fetches each referenced Secret in list order, deep-merges their YAML content (maps deep-merge, lists concatenate, type-mismatch errors), SSA-applies a single merged Secret (<vmimage-name>-cloud-config-merged), and passes that to the kairos-operator OSArtifact as cloudConfigRef (auroraboot build-iso --cloud-config). Empty list = no cloud-config. Index 0 is the base; each subsequent entry layers on top. SecretRef-first; see [CloudConfigSource] and ADR-0020. Ignored for non-Url sources.
firstBootSealing object Declares that every clone of this image seals the listed partitions to its own vTPM on its first boot (ADR-0088), which is what lets a VMClass with tpmEnabled: true use an Immediate (pre-installed) image. Without it that pairing is refused, because the template was installed before any per-VM vTPM existed (ADR-0048).
guestAgent string Guest agent contract this image is built to support; determines how VirtualMachine.spec.userData is delivered. Allowed: cloud-init, ignition, sysprep, none.
isoOverlay object Additional files overlaid onto a built ISO for Url-kind vSphere sources (e.g. a hand-verified grub.cfg). Resolved by banlieue-imagebuilder into the kairos-operator OSArtifact's spec.volumes[] + spec.artifacts.overlayISOVolume — the same auroraboot build-iso --overlay-iso mechanism a hand-run ISO-build pipeline would use. See [IsoOverlaySource] and ADR-0022. Ignored for cloudImage-kind builds and non-Url sources.
osDistribution string Yes Free-form distribution string. Examples: ubuntu, rhel, debian, fedora-coreos, windows-server.
osFamily string Yes Broad operating-system family. Coarser than osDistribution; lets providers apply high-level guest handling. Allowed: linux, windows, bsd, other.
osVersion string Yes Free-form version string. Examples: "22.04", "9.4", "2022".
prelay object Pre-lay the built image (ADR-0113): banlieue-imagebuilder boots the raw cloudImage once, at build time, through the Kairos recovery reset every clone would otherwise run on its first boot, so each clone boots straight into the installed system. Only for a Url source built as a cloudImage; an iso build is refused (PrelayNeedsCloudImage). The pre-lay Job runs the published banlieue-prelay image (banlieue-imagebuilder --prelay-image) and needs /dev/kvm on the build node. The published artifact is the pre-laid file, with a checksum the builder computed after verifying the built file against the source's checksum.
sources object[] Yes Per-provider source mappings — one backend binding for this catalog entry per providerClass you intend to schedule VMs onto ("one name, many backends", see the type-level doc comment above).
template object How the backend template is built from a Url source (root folder, network, disk, CPU / memory / firmware / NIC, force knobs). Every field is optional and falls back to a built-in default. Only meaningful for Url sources, with one exception: for a vSphere Template source (an existing template banlieue adopts and never builds) only rootFolder is read, to find the template in <rootFolder>/<failure-domain>; every other field is ignored. Ignored for BackingFile. See [VMImageTemplate], ADR-0020 and ADR-0104.
trustedBoot object Requests a Trusted Boot (UKI) artifact instead of a classic kernel+initrd one, for Url-kind vSphere sources. Resolved by banlieue-imagebuilder into the kairos-operator OSArtifact's spec.artifacts.uki.{iso,keysVolume} (replacing the plain artifacts.iso request) — the auroraboot build-uki mechanism. See [TrustedBootSource] and ADR-0051. Ignored for cloudImage-kind builds and non-Url sources.

.spec.cloudConfigs[]

Layered cloud-configs baked into the built artifact for Url-kind sources (ADR-0037). banlieue-imagebuilder fetches each referenced Secret in list order, deep-merges their YAML content (maps deep-merge, lists concatenate, type-mismatch errors), SSA-applies a single merged Secret (<vmimage-name>-cloud-config-merged), and passes that to the kairos-operator OSArtifact as cloudConfigRef (auroraboot build-iso --cloud-config). Empty list = no cloud-config. Index 0 is the base; each subsequent entry layers on top. SecretRef-first; see [CloudConfigSource] and ADR-0020. Ignored for non-Url sources.

Field Type Required Description
secretRef object Key in a Secret in the imagebuild namespace holding the cloud-config YAML (key defaults to [DEFAULT_CLOUD_CONFIG_KEY]).
.spec.cloudConfigs[].secretRef

Key in a Secret in the imagebuild namespace holding the cloud-config YAML (key defaults to [DEFAULT_CLOUD_CONFIG_KEY]).

Field Type Required Description
key string Key within the object's data. Defaults are caller-defined.
name string Yes Name of the ConfigMap / Secret in the referrer's namespace.

.spec.firstBootSealing

Declares that every clone of this image seals the listed partitions to its own vTPM on its first boot (ADR-0088), which is what lets a VMClass with tpmEnabled: true use an Immediate (pre-installed) image. Without it that pairing is refused, because the template was installed before any per-VM vTPM existed (ADR-0048).

For a Url source banlieue-imagebuilder writes the sealing policy into the built image itself (status.firstBootSealing: Built); for a Template or BackingFile source the image must already carry it, and this field is an operator assertion (Asserted). Either way every clone's GuestReady waits for the guest to report each listed partition sealed. Needs a source image on Kairos v4.4.0 or later. Honoured unless banlieue-controller runs with --enable-first-boot-sealing=false, which refuses a VirtualMachine of this image (FirstBootSealingDisabled). Not combinable with trustedBoot.

Field Type Required Description
partitions string[] Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal.
timeoutSeconds integer Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed.

.spec.isoOverlay

Additional files overlaid onto a built ISO for Url-kind vSphere sources (e.g. a hand-verified grub.cfg). Resolved by banlieue-imagebuilder into the kairos-operator OSArtifact's spec.volumes[] + spec.artifacts.overlayISOVolume — the same auroraboot build-iso --overlay-iso mechanism a hand-run ISO-build pipeline would use. See [IsoOverlaySource] and ADR-0022. Ignored for cloudImage-kind builds and non-Url sources.

Field Type Required Description
files object[] Explicit key -> ISO-relative-path mapping. At least one entry expected; an empty list is accepted but wires nothing into the OSArtifact.
secretRef object Yes Secret in the imagebuild namespace holding the overlay file contents.
.spec.isoOverlay.files[]

Explicit key -> ISO-relative-path mapping. At least one entry expected; an empty list is accepted but wires nothing into the OSArtifact.

Field Type Required Description
key string Yes Key within the overlay Secret holding this file's content.
path string Yes Destination path, relative to the ISO root (e.g. boot/grub2/grub.cfg).
.spec.isoOverlay.secretRef

Secret in the imagebuild namespace holding the overlay file contents.

Field Type Required Description
name string Yes

.spec.prelay

Pre-lay the built image (ADR-0113): banlieue-imagebuilder boots the raw cloudImage once, at build time, through the Kairos recovery reset every clone would otherwise run on its first boot, so each clone boots straight into the installed system. Only for a Url source built as a cloudImage; an iso build is refused (PrelayNeedsCloudImage). The pre-lay Job runs the published banlieue-prelay image (banlieue-imagebuilder --prelay-image) and needs /dev/kvm on the build node. The published artifact is the pre-laid file, with a checksum the builder computed after verifying the built file against the source's checksum.

Field Type Required Description
diskSizeGiB integer Yes The clones' OS disk size, in GiB. COS_PERSISTENT fills a disk of this size and does not grow on a larger one, and a smaller one cannot hold the image: give the classes that use this image this disk size (ADR-0113 Decision 4).

.spec.sources[]

Per-provider source mappings — one backend binding for this catalog entry per providerClass you intend to schedule VMs onto ("one name, many backends", see the type-level doc comment above).

x-kubernetes-list-type: map keyed on providerClass: the API server rejects a second entry for a providerClass that already has one, rather than leaving it to find_url_source / find_vsphere_source to silently pick whichever came first.

Field Type Required Description
checksum string Optional checksum for imported images. Format: <alg>:<hex>, e.g. sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b.... Supported algorithms: sha256, sha512. Provider import Jobs verify the built artifact against this value before writing it to the backend and fail closed on mismatch or an unsupported algorithm.
importFrom string Optional source URL. When set, providers that support image import will pull from here if the image isn't already present locally.
kind string Yes What kind of backend artifact ref refers to. Allowed: Template, BackingFile, Url.
providerClass string Yes Name of the ProviderClass this source applies to. Conventional values: vsphere, proxmox, libvirt.
ref string Yes Provider-interpreted reference: vsphere + Template: template name e.g. "ubuntu-22.04-cloudinit" proxmox + Template: template VMID e.g. "9000" libvirt + BackingFile: path e.g. "/var/lib/libvirt/images/ubuntu.qcow2" * + Url: ignored; uses importFrom

.spec.template

How the backend template is built from a Url source (root folder, network, disk, CPU / memory / firmware / NIC, force knobs). Every field is optional and falls back to a built-in default. Only meaningful for Url sources, with one exception: for a vSphere Template source (an existing template banlieue adopts and never builds) only rootFolder is read, to find the template in <rootFolder>/<failure-domain>; every other field is ignored. Ignored for BackingFile. See [VMImageTemplate], ADR-0020 and ADR-0104.

Field Type Required Description
cpus integer Virtual CPU count of the template (govc vm.create -c). When unset, defaults to 2. vSphere-only.
disk object Install disk of the template (the clone source's disk). When unset, a thin 100 GiB disk on a pvscsi controller is used.
firmware string Firmware for the template (govc vm.create -firmware). Reuses the backend-agnostic [Firmware] hint (bios / efi / efi-secure). When unset, defaults to efi. vSphere maps efi-secure to EFI with secure boot enabled. Allowed: bios, efi, efi-secure, null.
forceCreate boolean Recreate the template even if one of that name already exists, destroying the existing one first. Threaded as --force-create.
forceUpload boolean Re-upload the built ISO even if one of that name already exists on the backend, deleting the existing one first (the vСenter datastore file API does not overwrite in place). Threaded as --force-upload.
guestId string vCenter guestId for the template (govc vm.create -g, e.g. rhel9_64Guest, ubuntu64Guest). When unset, it is derived from the VMImage's osFamily / osDistribution / osVersion. vSphere-only.
installMode string How the template's install step is driven. See [InstallMode] and ADR-0021 / ADR-0040. Allowed: immediate, deferred, manual.
installTimeoutSeconds integer Bound, in seconds, on how long the import Job waits for the unattended Kairos install to finish and the VM to power itself off (install.poweroff: true in the cloud-config) before failing the Job. When unset, defaults to 1800 (30 min). See ADR-0021: the golden disk is never rebooted by the build, so this bounds only the (typically 8-12 min) unattended-install window, not a boot cycle.
memoryMib integer Memory of the template, in MiB (govc vm.create -m). When unset, defaults to 4096. vSphere-only.
network object[] The template's network interfaces. Empty means exactly one NIC, using every per-entry default below — the same behavior this field had before it became a list (ADR-0031). vSphere-only.
retainOnDelete boolean Keep the per-zone vCenter template(s) this VMImage caused to be built when the VMImage itself is deleted. When unset (the default), deleting a VMImage also destroys every per-zone template it owns — declarative deletion, matching VirtualMachine's own cascade onto its VSphereMachine (ADR-0026). Set true to opt out — e.g. the template is still referenced by another generation, or its lifecycle is managed by hand outside banlieue. vSphere-only; ignored by any other provider. See ADR-0028.
rootFolder string Root vCenter inventory folder (path under the datacenter's VM folder, e.g. templates/kairos); created if missing. When unset, the datacenter's VM-folder root is the root. vSphere-only. Read for both Url (where the template is created) and Template (where the existing template is looked up) sources (ADR-0104).
.spec.template.disk

Install disk of the template (the clone source's disk). When unset, a thin 100 GiB disk on a pvscsi controller is used.

Field Type Required Description
controller string Disk controller type. Defaults to pvscsi. Allowed: pvscsi, lsiLogic, lsiLogicSas, busLogic.
size integer Disk size, in GiB. Defaults to 100 when unset.
type string Provisioning hint: thin (default), thick, or eagerZeroed. Reuses the backend-agnostic [DiskProvisioning] shared with VMClass / VSphereMachine; eager-zeroing is the eagerZeroed variant, not a separate flag. Providers honor it on a best-effort basis. Allowed: thin, thick, eagerZeroed.
.spec.template.network[]

The template's network interfaces. Empty means exactly one NIC, using every per-entry default below — the same behavior this field had before it became a list (ADR-0031). vSphere-only.

Field Type Required Description
adapter string Virtual NIC adapter type for the template (govc vm.create -net.adapter). Allowed: vmxnet3, vmxnet2, e1000, e1000e.
network string Port group this NIC attaches to. When unset, the zone's first reachable network class (ADR-0019) is used.
pciSlot integer PCI slot number for this NIC (ethernetN.pciSlotNumber). Slot 192 on the first NIC yields a stable ens192 interface name in the guest. When unset, defaults to 192 + this NIC's index in VMImageTemplate.network — so a template with several NICs and no explicit slots still gets predictable, non-colliding ens192/ens193/ens194/... naming.

.spec.trustedBoot

Requests a Trusted Boot (UKI) artifact instead of a classic kernel+initrd one, for Url-kind vSphere sources. Resolved by banlieue-imagebuilder into the kairos-operator OSArtifact's spec.artifacts.uki.{iso,keysVolume} (replacing the plain artifacts.iso request) — the auroraboot build-uki mechanism. See [TrustedBootSource] and ADR-0051. Ignored for cloudImage-kind builds and non-Url sources.

Field Type Required Description
secretRef object Yes Secret in the imagebuild namespace holding the six files auroraboot build-uki requires: PK.auth, KEK.auth, db.auth, db.key, db.pem, tpm2-pcr-private.pem. Generated out-of-band via auroraboot genkey — banlieue never generates or manages this key material.
.spec.trustedBoot.secretRef

Secret in the imagebuild namespace holding the six files auroraboot build-uki requires: PK.auth, KEK.auth, db.auth, db.key, db.pem, tpm2-pcr-private.pem. Generated out-of-band via auroraboot genkey — banlieue never generates or manages this key material.

Field Type Required Description
name string Yes

.status

Observed availability of a VMImage across the Providers that can serve it. Maintained by the image controller; read by the scheduler.

Field Type Required Description
buildArtifact object Progress of the shared, provider-agnostic image build for Url-kind sources — set exclusively by banlieue-imagebuilder (field manager banlieue.io/imagebuilder), never by a provider. Typed by kind (cloudImage for libvirt, iso for vSphere). None when no Url source exists on this VMImage or the build hasn't started. See ADR-0010 and ADR-0020.
conditions object[] Ready is True iff every per-provider entry is ready.
firstBootSealing string How banlieue knows an image seals itself on first boot (ADR-0088). Allowed: Built, Asserted.
observedGeneration integer
perProvider object[] Per-Provider readiness. One entry per Provider that supports this image's providerClass and has reconciled at least once.

.status.buildArtifact

Progress of the shared, provider-agnostic image build for Url-kind sources — set exclusively by banlieue-imagebuilder (field manager banlieue.io/imagebuilder), never by a provider. Typed by kind (cloudImage for libvirt, iso for vSphere). None when no Url source exists on this VMImage or the build hasn't started. See ADR-0010 and ADR-0020.

Field Type Required Description
checksum string Expected checksum (<alg>:<hex>) of the built artifact, copied from the Url source the build serves. Consumers that stream the artifact to a backend MUST verify it against this value and fail closed on mismatch (security review 2026-07-31, SEC-004) — the value lives here, next to the PVC reference, so no consumer has to re-derive which source the shared build came from.
file string File name of the artifact within the artifacts PVC (kairos-operator convention: <osArtifactRef>.raw for cloudImage, <osArtifactRef>.iso for iso). Populated at phase Ready.
firstBootSealingLayer boolean Whether this build carries the banlieue-generated first-boot sealing layer (ADR-0088): set when spec.firstBootSealing was honoured by the merged cloud-config this artifact was built from. Omitted when false.
kind string Yes What kind of artifact was built, aligned with kairos-operator's own OSArtifactKind. Determines the file extension and which provider class consumes it. Allowed: cloudImage, iso.
message string Long human-readable detail, e.g. the OSArtifact.status.message on failure.
ociArtifact object The same artifact, pushed to an OCI registry for providers that run outside the cluster and cannot mount the artifacts PVC (ADR-0064). Set only when a cloud-hypervisor Url source exists; None otherwise, so installs without a host-resident provider need no registry.
osArtifactRef string Yes Name of the OSArtifact CR banlieue-imagebuilder created for this VMImage (same namespace as the artifacts PVC below).
osArtifactUid string metadata.uid of the OSArtifact named by os_artifact_ref, once observed. Each provider's per-zone import Job sets this as its own ownerReference so a rebuilt (deleted-and-recreated) OSArtifact garbage-collects the stale Job — and the artifacts PVC mount it holds — instead of the Job outliving it for up to its ttlSecondsAfterFinished (ADR-0027). Absent until the OSArtifact has actually been observed once.
phase string Yes Current build phase. Allowed: Pending, Building, Ready, Failed.
prelaidDiskSizeGiB integer The disk size, in GiB, the artifact was pre-laid for (ADR-0113), when spec.prelay was honoured: file is then the pre-laid image and checksum its digest, computed by the builder. Omitted otherwise.
pvcRef object Reference to the PVC kairos-operator created holding the built artifact, once known. Populated no earlier than phase Building.
reason string Short reason, mirroring the stable-string convention used elsewhere in this status (e.g. ImagePerProviderStatus.reason).
.status.buildArtifact.ociArtifact

The same artifact, pushed to an OCI registry for providers that run outside the cluster and cannot mount the artifacts PVC (ADR-0064). Set only when a cloud-hypervisor Url source exists; None otherwise, so installs without a host-resident provider need no registry.

Field Type Required Description
message string Human-readable detail, e.g. why the push failed.
phase string Yes Current push phase. Allowed: Pushing, Ready, Failed.
reference string Digest-pinned reference, registry/repository@sha256:<hex>, once the push succeeded. Consumers pull by this digest and nothing else: integrity comes from content addressing, so a tag moved after the push cannot change what a host boots.
.status.buildArtifact.pvcRef

Reference to the PVC kairos-operator created holding the built artifact, once known. Populated no earlier than phase Building.

Field Type Required Description
name string Yes

.status.conditions[]

Ready is True iff every per-provider entry is ready.

Written only by banlieue-controller (field manager banlieue.io/controller), which is the only component with a whole-image view. A provider cannot compute "ready everywhere" from rows it does not own, so it writes its perProvider entry and nothing here (ADR-0015). Merge-keyed on type, per Kubernetes convention.

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

.status.perProvider[]

Per-Provider readiness. One entry per Provider that supports this image's providerClass and has reconciled at least once.

Merge-keyed, and it must stay that way (ADR-0015). Several providers write this list concurrently, each applying only its own entry. Without x-kubernetes-list-type: map server-side apply treats the array as atomic — one manager owns the whole thing and force() hands it over wholesale, silently discarding every other provider's row. That was a real, reproduced bug, not a theoretical one.

Field Type Required Description
message string Long human-readable detail.
providerName string Yes Name of the Provider.
providerNamespace string Yes Namespace of the Provider.
ready boolean Yes True when the image can be used to clone/create a VM on this provider.
reason string Short reason if not ready. Stable values from condition_reasons::IMAGE_*.
resolvedRef string Resolved concrete reference on the backend, for backends with one reference per provider. Proxmox: VMID. Libvirt: path. Unset for vSphere, whose per-zone references are in [Self::zones] (ADR-0104).
zones object[] Per-zone (per-Provider.status.failureDomains[]) readiness. Populated by the vSphere provider for both Url sources (import progress) and Template sources (whether the adopted template exists in each zone's folder, ADR-0104). For Url, ready means every zone is ready; for Template it means at least one zone is, and the scheduler places VMs only in ready zones. Empty for backends without zones (libvirt, Proxmox).
.status.perProvider[].zones[]

Per-zone (per-Provider.status.failureDomains[]) readiness. Populated by the vSphere provider for both Url sources (import progress) and Template sources (whether the adopted template exists in each zone's folder, ADR-0104). For Url, ready means every zone is ready; for Template it means at least one zone is, and the scheduler places VMs only in ready zones. Empty for backends without zones (libvirt, Proxmox).

Field Type Required Description
message string
name string Yes Name of the failure domain, matching Provider.status.failureDomains[].name.
ready boolean Yes True once the template is usable in this zone (import finished for Url; template found in the zone's folder for Template).
reason string
resolvedRef string The template's bare display name within this zone once ready — the value a provider passes to a name-based template lookup. NOT a decorated string (no [dc]/folder prefix): the folder lives in [Self::template_folder], kept separate so a lookup can be built from structured fields instead of parsing this one.
templateFolder string The vCenter folder path (relative to the datacenter's VM folder, e.g. templates/cluster-01) the template in [Self::resolved_ref] lives in: <spec.template.rootFolder>/<zone> for both Url imports (ADR-0020 Decision #5) and Template sources (ADR-0104). Unset while the zone is not ready.

CloudHypervisorMachine

API: infrastructure.banlieue.io/v1alpha1 · Kind: CloudHypervisorMachine · Scope: Namespaced · Short names: chm

CloudHypervisorMachine — the concrete, scheduled VM request for a Cloud Hypervisor host.

You normally do not create this by hand: banlieue's controller does, owned by the VirtualMachine it was scheduled from, and the host-resident provider on the chosen host runs it as a Cloud Hypervisor guest.

Printer columns (kubectl get):

Name Type JSON path Priority
Provider string .spec.providerRef.name 0
Provisioned boolean .status.initialization.provisioned 0
Power string .status.observedPowerState 0
Image string .spec.bootSource.image 1
ProviderID string .spec.providerID 1
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
bootSource object Yes Where the OS disk comes from.
cpus object Yes Virtual CPUs.
desiredPowerState string Desired power state, resolved from the parent VirtualMachine. Allowed: PoweredOn, PoweredOff, Suspended.
failureDomain string CAPI contract (optional): failure domain placement. One host is one failure domain on this backend, as on libvirt.
firstBootSealing object First-boot sealing the guest must report before GuestReady (ADR-0088, ADR-0112), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. The guest reports over its vsock (sealed= beside phase=installed). None for every other machine, which keeps today's GuestReady meaning unchanged.
memory object Yes Guest memory.
nics object[] Yes Network interfaces.
osDiskSizeGiB integer Yes OS disk size in GiB. Required, and grown to before first boot; never shrunk. Must be at least the image's size.
providerID string CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: cloudhypervisor://<provider-name>/<machine-uid>. Set by the provider once the guest exists.
providerRef object Yes The Provider for the one host that runs this machine (ADR-0060).
storageClass string Yes Storage class the machine's disks live in. A name the host declares in its local config and publishes on its failure domain; never a path.
tpmEnabled boolean Attach a vTPM (swtpm), resolved from the VM's VMClass.spec.tpmEnabled. Requires [ChBootSourceKind::InstallMedia] (ADR-0040, ADR-0048, ADR-0065), or an image that seals itself on first boot ([Self::first_boot_sealing], ADR-0088, ADR-0112).
userData string Guest bootstrap payload, already resolved and placeholder-substituted by banlieue-controller (ADR-0025, ADR-0038). Rendered into a NoCloud CIDATA seed disk; the provider reads no Secret or ConfigMap.

.spec.bootSource

Where the OS disk comes from.

Field Type Required Description
image string Yes The image in the host's image cache: an installed raw disk for Image, the installer ISO for InstallMedia.
kind string Yes Which provisioning shape this machine uses. Allowed: image, installMedia.

.spec.cpus

Virtual CPUs.

Field Type Required Description
boot integer Yes vCPUs the guest boots with.
max integer Hotplug headroom: the most vCPUs the guest may be resized to. Fixed when the VM is created. None means no headroom.

.spec.firstBootSealing

First-boot sealing the guest must report before GuestReady (ADR-0088, ADR-0112), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. The guest reports over its vsock (sealed= beside phase=installed). None for every other machine, which keeps today's GuestReady meaning unchanged.

Field Type Required Description
partitions string[] Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal.
timeoutSeconds integer Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed.

.spec.memory

Guest memory.

Field Type Required Description
hugepages boolean Back guest memory with hugepages. The host reports hugepages as their own capacity, since they are reserved rather than allocated on demand.
sizeMiB integer Yes Guest memory in MiB.

.spec.nics[]

Network interfaces.

Field Type Required Description
ipam object Yes IP address management for this interface.
macAddress string Optional MAC address. The provider derives a stable one from the machine UID otherwise, so the address survives a restart.
name string Yes Stable NIC name; echoed in status.
networkClass string Yes Network class: a name the host resolves to one of its bridges. Never a bridge name from the cluster.
.spec.nics[].ipam

IP address management for this interface.

Field Type Required Description
pool object Pool-based IPAM parameters.
static object Static IPAM parameters (address, prefix, gateway, nameservers, domain).
.spec.nics[].ipam.pool

Pool-based IPAM parameters.

Field Type Required Description
poolRef object Yes Typed reference (apiGroup + kind + name + optional namespace).
# .spec.nics[].ipam.pool.poolRef

Typed reference (apiGroup + kind + name + optional namespace).

Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's default) or future banlieue-native pool types.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string
.spec.nics[].ipam.static

Static IPAM parameters (address, prefix, gateway, nameservers, domain).

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes

.spec.providerRef

The Provider for the one host that runs this machine (ADR-0060).

Field Type Required Description
name string Yes

.status

Observed state of a CloudHypervisorMachine, shaped to the CAPI v1beta2 InfraMachine status contract. The non-contract fields mean what they mean on LibvirtMachineStatus, so the controller's status mirror treats both backends alike.

Field Type Required Description
addressSource string Which source answered the provider's address lookup. Allowed: static, neighbour.
addresses object[] CAPI contract field (optional): VM addresses.
conditions object[] Standard Kubernetes conditions.
failureDomain string CAPI contract field (optional): observed failure domain.
guestInstalled boolean Whether the installed guest has announced itself (ADR-0043). Sticky once true.
hostUid integer The unprivileged host uid this machine's units run as (ADR-0063 Decision 3). Recorded so the provider re-adopts a running guest without trusting its own memory.
initialization object CAPI contract field.
installMediaDetached boolean Whether the installer has been removed, live and for future starts (ADR-0044, ADR-0065 Decision 4). Sticky once true; None when there was never an installer.
observedGeneration integer The metadata.generation this status was computed from.
observedPowerState string The VM's last observed run state. Allowed: PoweredOn, PoweredOff, Suspended, null.
sealedPartitions string[] Partitions the guest has reported sealed, as LUKS containers, on a first-boot sealing machine (ADR-0088, ADR-0112): from the sealed= line of its vsock report. Sticky: the report is re-sent every boot, and a powered-off machine has not become unsealed. Empty until reported, and on every machine without spec.firstBootSealing. Guest-supplied, so it is only ever used to withhold GuestReady.
tpmAttached boolean Whether a vTPM was attached, when spec.tpmEnabled is set.
tpmEndorsementCertificates string[] PEM EK certificates, validated against this machine (ADR-0045, ADR-0065).

.status.addresses[]

CAPI contract field (optional): VM addresses.

Field Type Required Description
address string Yes The address itself.
type string Yes Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS.

.status.conditions[]

Standard Kubernetes conditions.

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

.status.initialization

CAPI contract field.

Field Type Required Description
provisioned boolean True when the infrastructure provider reports that the resource's infrastructure is fully provisioned.

CloudHypervisorMachineTemplate

API: infrastructure.banlieue.io/v1alpha1 · Kind: CloudHypervisorMachineTemplate · Scope: Namespaced · Short names: chmt

CloudHypervisorMachineTemplate — a stamped-out CloudHypervisorMachine spec.

CAPI requires an InfraMachineTemplate so a MachineSet or MachineDeployment can mint identical machines. A spec template, not a disk template: nothing clones a guest, which is what keeps per-VM vTPMs unique (ADR-0040).

.spec

Field Type Required Description
template object Yes The spec stamped into every machine created from this template.

.spec.template

The spec stamped into every machine created from this template.

Field Type Required Description
spec object Yes The CloudHypervisorMachine spec for machines created from this template.
.spec.template.spec

The CloudHypervisorMachine spec for machines created from this template.

Field Type Required Description
bootSource object Yes Where the OS disk comes from.
cpus object Yes Virtual CPUs.
desiredPowerState string Desired power state, resolved from the parent VirtualMachine. Allowed: PoweredOn, PoweredOff, Suspended.
failureDomain string CAPI contract (optional): failure domain placement. One host is one failure domain on this backend, as on libvirt.
firstBootSealing object First-boot sealing the guest must report before GuestReady (ADR-0088, ADR-0112), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. The guest reports over its vsock (sealed= beside phase=installed). None for every other machine, which keeps today's GuestReady meaning unchanged.
memory object Yes Guest memory.
nics object[] Yes Network interfaces.
osDiskSizeGiB integer Yes OS disk size in GiB. Required, and grown to before first boot; never shrunk. Must be at least the image's size.
providerID string CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: cloudhypervisor://<provider-name>/<machine-uid>. Set by the provider once the guest exists.
providerRef object Yes The Provider for the one host that runs this machine (ADR-0060).
storageClass string Yes Storage class the machine's disks live in. A name the host declares in its local config and publishes on its failure domain; never a path.
tpmEnabled boolean Attach a vTPM (swtpm), resolved from the VM's VMClass.spec.tpmEnabled. Requires [ChBootSourceKind::InstallMedia] (ADR-0040, ADR-0048, ADR-0065), or an image that seals itself on first boot ([Self::first_boot_sealing], ADR-0088, ADR-0112).
userData string Guest bootstrap payload, already resolved and placeholder-substituted by banlieue-controller (ADR-0025, ADR-0038). Rendered into a NoCloud CIDATA seed disk; the provider reads no Secret or ConfigMap.
.spec.template.spec.bootSource

Where the OS disk comes from.

Field Type Required Description
image string Yes The image in the host's image cache: an installed raw disk for Image, the installer ISO for InstallMedia.
kind string Yes Which provisioning shape this machine uses. Allowed: image, installMedia.
.spec.template.spec.cpus

Virtual CPUs.

Field Type Required Description
boot integer Yes vCPUs the guest boots with.
max integer Hotplug headroom: the most vCPUs the guest may be resized to. Fixed when the VM is created. None means no headroom.
.spec.template.spec.firstBootSealing

First-boot sealing the guest must report before GuestReady (ADR-0088, ADR-0112), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. The guest reports over its vsock (sealed= beside phase=installed). None for every other machine, which keeps today's GuestReady meaning unchanged.

Field Type Required Description
partitions string[] Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal.
timeoutSeconds integer Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed.
.spec.template.spec.memory

Guest memory.

Field Type Required Description
hugepages boolean Back guest memory with hugepages. The host reports hugepages as their own capacity, since they are reserved rather than allocated on demand.
sizeMiB integer Yes Guest memory in MiB.
.spec.template.spec.nics[]

Network interfaces.

Field Type Required Description
ipam object Yes IP address management for this interface.
macAddress string Optional MAC address. The provider derives a stable one from the machine UID otherwise, so the address survives a restart.
name string Yes Stable NIC name; echoed in status.
networkClass string Yes Network class: a name the host resolves to one of its bridges. Never a bridge name from the cluster.
# .spec.template.spec.nics[].ipam

IP address management for this interface.

Field Type Required Description
pool object Pool-based IPAM parameters.
static object Static IPAM parameters (address, prefix, gateway, nameservers, domain).
## .spec.template.spec.nics[].ipam.pool

Pool-based IPAM parameters.

Field Type Required Description
poolRef object Yes Typed reference (apiGroup + kind + name + optional namespace).
### .spec.template.spec.nics[].ipam.pool.poolRef

Typed reference (apiGroup + kind + name + optional namespace).

Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's default) or future banlieue-native pool types.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string
## .spec.template.spec.nics[].ipam.static

Static IPAM parameters (address, prefix, gateway, nameservers, domain).

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes
.spec.template.spec.providerRef

The Provider for the one host that runs this machine (ADR-0060).

Field Type Required Description
name string Yes

LibvirtMachine

API: infrastructure.banlieue.io/v1alpha1 · Kind: LibvirtMachine · Scope: Namespaced · Short names: lvm

LibvirtMachine — the concrete, scheduled VM request for a libvirt/KVM host.

You normally do not create this by hand: banlieue's controller does, owned by the VirtualMachine it was scheduled from, and the libvirt provider reconciles it into a real domain.

Printer columns (kubectl get):

Name Type JSON path Priority
Provider string .spec.providerRef.name 0
Provisioned boolean .status.initialization.provisioned 0
Power string .status.observedPowerState 0
Domain string .spec.domainName 1
ProviderID string .spec.providerID 1
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
bootSource object Yes How this machine's OS disk comes into being.
desiredPowerState string Desired power state, resolved from the parent VirtualMachine's spec.desiredPowerState (ADR-0024). Allowed: PoweredOn, PoweredOff, Suspended.
disks object[] Yes Disks. The first is the OS disk; the rest are blank data disks.
domainName string Yes libvirt domain name. Unique per host, and the handle every domain procedure takes.
failureDomain string CAPI contract (optional): failure domain placement. The banlieue scheduler writes the chosen failure domain here.
firmware string Yes Firmware. EFI requires OVMF on the host; EfiSecure additionally requires a .secboot.fd variant and pre-enrolled keys. Allowed: bios, efi, efi-secure.
firstBootSealing object First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged.
machineType string QEMU machine type (q35, pc, …). None lets libvirt pick its default for the host's architecture, which is the right answer unless an image needs a specific chipset.
memoryMiB integer Yes Memory in MiB.
network object[] Yes Network interfaces.
pool string Yes Storage pool that holds this machine's volumes, resolved from the storage class by the scheduler.
providerID string CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: libvirt://<provider-name>/<domain-uuid>. Set by the provider controller after the domain is defined.
providerRef object Yes Reference to the banlieue Provider whose connection details describe the target libvirt host.
tpmEnabled boolean Attach an emulated TPM 2.0 device (swtpm), resolved from the VM's VMClass.spec.tpmEnabled (ADR-0039).
userData string Guest bootstrap payload, already resolved from the parent VirtualMachine's spec.userData Secret or ConfigMap (ADR-0038) and placeholder-substituted by banlieue-controller (ADR-0025). The provider renders it into a NoCloud cidata volume — it never reads a Secret or ConfigMap itself.
vcpus integer Yes Number of virtual CPUs.

.spec.bootSource

How this machine's OS disk comes into being.

Field Type Required Description
kind string Yes Which of the two provisioning shapes this machine uses. Allowed: backingVolume, installMedia.
volume string Yes Volume name within [LibvirtMachineSpec::pool]: the backing image for BackingVolume, or the installer ISO for InstallMedia.

.spec.disks[]

Disks. The first is the OS disk; the rest are blank data disks.

Field Type Required Description
bus string Controller bus. Allowed: virtio, scsi, sata.
name string Yes Stable disk name; echoed in status and used to name the volume.
sizeGiB integer Yes Disk size in GiB. For an overlay OS disk this is a floor — the overlay is created at least this large.

.spec.firstBootSealing

First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged.

Field Type Required Description
partitions string[] Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal.
timeoutSeconds integer Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed.

.spec.network[]

Network interfaces.

Field Type Required Description
ipam object Yes IP address management for this interface.
macAddress string Optional MAC address (otherwise libvirt generates one).
model string Device model. None means virtio, which is what every image banlieue builds expects.
name string Yes Stable NIC name; echoed in status.
source object Yes Resolved bridge or libvirt network.
.spec.network[].ipam

IP address management for this interface.

Field Type Required Description
pool object Pool-based IPAM parameters.
static object Static IPAM parameters (address, prefix, gateway, nameservers, domain).
.spec.network[].ipam.pool

Pool-based IPAM parameters.

Field Type Required Description
poolRef object Yes Typed reference (apiGroup + kind + name + optional namespace).
# .spec.network[].ipam.pool.poolRef

Typed reference (apiGroup + kind + name + optional namespace).

Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's default) or future banlieue-native pool types.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string
.spec.network[].ipam.static

Static IPAM parameters (address, prefix, gateway, nameservers, domain).

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes
.spec.network[].source

Resolved bridge or libvirt network.

Field Type Required Description
kind string Yes Whether name names a host bridge or a libvirt network. Allowed: network, bridge.
name string Yes The bridge interface (br0) or libvirt network (default).

.spec.providerRef

Reference to the banlieue Provider whose connection details describe the target libvirt host.

Field Type Required Description
name string Yes

.status

Observed state of a LibvirtMachine, shaped to the CAPI v1beta2 InfraMachine status contract (plus libvirt-specific diagnostics).

Field Type Required Description
addressSource string Which source answered when the provider looked up the guest's addresses (ADR-0050 Decision 8). Allowed: guestAgent, dhcpLease, arpTable, static.
addresses object[] CAPI contract field (optional): VM addresses.
conditions object[] CAPI-compatible conditions. The Ready condition is mirrored as InfrastructureReady on the parent per contract.
domainUuid string libvirt's UUID for the domain, in its 36-character textual form. The domain's real identity — stable across rename and host restart — and the source for spec.providerID. Not part of the CAPI contract.
failureDomain string CAPI contract field (optional): observed failure domain — the host the domain actually landed on.
guestInstalled boolean Whether the installed guest has announced itself (ADR-0043).
initialization object CAPI contract field: replaces the deprecated v1beta1 status.ready.
installMediaDetached boolean Whether the install medium has been ejected (ADR-0044).
observedGeneration integer
observedPowerState string The domain's last observed run state, mapped onto banlieue's backend-neutral [PowerState] (ADR-0034). The hypervisor's view, not a guest-OS-boot signal. Not part of the CAPI contract; mirrored onto the parent VirtualMachine's status.observedPowerState. Allowed: PoweredOn, PoweredOff, Suspended, null.
sealedPartitions string[] Partitions the guest has reported sealed, as LUKS containers, on a first-boot sealing machine (ADR-0088): from `/run/banlieue/sealed, read with the guest agent. **Sticky**: the report is re-asserted every boot but lives in volatile state, and a powered-off machine has not become unsealed. Empty until reported, and on every machine withoutspec.firstBootSealing. Guest-supplied, so it is only ever used to *withhold*GuestReady`.
tpmAttached boolean Whether an emulated TPM was attached, when spec.tpmEnabled is set (ADR-0039). None when tpmEnabled is false or the attach has not run yet. A failed attach surfaces through the conditions rather than a dedicated VirtualMachine-level mirror.
tpmEndorsementCertificates string[] PEM vTPM endorsement key certificate(s) reported by the guest and validated against this domain (ADR-0045).

.status.addresses[]

CAPI contract field (optional): VM addresses.

Field Type Required Description
address string Yes The address itself.
type string Yes Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS.

.status.conditions[]

CAPI-compatible conditions. The Ready condition is mirrored as InfrastructureReady on the parent per contract.

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

.status.initialization

CAPI contract field: replaces the deprecated v1beta1 status.ready.

Field Type Required Description
provisioned boolean True when the infrastructure provider reports that the resource's infrastructure is fully provisioned.

LibvirtMachineTemplate

API: infrastructure.banlieue.io/v1alpha1 · Kind: LibvirtMachineTemplate · Scope: Namespaced · Short names: lvmt

LibvirtMachineTemplate — a stamped-out LibvirtMachine spec.

CAPI requires an InfraMachineTemplate so higher-level controllers (a MachineSet / MachineDeployment) can mint many identical machines from one template. banlieue ships it for CAPI compatibility; standalone VirtualMachine users do not need it.

Note that a template is a spec template, not a disk template: nothing here clones a domain. That distinction matters on libvirt, because cloning a domain that carries TPM state would copy the state too, which is precisely ADR-0040's shared-vTPM problem.

.spec

Field Type Required Description
template object Yes The LibvirtMachine spec stamped into every machine created from this template.

.spec.template

The LibvirtMachine spec stamped into every machine created from this template.

Field Type Required Description
spec object Yes The LibvirtMachine spec for machines created from this template.
.spec.template.spec

The LibvirtMachine spec for machines created from this template.

Field Type Required Description
bootSource object Yes How this machine's OS disk comes into being.
desiredPowerState string Desired power state, resolved from the parent VirtualMachine's spec.desiredPowerState (ADR-0024). Allowed: PoweredOn, PoweredOff, Suspended.
disks object[] Yes Disks. The first is the OS disk; the rest are blank data disks.
domainName string Yes libvirt domain name. Unique per host, and the handle every domain procedure takes.
failureDomain string CAPI contract (optional): failure domain placement. The banlieue scheduler writes the chosen failure domain here.
firmware string Yes Firmware. EFI requires OVMF on the host; EfiSecure additionally requires a .secboot.fd variant and pre-enrolled keys. Allowed: bios, efi, efi-secure.
firstBootSealing object First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged.
machineType string QEMU machine type (q35, pc, …). None lets libvirt pick its default for the host's architecture, which is the right answer unless an image needs a specific chipset.
memoryMiB integer Yes Memory in MiB.
network object[] Yes Network interfaces.
pool string Yes Storage pool that holds this machine's volumes, resolved from the storage class by the scheduler.
providerID string CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: libvirt://<provider-name>/<domain-uuid>. Set by the provider controller after the domain is defined.
providerRef object Yes Reference to the banlieue Provider whose connection details describe the target libvirt host.
tpmEnabled boolean Attach an emulated TPM 2.0 device (swtpm), resolved from the VM's VMClass.spec.tpmEnabled (ADR-0039).
userData string Guest bootstrap payload, already resolved from the parent VirtualMachine's spec.userData Secret or ConfigMap (ADR-0038) and placeholder-substituted by banlieue-controller (ADR-0025). The provider renders it into a NoCloud cidata volume — it never reads a Secret or ConfigMap itself.
vcpus integer Yes Number of virtual CPUs.
.spec.template.spec.bootSource

How this machine's OS disk comes into being.

Field Type Required Description
kind string Yes Which of the two provisioning shapes this machine uses. Allowed: backingVolume, installMedia.
volume string Yes Volume name within [LibvirtMachineSpec::pool]: the backing image for BackingVolume, or the installer ISO for InstallMedia.
.spec.template.spec.disks[]

Disks. The first is the OS disk; the rest are blank data disks.

Field Type Required Description
bus string Controller bus. Allowed: virtio, scsi, sata.
name string Yes Stable disk name; echoed in status and used to name the volume.
sizeGiB integer Yes Disk size in GiB. For an overlay OS disk this is a floor — the overlay is created at least this large.
.spec.template.spec.firstBootSealing

First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged.

Field Type Required Description
partitions string[] Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal.
timeoutSeconds integer Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed.
.spec.template.spec.network[]

Network interfaces.

Field Type Required Description
ipam object Yes IP address management for this interface.
macAddress string Optional MAC address (otherwise libvirt generates one).
model string Device model. None means virtio, which is what every image banlieue builds expects.
name string Yes Stable NIC name; echoed in status.
source object Yes Resolved bridge or libvirt network.
# .spec.template.spec.network[].ipam

IP address management for this interface.

Field Type Required Description
pool object Pool-based IPAM parameters.
static object Static IPAM parameters (address, prefix, gateway, nameservers, domain).
## .spec.template.spec.network[].ipam.pool

Pool-based IPAM parameters.

Field Type Required Description
poolRef object Yes Typed reference (apiGroup + kind + name + optional namespace).
### .spec.template.spec.network[].ipam.pool.poolRef

Typed reference (apiGroup + kind + name + optional namespace).

Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's default) or future banlieue-native pool types.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string
## .spec.template.spec.network[].ipam.static

Static IPAM parameters (address, prefix, gateway, nameservers, domain).

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes
# .spec.template.spec.network[].source

Resolved bridge or libvirt network.

Field Type Required Description
kind string Yes Whether name names a host bridge or a libvirt network. Allowed: network, bridge.
name string Yes The bridge interface (br0) or libvirt network (default).
.spec.template.spec.providerRef

Reference to the banlieue Provider whose connection details describe the target libvirt host.

Field Type Required Description
name string Yes

ProxmoxMachine

API: infrastructure.banlieue.io/v1alpha1 · Kind: ProxmoxMachine · Scope: Namespaced · Short names: pvem

ProxmoxMachine — the concrete, scheduled VM request for the Proxmox backend.

You normally do not create this by hand: banlieue's controller does, owned by the VirtualMachine it was scheduled from, and the Proxmox provider clones the template into a VM and reports CAPI-shaped status.

Printer columns (kubectl get):

Name Type JSON path Priority
Provider string .spec.providerRef.name 0
Node string .status.node 0
VMID integer .status.vmid 0
Provisioned boolean .status.initialization.provisioned 0
Power string .status.observedPowerState 0
ProviderID string .spec.providerID 1
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
cores integer Yes Cores per socket.
cpuType string CPU model (host, x86-64-v2-AES, …). Proxmox's default applies when absent.
dataDisks object[] Additional blank disks, attached after the OS disk.
desiredPowerState string Desired power state, resolved from the parent VirtualMachine. Allowed: PoweredOn, PoweredOff, Suspended.
failureDomain string CAPI contract (optional): failure domain placement. One node is one failure domain (roadmap 06).
firmware string Firmware: bios selects SeaBIOS; efi and efi-secure select OVMF, the latter with Microsoft/distribution keys pre-enrolled. The template must be able to boot the chosen firmware. Allowed: bios, efi, efi-secure.
isoStorage string Storage the NoCloud seed ISO is uploaded to. Must allow iso content. Required whenever userData is set.
memoryMiB integer Yes Memory in MiB.
nics object[] Yes Network interfaces.
node string Yes Node the VM is created on (resolved from the failure domain).
osDiskSizeGiB integer Yes OS disk size in GiB: the cloned disk is grown to at least this, never shrunk.
pool string Proxmox resource pool to place the VM in.
providerID string CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: proxmox://<provider-name>/<vmid>. Set by the provider once the VM exists.
providerRef object Yes The Provider whose connection describes the target Proxmox cluster.
sockets integer CPU sockets.
storage string Yes Storage id for the cloned and new disks (resolved from the storage class). Must allow images content.
templateVmid integer Yes VMID of the template VM to clone. Must be a template (ADR-0075 Decision 5a); the provider checks before cloning.
tpmEnabled boolean Attach a vTPM 2.0 (tpmstate0 on storage), resolved from VMClass.spec.tpmEnabled and attached before first boot.
userData string Guest bootstrap payload, already resolved and placeholder-substituted by banlieue-controller (ADR-0025, ADR-0038). Rendered into a NoCloud CIDATA ISO (ADR-0054); the provider reads no Secret or ConfigMap.

.spec.dataDisks[]

Additional blank disks, attached after the OS disk.

Field Type Required Description
discard boolean Pass TRIM/discard to the storage.
iothread boolean Dedicated I/O thread (virtio-scsi-single).
name string Yes Stable disk name; echoed in status.
sizeGiB integer Yes Size in GiB.
ssd boolean Present as an SSD to the guest.
storage string Storage id; defaults to the machine's storage.

.spec.nics[]

Network interfaces.

Field Type Required Description
bridge string Yes Bridge on the node (resolved from the network class), e.g. vmbr0.
ipam object Yes IP address management for this interface.
macAddress string Optional MAC address (Proxmox generates one otherwise).
model string Emulated NIC model. Allowed: virtio, e1000, rtl8139, vmxnet3.
name string Yes Stable NIC name; echoed in status.
vlan integer 802.1Q VLAN tag.
.spec.nics[].ipam

IP address management for this interface.

Field Type Required Description
pool object Pool-based IPAM parameters.
static object Static IPAM parameters (address, prefix, gateway, nameservers, domain).
.spec.nics[].ipam.pool

Pool-based IPAM parameters.

Field Type Required Description
poolRef object Yes Typed reference (apiGroup + kind + name + optional namespace).
# .spec.nics[].ipam.pool.poolRef

Typed reference (apiGroup + kind + name + optional namespace).

Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's default) or future banlieue-native pool types.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string
.spec.nics[].ipam.static

Static IPAM parameters (address, prefix, gateway, nameservers, domain).

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes

.spec.providerRef

The Provider whose connection describes the target Proxmox cluster.

Field Type Required Description
name string Yes

.status

Observed state of a ProxmoxMachine, shaped to the CAPI v1beta2 InfraMachine status contract. The non-contract fields mean what they mean on the siblings, so the controller's status mirror treats backends alike.

Field Type Required Description
addressSource string Which source produced a machine's addresses. Allowed: static, guestAgent.
addresses object[] CAPI contract field (optional): VM addresses.
conditions object[] Standard Kubernetes conditions.
failureDomain string CAPI contract field (optional): observed failure domain.
initialization object CAPI contract field.
node string The node the VM was last seen on; a migration changes it.
observedGeneration integer The metadata.generation this status was computed from.
observedPowerState string The VM's last observed run state. Allowed: PoweredOn, PoweredOff, Suspended, null.
tpmAttached boolean Whether a vTPM was attached, when spec.tpmEnabled is set.
vmid integer The VMID, recorded before the clone so a crash cannot allocate a second VM (ADR-0075 Decision 4). A cache, not the source of truth: the VM's name is the ownership marker.

.status.addresses[]

CAPI contract field (optional): VM addresses.

Field Type Required Description
address string Yes The address itself.
type string Yes Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS.

.status.conditions[]

Standard Kubernetes conditions.

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

.status.initialization

CAPI contract field.

Field Type Required Description
provisioned boolean True when the infrastructure provider reports that the resource's infrastructure is fully provisioned.

ProxmoxMachineTemplate

API: infrastructure.banlieue.io/v1alpha1 · Kind: ProxmoxMachineTemplate · Scope: Namespaced · Short names: pvemt

ProxmoxMachineTemplate — a stamped-out ProxmoxMachine spec.

CAPI requires an InfraMachineTemplate so a MachineSet or MachineDeployment can mint identical machines. banlieue ships it for CAPI compatibility; standalone VirtualMachine users do not need it.

.spec

Field Type Required Description
template object Yes The spec stamped into every machine created from this template.

.spec.template

The spec stamped into every machine created from this template.

Field Type Required Description
spec object Yes The ProxmoxMachine spec for machines created from this template.
.spec.template.spec

The ProxmoxMachine spec for machines created from this template.

Field Type Required Description
cores integer Yes Cores per socket.
cpuType string CPU model (host, x86-64-v2-AES, …). Proxmox's default applies when absent.
dataDisks object[] Additional blank disks, attached after the OS disk.
desiredPowerState string Desired power state, resolved from the parent VirtualMachine. Allowed: PoweredOn, PoweredOff, Suspended.
failureDomain string CAPI contract (optional): failure domain placement. One node is one failure domain (roadmap 06).
firmware string Firmware: bios selects SeaBIOS; efi and efi-secure select OVMF, the latter with Microsoft/distribution keys pre-enrolled. The template must be able to boot the chosen firmware. Allowed: bios, efi, efi-secure.
isoStorage string Storage the NoCloud seed ISO is uploaded to. Must allow iso content. Required whenever userData is set.
memoryMiB integer Yes Memory in MiB.
nics object[] Yes Network interfaces.
node string Yes Node the VM is created on (resolved from the failure domain).
osDiskSizeGiB integer Yes OS disk size in GiB: the cloned disk is grown to at least this, never shrunk.
pool string Proxmox resource pool to place the VM in.
providerID string CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: proxmox://<provider-name>/<vmid>. Set by the provider once the VM exists.
providerRef object Yes The Provider whose connection describes the target Proxmox cluster.
sockets integer CPU sockets.
storage string Yes Storage id for the cloned and new disks (resolved from the storage class). Must allow images content.
templateVmid integer Yes VMID of the template VM to clone. Must be a template (ADR-0075 Decision 5a); the provider checks before cloning.
tpmEnabled boolean Attach a vTPM 2.0 (tpmstate0 on storage), resolved from VMClass.spec.tpmEnabled and attached before first boot.
userData string Guest bootstrap payload, already resolved and placeholder-substituted by banlieue-controller (ADR-0025, ADR-0038). Rendered into a NoCloud CIDATA ISO (ADR-0054); the provider reads no Secret or ConfigMap.
.spec.template.spec.dataDisks[]

Additional blank disks, attached after the OS disk.

Field Type Required Description
discard boolean Pass TRIM/discard to the storage.
iothread boolean Dedicated I/O thread (virtio-scsi-single).
name string Yes Stable disk name; echoed in status.
sizeGiB integer Yes Size in GiB.
ssd boolean Present as an SSD to the guest.
storage string Storage id; defaults to the machine's storage.
.spec.template.spec.nics[]

Network interfaces.

Field Type Required Description
bridge string Yes Bridge on the node (resolved from the network class), e.g. vmbr0.
ipam object Yes IP address management for this interface.
macAddress string Optional MAC address (Proxmox generates one otherwise).
model string Emulated NIC model. Allowed: virtio, e1000, rtl8139, vmxnet3.
name string Yes Stable NIC name; echoed in status.
vlan integer 802.1Q VLAN tag.
# .spec.template.spec.nics[].ipam

IP address management for this interface.

Field Type Required Description
pool object Pool-based IPAM parameters.
static object Static IPAM parameters (address, prefix, gateway, nameservers, domain).
## .spec.template.spec.nics[].ipam.pool

Pool-based IPAM parameters.

Field Type Required Description
poolRef object Yes Typed reference (apiGroup + kind + name + optional namespace).
### .spec.template.spec.nics[].ipam.pool.poolRef

Typed reference (apiGroup + kind + name + optional namespace).

Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's default) or future banlieue-native pool types.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string
## .spec.template.spec.nics[].ipam.static

Static IPAM parameters (address, prefix, gateway, nameservers, domain).

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes
.spec.template.spec.providerRef

The Provider whose connection describes the target Proxmox cluster.

Field Type Required Description
name string Yes

VSphereCluster

API: infrastructure.banlieue.io/v1alpha1 · Kind: VSphereCluster · Scope: Namespaced · Short names: vsc

VSphereCluster — banlieue's CAPI v1beta2 InfraCluster for vSphere backends.

It tells CAPI where a cluster's machines may be placed by aggregating the failure domains of one or more Providers (vCenters) into the CAPI-shaped status.failureDomains list. The control-plane endpoint is operator-supplied (a VIP) or filled in by the control-plane provider (e.g. k0smotron).

Why it exists

  • Cluster-side failure-domain spread. CAPI's control-plane / MachineSet controllers balance machines across the FDs published here. "Spread across all 6 domains" is simply replicas: 6 over a VSphereCluster that advertises 6 FDs.
  • Multi-vCenter clusters. One Kubernetes cluster can span several Providers — a capability beyond single-vCenter CAPV.

You do not create the resulting VMs by hand; CAPI mints VSphereMachines (the InfraMachine) from a VSphereMachineTemplate. This object only advertises where they may go.

Printer columns (kubectl get):

Name Type JSON path Priority
Provisioned boolean .status.initialization.provisioned 0
Endpoint string .status.controlPlaneEndpoint.host 1
Ready string .status.conditions[?(@.type=='Ready')].status 0
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
controlPlaneEndpoint object CAPI contract (optional): the cluster's API-server endpoint. Operator- supplied control-plane VIP, or left unset for a control-plane provider (e.g. k0smotron) to manage. Mirrored to status.controlPlaneEndpoint.
controlPlaneFailureDomainSelector object Which aggregated failure domains are eligible to run control-plane nodes, matched against the Provider FD labels. When unset, all aggregated FDs are control-plane eligible. Use this to keep the etcd quorum to a bounded, odd set of domains while workers spread wider.
paused boolean Suspend reconciliation. Equivalent to the cluster.x-k8s.io/paused annotation but in-band.
providerRefs object[] Explicit list of Providers (in this namespace) to aggregate. Takes precedence over providerSelector when non-empty. Declaring the set explicitly is the preferred, "explicit over implicit" form.
providerSelector object Select Providers (in this namespace) to aggregate failure domains from, by matching their labels. Ignored when providerRefs is set.

.spec.controlPlaneEndpoint

CAPI contract (optional): the cluster's API-server endpoint. Operator- supplied control-plane VIP, or left unset for a control-plane provider (e.g. k0smotron) to manage. Mirrored to status.controlPlaneEndpoint.

Field Type Required Description
host string Yes Hostname or IP on which the API server is serving.
port integer Yes Port on which the API server is serving.

.spec.controlPlaneFailureDomainSelector

Which aggregated failure domains are eligible to run control-plane nodes, matched against the Provider FD labels. When unset, all aggregated FDs are control-plane eligible. Use this to keep the etcd quorum to a bounded, odd set of domains while workers spread wider.

Field Type Required Description
matchExpressions object[]
matchLabels map[string]string
.spec.controlPlaneFailureDomainSelector.matchExpressions[]
Field Type Required Description
key string Yes
operator string Yes Allowed: In, NotIn, Exists, DoesNotExist.
values string[]

.spec.providerRefs[]

Explicit list of Providers (in this namespace) to aggregate. Takes precedence over providerSelector when non-empty. Declaring the set explicitly is the preferred, "explicit over implicit" form.

Field Type Required Description
name string Yes

.spec.providerSelector

Select Providers (in this namespace) to aggregate failure domains from, by matching their labels. Ignored when providerRefs is set.

Field Type Required Description
matchExpressions object[]
matchLabels map[string]string
.spec.providerSelector.matchExpressions[]
Field Type Required Description
key string Yes
operator string Yes Allowed: In, NotIn, Exists, DoesNotExist.
values string[]

.status

Observed state of a VSphereCluster, shaped to the CAPI v1beta2 InfraCluster status contract.

Field Type Required Description
conditions object[] CAPI-compatible conditions. The Ready condition is mirrored to the parent Cluster's InfrastructureReady; Paused reflects pause state.
controlPlaneEndpoint object CAPI contract field (optional): the resolved API-server endpoint, echoed from spec.controlPlaneEndpoint or set by the control-plane provider.
failureDomains object[] CAPI contract field: the failure domains machines may be placed in, aggregated from the selected Providers. A list per v1beta2.
initialization object CAPI contract field: replaces the deprecated v1beta1 status.ready. provisioned == true once the failure domains are resolved (and the control-plane endpoint is known, when one is required).
observedGeneration integer The generation of the spec the controller has reconciled.

.status.conditions[]

CAPI-compatible conditions. The Ready condition is mirrored to the parent Cluster's InfrastructureReady; Paused reflects pause state.

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

.status.controlPlaneEndpoint

CAPI contract field (optional): the resolved API-server endpoint, echoed from spec.controlPlaneEndpoint or set by the control-plane provider.

Field Type Required Description
host string Yes Hostname or IP on which the API server is serving.
port integer Yes Port on which the API server is serving.

.status.failureDomains[]

CAPI contract field: the failure domains machines may be placed in, aggregated from the selected Providers. A list per v1beta2.

Field Type Required Description
attributes map[string]string Arbitrary attributes for consumers. banlieue flattens the Provider FD's attributes.raw plus dc/cluster labels into this map.
controlPlane boolean Whether this failure domain is eligible to run control-plane nodes. None is treated by CAPI as "not control-plane eligible".
name string Yes Unique failure-domain name (one of the Provider's status.failureDomains[].name).

.status.initialization

CAPI contract field: replaces the deprecated v1beta1 status.ready. provisioned == true once the failure domains are resolved (and the control-plane endpoint is known, when one is required).

Field Type Required Description
provisioned boolean True when the infrastructure provider reports that the resource's infrastructure is fully provisioned.

VSphereMachine

API: infrastructure.banlieue.io/v1alpha1 · Kind: VSphereMachine · Scope: Namespaced · Short names: vsm

VSphereMachine — the concrete, scheduled VM request for the vSphere backend.

This is banlieue's reference implementation of the CAPI v1beta2 InfraMachine contract. Where a VirtualMachine is abstract, every field here is already resolved: a real vCenter template, datacenter, cluster, datastore, and per-NIC portGroup. banlieue's main controller creates it after scheduling; the vSphere provider reconciles it into a real VM and reports CAPI-shaped status.

Why it exists

  • It is the hand-off. A VirtualMachine says "an ubuntu db-prod VM somewhere reasonable"; a VSphereMachine says "clone template X in DC0 / cluster C0 onto datastore ds-fast-01" — the thing a provider can actually execute.
  • CAPI-compatible by contract. Because it satisfies the InfraMachine contract, it doubles as a Cluster API infrastructure provider: a clusterv1.Machine with infrastructureRef.kind: VSphereMachine drives it the same way.

You normally do not create this by hand — the controller does, owned by the VirtualMachine. The CAPI contract label cluster.x-k8s.io/v1beta2: v1alpha1 is emitted onto the generated CRD by crdgen, since kube-derive cannot set CRD-level labels (ADR-0005).

Printer columns (kubectl get):

Name Type JSON path Priority
Provider string .spec.providerRef.name 0
Provisioned boolean .status.initialization.provisioned 0
Power string .status.observedPowerState 0
ProviderID string .spec.providerID 1
Cluster string .spec.cluster 1
Age date .metadata.creationTimestamp 0

.spec

Field Type Required Description
cluster string Yes Compute cluster within the datacenter.
createdBy string The principal that created the parent VirtualMachine, copied from its banlieue.io/created-by annotation when present (ADR-0089). That annotation is stamped by an optional MutatingAdmissionPolicy (deploy/admission/virtualmachine-created-by.yaml) from request.userInfo.username at VirtualMachine CREATE — None on a cluster that doesn't apply it, or for a VirtualMachine that predates it. Surfaced as the vCenter CreatedBy custom attribute by the provider; never a stand-in value when absent.
datacenter string Yes Datacenter name.
datastore string Yes Datastore or datastore cluster name (resolved from the storage class).
desiredPowerState string Desired power state, resolved from the parent VirtualMachine's spec.desiredPowerState (ADR-0024). Defaults to PoweredOn, matching VirtualMachineSpec's own default. Allowed: PoweredOn, PoweredOff, Suspended.
disks object[] Yes Disks. The first disk is the template's OS disk (grown if needed); subsequent disks are blank.
failureDomain string CAPI contract (optional): failure domain placement. The banlieue scheduler writes the chosen failure domain here; for CAPI users the parent Machine's spec.failureDomain is what populates this.
firmware string Yes Firmware. EFI / EFI Secure require the template to be EFI-capable. Allowed: bios, efi, efi-secure.
firstBootSealing object First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged.
folder string Destination vCenter folder path for the clone (not the source template — see template_folder). Optional; defaults to the datacenter VM root, or (once set by banlieue-controller) the same per-zone folder the template lives in.
memoryMiB integer Yes Memory in MiB.
network object[] Yes Network interfaces.
numCpus integer Yes Number of virtual CPUs.
providerID string CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: vsphere://<vm-instance-uuid>. Set by the provider controller after the VM is created.
providerRef object Yes Reference to the banlieue Provider whose connection details describe the target vCenter.
resourcePool string Resource pool path within the cluster. Optional; defaults to the cluster's root resource pool.
template string Yes vCenter template's bare display name (resolved from VMImage). Never a decorated string (no [dc]/folder prefix) — see template_folder for the scoping the lookup needs.
templateFolder string The per-zone vCenter folder the template in template lives in (resolved from VMImage.status, e.g. templates/cluster-01, ADR-0020 Decision #5). Set for both Url and Template vSphere sources (ADR-0104); None only for a row written by a provider that predates it, whose lookup is datacenter-wide.
tpmEnabled boolean Attach a virtual TPM (vTPM) device to this VM, resolved from the VM's VMClass.spec.tpmEnabled (ADR-0039). Consumed by the provider controller between clone_vm (which always clones powered off) and the power-on step, so the device exists before first boot — a hard requirement for Kairos's kcrypt to seal LUKS keys to it during unattended install.
userData string Guest bootstrap payload content — already resolved from the parent VirtualMachine's spec.userData Secret or ConfigMap (ADR-0038) and placeholder-substituted (ADR-0024's ${VM_NAME}/${FQDN}/etc. set) by banlieue-controller (ADR-0025). The provider delivers this verbatim (base64 into guestinfo.userdata) — it never reads a Secret or ConfigMap itself.

.spec.disks[]

Disks. The first disk is the template's OS disk (grown if needed); subsequent disks are blank.

Field Type Required Description
name string Yes Stable disk name; echoed in status with resolved backend identifiers.
provisioning string Provisioning hint (thin / thick / eager-zeroed). Allowed: thin, thick, eagerZeroed.
sizeGiB integer Yes Disk size in GiB. For the OS disk this is a floor — the template's disk is grown to at least this size.

.spec.firstBootSealing

First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged.

Field Type Required Description
partitions string[] Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal.
timeoutSeconds integer Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed.

.spec.network[]

Network interfaces.

Field Type Required Description
ipam object Yes IP address management for this interface.
macAddress string Optional MAC address (otherwise vCenter generates one).
name string Yes Stable NIC name; echoed in status.
portGroup string Yes Resolved port group or distributed port group name.
.spec.network[].ipam

IP address management for this interface.

Field Type Required Description
pool object Pool-based IPAM parameters.
static object Static IPAM parameters (address, prefix, gateway, nameservers, domain).
.spec.network[].ipam.pool

Pool-based IPAM parameters.

Field Type Required Description
poolRef object Yes Typed reference (apiGroup + kind + name + optional namespace).
# .spec.network[].ipam.pool.poolRef

Typed reference (apiGroup + kind + name + optional namespace).

Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's default) or future banlieue-native pool types.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string
.spec.network[].ipam.static

Static IPAM parameters (address, prefix, gateway, nameservers, domain).

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes

.spec.providerRef

Reference to the banlieue Provider whose connection details describe the target vCenter.

Field Type Required Description
name string Yes

.status

Observed state of a VSphereMachine, shaped to the CAPI v1beta2 InfraMachine status contract (plus a few vSphere-specific diagnostics).

Field Type Required Description
addresses object[] CAPI contract field (optional): VM addresses. Surfaced to the parent Machine's status.addresses once initialization is complete.
conditions object[] CAPI-compatible conditions (using metav1.Condition). The Ready condition is mirrored as InfrastructureReady on the parent (clusterv1.Machine or banlieue VirtualMachine) per contract.
failureDomain string CAPI contract field (optional): observed failure domain. Surfaced to the parent Machine's status.failureDomain.
guestInstalled boolean Whether the installed guest has announced itself, distinct from a live installer still overwriting the disk (ADR-0043). Read from guestinfo.banlieue.phase via config.extraConfig — the guest writes it with vmware-rpctool, the host reads it back here. None means nothing has looked yet (the whole life of an Immediate image, or a Deferred one before its first observation); sticky at Some(true) once observed, since the runtime value does not survive a power cycle but a stopped VM has not become uninstalled. Not part of the CAPI contract; mirrored onto the parent VirtualMachine as the GuestReady condition (common::condition_types::GUEST_READY), never as Ready.
initialization object CAPI contract field: replaces the deprecated v1beta1 status.ready.
installMediaDetached boolean Whether the provider has made sure no install medium is left on the VM (ADR-0044, vSphere amendment 2026-10-23).
instanceUuid string VM instance UUID. Stable across vCenter restarts and the source for spec.providerID. Not part of the CAPI contract.
observedGeneration integer
observedPowerState string The backend VM's actual power state, as last observed via VirtualMachine.runtime.powerState (ADR-0034) — the hypervisor's view, available immediately on power-on, not a guest-OS-boot signal. Absent until first observed. Not part of the CAPI contract; mirrored onto the parent VirtualMachine's own status.observedPowerState. Allowed: PoweredOn, PoweredOff, Suspended, null.
sealedPartitions string[] Partitions the guest has reported sealed, as LUKS containers, on a first-boot sealing machine (ADR-0088): from guestinfo.banlieue.sealed. Sticky: the report is re-asserted every boot but lives in volatile state, and a powered-off machine has not become unsealed. Empty until reported, and on every machine without spec.firstBootSealing. Guest-supplied, so it is only ever used to withhold GuestReady.
tpmAttached boolean Whether a vTPM device was successfully attached, when spec.tpmEnabled is set (ADR-0039). None when tpmEnabled is false (nothing was ever attempted) or the attach hasn't run yet. Not part of the CAPI contract; a failed attach surfaces through the Ready/InfrastructureReady conditions rather than a dedicated VirtualMachine-level mirror (ADR-0034's reasoning for observedPowerState applies equally here).
tpmEndorsementCertificates string[] PEM vTPM endorsement key certificate(s) issued by vCenter for this VM's vTPM (ADR-0045).
vmRef string VMware managed-object reference (vm-NNNN). Useful for operator diagnostics. Not part of the CAPI contract.

.status.addresses[]

CAPI contract field (optional): VM addresses. Surfaced to the parent Machine's status.addresses once initialization is complete.

Field Type Required Description
address string Yes The address itself.
type string Yes Address type. Accepted: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS. Allowed: Hostname, ExternalIP, InternalIP, ExternalDNS, InternalDNS.

.status.conditions[]

CAPI-compatible conditions (using metav1.Condition). The Ready condition is mirrored as InfrastructureReady on the parent (clusterv1.Machine or banlieue VirtualMachine) per contract.

Field Type Required Description
lastTransitionTime string Yes lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
message string Yes message is a human readable message indicating details about the transition. This may be an empty string.
observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
reason string Yes reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status string Yes status of the condition, one of True, False, Unknown.
type string Yes type of condition in CamelCase or in foo.example.com/CamelCase.

.status.initialization

CAPI contract field: replaces the deprecated v1beta1 status.ready.

Field Type Required Description
provisioned boolean True when the infrastructure provider reports that the resource's infrastructure is fully provisioned.

VSphereMachineTemplate

API: infrastructure.banlieue.io/v1alpha1 · Kind: VSphereMachineTemplate · Scope: Namespaced · Short names: vsmt

VSphereMachineTemplate — a stamped-out VSphereMachine spec.

CAPI requires an InfraMachineTemplate so higher-level controllers (a MachineSet / MachineDeployment) can mint many identical machines from one template. It wraps a single template.spec that is the VSphereMachine spec used for each generated machine. banlieue ships it for CAPI compatibility; standalone VirtualMachine users do not need it.

.spec

Field Type Required Description
template object Yes The VSphereMachine spec stamped into every machine created from this template.

.spec.template

The VSphereMachine spec stamped into every machine created from this template.

Field Type Required Description
spec object Yes The VSphereMachine spec for machines created from this template.
.spec.template.spec

The VSphereMachine spec for machines created from this template.

Field Type Required Description
cluster string Yes Compute cluster within the datacenter.
createdBy string The principal that created the parent VirtualMachine, copied from its banlieue.io/created-by annotation when present (ADR-0089). That annotation is stamped by an optional MutatingAdmissionPolicy (deploy/admission/virtualmachine-created-by.yaml) from request.userInfo.username at VirtualMachine CREATE — None on a cluster that doesn't apply it, or for a VirtualMachine that predates it. Surfaced as the vCenter CreatedBy custom attribute by the provider; never a stand-in value when absent.
datacenter string Yes Datacenter name.
datastore string Yes Datastore or datastore cluster name (resolved from the storage class).
desiredPowerState string Desired power state, resolved from the parent VirtualMachine's spec.desiredPowerState (ADR-0024). Defaults to PoweredOn, matching VirtualMachineSpec's own default. Allowed: PoweredOn, PoweredOff, Suspended.
disks object[] Yes Disks. The first disk is the template's OS disk (grown if needed); subsequent disks are blank.
failureDomain string CAPI contract (optional): failure domain placement. The banlieue scheduler writes the chosen failure domain here; for CAPI users the parent Machine's spec.failureDomain is what populates this.
firmware string Yes Firmware. EFI / EFI Secure require the template to be EFI-capable. Allowed: bios, efi, efi-secure.
firstBootSealing object First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged.
folder string Destination vCenter folder path for the clone (not the source template — see template_folder). Optional; defaults to the datacenter VM root, or (once set by banlieue-controller) the same per-zone folder the template lives in.
memoryMiB integer Yes Memory in MiB.
network object[] Yes Network interfaces.
numCpus integer Yes Number of virtual CPUs.
providerID string CAPI contract: Provider ID for the resulting Node, if this VM becomes a Kubernetes node. Format: vsphere://<vm-instance-uuid>. Set by the provider controller after the VM is created.
providerRef object Yes Reference to the banlieue Provider whose connection details describe the target vCenter.
resourcePool string Resource pool path within the cluster. Optional; defaults to the cluster's root resource pool.
template string Yes vCenter template's bare display name (resolved from VMImage). Never a decorated string (no [dc]/folder prefix) — see template_folder for the scoping the lookup needs.
templateFolder string The per-zone vCenter folder the template in template lives in (resolved from VMImage.status, e.g. templates/cluster-01, ADR-0020 Decision #5). Set for both Url and Template vSphere sources (ADR-0104); None only for a row written by a provider that predates it, whose lookup is datacenter-wide.
tpmEnabled boolean Attach a virtual TPM (vTPM) device to this VM, resolved from the VM's VMClass.spec.tpmEnabled (ADR-0039). Consumed by the provider controller between clone_vm (which always clones powered off) and the power-on step, so the device exists before first boot — a hard requirement for Kairos's kcrypt to seal LUKS keys to it during unattended install.
userData string Guest bootstrap payload content — already resolved from the parent VirtualMachine's spec.userData Secret or ConfigMap (ADR-0038) and placeholder-substituted (ADR-0024's ${VM_NAME}/${FQDN}/etc. set) by banlieue-controller (ADR-0025). The provider delivers this verbatim (base64 into guestinfo.userdata) — it never reads a Secret or ConfigMap itself.
.spec.template.spec.disks[]

Disks. The first disk is the template's OS disk (grown if needed); subsequent disks are blank.

Field Type Required Description
name string Yes Stable disk name; echoed in status with resolved backend identifiers.
provisioning string Provisioning hint (thin / thick / eager-zeroed). Allowed: thin, thick, eagerZeroed.
sizeGiB integer Yes Disk size in GiB. For the OS disk this is a floor — the template's disk is grown to at least this size.
.spec.template.spec.firstBootSealing

First-boot sealing the guest must report before GuestReady (ADR-0088), copied by banlieue-controller from the parent VirtualMachine's VMImage.spec.firstBootSealing when the class is tpmEnabled. None for every other machine, which keeps today's GuestReady meaning unchanged.

Field Type Required Description
partitions string[] Kairos partition labels to seal on first boot. Defaults to [COS_PERSISTENT]. COS_OEM, COS_STATE, COS_RECOVERY and COS_GRUB are refused at admission, mirroring Kairos's own refusal.
timeoutSeconds integer Seconds from the machine's power-on (its infrastructure Ready transition) within which the guest must report every listed partition sealed; after that GuestReady is False with reason FirstBootSealingTimeout. A clone that cannot seal halts in its initramfs and never reports anything, so this is how it is noticed.
.spec.template.spec.network[]

Network interfaces.

Field Type Required Description
ipam object Yes IP address management for this interface.
macAddress string Optional MAC address (otherwise vCenter generates one).
name string Yes Stable NIC name; echoed in status.
portGroup string Yes Resolved port group or distributed port group name.
# .spec.template.spec.network[].ipam

IP address management for this interface.

Field Type Required Description
pool object Pool-based IPAM parameters.
static object Static IPAM parameters (address, prefix, gateway, nameservers, domain).
## .spec.template.spec.network[].ipam.pool

Pool-based IPAM parameters.

Field Type Required Description
poolRef object Yes Typed reference (apiGroup + kind + name + optional namespace).
### .spec.template.spec.network[].ipam.pool.poolRef

Typed reference (apiGroup + kind + name + optional namespace).

Used wherever the referenced kind is pluggable — e.g. IPAM pools, where we want to accept either ipam.cluster.x-k8s.io/IPAddressClaim (CAPI's default) or future banlieue-native pool types.

Field Type Required Description
apiGroup string Yes
kind string Yes
name string Yes
namespace string
## .spec.template.spec.network[].ipam.static

Static IPAM parameters (address, prefix, gateway, nameservers, domain).

Field Type Required Description
address string Yes
domain string DNS domain, used both as a DNS search domain and (by a VirtualMachine.spec.networkOverrides consumer, ADR-0024) to build an FQDN as <vm-name>.<domain>.
gateway string
nameservers string[]
prefix integer Yes
.spec.template.spec.providerRef

Reference to the banlieue Provider whose connection details describe the target vCenter.

Field Type Required Description
name string Yes