Weekend Scripter: Use PowerShell to Build Multiple Virtual Machines

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to build multiple virtual machines with Hyper-V.

Microsoft Scripting Guy, Ed Wilson, is here. One of the really cool things that I love about Windows 8 is having real-live, honest-to-goodness, Hyper-V built in to the operating system. And of course, that means also having the Windows PowerShell cmdlets to manage it. With the power of modern laptops (the Scripting Wife has 32 GB of RAM, a solid-state drive, and a SATA 3 drive on her new laptop), running multiple virtual machines is a real option—and a real treat.

The other day, I needed to create three virtual machines to test my instructor-led lab scenario that I am creating for TechEd in New Orleans and Madrid. Because I am in the process of redoing my network, I do not have access to any advanced deployment tools. It’s just me, my laptop, and Windows PowerShell. Because my objective is to build three virtual machines (not to write the perfect script), I decided to knock out a quick script. The result is shown here:

$name = “Client1″,”Server1″,”Server2”

$name |

Foreach {

    new-vm $_ -MemoryStartupBytes 512MB -SwitchName InternalSwitch `

    -BootDevice cd -NewVHDPath “F:VM$_Virtual Hard Disks$_.vhdx” `

    -NewVHDSizeBytes 127GB }

 

Foreach($n in $name)

{

 if($n -match ‘client’)

    {

     Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 4096MB -StartupBytes 2048MB -Buffer 20

     Set-VMDvdDrive -VMName $n -Path $((Get-Item F:winsource*client*).fullname)

    }

 if($n -match ‘server’)

  {

   Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 2048MB -StartupBytes 1024MB -Buffer 20

   Set-VMDvdDrive -VMName $n -Path $((Get-Item F:winsource*server*).fullname)

  }

}

 

Get-VM $name | Start-VM

Three important cmdlets

Because I only needed to create three virtual machines, I hard coded the machine names into a variable. I also thought it was a good idea to use easy-to-remember names. This part of the code is no surprise:

$name = “Client1″,”Server1″,”Server2”

New-VM

Now I come to the first important cmdlet: New-VM. The New-VM cmdlet creates a new virtual machine. The basic configuration for all three virtual machines is the same. I specify the startup memory, the name of the switch, the boot device, the path to the VHD, and the size of the VHD. I pipe the three computer names to the New-VM cmdlet, and I end up with three new virtual machines. This portion of the code is shown here:

$name |

Foreach {

    new-vm $_ -MemoryStartupBytes 512MB -SwitchName InternalSwitch `

    -BootDevice cd -NewVHDPath “F:VM$_Virtual Hard Disks$_.vhdx” `

    -NewVHDSizeBytes 127GB }

Set-VMMemory and Set-VMDvdDrive

Now I need to walk through the computer names by using the ForEach command. For each of the computer names, I will set the virtual machine memory and the DVD drive information. But because I will have different memory and different DVD info depending on if the operating system is a client or a server, I use the If statement.

To set the memory, I use the Set-VMMemory cmdlet, and I specify that I want to use dynamic memory in addition to the minimum and maximum bytes. I also set the startup memory. Next, I set the DVD drive to point to the ISO of the operating system I want to use.

This portion of the code is shown here:

Foreach($n in $name)

{

 if($n -match ‘client’)

    {

     Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 4096MB -StartupBytes 2048MB -Buffer 20

     Set-VMDvdDrive -VMName $n -Path $((Get-Item F:winblue*client*).fullname)

    }

 if($n -match ‘server’)

  {

   Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 2048MB -StartupBytes 1024MB -Buffer 20

   Set-VMDvdDrive -VMName $n -Path $((Get-Item F:winblue*server*).fullname)

  }

Start me up

The last thing to do is to start the newly created virtual machines. To do this, I use the Get-VM cmdlet and supply the three computer names that are stored in the $Name variable. I pipe the results to the Start-VM cmdlet. Now, I still have to walk through the wizard, but that actually goes pretty quickly on modern operating systems.

Join me tomorrow because I have an awesome guest blog about WSUS by Honorary Scripting Guy, Boe Prox. You don’t want to miss it—the post absolutely rocks!

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy