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

Add vm.ConsolidateDisks and vm.ConsolidateDisksAsync #650

Merged
merged 3 commits into from
Feb 22, 2024
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
2 changes: 2 additions & 0 deletions .changes/v2.23.0/650-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Add support for VM disk consolidation using `vm.ConsolidateDisksAsync` and `vm.ConsolidateDisks`
[GH-650]
19 changes: 19 additions & 0 deletions govcd/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2056,3 +2056,22 @@ func (vm *VM) ChangeCPUAndCoreCount(cpus, cpuCores *int) error {
}
return nil
}

// ConsolidateDisksAsync triggers VM disk consolidation task
func (vm *VM) ConsolidateDisksAsync() (Task, error) {
if vm.VM.HREF == "" {
return Task{}, fmt.Errorf("cannot consolidate disks, VM HREF is unset")
}

return vm.client.ExecuteTaskRequest(vm.VM.HREF+"/action/consolidate", http.MethodPost,
types.AnyXMLMime, "error consolidating VM disks: %s", nil)
}

// ConsolidateDisks triggers VM disk consolidation task and waits until it is completed
func (vm *VM) ConsolidateDisks() error {
task, err := vm.ConsolidateDisksAsync()
if err != nil {
return err
}
return task.WaitTaskCompletion()
}
101 changes: 100 additions & 1 deletion govcd/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1995,6 +1995,10 @@ func createNsxtVAppAndVm(vcd *TestVCD, check *C) (*VApp, *VM) {
check.Assert(err, IsNil)
check.Assert(vapptemplate.VAppTemplate.Children.VM[0].HREF, NotNil)

return createNsxtVAppAndVmFromCustomTemplate(vcd, check, &vapptemplate)
}

func createNsxtVAppAndVmFromCustomTemplate(vcd *TestVCD, check *C, vapptemplate *VAppTemplate) (*VApp, *VM) {
vapp, err := vcd.nsxtVdc.CreateRawVApp(check.TestName(), check.TestName())
check.Assert(err, IsNil)
check.Assert(vapp, NotNil)
Expand Down Expand Up @@ -2118,7 +2122,6 @@ func createNsxtVAppAndVmWithEfiSupport(vcd *TestVCD, check *C) (*VApp, *VM) {
}

func (vcd *TestVCD) Test_GetOvfEnvironment(check *C) {

version, err := vcd.client.Client.GetVcdShortVersion()
check.Assert(err, IsNil)
if version == "10.5.0" {
Expand Down Expand Up @@ -2160,3 +2163,99 @@ func (vcd *TestVCD) Test_GetOvfEnvironment(check *C) {
err = deleteNsxtVapp(vcd, check.TestName())
check.Assert(err, IsNil)
}

// Test_VmConsolidateDisks attempts to validate vm.ConsolidateDisks by performing the following
// operations:
// * setting up a vApp and a VM
// * trying to resize VM disk and expecting to get an error (cannot be modified while the virtual machine has snapshots)
// * consolidating disks
// * resizing VM disk (growing by 1024MB)
// * verifying that new size is correct
// * attempting to consolidate once more (it is already consolidated so expecting a quick return)
// * cleanup
func (vcd *TestVCD) Test_VmConsolidateDisks(check *C) {
org := vcd.org
catalog, err := org.GetCatalogByName(vcd.config.VCD.Catalog.NsxtBackedCatalogName, false)
check.Assert(err, IsNil)
vappTemplateName := vcd.config.VCD.Catalog.CatalogItemWithMultiVms
if vappTemplateName == "" {
check.Skip(fmt.Sprintf("vApp template missing in configuration - Make sure there is such template in catalog %s -"+
" Using test_resources/vapp_with_3_vms.ova",
vcd.config.VCD.Catalog.NsxtBackedCatalogName))
}
vappTemplate, err := catalog.GetVAppTemplateByName(vappTemplateName)
if err != nil {
if ContainsNotFound(err) {
check.Skip(fmt.Sprintf("vApp template %s not found - Make sure there is such template in catalog %s -"+
" Using test_resources/vapp_with_3_vms.ova",
vappTemplateName, vcd.config.VCD.Catalog.NsxtBackedCatalogName))
}
}
check.Assert(err, IsNil)
check.Assert(vappTemplate.VAppTemplate.Children, NotNil)
check.Assert(vappTemplate.VAppTemplate.Children.VM, NotNil)

vapp, vm := createNsxtVAppAndVmFromCustomTemplate(vcd, check, vappTemplate)
check.Assert(vapp, NotNil)
check.Assert(vm, NotNil)

// Check that vApp did not lose its state
vappStatus, err := vapp.GetStatus()
check.Assert(err, IsNil)
check.Assert(vappStatus, Equals, "MIXED") //vApp is powered on, but the VM within is powered off
check.Assert(vapp.VApp.Name, Equals, check.TestName())
check.Assert(vapp.VApp.Description, Equals, check.TestName())

// Check that VM is not powered on
vmStatus, err := vm.GetStatus()
check.Assert(err, IsNil)
check.Assert(vmStatus, Equals, "POWERED_OFF")

// Attempt to resize before consolidating disks - it should fail
vmSpecSection := vm.VM.VmSpecSection
vmSizeBeforeGrowing := vmSpecSection.DiskSection.DiskSettings[0].SizeMb
vmSpecSection.DiskSection.DiskSettings[0].SizeMb = vmSizeBeforeGrowing + 1024
_, err = vm.UpdateInternalDisks(vmSpecSection)
check.Assert(strings.Contains(err.Error(), "cannot be modified while the virtual machine has snapshots"), Equals, true)

// Trigger disk consolidation
err = vm.ConsolidateDisks()
check.Assert(err, IsNil)

// Resize disk after consolidation - it should work now
err = vm.Refresh() // reloading VM structure to avoid
check.Assert(err, IsNil)
vmSpecSection = vm.VM.VmSpecSection
vmSizeBeforeGrowing = vmSpecSection.DiskSection.DiskSettings[0].SizeMb
vmSpecSection.DiskSection.DiskSettings[0].SizeMb = vmSizeBeforeGrowing + 1024

_, err = vm.UpdateInternalDisks(vmSpecSection)
check.Assert(err, IsNil)

// Refresh VM and verify size
err = vm.Refresh()
check.Assert(err, IsNil)
check.Assert(vm.VM.VmSpecSection.DiskSection.DiskSettings[0].SizeMb, Equals, vmSizeBeforeGrowing+1024)

// Trigger async disk consolidation - it will return instantly because the disk is already
// consolidated and there is nothing to do
task, err := vm.ConsolidateDisksAsync()
check.Assert(err, IsNil)
err = task.WaitTaskCompletion()
check.Assert(err, IsNil)

// Cleanup
task, err = vapp.Undeploy()
check.Assert(err, IsNil)
check.Assert(task, Not(Equals), Task{})

err = task.WaitTaskCompletion()
check.Assert(err, IsNil)

task, err = vapp.Delete()
check.Assert(err, IsNil)
check.Assert(task, Not(Equals), Task{})

err = task.WaitTaskCompletion()
check.Assert(err, IsNil)
}
Loading