Skip to content

feat: support a remote Liqo Snapshot control plane - #16

Merged
rst0git merged 5 commits into
mainfrom
feat/liqo-control-plane
Oct 20, 2026
Merged

rst0git merged 5 commits into
mainfrom
feat/liqo-control-plane

Conversation

@rst0git

@rst0git rst0git commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Box agent with separate Curie and box API clients, pod-identity stamping and an admission webhook, explicit cleanup handoff. Unmodified Liqo. Design: doublewordai/internal#4677

View guided diff Turn on auto-fix

Keep Snapshot metadata on the consumer while a provider agent validates
reflected Pod identities and executes against its local runtime. Delegate
artifact cleanup explicitly so the consumer cannot acknowledge deletion
from an unrelated filesystem.

Scope the initial path to one namespace mapping and physical node. Add
capture reservation, restore revalidation, cleanup guards, chart
configuration and regression tests. Leave the feature disabled by default.

Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
A restore Pod with an unknown or unrecognized phase may still be using its artifact. Only treat Succeeded and Failed Pods as terminal, and continue blocking cleanup while a restore protection finalizer remains.

Cover terminal, active and unknown phases on both metadata and provider APIs, including protected terminal Pods.

Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The credential volume exposed only the kubeconfig key, so referenced token and certificate files were unavailable. Project the dedicated Secret in full into the agent without subPath mounts, preserving file-based token rotation.

Document the token-file configuration and cover the complete, read-only agent projection and exclusion from PageBroker in a Helm regression test.

Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Keep consumer-owned Snapshot metadata without requiring a modified Liqo
reflector. Stamp actual consumer Pod UIDs with optimistic preconditions
and validate new provider ShadowPods against fresh metadata and the
configured reflector identity. Prevent updates from adopting or rebinding
an existing ShadowPod while allowing cleanup after source loss.

Share binding checks between the agent and webhook, deploy admission as a
separate process with read-only credentials and provisioned TLS, and keep
the new components disabled by default. Document fresh-namespace migration
and fail-closed availability requirements.

Cover stamping and admission with unit tests, two-apiserver TLS integration
tests, and Helm configuration guards. Real Liqo/GPU qualification remains
a separate deployment gate.

Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
@cubic-dev-ai

cubic-dev-ai Bot commented Oct 20, 2026

Copy link
Copy Markdown

Running ultrareview automatically — this PR appears to change authentication, authorization, or input validation, where a missed bug can expose data or grant the wrong access, so a deeper multi-pass review is worth running. I'll post findings when complete.

@rst0git rst0git added the skip-issue-check Maintainer waiver for the approved-issue requirement label Oct 20, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultrareview ran automatically — this PR appears to change authentication, authorization, or input validation, where a missed bug can expose data or grant the wrong access, so a deeper multi-pass review is worth running.

1 issue found across 43 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="agent/pkg/provenance/client.go">

<violation number="1" location="agent/pkg/provenance/client.go:51">
P2: This client-wide timeout also applies to `w.dynClient`, closing each long-lived PodSnapshotContent informer watch after 30 seconds. Leave it unset and bound individual API calls with request contexts.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread agent/internal/controller/podsnapshotcontent.go
Comment thread agent/internal/controller/remote.go
Comment thread agent/internal/controller/remote_cleanup.go Outdated
if !strings.HasPrefix(cfg.Host, "https://") || cfg.Insecure {
return nil, fmt.Errorf("metadata API requires HTTPS with certificate verification")
}
cfg.Timeout = 30 * time.Second

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This client-wide timeout also applies to w.dynClient, closing each long-lived PodSnapshotContent informer watch after 30 seconds. Leave it unset and bound individual API calls with request contexts.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At agent/pkg/provenance/client.go, line 51:

<comment>This client-wide timeout also applies to `w.dynClient`, closing each long-lived PodSnapshotContent informer watch after 30 seconds. Leave it unset and bound individual API calls with request contexts.</comment>

<file context>
@@ -0,0 +1,116 @@
+	if !strings.HasPrefix(cfg.Host, "https://") || cfg.Insecure {
+		return nil, fmt.Errorf("metadata API requires HTTPS with certificate verification")
+	}
+	cfg.Timeout = 30 * time.Second
+	return cfg, nil
+}
</file context>

Comment thread charts/snapshot/templates/provenance.yaml Outdated
Comment thread operator/internal/controller/podsnapshot_reconciler.go Outdated
Comment thread agent/internal/controller/controller.go
Comment thread docs/operations/liqo-control-plane.md Outdated
Comment thread agent/pkg/provenance/binding.go Outdated
Comment thread agent/internal/types/remote.go Outdated
Capture: the agent now names itself in a remote capture reservation and
remembers which content it handed to the checkpoint. A retry by the same
process may resume a reservation it never executed, so a transient API or
runtime error in the checks after the reservation, or a reservation whose
reply was lost, no longer fails the capture as CaptureOutcomeUnknown. A
reservation from another process, or one already executed, still fails
closed.

Restore: resolve now requires the queued (or CRI) Pod's Snapshot request
annotations to equal the fresh, authoritative ones, so restore-from, the
container map and the compatibility bypass can no longer come from a stale
copy. A runtime that cannot report a container's Pod is retried as pending;
only a runtime naming another Pod stays terminal.

Cleanup: any Pod carrying the restore protection finalizer defers artifact
deletion, whatever its restore-from annotation now says.

Operator: pending content on a node later listed in RemoteAgentNodes gets
its cleanup delegation backfilled instead of staying Pending; terminal
content never changes cleanup owner.

Agent client: the content informer uses a copy of the remote config without
the 30s client timeout, which ended every watch. Binding validation reports
fields in a fixed order.

Chart: the agent reads ShadowPods through a Role in the provider namespace
instead of a cluster-wide rule; the provenance name is truncated to a valid
label value; the webhook rolls when its binding changes. Docs require
restarting the webhook, not only the agent, after credential rotation.

Each behaviour change has a regression test that fails on the previous code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
@rst0git

rst0git commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

Addressed all 11 review findings in 613f6dd, each
with a regression test that fails on the previous code: capture resumes its own unexecuted reservation
after a transient error; restore rejects stale queued Snapshot annotations; a runtime-identity outage
retries; the protection finalizer blocks cleanup; the operator backfills cleanup delegation on pending
content; the informer watch has no client timeout; ShadowPod RBAC is namespaced; the provenance name is
truncated; the webhook rolls on binding changes; docs and P3s updated.

@rst0git
rst0git merged commit de499e4 into main Oct 20, 2026
13 checks passed
@rst0git
rst0git deleted the feat/liqo-control-plane branch October 20, 2026 14:41
@rst0git
rst0git restored the feat/liqo-control-plane branch October 20, 2026 15:26
@rst0git
rst0git deleted the feat/liqo-control-plane branch October 20, 2026 16:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-issue-check Maintainer waiver for the approved-issue requirement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant