Hyper-V: Scripting Dynamic VHD Creation
Today I would like to show you some basic scripts for creating a new dynamically expanding virtual hard disk. The tricky thing about doing this is that the WMI interfaces for creating virtual hard disks expect the size of the new virtual hard disk to be specified as a UINT64. This requires some special handling - but can be done in both VBScript and PowerShell.
VBScript:
Option Explicit
'Setup constant to use for getting the right value for the new VHD size
const Size1G = &H40000000
Dim HyperVServer
Dim VHDName
Dim VHDSize
Dim WMIService
Dim Msvm_ImageManagementService
Dim Result
Dim Job
Dim InParam
Dim OutParam
'Prompt for the Hyper-V Server to use
HyperVServer = InputBox("Specify the Hyper-V Server to create the dynamic virtual hard disk on:")
'Get name for VHD
VHDName = InputBox("Specify the name of the new dynamic virtual hard disk:")
'Get size for VHD
VHDSize = InputBox("Specify the size of the new dynamic virtual hard disk (in GB):") * Size1G
'Get an instance of the WMI Service in the virtualization namespace.
Set WMIService = GetObject("winmgmts:\\" & HyperVServer & "\root\virtualization")
'Get the Msvm_ImageManagementService object
Set Msvm_ImageManagementService = WMIService.ExecQuery("SELECT * FROM Msvm_ImageManagementService").ItemIndex(0)
'Setup the input parameter list
Set InParam = Msvm_ImageManagementService.Methods_("CreateDynamicVirtualHardDisk").InParameters.SpawnInstance_()
InParam.Path = VHDName
InParam.MaxInternalSize = VHDSize
'Execute the method and store the results in OutParam
Set OutParam = Msvm_ImageManagementService.ExecMethod_("CreateDynamicVirtualHardDisk", InParam)
'Check to see if the job completed synchronously
if (OutParam.ReturnValue = 0) then
Wscript.Echo "The virtual hard disk has been created."
elseif (OutParam.ReturnValue <> 4096) then
Wscript.Echo "The virtual hard disk has not been created."
else
'Get the job object
set Job = WMIService.Get(OutParam.Job)
'Wait for the job to complete (3 == starting, 4 == running)
while (Job.JobState = 3) or (Job.JobState = 4)
Wscript.Echo "Creating VHD. " & Job.PercentComplete & "% complete"
WScript.Sleep(1000)
'Refresh the job object
set Job = WMIService.Get(OutParam.Job)
Wend
'Provide details if the job fails (7 == complete)
if (Job.JobState <> 7) then
Wscript.Echo "The virtual hard disk has not been created."
Wscript.Echo "ErrorCode:" & Job.ErrorCode
Wscript.Echo "ErrorDescription:" & Job.ErrorDescription
else
Wscript.Echo "The virtual hard disk has been created."
end If
end if
PowerShell:
# Setup constant to use for getting the right value for the new VHD size
[UInt64]$Size1G = 0x40000000
# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
# Get name for VHD
$VHDName = Read-Host "Specify the name of the new dynamic virtual hard disk"
# Get size for VHD
[UInt64]$VHDSize = Read-Host "Specify the size of the new dynamic virtual hard disk (in GB)"
# Get the Msvm_ImageManagementService object
$ImageManagementService = gwmi Msvm_ImageManagementService -namespace "root\virtualization" -computername $HyperVServer
# Compact the VHD
$result = $ImageManagementService.CreateDynamicVirtualHardDisk($VHDName, $VHDSize * $Size1G)
#Return success if the return value is "0"
if ($Result.ReturnValue -eq 0)
{write-host "The virtual hard disk has been created."}
#If the return value is not "0" or "4096" then the operation failed
ElseIf ($Result.ReturnValue -ne 4096)
{write-host "The virtual hard disk has not been created. Error value:" $Result.ReturnValue}
Else
{#Get the job object
$job=[WMI]$Result.job
#Provide updates if the jobstate is "3" (starting) or "4" (running)
while ($job.JobState -eq 3 -or $job.JobState -eq 4)
{write-host "Creating. "$job.PercentComplete "% complete"
start-sleep 1
#Refresh the job object
$job=[WMI]$Result.job}
#A jobstate of "7" means success
if ($job.JobState -eq 7)
{write-host "The virtual hard disk has been created."}
Else
{write-host "The virtual hard disk has not been created."
write-host "ErrorCode:" $job.ErrorCode
write-host "ErrorDescription" $job.ErrorDescription}
}
Cheers,
Ben