-
Notifications
You must be signed in to change notification settings - Fork 285
Support assigning cpugroup immediately after UVM start #888
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| package cpugroup | ||
|
|
||
| import ( | ||
| "context" | ||
| "encoding/json" | ||
| "errors" | ||
| "fmt" | ||
| "strings" | ||
|
|
||
| "github.com/Microsoft/hcsshim/internal/hcs" | ||
| hcsschema "github.com/Microsoft/hcsshim/internal/schema2" | ||
| ) | ||
|
|
||
| const NullGroupID = "00000000-0000-0000-0000-000000000000" | ||
|
|
||
| // ErrHVStatusInvalidCPUGroupState corresponds to the internal error code for HV_STATUS_INVALID_CPU_GROUP_STATE | ||
| var ErrHVStatusInvalidCPUGroupState = errors.New("The hypervisor could not perform the operation because the CPU group is entering or in an invalid state.") | ||
|
|
||
| // Delete deletes the cpugroup from the host | ||
| func Delete(ctx context.Context, id string) error { | ||
| operation := hcsschema.DeleteGroup | ||
| details := hcsschema.DeleteGroupOperation{ | ||
| GroupId: id, | ||
| } | ||
|
|
||
| return modifyCPUGroupRequest(ctx, operation, details) | ||
| } | ||
|
|
||
| // modifyCPUGroupRequest is a helper function for making modify calls to a cpugroup | ||
| func modifyCPUGroupRequest(ctx context.Context, operation hcsschema.CPUGroupOperation, details interface{}) error { | ||
| req := hcsschema.ModificationRequest{ | ||
| PropertyType: hcsschema.PTCPUGroup, | ||
| Settings: &hcsschema.HostProcessorModificationRequest{ | ||
| Operation: operation, | ||
| OperationDetails: details, | ||
| }, | ||
| } | ||
|
|
||
| return hcs.ModifyServiceSettings(ctx, req) | ||
| } | ||
|
|
||
| // Create creates a new cpugroup on the host with a prespecified id | ||
| func Create(ctx context.Context, id string, logicalProcessors []uint32) error { | ||
| operation := hcsschema.CreateGroup | ||
| details := &hcsschema.CreateGroupOperation{ | ||
| GroupId: strings.ToLower(id), | ||
| LogicalProcessors: logicalProcessors, | ||
| LogicalProcessorCount: uint32(len(logicalProcessors)), | ||
| } | ||
| if err := modifyCPUGroupRequest(ctx, operation, details); err != nil { | ||
| return fmt.Errorf("failed to make cpugroups CreateGroup request for details %+v with: %s", details, err) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| // getCPUGroupConfig finds the cpugroup config information for group with `id` | ||
| func getCPUGroupConfig(ctx context.Context, id string) (*hcsschema.CpuGroupConfig, error) { | ||
| query := hcsschema.PropertyQuery{ | ||
| PropertyTypes: []hcsschema.PropertyType{hcsschema.PTCPUGroup}, | ||
| } | ||
| cpuGroupsPresent, err := hcs.GetServiceProperties(ctx, query) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| groupConfigs := &hcsschema.CpuGroupConfigurations{} | ||
| if err := json.Unmarshal(cpuGroupsPresent.Properties[0], groupConfigs); err != nil { | ||
| return nil, fmt.Errorf("failed to unmarshal host cpugroups: %v", err) | ||
| } | ||
|
|
||
| for _, c := range groupConfigs.CpuGroups { | ||
| if strings.ToLower(c.GroupId) == strings.ToLower(id) { | ||
| return &c, nil | ||
| } | ||
| } | ||
| return nil, fmt.Errorf("no cpugroup exists with id %v", id) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package cpugroup | ||
|
|
||
| import ( | ||
| "context" | ||
| "testing" | ||
|
|
||
| "github.com/Microsoft/go-winio/pkg/guid" | ||
| ) | ||
|
|
||
| // Unit tests for creating and deleting a CPU group on the host | ||
| func TestCPUGroupCreateWithIDAndDelete(t *testing.T) { | ||
| t.Skip("only works on classic/core scheduler, skipping as we can't check this dynamically right now") | ||
|
|
||
| lps := []uint32{0, 1} | ||
| ctx, cancel := context.WithCancel(context.Background()) | ||
| defer cancel() | ||
| id, err := guid.NewV4() | ||
| if err != nil { | ||
| t.Fatalf("failed to create cpugroup guid with: %v", err) | ||
| } | ||
| err = Create(ctx, id.String(), lps) | ||
| if err != nil { | ||
| t.Fatalf("failed to create cpugroup %s with: %v", id.String(), err) | ||
| } | ||
| defer func() { | ||
| if err := Delete(ctx, id.String()); err != nil { | ||
| t.Fatalf("failed to delete cpugroup %s with: %v", id.String(), err) | ||
| } | ||
| }() | ||
|
|
||
| _, err = getCPUGroupConfig(ctx, id.String()) | ||
| if err != nil { | ||
| t.Fatalf("failed to find cpugroup on host with: %v", err) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| /* | ||
| * HCS API | ||
| * | ||
| * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) | ||
| * | ||
| * API version: 2.4 | ||
| * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) | ||
| */ | ||
|
|
||
| package hcsschema | ||
|
|
||
| // CPU groups allow Hyper-V administrators to better manage and allocate the host's CPU resources across guest virtual machines | ||
| type CpuGroup struct { | ||
| Id string `json:"Id,omitempty"` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| /* | ||
| * HCS API | ||
| * | ||
| * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) | ||
| * | ||
| * API version: 2.4 | ||
| * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) | ||
| */ | ||
|
|
||
| package hcsschema | ||
|
|
||
| type CpuGroupAffinity struct { | ||
| LogicalProcessorCount int32 `json:"LogicalProcessorCount,omitempty"` | ||
| LogicalProcessors []int32 `json:"LogicalProcessors,omitempty"` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /* | ||
| * HCS API | ||
| * | ||
| * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) | ||
| * | ||
| * API version: 2.4 | ||
| * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) | ||
| */ | ||
|
|
||
| package hcsschema | ||
|
|
||
| type CpuGroupConfig struct { | ||
| GroupId string `json:"GroupId,omitempty"` | ||
| Affinity *CpuGroupAffinity `json:"Affinity,omitempty"` | ||
| GroupProperties []CpuGroupProperty `json:"GroupProperties,omitempty"` | ||
| // Hypervisor CPU group IDs exposed to clients | ||
| HypervisorGroupId int32 `json:"HypervisorGroupId,omitempty"` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| /* | ||
| * HCS API | ||
| * | ||
| * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) | ||
| * | ||
| * API version: 2.4 | ||
| * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) | ||
| */ | ||
|
|
||
| package hcsschema | ||
|
|
||
| // Structure used to return cpu groups for a Service property query | ||
| type CpuGroupConfigurations struct { | ||
| CpuGroups []CpuGroupConfig `json:"CpuGroups,omitempty"` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /* | ||
| * HCS API | ||
| * | ||
| * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) | ||
| * | ||
| * API version: 2.4 | ||
| * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) | ||
| */ | ||
|
|
||
| package hcsschema | ||
|
|
||
| type CPUGroupOperation string | ||
|
|
||
| const ( | ||
| CreateGroup CPUGroupOperation = "CreateGroup" | ||
| DeleteGroup CPUGroupOperation = "DeleteGroup" | ||
| SetProperty CPUGroupOperation = "SetProperty" | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| /* | ||
| * HCS API | ||
| * | ||
| * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) | ||
| * | ||
| * API version: 2.4 | ||
| * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) | ||
| */ | ||
|
|
||
| package hcsschema | ||
|
|
||
| type CpuGroupProperty struct { | ||
| PropertyCode uint32 `json:"PropertyCode,omitempty"` | ||
| PropertyValue uint32 `json:"PropertyValue,omitempty"` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| /* | ||
| * HCS API | ||
| * | ||
| * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) | ||
| * | ||
| * API version: 2.4 | ||
| * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) | ||
| */ | ||
|
|
||
| package hcsschema | ||
|
|
||
| // Create group operation settings | ||
| type CreateGroupOperation struct { | ||
| GroupId string `json:"GroupId,omitempty"` | ||
| LogicalProcessorCount uint32 `json:"LogicalProcessorCount,omitempty"` | ||
| LogicalProcessors []uint32 `json:"LogicalProcessors,omitempty"` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| /* | ||
| * HCS API | ||
| * | ||
| * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) | ||
| * | ||
| * API version: 2.4 | ||
| * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) | ||
| */ | ||
|
|
||
| package hcsschema | ||
|
|
||
| // Delete group operation settings | ||
| type DeleteGroupOperation struct { | ||
| GroupId string `json:"GroupId,omitempty"` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| /* | ||
| * HCS API | ||
| * | ||
| * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) | ||
| * | ||
| * API version: 2.4 | ||
| * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) | ||
| */ | ||
|
|
||
| package hcsschema | ||
|
|
||
| // Structure used to request a service processor modification | ||
| type HostProcessorModificationRequest struct { | ||
| Operation CPUGroupOperation `json:"Operation,omitempty"` | ||
| OperationDetails interface{} `json:"OperationDetails,omitempty"` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package uvm | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should move out the core CPU groups support into an
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are some standalone pieces that I moved out, but the code that needs to be run in Set/Unset/Release require the uvm package, so I did not move those. Let me know if it looks okay. |
||
|
|
||
| import ( | ||
| "context" | ||
| "errors" | ||
| "fmt" | ||
|
|
||
| "github.com/Microsoft/hcsshim/internal/cpugroup" | ||
| hcsschema "github.com/Microsoft/hcsshim/internal/schema2" | ||
| ) | ||
|
|
||
| // ReleaseCPUGroup unsets the cpugroup from the VM | ||
| func (uvm *UtilityVM) ReleaseCPUGroup(ctx context.Context) error { | ||
| groupID := uvm.cpuGroupID | ||
| if groupID == "" { | ||
| // not set, don't try to do anything | ||
| return nil | ||
| } | ||
| if err := uvm.unsetCPUGroup(ctx); err != nil { | ||
| return fmt.Errorf("failed to remove VM %s from cpugroup %s", uvm.ID(), groupID) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| // SetCPUGroup setups up the cpugroup for the VM with the requested id | ||
| func (uvm *UtilityVM) SetCPUGroup(ctx context.Context, id string) error { | ||
| if id == "" { | ||
| return errors.New("must specify an ID to use when configuring a VM's cpugroup") | ||
| } | ||
| return uvm.setCPUGroup(ctx, id) | ||
| } | ||
|
|
||
| // setCPUGroup sets the VM's cpugroup | ||
| func (uvm *UtilityVM) setCPUGroup(ctx context.Context, id string) error { | ||
|
kevpar marked this conversation as resolved.
|
||
| req := &hcsschema.ModifySettingRequest{ | ||
| ResourcePath: cpuGroupResourcePath, | ||
| Settings: &hcsschema.CpuGroup{ | ||
| Id: id, | ||
| }, | ||
| } | ||
| if err := uvm.modify(ctx, req); err != nil { | ||
| return err | ||
| } | ||
| uvm.cpuGroupID = id | ||
|
anmaxvl marked this conversation as resolved.
|
||
| return nil | ||
| } | ||
|
|
||
| // unsetCPUGroup sets the VM's cpugroup to the null group ID | ||
| // set groupID to 00000000-0000-0000-0000-000000000000 to remove the VM from a cpugroup | ||
| // | ||
| // Since a VM must be moved to the null group before potentially being added to a different | ||
| // cpugroup, that means there may be a segment of time that the VM's cpu usage runs unrestricted. | ||
| func (uvm *UtilityVM) unsetCPUGroup(ctx context.Context) error { | ||
| return uvm.setCPUGroup(ctx, cpugroup.NullGroupID) | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.