Ok, so far we have created, modified, and added resources (memory, processor, disks, and network) to virtual machines. Now, we want to take that information and build a complete virtual machine.
# Set up variables
$VHD = "f:\VHDs\win2k8.vhd"
$GuestVM = "Win2k8"
$Namespace = "root\virtualization"
$Computer = "HyperV"
$VHDSize = "10GB"
$VMSwitchName = "Hyper-V External Switch"
$VMSwitchPortName = "MyPort"
$VMNICAddress = "00155D9290FF"
$VMSvc = Get-WmiObject -class "Msvm_VirtualSystemManagementService" -namespace $Namespace -ComputerName $Computer
$VM = Get-WmiObject -Namespace $Namespace -ComputerName $Computer -Query "Select * From Msvm_ComputerSystem Where ElementName='$GuestVM'"
$VMSettingData = Get-WmiObject -Namespace $Namespace -Query "Associators of {$VM} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"
# Give the new virtual machine a name
$VMGlobalSettingClass = [WMIClass]"\\$Computer\root\virtualization:Msvm_VirtualSystemGlobalSettingData"
$NewVMGS = $VMGlobalSettingClass.psbase.CreateInstance()
while ($NewVMGS.psbase.Properties -eq $null) {}
$NewVMGS.psbase.Properties.Item("ElementName").value = $GuestVM
# Create a virtual disk
$VMDiskSvc = Get-WmiObject -Class "Msvm_ImageManagementService" -Namespace "root\virtualization"
$DiskCreate = $VMDiskSvc.CreateFixedVirtualHardDisk($VHD, 10GB)
$DiskJob = [WMI]$DiskCreate.job
while (($DiskJob.JobState -eq "2") -or ($DiskJob.JobState -eq "3") -or ($DiskJob.JobState -eq "4")) {Start-Sleep -m 100 $DiskJob = [WMI]$DiskCreate.job}
#Create memory resource
$VMMem = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$VMSettingData} Where ResultClass = Msvm_VirtualSystemSettingDataComponent" | where-object -FilterScript {$_.ResourceSubType -eq "Microsoft Virtual Machine Memory"})
$VMMem.VirtualQuantity = [string]2048
$VMMem.Reservation = [string]2048
$VMMem.Limit = [string]2048
# Create processor resource
$VMProc = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$VMSettingData} Where ResultClass = Msvm_ProcessorSettingData" | where-object -FilterScript {$_.ResourceSubType -eq "Microsoft Processor"})
$VMProc.VirtualQuantity = [string]1
$VMProc.Reservation = [string]0
$VMProc.Limit = [string]100000
$VMProc.Weight = [string]100
# Create network interface
$DefaultNet = Get-WmiObject -Namespace $Namespace -Class Msvm_SyntheticEthernetPortSettingData | Where-Object -FilterScript {$_.InstanceID -like "*Default*"}
$GUID1 = [GUID]::NewGUID().ToString()
$GUID2 = [GUID]::NewGUID().ToString()
$VMSwitchQuery = Get-WmiObject -Class "Msvm_VirtualSwitchManagementService" -Namespace $Namespace
# $VMSvc = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -namespace $Namespace -ComputerName $Computer
$VMSwitch = Get-WmiObject -Namespace $Namespace -Query "Select * From Msvm_VirtualSwitch Where ElementName = '$VMSwitchName'"
$ReturnObject = $VMSwitchQuery.CreateSwitchPort($VMSwitch, [guid]::NewGuid().ToString(), $VMSwitchPortName, "")
$NewSwitchPort1 = $ReturnObject.CreatedSwitchPort
$ReturnObject = $VMSwitchQuery.CreateSwitchPort($VMSwitch, [guid]::NewGUID().ToString(), $VMSwitchPortName, "")
$NewSwitchPort2 = $ReturnObject.CreatedSwitchPort
$StaticNet = $DefaultNet.psbase.Clone()
$StaticNet.VirtualSystemIdentifiers = "{GUID1}"
$StaticNet.StaticMacAddress = $true
$StaticNet.Address = $VMNICAddress
$StaticNet.Connection = $NewSwitchPort1
$DynNet = $DefaultNet.psbase.Clone()
$DynNet.VirtualSystemIdentifiers = "{GUID2}"
$DynNet.Connection = $NewSwitchPort2
#Add the network interface resources to Resource Allocation Settings
$VMRASD = @()
$VMRASD += $StaticNet.psbase.gettext(1)
$VMRASD += $DynNet.psbase.gettext(1)
$VMRASD += $VMMem.psbase.gettext(1)
$VMRASD += $VMProc.psbase.gettext(1)
# Time to create the virtual machine
$VMSvc.DefineVirtualSystem($NewVMGS.psbase.GetText(1), $VMRASD)
# Add our disk to the virtual machine
# $VM = Get-WmiObject -Namespace $Namespace -ComputerName $Computer -Query "Select * From Msvm_ComputerSystem Where ElementName = '$GuestVM'"
# $VMSettingData = Get-WmiObject -Namespace $Namespace -Query "Associators of {$VM} Where ResultClass = Msvm_VirtualSystemSettingData AssocClass = Msvm_SettingsDefineState"
$VMIDECtrl = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$VMSettingData} Where ResultClass = Msvm_ResourceAllocationSettingData AssocClass = Msvm_VirtualSystemSettingDataComponent" | where-object -FilterScript {$_.ResourceSubType -eq "Microsoft Emulated IDE Controller" -and $_.Address -eq 0})
$DiskAllocationSetting = Get-WmiObject -Namespace $Namespace -Query "Select * From Msvm_AllocationCapabilities Where ResourceSubType = 'Microsoft Synthetic Disk Drive'"
$DefaultDiskDrive = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$DiskAllocationSetting} Where ResultClass = Msvm_ResourceAllocationSettingData AssocClass = Msvm_SettingsDefineCapabilities" | where-object -FilterScript {$_.InstanceID -like "*Default*"})
$DefaultDiskDrive.Parent = $VMIDECtrl._Path
$DefaultDiskDrive.Address = 0
$NewDiskDrive = ($VMSvc.AddVirtualSystemResources($VM._Path, $DefaultDiskDrive.PSBase.GetText(1))).NewResources
$DiskAllocationSetting = Get-WmiObject -Namespace $Namespace -Query "Select * From Msvm_AllocationCapabilities Where ResourceSubType = 'Microsoft Virtual Hard Disk'"
$DefaultHardDisk = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$DiskAllocationSetting} Where ResultClass = Msvm_ResourceAllocationSettingData AssocClass = Msvm_SettingsDefineCapabilities" | where-object -FilterScript {$_.InstanceID -like "*Default"})
$DefaultHardDisk.Parent = $NewDiskDrive
$DefaultHardDisk.Connection = $VHD
$VMSvc.AddVirtualSystemResources($VM._Path, $DefaultHardDisk.PSBase.GetText(1))
#Now, we add a DVD
$DVDAllocationSetting = Get-WmiObject -Namespace $Namespace -Query "Select * From Msvm_AllocationCapabilities Where ResourceSubType = 'Microsoft Synthetic DVD Drive'"
$DefaultDVDDrive = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$DVDAllocationSetting} Where ResultClass = Msvm_ResourceAllocationSettingData AssocClass = Msvm_SettingsDefineCapabilities" | where-object -FilterScript {$_.InstanceID -like "*Default"})
$DefaultDVDDrive.Parent = $VMIDECtrl._Path
$DefaultDVDDrive.Address = 1
$NewDVDDrive = $DefaultDVDDrive.psbase.Clone()
$VMSvc.AddVirtualSystemResources($VM._Path, $NewDVDDrive.psbase.GetText(1))
In this code, I am using a data array to contain all of the resources that will be used to create the virtual machine.
$VMRASD = @()
$VMRASD += $StaticNet.psbase.gettext(1)
$VMRASD += $DynNet.psbase.gettext(1)
You will notice that the hard disk and DVD drive are not included in this array. This is because they are added to a virtual IDE port. These ports do not exist until after the virtual machine is created, so we add them after it is.
That wraps up this session for automating Hyper-V virtual machine creation through scripts. As always, any comments or questions, let me know.