Skip to content

Commit

Permalink
Adds minimum h/w version to VirtualMachine CRD
Browse files Browse the repository at this point in the history
Introduces a new field on the VirtualMachine CRD which allows the user
to define the minimum hardware version for the provisioned VM.
The behavior of the field is as follows:
- If the VMClassAsConfig FSS is enabled, it will override the hardware version
  derived from the VMClass's ConfigSpec if it is lower than the minimum version
  field. Otherwise, the value from the ConfigSpec is honored.
- If the VMClassAsConfig FSS is disabled, it will reconfigure the VM post
  creation before the power on operation to ensure that the h/w version is
  atleast set to the minimum version. This means, it can override the hardware
  version of the OVA with a hardware version value lower than this field.

Signed-off-by: Sagar Muchhal <[email protected]>
  • Loading branch information
srm09 committed Nov 9, 2023
1 parent a4d06bd commit 0ad01d5
Show file tree
Hide file tree
Showing 15 changed files with 320 additions and 46 deletions.
47 changes: 47 additions & 0 deletions api/v1alpha1/virtualmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,44 @@ type VirtualMachineSpec struct {

// AdvancedOptions describes a set of optional, advanced options for configuring a VirtualMachine
AdvancedOptions *VirtualMachineAdvancedOptions `json:"advancedOptions,omitempty"`

// MinHardwareVersion specifies the desired minimum hardware version
// for this VM.
//
// Usually the VM's hardware version is derived from:
// 1. the VirtualMachineClass used to deploy the VM provided by the ClassName field
// 2. the datacenter/cluster/host default hardware version
// Setting this field will ensure that the hardware version of the VM
// is at least set to the specified value. To enforce this, it will override
// the value from the VirtualMachineClass.
//
// This field is never updated to reflect the derived hardware version.
// Instead, VirtualMachineStatus.HardwareVersion surfaces
// the observed hardware version.
//
// Please note, setting this field's value to N ensures a VM's hardware
// version is equal to or greater than N. For example, if a VM's observed
// hardware version is 10 and this field's value is 13, then the VM will be
// upgraded to hardware version 13. However, if the observed hardware
// version is 17 and this field's value is 13, no change will occur.
//
// Several features are hardware version dependent, for example:
//
// * NVMe Controllers >= 14
// * Dynamic Direct Path I/O devices >= 17
//
// Please refer to https://kb.vmware.com/s/article/1003746 for a list of VM
// hardware versions.
//
// It is important to remember that a VM's hardware version may not be
// downgraded and upgrading a VM deployed from an image based on an older
// hardware version to a more recent one may result in unpredictable
// behavior. In other words, please be careful when choosing to upgrade a
// VM to a newer hardware version.
//
// +optional
// +kubebuilder:validation:Minimum=13
MinHardwareVersion int32 `json:"minHardwareVersion,omitempty"`
}

// VirtualMachineAdvancedOptions describes a set of optional, advanced options for configuring a VirtualMachine.
Expand Down Expand Up @@ -602,6 +640,15 @@ type VirtualMachineStatus struct {
// LastRestartTime describes the last time the VM was restarted.
// +optional
LastRestartTime *metav1.Time `json:"lastRestartTime,omitempty"`

// HardwareVersion describes the VirtualMachine resource's observed
// hardware version.
//
// Please refer to VirtualMachineSpec.MinHardwareVersion for more
// information on the topic of a VM's hardware version.
//
// +optional
HardwareVersion int32 `json:"hardwareVersion,omitempty"`
}

func (vm *VirtualMachine) GetConditions() Conditions {
Expand Down
49 changes: 48 additions & 1 deletion api/v1alpha2/virtualmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ type VirtualMachineSpec struct {
// +optional
ImageName string `json:"imageName,omitempty"`

// Class describes the name of the VirtualMachineClass resource used to
// ClassName describes the name of the VirtualMachineClass resource used to
// deploy this VM.
//
// This field is optional in the cases where there exists a sensible
Expand Down Expand Up @@ -335,6 +335,44 @@ type VirtualMachineSpec struct {
//
// +optional
Reserved VirtualMachineReservedSpec `json:"reserved,omitempty"`

// MinHardwareVersion specifies the desired minimum hardware version
// for this VM.
//
// Usually the VM's hardware version is derived from:
// 1. the VirtualMachineClass used to deploy the VM provided by the ClassName field
// 2. the datacenter/cluster/host default hardware version
// Setting this field will ensure that the hardware version of the VM
// is at least set to the specified value. To enforce this, it will override
// the value from the VirtualMachineClass.
//
// This field is never updated to reflect the derived hardware version.
// Instead, VirtualMachineStatus.HardwareVersion surfaces
// the observed hardware version.
//
// Please note, setting this field's value to N ensures a VM's hardware
// version is equal to or greater than N. For example, if a VM's observed
// hardware version is 10 and this field's value is 13, then the VM will be
// upgraded to hardware version 13. However, if the observed hardware
// version is 17 and this field's value is 13, no change will occur.
//
// Several features are hardware version dependent, for example:
//
// * NVMe Controllers >= 14
// * Dynamic Direct Path I/O devices >= 17
//
// Please refer to https://kb.vmware.com/s/article/1003746 for a list of VM
// hardware versions.
//
// It is important to remember that a VM's hardware version may not be
// downgraded and upgrading a VM deployed from an image based on an older
// hardware version to a more recent one may result in unpredictable
// behavior. In other words, please be careful when choosing to upgrade a
// VM to a newer hardware version.
//
// +optional
// +kubebuilder:validation:Minimum=13
MinHardwareVersion int32 `json:"minHardwareVersion,omitempty"`
}

// VirtualMachineReservedSpec describes a set of VM configuration options
Expand Down Expand Up @@ -455,6 +493,15 @@ type VirtualMachineStatus struct {
//
// +optional
LastRestartTime *metav1.Time `json:"lastRestartTime,omitempty"`

// HardwareVersion describes the VirtualMachine resource's observed
// hardware version.
//
// Please refer to VirtualMachineSpec.MinHardwareVersion for more
// information on the topic of a VM's hardware version.
//
// +optional
HardwareVersion int32 `json:"hardwareVersion,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
68 changes: 67 additions & 1 deletion config/crd/bases/vmoperator.vmware.com_virtualmachines.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,33 @@ spec:
be introspected to discover identifying attributes that may help
users to identify the desired image to use.
type: string
minHardwareVersion:
description: "MinHardwareVersion specifies the desired minimum hardware
version for this VM. \n Usually the VM's hardware version is derived
from: 1. the VirtualMachineClass used to deploy the VM provided
by the ClassName field 2. the datacenter/cluster/host default hardware
version Setting this field will ensure that the hardware version
of the VM is at least set to the specified value. To enforce this,
it will override the value from the VirtualMachineClass. \n This
field is never updated to reflect the derived hardware version.
Instead, VirtualMachineStatus.HardwareVersion surfaces the observed
hardware version. \n Please note, setting this field's value to
N ensures a VM's hardware version is equal to or greater than N.
For example, if a VM's observed hardware version is 10 and this
field's value is 13, then the VM will be upgraded to hardware version
13. However, if the observed hardware version is 17 and this field's
value is 13, no change will occur. \n Several features are hardware
version dependent, for example: \n * NVMe Controllers \t\t
>= 14 * Dynamic Direct Path I/O devices >= 17 \n Please refer to
https://kb.vmware.com/s/article/1003746 for a list of VM hardware
versions. \n It is important to remember that a VM's hardware version
may not be downgraded and upgrading a VM deployed from an image
based on an older hardware version to a more recent one may result
in unpredictable behavior. In other words, please be careful when
choosing to upgrade a VM to a newer hardware version."
format: int32
minimum: 13
type: integer
networkInterfaces:
description: NetworkInterfaces describes a list of VirtualMachineNetworkInterfaces
to be configured on the VirtualMachine instance. Each of these VirtualMachineNetworkInterfaces
Expand Down Expand Up @@ -494,6 +521,12 @@ spec:
- type
type: object
type: array
hardwareVersion:
description: "HardwareVersion describes the VirtualMachine resource's
observed hardware version. \n Please refer to VirtualMachineSpec.MinHardwareVersion
for more information on the topic of a VM's hardware version."
format: int32
type: integer
host:
description: Host describes the hostname or IP address of the infrastructure
host that the VirtualMachine is executing on.
Expand Down Expand Up @@ -1500,7 +1533,7 @@ spec:
type: object
type: object
className:
description: "Class describes the name of the VirtualMachineClass
description: "ClassName describes the name of the VirtualMachineClass
resource used to deploy this VM. \n This field is optional in the
cases where there exists a sensible default value, such as when
there is a single VirtualMachineClass resource available in the
Expand All @@ -1518,6 +1551,33 @@ spec:
default value, such as when there is a single VirtualMachineImage
resource available in the same Namespace as the VM being deployed."
type: string
minHardwareVersion:
description: "MinHardwareVersion specifies the desired minimum hardware
version for this VM. \n Usually the VM's hardware version is derived
from: 1. the VirtualMachineClass used to deploy the VM provided
by the ClassName field 2. the datacenter/cluster/host default hardware
version Setting this field will ensure that the hardware version
of the VM is at least set to the specified value. To enforce this,
it will override the value from the VirtualMachineClass. \n This
field is never updated to reflect the derived hardware version.
Instead, VirtualMachineStatus.HardwareVersion surfaces the observed
hardware version. \n Please note, setting this field's value to
N ensures a VM's hardware version is equal to or greater than N.
For example, if a VM's observed hardware version is 10 and this
field's value is 13, then the VM will be upgraded to hardware version
13. However, if the observed hardware version is 17 and this field's
value is 13, no change will occur. \n Several features are hardware
version dependent, for example: \n * NVMe Controllers \t\t
>= 14 * Dynamic Direct Path I/O devices >= 17 \n Please refer to
https://kb.vmware.com/s/article/1003746 for a list of VM hardware
versions. \n It is important to remember that a VM's hardware version
may not be downgraded and upgrading a VM deployed from an image
based on an older hardware version to a more recent one may result
in unpredictable behavior. In other words, please be careful when
choosing to upgrade a VM to a newer hardware version."
format: int32
minimum: 13
type: integer
network:
description: "Network describes the desired network configuration
for the VM. \n Please note this value may be omitted entirely and
Expand Down Expand Up @@ -2203,6 +2263,12 @@ spec:
- type
type: object
type: array
hardwareVersion:
description: "HardwareVersion describes the VirtualMachine resource's
observed hardware version. \n Please refer to VirtualMachineSpec.MinHardwareVersion
for more information on the topic of a VM's hardware version."
format: int32
type: integer
host:
description: Host describes the hostname or IP address of the infrastructure
host where the VM is executed.
Expand Down
18 changes: 18 additions & 0 deletions pkg/util/configspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package util

import (
"bytes"
"fmt"
"reflect"

"github.com/vmware/govmomi/vim25"
Expand Down Expand Up @@ -215,3 +216,20 @@ func MergeExtraConfig(extraConfig []vimTypes.BaseOptionValue, newMap map[string]
}
return merged
}

// EnsureMinHardwareVersionInConfigSpec ensures that the hardware version in the ConfigSpec
// is at least equal to the passed minimum hardware version value.
func EnsureMinHardwareVersionInConfigSpec(configSpec *vimTypes.VirtualMachineConfigSpec, minVersion int32) {
if minVersion == 0 {
return
}

configSpecHwVersion := int32(0)
if configSpec.Version != "" {
configSpecHwVersion = ParseVirtualHardwareVersion(configSpec.Version)
}
if minVersion > configSpecHwVersion {
configSpecHwVersion = minVersion
}
configSpec.Version = fmt.Sprintf("vmx-%d", configSpecHwVersion)
}
39 changes: 39 additions & 0 deletions pkg/util/configspec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,45 @@ var _ = Describe("ConfigSpec Util", func() {
Expect(cmp.Diff(cs2, cs3)).To(BeEmpty())
})
})

Context("EnsureMinHardwareVersionInConfigSpec", func() {
When("minimum hardware version is unset", func() {
It("does not change the existing value of the configSpec's version", func() {
configSpec := &vimTypes.VirtualMachineConfigSpec{Version: "vmx-15"}
util.EnsureMinHardwareVersionInConfigSpec(configSpec, 0)

Expect(configSpec.Version).To(Equal("vmx-15"))
})

It("does not set the configSpec's version", func() {
configSpec := &vimTypes.VirtualMachineConfigSpec{}
util.EnsureMinHardwareVersionInConfigSpec(configSpec, 0)

Expect(configSpec.Version).To(BeEmpty())
})
})

It("overrides the hardware version if the existing version is lesser", func() {
configSpec := &vimTypes.VirtualMachineConfigSpec{Version: "vmx-15"}
util.EnsureMinHardwareVersionInConfigSpec(configSpec, 17)

Expect(configSpec.Version).To(Equal("vmx-17"))
})

It("sets the hardware version if the existing version is unset", func() {
configSpec := &vimTypes.VirtualMachineConfigSpec{}
util.EnsureMinHardwareVersionInConfigSpec(configSpec, 16)

Expect(configSpec.Version).To(Equal("vmx-16"))
})

It("overrides the hardware version if the existing version is set incorrectly", func() {
configSpec := &vimTypes.VirtualMachineConfigSpec{Version: "foo"}
util.EnsureMinHardwareVersionInConfigSpec(configSpec, 17)

Expect(configSpec.Version).To(Equal("vmx-17"))
})
})
})

var _ = Describe("RemoveDevicesFromConfigSpec", func() {
Expand Down
29 changes: 29 additions & 0 deletions pkg/util/hardware_version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2023 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package util

import (
"regexp"
"strconv"
)

var vmxRe = regexp.MustCompile(`vmx-(\d+)`)

// ParseVirtualHardwareVersion parses the virtual hardware version
// For eg. "vmx-15" returns 15.
func ParseVirtualHardwareVersion(vmxVersion string) int32 {
// obj matches the full string and the submatch (\d+)
// and return a []string with values
obj := vmxRe.FindStringSubmatch(vmxVersion)
if len(obj) != 2 {
return 0
}

version, err := strconv.ParseInt(obj[1], 10, 32)
if err != nil {
return 0
}

return int32(version)
}
28 changes: 28 additions & 0 deletions pkg/util/hardware_version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2023 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package util_test

import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"github.com/vmware-tanzu/vm-operator/pkg/util"
)

var _ = Describe("ParseVirtualHardwareVersion", func() {
It("empty hardware string", func() {
vmxHwVersionString := ""
Expect(util.ParseVirtualHardwareVersion(vmxHwVersionString)).To(BeZero())
})

It("invalid hardware string", func() {
vmxHwVersionString := "blah"
Expect(util.ParseVirtualHardwareVersion(vmxHwVersionString)).To(BeZero())
})

It("valid hardware version string eg. vmx-15", func() {
vmxHwVersionString := "vmx-15"
Expect(util.ParseVirtualHardwareVersion(vmxHwVersionString)).To(Equal(int32(15)))
})
})
Loading

0 comments on commit 0ad01d5

Please sign in to comment.