Refactor the import script to fully use Compare-VM for creating the new VM.

Implemented the differencing disk for vmcx.
This means the disk is now copied by Hyper-V (Powershell) instead of Ruby for new machines.
This does mean EFI Firmware now does work for machines since it is quite a feep copy. Compare-VM will report incompatibilities should they be found.
This commit is contained in:
Bjorn Brala 2016-10-08 16:38:42 +02:00
parent a77da314e5
commit debe50957b
4 changed files with 63 additions and 66 deletions

View File

@ -44,7 +44,6 @@ module VagrantPlugins
end end
end end
# Only check for .vmcx if there is no XML found to not # Only check for .vmcx if there is no XML found to not
# risk breaking older vagrant boxes that added an XML # risk breaking older vagrant boxes that added an XML
# file manually # file manually
@ -58,7 +57,6 @@ module VagrantPlugins
end end
end end
image_path = nil image_path = nil
image_ext = nil image_ext = nil
image_filename = nil image_filename = nil
@ -116,12 +114,16 @@ module VagrantPlugins
end end
env[:ui].detail("Cloning virtual hard drive...") env[:ui].detail("Cloning virtual hard drive...")
source_path = image_path.to_s source_path = image_path.to_s
dest_path = env[:machine].data_dir.join("#{image_filename}#{image_ext}").to_s dest_path = env[:machine].data_dir.join("#{image_filename}#{image_ext}").to_s
if differencing_disk
env[:machine].provider.driver.execute("clone_vhd.ps1", {Source: source_path, Destination: dest_path}) # Still hard copy the disk of old XML configurations
else if config_type == 'xml'
FileUtils.cp(source_path, dest_path) if differencing_disk
env[:machine].provider.driver.execute("clone_vhd.ps1", {Source: source_path, Destination: dest_path})
else
FileUtils.cp(source_path, dest_path)
end
end end
image_path = dest_path image_path = dest_path
@ -130,7 +132,9 @@ module VagrantPlugins
options = { options = {
vm_config_file: config_path.to_s.gsub("/", "\\"), vm_config_file: config_path.to_s.gsub("/", "\\"),
vm_config_type: config_type, vm_config_type: config_type,
image_path: image_path.to_s.gsub("/", "\\") source_path: source_path.to_s,
dest_path: env[:machine].data_dir.join("Virtual Hard Disks").join("#{image_filename}#{image_ext}").to_s,
data_path: env[:machine].data_dir.to_s.gsub("/", "\\")
} }
options[:switchname] = switch if switch options[:switchname] = switch if switch
options[:memory] = memory if memory options[:memory] = memory if memory
@ -139,6 +143,7 @@ module VagrantPlugins
options[:vmname] = vmname if vmname options[:vmname] = vmname if vmname
options[:auto_start_action] = auto_start_action if auto_start_action options[:auto_start_action] = auto_start_action if auto_start_action
options[:auto_stop_action] = auto_stop_action if auto_stop_action options[:auto_stop_action] = auto_stop_action if auto_stop_action
options[:differencing_disk] = differencing_disk if differencing_disk
env[:ui].detail("Creating and registering the VM...") env[:ui].detail("Creating and registering the VM...")
server = env[:machine].provider.driver.import(options) server = env[:machine].provider.driver.import(options)

View File

@ -78,6 +78,9 @@ module VagrantPlugins
if config_type === "vmcx" if config_type === "vmcx"
execute('import_vm_vmcx.ps1', options) execute('import_vm_vmcx.ps1', options)
else else
option.delete(:data_path)
option.delete(:source_path)
option.delete(:differencing_disk)
execute('import_vm_xml.ps1', options) execute('import_vm_xml.ps1', options)
end end
end end

View File

@ -2,7 +2,11 @@
[Parameter(Mandatory=$true)] [Parameter(Mandatory=$true)]
[string]$vm_config_file, [string]$vm_config_file,
[Parameter(Mandatory=$true)] [Parameter(Mandatory=$true)]
[string]$image_path, [string]$source_path,
[Parameter(Mandatory=$true)]
[string]$dest_path,
[Parameter(Mandatory=$true)]
[string]$data_path,
[string]$switchname=$null, [string]$switchname=$null,
[string]$memory=$null, [string]$memory=$null,
@ -10,15 +14,19 @@
[string]$cpus=$null, [string]$cpus=$null,
[string]$vmname=$null, [string]$vmname=$null,
[string]$auto_start_action=$null, [string]$auto_start_action=$null,
[string]$auto_stop_action=$null [string]$auto_stop_action=$null,
[string]$differencing_disk=$null
) )
"$($data_path)/Snapshots"
# Include the following modules # Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path $Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1")) . ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
# load the config from the vmcx and make a copy for editing, use TMP path so we are sure there is no vhd at the destination # load the config from the vmcx and make a copy for editing, use TMP path so we are sure there is no vhd at the destination
$vmConfig = (Compare-VM -Copy -Path $vm_config_file -GenerateNewID -VhdDestinationPath $env:Temp) $vmConfig = (Compare-VM -Copy -Path $vm_config_file -GenerateNewID -SnapshotFilePath "$($data_path)Snapshots" -VhdDestinationPath "$($data_path)Virtual Hard Disks" -VirtualMachinePath "$($data_path)Virtual Machines")
$generation = $vmConfig.VM.Generation $generation = $vmConfig.VM.Generation
@ -32,7 +40,6 @@ if (!$vmname) {
if (!$cpus) { if (!$cpus) {
# Get the processorcount of the VM # Get the processorcount of the VM
$processors = (Get-VMProcessor -VM $vmConfig.VM).Count $processors = (Get-VMProcessor -VM $vmConfig.VM).Count
}else { }else {
$processors = $cpus $processors = $cpus
} }
@ -80,82 +87,64 @@ if (!$switchname) {
$switchname = (Get-VMNetworkAdapter -VM $vmConfig.VM).SwitchName $switchname = (Get-VMNetworkAdapter -VM $vmConfig.VM).SwitchName
} }
$vm_params = @{
Name = $vm_name
NoVHD = $True
MemoryStartupBytes = $MemoryStartupBytes
SwitchName = $switchname
ErrorAction = "Stop"
}
# Generation parameter was added in ps v4 Connect-VMNetworkAdapter -VMNetworkAdapter (Get-VMNetworkAdapter -VM $vmConfig.VM) -SwitchName $switchname
if((get-command New-VM).Parameters.Keys.Contains("generation")) { Set-VM -VM $vmConfig.VM -NewVMName $vm_name -MemoryStartupBytes $MemoryStartupBytes
$vm_params.Generation = $generation Set-VM -VM $vmConfig.VM -MemoryMinimumBytes $MemoryMinimumBytes -MemoryMaximumBytes $MemoryMaximumBytes
} Set-VM -VM $vmConfig.VM -ErrorAction "Stop" -ProcessorCount $processors
# Create the VM using the values in the hash map
$vm = New-VM @vm_params
$notes = $vmConfig.VM.Notes
# Set-VM parameters to configure new VM with old values
$more_vm_params = @{
ProcessorCount = $processors
MemoryStartupBytes = $MemoryStartupBytes
}
If ($dynamicmemory) { If ($dynamicmemory) {
$more_vm_params.Add("DynamicMemory",$True) Set-VM -VM $vmConfig.VM -DynamicMemory
$more_vm_params.Add("MemoryMinimumBytes",$MemoryMinimumBytes)
$more_vm_params.Add("MemoryMaximumBytes", $MemoryMaximumBytes)
} else { } else {
$more_vm_params.Add("StaticMemory",$True) Set-VM -VM $vmConfig.VM -StaticMemory
} }
if ($notes) { if ($notes) {
$more_vm_params.Add("Notes",$notes) Set-VM -VM $vmConfig.VM -Notes $notes
} }
if ($auto_start_action) { if ($auto_start_action) {
$more_vm_params.Add("AutomaticStartAction",$auto_start_action) Set-VM -VM $vmConfig.VM -AutomaticStartAction $auto_start_action
} }
if ($auto_stop_action) { if ($auto_stop_action) {
$more_vm_params.Add("AutomaticStopAction",$auto_stop_action) Set-VM -VM $vmConfig.VM -AutomaticStartAction $auto_stop_action
} }
# Set the values on the VM
$vm | Set-VM @more_vm_params -Passthru
# Only set EFI secure boot for Gen 2 machines, not gen 1 # Only set EFI secure boot for Gen 2 machines, not gen 1
if ($generation -ne 1) { if ($generation -ne 1) {
Set-VMFirmware -VM $vm -EnableSecureBoot (Get-VMFirmware -VM $vmConfig.VM).SecureBoot Set-VMFirmware -VM $vmConfig.VM -EnableSecureBoot (Get-VMFirmware -VM $vmConfig.VM).SecureBoot
} }
# Get all controller on the VM, first scsi, then IDE if it is a Gen 1 device $report = Compare-VM -CompatibilityReport $vmConfig
$controllers = Get-VMScsiController -VM $vmConfig.VM if($report.Incompatibilities.Length -gt 0){
if($generation -eq 1){ $report.Incompatibilities
$controllers = @($controllers) + @(Get-VMIdeController -VM $vmConfig.VM) Write-Error-Message ConvertTo-Json $report.Incompatibilities
} }
foreach($controller in $controllers){ # Differencing disk
foreach($drive in $controller.Drives){ if($differencing_disk){
$addDriveParam = @{ # Get all controller on the VM, first scsi, then IDE if it is a Gen 1 device
ControllerNumber = $drive.ControllerNumber $controllers = Get-VMScsiController -VM $vmConfig.VM
Path = $image_path if($generation -eq 1){
} $controllers = @($controllers) + @(Get-VMIdeController -VM $vmConfig.VM)
if($drive.PoolName){ }
$addDriveParam.Add("ResourcePoolname",$drive.PoolName)
}
# If the drive path is set, it is a harddisk, only support single harddisk foreach($controller in $controllers){
if ($drive.Path) { foreach($drive in $controller.Drives){
$addDriveParam.add("ControllerType", $ControllerType) if([System.IO.Path]::GetFileName($drive.Path) -eq [System.IO.Path]::GetFileName($source_path)){
$vm | Add-VMHardDiskDrive @AddDriveparam # Remove the old disk and replace it with a differencing version
$path = $drive.Path
Remove-VMHardDiskDrive $drive
New-VHD -Path $dest_path -ParentPath $source_path -ErrorAction Stop
Add-VMHardDiskDrive -VM $vmConfig.VM -Path $dest_path
}
} }
} }
} }
Import-VM -CompatibilityReport $vmConfig
$vm_id = (Get-VM $vm_name).id.guid $vm_id = (Get-VM $vm_name).id.guid
$resultHash = @{ $resultHash = @{

View File

@ -2,7 +2,7 @@ Param(
[Parameter(Mandatory=$true)] [Parameter(Mandatory=$true)]
[string]$vm_config_file, [string]$vm_config_file,
[Parameter(Mandatory=$true)] [Parameter(Mandatory=$true)]
[string]$image_path, [string]$dest_path,
[string]$switchname=$null, [string]$switchname=$null,
[string]$memory=$null, [string]$memory=$null,
@ -190,7 +190,7 @@ foreach ($controller in $controllers) {
$addDriveParam = @{ $addDriveParam = @{
ControllerNumber = $rx.Match($controller.node.name).value ControllerNumber = $rx.Match($controller.node.name).value
Path = $image_path Path = $dest_path
} }
if ($drive.pool_id."#text") { if ($drive.pool_id."#text") {