Creating Hyper-V VM with PowerShell

Just another Tech site

Creating Hyper-V VM with PowerShell

I was trying to learn how to create a VM in Windows 2019 Hypervisor with PowerShell. Microsoft Resource  was a big help.

Some of things that I started to learn was how to setup VM Switches, enable VLAN, create and configure a VM that would show up in Hyper-V and the settings needed to run.

Reading what others did, I worked through trying to build a PowerShell install Process using resources found on internet, where others had the same questions, I had.

  • Identify the VM Switch – I only had one to work with, but I could see where changing the variable to exact name would make sense.
  • Server Names – New Server name for the new VM, and the old Server name that I would be replacing gathering information from it.
  • Storage path – Place where I would host the VM’s
  • Source Location – The location for the VHDX’s that would be used as part of the build process that would be linked together.
  • Identify VLAN ID – Identify VLAN ID on system that was being replaced, this was very hard to figure out for what I wanted to do.
  • Building the VM
    • Create the new VM folder on the destination location.
    • Copy the source location to new VM Folder
    • Set VM Configurations
      • Memory, TPM, CPU, VLAN ID
    • Set Automatic checkpoint.
    • Remove VMDVD – I wanted to have this removed before adding the new Volumes, it could be added back afterwards if that is what I wanted to
    • Copy the additional volumes (VHDX) files to the new VM Folder
    • Add New Volumes after Primary Volume is attached to the Hyper-V VM.
    • Create Snapshot – Should I need to restore after I started working and had issues.
    • Start VM – I still need to work on automating joining to the domain, setting static IP and making sure all volumes are connected to the VM inside the Operating System.
$NICSwitch = (Get-VMSwitch).Name # Hyper-V VM Switch name

$VMNames = 'BAT-TECH-VM' # New Server that is replacing or being added to Hyper-V

$ReplacingServer = "BAT-TECH-3" # Replacing old Server with a new server

$MachinePath = "D:\" # Drive where VM's are created and Stored

$DiskPath = "D:\" # Drive where VM's are stored

$SmartPagingFilePath = "D:\"

$SysprepVHD = "D:\Source\BAT-TECH-DEV.vhdx" # C Drive Sysprepped VHD location

$DataVHD = "D:\Source\Data.VHDX" # D Drive added Data Volume

$RepositoryVHD = "D:\Source\Repository.VHDX" # E Drive added Repository Volume 


############################################################################################################
#Capture VLANID
$virtualmachines = $ReplaceServer 

$vmvlans = Get-VMNetworkAdapterVlan -VMName $virtualmachines 

$vmnetworkinfo = @()

foreach ($virtualmachine in $virtualmachines)
{


                $virtualnetworkadapters = Get-VMNetworkAdapter -VMName $virtualmachine 
                $vmvlans = Get-VMNetworkAdapterVlan -VMName $virtualmachine 
                $vmproperties = New-Object -TypeName PSObject
                $vmproperties | Add-Member -MemberType NoteProperty -Name VMName -Value $virtualnetworkadapters.vmname 
                $vmproperties | Add-Member -MemberType NoteProperty -Name Name -value  $virtualnetworkadapters.Name
                $vmproperties | Add-Member -MemberType NoteProperty -Name SwitchName -Value $virtualnetworkadapters.switchname
                $vmproperties | Add-Member -MemberType NoteProperty -Name isLegacy -Value $virtualnetworkadapters.islegacy
                $vmproperties | Add-Member -MemberType NoteProperty -name VlanList -value $vmvlans.accessvlanid
                $vmnetworkinfo += $vmproperties

}

$VLANID = ($vmnetworkinfo | Select-Object VlanList | Format-Table -HideTableHeaders | Out-String | ForEach-Object { $_.Trim() })

$VLANID # Showing that I got the VLAN ID number 
############################################################################################################
#Build VM

foreach ($VMName IN $VMNames)
{
   Write-Host "Preparing " $VMName

    MkDir "$Diskpath\$VMName" -ErrorAction SilentlyContinue

   Copy-Item $SysprepVHD -destination "$DiskPath\$VMName\$VMName.vhdx"

   New-VM -Name $VMName -path $MachinePath -switchname $NICSwitch -generation 2 -VHDPath "$DiskPath\$VMName\$VMName.vhdx" -MemorystartupBytes 8GB | Out-Null

   Set-VMKeyProtector -VMName $VMName -NewLocalKeyProtector | Out-Null

   Enable-VMTPM -VMName $VMName | Out-Null

    Set-VMProcessor $VMname -Count 4 | Out-Null

    set-VMNetworkAdapterVlan -VMName "$VMName" -Access -VlanId $VLANID

   Set-VM -Name $VMName -automaticCheckpointsenabled $false -SmartPagingFilePath "$SmartPagingFilePath\$VMName" -staticmemory | Out-Null

    Get-VMDvdDrive -VMName $VMName -ControllerNumber 1 | Remove-VMDvdDrive

    Copy-Item $DataVHD -destination "$DiskPath\$VMName\Data.vhdx"

    Add-VMHardDiskDrive -VMName $VMName -Path "$DiskPath\$VMName\Data.vhdx" #-ControllerType SCSI -ControllerNumber 1

    Copy-Item $RepositoryVHD -destination "$DiskPath\$VMName\Repository.vhdx"

    Add-VMHardDiskDrive -VMName $VMName -Path "$DiskPath\$VMName\Repository.vhdx" #-ControllerType SCSI -ControllerNumber 2

   Checkpoint-vm -name $VMName -SnapShotName '' | Out-Null

   Start-VM -Name $VMName | Out-Null

   Write-Host "Starting " $VMName
   
}

Now that I have this, I want to make some changes to streamline it more, put some checks in place to make sure files and resources are available and create a log file for reporting back on creation of VM.

Thanks for reading.