PowerShell Pipeline

Creating a Virtual Machine in Hyper-V Using PowerShell

Getting a VM up and running requires just a small amount of time and seven cmdlets.

Continuing where I left off on during a previous article on using the Hyper-V PowerShell module, we will go from viewing our virtual infrastructure and gathering information about various parts of it to building and adding additional configurations to a virtual machine.

To accomplish our goal of creating a virtual machine, we will be using seven cmdlets from the Hyper-V module to make this happen. Those cmdlets are:

  • New-VM
  • Set-VM
  • New-VHD
  • Add-VMHardDiskDrive
  • Set-VMDvdDrive
  • Add-VMNetworkAdapter
  • Start-VM

With that, let's go ahead and begin building our virtual machine and then work from there in adding additional pieces. There are a lot of parameters that I am going to be using with New-VM (and most of the other cmdlets as well), so I will not be going about the traditional approach of calling the cmdlet with all parameters and instead will be using a technique called Splatting which is where I create a hash table of parameters with their associated value and then run the cmdlet using the hash table. Instead of specifying the actual variable, I instead call a variable using the "@" sign, which PowerShell interprets as the splatted parameters to assign to the cmdlet. This is a very useful technique and also helps to better organize your parameters prior to being used in a command.

$NewVMParam = @{
Name = 'MS01B'
MemoryStartUpBytes = 1GB
Path = "C:\ProgramData\Microsoft\Windows\Hyper-V"
SwitchName = "Internal"
NewVHDPath = "C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\MS01B.vhdx"
NewVHDSizeBytes = 60GB
ErrorAction = 'Stop'
Verbose = $True
$VM = New-VM @NewVMParam
[Click on image for larger view.] Figure 1. The first steps in creating out virtual machine.

Here I am only assigning 1GB of memory to my virtual machine, which happens to be called MS02A. This will just be a simple member server as I haven't quite decided what I want it to do just yet. I also specified a new virtual hard drive (VHD) to be automatically created with a size of 60GB to host the operating system and to store the VHD and the virtual machine files in their respective folders.
Now that we have a virtual machine created, we can now move forward and make some additional customizations such as setting the number of processors on the virtual machine and setting the dynamic memory on the system.

$SetVMParam = @{
ProcessorCount = 1
DynamicMemory = $True
MemoryMinimumBytes = 512MB
MemoryMaximumBytes = 1Gb
ErrorAction = 'Stop'
PassThru = $True
Verbose = $True
$VM = $VM | Set-VM @SetVMParam
[Click on image for larger view.] Figure 2. Making some additional configurations to  our virtual machine.

I have decided that one hard disk was simply not enough for this virtual machine and am going to add another drive. To do this, I must first create the VHD and then add the drive to the existing virtual machine.

$NewVHDParam = @{
Path = 'C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\MS01B_Data.vhdx'
Dynamic = $True
SizeBytes = 60GB
ErrorAction = 'Stop'
Verbose = $True
$VHD = New-VHD @NewVHDParam
[Click on image for larger view.] Figure 3. Adding an additional hard disk to our virtual machine.

Like my OS drive, this drive will also be 60GB in size to host some data on it. I am choosing to make this a dynamically expanding drive so it will not be 60GB when it starts out on the Hyper-V server but a much smaller size and slowly grow as needed.

Next up is to add the hard disk to the virtual machine:

$AddVMHDDParam = @{
Path = 'C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks\MS01B_Data.vhdx'
ControllerType = 'SCSI'
ControllerLocation = 1
$VM | Add-VMHardDiskDrive @AddVMHDDParam

I simply need to ensure that I have the correct path to the hard disk and also making sure to have the proper controller configurations in place when it is added.

With the virtual machine created and configured, and an additional hard disk created and added to the virtual machine, the next step is to mount a DVD drive and point it to an ISO so that when we start the system, it will boot into the operating system installation.

$VMDVDParam = @{
VMName = 'MS01B'
Path = 'E:\ISOs\Win2012R2\en_windows_server_2012_r2_with_update_x64_dvd_4065220.iso'
ErrorAction = 'Stop'
Verbose = $True
Set-VMDvdDrive @VMDVDParam
[Click on image for larger view.] Figure 4. Mounting a DVD drive to load the operating system.

One last thing: I have a requirement that came in to create an additional network adapter and to point that towards our external switch that faces the internet. I will comply with this request and create a network adapter and add that to the External switch.

$AddVMNICParam = @{
SwitchName = 'External'
$VM | Add-VMNetworkAdapter @AddVMNICParam

All done! All that is left is to start up the virtual machine and prepare for the operating installation.

$VM | Start-VM -Verbose
[Click on image for larger view.] Figure 5. Starting up the virtual machine.

And sure enough, there is our powered on virtual machine sitting at the installation window awaiting our inputs.

[Click on image for larger view.] Figure 6. Virutal machine sitting at the operating system installation window.

From here we can continue on our way to get this virtual machine configured and send it on its way to new and amazing things! As you can see, using PowerShell can allow us to quickly build and configure a virtual machine without much effort. If you wanted, you could wrap this up in a build script with some parameters and have a quick way to churn out virtual machines pretty quickly!

About the Author

Boe Prox is a Microsoft MVP in Windows PowerShell and a Senior Windows System Administrator. He has worked in the IT field since 2003, and he supports a variety of different platforms. He is a contributing author in PowerShell Deep Dives with chapters about WSUS and TCP communication. He is a moderator on the Hey, Scripting Guy! forum, and he has been a judge for the Scripting Games. He has presented talks on the topics of WSUS and PowerShell as well as runspaces to PowerShell user groups. He is an Honorary Scripting Guy, and he has submitted a number of posts as a to Microsoft's Hey, Scripting Guy! He also has a number of open source projects available on Codeplex and GitHub. His personal blog is at http://learn-powershell.net.

comments powered by Disqus

SharePoint Watch

Sign up for our newsletter.

I agree to this site's Privacy Policy.