Home > Paravirtual, PowerCLI, PowerShell > Switching to the Paravirtual SCSI Controller

Switching to the Paravirtual SCSI Controller

December 8th, 2009 LucD Leave a comment Go to comments

Since ESX 4u1 you have a new SCSI controller type available for your guests, the VMware Paravirtual SCSI Controller.
From several sources we learn that the performance of this controller is better.

See for example the New !! Open unofficial storage performance thread where Lars gave some interesting performance figures.

And in the PowerCLI Community there is a recent thread, called Change SCSI adapter to paravirtual with PowerCLI, where the user asks how he can change his disk adapters.

Reason enough to look how I could use PowerCLI to migrate guests to the VMware Paravirtual SCSI Controller.

The script uses the well-known ReconfigVM_Task method to make the change. It will change any existing SCSI controller, whose name is specified in the $ctrlName variable, to a VMware Paravirtualization SCSI controller.

Make sure the correct driver is installed in the Windows guest OS before you run the script to change the controller that hosts your boot device, otherwise the OS will BSOD !

Update August 20th 2010: A thread in the PowerCLI Community from Benj informed me that the script didn’t work any more in  vSphere 4.1. It seems that API 4.1 requires the ControllerKey and UnitNumber of the new Paravirtual SCSI Controller to be specified. The script has been updated.

The script

$vmName = "MyVM"
$ctrlName = "SCSI controller 0"

$vm = Get-VM $vmName | Get-View

# Get the controller and the devices connected to it
$vm.Config.Hardware.Device | where {$_.DeviceInfo.Label -eq $ctrlName} | % {
	$oldCtrl = $_
	$ctrlKey = $_.Key
	$devs = @()
	$_.Device | % {
		$devKey = $_
		$vm.Config.Hardware.Device | where {$_.Key -eq $devKey} | % {
			$devs += $_
		}
	}
}

# Create the specification for the device changes
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec

# Remove old controller
$old = New-Object VMware.Vim.VirtualDeviceConfigSpec
$old.device = $oldCtrl
$old.operation = "remove"
$spec.DeviceChange += $old

# Update the devices connected to the controller
$devs | % {
	$dev = New-Object VMware.Vim.VirtualDeviceConfigSpec
	$dev.device = $_
	$dev.device.ControllerKey = -100
	$dev.operation = "edit"
	$spec.DeviceChange += $dev
}

# Add new controller
$new = New-Object VMware.Vim.VirtualDeviceConfigSpec
$new.Device = New-Object VMware.Vim.ParaVirtualSCSIController
$new.Device.Key = -100
if($defaultVIServer.Build -ge '258902'){
	$new.Device.ControllerKey = $oldCtrl.ControllerKey
	$new.Device.UnitNumber = $oldCtrl.UnitNumber
}
$new.operation = "add"
$spec.DeviceChange += $new

$vm.ReconfigVM($spec)

Annotation

Line 8: remember the ‘old’ controller

Line 10-16: collect all devices that are connected to the controller

Line 19-42: populate the VirtualMachineConfigSpec object with all the changes

Line 22-26: remove the ‘old’ controller

Line 28-35: change the ControllerKey for all the devices that were connected to the ‘old’ controller. As stated in the SDK documentation, you may not reassign keys in your script. To avoid this problem, use a temporary key which the system will replace by the new key. Use a negative integer for the temporary key.

Line 37-48: create the new controller. Note that the vSphere system will pick up the devices that were connected to the old controller and will updated their ControllerKey property to point to the new controller.

Line 41-44: test if the script is running in a vSphere 4.1 environment (build 258902 or higher). If it is, fill in the ControllerKey and UnitNumber properties.

Remarks

The VMware Paravirtual SCSI Controller is currently only supported on a limited set of guest operating systems. See KB Article: 1010398 for the list and also for some other limitations.

Note that you can not use a VMware Paravirtual SCSI Controller on a guest that you have configured for Fault Tolerance.

Although there are some limitations, I still hope the script is useful to some of you.

  1. Samuel Stynen
    August 25th, 2010 at 12:39 | #1

    @LucD
    What did you change exactly to the script?

    • August 25th, 2010 at 13:44 | #2

      Hi Samuel, I mentioned the change in the Update text at the beginning of the post.
      The lines that were added:


      if($defaultVIServer.Build -ge '258902'){
      $new.Device.ControllerKey = $oldCtrl.ControllerKey
      $new.Device.UnitNumber = $oldCtrl.UnitNumber
      }

  2. August 20th, 2010 at 13:23 | #3

    @PiroNet

    The PVSCSI driver has been updated for vSphere 4.1 and that limitation is no longer an issue. I wrote a blog post about it just this week actually.

    http://www.thelowercasew.com/more-vsphere-4-1-enhancements-welcome-back-pvscsi-driver

    • August 20th, 2010 at 13:55 | #4

      @Matt, thanks for the information. Great blog btw.

      @all, like Matt says in his post, we can now make the Paravirtual SCSI Controller the default.
      But remember to inject the driver into the OS first, otherwise there will be a BSOD (see earlier) when your boot disk is connected to the Paravirtual SCSI Controller.

  3. August 20th, 2010 at 09:29 | #5

    The driver injection method that NiTRo blogged about works great. I was using the same trick at the physical server era :)

    Not sure how you could insert it in your code thought!?

    Also a side note, PVSCSI is not for every VM. Scott Drummonds at vpivot.com has a great post about it: http://vpivot.com/2010/02/04/pvscsi-and-low-io-workloads/

    Cheers,
    Didier

    • August 20th, 2010 at 11:03 | #6

      Thanks for the information.
      The automation of the injection process would be a great feature. I’ll put it on my (long) list ;-)

  4. Carl
    May 4th, 2010 at 14:25 | #7

    Hi LucD,

    I tried running the script but I get the follwoing errors:
    Property ‘ControllerKey’ cannot be found on this object; make sure it exists and is settable.
    At D:\Change_Controller_to_PVSCSI.ps1:32 char:14
    + $dev.device. <<<< ControllerKey = – 100
    + CategoryInfo : InvalidOperation: (ControllerKey:String) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

    Exception calling "ReconfigVM" with "1" argument(s): "Not initialized: vim.vm.device.VirtualDevice device"
    At D:\Change_Controller_to_PVSCSI.ps1:44 char:15
    + $vm.ReconfigVM <<<< ($spec)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Any Ideas whats going wrong?

    • May 4th, 2010 at 15:33 | #8

      Hi Carl, it looks as if there is indeed a device connected to the “old” controller that doesn’t seem to have the ControllerKey property.
      Can you perhaps send me screenshots of the controller and the devices connected to it from the Edit Settings option on the guest.
      You can send them to lucd(at)lucd(dot)info.

    • May 6th, 2010 at 15:07 | #9

      After some debugging we found out that the problem was caused by the “regional settings”.
      On Carl’s PC the regional settings were set to German.
      Where the vCenter client still shows “SCSI controller 0” if you open the settings of the guest, the label property contained “SCSI-Controller 0” (notice the additional dash in there !).
      Once the script was adapted for this strange behaviour, the script worked as intended.

  5. January 21st, 2010 at 01:32 | #10

    Here is a way to automate driver switch, hope it could help someone : http://www.hypervisor.fr/?p=1764

  6. dboftlp
    December 8th, 2009 at 17:47 | #11

    Alan ran into an issue where just switching the controller would cause VM to BSOD b/c no drivers were installed yet from vmtools (http://bit.ly/4Hmn9X). Can you confirm that this is not the case using your script. He also gives a work around, adding another tiny drive so drivers are installed then going back and changing on boot drive then removing, but sheesh…
    kthxbye

    -dboftlp

    • December 8th, 2009 at 18:10 | #12

      No, if you don’t have the driver installed before you run the script, the OS will BSOD, provided your boot disk is located under the PV controller.
      I tested with a Windows 2008 Standard server.

      I’ll have a look if I can automate that part as well.

      I have put up a warning in the article to make sure people know the risk.

  1. December 8th, 2009 at 17:33 | #1
  2. January 21st, 2010 at 01:21 | #2
  3. January 22nd, 2010 at 22:14 | #3
  4. August 20th, 2010 at 09:06 | #4