From 3fc2defb6d22fc7025501d836afa44c7b56d2814 Mon Sep 17 00:00:00 2001 From: DanHam Date: Sat, 16 Jun 2018 18:02:38 +0100 Subject: [PATCH] Refactor the export step for Hyper-V ISO and VMCX builders * Fixes a bug that caused the build to error if users did not explicitly set `skip_compaction:true` when setting `skip_export: true`. See #6392. * Improves the efficiency of the compaction and export process by reordering the compaction and export steps. * Further improves the efficiency of the compacting step through compacting the vmd* file directly rather than creating and then operating on a copy. * The changes mean the export process now stores the exported machine files and folders under a folder with name 'vm_name' in the output directory. Previously the exported machine files and folders were stored directly in the output directory. --- builder/hyperv/common/driver.go | 2 +- builder/hyperv/common/driver_mock.go | 12 ++-- builder/hyperv/common/driver_ps_4.go | 4 +- builder/hyperv/common/step_export_vm.go | 74 +++++++++---------------- common/powershell/hyperv/hyperv.go | 8 +-- 5 files changed, 38 insertions(+), 62 deletions(-) diff --git a/builder/hyperv/common/driver.go b/builder/hyperv/common/driver.go index 535652923..2f79d8079 100644 --- a/builder/hyperv/common/driver.go +++ b/builder/hyperv/common/driver.go @@ -94,7 +94,7 @@ type Driver interface { ExportVirtualMachine(string, string) error - CompactDisks(string, string) error + CompactDisks(string) error CopyExportedVirtualMachine(string, string, string, string) error diff --git a/builder/hyperv/common/driver_mock.go b/builder/hyperv/common/driver_mock.go index 3fcb46323..669e47dde 100644 --- a/builder/hyperv/common/driver_mock.go +++ b/builder/hyperv/common/driver_mock.go @@ -186,10 +186,9 @@ type DriverMock struct { ExportVirtualMachine_Path string ExportVirtualMachine_Err error - CompactDisks_Called bool - CompactDisks_ExpPath string - CompactDisks_VhdDir string - CompactDisks_Err error + CompactDisks_Called bool + CompactDisks_Path string + CompactDisks_Err error CopyExportedVirtualMachine_Called bool CopyExportedVirtualMachine_ExpPath string @@ -489,10 +488,9 @@ func (d *DriverMock) ExportVirtualMachine(vmName string, path string) error { return d.ExportVirtualMachine_Err } -func (d *DriverMock) CompactDisks(expPath string, vhdDir string) error { +func (d *DriverMock) CompactDisks(path string) error { d.CompactDisks_Called = true - d.CompactDisks_ExpPath = expPath - d.CompactDisks_VhdDir = vhdDir + d.CompactDisks_Path = path return d.CompactDisks_Err } diff --git a/builder/hyperv/common/driver_ps_4.go b/builder/hyperv/common/driver_ps_4.go index cadaa2ba5..2f75a1810 100644 --- a/builder/hyperv/common/driver_ps_4.go +++ b/builder/hyperv/common/driver_ps_4.go @@ -219,8 +219,8 @@ func (d *HypervPS4Driver) ExportVirtualMachine(vmName string, path string) error return hyperv.ExportVirtualMachine(vmName, path) } -func (d *HypervPS4Driver) CompactDisks(expPath string, vhdDir string) error { - return hyperv.CompactDisks(expPath, vhdDir) +func (d *HypervPS4Driver) CompactDisks(path string) error { + return hyperv.CompactDisks(path) } func (d *HypervPS4Driver) CopyExportedVirtualMachine(expPath string, outputPath string, vhdDir string, vmDir string) error { diff --git a/builder/hyperv/common/step_export_vm.go b/builder/hyperv/common/step_export_vm.go index 8161da31d..f582c30f6 100644 --- a/builder/hyperv/common/step_export_vm.go +++ b/builder/hyperv/common/step_export_vm.go @@ -3,18 +3,11 @@ package common import ( "context" "fmt" - "io/ioutil" - "path/filepath" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) -const ( - vhdDir string = "Virtual Hard Disks" - vmDir string = "Virtual Machines" -) - type StepExportVm struct { OutputDir string SkipCompaction bool @@ -24,63 +17,48 @@ type StepExportVm struct { func (s *StepExportVm) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) - var err error - var errorMsg string - vmName := state.Get("vmName").(string) - tmpPath := state.Get("packerTempDir").(string) - outputPath := s.OutputDir - expPath := s.OutputDir - - // create temp path to export vm - errorMsg = "Error creating temp export path: %s" - vmExportPath, err := ioutil.TempDir(tmpPath, "export") - if err != nil { - err := fmt.Errorf(errorMsg, err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt + // Get the VM name; Get the temp directory used to store the VMs files + // during the build process + var vmName, tmpPath string + if v, ok := state.GetOk("vmName"); ok { + vmName = v.(string) } - if !s.SkipExport { - ui.Say("Exporting vm...") - - err = driver.ExportVirtualMachine(vmName, vmExportPath) - if err != nil { - errorMsg = "Error exporting vm: %s" - err := fmt.Errorf(errorMsg, err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - // copy to output dir - expPath = filepath.Join(vmExportPath, vmName) + if v, ok := state.GetOk("packerTempDir"); ok { + tmpPath = v.(string) } + // Compact disks first so the export process has less to do if s.SkipCompaction { ui.Say("Skipping disk compaction...") } else { ui.Say("Compacting disks...") - err = driver.CompactDisks(expPath, vhdDir) + err := driver.CompactDisks(tmpPath) if err != nil { - errorMsg = "Error compacting disks: %s" - err := fmt.Errorf(errorMsg, err) + err := fmt.Errorf("Error compacting disks: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } } - if !s.SkipExport { - ui.Say("Copying to output dir...") - err = driver.CopyExportedVirtualMachine(expPath, outputPath, vhdDir, vmDir) - if err != nil { - errorMsg = "Error exporting vm: %s" - err := fmt.Errorf(errorMsg, err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } + if s.SkipExport { + ui.Say("Skipping export of virtual machine...") + return multistep.ActionContinue } + + ui.Say("Exporting virtual machine...") + // The export process exports the VM to a folder named 'vmName' under + // the output directory. This contains the usual 'Snapshots', 'Virtual + // Hard Disks' and 'Virtual Machines' directories. + err := driver.ExportVirtualMachine(vmName, s.OutputDir) + if err != nil { + err = fmt.Errorf("Error exporting vm: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + return multistep.ActionContinue } diff --git a/common/powershell/hyperv/hyperv.go b/common/powershell/hyperv/hyperv.go index 343e02776..0a5505b19 100644 --- a/common/powershell/hyperv/hyperv.go +++ b/common/powershell/hyperv/hyperv.go @@ -665,16 +665,16 @@ if (Test-Path -Path ([IO.Path]::Combine($path, $vmName, 'Virtual Machines', '*.V return err } -func CompactDisks(expPath string, vhdDir string) error { +func CompactDisks(path string) error { var script = ` -param([string]$srcPath, [string]$vhdDirName) -Get-ChildItem "$srcPath/$vhdDirName" -Filter *.vhd* | %{ +param([string]$srcPath) +Get-ChildItem "$srcPath" -Filter *.vhd* | %{ Optimize-VHD -Path $_.FullName -Mode Full } ` var ps powershell.PowerShellCmd - err := ps.Run(script, expPath, vhdDir) + err := ps.Run(script, path) return err }