M4ttH
Contributor
Contributor

Remove RDM and re-create RDM mapping file and attach

Jump to solution

Hi,

I've written the script below but it works fine except it doesn't create the RDM mapping file.

If I comment out the following lines it works fine.

$fileMgr.DeleteDatastoreFile_Task($name, $datacenter)

$spec.deviceChange[0].fileOperation = "create"

Here's the code below

Function Replace-VM-RDM {

param($vmname, $scsiid, $rdmname, $filename)

<#

Convert the SCSI address in to Vmware format

#>

$scsicontroller=$null

$scsiid_split=$null

$scsiid_split=$scsiid.split(":")

$scsicontroller=($scsiid_split[0])

# VMware SCSI controller ID in gui is one number higher than the actual controller id

$scsicontroller=[int]$scsicontroller+1

# Vmware expects a conntroller id with 4 chars

$scsicontroller=($scsicontroller.ToString())+"000"

$scsicontroller

# SCSI LUN

$scsilun=$null

# VMware SCSI LUN ID in gui is one number higher than the actual lun id

$scsilun=[int]($scsiid_split[1])#+1

###

$vm = Get-VM -Name "$vmname" | Get-View

IF (!($filename)){

$RDMFile=$rdmname.split(" ")[0]+"_RDM.vmdk"

$filename=(($vm.Config.Files.VmPathName).Replace("$vmname.vmx","$RDMFile"))

}

$esx = Get-View $vm.Runtime.Host

<#

Get CanonicalName for RDM LUN

#>

$rdmCanonicalName=$null

$rdmCanonicalName=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).CanonicalName)

$rdmDevicePath=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).DevicePath)

foreach($dev in $vm.Config.Hardware.Device){

    if(($dev.gettype()).Name -eq "VirtualDisk"){

        if(($dev.Backing.CompatibilityMode -eq "physicalMode") -or

        ($dev.Backing.CompatibilityMode -eq "virtualMode")){

            if (($dev.ControllerKey -eq "$scsicontroller") -and ($dev.UnitNumber -eq "$scsilun")) {

                # Remove Harddisk

                $hd=get-harddisk $vm.name | where {$_.Filename -eq $dev.Backing.FileName}

                $hd | remove-harddisk -confirm:$false

                Write-Host "Filename: "$dev.backing.fileName

                Write-Host "Disk Mode: "$dev.backing.diskMode

                $dev.backing.deviceName

                $dev.backing.lunUuid

                $DevKey=$dev.key

                $CapacityInKB=$dev.CapacityInKB

                $fileMgr = Get-View (Get-View ServiceInstance).Content.fileManager

                $datacenter = (Get-View (Get-VM $VMname | Get-Datacenter).ID).get_MoRef()

                foreach($disk in $vm.LayoutEx.Disk){

                    if($disk.Key -eq $dev.Key){

                    foreach($chain in $disk.Chain){

                        foreach($file in $chain.FileKey){

                            $name = $vm.LayoutEx.File[$file].Name

                            $fileMgr.DeleteDatastoreFile_Task($name, $datacenter)

                            }

                        }

                    continue

                    }

                }

            }

        }

        Elseif (($dev.ControllerKey -eq "$scsicontroller") -and ($dev.UnitNumber -eq "$scsilun")) {Write-Host "Selected SCSI Address [$scsiid] is not a RDM"}

    }

}

#$hd1 = New-HardDisk -VM $vmname -DeviceName $rdmDevicePath -DiskType RawPhysical # this line works

    $spec=$null

    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

    $spec.deviceChange = @()

    $spec.deviceChange += New-Object VMware.Vim.VirtualDeviceConfigSpec

    $spec.deviceChange[0].device = New-Object VMware.Vim.VirtualDisk

    $spec.devicechange[0].device.capacityInKB=$CapacityInKB

    $spec.deviceChange[0].device.backing = New-Object VMware.Vim.VirtualDiskRawDiskMappingVer1BackingInfo

    $spec.deviceChange[0].device.backing.fileName=$filename

    $spec.deviceChange[0].device.backing.compatibilityMode ="physicalMode"

    $spec.deviceChange[0].device.backing.diskMode = ""

    $spec.deviceChange[0].device.backing.lunUuid=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).Uuid)

    $spec.deviceChange[0].device.connectable = New-Object VMware.Vim.VirtualDeviceConnectInfo

    $spec.deviceChange[0].device.connectable.startConnected = $true

    $spec.deviceChange[0].device.connectable.allowGuestControl = $false

    $spec.deviceChange[0].device.connectable.connected = $true

# Take next unused device key for HD

    $spec.deviceChange[0].device.key = $DevKey + 1

# The UnitNUmber SCSIID 7 is reserved for the Controller - so skip to 8.

    if ($scsilun -eq 6) {$scsilun = $scsilun + 1}

# Take next unit number for HD

    $spec.deviceChange[0].device.unitnumber = $scsilun

# SCSI controller device key

    $spec.deviceChange[0].device.controllerKey = $scsicontroller

# Create vmdk file

    $spec.deviceChange[0].fileOperation = "create"

    $spec.deviceChange[0].operation = "add"

$vm = Get-View (Get-VM $VMname).ID

    $vm.ReconfigVM_Task($spec)

}

Replace-VM-RDM $vmname $scsiid $rdmname $filename

0 Kudos
1 Solution

Accepted Solutions
M4ttH
Contributor
Contributor

I got it working, it just needed re-ordering and then the Devicename was wrong.

Here's the working script.

Function Replace-VM-RDM {

param($vmname, $scsiid, $rdmname, $filename)

<#

Convert the SCSI address in to Vmware format

#>

$scsicontroller=$null

$scsiid_split=$null

$scsiid_split=$scsiid.split(":")

$scsicontroller=($scsiid_split[0])

# VMware SCSI controller ID in gui is one number higher than the actual controller id

$scsicontroller=[int]$scsicontroller+1

# Vmware expects a conntroller id with 4 chars

$scsicontroller=($scsicontroller.ToString())+"000"

$scsicontroller

# SCSI LUN

$scsilun=$null

# VMware SCSI LUN ID in gui is one number higher than the actual lun id

$scsilun=[int]($scsiid_split[1])#+1

###

$vm = Get-VM -Name "$vmname" | Get-View

IF (!($filename)){

$RDMFile=$rdmname.split(" ")[0]+"_RDM.vmdk"

$filename=(($vm.Config.Files.VmPathName).Replace("$vmname.vmx","$RDMFile"))

}

$esx = Get-View $vm.Runtime.Host

<#

Get CanonicalName for RDM LUN

#>

$rdmCanonicalName=$null

$rdmCanonicalName=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).CanonicalName)

$rdmDevicePath=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).DevicePath)

foreach($dev in $vm.Config.Hardware.Device){

    if(($dev.gettype()).Name -eq "VirtualDisk"){

        if(($dev.Backing.CompatibilityMode -eq "physicalMode") -or

        ($dev.Backing.CompatibilityMode -eq "virtualMode")){

            if (($dev.ControllerKey -eq "$scsicontroller") -and ($dev.UnitNumber -eq "$scsilun")) {

                # Remove Harddisk

                $hd=get-harddisk $vm.name | where {$_.Filename -eq $dev.Backing.FileName}

                $hd | remove-harddisk -confirm:$false -DeletePermanently

                Write-Host "Filename: "$dev.backing.fileName

                Write-Host "Disk Mode: "$dev.backing.diskMode

                $dev.backing.deviceName

                $dev.backing.lunUuid

                $DevKey=$dev.key

                $CapacityInKB=$dev.CapacityInKB

                <#$fileMgr = Get-View (Get-View ServiceInstance).Content.fileManager

                $datacenter = (Get-View (Get-VM $VMname | Get-Datacenter).ID).get_MoRef()

                foreach($disk in $vm.LayoutEx.Disk){

                    if($disk.Key -eq $dev.Key){

                    foreach($chain in $disk.Chain){

                        foreach($file in $chain.FileKey){

                            $name = $vm.LayoutEx.File[$file].Name

                            $fileMgr.DeleteDatastoreFile_Task($name, $datacenter)

                            }

                        }

                    continue

                    }

                }#>

            }

        }

        Elseif (($dev.ControllerKey -eq "$scsicontroller") -and ($dev.UnitNumber -eq "$scsilun")) {Write-Host "Selected SCSI Address [$scsiid] is not a RDM"}

    }

}

#$hd1 = New-HardDisk -VM $vmname -DeviceName $rdmDevicePath -DiskType RawPhysical # this line works

    $spec=$null

    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

    $spec.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (1)

    $spec.deviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec

    # Create vmdk file

    $spec.deviceChange[0].fileOperation = "create"

    $spec.deviceChange[0].operation = "add"

    $spec.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (1)

    $spec.deviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec

    $spec.deviceChange[0].operation = "add"

    $spec.deviceChange[0].fileOperation = "create"

    $spec.deviceChange[0].device = New-Object VMware.Vim.VirtualDisk

    $spec.deviceChange[0].device.key = -100

    $spec.deviceChange[0].device.backing = New-Object VMware.Vim.VirtualDiskRawDiskMappingVer1BackingInfo

    $spec.deviceChange[0].device.backing.fileName = "$filename"

    $spec.deviceChange[0].device.backing.deviceName = (($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).DevicePath)

    $spec.deviceChange[0].device.backing.compatibilityMode = "physicalMode"

    $spec.deviceChange[0].device.backing.diskMode = ""

    $spec.deviceChange[0].device.connectable = New-Object VMware.Vim.VirtualDeviceConnectInfo

    $spec.deviceChange[0].device.connectable.startConnected = $true

    $spec.deviceChange[0].device.connectable.allowGuestControl = $false

    $spec.deviceChange[0].device.connectable.connected = $true

# SCSI controller device key

    $spec.deviceChange[0].device.controllerKey = [int]$scsicontroller

# The UnitNUmber SCSIID 7 is reserved for the Controller - so skip to 8.

    if ($scsilun -eq 6) {$scsilun = $scsilun + 1}

# Take next unit number for HD

    $spec.deviceChange[0].device.unitnumber = [int]$scsilun

    $spec.deviceChange[0].device.capacityInKB = [int]$CapacityInKB

    $vm = Get-View (Get-VM $VMname).ID

    $vm.ReconfigVM($spec)

}

Replace-VM-RDM $vmname $scsiid $rdmname $filename

View solution in original post

0 Kudos
6 Replies
LucD
Leadership
Leadership

Some questions:

  • why do you not add the DeletePermanently switch to the Remove-Harddisk cmdlet ? That way the header file (.VMDK) will be removed as well. And there will be no need to call the DeleteDatastoreFile method
  • For most methods there are 2 variations, the one with _Task at the end and the one without. The one with _Task at the end will call the method in the background, it comes back immediately to your script (similar to the RunAsync switch on some cmdlets). It could be that the file is not yet removed when you reach the call to the ReconfigVM method.

Can you try those changes and see if that makes your function behave like you intend it to do ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
M4ttH
Contributor
Contributor

Thanks for the response,

This script is only part one of the script that I'm writing, in the end it will do the following

1. Remove-RDM from TMPVM, this is a VM that is online at my DR site and is used a file dump location

2. Delete RDM vmdk header file

3. Remove broken RDM from SQL Cluster node

4. Create RDM vmdk header file and attach to SQL Cluster node using correct SCSI ID

At the moment i just need it to do step 1,2,4 but mounting on the same VM.

I'm doing this as SRM doesn't like mounting the vmdk that is setup on the TMPVM , even though i suspend the TMPVM thus freeing up the lock. I ended up needed to manually do it via the GUI and that works fine.

I've added the DeletePermanently switch to Remove-Hardisk and removed the _task from $vm.ReconfigVM. The difference now it that it throws the error to the powershell window instead of the vi client task window.

Below is the error that is being reported.

Exception calling "ReconfigVM" with "1" argument(s): "Incompatible device backing specified for device '0'."

At line:92 char:19

+     $vm.ReconfigVM <<<< ($spec)

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : DotNetMethodException

0 Kudos
LucD
Leadership
Leadership

That error was there, but you didn't see it because the method call was done in the background.

Did you get rid of the DeleteDatastoreFile call as well, now that you have the Remove-Harddisk ammended with the DeletePermanently switch ?

As a matter of fact you can get rid of the call(s) to the ReconfigVM method as well, by using a New-Harddisk cmdlet.

With the DeviceName and the ScsiController parameters you can replace all the functionality from the ReconfigVM method call.

Most, if not all, of your code can be replaced by a call to Remove-Harddisk and New-Harddisk.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
M4ttH
Contributor
Contributor

Yes, i did originally start using the Remove-Hardisk and New-Hardisk, but the New-Harddisk wouldn't let me select a different scsi id, as it was always using the next available one.

This is why I ended up writing the script.

Here's the script at the moment

Function Replace-VM-RDM {

param($vmname, $scsiid, $rdmname, $filename)

<#

Convert the SCSI address in to Vmware format

#>

$scsicontroller=$null

$scsiid_split=$null

$scsiid_split=$scsiid.split(":")

$scsicontroller=($scsiid_split[0])

# VMware SCSI controller ID in gui is one number higher than the actual controller id

$scsicontroller=[int]$scsicontroller+1

# Vmware expects a conntroller id with 4 chars

$scsicontroller=($scsicontroller.ToString())+"000"

$scsicontroller

# SCSI LUN

$scsilun=$null

# VMware SCSI LUN ID in gui is one number higher than the actual lun id

$scsilun=[int]($scsiid_split[1])#+1

###

$vm = Get-VM -Name "$vmname" | Get-View

IF (!($filename)){

$RDMFile=$rdmname.split(" ")[0]+"_RDM.vmdk"

$filename=(($vm.Config.Files.VmPathName).Replace("$vmname.vmx","$RDMFile"))

}

$esx = Get-View $vm.Runtime.Host

<#

Get CanonicalName for RDM LUN

#>

$rdmCanonicalName=$null

$rdmCanonicalName=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).CanonicalName)

$rdmDevicePath=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).DevicePath)

foreach($dev in $vm.Config.Hardware.Device){

    if(($dev.gettype()).Name -eq "VirtualDisk"){

        if(($dev.Backing.CompatibilityMode -eq "physicalMode") -or

        ($dev.Backing.CompatibilityMode -eq "virtualMode")){

            if (($dev.ControllerKey -eq "$scsicontroller") -and ($dev.UnitNumber -eq "$scsilun")) {

                # Remove Harddisk

                $hd=get-harddisk $vm.name | where {$_.Filename -eq $dev.Backing.FileName}

                $hd | remove-harddisk -confirm:$false -DeletePermanently

                Write-Host "Filename: "$dev.backing.fileName

                Write-Host "Disk Mode: "$dev.backing.diskMode

                $dev.backing.deviceName

                $dev.backing.lunUuid

                $DevKey=$dev.key

                $CapacityInKB=$dev.CapacityInKB

                <#$fileMgr = Get-View (Get-View ServiceInstance).Content.fileManager

                $datacenter = (Get-View (Get-VM $VMname | Get-Datacenter).ID).get_MoRef()

                foreach($disk in $vm.LayoutEx.Disk){

                    if($disk.Key -eq $dev.Key){

                    foreach($chain in $disk.Chain){

                        foreach($file in $chain.FileKey){

                            $name = $vm.LayoutEx.File[$file].Name

                            $fileMgr.DeleteDatastoreFile_Task($name, $datacenter)

                            }

                        }

                    continue

                    }

                }#>

            }

        }

        Elseif (($dev.ControllerKey -eq "$scsicontroller") -and ($dev.UnitNumber -eq "$scsilun")) {Write-Host "Selected SCSI Address [$scsiid] is not a RDM"}

    }

}

#$hd1 = New-HardDisk -VM $vmname -DeviceName $rdmDevicePath -DiskType RawPhysical # this line works

    $spec=$null

    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

    $spec.deviceChange = @()

    $spec.deviceChange += New-Object VMware.Vim.VirtualDeviceConfigSpec

    $spec.deviceChange[0].device = New-Object VMware.Vim.VirtualDisk

    $spec.devicechange[0].device.capacityInKB=$CapacityInKB

    $spec.deviceChange[0].device.backing = New-Object VMware.Vim.VirtualDiskRawDiskMappingVer1BackingInfo

    $spec.deviceChange[0].device.backing.fileName=$filename

    $spec.deviceChange[0].device.backing.compatibilityMode ="physicalMode"

    $spec.deviceChange[0].device.backing.diskMode = ""

    $spec.deviceChange[0].device.backing.lunUuid=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).Uuid)

    $spec.deviceChange[0].device.connectable = New-Object VMware.Vim.VirtualDeviceConnectInfo

    $spec.deviceChange[0].device.connectable.startConnected = $true

    $spec.deviceChange[0].device.connectable.allowGuestControl = $false

    $spec.deviceChange[0].device.connectable.connected = $true

# Take next unused device key for HD

    $spec.deviceChange[0].device.key = $DevKey + 1

# The UnitNUmber SCSIID 7 is reserved for the Controller - so skip to 8.

    if ($scsilun -eq 6) {$scsilun = $scsilun + 1}

# Take next unit number for HD

    $spec.deviceChange[0].device.unitnumber = $scsilun

# SCSI controller device key

    $spec.deviceChange[0].device.controllerKey = $scsicontroller

# Create vmdk file

    $spec.deviceChange[0].fileOperation = "create"

    $spec.deviceChange[0].operation = "add"

    $vm = Get-View (Get-VM $VMname).ID

    $vm.ReconfigVM($spec)

}

Replace-VM-RDM $vmname $scsiid $rdmname $filename

0 Kudos
M4ttH
Contributor
Contributor

I got it working, it just needed re-ordering and then the Devicename was wrong.

Here's the working script.

Function Replace-VM-RDM {

param($vmname, $scsiid, $rdmname, $filename)

<#

Convert the SCSI address in to Vmware format

#>

$scsicontroller=$null

$scsiid_split=$null

$scsiid_split=$scsiid.split(":")

$scsicontroller=($scsiid_split[0])

# VMware SCSI controller ID in gui is one number higher than the actual controller id

$scsicontroller=[int]$scsicontroller+1

# Vmware expects a conntroller id with 4 chars

$scsicontroller=($scsicontroller.ToString())+"000"

$scsicontroller

# SCSI LUN

$scsilun=$null

# VMware SCSI LUN ID in gui is one number higher than the actual lun id

$scsilun=[int]($scsiid_split[1])#+1

###

$vm = Get-VM -Name "$vmname" | Get-View

IF (!($filename)){

$RDMFile=$rdmname.split(" ")[0]+"_RDM.vmdk"

$filename=(($vm.Config.Files.VmPathName).Replace("$vmname.vmx","$RDMFile"))

}

$esx = Get-View $vm.Runtime.Host

<#

Get CanonicalName for RDM LUN

#>

$rdmCanonicalName=$null

$rdmCanonicalName=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).CanonicalName)

$rdmDevicePath=(($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).DevicePath)

foreach($dev in $vm.Config.Hardware.Device){

    if(($dev.gettype()).Name -eq "VirtualDisk"){

        if(($dev.Backing.CompatibilityMode -eq "physicalMode") -or

        ($dev.Backing.CompatibilityMode -eq "virtualMode")){

            if (($dev.ControllerKey -eq "$scsicontroller") -and ($dev.UnitNumber -eq "$scsilun")) {

                # Remove Harddisk

                $hd=get-harddisk $vm.name | where {$_.Filename -eq $dev.Backing.FileName}

                $hd | remove-harddisk -confirm:$false -DeletePermanently

                Write-Host "Filename: "$dev.backing.fileName

                Write-Host "Disk Mode: "$dev.backing.diskMode

                $dev.backing.deviceName

                $dev.backing.lunUuid

                $DevKey=$dev.key

                $CapacityInKB=$dev.CapacityInKB

                <#$fileMgr = Get-View (Get-View ServiceInstance).Content.fileManager

                $datacenter = (Get-View (Get-VM $VMname | Get-Datacenter).ID).get_MoRef()

                foreach($disk in $vm.LayoutEx.Disk){

                    if($disk.Key -eq $dev.Key){

                    foreach($chain in $disk.Chain){

                        foreach($file in $chain.FileKey){

                            $name = $vm.LayoutEx.File[$file].Name

                            $fileMgr.DeleteDatastoreFile_Task($name, $datacenter)

                            }

                        }

                    continue

                    }

                }#>

            }

        }

        Elseif (($dev.ControllerKey -eq "$scsicontroller") -and ($dev.UnitNumber -eq "$scsilun")) {Write-Host "Selected SCSI Address [$scsiid] is not a RDM"}

    }

}

#$hd1 = New-HardDisk -VM $vmname -DeviceName $rdmDevicePath -DiskType RawPhysical # this line works

    $spec=$null

    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

    $spec.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (1)

    $spec.deviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec

    # Create vmdk file

    $spec.deviceChange[0].fileOperation = "create"

    $spec.deviceChange[0].operation = "add"

    $spec.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (1)

    $spec.deviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec

    $spec.deviceChange[0].operation = "add"

    $spec.deviceChange[0].fileOperation = "create"

    $spec.deviceChange[0].device = New-Object VMware.Vim.VirtualDisk

    $spec.deviceChange[0].device.key = -100

    $spec.deviceChange[0].device.backing = New-Object VMware.Vim.VirtualDiskRawDiskMappingVer1BackingInfo

    $spec.deviceChange[0].device.backing.fileName = "$filename"

    $spec.deviceChange[0].device.backing.deviceName = (($esx.Config.StorageDevice.ScsiLun | where {$_.DisplayName -eq $rdmname}).DevicePath)

    $spec.deviceChange[0].device.backing.compatibilityMode = "physicalMode"

    $spec.deviceChange[0].device.backing.diskMode = ""

    $spec.deviceChange[0].device.connectable = New-Object VMware.Vim.VirtualDeviceConnectInfo

    $spec.deviceChange[0].device.connectable.startConnected = $true

    $spec.deviceChange[0].device.connectable.allowGuestControl = $false

    $spec.deviceChange[0].device.connectable.connected = $true

# SCSI controller device key

    $spec.deviceChange[0].device.controllerKey = [int]$scsicontroller

# The UnitNUmber SCSIID 7 is reserved for the Controller - so skip to 8.

    if ($scsilun -eq 6) {$scsilun = $scsilun + 1}

# Take next unit number for HD

    $spec.deviceChange[0].device.unitnumber = [int]$scsilun

    $spec.deviceChange[0].device.capacityInKB = [int]$CapacityInKB

    $vm = Get-View (Get-VM $VMname).ID

    $vm.ReconfigVM($spec)

}

Replace-VM-RDM $vmname $scsiid $rdmname $filename

0 Kudos
LucD
Leadership
Leadership

Great


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos