Skip to content

[LXC] (4/5) Turn on in-process streaming - #1333

Merged
Soham Das (SohamDas2021) merged 5 commits into
mainfrom
sohamdas2021-1291-pr4
Oct 2, 2026
Merged

Soham Das (SohamDas2021) merged 5 commits into
mainfrom
sohamdas2021-1291-pr4

Conversation

@SohamDas2021

@SohamDas2021 Soham Das (SohamDas2021) commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #1329 (3/5). Review only the top commit; the rest is that PR.

PRs 1–3 built the LXC streaming handle and made it safe to hold more than one at a time. Nothing reaches it yet: ContainmentBackend::Lxc still falls to the engine's catch-all, so spawn_sandbox, run, and every SDK built on mxc_spawn_request answer UnsupportedContainment. This PR routes it.

Two production changes:

  • dispatch.rs gains the spawn_lxc arm, modelled on spawn_bubblewrap, with the matching off-Linux rejection.
  • platform.rs reports lxc on Linux. It hard-coded an exclusion, so a host with LXC but no usable bwrap reported isSupported: false — discovery would have kept sending callers away from a backend that now works. The Linux branch now mirrors the TypeScript SDK's getPlatformSupport: order [lxc, bubblewrap], either one alone makes the host supported.

Everything else is the coverage that turning it on requires: a live streaming suite (mxc-sdk/tests/streaming_lxc.rs), a container-free FFI routing pin, .NET and Node cases, and the CI steps that run them. lxc-exec goes through mxc_engine::run and never reaches spawn_sandbox, so no shell script can cover this path — the tests have to be Rust.

Availability is not privilege: lxc in availableMethods means the tooling is present, not that the caller may use it. LXC needs root for a system container. That is documented on the field rather than gated in the probe, because resolve_default_lxcpath supports unprivileged LXC and a euid check would hide hosts where it works.

Validation

cargo fmt --all --check, clippy --all-targets -D warnings, and the unit tests pass on Windows and cross-compiled to x86_64-unknown-linux-gnu. Every #[cfg(target_os = "linux")] body is invisible to a Windows-only lane, so the cross-compile is the part that type-checks the new code.

The live LXC cases need Linux, LXC, and root, so they have not run locally. lxc-e2e.yml runs them under MXC_LXC_TESTS_REQUIRE_EXECUTION=1, which turns a skipped prerequisite into a failure rather than a green job that tested nothing. The kill case asserts the container is no longer running after kill() — a container cannot be stopped while it holds a live process, so that is what proves the kill reached the workload and the descendant it backgrounded, rather than stopping at the host lxc-attach.

Refs #1291.

Microsoft Reviewers: Open in CodeFlow

@SohamDas2021
Soham Das (SohamDas2021) requested a review from a team as a code owner September 29, 2026 23:18
@SohamDas2021
Soham Das (SohamDas2021) added this pull request to stack #1327 September 29, 2026 23:22
Copilot AI balanced review requested due to automatic review settings September 29, 2026 23:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Public documentation incorrectly presents root as mandatory despite supported unprivileged no-network LXC operation.

Review effort: Balanced
Findings: 4 Low severity

Open (4)
What changed in this PR

Routes LXC through in-process streaming APIs, advertises it in Linux discovery, and adds cross-SDK validation.

Changes:

  • Adds Linux LXC streaming dispatch and platform discovery.
  • Adds Rust, FFI, Node, and .NET coverage.
  • Extends CI and documentation for the new path.
File Description
src/​ffi/​mxc_ffi/​tests/​ffi.rs Tests FFI routing into LXC.
src/​core/​mxc-sdk/​tests/​streaming_lxc.rs Adds live LXC streaming tests.
src/​core/​mxc-sdk/​tests/​sdk_helpers.rs Updates Linux discovery assertions.
src/​core/​mxc-sdk/​src/​lib.rs Documents LXC SDK support.
src/​core/​mxc-sdk/​README.md Documents LXC streaming behavior.
src/​core/​mxc-sdk/​Cargo.toml Adds Linux test dependencies.
src/​core/​mxc_engine/​src/​platform.rs Reports LXC in platform support.
src/​core/​mxc_engine/​src/​dispatch.rs Adds LXC spawn dispatch.
src/​Cargo.lock Records dependency changes.
sdk/​node/​tests/​integration/​native-streaming.test.ts Adds native Node LXC coverage.
sdk/​dotnet/​README.md Documents managed LXC support.
sdk/​dotnet/​Microsoft.Mxc.Sdk.Tests/​MxcSandboxLxcE2ETests.cs Adds .NET LXC end-to-end tests.
sdk/​dotnet/​Microsoft.Mxc.Sdk.Tests/​LxcHost.cs Adds shared LXC host gating.
docs/​pull-requests.md Documents LXC PR validation.
docs/​lxc-support/​lxc-backend.md Documents streaming semantics.
docs/​ci-validation-infrastructure.md Updates LXC validation coverage.
.github/​workflows/​SDK.Integration.Test.Job.yml Requires Node LXC execution.
.github/​workflows/​SDK.Dotnet.Test.Job.yml Installs and tests LXC for .NET.
.github/​workflows/​lxc-e2e.yml Runs live Rust streaming tests.
.github/​workflows/​Build.Linux.Job.yml Pins dispatch and discovery tests.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/lxc-support/lxc-backend.md Outdated
Comment thread sdk/dotnet/README.md Outdated
Comment on lines +547 to +551
`Containment::Lxc` names the LXC backend, served by `run` and `spawn_sandbox`
with piped stdio. `Containment::Process` resolves to Bubblewrap on Linux, so
LXC is reachable only by naming it. It needs root. Its stdio is pipes rather
than a pty, so the workload sees no TTY — unlike the `lxc-exec` binary, which
allocates one. `kill()` stops the whole container, which is the only way to
Comment on lines +54 to +56
//! LXC is reachable only by naming it: [`Containment::Process`] resolves to
//! Bubblewrap on Linux. It needs root, and it streams over pipes, so the
//! workload sees no TTY — unlike the `lxc-exec` binary, which allocates a pty.
Copilot AI balanced review requested due to automatic review settings September 30, 2026 02:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The new documentation contains a nonfunctional LXC example and incorrectly describes root as universally required.

Review effort: Balanced
Findings: 4 Low severity

Open (4)
Previously missed (2)

In code that hasn't changed since last review

Low severity Fix rejected legacy LXC network example

docs/​lxc-support/​lxc-backend.md:224

This example is rejected before launch: its legacy allowOutbound: false shape is normalized with defaultPolicy and the default enforcementMode: 'capabilities', while LXC explicitly rejects capabilities enforcement. Use the directional 0.8 shape shown by the new live tests so the documented LXC sample actually runs.

Low severity Fix invalid LXC network example

src/​core/​mxc-sdk/​README.md:165

The example immediately above cannot actually be passed to run or spawn_sandbox: network: None is emitted in the legacy form with a default network posture, which LXC interprets as capabilities enforcement and rejects. Please make the example use explicit directional deny egress/ingress (as streaming_lxc.rs does), or avoid claiming that this exact request runs.

Comment thread .github/workflows/Build.Linux.Job.yml
Comment thread .github/workflows/lxc-e2e.yml Outdated
Comment thread docs/lxc-support/lxc-backend.md Outdated
Comment thread sdk/dotnet/Microsoft.Mxc.Sdk.Tests/MxcSandboxLxcE2ETests.cs
Comment thread src/backends/lxc/common/src/lxc_bindings.rs
Comment thread src/backends/lxc/common/src/lxc_bindings.rs
Comment thread src/backends/lxc/common/src/lxc_bindings.rs
Comment thread src/backends/lxc/common/src/lxc_runner.rs Outdated
Copilot AI balanced review requested due to automatic review settings October 1, 2026 20:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Several updated public documents incorrectly describe root as mandatory despite supported unprivileged no-network LXC execution.

Review effort: Balanced
Findings: 4 Low severity

Open (4)

Comment thread src/ffi/mxc_ffi/tests/ffi.rs Outdated
Base automatically changed from sohamdas2021-1291-pr3 to main October 1, 2026 20:51
Copilot AI balanced review requested due to automatic review settings October 1, 2026 22:08
… discovery

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…rm LXC accepts

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…egration lane

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Node cleanup can skip disposal after a kill failure, and several public docs incorrectly exclude supported unprivileged LXC.

Review effort: Balanced
Findings: 4 Low severity

Open (4)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Guarantee container disposal when native termination fails

sdk/​node/​tests/​integration/​native-streaming.test.ts:304

kill() can throw when native termination fails, which skips dispose() and defeats this finally block's root-container cleanup. Guarantee disposal with a nested finally (or call dispose() directly, since it already kills active processes).

Copilot AI balanced review requested due to automatic review settings October 1, 2026 22:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The Node LXC test passes a forbidden policy version and fails before spawning, while several documentation claims contradict supported unprivileged and preserved-container behavior.

Review effort: Balanced
Findings: 1 High severity · 7 Low severity

Open (8)

Comment thread sdk/node/tests/integration/native-streaming.test.ts
Comment on lines 211 to 213
const policy: SandboxPolicy = {
version: '0.8.0-alpha',
filesystem: {
Comment thread docs/lxc-support/lxc-backend.md Outdated
Comment on lines +266 to +271
**Teardown is owed on every terminal path.** Completing, timing out, and being
dropped without a `wait` all remove the `/etc/hosts` proxy pin, the egress and
ingress chains, and the container itself. A teardown step that fails after a
`wait` is reported through `Sandbox::warnings`; after a bare drop there is no
handle left to report through, so a caller that wants to see those failures has
to wait.
Comment on lines +143 to +145
This runs through `run` and `spawn_sandbox` like any other backend. LXC needs
root, and it streams over pipes, so the workload sees no TTY — unlike the
`lxc-exec` binary, which allocates a pty.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 948c2709-7922-4c67-8b1c-1d589d6edd03
Copilot AI balanced review requested due to automatic review settings October 1, 2026 22:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread sdk/node/tests/integration/native-streaming.test.ts
Comment thread .github/workflows/Build.Linux.Job.yml Outdated
Comment thread docs/pull-requests.md Outdated
Comment thread docs/lxc-support/lxc-backend.md
Comment thread sdk/dotnet/README.md Outdated
Comment on lines +74 to +84
nativeStreamingSkipReason ??
(os.platform() !== 'linux' ? 'LXC streaming is available on Linux only' : undefined) ??
(!isLinuxRoot
? 'LXC creates, starts, and attaches to a system container, which needs root (sudo npm test)'
: undefined) ??
(!platformSupport.availableMethods.includes('lxc')
? 'LXC is not installed on this host'
: undefined) ??
(process.env.MXC_SKIP_LXC_TESTS === '1'
? 'Skipped: LXC tests disabled (MXC_SKIP_LXC_TESTS)'
: undefined);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

note: this one is getting slightly harder to read

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not doing it in this PR.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 948c2709-7922-4c67-8b1c-1d589d6edd03
Copilot AI balanced review requested due to automatic review settings October 2, 2026 00:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Public documentation overstates LXC probe guarantees, incorrectly makes root unconditional, and leaves the discovery design document stale.

Review effort: Balanced
Findings: 5 Low severity

Open (5)
Resolved since last review (2)
Previously missed (1)

In code that hasn't changed since last review

Low severity Document LXC availability as a probe, not launch usability

src/​core/​mxc_engine/​src/​platform.rs:48

This overstates the LXC probe: is_lxc_available() only checks that lxc-ls --version exits successfully, so it does not establish that the rest of the runtime tooling is installed or that a container can be launched. Document the field as probe availability rather than usability; otherwise callers may treat availableMethods as a launch preflight even though docs/backend-support-probe-api-plan.md:100 explicitly says it can report LXC on a host where a real run fails.

This issue also appears on line 127 of the same file.

@SohamDas2021
Soham Das (SohamDas2021) merged commit ac1a872 into main Oct 2, 2026
31 checks passed
@SohamDas2021
Soham Das (SohamDas2021) deleted the sohamdas2021-1291-pr4 branch October 2, 2026 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants