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.
This commit is contained in:
DanHam 2018-06-16 18:02:38 +01:00
parent a5a6b1ab58
commit 3fc2defb6d
No known key found for this signature in database
GPG Key ID: 58E79AEDD6AA987E
5 changed files with 38 additions and 62 deletions

View File

@ -94,7 +94,7 @@ type Driver interface {
ExportVirtualMachine(string, string) error
CompactDisks(string, string) error
CompactDisks(string) error
CopyExportedVirtualMachine(string, string, string, string) error

View File

@ -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
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}