mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
provider/vsphere: added update function with support for vcpu and memory (#6356)
* added update function with support for vcpu and memory * waiting for vmware tools redundant with WaitForIP * proper error handling of PowerOn task * added test cases for update memory and vcpu * reboot flag
This commit is contained in:
parent
b005709ed1
commit
bb73c74414
@ -105,6 +105,7 @@ func resourceVSphereVirtualMachine() *schema.Resource {
|
|||||||
return &schema.Resource{
|
return &schema.Resource{
|
||||||
Create: resourceVSphereVirtualMachineCreate,
|
Create: resourceVSphereVirtualMachineCreate,
|
||||||
Read: resourceVSphereVirtualMachineRead,
|
Read: resourceVSphereVirtualMachineRead,
|
||||||
|
Update: resourceVSphereVirtualMachineUpdate,
|
||||||
Delete: resourceVSphereVirtualMachineDelete,
|
Delete: resourceVSphereVirtualMachineDelete,
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
@ -123,13 +124,11 @@ func resourceVSphereVirtualMachine() *schema.Resource {
|
|||||||
"vcpu": &schema.Schema{
|
"vcpu": &schema.Schema{
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"memory": &schema.Schema{
|
"memory": &schema.Schema{
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"memory_reservation": &schema.Schema{
|
"memory_reservation": &schema.Schema{
|
||||||
@ -401,6 +400,93 @@ func resourceVSphereVirtualMachine() *schema.Resource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resourceVSphereVirtualMachineUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
// flag if changes have to be applied
|
||||||
|
hasChanges := false
|
||||||
|
// flag if changes have to be done when powered off
|
||||||
|
rebootRequired := false
|
||||||
|
|
||||||
|
// make config spec
|
||||||
|
configSpec := types.VirtualMachineConfigSpec{}
|
||||||
|
|
||||||
|
if d.HasChange("vcpu") {
|
||||||
|
configSpec.NumCPUs = d.Get("vcpu").(int)
|
||||||
|
hasChanges = true
|
||||||
|
rebootRequired = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("memory") {
|
||||||
|
configSpec.MemoryMB = int64(d.Get("memory").(int))
|
||||||
|
hasChanges = true
|
||||||
|
rebootRequired = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// do nothing if there are no changes
|
||||||
|
if !hasChanges {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
client := meta.(*govmomi.Client)
|
||||||
|
dc, err := getDatacenter(client, d.Get("datacenter").(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
finder := find.NewFinder(client.Client, true)
|
||||||
|
finder = finder.SetDatacenter(dc)
|
||||||
|
|
||||||
|
vm, err := finder.VirtualMachine(context.TODO(), vmPath(d.Get("folder").(string), d.Get("name").(string)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Printf("[DEBUG] virtual machine config spec: %v", configSpec)
|
||||||
|
|
||||||
|
if rebootRequired {
|
||||||
|
log.Printf("[INFO] Shutting down virtual machine: %s", d.Id())
|
||||||
|
|
||||||
|
task, err := vm.PowerOff(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = task.Wait(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[INFO] Reconfiguring virtual machine: %s", d.Id())
|
||||||
|
|
||||||
|
task, err := vm.Reconfigure(context.TODO(), configSpec)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = task.Wait(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rebootRequired {
|
||||||
|
task, err = vm.PowerOn(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = task.Wait(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ip, err := vm.WaitForIP(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Printf("[DEBUG] ip address: %v", ip)
|
||||||
|
|
||||||
|
return resourceVSphereVirtualMachineRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*govmomi.Client)
|
client := meta.(*govmomi.Client)
|
||||||
|
|
||||||
|
@ -517,6 +517,168 @@ func TestAccVSphereVirtualMachine_createWithExistingVmdk(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccVSphereVirtualMachine_updateMemory(t *testing.T) {
|
||||||
|
var vm virtualMachine
|
||||||
|
var locationOpt string
|
||||||
|
var datastoreOpt string
|
||||||
|
|
||||||
|
if v := os.Getenv("VSPHERE_DATACENTER"); v != "" {
|
||||||
|
locationOpt += fmt.Sprintf(" datacenter = \"%s\"\n", v)
|
||||||
|
}
|
||||||
|
if v := os.Getenv("VSPHERE_CLUSTER"); v != "" {
|
||||||
|
locationOpt += fmt.Sprintf(" cluster = \"%s\"\n", v)
|
||||||
|
}
|
||||||
|
if v := os.Getenv("VSPHERE_RESOURCE_POOL"); v != "" {
|
||||||
|
locationOpt += fmt.Sprintf(" resource_pool = \"%s\"\n", v)
|
||||||
|
}
|
||||||
|
if v := os.Getenv("VSPHERE_DATASTORE"); v != "" {
|
||||||
|
datastoreOpt = fmt.Sprintf(" datastore = \"%s\"\n", v)
|
||||||
|
}
|
||||||
|
template := os.Getenv("VSPHERE_TEMPLATE")
|
||||||
|
label := os.Getenv("VSPHERE_NETWORK_LABEL_DHCP")
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(
|
||||||
|
testAccCheckVSphereVirtualMachineConfig_updateMemoryInitial,
|
||||||
|
locationOpt,
|
||||||
|
label,
|
||||||
|
datastoreOpt,
|
||||||
|
template,
|
||||||
|
),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckVSphereVirtualMachineExists("vsphere_virtual_machine.bar", &vm),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "name", "terraform-test"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "vcpu", "2"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "memory", "4096"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "disk.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "disk.0.template", template),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "network_interface.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "network_interface.0.label", label),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(
|
||||||
|
testAccCheckVSphereVirtualMachineConfig_updateMemoryUpdate,
|
||||||
|
locationOpt,
|
||||||
|
label,
|
||||||
|
datastoreOpt,
|
||||||
|
template,
|
||||||
|
),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckVSphereVirtualMachineExists("vsphere_virtual_machine.bar", &vm),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "name", "terraform-test"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "vcpu", "2"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "memory", "2048"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "disk.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "disk.0.template", template),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "network_interface.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "network_interface.0.label", label),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccVSphereVirtualMachine_updateVcpu(t *testing.T) {
|
||||||
|
var vm virtualMachine
|
||||||
|
var locationOpt string
|
||||||
|
var datastoreOpt string
|
||||||
|
|
||||||
|
if v := os.Getenv("VSPHERE_DATACENTER"); v != "" {
|
||||||
|
locationOpt += fmt.Sprintf(" datacenter = \"%s\"\n", v)
|
||||||
|
}
|
||||||
|
if v := os.Getenv("VSPHERE_CLUSTER"); v != "" {
|
||||||
|
locationOpt += fmt.Sprintf(" cluster = \"%s\"\n", v)
|
||||||
|
}
|
||||||
|
if v := os.Getenv("VSPHERE_RESOURCE_POOL"); v != "" {
|
||||||
|
locationOpt += fmt.Sprintf(" resource_pool = \"%s\"\n", v)
|
||||||
|
}
|
||||||
|
if v := os.Getenv("VSPHERE_DATASTORE"); v != "" {
|
||||||
|
datastoreOpt = fmt.Sprintf(" datastore = \"%s\"\n", v)
|
||||||
|
}
|
||||||
|
template := os.Getenv("VSPHERE_TEMPLATE")
|
||||||
|
label := os.Getenv("VSPHERE_NETWORK_LABEL_DHCP")
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(
|
||||||
|
testAccCheckVSphereVirtualMachineConfig_updateVcpuInitial,
|
||||||
|
locationOpt,
|
||||||
|
label,
|
||||||
|
datastoreOpt,
|
||||||
|
template,
|
||||||
|
),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckVSphereVirtualMachineExists("vsphere_virtual_machine.bar", &vm),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "name", "terraform-test"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "vcpu", "2"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "memory", "4096"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "disk.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "disk.0.template", template),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "network_interface.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "network_interface.0.label", label),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(
|
||||||
|
testAccCheckVSphereVirtualMachineConfig_updateVcpuUpdate,
|
||||||
|
locationOpt,
|
||||||
|
label,
|
||||||
|
datastoreOpt,
|
||||||
|
template,
|
||||||
|
),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckVSphereVirtualMachineExists("vsphere_virtual_machine.bar", &vm),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "name", "terraform-test"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "vcpu", "4"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "memory", "4096"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "disk.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "disk.0.template", template),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "network_interface.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"vsphere_virtual_machine.bar", "network_interface.0.label", label),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error {
|
func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error {
|
||||||
client := testAccProvider.Meta().(*govmomi.Client)
|
client := testAccProvider.Meta().(*govmomi.Client)
|
||||||
finder := find.NewFinder(client.Client, true)
|
finder := find.NewFinder(client.Client, true)
|
||||||
@ -853,3 +1015,67 @@ resource "vsphere_virtual_machine" "with_existing_vmdk" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const testAccCheckVSphereVirtualMachineConfig_updateMemoryInitial = `
|
||||||
|
resource "vsphere_virtual_machine" "bar" {
|
||||||
|
name = "terraform-test"
|
||||||
|
%s
|
||||||
|
vcpu = 2
|
||||||
|
memory = 4096
|
||||||
|
network_interface {
|
||||||
|
label = "%s"
|
||||||
|
}
|
||||||
|
disk {
|
||||||
|
%s
|
||||||
|
template = "%s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccCheckVSphereVirtualMachineConfig_updateMemoryUpdate = `
|
||||||
|
resource "vsphere_virtual_machine" "bar" {
|
||||||
|
name = "terraform-test"
|
||||||
|
%s
|
||||||
|
vcpu = 2
|
||||||
|
memory = 2048
|
||||||
|
network_interface {
|
||||||
|
label = "%s"
|
||||||
|
}
|
||||||
|
disk {
|
||||||
|
%s
|
||||||
|
template = "%s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccCheckVSphereVirtualMachineConfig_updateVcpuInitial = `
|
||||||
|
resource "vsphere_virtual_machine" "bar" {
|
||||||
|
name = "terraform-test"
|
||||||
|
%s
|
||||||
|
vcpu = 2
|
||||||
|
memory = 4096
|
||||||
|
network_interface {
|
||||||
|
label = "%s"
|
||||||
|
}
|
||||||
|
disk {
|
||||||
|
%s
|
||||||
|
template = "%s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccCheckVSphereVirtualMachineConfig_updateVcpuUpdate = `
|
||||||
|
resource "vsphere_virtual_machine" "bar" {
|
||||||
|
name = "terraform-test"
|
||||||
|
%s
|
||||||
|
vcpu = 4
|
||||||
|
memory = 4096
|
||||||
|
network_interface {
|
||||||
|
label = "%s"
|
||||||
|
}
|
||||||
|
disk {
|
||||||
|
%s
|
||||||
|
template = "%s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
Loading…
Reference in New Issue
Block a user