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

Adding ballooning support #207

Merged
1 commit merged into from
May 25, 2022
Merged
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
6 changes: 4 additions & 2 deletions util_test_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"math/rand"
"os"
"strings"
"regexp"
"testing"
"time"

Expand Down Expand Up @@ -436,8 +436,10 @@ type testHelper struct {
username string
}

var resourceNameRe = regexp.MustCompile(`[^a-zA-Z\d_.-]`)

func (t *testHelper) GenerateTestResourceName(test *testing.T) string {
return strings.ReplaceAll(fmt.Sprintf("%s-%s", test.Name(), t.GenerateRandomID(5)), "/", "_")
return resourceNameRe.ReplaceAllString(fmt.Sprintf("%s-%s", test.Name(), t.GenerateRandomID(5)), "_")
}

func (t *testHelper) GetUsername() string {
Expand Down
72 changes: 54 additions & 18 deletions vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,8 @@ type VMData interface {
CPU() VMCPU
// Memory return the Memory of a VM in Bytes.
Memory() int64
// MemoryPolicy returns the memory policy set on the VM, if any. The second parameter returned is true if the
// memory policy is set.
MemoryPolicy() (MemoryPolicy, bool)
// MemoryPolicy returns the memory policy set on the VM.
MemoryPolicy() MemoryPolicy
// TagIDs returns a list of tags for this VM.
TagIDs() []TagID
// HugePages returns the hugepage settings for the VM, if any.
Expand Down Expand Up @@ -1120,6 +1119,7 @@ func (v vmPlacementPolicyParameters) MustWithHostIDs(hostIDs []HostID) Buildable
type MemoryPolicyParameters interface {
Guaranteed() *int64
Max() *int64
Ballooning() *bool
}

// BuildableMemoryPolicyParameters is a buildable version of MemoryPolicyParameters.
Expand All @@ -1131,6 +1131,9 @@ type BuildableMemoryPolicyParameters interface {

WithMax(max int64) (BuildableMemoryPolicyParameters, error)
MustWithMax(max int64) BuildableMemoryPolicyParameters

WithBallooning(ballooning bool) (BuildableMemoryPolicyParameters, error)
MustWithBallooning(ballooning bool) BuildableMemoryPolicyParameters
}

// NewMemoryPolicyParameters creates a new instance of BuildableMemoryPolicyParameters.
Expand All @@ -1141,6 +1144,24 @@ func NewMemoryPolicyParameters() BuildableMemoryPolicyParameters {
type memoryPolicyParameters struct {
guaranteed *int64
max *int64
ballooning *bool
}

func (m *memoryPolicyParameters) Ballooning() *bool {
return m.ballooning
}

func (m *memoryPolicyParameters) WithBallooning(ballooning bool) (BuildableMemoryPolicyParameters, error) {
m.ballooning = &ballooning
return m, nil
}

func (m *memoryPolicyParameters) MustWithBallooning(ballooning bool) BuildableMemoryPolicyParameters {
builder, err := m.WithBallooning(ballooning)
if err != nil {
panic(err)
}
return builder
}

func (m *memoryPolicyParameters) MustWithGuaranteed(guaranteed int64) BuildableMemoryPolicyParameters {
Expand Down Expand Up @@ -1183,11 +1204,18 @@ type MemoryPolicy interface {
Guaranteed() *int64
// Max returns the maximum amount of memory given to the VM.
Max() *int64
// Ballooning returns true if the VM can give back the memory it is not using to the host OS.
Ballooning() bool
}

type memoryPolicy struct {
guaranteed *int64
max *int64
ballooning bool
}

func (m memoryPolicy) Ballooning() bool {
return m.ballooning
}

func (m memoryPolicy) Max() *int64 {
Expand Down Expand Up @@ -1806,8 +1834,8 @@ func (v *vm) PlacementPolicy() (VMPlacementPolicy, bool) {
return v.placementPolicy, v.placementPolicy != nil
}

func (v *vm) MemoryPolicy() (MemoryPolicy, bool) {
return v.memoryPolicy, v.memoryPolicy != nil
func (v *vm) MemoryPolicy() MemoryPolicy {
return v.memoryPolicy
}

func (v *vm) WaitForIPAddresses(params VMIPSearchParams, retries ...RetryStrategy) (map[string][]net.IP, error) {
Expand Down Expand Up @@ -2080,21 +2108,29 @@ func vmInstanceTypeIDConverter(object *ovirtsdk.Vm, v *vm) error {
}

func vmMemoryPolicyConverter(object *ovirtsdk.Vm, v *vm) error {
if memPolicy, ok := object.MemoryPolicy(); ok {
resultMemPolicy := &memoryPolicy{}
if guaranteed, ok := memPolicy.Guaranteed(); ok {
if guaranteed < -1 {
return newError(
EBug,
"the engine returned a negative guaranteed memory value for VM %s (%d)",
object.MustId(),
guaranteed,
)
}
resultMemPolicy.guaranteed = &guaranteed
memPolicy, ok := object.MemoryPolicy()
if !ok {
return newFieldNotFound("vm", "memory policy")
}
resultMemPolicy := &memoryPolicy{}
if guaranteed, ok := memPolicy.Guaranteed(); ok {
if guaranteed < -1 {
return newError(
EBug,
"the engine returned a negative guaranteed memory value for VM %s (%d)",
object.MustId(),
guaranteed,
)
}
v.memoryPolicy = resultMemPolicy
resultMemPolicy.guaranteed = &guaranteed
}
if max, ok := memPolicy.Max(); ok {
resultMemPolicy.max = &max
}
if ballooning, ok := memPolicy.Ballooning(); ok {
resultMemPolicy.ballooning = ballooning
}
v.memoryPolicy = resultMemPolicy
return nil
}

Expand Down
20 changes: 12 additions & 8 deletions vm_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ func vmBuilderMemoryPolicy(params OptionalVMParameters, builder *ovirtsdk.VmBuil
if max := (*memPolicyParams).Max(); max != nil {
memoryPolicyBuilder.Max(*max)
}
if ballooning := (*memPolicyParams).Ballooning(); ballooning != nil {
memoryPolicyBuilder.Ballooning(*ballooning)
}
builder.MemoryPolicyBuilder(memoryPolicyBuilder)
}
}
Expand Down Expand Up @@ -412,19 +415,20 @@ func (m *mockClient) createVMMemory(params OptionalVMParameters) int64 {
}

func (m *mockClient) createVMMemoryPolicy(params OptionalVMParameters) *memoryPolicy {
var memPolicy *memoryPolicy
memPolicy := &memoryPolicy{
ballooning: true,
}
if memoryPolicyParams := params.MemoryPolicy(); memoryPolicyParams != nil {
var guaranteed *int64
if guaranteedMemory := (*memoryPolicyParams).Guaranteed(); guaranteedMemory != nil {
guaranteed = guaranteedMemory
memPolicy.guaranteed = guaranteedMemory
}
var max *int64

if maxMemory := (*memoryPolicyParams).Max(); maxMemory != nil {
max = maxMemory
memPolicy.max = maxMemory
}
memPolicy = &memoryPolicy{
guaranteed,
max,

if memBallooning := (*memoryPolicyParams).Ballooning(); memBallooning != nil {
memPolicy.ballooning = *memBallooning
}
}
return memPolicy
Expand Down
78 changes: 70 additions & 8 deletions vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,22 @@ func TestVMCreationWithSparseDisks(t *testing.T) {
)
}

func TestMemoryPolicyDefaults(t *testing.T) {
helper := getHelper(t)
vm := assertCanCreateVM(
t,
helper,
helper.GenerateTestResourceName(t),
nil,
)
// Test if memory policy is correctly set
memoryPolicy := vm.MemoryPolicy()
if memoryPolicy == nil {
t.Fatalf("Memory policy was not set.")
}

}

func TestGuaranteedMemory(t *testing.T) {
helper := getHelper(t)
expectedGuaranteed := int64(2 * 1024 * 1024 * 1024)
Expand All @@ -486,10 +502,7 @@ func TestGuaranteedMemory(t *testing.T) {
MustWithGuaranteed(expectedGuaranteed),
).MustWithMemory(expectedGuaranteed),
)
memoryPolicy, ok := vm.MemoryPolicy()
if !ok {
t.Fatalf("Memory policy is not set on VM.")
}
memoryPolicy := vm.MemoryPolicy()
guaranteed := memoryPolicy.Guaranteed()
if guaranteed == nil {
t.Fatalf("Guaranteed memory is not set on VM.")
Expand All @@ -514,10 +527,7 @@ func TestMaxMemory(t *testing.T) {
MustWithMax(expectedMax),
).MustWithMemory(expectedMax),
)
memoryPolicy, ok := vm.MemoryPolicy()
if !ok {
t.Fatalf("Memory policy is not set on VM.")
}
memoryPolicy := vm.MemoryPolicy()
max := memoryPolicy.Max()
if max == nil {
t.Fatalf("Guaranteed memory is not set on VM.")
Expand All @@ -527,6 +537,58 @@ func TestMaxMemory(t *testing.T) {
}
}

func TestBallooning(t *testing.T) {
truePointer := true
falsePointer := false
testCases := []struct {
name string
set *bool
expected bool
}{
{
"empty",
nil,
true,
},
{
"true",
&truePointer,
true,
},
{
"false",
&falsePointer,
false,
},
}

for _, testCase := range testCases {
t.Run(fmt.Sprintf("ballooning=%s", testCase.name), func(t *testing.T) {
helper := getHelper(t)
params := ovirtclient.NewCreateVMParams()
if testCase.set != nil {
params = params.WithMemoryPolicy(
ovirtclient.
NewMemoryPolicyParameters().
MustWithBallooning(*testCase.set),
)
}
vm := assertCanCreateVM(
t,
helper,
helper.GenerateTestResourceName(t),
params,
)
memoryPolicy := vm.MemoryPolicy()
ballooning := memoryPolicy.Ballooning()
if ballooning != testCase.expected {
t.Fatalf("Incorrect ballooning value")
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: If we make this Fatalf more expressive, it'll be easier to figure out what is wrong. E.g.

t.Fatalf("Expected balooning value to be %t, but got %t", testCase.expected, balooning)

}
})
}

}

func checkVMDiskSparseness(t *testing.T, checkVM ovirtclient.VM, sparse bool, message string) {
t.Helper()
diskAttachments, err := checkVM.ListDiskAttachments()
Expand Down