Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: cross-container named pipes #2358

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/hcsoci/hcsdoc_wcow.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func createMountsConfig(ctx context.Context, coi *createOptionsInternal) (*mount
}
mdv2.HostPath = src
} else if mount.Type == MountTypeVirtualDisk || mount.Type == MountTypePhysicalDisk || mount.Type == MountTypeExtensibleVirtualDisk {
// For v2 schema containers, any disk mounts will be part of coi.additionalMounts.
// For v2 schema containers, any disk mounts will be part of coi.windowsAdditionalMounts.
// For v1 schema containers, we don't even get here, since there is no HostingSystem.
continue
} else if strings.HasPrefix(mount.Source, guestpath.SandboxMountPrefix) {
Expand Down
9 changes: 8 additions & 1 deletion internal/hcsoci/resources_wcow.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,16 @@ func setupMounts(ctx context.Context, coi *createOptionsInternal, r *resources.R
} else if strings.HasPrefix(mount.Source, guestpath.SandboxMountPrefix) {
// Mounts that map to a path in the UVM are specified with a 'sandbox://' prefix.
//
// Example: sandbox:///a/dirInUvm destination:C:\\dirInContainer.
// Example:
// - sandbox:///a/dirInUvm destination:C:\\dirInContainer.
// - sandbox://\\.\pipe\uvmNamedPipe destination: \\.\pipe\containerNamedPipe
//
// so first convert to a path in the sandboxmounts path itself.
if uvm.IsPipe(mount.Source) {
// When mapping UVM named pipe into container, we don't need to do anything else, since it'll be
// handled via `createMountsConfig`.
continue
}
sandboxPath := convertToWCOWSandboxMountPath(mount.Source)

// Now we need to exec a process in the vm that will make these directories as theres
Expand Down
27 changes: 24 additions & 3 deletions internal/uvm/pipes.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import (
"fmt"
"strings"

"github.com/Microsoft/hcsshim/internal/guestpath"
"github.com/Microsoft/hcsshim/internal/hcs/resourcepaths"
hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2"
"github.com/Microsoft/hcsshim/internal/protocol/guestrequest"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-spec/specs-go"
)

const pipePrefix = `\\.\pipe\`
Expand Down Expand Up @@ -54,18 +55,38 @@ func (uvm *UtilityVM) RemovePipe(ctx context.Context, hostPath string) error {
return nil
}

// IsPipe returns true if the given path references a named pipe.
// SandboxNamedPipe returns a named pipe in UVM, which will be shared across containers.
func (uvm *UtilityVM) SandboxNamedPipe(hostPath string) string {
podID := strings.TrimPrefix(uvm.id, "@vm")
if uvm.operatingSystem == "windows" {
uvmPipeName := strings.TrimPrefix(hostPath, pipePrefix)
return fmt.Sprintf(`%s%s\%s`, pipePrefix, podID, uvmPipeName)
}
return fmt.Sprintf("%s-%s", podID, hostPath)
}

// IsPipe returns true if the given path references a named pipe. The pipe can be:
// - host named pipe shared via VSMB
// - UVM named pipe
func IsPipe(hostPath string) bool {
if sandboxMount, ok := strings.CutPrefix(hostPath, guestpath.SandboxMountPrefix); ok {
return strings.HasPrefix(sandboxMount, pipePrefix)
}
return strings.HasPrefix(hostPath, pipePrefix)
}

// GetContainerPipeMapping returns the source and destination to use for a given
// pipe mount in a container.
// The pipe mount can be either a host pipe shared via VSMB or a UVM pipe.
func GetContainerPipeMapping(uvm *UtilityVM, mount specs.Mount) (src string, dst string) {
if uvm == nil {
src = mount.Source
} else {
src = vsmbSharePrefix + `IPC$\` + strings.TrimPrefix(mount.Source, pipePrefix)
if uvmPipe, ok := strings.CutPrefix(mount.Source, guestpath.SandboxMountPrefix); ok {
src = uvm.SandboxNamedPipe(uvmPipe)
} else {
src = vsmbSharePrefix + `IPC$\` + strings.TrimPrefix(mount.Source, pipePrefix)
}
}
dst = strings.TrimPrefix(mount.Destination, pipePrefix)
return src, dst
Expand Down
Loading