Commit Graph
3 Commits
Author SHA1 Message Date
Aleksei Sviridkin 620a4bdcc0 feat(cozystack-controller): run the GPU class controllers
The class status and the license copier run in cozystack-controller
behind --enable-gpu, which the chart passes from gpu.enabled. The
status controller is off without the flag, since it caches every
Node. The copier always runs: without the flag it deletes every
copy, so a token does not stay in tenant namespaces after GPU
features are switched off, and clears the free counts and conditions
the stopped status controller would otherwise leave stale.

License Secrets are watched on the metadata-only Secret cache the CA
projection already owns. The manager's own Secret cache is scoped by
label to wildcard replicas, and a watch on it would never see a
hoster's Secret. The envtest suite drives both controllers through
their watches, since a mis-scoped watch fails without an error.

No RBAC rule is added: the controller already reads every kind, holds
every verb on cozystack.io and the cluster-wide Secret write.

Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-11-03 13:15:13 +03:00
Aleksei Sviridkin 5fa3133505 feat(gpu): copy vGPU license Secrets into entitled namespaces
A VM of a licensed vGPU class mounts its license from a Secret in its
own namespace, so the token reaches entitled tenants only and is
rotated by a VM restart rather than by rebuilding a shared image. The
copier keeps one copy per class in every namespace whose vGPU label
is "true", with the token and a gridd.conf carrying the class's
FeatureType, and deletes copies the label, the class or its license
no longer call for.

A missing hoster Secret, or one without the token, keeps the copies
already written: deleting them would stop every restarting VM over
what is usually a rotation in progress. New copies wait, and the
class shows LicenseSecretMissing so the hoster sees why.

Only Secrets carrying both the copy's name and the class label are
ever written or deleted, so a tenant's own Secret of the same name is
left alone. The token is read through the uncached reader and stays
out of every cache.

Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-11-03 13:15:12 +03:00
Aleksei Sviridkin 02df4af713 feat(gpu): compute GPUClass free capacity from node allocatable
A tenant picking a GPU class needs to know whether a VM of it is
likely to start, and a hoster needs to see a class that can never
serve a VM before a tenant's start is refused. With no GPUNode and no
binder in step 1, both figures come from the Node and Pod objects
alone: free units are a node's allocatable count of the class's
resource name minus what its pods request, over nodes that are Ready,
not cordoned and carry no taint the class does not tolerate.

One pass covers every class, because a class's ResourceNameConflict
depends on the classes created before it. The KubeVirt CR is read on
each pass and on a one-minute recheck instead of watched, so the
controller needs no KubeVirt kinds served to start.

The class status is readable by every authenticated user, so the
inventory and load behind it, the allocatable and requested totals
per class, go to metrics instead.

Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-11-03 06:28:33 +03:00