Ensure the export directory structure matches that of previous versions
Commit3fc2defb6
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 with3fc2defb6
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 to3fc2defb6
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:
parent
dc46848f89
commit
534fc4a473
|
@ -94,6 +94,8 @@ type Driver interface {
|
|||
|
||||
ExportVirtualMachine(string, string) error
|
||||
|
||||
PreserveLegacyExportBehaviour(string, string) error
|
||||
|
||||
CompactDisks(string) error
|
||||
|
||||
RestartVirtualMachine(string) error
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue