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

r/vm: Support hardware versions #1020

Merged
merged 2 commits into from
Apr 3, 2020
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
51 changes: 0 additions & 51 deletions go.sum

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions vsphere/internal/helper/virtualmachine/virtual_machine_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/vmware/govmomi/vapi/vcenter"
"log"
"net"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -865,3 +866,60 @@ func (r MOIDForUUIDResults) UUIDs() []string {
}
return uuids
}

// GetHardwareVersionID gets the hardware version string from integer
func GetHardwareVersionID(vint int) string {
// hardware_version isn't set, so return an empty string.
if vint == 0 {
return ""
}
return fmt.Sprintf("vmx-%d", vint)
}

// GetHardwareVersionNumber gets the hardware version number from string.
func GetHardwareVersionNumber(vstring string) int {
vstring = strings.TrimPrefix(vstring, "vmx-")
v, err := strconv.Atoi(vstring)
if err != nil {
log.Printf("[DEBUG] Unable to parse hardware version: %s", vstring)
}
return v
}

// SetHardwareVersion sets the virtual machine's hardware version. The virtual
// machine must be powered off, and the version can only be increased.
func SetHardwareVersion(vm *object.VirtualMachine, target int) error {
// First get current and target versions and validate
tv := GetHardwareVersionID(target)
vprops, err := Properties(vm)
if err != nil {
return err
}
cv := vprops.Config.Version
// Skip the rest if there is no version change.
if cv == tv {
return nil
}
if err := ValidateHardwareVersion(GetHardwareVersionNumber(cv), target); err != nil {
return err
}

ctx, cancel := context.WithTimeout(context.Background(), provider.DefaultAPITimeout)
defer cancel()

task, err := vm.UpgradeVM(ctx, tv)
_, err = task.WaitForResult(ctx, nil)
return err
}

// ValidateHardwareVersion checks that the target hardware version is equal to
// or greater than the current hardware version.
func ValidateHardwareVersion(current, target int) error {
switch {
case target == 0:
return nil
case target < current:
return fmt.Errorf("Cannot downgrade virtual machine hardware version. current: %d, target: %d", current, target)
}
return nil
}
23 changes: 23 additions & 0 deletions vsphere/resource_vsphere_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,11 @@ func resourceVSphereVirtualMachineUpdate(d *schema.ResourceData, meta interface{
return err
}
// Only carry out the reconfigure if we actually have a change to process.
cv := virtualmachine.GetHardwareVersionNumber(vprops.Config.Version)
tv := d.Get("hardware_version").(int)
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the default value if there is no hardware version set? 0 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct. The default value is 0.

if tv > cv {
d.Set("reboot_required", true)
}
if changed || len(spec.DeviceChange) > 0 {
//Check to see if we need to shutdown the VM for this process.
if d.Get("reboot_required").(bool) && vprops.Runtime.PowerState != types.VirtualMachinePowerStatePoweredOff {
Expand Down Expand Up @@ -668,6 +673,12 @@ func resourceVSphereVirtualMachineUpdate(d *schema.ResourceData, meta interface{
err = virtualmachine.Reconfigure(vm, spec)
}

// Upgrade the VM's hardware version if needed.
err = virtualmachine.SetHardwareVersion(vm, d.Get("hardware_version").(int))
if err != nil {
return err
}

// Regardless of the result we no longer need to watch for pending questions.
gChan <- true

Expand Down Expand Up @@ -711,6 +722,7 @@ func resourceVSphereVirtualMachineUpdate(d *schema.ResourceData, meta interface{
}
}
}

// Now safe to turn off partial mode.
d.Partial(false)
d.Set("reboot_required", false)
Expand Down Expand Up @@ -886,6 +898,11 @@ func resourceVSphereVirtualMachineCustomizeDiff(d *schema.ResourceDiff, meta int
}
}
}

// Validate hardware version changes.
cv, tv := d.GetChange("hardware_version")
virtualmachine.ValidateHardwareVersion(cv.(int), tv.(int))

// Validate that the config has the necessary components for vApp support.
// Note that for clones the data is prepopulated in
// ValidateVirtualMachineClone.
Expand Down Expand Up @@ -1376,6 +1393,12 @@ func resourceVSphereVirtualMachineCreateClone(d *schema.ResourceData, meta inter
)
}

// Upgrade the VM's hardware version if needed.
err = virtualmachine.SetHardwareVersion(vm, d.Get("hardware_version").(int))
if err != nil {
return nil, err
}

var cw *virtualMachineCustomizationWaiter
// Send customization spec if any has been defined.
if len(d.Get("clone.0.customize").([]interface{})) > 0 {
Expand Down
Loading