My requirement was to write and automate adding a new virtual SCSI controller to virtual machines using PowerCLI. For this task there is cmdlet is already available New-ScsiController. But the problem with command is, standalone virtual SCSI controller cannot be added. It has to add new or existing virtual disk while creating virtual SCSI controller. In both cases you have to have virtual disk created or existed.
What I was looking for was to just add a standalone virtual SCSI controller without any attached virtual disk.
#Example - 1 Get-VM VM | New-HardDisk -CapacityKB 10485760 | New-ScsiController
#Example - 2 Get-HardDisk -VM VM | Select -First 2 | New-ScsiController -BusSharingMode Physical -Type VirtualLsiLogicSAS
Here is a script to achieve the task. First 3 lines are related to login into vCenter server. The main parameter is VirtualMachineID, where you will need to mention VM ID. VM ID can be find on Get-VM - ID property.
Next There are 4 types of SCSI controller ParaVirtualSCSIController, VirtualBusLogicController, VirtualLsiLogicController, VirtualLsiLogicSASController and you have to use exact any one value in ControllerType parameter. Another parameter is SharedBus represents SCSI bus sharing parameter values should be either one of noSharing, physicalSharing, virtualSharing.
Another important and required parameter is BusNumber, you can only add maximum four SCSI controller, starting number from 0 to 3. (SCSI Controller 0 is already by default created while creating VM, if you have virtual disk added)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
#Remove-Module Hyper-V #Import-Module VMware.PowerCLI #Connect-VIServer -Server marvel.vcloud-lab.com -Username [email protected] -Password P@ssw0rd function Add-VMScsiController { [CmdletBinding()] param ( [Parameter( Position=0, Mandatory=$true, #change here ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage='Enter one or more VM Id separated by commas.' )] [Alias('VmID')] [string[]]$VirtualMachineId, #change here [Parameter( Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage='Enter SCSI contoller type.' )] [ValidateSet('ParaVirtualSCSIController','VirtualBusLogicController','VirtualLsiLogicController','VirtualLsiLogicSASController')] [string]$ControllerType = 'VirtualLsiLogicSASController', [Parameter( Position=2, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage='Enter SCSI shared bus.' )] [ValidateSet('noSharing', 'physicalSharing', 'virtualSharing')] [string]$SharedBus = 'noSharing', [Parameter( Position=3, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage='Enter SCSI bus Number type.' )] [ValidateRange(0,3)] [string]$BusNumber = 1 ) $virtualMachine = Get-VM -Id $VirtualMachineId $scsiController = $virtualMachine | Get-ScsiController Write-Host -BackgroundColor DarkYellow "$([char]8734)" -NoNewline Write-Host " '$($virtualMachine.Name)' - Configuring SCSI controller $BusNumber" if ($scsiController.ExtensionData.BusNumber -contains $BusNumber) { Write-Host -BackgroundColor DarkRed "`t$([char]215)" -NoNewline Write-Host " 'SCSI controller $BusNumber' already exist" } #1) if ($virtualMachine.ExtensionData.BusNumber -contains $BusNumber) else { $spec = New-Object VMware.Vim.VirtualMachineConfigSpec $spec.DeviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (1) $spec.DeviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec $spec.DeviceChange[0].Device = New-Object VMware.Vim.$ControllerType #ParaVirtualSCSIController, VirtualBusLogicController, VirtualLsiLogicController, VirtualLsiLogicSASController $spec.DeviceChange[0].Device.SharedBus = $SharedBus #noSharing, physicalSharing, virtualSharing #$spec.DeviceChange[0].Device.ScsiCtlrUnitNumber = 7 #The unit number of the SCSI controller. The SCSI controller sits on its own bus, so this field defines which slot the controller is using. $spec.DeviceChange[0].Device.DeviceInfo = New-Object VMware.Vim.Description $spec.DeviceChange[0].Device.DeviceInfo.Summary = 'New SCSI controller' $spec.DeviceChange[0].Device.DeviceInfo.Label = 'New SCSI controller' #$spec.DeviceChange[0].Device.Key = -107 $spec.DeviceChange[0].Device.BusNumber = $BusNumber $spec.DeviceChange[0].Operation = 'add' $vm = Get-View -Id $VirtualMachineId [void]$vm.ReconfigVM_Task($spec) Start-Sleep -Seconds 3 $scsiController = $virtualMachine | Get-ScsiController if ($scsiController.ExtensionData.BusNumber -contains $BusNumber) { Write-Host -BackgroundColor DarkGreen "`t$([char]8730)" -NoNewline Write-Host " 'SCSI controller $BusNumber' created successfully" } else { Write-Host -BackgroundColor DarkRed "`t$([char]215)" -NoNewline Write-Host " 'SCSI controller $BusNumber' adding failed" } } #1) else if ($virtualMachine.ExtensionData.BusNumber -contains $BusNumber) } |
Another interesting and Important information is ScsiCtlrUnitNumber by default it will be 7, This is a unit number of SCSI controller. The SCSI controller sits on its own bus, so this field defines which slot the controller is using. To simplify there are only 15 slots on SCSI controller, It means only 15 virtual disks can be added to a SCSI controller. One of the slot number is itself is used by VM SCSI controller. The same behavior you can see with below edit settings screenshot, where I am trying to create new virtual hard disk with new SCSI controller and slot number 7 is not visible or already taken.
One more property is device key, I will let system choose it - This property is a unique key that distinguishes this device from other devices in the same virtual machine. Keys are immutable but may be recycled; that is, a key does not change as long as the device is associated with a particular virtual machine. However, once a device is removed, its key may be used when another device is added.This property is not read-only, but the client cannot control its value. Persistent device keys are always assigned and managed by the server, which guarantees that all devices will have non-negative key values.When adding new devices, it may be necessary for a client to assign keys temporarily in order to associate controllers with devices in configuring a virtual machine. However, the server does not allow a client to reassign a device key, and the server may assign a different value from the one passed during configuration. Clients should ensure that existing device keys are not reused as temporary key values for the new device to be added (for example, by using negative integers as temporary keys). When editing or deleting a device, clients must use the server-provided key to refer to an existing device.
Here is the example how to use this script. I have highlighted the items in dark yellow which needs to be modified before running script.
#Get existing virtual SCSI controller information from VMs $vms = Get-VM dev-01,dev-02,uat-01,uat-02 $vms | Get-ScsiController | Select Parent, Name, Type #Add SCSI controller $vms | Foreach-Object {Add-VMScsiController -VirtualMachineId $_.Id -ControllerType ParaVirtualSCSIController -BusNumber 1} #Recheck virtual SCSI controller information again $vms | Get-ScsiController | Select-Object Parent, Name, Type
Download the Add-VMScsiController.ps1 script here, this script is also available on github.com/kunaludapi.
Useful Articles
POWERCLI AND VSPHERE WEB CLIENT: JOIN ESXI INTO ACTIVE DIRECTORY DOMAIN CONTROLLER
Resolved: Esxi Join domain failed - Error in Active Directory Operations
Join domain ESXi to an Active Directory OU : Powercli
Reset forgotten ESXi root password on Domain joined Esxi using vSphere web client and Powercli
Reset ESXi root password using Host Profiles on vCenter server: VMWare vSphere Web client
Resolved: Reset Esxi forgotten root password using hiren bootCD step by step