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{
|
||||
Create: resourceVSphereVirtualMachineCreate,
|
||||
Read: resourceVSphereVirtualMachineRead,
|
||||
Update: resourceVSphereVirtualMachineUpdate,
|
||||
Delete: resourceVSphereVirtualMachineDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
|
@ -123,13 +124,11 @@ func resourceVSphereVirtualMachine() *schema.Resource {
|
|||
"vcpu": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"memory": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"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 {
|
||||
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 {
|
||||
client := testAccProvider.Meta().(*govmomi.Client)
|
||||
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