It isn’t exactly a secret that Windows PowerShell can be used to reconfigure a Hyper-V virtual machine. One of the really great things about PowerShell, however, is that it allows VMs to be managed in bulk. This can be especially useful when an entire class of workloads needs to be allocated additional resources (such as memory).
The PowerShell cmdlet that is used for viewing current VM memory usage is Get-VMMemory. There are a couple of different ways that you can use this cmdlet. If you are interested in viewing the memory usage for a single virtual machine, then you can simply enter the cmdlet, followed by the virtual machine name. If, on the other hand, you want to see the memory usage for all of the virtual machines that are running on the server, then you would start by entering the Get-VM cmdlet, and then you would use the pipeline to drive the cmdlet’s output into the Get-VMMemory cmdlet. The actual command looks like this:
Get-VM | Get-VMMemory
The figure below shows how both commands work.
Although it’s helpful to be able to view the amount of memory that has been allocated to a virtual machine, it is also useful to be able to modify virtual machine memory allocations. The PowerShell cmdlet that is used for doing so is Set-VMMemory. Here is the full syntax of the cmdlet:
Set-VMMemory [-VMMemory] <VMMemory[]> [-Buffer <Int32>] [-DynamicMemoryEnabled <Boolean>]
[-MaximumBytes <Int64>] [-StartupBytes <Int64>] [-MinimumBytes <Int64>] [-Priority <Int32>]
[-MaximumAmountPerNumaNodeBytes <Int64>] [-ResourcePoolName <String>] [-Passthru] [-WhatIf] [-Confirm] [<CommonParameters>]
As you can see, this cmdlet is really flexible. It can be used to configure both static and dynamic memory usage. Since there are other things that I want to get to, I’m going to limit the scope of my discussion to static memory. If you need to configure dynamic memory however, then here is an example that Microsoft provides:
Set-VMMemory TestVM -DynamicMemoryEnabled $true -MinimumBytes 64MB -StartupBytes 256MB -MaximumBytes 2GB -Priority 80 -Buffer 25
So with that said, let’s look at a really simple example of using PowerShell to reconfigure virtual machine memory. I have a virtual machine on my Hyper-V Server named Linux. If I use the Get-VMMemory cmdlet, I can see that the Linux VM currently has 4GB of memory assigned. If I want to increase that amount to 6GB, I can do so by using this command:
Set-VMMemory Linux -StartupBytes 6GB
The figure below shows the usage for this command. The figure also shows the change that the command has made in the amount of memory that is allocated to the virtual machine.
So as you can see in the figure, this technique works really well. The only problem is that the method that I just showed you doesn’t scale very well. The technique works fine if you need to modify a couple of VMs, but you probably would not want to use this method to reconfigure a thousand VMs. Fortunately, you don’t have to. PowerShell can perform bulk operations against multiple VMs.
The first step in doing so is to set up a variable containing the names of all of the VMs that we need to modify. I will be using a variable named $VMs. The technique used to populate this variable varies a little bit depending on whether you want to include specific VMs or all of your VMs.
If you only want to include certain VMs, then the command would look something like this:
$VMs=(‘VM1′,’VM2′,’VM3’)
You can see an example of this in the figure below.
If on the other hand you want to store the names of all of the VMs, then you will need to create a temporary variable, and then pass the VM names from the temporary variable to the $VMs variable. The commands look like this:
$Temp = Get-VM
$VMs = $Temp.Name
Here is what this technique looks like:
Once you have created a variable containing the names of the VMs that you want to modify, the next step in the process is to set up a “for each” loop. The loop is going to be based on the list of virtual machines (the $VMs variable). It will essentially tell PowerShell that for each VM in the list of VMs, perform a certain action. That action is, of course, a memory modification.
We already have a variable ($VMs) that represents our virtual machine list, but we also need a variable that will represent a single virtual machine. For this I will use $VM (without the S on the end). The loop will look like this:
ForEach ($VM in $VMs)
Now, we have to decide what we want the loop to do. If this were a real world situation, we could simply modify the VM memory and be done with it. For the sake of demonstration, however, I am going to display the process. Therefore, my loop will display the VM name, display the current memory allocation, modify the memory allocation, and then display the new memory allocation. Because there are so many steps being performed, I am going to add this to a script. Here is what my script will look like:
$VMs=(‘Repl1′,’Repl2’)
ForEach ($VM in $VMs) {
$VM
Get-VMMemory $VM
Set-VMMemory $VM -StartupBytes 10GB
Get-VMMemory $VM
}
So as you can see, I am setting the memory for VMs Repl1 and Repl2 to 10GB. The output is shown in the figure below.
Fell the power of PowerShell
PowerShell is a handy interface for managing Hyper-V virtual machines. Even so, the real benefit of using PowerShell is only realized when managing large numbers of resources such as virtual machines. With a mere seven lines of code, PowerShell was able to automate the process of changing virtual machine memory allocations. In actually, however, this could have been done using two lines of code if I wrote the script in a different way. I simply chose to write the script in long form to make it easier to understand.