Switching to the Paravirtual SCSI Controller

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

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.

21 Comments

    Brett

    This is a great script. I am trying to make two modifications to it but can’t seem to get it working. I do not want to delete controller 0 and I would like to have Disk 1 remain connected to Controller 0. Could you assist please?

      LucD

      Thanks.
      Give it a try like this

      $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 -and $_.DeviceInfo.Label -ne 'Hard disk 1' } | % {
      $devs += $_
      }
      }
      }

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

      # 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)

        Brett

        Thanks for your assistance it is really appreciated. The changes have the same outcome, controller 0 is being deleted, the paravirtual is being added as controller 0 and all disks are being moved to the paravirtual.

        I am trying to leave controller 0 intact with disk 1 attached, add a paravirtual controller as controller 1 and move all remaining disks to controller 2.

        I have tried just about everything I can think of to get this working, but the results are always the same.

          Palani

          Brett have you found the solution/script for the above issue

        Palani

        After running the script I could see only one scsi controller with type as paravirtual also hard disk 1 is connected to that scsi

    J

    Could you make a post on how to make a completely NEW SCSI controller?

    Thank you

    harshvardhan gupta

    how to upgrade this script to powercli 5.1?

    Youngtech

    If you would like to evaluate a script that automates the Guest OS configuration, take a look at https://blog.virtualyoungtech.com/?p=108. At a customer’s request, I have been working on automating the VMxNet3 and Paravirtual SCSI process from a to z. I’ll publish a new revision shortly, still working on a better way to snag the DNS server configuration consistently regardless of the Windows OS version. Feedback welcomed! Thanks!

      LucD

      That’s a great script.
      Love the way you configure the guest OS for the new controller.

      PowerCLI builds released after this post, offer the New-ScsiController cmdlet, which make the addition of a Paravirtual SCSI controller to the guest a lot easier.

    Samuel Stynen

    @LucD
    What did you change exactly to the script?

      LucD

      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
      }

    Matt Liebowitz

    @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.

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

      LucD

      @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.

    PiroNet

    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: https://vpivot.com/2010/02/04/pvscsi-and-low-io-workloads/

    Cheers,
    Didier

      LucD

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

    Carl

    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?

      LucD

      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.

      LucD

      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.

    NiTRo

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

    dboftlp

    Alan ran into an issue where just switching the controller would cause VM to BSOD b/c no drivers were installed yet from vmtools (https://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

      LucD

      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.

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.