Change VM Video Memory

I was contacted by a colleague asking if there was an easy way to set the video memory for a number of virtual machines, he had been working with a customer who had received an error when a virtual machine was being Vmotioned, the Vmotion completes successfully but the following error is received:

Insufficient video RAM. The maximum resolution of the virtual machine will be limited to 1176×885 at 16 bits per pixel. To use the configured maximum resolution of 2360×1770 at 16 bits per pixel, increase the amount of video RAM allocated to this virtual machine by setting svga.vramSize=”16708800″ in the virtual machine’s configuration file.

After applying his best Google-Fu he managed to find the following KB article: http://kb.vmware.com/kb/1014593

This clearly tells him the issue and how to resolve this by changing the video memory on the virtual machine, however, after changing this setting he then came across another issue as SRM was unable to protect these virtual machines as described in this KB article: http://kb.vmware.com/kb/1020796

The long and the short of it was that he needed to change the video memory in over 3000 VMs, you can of course do this in the vCenter client using the following screen but for 3000 VMs this may take a while !

Vide card settings

PowerCLI to the rescue !

With the following PowerCLI function he will be able to adjust a number of VMs without spending hours pointing and clicking.

function Set-VMVideoMemory {
<# .SYNOPSIS   Changes the video memory of a VM .DESCRIPTION   This function changes the video memory of a VM .NOTES   Source: http://virtu-al.net   Author: Alan Renouf   Version: 1.1 .PARAMETER VM   Specify the virtual machine .PARAMETER MemoryMB   Specify the memory size in MB .EXAMPLE   PS> Get-VM VM1 | Set-VMVideoMemory -MemoryMB 4 -AutoDetect $false
#>

  Param (
    [parameter(valuefrompipeline = $true, mandatory = $true, HelpMessage = "Enter a vm entity")]
    [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]$VM,
    [int64]$MemoryMB,
	[bool]$AutoDetect,
	[int]$NumDisplays
   )

  Process {
	$VM | Foreach {
		$VideoAdapter = $_.ExtensionData.Config.Hardware.Device | Where {$_.GetType().Name -eq "VirtualMachineVideoCard"}
		$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
		$Config = New-Object VMware.Vim.VirtualDeviceConfigSpec
		$Config.device = $VideoAdapter
		If ($MemoryMB) {
			$Config.device.videoRamSizeInKB = $MemoryMB * 1KB
		}
		If ($AutoDetect) {
			$Config.device.useAutoDetect = $true
		} Else {
			$Config.device.useAutoDetect = $false
		}
		Switch ($NumDisplays) {
			1{ $Config.device.numDisplays = 1}
			2{ $Config.device.numDisplays = 2}
			3{ $Config.device.numDisplays = 3}
			4{ $Config.device.numDisplays = 4}
			Default {}
		}
		$Config.operation = "edit"
		$spec.deviceChange += $Config
		$VMView = $_ | Get-View
		Write-Host "Setting Video Display for $($_)"
		$VMView.ReconfigVM($spec)
	}
  }
}

# For a single VM setting the video memory to 4MB
Get-VM VIEW01 | Set-VMVideoMemory -MemoryMB 4 -AutoDetect $false

# For all VMs on a Host setting the vide memory to Auto Detect
Get-VMHost Host01 | Get-VM | Set-VMVideoMemory -AutoDetect $true

# For all VMs in a cluster to set the Video Memory to 8MB
Get-Cluster Production | Get-VM | Set-VMVideoMemory -MemoryMB 8 -AutoDetect $false

20 thoughts on “Change VM Video Memory”

  1. can anyone tell?? how to export a xls file with the current Video memory size for all available VM ?

  2. Your error message:
    “The term ‘Set-VMVideoMemory’ is not recognized as the name of a cmdlet, functio
    n, script file, or operable program.”,

    means the parser didn’t read the function definition yet. Make sure the function is defined before you call it. In other words, put the command calling the function after the function definition.

    The code sample in this article has it correct, the function is defined then at the bottom, he calls it.

  3. Very new to powercli. Very excited to find your script. After running it I tried to use the function as per your examples in the bottom of the script and received the following error:

    PowerCLI H:\My Documents> get-vm win2k8r264 | Set-VMVideoMemory -MemoryMB 24 -Au
    toDetect $false
    The term ‘Set-VMVideoMemory’ is not recognized as the name of a cmdlet, functio
    n, script file, or operable program. Check the spelling of the name, or if a pa
    th was included, verify that the path is correct and try again.
    At line:1 char:38
    + get-vm win2k8r264 | Set-VMVideoMemory <<<< -MemoryMB 24 -AutoDetect $false
    + CategoryInfo : ObjectNotFound: (Set-VMVideoMemory:String) [], C
    ommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Can you please help a newbie by providing the steps to install the function in as much detail as possible?

    Many Thanks,
    Simon

  4. Hi the snippet at the bottom does the same, except implemented in perl using the VMware perl api.

    #!/usr/bin/perl -w
    use strict;
    use warnings;

    use VMware::VIRuntime;
    use Data::Dumper;

    my $vm_name = “vmnamehere”;

    my $shiny_new_vm = Vim::find_entity_view(view_type => ‘VirtualMachine’,
    filter => { ‘config.name’ => $vm_name });

    my $deviceList = $shiny_new_vm->config->hardware->device;
    foreach my $device (@$deviceList) {

    if ( ref ($device) eq “VirtualMachineVideoCard” ){

    $device->useAutoDetect(1);
    my $spec = VirtualMachineConfigSpec->new(
    changeVersion => $shiny_new_vm->config->changeVersion,
    deviceChange => [
    VirtualDeviceConfigSpec->new(
    operation => VirtualDeviceConfigSpecOperation->new(“edit”),
    device => $device
    )
    ]
    );
    eval {
    $shiny_new_vm->ReconfigVM(spec => $spec);
    };

    }
    }

  5. I think decreasing the resolution on the guest would be a better option.

    Seems like a waste to increase the video memory usage on every single vm.

  6. So the two VMware articles you mention contradict each other. Any chance that VMware will correct this in the future?

  7. Thanks for the post, just one suggestion – since you are applying the same spec to all the VM’s you can re-use the $spec, so just create it once, and then run something along the lines of:
    $VM | get-view | % { $_.ReconfigureVM($spec) }

    Also, why the switch on the NumDisplays, you can just get away with $config.device.numDisplay = $NumDisplay

    1. Thanks for the comment, I agree for performance reasons you could do it the way you suggested with $VM | get-view | % { $_.ReconfigureVM($spec) } but I guess I just like knowing if and when an error occurred, good catch though.

      As for the NumDisplays, I do it this way as the only options you can have are 1-4 if I did it your way there would be no way of checking the user hadn’t put 20 in, I guess more error checking could be added.

      Thanks for the comment

Leave a Reply