Skip to content

infra: netlaunch: Add new grpc modes#530

Open
frhuelsz wants to merge 12 commits intomainfrom
user/frhuelsz/netlaunch-grpc-modes
Open

infra: netlaunch: Add new grpc modes#530
frhuelsz wants to merge 12 commits intomainfrom
user/frhuelsz/netlaunch-grpc-modes

Conversation

@frhuelsz
Copy link
Copy Markdown
Contributor

🔍 Description

Expand netlaunch's capabilities to support using gRPC for: install, image stream, and starting a local proxy for other tools to talk to trident in the VM.

Copilot AI review requested due to automatic review settings February 23, 2026 22:55
@frhuelsz frhuelsz requested a review from a team as a code owner February 23, 2026 22:55
@frhuelsz
Copy link
Copy Markdown
Contributor Author

/AzurePipelines run [GITHUB]-trident-pr-e2e

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR expands netlaunch's capabilities to support three new gRPC modes for communicating with Trident: install (direct gRPC installation), stream (direct gRPC image streaming), and local-proxy (opens a local Unix socket proxy for other tools to communicate with Trident). The changes refactor the RCP configuration from a boolean flag to an enumerated GrpcMode type and restructure the connection handling logic.

Changes:

  • Converted GrpcMode from boolean to enumerated string type with four modes: disabled, local-proxy, install, and stream
  • Added new doGrpcStream function and moved doGrpcInstall to a separate grpc.go file
  • Implemented local proxy functionality that forwards connections between a Unix socket and the RCP connection
  • Modified RCP client listener to support accepting multiple sequential connections instead of just one
  • Updated Makefile with new targets for testing the different gRPC modes

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
tools/pkg/netlaunch/config.go Converts GrpcMode from bool to enum type with four modes and adds LocalProxySocket configuration
tools/pkg/netlaunch/netlaunch.go Restructures main logic to handle different gRPC modes, moves ISO patching logic, and adds mode-specific handling
tools/pkg/netlaunch/grpc.go Creates new file with gRPC-specific functions (doGrpcInstall and doGrpcStream)
tools/pkg/netlaunch/localproxy.go Implements new local proxy mode that creates a Unix socket and forwards connections to Trident
tools/pkg/netlaunch/stream_image.go Refactors image URL/hash extraction into a separate helper function for reuse
tools/pkg/rcp/client/listen.go Changes listener to accept multiple sequential connections instead of single connection
tools/pkg/tridentgrpc/grpc.go Adds InstallServiceClient to TridentClient struct
tools/storm/helpers/direct_streaming.go Updates to use new GrpcMode enum instead of bool
tools/cmd/netlaunch/main.go Updates CLI to support new gRPC modes with appropriate flag mappings
Makefile Adds run-netlaunch-stream and run-netlaunch-proxy targets

Comment thread tools/pkg/netlaunch/stream_image.go Outdated
Comment thread Makefile Outdated
Comment thread tools/pkg/rcp/client/listen.go
Comment thread tools/pkg/netlaunch/netlaunch.go
Comment thread tools/pkg/netlaunch/netlaunch.go
Comment thread tools/pkg/netlaunch/config.go Outdated
Comment thread tools/pkg/netlaunch/stream_image.go Outdated
Comment thread tools/pkg/netlaunch/netlaunch.go Outdated
Comment thread tools/pkg/netlaunch/netlaunch.go Outdated
Comment thread tools/pkg/rcp/client/listen.go
Copilot AI review requested due to automatic review settings February 24, 2026 22:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

tools/pkg/netlaunch/netlaunch.go:162

  • Issue: finalHostConfigurationYaml is only set inside the block that patches /etc/trident/config.yaml. When UseStreamImage is true and gRPC mode is enabled, that block is skipped, leaving finalHostConfigurationYaml empty. In GrpcModeInstall this empty config will be sent to Trident.

Evidence: The YAML marshal that assigns finalHostConfigurationYaml is guarded by if config.Rcp == nil || !config.Rcp.UseStreamImage || !config.IsGrpcModeEnabled(), but doGrpcInstall(..., finalHostConfigurationYaml) is still used later for GrpcModeInstall.

Suggestion: Ensure finalHostConfigurationYaml is always populated when GrpcModeInstall is selected (even if you don't patch the ISO), or reject incompatible flag combinations (e.g., --stream-image with grpc-install).

		// Patch the ISO Host Configuration file unless this is a stream-image
		// test, where the Host Configuration file is not expected to be
		// present, or we are using gRPC mode, where the HC file is irrelevant.
		if config.Rcp == nil || !config.Rcp.UseStreamImage || !config.IsGrpcModeEnabled() {
			tridentConfig, err := yaml.Marshal(hostConfigData)
			if err != nil {
				return fmt.Errorf("failed to marshal Trident config: %w", err)
			}

			// Store the modified trident config for later use
			finalHostConfigurationYaml = string(tridentConfig)

Comment thread tools/pkg/netlaunch/localproxy.go
Comment thread tools/pkg/rcp/proxy/proxy.go
Comment thread tools/pkg/rcp/client/listen.go
Comment thread tools/cmd/rcp-agent/main.go
Comment thread tools/pkg/netlaunch/stream_image.go Outdated
@frhuelsz frhuelsz marked this pull request as draft February 25, 2026 22:25
@frhuelsz frhuelsz marked this pull request as ready for review March 2, 2026 03:52
Copilot AI review requested due to automatic review settings March 2, 2026 03:52
@frhuelsz
Copy link
Copy Markdown
Contributor Author

frhuelsz commented Mar 2, 2026

/AzurePipelines run [GITHUB]-trident-pr-e2e

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

tools/pkg/netlaunch/netlaunch.go:181

  • finalHostConfigurationYaml is only set when the host config is patched into the ISO. In gRPC install mode, that patching is explicitly skipped, so doGrpcInstall() is called with an empty config string, which will likely make installs fail. Marshal hostConfigData into finalHostConfigurationYaml regardless of whether you inject it into the ISO (and only gate the ISO patching itself).
		// Patch the ISO Host Configuration file when it will be needed by
		// Trident, which is when: 
		// 
		// - We are NOT using RCP (config.Rcp == nil), OR 
		// - We are using RCP, but we are NOT:
		//   - Using Stream Disk, NOR
		//   - Using gRPC mode.
		//
		// Stream disk and gRPC modes do NOT need an in-ISO Host Configuration
		// file, so we skip injecting it in those cases.
		if config.Rcp == nil || !(config.Rcp.ReplaceInstallWithStreamDisk || config.IsGrpcModeEnabled()) {
			tridentConfig, err := yaml.Marshal(hostConfigData)
			if err != nil {
				return fmt.Errorf("failed to marshal Trident config: %w", err)
			}

			// Store the modified trident config for later use
			finalHostConfigurationYaml = string(tridentConfig)

Comment on lines 213 to 214
// We injected the phonehome & logstream config, so we're expecting Trident to reach back
enable_phonehome_listening = true
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

enable_phonehome_listening is set to true whenever a host config file is provided, but in gRPC modes the code intentionally does not inject phonehome/logstream settings into the host config. This makes netlaunch set up phonehome/logstream/tracestream handlers (and associated files) even though Trident won't call them, and also changes the termination behavior after serving the ISO. Consider gating this assignment on actually injecting phonehome/logstream config, or splitting the concept into separate flags (e.g., keep HTTP server running vs. listen for phonehome).

Suggested change
// We injected the phonehome & logstream config, so we're expecting Trident to reach back
enable_phonehome_listening = true
// We injected the phonehome & logstream config, so we're expecting Trident to reach back.
// In gRPC modes, we intentionally do not inject phonehome/logstream settings into the host
// config, so only enable phonehome listening when not running in gRPC mode.
if config.TridentGrpc == nil {
enable_phonehome_listening = true
}

Copilot uses AI. Check for mistakes.
}

// forwardConnections copies data bidirectionally between two connections.
// It blocks until both directions are finished (i.e. one side closes or errors).
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

The comment on forwardConnections says it "blocks until both directions are finished", but the implementation returns after the first copy completes (it waits for a single message from doneChan). Please update the comment to match the actual behavior (or wait for both directions if that was the intent).

Suggested change
// It blocks until both directions are finished (i.e. one side closes or errors).
// It blocks until one direction is finished (i.e. one side closes or errors) or the context is cancelled.

Copilot uses AI. Check for mistakes.
Comment thread tools/pkg/netlaunch/grpc.go
Comment thread tools/pkg/netlaunch/localproxy.go Outdated
Copilot AI review requested due to automatic review settings March 6, 2026 00:57
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.

Comment on lines +94 to +100
// forwardConnections copies data bidirectionally between two connections.
// It blocks until both directions are finished (i.e. one side closes or errors).
func forwardConnections(ctx context.Context, local, remote net.Conn) {
defer local.Close()

local.SetReadDeadline(time.Time{})
remote.SetReadDeadline(time.Time{})
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

forwardConnections' docstring says it blocks until both directions are finished, but the implementation waits for only one doneChan message (or context cancel) and then returns. Either update the comment to match the behavior, or wait for both copy goroutines to finish (e.g., read twice from doneChan) to match the stated contract.

Copilot uses AI. Check for mistakes.
listener, err := net.Listen("unix", socketPath)
if err != nil {
return fmt.Errorf("failed to listen on unix socket %s: %w", socketPath, err)
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The local proxy listens on a predictable socket path (default under /tmp) but does not set restrictive permissions on the created Unix socket. On multi-user systems this can allow other local users to connect and issue gRPC calls through to Trident in the VM. Consider creating the socket in a private runtime dir (e.g., under $XDG_RUNTIME_DIR) and/or explicitly chmod'ing the socket to 0600 after net.Listen.

Suggested change
}
}
// Restrict permissions on the Unix socket so that only the owner can access it.
if err := os.Chmod(socketPath, 0o600); err != nil {
listener.Close()
_ = os.Remove(socketPath)
return fmt.Errorf("failed to set permissions on unix socket %s: %w", socketPath, err)
}

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +12
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.4
// source: bmiprepagent.proto

package bpapb

import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

These newly added generated protobuf files for bpatest don't appear to be referenced anywhere else in tools/cmd/bpatest or the wider tools/ code. If they're not required for the netlaunch gRPC modes work, consider removing them from this PR to keep the change focused (or add the missing code that uses them if they are required).

Copilot uses AI. Check for mistakes.
if config.Rcp.GetGrpcMode() == GrpcModeInstall {
installCtx, installCancel := context.WithTimeout(ctx, time.Minute*10)
defer installCancel()

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

doGrpcInstall() is invoked with finalHostConfigurationYaml, but that variable is only set inside the block that patches the host config into the ISO. In gRPC install mode you intentionally skip ISO injection, so finalHostConfigurationYaml remains empty and the install request will be sent with an empty host configuration.

Suggested change
// In gRPC install mode we may skip ISO injection, so ensure the
// host configuration YAML is still populated from hostConfigData.
if finalHostConfigurationYaml == "" && hostConfigData != nil {
marshaledHostConfig, marshalErr := yaml.Marshal(hostConfigData)
if marshalErr != nil {
return fmt.Errorf("failed to marshal host configuration for gRPC install: %w", marshalErr)
}
finalHostConfigurationYaml = string(marshaledHostConfig)
}

Copilot uses AI. Check for mistakes.
Comment on lines 184 to 185
rootCmd.PersistentFlags().StringVarP(&rcpMode, "rcp-agent-mode", "", "", "RCP agent mode to use (grpc|cli). If not specified, the rcp-agent is not used.")
rootCmd.PersistentFlags().StringVarP(&tridentBinaryPath, "trident-binary", "", "", "Optional path to Trident binary to be copied into the VM, requires RCP mode.")
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The --rcp-agent-mode flag help text still says "(grpc|cli)", but the CLI now accepts multiple gRPC modes (grpc-local-proxy / grpc-install / grpc-stream). Update the help string to list the supported values so users discover the new modes via --help.

Copilot uses AI. Check for mistakes.
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.

2 participants