Ensure the export directory structure matches that of previous versions

Commit 3fc2defb6 altered the directory structure associated with an
exported VM. The changes mean that the export process now stores the
exported machine files and folders under a folder with name 'vm_name' in
the output directory.
This commit restores the previous behaviour whereby the exported machine
files and folders were stored directly in the output directory. This
allows us to keep the efficiency improvements introduced with 3fc2defb6
while maintaining backward compatibility.

By default the Export-VM command creates three folders in the specified
export directory - 'Virtual Hard Disks', 'Virtual Machines' and
'Snapshots'. When a machine with no associated snapshots is exported the
'Snapshots' directory is empty.
Prior to 3fc2defb6 the Snapshots folder was not copied/incorporated into
the output directory at all. This was a bug.
This commit preserves the legacy behaviour by not including an empty
Snapshots directory in the export. However, if there *are* Snapshots
associated with the VM, they are now moved into the output directory
along with the usual directories containing disks and VM metadata. This
prevents warnings/errors on import due to missing snapshots.
This commit is contained in:
DanHam 2018-07-04 13:03:32 +01:00
parent dc46848f89
commit 534fc4a473
No known key found for this signature in database
GPG Key ID: 58E79AEDD6AA987E
5 changed files with 90 additions and 0 deletions

View File

@ -94,6 +94,8 @@ type Driver interface {
ExportVirtualMachine(string, string) error
PreserveLegacyExportBehaviour(string, string) error
CompactDisks(string) error
RestartVirtualMachine(string) error

View File

@ -186,6 +186,11 @@ type DriverMock struct {
ExportVirtualMachine_Path string
ExportVirtualMachine_Err error
PreserveLegacyExportBehaviour_Called bool
PreserveLegacyExportBehaviour_SrcPath string
PreserveLegacyExportBehaviour_DstPath string
PreserveLegacyExportBehaviour_Err error
CompactDisks_Called bool
CompactDisks_Path string
CompactDisks_Err error
@ -481,6 +486,13 @@ func (d *DriverMock) ExportVirtualMachine(vmName string, path string) error {
return d.ExportVirtualMachine_Err
}
func (d *DriverMock) PreserveLegacyExportBehaviour(srcPath string, dstPath string) error {
d.PreserveLegacyExportBehaviour_Called = true
d.PreserveLegacyExportBehaviour_SrcPath = srcPath
d.PreserveLegacyExportBehaviour_DstPath = dstPath
return d.PreserveLegacyExportBehaviour_Err
}
func (d *DriverMock) CompactDisks(path string) error {
d.CompactDisks_Called = true
d.CompactDisks_Path = path

View File

@ -219,6 +219,10 @@ func (d *HypervPS4Driver) ExportVirtualMachine(vmName string, path string) error
return hyperv.ExportVirtualMachine(vmName, path)
}
func (d *HypervPS4Driver) PreserveLegacyExportBehaviour(srcPath string, dstPath string) error {
return hyperv.PreserveLegacyExportBehaviour(srcPath, dstPath)
}
func (d *HypervPS4Driver) CompactDisks(path string) error {
return hyperv.CompactDisks(path)
}

View File

@ -3,6 +3,7 @@ package common
import (
"context"
"fmt"
"path/filepath"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
@ -59,6 +60,21 @@ func (s *StepExportVm) Run(_ context.Context, state multistep.StateBag) multiste
return multistep.ActionHalt
}
// Shuffle around the exported folders to maintain backwards
// compatibility. This moves the 'Snapshots', 'Virtual Hard Disks' and
// 'Virtual Machines' directories from <output directory>/<vm name> so
// they appear directly under <output directory>. The empty '<output
// directory>/<vm name>' directory is removed when complete.
// The 'Snapshots' folder will not be moved into the output directory
// if it is empty.
exportPath := filepath.Join(s.OutputDir, vmName)
err = driver.PreserveLegacyExportBehaviour(exportPath, s.OutputDir)
if err != nil {
// No need to halt here; Just warn the user instead
err = fmt.Errorf("WARNING: Error restoring legacy export dir structure: %s", err)
ui.Error(err.Error())
}
return multistep.ActionContinue
}

View File

@ -665,6 +665,62 @@ if (Test-Path -Path ([IO.Path]::Combine($path, $vmName, 'Virtual Machines', '*.V
return err
}
func PreserveLegacyExportBehaviour(srcPath, dstPath string) error {
var script = `
param([string]$srcPath, [string]$dstPath)
# Validate the paths returning an error if they are empty or don't exist
$srcPath, $dstPath | % {
if ($_) {
if (! (Test-Path $_)) {
[System.Console]::Error.WriteLine("Path $_ does not exist")
exit
}
} else {
[System.Console]::Error.WriteLine("A supplied path is empty")
exit
}
}
# Export-VM should just create directories at the root of the export path
# but, just in case, move all files as well...
Move-Item -Path (Join-Path (Get-Item $srcPath).FullName "*.*") -Destination (Get-Item $dstPath).FullName
# Move directories with content; Delete empty directories
$dirObj = Get-ChildItem $srcPath -Directory | % {
New-Object PSObject -Property @{
FullName=$_.FullName;
HasContent=$(if ($_.GetFileSystemInfos().Count -gt 0) {$true} else {$false})
}
}
foreach ($directory in $dirObj) {
if ($directory.HasContent) {
Move-Item -Path $directory.FullName -Destination (Get-Item $dstPath).FullName
} else {
Remove-Item -Path $directory.FullName
}
}
# Only remove the source directory if it is now empty
if ( $((Get-Item $srcPath).GetFileSystemInfos().Count) -eq 0 ) {
Remove-Item -Path $srcPath
} else {
# 'Return' an error message to PowerShellCmd as the directory should
# always be empty at the end of the script. The check is here to stop
# the Remove-Item command from doing any damage if some unforeseen
# error has occured
[System.Console]::Error.WriteLine("Refusing to remove $srcPath as it is not empty")
exit
}
`
var ps powershell.PowerShellCmd
err := ps.Run(script, srcPath, dstPath)
return err
}
func CompactDisks(path string) error {
var script = `
param([string]$srcPath)