diff --git a/internal/controller/vm/doc.go b/internal/controller/vm/doc.go index 304e117157..389b705e04 100644 --- a/internal/controller/vm/doc.go +++ b/internal/controller/vm/doc.go @@ -4,8 +4,8 @@ // // A Utility VM is a lightweight virtual machine used to host Linux (LCOW) or // Windows (WCOW) containers. This package abstracts the VM lifecycle — -// creation, startup, stats collection, and termination — behind the [Controller] -// interface, with [Manager] as the primary implementation. +// creation, startup, stats collection, and termination — with the [Controller] +// as the primary implementation. // // # Lifecycle // @@ -33,7 +33,7 @@ // // State descriptions: // -// - [StateNotCreated]: initial state after [NewController] is called. +// - [StateNotCreated]: initial state after [New] is called. // - [StateCreated]: after [Controller.CreateVM] succeeds; the VM exists but has not started. // - [StateRunning]: after [Controller.StartVM] succeeds; the guest OS is up and the // Guest Compute Service (GCS) connection is established. @@ -51,7 +51,7 @@ // // # Usage // -// ctrl := vm.NewController() +// ctrl := vm.New() // // if err := ctrl.CreateVM(ctx, &vm.CreateOptions{ // ID: "my-uvm", diff --git a/internal/controller/vm/interface.go b/internal/controller/vm/interface.go deleted file mode 100644 index 3629e21e33..0000000000 --- a/internal/controller/vm/interface.go +++ /dev/null @@ -1,88 +0,0 @@ -//go:build windows - -package vm - -import ( - "context" - "time" - - "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/stats" - hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" - "github.com/Microsoft/hcsshim/internal/protocol/guestresource" - "github.com/Microsoft/hcsshim/internal/shimdiag" - "github.com/Microsoft/hcsshim/internal/vm/guestmanager" - - "github.com/Microsoft/go-winio/pkg/guid" -) - -type Controller interface { - // Guest returns the guest manager instance for this VM. - Guest() *guestmanager.Guest - - // State returns the current VM state. - State() State - - // CreateVM creates and initializes a new VM with the specified options. - // This prepares the VM but does not start it. - CreateVM(ctx context.Context, opts *CreateOptions) error - - // StartVM starts the created VM with the specified options. - // This establishes the guest connection, sets up necessary listeners for - // guest-host communication, and transitions the VM to StateRunning. - StartVM(context.Context, *StartOptions) error - - // ExecIntoHost executes a command in the running UVM. - ExecIntoHost(ctx context.Context, request *shimdiag.ExecProcessRequest) (int, error) - - // DumpStacks dumps the GCS stacks associated with the VM. - DumpStacks(ctx context.Context) (string, error) - - // Wait blocks until the VM exits or the context is cancelled. - // It also waits for log output processing to complete. - Wait(ctx context.Context) error - - Stats(ctx context.Context) (*stats.VirtualMachineStatistics, error) - - TerminateVM(context.Context) error - - // StartTime returns the timestamp when the VM was started. - // Returns zero value of time.time, if the VM is not in StateRunning or StateTerminated. - StartTime() time.Time - - // ExitStatus returns information about the stopped VM, including when it - // stopped and any exit error. Returns an error if the VM is not in StateTerminated. - ExitStatus() (*ExitStatus, error) -} - -// CreateOptions contains the configuration needed to create a new VM. -type CreateOptions struct { - // ID specifies the unique identifier for the VM. - ID string - - // HCSDocument specifies the HCS schema document used to create the VM. - HCSDocument *hcsschema.ComputeSystem -} - -// StartOptions contains the configuration needed to start a VM and establish -// the Guest Compute Service (GCS) connection. -type StartOptions struct { - // GCSServiceID specifies the GUID for the GCS vsock service. - GCSServiceID guid.GUID - - // ConfigOptions specifies additional configuration options for the guest config. - ConfigOptions []guestmanager.ConfigOption - - // ConfidentialOptions specifies security policy and confidential computing - // options for the VM. This is optional and only used for confidential VMs. - ConfidentialOptions *guestresource.ConfidentialOptions -} - -// ExitStatus contains information about a stopped VM's final state. -type ExitStatus struct { - // StoppedTime is the timestamp when the VM stopped. - StoppedTime time.Time - - // Err is the error that caused the VM to stop, if any. - // This will be nil if the VM exited cleanly. - Err error -} diff --git a/internal/controller/vm/state.go b/internal/controller/vm/state.go index 6e98eb4ae1..f9aedddc47 100644 --- a/internal/controller/vm/state.go +++ b/internal/controller/vm/state.go @@ -29,7 +29,7 @@ type State int32 const ( // StateNotCreated indicates the VM has not been created yet. - // This is the initial state when a Controller is first instantiated via [NewController]. + // This is the initial state when a Controller is first instantiated via [New]. // Valid transitions: StateNotCreated → StateCreated (via [Controller.CreateVM]) StateNotCreated State = iota diff --git a/internal/controller/vm/types.go b/internal/controller/vm/types.go new file mode 100644 index 0000000000..383afffe9c --- /dev/null +++ b/internal/controller/vm/types.go @@ -0,0 +1,52 @@ +//go:build windows + +package vm + +import ( + "time" + + hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" + "github.com/Microsoft/hcsshim/internal/protocol/guestresource" + "github.com/Microsoft/hcsshim/internal/vm/guestmanager" + + "github.com/Microsoft/go-winio/pkg/guid" +) + +// CreateOptions contains the configuration needed to create a new VM. +type CreateOptions struct { + // ID specifies the unique identifier for the VM. + ID string + + // HCSDocument specifies the HCS schema document used to create the VM. + HCSDocument *hcsschema.ComputeSystem + + // NoWritableFileShares disallows writable file shares to the UVM. + NoWritableFileShares bool + + // FullyPhysicallyBacked indicates all memory allocations are backed by physical memory. + FullyPhysicallyBacked bool +} + +// StartOptions contains the configuration needed to start a VM and establish +// the Guest Compute Service (GCS) connection. +type StartOptions struct { + // GCSServiceID specifies the GUID for the GCS vsock service. + GCSServiceID guid.GUID + + // ConfigOptions specifies additional configuration options for the guest config. + ConfigOptions []guestmanager.ConfigOption + + // ConfidentialOptions specifies security policy and confidential computing + // options for the VM. This is optional and only used for confidential VMs. + ConfidentialOptions *guestresource.ConfidentialOptions +} + +// ExitStatus contains information about a stopped VM's final state. +type ExitStatus struct { + // StoppedTime is the timestamp when the VM stopped. + StoppedTime time.Time + + // Err is the error that caused the VM to stop, if any. + // This will be nil if the VM exited cleanly. + Err error +} diff --git a/internal/controller/vm/vm.go b/internal/controller/vm/vm.go index e4c8c42736..fb7abffb3e 100644 --- a/internal/controller/vm/vm.go +++ b/internal/controller/vm/vm.go @@ -12,26 +12,32 @@ import ( "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/stats" "github.com/Microsoft/hcsshim/internal/cmd" + "github.com/Microsoft/hcsshim/internal/controller/device/plan9" + "github.com/Microsoft/hcsshim/internal/controller/device/scsi" + "github.com/Microsoft/hcsshim/internal/controller/device/vpci" hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" "github.com/Microsoft/hcsshim/internal/log" "github.com/Microsoft/hcsshim/internal/logfields" + "github.com/Microsoft/hcsshim/internal/protocol/guestresource" "github.com/Microsoft/hcsshim/internal/shimdiag" "github.com/Microsoft/hcsshim/internal/timeout" "github.com/Microsoft/hcsshim/internal/vm/guestmanager" "github.com/Microsoft/hcsshim/internal/vm/vmmanager" "github.com/Microsoft/hcsshim/internal/vm/vmutils" iwin "github.com/Microsoft/hcsshim/internal/windows" - "github.com/containerd/errdefs" + "github.com/Microsoft/hcsshim/pkg/annotations" + "github.com/Microsoft/hcsshim/pkg/ctrdtaskapi" "github.com/Microsoft/go-winio/pkg/process" + "github.com/containerd/errdefs" "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" "golang.org/x/sys/windows" ) -// Manager is the VM controller implementation that manages the lifecycle of a Utility VM +// Controller is the VM controller implementation that manages the lifecycle of a Utility VM // and its associated resources. -type Manager struct { +type Controller struct { vmID string uvm *vmmanager.UtilityVM guest *guestmanager.Guest @@ -40,7 +46,7 @@ type Manager struct { // Access must be guarded by mu. vmState State - // mu guards the concurrent access to the Manager's fields and operations. + // mu guards the concurrent access to the Controller's fields and operations. mu sync.RWMutex // logOutputDone is closed when the GCS log output processing goroutine completes. @@ -55,14 +61,23 @@ type Manager struct { // isPhysicallyBacked indicates whether the VM is using physical backing for its memory. isPhysicallyBacked bool -} -// Ensure both the Controller, and it's subset Handle are implemented by Manager. -var _ Controller = (*Manager)(nil) + // noWritableFileShares indicates whether writable file shares are disabled for this VM. + noWritableFileShares bool + + // scsiController manages SCSI devices for this VM. + scsiController *scsi.Controller + + // vpciController manages virtual PCI device assignments for this VM. + vpciController *vpci.Controller -// NewController creates a new Manager instance in the [StateNotCreated] state. -func NewController() *Manager { - return &Manager{ + // plan9Controller manages Plan9 file share mounts for this VM. + plan9Controller *plan9.Controller +} + +// New creates a new Controller instance in the [StateNotCreated] state. +func New() *Controller { + return &Controller{ logOutputDone: make(chan struct{}), vmState: StateNotCreated, } @@ -70,20 +85,32 @@ func NewController() *Manager { // Guest returns the guest manager instance for this VM. // The guest manager provides access to guest-host communication. -func (c *Manager) Guest() *guestmanager.Guest { +func (c *Controller) Guest() *guestmanager.Guest { return c.guest } // State returns the current VM state. -func (c *Manager) State() State { +func (c *Controller) State() State { c.mu.RLock() defer c.mu.RUnlock() return c.vmState } +// RuntimeID returns the UVM runtime identifier when the VM is created or running. +func (c *Controller) RuntimeID() string { + c.mu.RLock() + defer c.mu.RUnlock() + + if c.vmState != StateCreated && c.vmState != StateRunning { + return "" + } + + return c.uvm.RuntimeID().String() +} + // CreateVM creates the VM using the HCS document and initializes device state. -func (c *Manager) CreateVM(ctx context.Context, opts *CreateOptions) error { +func (c *Controller) CreateVM(ctx context.Context, opts *CreateOptions) error { ctx, _ = log.WithContext(ctx, logrus.WithField(logfields.Operation, "CreateVM")) c.mu.Lock() @@ -100,17 +127,25 @@ func (c *Manager) CreateVM(ctx context.Context, opts *CreateOptions) error { return fmt.Errorf("failed to create VM: %w", err) } - // Set the Manager parameters after successful creation. + // Set the Controller parameters after successful creation. c.vmID = opts.ID c.uvm = uvm - // Determine if the VM is physically backed based on the HCS document configuration. - // We need this while extracting memory metrics, as some of them are only relevant for physically backed VMs. - c.isPhysicallyBacked = !opts.HCSDocument.VirtualMachine.ComputeTopology.Memory.AllowOvercommit + // Determine if the VM is physically backed based on the create options. + c.isPhysicallyBacked = opts.FullyPhysicallyBacked + // + c.noWritableFileShares = opts.NoWritableFileShares // Initialize the GuestManager for managing guest interactions. // We will create the guest connection via GuestManager during StartVM. c.guest = guestmanager.New(ctx, uvm) + // Eager initialize the SCSI controller as opposed to all other controllers. + // This is because we always use SCSI for attaching scratch VHDs. + c.scsiController, err = newSCSIController(ctx, opts.HCSDocument, c.uvm, c.guest, c.guest) + if err != nil { + return fmt.Errorf("failed to initialize SCSI controller: %w", err) + } + c.vmState = StateCreated return nil } @@ -119,7 +154,7 @@ func (c *Manager) CreateVM(ctx context.Context, opts *CreateOptions) error { // It starts the underlying HCS VM, establishes the GCS connection, // and transitions the VM to [StateRunning]. // On any failure the VM is transitioned to [StateInvalid]. -func (c *Manager) StartVM(ctx context.Context, opts *StartOptions) (err error) { +func (c *Controller) StartVM(ctx context.Context, opts *StartOptions) (err error) { ctx, _ = log.WithContext(ctx, logrus.WithField(logfields.Operation, "StartVM")) c.mu.Lock() @@ -202,9 +237,49 @@ func (c *Manager) StartVM(ctx context.Context, opts *StartOptions) (err error) { return nil } +// Update is used to update the VM configuration on-the-fly. +// It supports modifying resources like CPU and memory while the VM is running. +// It also supports injecting policy fragments or updating the CPU group id for the VM. +func (c *Controller) Update(ctx context.Context, resources interface{}, annots map[string]string) error { + ctx, _ = log.WithContext(ctx, logrus.WithField(logfields.Operation, "Update")) + + c.mu.Lock() + defer c.mu.Unlock() + + if c.vmState != StateRunning { + return fmt.Errorf("cannot update VM: VM is in state %s", c.vmState) + } + + // If the resource is a policy fragment, inject it directly into the guest and return. + if policyFragment, ok := resources.(*ctrdtaskapi.PolicyFragment); ok { + return c.guest.InjectPolicyFragment(ctx, + guestresource.SecurityPolicyFragment{ + Fragment: policyFragment.Fragment, + }, + ) + } + + // Apply generic VM resource updates (e.g., CPU count, memory). + if err := c.updateVMResources(ctx, resources); err != nil { + return fmt.Errorf("failed to update VM resources: %w", err) + } + + // Update CPU group membership if the corresponding annotation is present. + if cpuGroupID, ok := annots[annotations.CPUGroupID]; ok { + if cpuGroupID == "" { + return errors.New("must specify an ID to use when configuring a VM's cpugroup") + } + if err := c.uvm.SetCPUGroup(ctx, &hcsschema.CpuGroup{Id: cpuGroupID}); err != nil { + return fmt.Errorf("failed to set CPU group: %w", err) + } + } + + return nil +} + // waitForVMExit blocks until the VM exits and then transitions the VM state to [StateTerminated]. // This is called in StartVM in a background goroutine. -func (c *Manager) waitForVMExit(ctx context.Context) { +func (c *Controller) waitForVMExit(ctx context.Context) { // The original context may have timeout or propagate a cancellation // copy the original to prevent it affecting the background wait go routine ctx = context.WithoutCancel(ctx) @@ -216,14 +291,12 @@ func (c *Manager) waitForVMExit(ctx context.Context) { c.mu.Lock() if c.vmState != StateTerminated { c.vmState = StateTerminated - } else { - log.G(ctx).WithField("currentState", c.vmState).Debug("waitForVMExit: state transition to Terminated was a no-op") } c.mu.Unlock() } // ExecIntoHost executes a command in the running UVM. -func (c *Manager) ExecIntoHost(ctx context.Context, request *shimdiag.ExecProcessRequest) (int, error) { +func (c *Controller) ExecIntoHost(ctx context.Context, request *shimdiag.ExecProcessRequest) (int, error) { ctx, _ = log.WithContext(ctx, logrus.WithField(logfields.Operation, "ExecIntoHost")) if request.Terminal && request.Stderr != "" { @@ -256,7 +329,7 @@ func (c *Manager) ExecIntoHost(ctx context.Context, request *shimdiag.ExecProces } // DumpStacks dumps the GCS stacks associated with the VM -func (c *Manager) DumpStacks(ctx context.Context) (string, error) { +func (c *Controller) DumpStacks(ctx context.Context) (string, error) { ctx, _ = log.WithContext(ctx, logrus.WithField(logfields.Operation, "DumpStacks")) // Take read lock at this place. @@ -278,7 +351,7 @@ func (c *Manager) DumpStacks(ctx context.Context) (string, error) { } // Wait blocks until the VM exits and all log output processing has completed. -func (c *Manager) Wait(ctx context.Context) error { +func (c *Controller) Wait(ctx context.Context) error { ctx, _ = log.WithContext(ctx, logrus.WithField(logfields.Operation, "Wait")) // Validate that the VM has been created and can be waited on. @@ -308,7 +381,7 @@ func (c *Manager) Wait(ctx context.Context) error { // Stats returns runtime statistics for the VM including processor runtime and // memory usage. The VM must be in [StateRunning]. -func (c *Manager) Stats(ctx context.Context) (*stats.VirtualMachineStatistics, error) { +func (c *Controller) Stats(ctx context.Context) (*stats.VirtualMachineStatistics, error) { ctx, _ = log.WithContext(ctx, logrus.WithField(logfields.Operation, "Stats")) // Take read lock at this place. @@ -376,7 +449,7 @@ func (c *Manager) Stats(ctx context.Context) (*stats.VirtualMachineStatistics, e // // The context is used for all operations, including waits, so timeouts/cancellations may prevent // proper UVM cleanup. -func (c *Manager) TerminateVM(ctx context.Context) (err error) { +func (c *Controller) TerminateVM(ctx context.Context) (err error) { ctx, _ = log.WithContext(ctx, logrus.WithField(logfields.Operation, "TerminateVM")) c.mu.Lock() @@ -413,7 +486,7 @@ func (c *Manager) TerminateVM(ctx context.Context) (err error) { // StartTime returns the timestamp when the VM was started. // Returns zero value of time.Time if the VM has not yet reached // [StateRunning] or [StateTerminated]. -func (c *Manager) StartTime() (startTime time.Time) { +func (c *Controller) StartTime() (startTime time.Time) { c.mu.RLock() defer c.mu.RUnlock() @@ -427,7 +500,7 @@ func (c *Manager) StartTime() (startTime time.Time) { // ExitStatus returns the final status of the VM once it has reached // [StateTerminated], including the time it stopped and any exit error. // Returns an error if the VM has not yet stopped. -func (c *Manager) ExitStatus() (*ExitStatus, error) { +func (c *Controller) ExitStatus() (*ExitStatus, error) { c.mu.RLock() defer c.mu.RUnlock() diff --git a/internal/controller/vm/vm_devices.go b/internal/controller/vm/vm_devices.go new file mode 100644 index 0000000000..873a5aa161 --- /dev/null +++ b/internal/controller/vm/vm_devices.go @@ -0,0 +1,82 @@ +//go:build windows + +package vm + +import ( + "context" + "fmt" + "strconv" + + "github.com/Microsoft/hcsshim/internal/controller/device/scsi" + "github.com/Microsoft/hcsshim/internal/controller/device/vpci" + "github.com/Microsoft/hcsshim/internal/controller/network" + hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" + "github.com/Microsoft/hcsshim/internal/protocol/guestrequest" +) + +// NetworkController returns a new controller for managing network devices on the VM. +// Since we have a namespace per pod, we create a new controller per call. +func (c *Controller) NetworkController() *network.Controller { + return network.New(c.uvm, c.guest, c.guest) +} + +// SCSIController returns the singleton SCSI device controller for this VM. +func (c *Controller) SCSIController() *scsi.Controller { + return c.scsiController +} + +// VPCIController returns the singleton vPCI device controller for this VM. +func (c *Controller) VPCIController() *vpci.Controller { + c.mu.Lock() + defer c.mu.Unlock() + + if c.vpciController == nil { + c.vpciController = vpci.New(c.uvm, c.guest) + } + + return c.vpciController +} + +// newSCSIController creates a [scsi.Controller] from the HCS document, +// pre-reserving every rootfs slot that already has an attachment in the document. +func newSCSIController( + ctx context.Context, + doc *hcsschema.ComputeSystem, + vm scsi.VMSCSIOps, + linuxGuest scsi.LinuxGuestSCSIOps, + windowsGuest scsi.WindowsGuestSCSIOps, +) (*scsi.Controller, error) { + // If there are no SCSI device controllers in the document, error out. + if doc.VirtualMachine == nil || + doc.VirtualMachine.Devices == nil || + len(doc.VirtualMachine.Devices.Scsi) == 0 { + return nil, fmt.Errorf("expected the VM to have at least one SCSI controller") + } + + // Create a VM SCSI controller. + scsiMap := doc.VirtualMachine.Devices.Scsi + ctrl := scsi.New(len(scsiMap), vm, linuxGuest, windowsGuest) + + // Iterate over the well-known controller GUIDs so the slice index gives us + // the correct controller number directly. + for ctrlIdx, guid := range guestrequest.ScsiControllerGuids { + c, ok := scsiMap[guid] + if !ok { + continue + } + + // Found the controller GUID in the document. + for lunStr := range c.Attachments { + lun, err := strconv.ParseUint(lunStr, 10, 32) + if err != nil { + continue + } + + if err := ctrl.ReserveForRootfs(ctx, uint(ctrlIdx), uint(lun)); err != nil { + return nil, fmt.Errorf("reserve SCSI slot (controller=%d, lun=%d): %w", ctrlIdx, lun, err) + } + } + } + + return ctrl, nil +} diff --git a/internal/controller/vm/vm_lcow.go b/internal/controller/vm/vm_lcow.go index e8c5b51194..52769cb6fb 100644 --- a/internal/controller/vm/vm_lcow.go +++ b/internal/controller/vm/vm_lcow.go @@ -1,4 +1,4 @@ -//go:build windows && !wcow +//go:build windows && lcow package vm @@ -8,19 +8,38 @@ import ( "fmt" "io" + "github.com/Microsoft/hcsshim/internal/controller/device/plan9" + hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" + "github.com/Microsoft/hcsshim/internal/memory" "github.com/Microsoft/hcsshim/internal/vm/vmmanager" "github.com/Microsoft/hcsshim/internal/vm/vmutils" + "github.com/Microsoft/hcsshim/osversion" "github.com/Microsoft/go-winio" + "github.com/containerd/errdefs" + "github.com/opencontainers/runtime-spec/specs-go" "golang.org/x/sync/errgroup" ) +// Plan9Controller returns the singleton controller which can be used +// to manage the Plan9 shares on the Linux UVM. +func (c *Controller) Plan9Controller() *plan9.Controller { + c.mu.Lock() + defer c.mu.Unlock() + + if c.plan9Controller == nil { + c.plan9Controller = plan9.New(c.uvm, c.guest, c.noWritableFileShares) + } + + return c.plan9Controller +} + // setupEntropyListener sets up entropy for LCOW UVMs. // // Linux VMs require entropy to initialize their random number generators during boot. // This method listens on a predefined vsock port and provides cryptographically secure // random data to the Linux init process when it connects. -func (c *Manager) setupEntropyListener(ctx context.Context, group *errgroup.Group) { +func (c *Controller) setupEntropyListener(ctx context.Context, group *errgroup.Group) { group.Go(func() error { // The Linux guest will connect to this port during init to receive entropy. entropyConn, err := winio.ListenHvsock(&winio.HvsockAddr{ @@ -58,7 +77,7 @@ func (c *Manager) setupEntropyListener(ctx context.Context, group *errgroup.Grou // This method establishes a vsock connection to receive log output from GCS // running inside the Linux VM. The logs are parsed and // forwarded to the host's logging system for monitoring and debugging. -func (c *Manager) setupLoggingListener(ctx context.Context, group *errgroup.Group) { +func (c *Controller) setupLoggingListener(ctx context.Context, group *errgroup.Group) { group.Go(func() error { // The GCS will connect to this port to stream log output. logConn, err := winio.ListenHvsock(&winio.HvsockAddr{ @@ -93,6 +112,53 @@ func (c *Manager) setupLoggingListener(ctx context.Context, group *errgroup.Grou // finalizeGCSConnection finalizes the GCS connection for LCOW VMs. // For LCOW, no additional finalization is needed. -func (c *Manager) finalizeGCSConnection(_ context.Context) error { +func (c *Controller) finalizeGCSConnection(_ context.Context) error { + return nil +} + +// updateVMResources applies Linux VM memory and CPU limits from OCI resources. +func (c *Controller) updateVMResources(ctx context.Context, data interface{}) error { + resources, ok := data.(*specs.LinuxResources) + if !ok { + return fmt.Errorf("invalid resource type %T, expected *specs.LinuxResources", data) + } + + if resources.Memory != nil { + if resources.Memory.Limit == nil { + return fmt.Errorf("invalid linux memory limit") + } + + sizeInBytes := uint64(*resources.Memory.Limit) + // Make a call to the VM's orchestrator to update the VM's size in MB + // Internally, HCS will get the number of pages this corresponds to and attempt to assign + // pages to numa nodes evenly + requestedSizeInMB := sizeInBytes / memory.MiB + actual := vmutils.NormalizeMemorySize(ctx, c.vmID, requestedSizeInMB) + + if err := c.uvm.UpdateMemory(ctx, actual); err != nil { + return fmt.Errorf("update vm memory: %w", err) + } + } + + // Translate OCI CPU knobs to HCS processor limits. + if resources.CPU != nil { + processorLimits := &hcsschema.ProcessorLimits{} + if resources.CPU.Quota != nil { + processorLimits.Limit = uint64(*resources.CPU.Quota) + } + if resources.CPU.Shares != nil { + processorLimits.Weight = uint64(*resources.CPU.Shares) + } + + // Support for updating CPU limits was not added until 20H2 build + if osversion.Get().Build < osversion.V20H2 { + return errdefs.ErrNotImplemented + } + + if err := c.uvm.UpdateCPULimits(ctx, processorLimits); err != nil { + return fmt.Errorf("update vm cpu limits: %w", err) + } + } + return nil } diff --git a/internal/controller/vm/vm_unsupported.go b/internal/controller/vm/vm_unsupported.go new file mode 100644 index 0000000000..957c428f1f --- /dev/null +++ b/internal/controller/vm/vm_unsupported.go @@ -0,0 +1,26 @@ +//go:build windows && !wcow && !lcow + +package vm + +import ( + "context" + "fmt" + + "golang.org/x/sync/errgroup" +) + +// setupEntropyListener is a no-op for unsupported guests. +func (c *Controller) setupEntropyListener(_ context.Context, _ *errgroup.Group) {} + +// setupLoggingListener is a no-op for unsupported guests. +func (c *Controller) setupLoggingListener(_ context.Context, _ *errgroup.Group) {} + +// finalizeGCSConnection is not supported for unsupported guests. +func (c *Controller) finalizeGCSConnection(_ context.Context) error { + return fmt.Errorf("unsupported guest") +} + +// updateVMResources is not supported for unsupported guests. +func (c *Controller) updateVMResources(_ context.Context, _ interface{}) error { + return fmt.Errorf("unsupported guest") +} diff --git a/internal/controller/vm/vm_wcow.go b/internal/controller/vm/vm_wcow.go index de6053be8e..50061b3b58 100644 --- a/internal/controller/vm/vm_wcow.go +++ b/internal/controller/vm/vm_wcow.go @@ -10,9 +10,13 @@ import ( "github.com/Microsoft/go-winio" "github.com/Microsoft/hcsshim/internal/gcs/prot" hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" + "github.com/Microsoft/hcsshim/internal/memory" "github.com/Microsoft/hcsshim/internal/vm/vmmanager" "github.com/Microsoft/hcsshim/internal/vm/vmutils" + "github.com/Microsoft/hcsshim/osversion" + "github.com/containerd/errdefs" + "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" "golang.org/x/net/netutil" "golang.org/x/sync/errgroup" @@ -25,7 +29,7 @@ import ( // This is a no-op implementation to satisfy the platform-specific interface. // // For comparison, LCOW VMs require entropy to be provided during boot. -func (c *Manager) setupEntropyListener(_ context.Context, _ *errgroup.Group) {} +func (c *Controller) setupEntropyListener(_ context.Context, _ *errgroup.Group) {} // setupLoggingListener sets up logging for WCOW UVMs. // @@ -37,7 +41,7 @@ func (c *Manager) setupEntropyListener(_ context.Context, _ *errgroup.Group) {} // The listener is configured to accept only one concurrent connection at a time // to prevent resource exhaustion, but will accept new connections if the current one is closed. // This supports scenarios where the logging service inside the VM needs to restart. -func (c *Manager) setupLoggingListener(ctx context.Context, _ *errgroup.Group) { +func (c *Controller) setupLoggingListener(ctx context.Context, _ *errgroup.Group) { // For Windows, the listener can receive a connection later (after VM starts), // so we start the output handler in a goroutine with a non-timeout context. // This allows the output handler to run independently of the VM creation lifecycle. @@ -96,7 +100,7 @@ func (c *Manager) setupLoggingListener(ctx context.Context, _ *errgroup.Group) { // finalizeGCSConnection finalizes the GCS connection for WCOW UVMs. // This is called after CreateConnection succeeds and before the VM is considered fully started. -func (c *Manager) finalizeGCSConnection(ctx context.Context) error { +func (c *Controller) finalizeGCSConnection(ctx context.Context) error { // Prepare the HvSocket address configuration for the external GCS connection. // The LocalAddress is the VM's runtime ID, and the ParentAddress is the // predefined host ID for Windows GCS communication. @@ -114,3 +118,50 @@ func (c *Manager) finalizeGCSConnection(ctx context.Context) error { return nil } + +// updateVMResources applies Windows VM memory and CPU limits from OCI resources. +func (c *Controller) updateVMResources(ctx context.Context, data interface{}) error { + resources, ok := data.(*specs.WindowsResources) + if !ok { + return fmt.Errorf("invalid resource type %T, expected *specs.WindowsResources", data) + } + + if resources.Memory != nil { + if resources.Memory.Limit == nil { + return fmt.Errorf("invalid windows memory limit: nil") + } + + sizeInBytes := *resources.Memory.Limit + // Make a call to the VM's orchestrator to update the VM's size in MB + // Internally, HCS will get the number of pages this corresponds to and attempt to assign + // pages to numa nodes evenly + requestedSizeInMB := sizeInBytes / memory.MiB + actual := vmutils.NormalizeMemorySize(ctx, c.vmID, requestedSizeInMB) + + if err := c.uvm.UpdateMemory(ctx, actual); err != nil { + return fmt.Errorf("update vm memory: %w", err) + } + } + + // Translate OCI CPU knobs to HCS processor limits. + if resources.CPU != nil { + processorLimits := &hcsschema.ProcessorLimits{} + if resources.CPU.Maximum != nil { + processorLimits.Limit = uint64(*resources.CPU.Maximum) + } + if resources.CPU.Shares != nil { + processorLimits.Weight = uint64(*resources.CPU.Shares) + } + + // Support for updating CPU limits was not added until 20H2 build + if osversion.Get().Build < osversion.V20H2 { + return errdefs.ErrNotImplemented + } + + if err := c.uvm.UpdateCPULimits(ctx, processorLimits); err != nil { + return fmt.Errorf("update vm cpu limits: %w", err) + } + } + + return nil +} diff --git a/internal/vm/guestmanager/block_cims.go b/internal/vm/guestmanager/block_cims.go index 022829df9c..33bc741773 100644 --- a/internal/vm/guestmanager/block_cims.go +++ b/internal/vm/guestmanager/block_cims.go @@ -11,16 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestresource" ) -// CIMsManager exposes guest WCOW block CIM operations. -type CIMsManager interface { - // AddWCOWBlockCIMs adds WCOW block CIM mounts in the guest. - AddWCOWBlockCIMs(ctx context.Context, settings *guestresource.CWCOWBlockCIMMounts) error - // RemoveWCOWBlockCIMs removes WCOW block CIM mounts from the guest. - RemoveWCOWBlockCIMs(ctx context.Context, settings *guestresource.CWCOWBlockCIMMounts) error -} - -var _ CIMsManager = (*Guest)(nil) - // AddWCOWBlockCIMs adds WCOW block CIM mounts in the guest. func (gm *Guest) AddWCOWBlockCIMs(ctx context.Context, settings *guestresource.CWCOWBlockCIMMounts) error { request := &hcsschema.ModifySettingRequest{ diff --git a/internal/vm/guestmanager/combinedlayers_lcow.go b/internal/vm/guestmanager/combinedlayers_lcow.go index 2a5b56e5a9..ae09116f54 100644 --- a/internal/vm/guestmanager/combinedlayers_lcow.go +++ b/internal/vm/guestmanager/combinedlayers_lcow.go @@ -11,16 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestresource" ) -// LCOWLayersManager exposes combined layer operations in the LCOW guest. -type LCOWLayersManager interface { - // AddLCOWCombinedLayers adds combined layers to the LCOW guest. - AddLCOWCombinedLayers(ctx context.Context, settings guestresource.LCOWCombinedLayers) error - // RemoveLCOWCombinedLayers removes combined layers from the LCOW guest. - RemoveLCOWCombinedLayers(ctx context.Context, settings guestresource.LCOWCombinedLayers) error -} - -var _ LCOWLayersManager = (*Guest)(nil) - // AddLCOWCombinedLayers adds LCOW combined layers in the guest. func (gm *Guest) AddLCOWCombinedLayers(ctx context.Context, settings guestresource.LCOWCombinedLayers) error { modifyRequest := &hcsschema.ModifySettingRequest{ diff --git a/internal/vm/guestmanager/combinedlayers_wcow.go b/internal/vm/guestmanager/combinedlayers_wcow.go index 77b63d18f6..330232719d 100644 --- a/internal/vm/guestmanager/combinedlayers_wcow.go +++ b/internal/vm/guestmanager/combinedlayers_wcow.go @@ -11,20 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestresource" ) -// WCOWLayersManager exposes combined layer operations in the WCOW guest. -type WCOWLayersManager interface { - // AddWCOWCombinedLayers adds combined layers to the WCOW guest. - AddWCOWCombinedLayers(ctx context.Context, settings guestresource.WCOWCombinedLayers) error - // AddCWCOWCombinedLayers adds combined layers to the CWCOW guest. - AddCWCOWCombinedLayers(ctx context.Context, settings guestresource.CWCOWCombinedLayers) error - // RemoveWCOWCombinedLayers removes combined layers from the WCOW guest. - RemoveWCOWCombinedLayers(ctx context.Context, settings guestresource.WCOWCombinedLayers) error - // RemoveCWCOWCombinedLayers removes combined layers from the CWCOW guest. - RemoveCWCOWCombinedLayers(ctx context.Context, settings guestresource.CWCOWCombinedLayers) error -} - -var _ WCOWLayersManager = (*Guest)(nil) - // AddWCOWCombinedLayers adds WCOW combined layers in the guest. func (gm *Guest) AddWCOWCombinedLayers(ctx context.Context, settings guestresource.WCOWCombinedLayers) error { modifyRequest := &hcsschema.ModifySettingRequest{ diff --git a/internal/vm/guestmanager/guest.go b/internal/vm/guestmanager/guest.go index 7f9b705376..b8ef0f11be 100644 --- a/internal/vm/guestmanager/guest.go +++ b/internal/vm/guestmanager/guest.go @@ -17,6 +17,19 @@ import ( "github.com/sirupsen/logrus" ) +// uvm exposes the subset of [vmmanager.UtilityVM] functionality that the +// guest manager needs. +type uvm interface { + // ID returns the user-visible identifier for the Utility VM. + ID() string + // RuntimeID returns the Hyper-V VM GUID. + RuntimeID() guid.GUID + // Wait blocks until the VM exits or ctx is cancelled. + Wait(ctx context.Context) error + // ExitError returns the error that caused the VM to exit, if any. + ExitError() error +} + // Guest manages the GCS connection and guest-side operations for a utility VM. type Guest struct { // mu serializes all operations that interact with the guest connection (gc). @@ -28,22 +41,15 @@ type Guest struct { log *logrus.Entry // uvm is the utility VM that this GuestManager is managing. - // We restrict access to just lifetime manager and VMSocket manager. - // Other APIs are outside the purview of this package. - uvm interface { - vmmanager.LifetimeManager - vmmanager.VMSocketManager - } + // We restrict access to just the methods actually needed by this package. + uvm uvm // gc is the active GCS connection to the guest. // It will be nil if no connection is active. gc *gcs.GuestConnection } // New creates a new Guest Manager. -func New(ctx context.Context, uvm interface { - vmmanager.LifetimeManager - vmmanager.VMSocketManager -}) *Guest { +func New(ctx context.Context, uvm uvm) *Guest { return &Guest{ log: log.G(ctx).WithField(logfields.UVMID, uvm.ID()), uvm: uvm, diff --git a/internal/vm/guestmanager/hvsocket.go b/internal/vm/guestmanager/hvsocket.go index 1108ec1cd6..8cb616fd0f 100644 --- a/internal/vm/guestmanager/hvsocket.go +++ b/internal/vm/guestmanager/hvsocket.go @@ -11,13 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestresource" ) -// HVSocketManager exposes the hvSocket operations in the Guest. -type HVSocketManager interface { - UpdateHvSocketAddress(ctx context.Context, settings *hcsschema.HvSocketAddress) error -} - -var _ HVSocketManager = (*Guest)(nil) - // UpdateHvSocketAddress updates the Hyper-V socket address settings for the VM. // These address settings are applied by the GCS every time the VM starts or restores. func (gm *Guest) UpdateHvSocketAddress(ctx context.Context, settings *hcsschema.HvSocketAddress) error { diff --git a/internal/vm/guestmanager/manager.go b/internal/vm/guestmanager/manager.go index 2eeb705bbd..474e9ca63c 100644 --- a/internal/vm/guestmanager/manager.go +++ b/internal/vm/guestmanager/manager.go @@ -8,33 +8,8 @@ import ( "github.com/Microsoft/hcsshim/internal/cmd" "github.com/Microsoft/hcsshim/internal/gcs" - - "github.com/Microsoft/go-winio/pkg/guid" ) -// Manager provides access to guest operations over the GCS connection. -// Call CreateConnection before invoking other methods. -type Manager interface { - // CreateConnection accepts the GCS connection and performs initial setup. - CreateConnection(ctx context.Context, GCSServiceID guid.GUID, opts ...ConfigOption) error - // CloseConnection closes the GCS connection and listener. - CloseConnection() error - // Capabilities returns the guest's declared capabilities. - Capabilities() gcs.GuestDefinedCapabilities - // CreateContainer creates a container within guest using ID `cid` and `config`. - // Once the container is created, it can be managed using the returned `gcs.Container` interface. - // `gcs.Container` uses the underlying guest connection to issue commands to the guest. - CreateContainer(ctx context.Context, cid string, config interface{}) (*gcs.Container, error) - // DumpStacks requests a stack dump from the guest and returns it as a string. - DumpStacks(ctx context.Context) (string, error) - // DeleteContainerState removes persisted state for the container identified by `cid` from the guest. - DeleteContainerState(ctx context.Context, cid string) error - // ExecIntoUVM executes commands specified in the requests in the utility VM. - ExecIntoUVM(ctx context.Context, request *cmd.CmdProcessRequest) (int, error) -} - -var _ Manager = (*Guest)(nil) - // Capabilities returns the capabilities of the guest connection. func (gm *Guest) Capabilities() gcs.GuestDefinedCapabilities { gm.mu.RLock() diff --git a/internal/vm/guestmanager/mapped_directory_lcow.go b/internal/vm/guestmanager/mapped_directory_lcow.go index 6cd9409b47..75d355ffd6 100644 --- a/internal/vm/guestmanager/mapped_directory_lcow.go +++ b/internal/vm/guestmanager/mapped_directory_lcow.go @@ -11,16 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestresource" ) -// LCOWDirectoryManager exposes mapped directory operations in the LCOW guest. -type LCOWDirectoryManager interface { - // AddLCOWMappedDirectory maps a directory into the LCOW guest. - AddLCOWMappedDirectory(ctx context.Context, settings guestresource.LCOWMappedDirectory) error - // RemoveLCOWMappedDirectory unmaps a directory from the LCOW guest. - RemoveLCOWMappedDirectory(ctx context.Context, settings guestresource.LCOWMappedDirectory) error -} - -var _ LCOWDirectoryManager = (*Guest)(nil) - // AddLCOWMappedDirectory maps a directory into LCOW guest. func (gm *Guest) AddLCOWMappedDirectory(ctx context.Context, settings guestresource.LCOWMappedDirectory) error { request := &hcsschema.ModifySettingRequest{ diff --git a/internal/vm/guestmanager/mapped_directory_wcow.go b/internal/vm/guestmanager/mapped_directory_wcow.go index 8c5ee22700..78a93eb9d1 100644 --- a/internal/vm/guestmanager/mapped_directory_wcow.go +++ b/internal/vm/guestmanager/mapped_directory_wcow.go @@ -11,14 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestresource" ) -// WCOWDirectoryManager exposes mapped directory operations in the WCOW guest. -type WCOWDirectoryManager interface { - // AddMappedDirectory maps a directory into the WCOW guest. - AddMappedDirectory(ctx context.Context, settings *hcsschema.MappedDirectory) error -} - -var _ WCOWDirectoryManager = (*Guest)(nil) - // AddMappedDirectory maps a directory into the guest. func (gm *Guest) AddMappedDirectory(ctx context.Context, settings *hcsschema.MappedDirectory) error { request := &hcsschema.ModifySettingRequest{ diff --git a/internal/vm/guestmanager/security_policy.go b/internal/vm/guestmanager/security_policy.go index c91a4950b6..bb04749ced 100644 --- a/internal/vm/guestmanager/security_policy.go +++ b/internal/vm/guestmanager/security_policy.go @@ -11,16 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestresource" ) -// SecurityPolicyManager exposes guest security policy operations. -type SecurityPolicyManager interface { - // AddSecurityPolicy adds a security policy to the guest. - AddSecurityPolicy(ctx context.Context, settings guestresource.ConfidentialOptions) error - // InjectPolicyFragment injects a policy fragment into the guest. - InjectPolicyFragment(ctx context.Context, settings guestresource.SecurityPolicyFragment) error -} - -var _ SecurityPolicyManager = (*Guest)(nil) - // AddSecurityPolicy adds a security policy to the guest. func (gm *Guest) AddSecurityPolicy(ctx context.Context, settings guestresource.ConfidentialOptions) error { request := &hcsschema.ModifySettingRequest{ diff --git a/internal/vm/vmmanager/lifetime.go b/internal/vm/vmmanager/lifetime.go index b2cc737b53..c98cba82a4 100644 --- a/internal/vm/vmmanager/lifetime.go +++ b/internal/vm/vmmanager/lifetime.go @@ -11,57 +11,6 @@ import ( hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" ) -type LifetimeManager interface { - // ID will return a string identifier for the Utility VM. - ID() string - - // RuntimeID will return the Hyper-V VM GUID for the Utility VM. - // - // Only valid after the utility VM has been created. - RuntimeID() guid.GUID - - // Start will power on the Utility VM and put it into a running state. This will boot the guest OS and start all of the - // devices configured on the machine. - Start(ctx context.Context) error - - // Terminate will forcefully power off the Utility VM. - // It waits for the UVM to exit and returns any encountered errors. - Terminate(ctx context.Context) error - - // Close terminates and releases resources associated with the utility VM. - Close(ctx context.Context) error - - // Pause will place the Utility VM into a paused state. The guest OS will be halted and any devices will have be in a - // a suspended state. Save can be used to snapshot the current state of the virtual machine, and Resume can be used to - // place the virtual machine back into a running state. - Pause(ctx context.Context) error - - // Resume will put a previously paused Utility VM back into a running state. The guest OS will resume operation from the point - // in time it was paused and all devices should be un-suspended. - Resume(ctx context.Context) error - - // Save will snapshot the state of the Utility VM at the point in time when the VM was paused. - Save(ctx context.Context, options hcsschema.SaveOptions) error - - // Wait synchronously waits for the Utility VM to terminate. - Wait(ctx context.Context) error - - // PropertiesV2 returns the properties of the Utility VM. - PropertiesV2(ctx context.Context, types ...hcsschema.PropertyType) (*hcsschema.Properties, error) - - // StartedTime returns the time when the Utility VM entered the running state. - StartedTime() time.Time - - // StoppedTime returns the time when the Utility VM entered the stopped state. - StoppedTime() time.Time - - // ExitError will return any error if the Utility VM exited unexpectedly, or if the Utility VM experienced an - // error after Wait returned, it will return the wait error. - ExitError() error -} - -var _ LifetimeManager = (*UtilityVM)(nil) - // ID returns the ID of the utility VM. func (uvm *UtilityVM) ID() string { return uvm.id diff --git a/internal/vm/vmmanager/pipe.go b/internal/vm/vmmanager/pipe.go index 6de649e5b2..f46904ae14 100644 --- a/internal/vm/vmmanager/pipe.go +++ b/internal/vm/vmmanager/pipe.go @@ -11,17 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestrequest" ) -// PipeManager manages adding and removing named pipes for a Utility VM. -type PipeManager interface { - // AddPipe adds a named pipe to the Utility VM. - AddPipe(ctx context.Context, hostPath string) error - - // RemovePipe removes a named pipe from the Utility VM. - RemovePipe(ctx context.Context, hostPath string) error -} - -var _ PipeManager = (*UtilityVM)(nil) - func (uvm *UtilityVM) AddPipe(ctx context.Context, hostPath string) error { modification := &hcsschema.ModifySettingRequest{ RequestType: guestrequest.RequestTypeAdd, diff --git a/internal/vm/vmmanager/resources.go b/internal/vm/vmmanager/resources.go index 48f23a5fe1..c91ae3db07 100644 --- a/internal/vm/vmmanager/resources.go +++ b/internal/vm/vmmanager/resources.go @@ -10,23 +10,6 @@ import ( hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" ) -type ResourceManager interface { - // SetCPUGroup assigns the Utility VM to a cpu group. - SetCPUGroup(ctx context.Context, settings *hcsschema.CpuGroup) error - - // UpdateCPULimits updates the CPU limits for the Utility VM. - // `limit` is the percentage of CPU cycles that the Utility VM is allowed to use. - // `weight` is the relative weight of the Utility VM compared to other VMs when CPU cycles are contended. - // `reservation` is the percentage of CPU cycles that are reserved for the Utility VM. - // `maximumFrequencyMHz` is the maximum frequency in MHz that the Utility VM can use. - UpdateCPULimits(ctx context.Context, settings *hcsschema.ProcessorLimits) error - - // UpdateMemory makes a call to the VM's orchestrator to update the VM's size in MB - UpdateMemory(ctx context.Context, memory uint64) error -} - -var _ ResourceManager = (*UtilityVM)(nil) - func (uvm *UtilityVM) SetCPUGroup(ctx context.Context, settings *hcsschema.CpuGroup) error { modification := &hcsschema.ModifySettingRequest{ ResourcePath: resourcepaths.CPUGroupResourcePath, diff --git a/internal/vm/vmmanager/utils.go b/internal/vm/vmmanager/utils.go index ad247352c8..5790fd5b0d 100644 --- a/internal/vm/vmmanager/utils.go +++ b/internal/vm/vmmanager/utils.go @@ -7,9 +7,18 @@ import ( "net" ) +// vmWaiter exposes the subset of VM lifecycle needed by [AcceptConnection]: +// Implemented by [UtilityVM]. +type vmWaiter interface { + // Wait blocks until the VM exits or ctx is cancelled. + Wait(ctx context.Context) error + // ExitError returns the error that caused the VM to exit, if any. + ExitError() error +} + // AcceptConnection accepts a connection and then closes a listener. // It monitors ctx.Done() and uvm.Wait() for early termination. -func AcceptConnection(ctx context.Context, uvm LifetimeManager, l net.Listener, closeConnection bool) (net.Conn, error) { +func AcceptConnection(ctx context.Context, uvm vmWaiter, l net.Listener, closeConnection bool) (net.Conn, error) { // Channel to capture the accept result type acceptResult struct { conn net.Conn diff --git a/internal/vm/vmmanager/vmsocket.go b/internal/vm/vmmanager/vmsocket.go index 637850e931..c6fb7a0bfe 100644 --- a/internal/vm/vmmanager/vmsocket.go +++ b/internal/vm/vmmanager/vmsocket.go @@ -11,18 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestrequest" ) -// VMSocketManager manages configuration for a hypervisor socket transport. This includes sockets such as -// HvSocket and Vsock. -type VMSocketManager interface { - // UpdateHvSocketService will update the configuration for the HvSocket service with the specified `serviceID`. - UpdateHvSocketService(ctx context.Context, serviceID string, config *hcsschema.HvSocketServiceConfig) error - - // RemoveHvSocketService will remove the HvSocket service with the specified `serviceID` from the Utility VM. - RemoveHvSocketService(ctx context.Context, serviceID string) error -} - -var _ VMSocketManager = (*UtilityVM)(nil) - // UpdateHvSocketService calls HCS to update/create the hvsocket service for // the UVM. Takes in a service ID and the hvsocket service configuration. If there is no // entry for the service ID already it will be created. The same call on HvSockets side diff --git a/internal/vm/vmmanager/vsmb.go b/internal/vm/vmmanager/vsmb.go index af7af6c2d7..b957f257a2 100644 --- a/internal/vm/vmmanager/vsmb.go +++ b/internal/vm/vmmanager/vsmb.go @@ -11,17 +11,6 @@ import ( "github.com/Microsoft/hcsshim/internal/protocol/guestrequest" ) -// VSMBManager manages adding virtual smb shares to a Utility VM. -type VSMBManager interface { - // AddVSMB adds a virtual smb share to a running Utility VM. - AddVSMB(ctx context.Context, settings hcsschema.VirtualSmbShare) error - - // RemoveVSMB removes a virtual smb share from a running Utility VM. - RemoveVSMB(ctx context.Context, settings hcsschema.VirtualSmbShare) error -} - -var _ VSMBManager = (*UtilityVM)(nil) - func (uvm *UtilityVM) AddVSMB(ctx context.Context, settings hcsschema.VirtualSmbShare) error { modification := &hcsschema.ModifySettingRequest{ RequestType: guestrequest.RequestTypeAdd,