PureStorage.FlashArray.VMware.VMFS.psm1

$ErrorActionPreference = 'Stop'
function Get-PfaVmfsVol {
    <#
    .SYNOPSIS
      Retrieves the FlashArray volume that hosts a VMFS datastore.
    .DESCRIPTION
      Takes in a VMFS datastore and one or more FlashArrays and returns the volume if found.
    .INPUTS
      FlashArray connection(s) and a VMFS datastore.
    .OUTPUTS
      Returns FlashArray volume or null if not found.
    .NOTES
      Version: 3.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 12/17/2019
      Purpose/Change: Added parameter sets, validation
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ $fa = New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore myVMFS
      PS C:\ Get-PfaVMFSVol -datastore $ds -flasharray $fa
       
      Returns the volume that hosts the VMFS datastore.
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ New-PfaConnection -endpoint flasharray-x20-1 -credentials $faCreds -nondefaultArray
      PS C:\ $ds = get-datastore myVMFS
      PS C:\ Get-PfaVMFSVol -datastore $ds
       
      Returns the volume that hosts the VMFS datastore by finding it on one of the connected FlashArrays.
 
    *******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)]
            [ValidateScript({
              if ($_.Type -ne 'VMFS')
              {
                  throw "The entered datastore is not a VMFS datastore. It is type $($_.Type). Please only enter a VMFS datastore"
              }
              else {
                $true
              }
            })]
            [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]$Datastore,

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

    if ($null -eq $flasharray)
    {
        $fa = get-pfaConnectionOfDatastore -datastore $datastore
    }
    else {
      $fa = get-pfaConnectionOfDatastore -datastore $datastore -flasharrays $flasharray
    }
    $pureVolumes = New-PfaRestOperation -resourceType volume -restOperationType GET -flasharray $fa -SkipCertificateCheck
    $lun = $datastore.ExtensionData.Info.Vmfs.Extent.DiskName |select-object -unique
    $volserial = ($lun.ToUpper()).substring(12)
    $purevol = $purevolumes | where-object { $_.serial -eq $volserial }
    if ($null -ne $purevol.name)
    {
        return $purevol
    }
    else {
        throw "The volume was not found."
    }
}
function New-PfaVmfs {
    <#
    .SYNOPSIS
      Create a new VMFS on a new FlashArray volume
    .DESCRIPTION
      Creates a new FlashArray-based VMFS and presents it to a cluster.
    .INPUTS
      FlashArray connection, a vCenter cluster, a volume size, and name.
    .OUTPUTS
      Returns a VMFS object.
    .NOTES
      Version: 3.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 12/23/2019
      Purpose/Change: Added parameter sets, validation and creation from snapshot
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ New-PfaVmfs -cluster (get-cluster MountainView) -volName codytest0001 -sizeInTB 12
       
      Creates a 12 TB VMFS for a cluster named MountainView on the default FlashArray connection
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ $fa = New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ New-PfaVmfs -cluster (get-cluster MountainView) -volName codytest0002 -sizeInGB 16384 -flasharray $fa
       
      Creates a 16384 GB VMFS for a cluster named MountainView on the specified FlashArray connection
 
    *******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)]
            [VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]$Cluster,

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

            [Parameter(ParameterSetName='GB',Position=2,mandatory=$true)]
            [Parameter(ParameterSetName='TB',Position=2,mandatory=$true)]
            [Parameter(ParameterSetName='Snapshot',Position=5)]
            [ValidateScript({
              if (($_ -match "^[A-Za-z][a-zA-Z0-9\-_]+[a-zA-Z0-9]$") -and ($_.length -lt 64))
              {
                $true
              }
              else {
                throw "The name must be no more than 63 characters, start with a letter, and consist of only numbers, letters, and dashes."
              }
            })]
            [string]$VolName,

            [ValidateRange(1,63488)]
            [Parameter(ParameterSetName='GB',Position=3)]
            [int]$SizeInGB,

            [ValidateRange(1,62)]
            [Parameter(ParameterSetName='TB',Position=4)]
            [int]$SizeInTB,

            [Parameter(ParameterSetName='Snapshot',Position=5,mandatory=$true)]
            [string]$SnapName
    )
    Begin {
        if ($sizeInGB -ne 0) {
            $volSize = $sizeInGB * 1024 *1024 *1024   
        }
        elseif ($sizeInTB -ne 0) {
            $volSize = $sizeInTB * 1024 *1024 *1024 * 1024
        }
        $allFAs = @()
        $newNAAs = @()
        $volNames = @()
        $hostGroupNames = @()
        $oneVolume = 0
        $newDatastores = @()
    }
    Process 
    {
        if ($null -eq $flasharray)
        {
          $flasharray = checkDefaultFlashArray
        }
        if ($null -eq $volSize)
        {
          foreach ($fa in $flasharray)
          {
            $snapshot = $null
            $snapshot = New-PfaRestOperation -resourceType volume/$($snapName) -restOperationType GET -flasharray $fa -SkipCertificateCheck -queryFilter "?snap=true"
            if ($null -ne $snapshot)
            {
              break
            }
          }
          if ([string]::IsNullOrEmpty($volName))
          {
            $newDatastores = New-PfaVmfsFromSnapshot -cluster $cluster -flasharray $fa -snapName $snapshot.name
          }
          else {
            $newDatastores = New-PfaVmfsFromSnapshot -cluster $cluster -flasharray $fa -snapName $snapshot.name -volumeName $volName
          }
          $Global:CurrentFlashArray = $fa
        }
        else 
        {
          foreach ($fa in $flasharray)
          {
            try {
              $hostGroup = $cluster | get-pfaHostGroupfromVcCluster -flasharray $fa
            }  
            catch 
            {
                for ($h =0; $h -lt $volNames.Count; $h++)
                {
                  New-PfaRestOperation -resourceType "hgroup/$($hostGroupNames[$h])/volume/$($volNames[$h])" -restOperationType DELETE -flasharray $allFAs[$h] -SkipCertificateCheck |Out-Null
                  New-PfaRestOperation -resourceType "volume/$($volNames[$h])" -restOperationType DELETE -flasharray $allFAs[$h] -SkipCertificateCheck |Out-Null
                  New-PfaRestOperation -resourceType "volume/$($volNames[$h])" -restOperationType DELETE -flasharray $allFAs[$h] -SkipCertificateCheck -queryFilter "?eradicate=true" |Out-Null
                }
            }
            if ($oneVolume -gt 0)
            {
              if ($oneVolume -eq 1)
              {
                $nameSuffix = ("-" + (get-random -Maximum 9999 -Minimum 1000))
                New-PfaRestOperation -resourceType "volume/$($volName)" -restOperationType PUT -flasharray $lastFA -jsonBody "{`"name`":`"$($volName)$($nameSuffix)`"}" -SkipCertificateCheck |Out-Null
                $volNames[0] = ($volName + "-" + $nameSuffix)
                $newName = ($volName + "-" + (get-random -Maximum 9999 -Minimum 1000))
              }
              else {
                $newName = ($volName + "-" + (get-random -Maximum 9999 -Minimum 1000))
              }
            }
            else {
              $newName = $volName
            }
            $newVol = New-PfaRestOperation -resourceType "volume/$($newName)" -restOperationType POST -flasharray $fa -jsonBody "{`"size`":`"$($volSize)`"}" -SkipCertificateCheck -ErrorAction Stop
            $Global:CurrentFlashArray = $fa
            $lastFA = $fa
            New-PfaRestOperation -resourceType "hgroup/$($hostGroup.name)/volume/$($newVol.name)" -restOperationType POST -flasharray $fa -SkipCertificateCheck -ErrorAction Stop |Out-Null
            $newNAAs +=  "naa.624a9370" + $newVol.serial.toLower()
            $allFAs += $fa
            $volNames += $newVol.name
            $hostGroupNames += $hostGroup.name 
            $oneVolume++
          }
        }
    }
    End 
    {
      if ($newDatastores.count -lt 1)
      {
        $esxi = $cluster | get-vmhost | where-object {($_.version -like '5.5.*') -or ($_.version -like '6.*') -or ($_.version -like '7.*')}| where-object {($_.ConnectionState -eq 'Connected')} |Select-Object -last 1
        $cluster| Get-VMHost | Get-VMHostStorage -RescanAllHba |Out-Null
        $ESXiApiVersion = $esxi.ExtensionData.Summary.Config.Product.ApiVersion
        $varCount = 0
        foreach ($newNAA in $newNAAs)
        {  
          Write-Debug -Message $newNAA
            try 
            {
                if (($ESXiApiVersion -eq "5.5") -or ($ESXiApiVersion -eq "6.0") -or ($ESXiApiVersion -eq "5.1"))
                {
                    $newVMFS = $esxi |new-datastore -name $volNames[$varCount] -vmfs -Path $newNAAs[$varCount] -FileSystemVersion 5 -ErrorAction Stop
                }
                else
                {
                    $newVMFS = $esxi |new-datastore -name $volNames[$varCount] -vmfs -Path $newNAAs[$varCount] -FileSystemVersion 6 -ErrorAction Stop
                }
                $newDatastores += $newVMFS
            }
            catch {
                Write-Error $Global:Error[0]
                New-PfaRestOperation -resourceType "hgroup/$($hostGroupNames[$varCount])/volume/$($volNames[$varCount])" -restOperationType DELETE -flasharray $allFAs[$varCount] -SkipCertificateCheck |Out-Null
                New-PfaRestOperation -resourceType "volume/$($volNames[$varCount])" -restOperationType DELETE -flasharray $allFAs[$varCount] -SkipCertificateCheck |Out-Null
                New-PfaRestOperation -resourceType "volume/$($volNames[$varCount])" -restOperationType DELETE -flasharray $allFAs[$varCount] -SkipCertificateCheck -queryFilter "?eradicate=true" |Out-Null
            }
            $varCount++
        }
      }
      return $newDatastores
    }
}
function Add-PfaVmfsToCluster {
    <#
    .SYNOPSIS
      Add an existing FlashArray-based VMFS to another VMware cluster.
    .DESCRIPTION
      Takes in a vCenter Cluster and a datastore and the corresponding FlashArray
    .INPUTS
      FlashArray connection, a vCenter cluster, and a datastore
    .OUTPUTS
      Returns the FlashArray host group connection.
    .NOTES
      Version: 2.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 05/26/2019
      Purpose/Change: Updated for new connection mgmt
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ Add-PfaVmfsToCluster -cluster (get-cluster Cupertino) -datastore $ds
       
      Adds an existing datastore to another VMware cluster. The FlashArray connection is discovered in the default connection.
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ $fa = New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ Add-PfaVmfsToCluster -cluster (get-cluster Cupertino) -datastore $ds -flasharray $fa
       
      Adds an existing datastore to another VMware cluster.
    *******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.Inventory.Cluster[]]$Cluster,

            [Parameter(Position=1)]
            [PurePowerShell.PureArray[]]$Flasharray,

            [Parameter(Position=2,mandatory=$true)]
            [ValidateScript({
              if ($_.Type -ne 'VMFS')
              {
                  throw "The entered datastore is not a VMFS datastore. It is type $($_.Type). Please only enter a VMFS datastore"
              }
              else {
                $true
              }
            })]
            [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]$Datastore
    )
    Begin {
        $faConnections = @()
        if ($null -eq $flasharray)
        {
          $fa = get-pfaConnectionOfDatastore -datastore $datastore -ErrorAction Stop
        }
        else 
        {
          $fa = get-pfaConnectionOfDatastore -datastore $datastore -flasharrays $flasharray -ErrorAction Stop
        }
    }
    Process 
    {
        foreach ($cs in $cluster)
        {
            $pureVol = $datastore | get-pfaVolfromVMFS -flasharray $fa -ErrorAction Stop
            $hostGroup = get-pfaHostGroupfromVcCluster -flasharray $fa -ErrorAction Stop -cluster $cs
            if ($hostGroup.count -gt 1)
            {
              throw "This cluster spans more than one host group, please ensure this is a 1:1 relationship."
            }
            else 
            {
              try {
                $faConnection = New-PfaRestOperation -resourceType "hgroup/$($hostGroup.name)/volume/$($pureVol.name)" -restOperationType POST -flasharray $fa -SkipCertificateCheck -ErrorAction Stop
              }
              catch {
                Write-Error $Global:Error[0]
                continue 
              }
              $cs| Get-VMHost | Get-VMHostStorage -RescanAllHba -RescanVmfs -ErrorAction Stop |Out-Null
              $faConnections += $faConnection
              $Global:CurrentFlashArray = $fa
            } 
        }
    }
    End 
    {
        return $faConnections
    }
}
function Set-PfaVmfsCapacity {
    <#
    .SYNOPSIS
      Increase the size of a FlashArray-based VMFS datastore.
    .DESCRIPTION
      Takes in a datastore, the corresponding FlashArray, and a new size. Both the volume and the VMFS will be grown.
    .INPUTS
      FlashArray connection, a size, and a datastore
    .OUTPUTS
      Returns the datastore.
    .NOTES
      Version: 2.1
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 01/04/2019
      Purpose/Change: Updated to remove code that causes deprecation warning from VMware
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ $ds | Set-PfaVmfsCapacity -sizeInTB 16
       
      Expands the size of the VMFS datastore to 16 TB. The FlashArray connection is discovered in the default connection.
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ $fa = New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ $ds | Set-PfaVmfsCapacity -sizeInTB 16 -flasharray $fa
       
      Expands the size of the VMFS datastore to 16 TB.
    *******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)]
            [ValidateScript({
              if ($_.Type -ne 'VMFS')
              {
                  throw "The entered datastore is not a VMFS datastore. It is type $($_.Type). Please only enter a VMFS datastore"
              }
              else {
                $true
              }
            })]
            [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]$Datastore,

            [ValidateRange(1,63488)]
            [Parameter(ParameterSetName='GB',Position=2,mandatory=$true)]
            [int]$SizeInGB,

            [ValidateRange(1,62)]
            [Parameter(ParameterSetName='TB',Position=3,mandatory=$true)]
            [int]$SizeInTB
    )
   if ($sizeInGB -ne 0) {
        $volSize = $sizeInGB * 1024 *1024 *1024   
    }
    else {
        $volSize = $sizeInTB * 1024 *1024 *1024 * 1024
    }
    if ($null -eq $flasharray)
    {
        $fa = get-pfaConnectionOfDatastore -datastore $datastore -ErrorAction Stop
    }
    else 
    {
        $fa = get-pfaConnectionOfDatastore -datastore $datastore -flasharrays $flasharray -ErrorAction Stop
    }
    $pureVol = $datastore | get-pfaVolfromVMFS -flasharray $fa -ErrorAction Stop
    if ($volSize -le $pureVol.size)
    {
        throw "The new specified size, $($volsize/1024/1024/1024) GB, is smaller than the current size, $($pureVol.size/1024/1024/1024) GB. ESXi does not permit VMFS volumes to be shrunk--please specify a size larger than the existing."
    }
    New-PfaRestOperation -resourceType "volume/$($pureVol.name)" -restOperationType PUT -flasharray $fa -jsonBody "{`"size`":$($volSize)}" -SkipCertificateCheck |Out-Null
    $Global:CurrentFlashArray = $fa
    foreach ($dsHost in $datastore.ExtensionData.Host.Key)
    {
      #had to change this as get-vmhost -datastore spits out a deprecation error.
      get-vmhost -id "HostSystem-$($dsHost.value)" | Get-VMHostStorage -RescanAllHba -RescanVmfs -ErrorAction Stop  -WarningAction SilentlyContinue |Out-Null
    }
    $esxiView = Get-View -Id ($Datastore.ExtensionData.Host |Select-Object -last 1 | Select-Object -ExpandProperty Key)
    $datastoreSystem = Get-View -Id $esxiView.ConfigManager.DatastoreSystem
    $expandOptions = $datastoreSystem.QueryVmfsDatastoreExpandOptions($datastore.ExtensionData.MoRef)
    $expandedDS = $datastoreSystem.ExpandVmfsDatastore($datastore.ExtensionData.MoRef,$expandOptions[0].spec)
    $ds = get-datastore -Id $expandedDS
    return $ds 
}
function Get-PfaVmfsSnapshot {
    <#
    .SYNOPSIS
      Retrieve all of the FlashArray snapshots of a given VMFS volume
    .DESCRIPTION
      Takes in a datastore and the corresponding FlashArray and returns any available snapshots.
    .INPUTS
      FlashArray connection and a datastore
    .OUTPUTS
      Returns any snapshots.
    .NOTES
      Version: 3.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 12/23/2019
      Purpose/Change: Updated for new connection mgmt
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ $ds |Get-PfaVmfsSnapshot
       
      Returns all snapshots on the array for the VMFS. The FlashArray connection is discovered in the default connection.
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ $ds |Get-PfaVmfsSnapshot
       
      Returns all snapshots on the array for the VMFS. The FlashArray connection is discovered in the default connection.
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ $fa = New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ $ds |Get-PfaVmfsSnapshot -flasharray $fa
       
      Returns all snapshots on the array for the VMFS. The FlashArray connection is specified.
 
    *******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)]
            [ValidateScript({
              if ($_.Type -ne 'VMFS')
              {
                  throw "The entered datastore is not a VMFS datastore. It is type $($_.Type). Please only enter a VMFS datastore"
              }
              else {
                $true
              }
            })]
            [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]$Datastore
    )
    if ($null -eq $flasharray)
    {
        $fa = get-pfaConnectionOfDatastore -datastore $datastore -ErrorAction Stop
    }
    else 
    {
        $fa = get-pfaConnectionOfDatastore -datastore $datastore -flasharrays $flasharray -ErrorAction Stop
    }
    $pureVol = $datastore | get-pfaVolfromVMFS -flasharray $fa -ErrorAction Stop
    $volSnapshots = New-PfaRestOperation -resourceType "volume/$($pureVol.name)" -restOperationType GET -flasharray $fa -SkipCertificateCheck -queryFilter "?snap=true"
    $Global:CurrentFlashArray = $fa
    return $volSnapshots
}
function New-PfaVmfsSnapshot {
    <#
    .SYNOPSIS
      Creates a new FlashArray snapshot of a given VMFS volume
    .DESCRIPTION
      Takes in a datastore and the corresponding FlashArray and creates a snapshot.
    .INPUTS
      FlashArray connection and a datastore
    .OUTPUTS
      Returns created snapshot.
    .NOTES
      Version: 3.0
      Author: Cody Hosterman https://codyhosterman.com
      Creation Date: 12/23/2019
      Purpose/Change: Added examples and parameter sets/validation.
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ $ds |New-PfaVmfsSnapshot
       
      Create a snapshot of the VMFS volume with default snapshot name. The FlashArray connection is discovered in the default connection.
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ $ds |New-PfaVmfsSnapshot -suffix codysnap1
       
      Create a snapshot of the VMFS volume with the specified snapshot name. The FlashArray connection is discovered in the default connection.
    .EXAMPLE
      PS C:\ $faCreds = get-credential
      PS C:\ $fa = New-PfaConnection -endpoint flasharray-m20-2 -credentials $faCreds -defaultArray
      PS C:\ $ds = get-datastore codytest0001
      PS C:\ $ds |New-PfaVmfsSnapshot -suffix codysnap1 -flasharray $fa
       
      Create a snapshot of the VMFS volume with the specified snapshot name. The FlashArray connection is specified.
 
    *******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(ParameterSetName='datastore',Position=1,mandatory=$true,ValueFromPipeline=$True)]
            [Parameter(ParameterSetName='suffix',Position=1,mandatory=$true,ValueFromPipeline=$True)]
            [ValidateScript({
              if ($_.Type -ne 'VMFS')
              {
                  throw "The entered datastore is not a VMFS datastore. It is type $($_.Type). Please only enter a VMFS datastore"
              }
              else {
                $true
              }
            })]
            [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore[]]$Datastore,

            [ValidateScript({
              if (($_ -match "^[A-Za-z][a-zA-Z0-9\-_]+[a-zA-Z0-9]$") -and ($_.length -lt 64))
              {
                $true
              }
              else {
                throw "Volume name must be between 1 and 63 characters (alphanumeric, _ and -) in length and begin and end with a letter or number. The name must include at least one letter, _, or -"
              }
            })]
            [Parameter(ParameterSetName='suffix',Position=3,mandatory=$true)]
            [string]$suffix
    )
    Begin 
    {
      $newSnapshots = @()
    }
    Process 
    {
        foreach ($ds in $datastore)
        {
            if ($null -eq $flasharray)
            {
                $fa = get-pfaConnectionOfDatastore -datastore $ds -ErrorAction Stop
            }
            else 
            {
                $fa = get-pfaConnectionOfDatastore -datastore $ds -flasharrays $flasharray -ErrorAction Stop
            }
            $pureVol = $ds | get-pfaVolfromVMFS -flasharray $fa -ErrorAction Stop
            $Global:CurrentFlashArray = $fa
            if ($suffix -ne "")
            {
              $newSnapshots += New-PfaRestOperation -resourceType "volume" -restOperationType POST -flasharray $fa -jsonBody "{`"snap`":true,`"source`":[`"$($pureVol.name)`"],`"suffix`":`"$($suffix)`"}" -SkipCertificateCheck -ErrorAction Stop
            }
            else {
              $newSnapshots += New-PfaRestOperation -resourceType "volume" -restOperationType POST -flasharray $fa -jsonBody "{`"snap`":true,`"source`":[`"$($pureVol.name)`"]}" -SkipCertificateCheck -ErrorAction Stop
            }
            
        }
    }
    End {
      return $newSnapshots
    }
}

##Private functions
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."
  }
}
function New-PfaVmfsFromSnapshot {
  <#
  .SYNOPSIS
    Mounts a copy of a VMFS datastore to a VMware cluster from a FlashArray snapshot.
  .DESCRIPTION
    Takes in a snapshot name, the corresponding FlashArray, and a cluster. The VMFS copy will be resignatured and mounted.
  .INPUTS
    FlashArray connection, a snapshotName, and a cluster.
  .OUTPUTS
    Returns the new datastore.
  .NOTES
    Version: 1.0
    Author: Cody Hosterman https://codyhosterman.com
    Creation Date: 10/24/2018
    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.Inventory.Cluster]$cluster,

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

          [Parameter(Position=2,mandatory=$true)]
          [string]$snapName,

          [Parameter(Position=3)]
          [string]$volumeName
  )
  if ([string]::IsNullOrWhiteSpace($volumeName))
  {
    $volumeName = "newVMFSfromsnapshot-" + (Get-Random -Minimum 10000 -Maximum 99999)
  }
  $newVol = New-PfaRestOperation -resourceType "volume/$($volumeName)" -restOperationType POST -flasharray $flasharray -jsonBody "{`"source`":`"$($snapName)`"}" -SkipCertificateCheck -ErrorAction Stop
  $hostGroup = $flasharray |get-pfaHostGroupfromVcCluster -cluster $cluster
  New-PfaRestOperation -resourceType "hgroup/$($hostGroup.name)/volume/$($newVol.name)" -restOperationType POST -flasharray $flasharray -SkipCertificateCheck -ErrorAction Stop |Out-Null
  $esxi = $cluster | Get-VMHost| where-object {($_.ConnectionState -eq 'Connected')} |Select-Object -last 1 
  $esxi | Get-VMHostStorage -RescanAllHba -RescanVMFS -ErrorAction stop |Out-Null
  $hostStorage = get-view -ID $esxi.ExtensionData.ConfigManager.StorageSystem
  $resigVolumes= $hostStorage.QueryUnresolvedVmfsVolume()
  $newNAA =  "naa.624a9370" + $newVol.serial.toLower()
  $deleteVol = $false
  foreach ($resigVolume in $resigVolumes)
  {
      if ($deleteVol -eq $true)
      {
          break
      }
      foreach ($resigExtent in $resigVolume.Extent)
      {
          if ($resigExtent.Device.DiskName -eq $newNAA)
          {
              if ($resigVolume.ResolveStatus.Resolvable -eq $false)
              {
                  if ($resigVolume.ResolveStatus.MultipleCopies -eq $true)
                  {
                      write-host "The volume cannot be resignatured as more than one unresignatured copy is present. Deleting and ending." -BackgroundColor Red
                      write-host "The following volume(s) are presented and need to be removed/resignatured first:"
                      $resigVolume.Extent.Device.DiskName |where-object {$_ -ne $newNAA}
                  }
                  $deleteVol = $true
                  break
              }
              else {
                  $volToResignature = $resigVolume
                  break
              }
          }
      }
  }
  if (($null -eq $volToResignature) -and ($deleteVol -eq $false))
  {
      write-host "No unresolved volume found on the created volume. Deleting and ending." -BackgroundColor Red
      $deleteVol = $true
  }
  if ($deleteVol -eq $true)
  {
      New-PfaRestOperation -resourceType "hgroup/$($hostGroup.name)/volume/$($newVol.name)" -restOperationType DELETE -flasharray $flasharray -SkipCertificateCheck |Out-Null
      New-PfaRestOperation -resourceType "volume/$($newVol.name)" -restOperationType DELETE -flasharray $flasharray -SkipCertificateCheck |Out-Null
      New-PfaRestOperation -resourceType "volume/$($newVol.name)" -restOperationType DELETE -flasharray $flasharray -SkipCertificateCheck -queryFilter "?eradicate=true" |Out-Null
      return $null
  }
  $esxcli=get-esxcli -VMHost $esxi -v2 -ErrorAction stop
  $resigOp = $esxcli.storage.vmfs.snapshot.resignature.createargs()
  $resigOp.volumelabel = $volToResignature.VmfsLabel  
  $esxcli.storage.vmfs.snapshot.resignature.invoke($resigOp) |out-null
  Start-sleep -s 5
  $esxi |  Get-VMHostStorage -RescanVMFS -ErrorAction stop |Out-Null
  $datastores = $esxi| Get-Datastore -ErrorAction stop 
  foreach ($ds in $datastores)
  {
      $naa = $ds.ExtensionData.Info.Vmfs.Extent.DiskName
      if ($naa -eq $newNAA)
      {
          $resigds = $ds | Set-Datastore -Name $newVol.name -ErrorAction stop
          return $resigds
      }
  }    
}
New-Alias -Name get-faVolfromVMFS -Value Get-PfaVMFSVol
New-Alias -Name new-faVolVmfs -Value New-PfaVmfs
New-Alias -Name add-faVolVmfsToCluster -Value Add-PfaVmfsToCluster
New-Alias -Name set-faVolVmfsCapacity -Value Set-PfaVmfsCapacity
New-Alias -Name get-faVolVmfsSnapshots -Value get-pfaVolVmfsSnapshot
New-Alias -Name new-faVolVmfsSnapshot -Value new-pfaVolVmfsSnapshot
New-Alias -Name new-faVolVmfsFromSnapshot -Value New-PfaVmfs
New-Alias -Name get-pfaVolfromVMFS -Value Get-PfaVMFSVol 
New-Alias -Name new-pfaVolVmfs -Value New-PfaVmfs
New-Alias -Name add-pfaVolVmfsToCluster -Value Add-PfaVmfsToCluster
New-Alias -Name set-pfaVolVmfsCapacity -Value Set-PfaVmfsCapacity
New-Alias -Name get-pfaVolVmfsSnapshot -Value Get-PfaVmfsSnapshot
New-Alias -Name New-PfaVolVmfsSnapshot -Value New-PfaVmfsSnapshot
New-Alias -Name New-PfaVolVmfsFromSnapshot -Value New-PfaVmfs