Skip to content

Adds Builder and VM Manager interfaces + implementation for UVM#2597

Open
rawahars wants to merge 3 commits intomicrosoft:mainfrom
rawahars:feat/vm-package
Open

Adds Builder and VM Manager interfaces + implementation for UVM#2597
rawahars wants to merge 3 commits intomicrosoft:mainfrom
rawahars:feat/vm-package

Conversation

@rawahars
Copy link
Contributor

This pull request introduces a major refactor and formalization of the Utility VM (UVM) builder and management interfaces. It separates the responsibilities for VM configuration, host-side management, and guest-side actions into clear, testable layers. The changes include a new, well-documented builder interface, VM manager interface, concrete builder and VM manager implementations, along with comprehensive unit tests for the builder's functionality.

The most important changes are:

Architectural Refactor and Documentation

  • Added a detailed README.md to the internal/vm package, clearly explaining the separation of concerns between the Builder, VM Manager, and Guest Manager layers, and documenting the responsibilities and flow for each layer.

Builder Interface and Implementation

  • Replaced the old UVMBuilder interface with a new, comprehensive Builder interface in internal/vm/builder.go, providing modular access to memory, processor, NUMA, device, boot, and storage QoS configuration managers.
  • Introduced a concrete implementation of the Builder interface in internal/vm/builder/builder.go for creating and configuring hcsschema.ComputeSystem documents.

VM Manager Interface and Implementation

  • Created a new comprehensive UVM interface which corresponds to VM manager functionality.
  • All the VM host side modification are responsibility of this interface.

Testing

  • Added comprehensive unit tests for builder verification.

These changes establish a foundation for future VM configuration and management features.

Refactor UVM responsibilities into clear builder vs vmmanager packages and
document the intended 3-layer VM model.

Key changes:
- Introduce internal/vm/builder for HCS compute system construction.
- Introduce internal/vm/vmmanager for host-side lifecycle/resource control.
- Move UVM interfaces and shared types into focused locations.
- Add internal/vm/README.md describing layer boundaries and usage flow.
- Remove legacy internal/vm/hcs files and rename/move implementations.

Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>

var _ VMSocketManager = (*UtilityVM)(nil)

func (uvm *UtilityVM) VMSocketListen(connID guid.GUID) (net.Listener, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is in the wrong spot. Should be a higher level package IMO

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that sounds good. We can implement this in VM Controller too since we can extract the VM's ID via this interface.

request := &hcsschema.ModifySettingRequest{
RequestType: guestrequest.RequestTypeAdd,
Settings: hcsschema.Attachment{
Path: disk.Path,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we copy the disk? Why cant we just assign it to settings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I’ve updated this to assign the disk directly. I avoided this before because the old shim only set specific fields, but since we can move that logic to the upper layer, we can pass the whole object.

}

// Cache the VM ID of the utility VM.
properties, err := cs.Properties(ctx)
Copy link
Contributor

Choose a reason for hiding this comment

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

Do the properties return in any compute system state?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this specific method, the properties are queried to get the RuntimeID.
For higher layers, we have a method PropertiesV2 under LifetimeManager which can be used to query properties.


defer func() {
if cs != nil {
_ = cs.Terminate(ctx)
Copy link
Contributor

Choose a reason for hiding this comment

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

We dont start it why do we need terminate? Just delete right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No at the point when this defer is registered, we would have started the compute system. If there is a failure in Properties call, we move to terminate it.

request := &hcsschema.ModifySettingRequest{
ResourcePath: fmt.Sprintf(resourcepaths.VirtualPCIResourceFormat, vmbusGUID),
RequestType: guestrequest.RequestTypeAdd,
Settings: hcsschema.VirtualPciDevice{
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like we should actually have the API for the PCI device, and then this one is actually add function

}

ctrl.Attachments[lun] = disk
uvmb.doc.VirtualMachine.Devices.Scsi[controller] = ctrl
Copy link
Contributor

Choose a reason for hiding this comment

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

I've forgotten my golang. Can you not do this in place without the copy out / update model?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, nice catch! I have removed it and added a test too.


var _ ProcessorOptions = (*UtilityVM)(nil)

func (uvmb *UtilityVM) SetProcessorLimits(config *hcsschema.VirtualMachineProcessor) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This one is odd. If you had the VirtualMachineProcessor you would have already set its .Count/.Limit/,Weight and they would be in the builder right? Seems like if we need this overload we would want it to reflect a smaller set of just count/limit/weight overrides

return errors.Wrapf(errAlreadySet, "device %v already assigned to utility VM", device)
}

vmbusGUID, err := guid.NewV4()
Copy link
Contributor

Choose a reason for hiding this comment

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

The caller should pass this guid. You will need in in the controller layers for save/restore alignment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch! Changed this.

}

func (uvmb *UtilityVM) SetSerialConsole(port uint32, listenerPath string) error {
if !strings.HasPrefix(listenerPath, `\\.\pipe\`) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You should also allow the administrators pipe prefix

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The administrators pipe prefix(\\.\pipe\ProtectedPrefix\Administrator\) is already allowed since it starts with \\.\pipe\. I've added a test case to explicitly verify this.

case vm.Windows:
doc.VirtualMachine.Devices.VirtualSmb = &hcsschema.VirtualSmb{}
case vm.Linux:
doc.VirtualMachine.Devices.Plan9 = &hcsschema.Plan9{}
Copy link
Contributor

Choose a reason for hiding this comment

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

We should add this at the time of its use right? We dont want 9pfs if the caller has no shares right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IIRC these are added pre-emptively so that HCS can perform warm-up logic on its end.

Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
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.

3 participants

Comments