Skip to content

RFC: Independent Pipette for Manual Testing #2859

@mattkur

Description

@mattkur

Problem Statement

Pipette is an in-guest test agent used by the petri test framework to
execute commands, transfer files, and control guest lifecycle from the host. It
supports both VTL0 (guest OS) and VTL2 (OpenHCL paravisor) and communicates over
AF_VSOCK on port 0x1337 using a mesh-based RPC protocol.

Today, pipette is only practically usable through petri. Petri handles the full
lifecycle: building a FAT32 disk image with the pipette binary, injecting
cloud-init / IMC bootstrap configuration, wiring up VSOCK listeners in the VMM,
and connecting via PipetteClient. This is excellent for automated CI tests, but
it means manual testing has no access to pipette's capabilities.

Manual test workflows — for example, validating OpenHCL servicing on physical
hardware — currently rely on ad-hoc approaches to interact with guests:
PowerShell remoting, SSH, serial console scripts, or custom one-off tooling.
These approaches are fragile, inconsistent across VTLs, and lack the structured
command execution, file transfer, and diagnostic collection that pipette already
provides.

The gap is particularly acute for VTL2 (OpenHCL) interactions, where there is no
general-purpose remote shell. The ohcldiag tool provides some diagnostic
commands, but it is not a general execution environment. Pipette already solves
this problem — but only within petri.

Goals

  • Enable pipette to be used outside of petri for manual and ad-hoc testing.
  • Provide a simple host-side tool to connect to a running pipette agent and
    execute commands interactively.
  • Support both VTL0 and VTL2 agents.
  • Minimize new code by reusing the existing pipette, pipette_client, and
    pipette_protocol crates, which are already architecturally independent of
    petri.

Non-Goals

  • Replacing petri for automated test scenarios.
  • Building a full interactive shell experience (tab completion, job control,
    etc.) — a basic command interface is sufficient.
  • Modifying the pipette protocol or agent itself (the existing protocol is
    adequate).

Background: Current Architecture

The pipette system is composed of three crates that are already decoupled
from petri:

Crate Role Petri dependency?
pipette Guest-side agent binary None
pipette_client Host-side client library None
pipette_protocol Shared protocol definitions None

PipetteClient::new() accepts any AsyncRead + AsyncWrite byte stream, a
Spawn implementation, and an output directory. No petri types are required.

The coupling is entirely in deployment and lifecycle management that petri
provides:

  1. Disk image creation — petri builds a FAT32 VHD containing the pipette
    binary and guest bootstrap configuration.
  2. Guest bootstrap — cloud-init (Linux) or IMC hive (Windows) auto-starts
    pipette as a service.
  3. VSOCK listener setup — petri wires Unix socket listeners (OpenVMM) or
    AF_HYPERV sockets (Hyper-V) into the VMM configuration.
  4. VTL2 launch — petri uses DiagClient to mount the cidata disk in
    OpenHCL and launch pipette.
  5. Artifact resolution — petri resolves the correct pipette binary for the
    target architecture and OS.

Proposed Solution

Overview

Introduce a standalone host-side CLI (working name: pipette-cli) that
wraps pipette_client and connects to a running pipette agent over Hyper-V
sockets. This tool is aimed at developers doing manual testing against VMs
running on Hyper-V hosts — the primary use case is physical test machines (e.g.,
AH24 hosts) where petri is not in the loop.

The user is responsible for getting pipette running inside the guest. The CLI
only handles the host-side connection and interaction.

High-Level Design

  Developer workstation / test host
  ┌────────────────────────────────────────┐
  │  pipette-cli                           │
  │    • connects via AF_HYPERV socket     │
  │    • wraps PipetteClient               │
  │    • subcommands: exec, read, write,   │
  │      ping, shutdown                    │
  └──────────────┬─────────────────────────┘
                 │ AF_HYPERV / VSOCK
                 │ port 0x1337
  ┌──────────────▼─────────────────────────┐
  │  VM                                    │
  │  ┌──────────────────────────────────┐  │
  │  │ VTL2 (OpenHCL)                   │  │
  │  │   pipette (manually started or   │  │
  │  │   deployed via ohcldiag/script)  │  │
  │  ├──────────────────────────────────┤  │
  │  │ VTL0 (Guest OS)                  │  │
  │  │   pipette (started via script,   │  │
  │  │   service, or cloud-init)        │  │
  │  └──────────────────────────────────┘  │
  └────────────────────────────────────────┘

CLI Interface (Sketch)

pipette-cli --vm <vm-name-or-id> [--vtl2] <subcommand>

Subcommands:
  exec <command> [args...]   Run a command in the guest, streaming stdout/stderr
  read <guest-path>          Read a file from the guest to stdout
  write <guest-path>         Write stdin to a file in the guest
  ping                       Check connectivity to the pipette agent
  shutdown [--reboot]        Shut down or reboot the guest
  wait                       Wait for the pipette agent to become available

Connection targeting:

  • --vm identifies the VM by name or GUID (used to construct the AF_HYPERV
    address).
  • --vtl2 targets the VTL2 pipette agent instead of VTL0.

Guest-Side Deployment

The CLI does not automate deployment of the pipette binary into the guest.
Instead, we provide documentation and helper scripts for common scenarios:

Scenario Deployment method
VTL0 Linux scp or cloud-init; run pipette manually or as a systemd service
VTL0 Windows Copy pipette.exe; run manually or register as a service with pipette --service
VTL2 (OpenHCL) Use ohcldiag to push the binary and launch it, or include it in the OpenHCL image

For VTL2, the recommended approach mirrors what petri does today: mount a disk
containing the pipette binary and execute it. A helper script wrapping ohcldiag
commands could streamline this.

Milestones

Milestone 1: pipette-cli with Hyper-V Socket Connectivity

Deliverables:

  1. New crate: pipette-cli — A binary crate (likely in
    oss/petri/pipette_cli/) that depends on pipette_client and vmsocket.
    Implements the subcommands described above.

  2. AF_HYPERV connection logic — Connect to a VM's pipette agent using
    VmSocket with VmAddress::hyperv_vsock(vm_id, PIPETTE_VSOCK_PORT). Support
    --vtl2 via set_high_vtl.

  3. Deployment documentation — A guide page describing how to get pipette
    running in common guest configurations (VTL0 Linux, VTL0 Windows, VTL2
    OpenHCL).

  4. Helper scripts — Lightweight PowerShell or shell scripts for deploying
    pipette into a guest, especially the VTL2 ohcldiag-based flow.

Success criteria: A developer can build pipette-cli, manually deploy
pipette into a VM running on a Hyper-V host, and use pipette-cli exec to run a
command in VTL0 or VTL2 and see the output.

Open Questions

  1. Naming: Is pipette-cli the right name, or should it be something like
    pipette-host or pipette-manual?

  2. Scope of deployment automation: Should Milestone 1 include any
    deployment automation (e.g., a deploy subcommand that pushes the binary
    via ohcldiag), or is documentation + scripts sufficient?

  3. OpenVMM support: The initial milestone targets Hyper-V hosts, since
    that's where manual testing on physical hardware happens. Should OpenVMM
    (Unix socket VSOCK) be included in Milestone 1 or deferred?

  4. Integration with existing scripts: Scripts like
    Test-AH24NvmeServicing.ps1 could benefit from pipette. Should we provide
    a PowerShell wrapper module, or is the CLI sufficient?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions