PureStorage.FlashArray.VMware.RDM.psm1

function new-pfaVolRdm {
    <#
    .SYNOPSIS
      Creates a new Raw Device Mapping for a VM
    .DESCRIPTION
      Creates a new volume on a FlashArray and presents it to a VM as a RDM. Optionally can also be created from a snapshot
    .INPUTS
      FlashArray connection, volume name, capacity, virtual machine, SCSI adapter.
    .OUTPUTS
      FlashArray volume name
    .NOTES
      Version: 2.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 05/28/2019
      Purpose/Change: Updated for new connection mgmt
   
    *******Disclaimer:******************************************************
    This scripts are offered "as is" with no warranty. While this
    scripts is tested and working in my environment, it is recommended that you test
    this script in a test lab before using in a production environment. Everyone can
    use the scripts/commands provided here without any written permission but I
    will not be liable for any damage or loss to the system.
    ************************************************************************
    #>


    [CmdletBinding()]
    Param(
            [Parameter(Position=0,ValueFromPipeline=$True)]
            [PurePowerShell.PureArray]$flasharray,
            
            [Parameter(Position=1,mandatory=$true,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]$vm,

            [Parameter(Position=2)]
            [string]$volName,

            [Parameter(Position=3)]
            [int]$sizeInGB,

            [Parameter(Position=4)]
            [int]$sizeInTB,

            [Parameter(Position=5,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]$datastore,

            [Parameter(Position=6,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.ScsiController]$scsiController,

            [Parameter(Position=7)]
            [string]$snapshotName
    )
    if ($null -eq $flasharray)
    {
      $flasharray = checkDefaultFlashArray
    }
    if ($snapshotName -eq "")
    {
        if (($sizeInGB -eq 0) -and ($sizeInTB -eq 0))
        {
            throw "Please enter a size in GB or TB"
        }
        elseif (($sizeInGB -ne 0) -and ($sizeInTB -ne 0)) {
            throw "Please only enter a size in TB or GB, not both."
        }
        elseif ($sizeInGB -ne 0) {
            $volSize = $sizeInGB * 1024 *1024 *1024   
        }
        else {
            $volSize = $sizeInTB * 1024 *1024 *1024 * 1024
        }
    }
    elseif (($snapshotName -ne "") -and (($sizeInGB -ne 0) -or ($sizeInTB -ne 0))) 
    {
        throw "Please enter a snapshot or a size, not both."
    }
    $ErrorActionPreference = "stop"
    if ($volName -eq "")
    {
        $rand = get-random -Maximum 9999 -Minimum 1000
        $volName = "$($vm.Name)-rdm$($rand)"
        if ($volName -notmatch "^[a-zA-Z0-9\-]+$")
        {
            $volName = $volName -replace "[^\w\-]", ""
            $volName = $volName -replace "[_]", ""
            $volName = $volName -replace " ", ""
        }
    }
    if ($null -eq $datastore)
    {
        $vmDatastore = Get-Datastore -vm $vm
        if ($vmDatastore.count -gt 1)
        {
            $datastore = get-datastore (($vm.ExtensionData.Layoutex.file |where-object {$_.name -like "*.vmx*"}).name.split("]")[0].substring(1))
        }
        else {
            $datastore = $vmDatastore[0]
        }
    }
    if ($datastore.type -eq "VVOL")
    {
        throw "The datastore cannot be of type VVols as RDM pointer files are not supported on that type of datastore. Please specify a VMFS or NFS datastore"
    }
    $cluster = $vm | get-cluster
    if ($null -eq $cluster)
    {
        throw "This VM is not on a host in a cluster. Non-clustered hosts are not supported by this script."     
    }
    $hostGroup = $cluster | get-pfaHostGroupfromVcCluster -flasharray $flasharray -ErrorAction Stop
    if ($snapshotName -ne "")
    {
        $newVol = New-PfaVolume -Array $flasharray -VolumeName $volName -Source $snapshotName -ErrorAction Stop
    }
    else {
        $newVol = New-PfaVolume -Array $flasharray -Size $volSize -VolumeName $volName -ErrorAction Stop
    }
    New-PfaHostGroupVolumeConnection -Array $flasharray -VolumeName $newVol.name -HostGroupName $hostGroup.name |Out-Null
    $esxiHosts = $cluster| Get-VMHost 
    foreach ($esxiHost in $esxiHosts)
    {
        $esxi = $esxiHost.ExtensionData
        $storageSystem = Get-View -Id $esxi.ConfigManager.StorageSystem
        $hbas = ($esxihost |Get-VMHostHba |where-object {$_.Type -eq "FibreChannel" -or $_.Type -eq "iSCSI"}).device
        foreach ($hba in $hbas) {
            $storageSystem.rescanHba($hba)
        }
    }
    $newNAA =  "naa.624a9370" + $newVol.serial.toLower()
    if($null -eq $scsiController)
    {
        $controller = $vm |Get-ScsiController 
        if ($controller.count -gt 1)
        {
            $pvSCSIs = $vm |Get-ScsiController |Where-Object {$_.Type -eq "ParaVirtual"}
            if ($pvSCSIs.count -gt 1)
            {
                $pvDisksHigh = 1000
                foreach ($pvSCSI in $pvSCSIs)
                {
                    $pvDisks = ($vm | Get-HardDisk | Where-Object {$_.ExtensionData.ControllerKey -eq $pvSCSI.key}).count
                    if ($pvDisksHigh -ge $pvDisks)
                    {
                        $pvDisksHigh = $pvDisks
                        $controller = $pvSCSI
                    }
                }
            }
            elseif ($pvSCSIs.count -eq 1)
            {
                $controller = $pvSCSIs
            }
            else 
            {
                $lsiSCSIs = $vm |Get-ScsiController 
                if ($lsiSCSIs.count -gt 1)
                {
                    $lsiDisksHigh = 1000
                    foreach ($lsiSCSI in $lsiSCSIs)
                    {
                        $lsiDisks = ($vm | Get-HardDisk | Where-Object {$_.ExtensionData.ControllerKey -eq $lsiSCSI.key}).count
                        if ($lsiDisksHigh -ge $lsiDisks)
                        {
                            $lsiDisksHigh = $lsiDisks
                            $controller = $lsiSCSI
                        }
                    }
                }
                else
                {
                    $controller = $lsiSCSIs
                }
            }
        }   
    } 
    else {
        $controller = $scsiController
    }
    try {
        $newRDM = $vm | new-harddisk -DeviceName "/vmfs/devices/disks/$($newNAA)" -DiskType RawPhysical -Controller $controller -Datastore $datastore -ErrorAction stop
        $rdmDisk = $vm |Get-harddisk |where-object {$_.DiskType -eq "RawPhysical"}|  where-object {$null -ne $_.extensiondata.backing.lunuuid} |Where-Object {("naa." + $_.ExtensionData.Backing.LunUuid.substring(10).substring(0,32)) -eq $newNAA}
        return $rdmDisk
    }
    catch {
        Remove-PfaHostGroupVolumeConnection -Array $flasharray -VolumeName $newvol.name -HostGroupName $hostGroup.name|Out-Null
        Remove-PfaVolumeOrSnapshot -Array $flasharray -Name $newvol.name |Out-Null
        Remove-PfaVolumeOrSnapshot -Array $flasharray -Eradicate:$true -Name $newvol.name |Out-Null
        throw $PSItem
    }       
}
function get-pfaVolfromRDM {
    <#
    .SYNOPSIS
      Retrieves the FlashArray volume that hosts a RDM disk.
    .DESCRIPTION
      Takes in a RDM virtual disk and a FlashArray and returns the volume if found.
    .INPUTS
      FlashArray connection and a virtual disk.
    .OUTPUTS
      Returns FlashArray volume or error if not found.
    .NOTES
      Version: 2.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 05/28/2019
      Purpose/Change: Updated for new connection mgmt
   
    *******Disclaimer:******************************************************
    This scripts are offered "as is" with no warranty. While this
    scripts is tested and working in my environment, it is recommended that you test
    this script in a test lab before using in a production environment. Everyone can
    use the scripts/commands provided here without any written permission but I
    will not be liable for any damage or loss to the system.
    ************************************************************************
    #>


    [CmdletBinding()]
    Param(
            [Parameter(Position=0,mandatory=$True,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.HardDisk]$rdm,

            [Parameter(Position=1,ValueFromPipeline=$True)]
            [PurePowerShell.PureArray[]]$flasharray
    )
      if ($rdm.DiskType -ne 'RawPhysical')
      {
          throw "This is not a physical mode RDM disk. Detected configuration is $($rdm.DiskType)"
      }
      $lun = ("naa." + $rdm.ExtensionData.Backing.LunUuid.substring(10).substring(0,32))
      if ($null -eq $flasharray)
      {
        $flasharray = getAllFlashArrays 
      }
      if ($lun -like 'naa.624a9370*')
      {
          $volSerial = ($lun.ToUpper()).substring(12)
          foreach ($fa in $flasharray)
          {
              $purevol =  Get-PfaVolumes -Array  $fa -Filter "serial='$volSerial'"
              if ($null -ne $purevol)
              {
                $Global:CurrentFlashArray = $fa
                return $purevol
              }
          }
      }
      else {
          throw "Specified RDM is not hosted on FlashArray storage."
      }
      throw "Specified RDM was not found on the passed in FlashArrays."
}
function get-pfaConnectionfromRDM {
  <#
  .SYNOPSIS
    Retrieves the FlashArray connection of a volume that hosts a RDM disk.
  .DESCRIPTION
    Takes in a RDM virtual disk and optionally a set of FlashArray connections and returns the connection if found.
  .INPUTS
    FlashArray connection(s) and a virtual disk.
  .OUTPUTS
    Returns FlashArray connection or error if not found.
  .NOTES
    Version: 2.0
    Author: Cody Hosterman https://codyhosterman.com
    Creation Date: 05/28/2019
    Purpose/Change: Updated for new connection mgmt
 
  *******Disclaimer:******************************************************
  This scripts are offered "as is" with no warranty. While this
  scripts is tested and working in my environment, it is recommended that you test
  this script in a test lab before using in a production environment. Everyone can
  use the scripts/commands provided here without any written permission but I
  will not be liable for any damage or loss to the system.
  ************************************************************************
  #>


  [CmdletBinding()]
  Param(
          [Parameter(Position=0,mandatory=$True,ValueFromPipeline=$True)]
          [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.HardDisk]$rdm,

          [Parameter(Position=1,ValueFromPipeline=$True)]
          [PurePowerShell.PureArray[]]$flasharray
  )
    if ($rdm.DiskType -ne 'RawPhysical')
    {
        throw "This is not a physical mode RDM disk. Detected configuration is $($rdm.DiskType)"
    }
    $lun = ("naa." + $rdm.ExtensionData.Backing.LunUuid.substring(10).substring(0,32))
    if ($null -eq $flasharray)
    {
      $flasharray = getAllFlashArrays 
    }
    if ($lun -like 'naa.624a9370*')
    {
        $volSerial = ($lun.ToUpper()).substring(12)
        foreach ($fa in $flasharray)
        {
            $purevol =  Get-PfaVolumes -Array  $fa -Filter "serial='$volSerial'"
            if ($null -ne $purevol)
            {
              $Global:CurrentFlashArray = $fa
              return $fa
            }
        }
    }
    else {
        throw "Specified RDM is not hosted on FlashArray storage."
    }
    throw "Specified RDM was not found on the passed in FlashArrays."
}
function new-pfaVolRdmSnapshot {
    <#
    .SYNOPSIS
      Creates a new FlashArray snapshot of one or more given RDMs
    .DESCRIPTION
      Takes in a RDM disk and the corresponding FlashArray and creates a snapshot.
    .INPUTS
      FlashArray connection and a RDM disk
    .OUTPUTS
      Returns created snapshot.
    .NOTES
      Version: 2.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 05/31/2019
      Purpose/Change: Updated for new connection mgmt
   
    *******Disclaimer:******************************************************
    This scripts are offered "as is" with no warranty. While this
    scripts is tested and working in my environment, it is recommended that you test
    this script in a test lab before using in a production environment. Everyone can
    use the scripts/commands provided here without any written permission but I
    will not be liable for any damage or loss to the system.
    ************************************************************************
    #>


    [CmdletBinding()]
    Param(
            [Parameter(Position=0)]
            [PurePowerShell.PureArray[]]$flasharray,

            [Parameter(Position=1,mandatory=$True,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.HardDisk[]]$rdm,

            [Parameter(Position=2)]
            [string]$snapshot,

            [Parameter(Position=3)]
            [string]$suffix
    )
    Begin {
        $allSnaps = @()
        if (("" -ne $snapshot) -and ("" -ne $suffix))
        {
            throw "Please only enter in the suffix, the snapshot parameter is being deprecated."
        }
        elseif ("" -ne $snapshot) 
        {
          Write-Warning -Message "The snapshot parameter is being deprecated--please use the suffix parameter instead."  
          $suffix = $snapshot        
        }
    }
    Process {
        foreach ($rdmDisk in $rdm)
        {
            $fa = get-pfaConnectionfromRDM -rdm $rdmDisk -flasharray $flasharray -ErrorAction Stop
            $pureVol = $rdmDisk | get-faVolfromRDM -flasharray $fa -ErrorAction Stop
            $Global:CurrentFlashArray = $fa
            if ($suffix -eq "")
            {
                $newSnapshot = New-PfaVolumeSnapshots -Array $fa -Sources $pureVol.name  
            }
            else {
                $newSnapshot = New-PfaVolumeSnapshots -Array $fa -Sources $pureVol.name -Suffix $suffix
            }
            $allSnaps += $newSnapshot
        }
        
    }
    End {
        return $allSnaps
    }  
}
function get-pfaVolRDMSnapshot {
    <#
    .SYNOPSIS
      Retrieves snapshots of a FlashArray-based RDM
    .DESCRIPTION
      Pass in a RDM disk and this will returns all of the FlashArray snapshots
    .INPUTS
      FlashArray connection and a RDM-based disk.
    .OUTPUTS
      Returns FlashArray snapshot(s).
    .NOTES
      Version: 2.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 05/28/2019
      Purpose/Change: Updated for new connection mgmt
   
    *******Disclaimer:******************************************************
    This scripts are offered "as is" with no warranty. While this
    scripts is tested and working in my environment, it is recommended that you test
    this script in a test lab before using in a production environment. Everyone can
    use the scripts/commands provided here without any written permission but I
    will not be liable for any damage or loss to the system.
    ************************************************************************
    #>


    [CmdletBinding()]
    Param(
            [Parameter(Position=0,mandatory=$True,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.HardDisk]$rdm,

            [Parameter(Position=1,mandatory=$true,ValueFromPipeline=$True)]
            [PurePowerShell.PureArray[]]$flasharray
    )
      if ($null -eq $flasharray)
      {
        $flasharray = getAllFlashArrays 
      }
      $fa = get-pfaConnectionlfromRDM -rdm $rdm -flasharray $flasharray -ErrorAction Stop
      $pureVol = $rdm | get-faVolfromRDM -flasharray $fa 
      $snapshots = Get-PfaVolumeSnapshots -Array $fa -VolumeName $pureVol.name 
      return $snapshots
}
function copy-pfaSnapshotToRDM {
    <#
    .SYNOPSIS
      Input a FlashArray RDM and a snapshot to refresh the RDM
    .DESCRIPTION
      Pass in a RDM disk and a snapshot and it will copy the snapshot to the RDM FlashArray volume
    .INPUTS
      FlashArray connection, a snapshot, and a RDM-based disk.
    .OUTPUTS
      Returns the RDM disk
    .NOTES
      Version: 2.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 05/28/2019
      Purpose/Change: Updated for new connection mgmt
   
    *******Disclaimer:******************************************************
    This scripts are offered "as is" with no warranty. While this
    scripts is tested and working in my environment, it is recommended that you test
    this script in a test lab before using in a production environment. Everyone can
    use the scripts/commands provided here without any written permission but I
    will not be liable for any damage or loss to the system.
    ************************************************************************
    #>


    [CmdletBinding()]
    Param(
            [Parameter(Position=0,mandatory=$True,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.HardDisk]$rdm,

            [Parameter(Position=1,ValueFromPipeline=$True)]
            [PurePowerShell.PureArray[]]$flasharray,

            [Parameter(Position=2)]
            [string]$snapshot,

            [Parameter(Position=3,mandatory=$True)]
            [switch]$offlineConfirm
    )
        if ($offlineConfirm -ne $true)
        {
            throw "FlashArray volumes can be resized online, but VMware does not permit it with RDMs. Please confirm you will allow the RDM to go offline temporarily for the resize operation with the -offlineConfirm parameter."
        }
        if ($snapshot -eq "")
        {
            throw "You must enter a snapshot source"
        }
        if ($null -eq $flasharray)
        {
          $flasharray = getAllFlashArrays 
        }
        $fa = get-pfaConnectionlfromRDM -rdm $rdm -flasharray $flasharray -ErrorAction Stop
        $sourceVol = $rdm | get-faVolfromRDM -flasharray $fa 
        $vm = $rdm.Parent
        $controller = $rdm |Get-ScsiController
        $datastore = $rdm |Get-Datastore
        Remove-HardDisk $rdm -DeletePermanently -Confirm:$false
        $refreshedVol = New-PfaVolume -Array $fa -VolumeName $sourceVol.name -Source $snapshot -Overwrite -ErrorAction Stop
        $snapshotObj = Get-PfaVolumeSnapshot -SnapshotName $snapshot -Array $fa
        $esxiHosts = $rdm.Parent|get-cluster| Get-VMHost 
        foreach ($esxiHost in $esxiHosts)
        {
            $esxi = $esxiHost.ExtensionData
            $storageSystem = Get-View -Id $esxi.ConfigManager.StorageSystem
            $hbas = ($esxihost |Get-VMHostHba |where-object {$_.Type -eq "FibreChannel" -or $_.Type -eq "iSCSI"}).device
            foreach ($hba in $hbas) {
                $storageSystem.rescanHba($hba)
            }
            $storageSystem.RefreshStorageSystem()
        }
        $newNAA =  "naa.624a9370" + $refreshedVol.serial.toLower()
        $updatedRDM = $vm | new-harddisk -DeviceName "/vmfs/devices/disks/$($newNAA)" -DiskType RawPhysical -Controller $controller -Datastore $datastore -ErrorAction stop
        $rdmDisk = $vm |Get-harddisk |where-object {$_.DiskType -eq "RawPhysical"}|  where-object {$null -ne $_.extensiondata.backing.lunuuid} |Where-Object {("naa." + $_.ExtensionData.Backing.LunUuid.substring(10).substring(0,32)) -eq $newNAA}
        return $rdmDisk
}
function set-pfaVolRDMCapacity {
    <#
    .SYNOPSIS
      Resizes the RDM volume
    .DESCRIPTION
      Takes in a new size and resizes the underlying volume and rescans the VMware environment
    .INPUTS
      Takes in a RDM virtual disk, a FlashArray, and a new size.
    .OUTPUTS
      Returns RDM disk.
    .NOTES
      Version: 2.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 05/31/2019
      Purpose/Change: Updated for new connection mgmt
   
    *******Disclaimer:******************************************************
    This scripts are offered "as is" with no warranty. While this
    scripts is tested and working in my environment, it is recommended that you test
    this script in a test lab before using in a production environment. Everyone can
    use the scripts/commands provided here without any written permission but I
    will not be liable for any damage or loss to the system.
    ************************************************************************
    #>


    [CmdletBinding()]
    Param(
            [Parameter(Position=0,mandatory=$True,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.HardDisk]$rdm,

            [Parameter(Position=1,ValueFromPipeline=$True)]
            [PurePowerShell.PureArray[]]$flasharray,

            [Parameter(Position=2)]
            [int]$sizeInGB,

            [Parameter(Position=3)]
            [int]$sizeInTB,

            [Parameter(Position=4)]
            [switch]$truncate,

            [Parameter(Position=5,mandatory=$True)]
            [switch]$offlineConfirm
    )
    if ($offlineConfirm -ne $true)
    {
        throw "FlashArray volumes can be resized online, but VMware does not permit it with RDMs. Please confirm you will allow the RDM to go offline temporarily for the resize operation with the -offlineConfirm parameter."
    }
    if (($sizeInGB -eq 0) -and ($sizeInTB -eq 0))
    {
        throw "Please enter a size in GB or TB"
    }
    elseif (($sizeInGB -ne 0) -and ($sizeInTB -ne 0)) {
        throw "Please only enter a size in TB or GB, not both."
    }
    elseif ($sizeInGB -ne 0) {
        $volSize = $sizeInGB * 1024 *1024 *1024   
    }
    else {
        $volSize = $sizeInTB * 1024 *1024 *1024 * 1024
    }
    if ($null -eq $flasharray)
    {
      $flasharray = getAllFlashArrays 
    }
    $fa = get-pfaConnectionlfromRDM -rdm $rdm -flasharray $flasharray -ErrorAction Stop
    $pureVol = $rdm | get-faVolfromRDM -flasharray $fa 
    $vm = $rdm.Parent
    $controller = $rdm |Get-ScsiController
    $datastore = $rdm |Get-Datastore
    if (($truncate -ne $true) -and ($pureVol.size -gt $volSize))
    {
        throw "This operation will shrink the target RDM--please ensure this is expected and if so, please rerun the operation with the -truncate parameter."
    }
    Remove-HardDisk $rdm -DeletePermanently -Confirm:$false
    if ($truncate -eq $true)
    {
        $expandedVol = Resize-PfaVolume -Array $fa -VolumeName $pureVol.name -NewSize $volSize -Truncate
    }
    else {
        $expandedVol = Resize-PfaVolume -Array $fa -VolumeName $pureVol.name -NewSize $volSize 
    }
    $esxiHosts = $rdm.Parent|get-cluster| Get-VMHost 
    foreach ($esxiHost in $esxiHosts)
    {
        $esxi = $esxiHost.ExtensionData
        $storageSystem = Get-View -Id $esxi.ConfigManager.StorageSystem
        $hbas = ($esxihost |Get-VMHostHba |where-object {$_.Type -eq "FibreChannel" -or $_.Type -eq "iSCSI"}).device
        foreach ($hba in $hbas) {
            $storageSystem.rescanHba($hba)
        }
        $storageSystem.RefreshStorageSystem()
    }
    $expandedVol = Get-PfaVolume -Name $expandedVol.name -Array $flasharray
    $newNAA =  "naa.624a9370" + $expandedVol.serial.toLower()
    $vm | new-harddisk -DeviceName "/vmfs/devices/disks/$($newNAA)" -DiskType RawPhysical -Controller $controller -Datastore $datastore -ErrorAction stop |Out-Null
    $rdmDisk = $vm |Get-harddisk |where-object {$_.DiskType -eq "RawPhysical"}|  where-object {$null -ne $_.extensiondata.backing.lunuuid} |Where-Object {("naa." + $_.ExtensionData.Backing.LunUuid.substring(10).substring(0,32)) -eq $newNAA}
    return $rdmDisk
}
function remove-pfaVolRDM {
    <#
    .SYNOPSIS
      Removes one or more RDM volumes
    .DESCRIPTION
      Deletes the virtual disk pointer to the RDM and deletes the volume on the FlashArray. Volume will be deleted permanently in 24 hours
    .INPUTS
      Takes in one or more RDM virtual disks and optionally one or more FlashArray connections.
    .OUTPUTS
      Returns destroyed FA volume(s).
    .NOTES
      Version: 2.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 05/28/2019
      Purpose/Change: Updated for new connection mgmt
   
    *******Disclaimer:******************************************************
    This scripts are offered "as is" with no warranty. While this
    scripts is tested and working in my environment, it is recommended that you test
    this script in a test lab before using in a production environment. Everyone can
    use the scripts/commands provided here without any written permission but I
    will not be liable for any damage or loss to the system.
    ************************************************************************
    #>


    [CmdletBinding()]
    Param(
            [Parameter(Position=0,mandatory=$True,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.HardDisk[]]$rdm,

            [Parameter(Position=1)]
            [PurePowerShell.PureArray[]]$flasharray
    )
    Begin {
        $destroyedVols = @()
        $esxiHosts = @()
    }
    Process {
        foreach ($rdmDisk in $rdm)
        {
            if ($null -eq $flasharray)
            {
              $flasharray = getAllFlashArrays 
            }
            $fa = get-pfaConnectionlfromRDM -rdm $rdmDisk -flasharray $flasharray
            $pureVol = $rdmDisk | get-faVolfromRDM -flasharray $fa 
            $esxiHosts += $rdmDisk.Parent|get-cluster| Get-VMHost 
            Remove-HardDisk $rdmDisk -DeletePermanently -Confirm:$false
            $hostConnections = Get-PfaVolumeHostConnections -Array $fa -VolumeName $pureVol.name
            if ($hostConnections.count -gt 0)
            {
                foreach ($hostConnection in $hostConnections)
                {
                    Remove-PfaHostVolumeConnection -Array $fa -VolumeName $pureVol.name -HostName $hostConnection.host |Out-Null
                } 
            }
            $hostGroupConnections = Get-PfaVolumeHostGroupConnections -Array $fa -VolumeName $pureVol.name
            if ($hostGroupConnections.count -gt 0)
            {
                $hostGroupConnections = $hostGroupConnections.hgroup |Select-Object -unique
                foreach ($hostGroupConnection in $hostGroupConnections)
                {
                    Remove-PfaHostGroupVolumeConnection -Array $fa -VolumeName $pureVol.name -HostGroupName $hostGroupConnection |Out-Null
                } 
            }
          $destroyedVol =  Remove-PfaVolumeOrSnapshot -Array $fa -Name $pureVol.name 
          $destroyedVols += $destroyedVol
        }
    }
    End {
        $esxiHostsUnique = $esxiHosts |Select-Object -Unique
        foreach ($esxiHost in $esxiHostsUnique)
        {
            $esxi = $esxiHost.ExtensionData
            $storageSystem = Get-View -Id $esxi.ConfigManager.StorageSystem
            $hbas = ($esxihost |Get-VMHostHba |where-object {$_.Type -eq "FibreChannel" -or $_.Type -eq "iSCSI"}).device
            foreach ($hba in $hbas) {
                $storageSystem.rescanHba($hba)
            }
        }
        return $destroyedVols
    }  
}
function convert-pfaVolRDMtoVvol {
    <#
    .SYNOPSIS
      Converts a RDM to a VVol
    .DESCRIPTION
      Removes the RDM from the virtual machine and copies it to a new VVol and destroys the old RDM.
    .INPUTS
      Takes in a RDM virtual disk, a FlashArray connection, and optionally a VVol datastore.
    .OUTPUTS
      Returns the new VVol virtual disk.
    .NOTES
      Version: 2.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 05/29/2019
      Purpose/Change: Updated for new connection mgmt
   
    *******Disclaimer:******************************************************
    This scripts are offered "as is" with no warranty. While this
    scripts is tested and working in my environment, it is recommended that you test
    this script in a test lab before using in a production environment. Everyone can
    use the scripts/commands provided here without any written permission but I
    will not be liable for any damage or loss to the system.
    ************************************************************************
    #>


    [CmdletBinding()]
    Param(
            [Parameter(Position=0,mandatory=$True,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.VirtualDevice.HardDisk]$rdm,

            [Parameter(Position=1,mandatory=$true,ValueFromPipeline=$True)]
            [PurePowerShell.PureArray[]]$flasharray,

            [Parameter(Position=2,ValueFromPipeline=$True)]
            [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]$datastore,

            [Parameter(Position=3)]
            [switch]$offlineConfirm
    )
    $vm = $rdm.Parent
    if (($vm.PowerState -ne "PoweredOff") -and ($offlineConfirm -ne $true))
    {
        throw "The RDM to VVol migration is an offline process--please either shut down the VM or confirm this downtime with the -offlineConfirm parameter"
    }   
    if ($null -eq $flasharray)
    {
      $flasharray = getAllFlashArrays 
    }
    $fa = get-pfaConnectionlfromRDM -flasharray $flasharray -rdm $rdm -ErrorAction Stop
    $sourceVol = $rdm|get-faVolfromRDM -flasharray $fa -ErrorAction Stop
    $arraySerial = (Get-PfaArrayAttributes -array $fa).id
    if ($null -eq $datastore)
    {
        $datastores = $vm |get-vmhost |Get-Datastore |Where-Object {$_.Type -eq "VVOL"}
        foreach ($checkDatastore in $datastores)
        {
            if ($arraySerial -eq $checkDatastore.ExtensionData.Info.VvolDS.StorageArray[0].uuid.Substring(16))
            {
                #finding first VVol datastore on host running VM on same FlashArray
                $datastore = $checkDatastore
                break
            }
        }
        if ($null -eq $datastore)
        {
            throw "No VVol datastore found on ESXi host for input array. Please ensure one is mounted."
        }
    }
    else {
        if ($arraySerial -ne $datastore.ExtensionData.Info.VvolDS.StorageArray[0].uuid.Substring(16))
        {
            throw "The input datastore is not on the same array as the input FlashArray connection."
        }
    }
    $controller = $rdm |Get-ScsiController
    $volSize = $rdm.CapacityGB
    remove-faVolRDM -rdm $rdm -flasharray $fa -ErrorAction Stop |Out-Null
    $vvolVmdk = $vm | new-harddisk -CapacityGB $volSize -Controller $controller -Datastore $datastore -ErrorAction stop
    $vvolUuid = $vvolVmdk |get-vvolUuidFromHardDisk
    $targetVol = get-pfaVolumeNameFromVvolUuid -flasharray $fa -vvolUUID $vvolUuid
    Restore-PfaDestroyedVolume -Array $fa -Name $sourceVol.name |Out-Null
    New-PfaVolume -Array $fa -VolumeName $targetVol -Source $sourceVol.name -Overwrite -ErrorAction Stop |Out-Null
    Remove-PfaVolumeOrSnapshot -Array $fa -Name $sourceVol.name |Out-Null
    return $vvolVmdk
}
function checkDefaultFlashArray{
    if ($null -eq $Global:DefaultFlashArray)
    {
        throw "You must pass in a FlashArray connection or create a default FlashArray connection with new-pfaconnection"
    }
    else 
    {
        return $Global:DefaultFlashArray
    }
}
function getAllFlashArrays {
  if ($null -ne $Global:AllFlashArrays)
  {
      return $Global:AllFlashArrays
  }
  else
  {
      throw "Please either pass in one or more FlashArray connections or create connections via the new-pfaConnection cmdlet."
  }
}
New-Alias -Name new-faVolRdm -Value new-pfaVolRdm
New-Alias -Name set-faVolRDMCapacity -Value set-pfaVolRDMCapacity
New-Alias -Name copy-faSnapshotToRDM -Value copy-pfaSnapshotToRDM
New-Alias -Name get-faVolRDMSnapshots -Value get-pfaVolRDMSnapshot
New-Alias -Name new-faVolRdmSnapshot -Value new-pfaVolRdmSnapshot
New-Alias -Name get-faVolfromRDM -Value get-pfaVolfromRDM
New-Alias -Name remove-faVolRDM -Value remove-pfaVolRDM
New-Alias -Name convert-faVolRDMtoVvol -Value convert-pfaVolRDMtoVvol