3par Powershell Example

HP has amazing product called 3par but it’s definitely lucking some features on add-on software side.

One of the products HP offers is called HP 3PAR Recovery Manager Software for Microsoft SQL Server (RM-SQL). Purpose of this software is to provide rapid on-site “backup” and not DR (in my experience majority of folks in HP don’t understand what this product does). I am not going into details how this software works but to give you a brief summary: it uses 3PAR hardware VSS provider to create application consistent snapshots and replicates them to another remote 3PAR SAN or stores them on 3PAR SAN locally.

 

You might think it does achieve objectives of DR but don’t be fooled. You are unable to restore replicated snapshots to a DR SQL server – the can only be restored to the same SQL server (you need to zone the same server to both 3PAR systems). Silly if you ask me as it seems to be solo software restriction.

 

Our objective for this exercise is DR for physical SQL servers hosted on 3PAR SAN. Additionally, we need to achieve low RTO and RPO. I am not describing on how to configure HP 3PAR RM-SQL to get data across to DR site.

The following Powershell script requires HP 3PAR CLI 3.1.3 installed. Additionally, DR server needs to have WINRM enabled (winrm quickconfig) and appropriate permissions for account (local administrators) under which you will be executing this script.

# Name: RM_Recovery.ps1
# Author: Naz Snidanko
# Date Created: Sept 02, 2014
# Date Modified: Sept 08, 2014
# Version: 0.2
# Description: Selects latests 3par snapshots and mounts them on a host.
#              Requirements: HP 3par CLI 3.1.3, WinRM enabled on Recovery host (winrm quickconfig)
############# START EDIT ##############
#  Set the hostname of the 3par storage system here
$env:TPDSYSNAME = "1.1.1.1"
# Set the location of the pwfile you created with "setpassword -saveonly -file"
$env:TPDPWFILE = "C:\3par_test.pwfile"
# Name of the remote copy group
$rcgroup =  "TEST_GROUP.r21111"
# Name of the DR host (has to be created in 3par)
$RMHost = "TEST"
# Log file
$LogFile = "C:\blah.txt"
#
############# END EDIT #############
# Writes stdin to a file
function Log {
    param([string] $fileName,
          [switch] $echo,
          [switch] $clear
    )

    process {
        $input | % {
            if ($echo.IsPresent)
            {
                Write-Output $_
            }
            [boolean] $isAppend = !$clear.IsPresent
            $_ | Out-File $logFile -Append:$isAppend | Out-Null
        }
    }
}
#######################################
Write-Output "*****START*****" | Log $logFile
Get-Date | Log $logFile
Write-Output "3par System:" | Log $logFile
$strShowSys = cmd /c showsys
Write-Output $strShowSys | Log $logFile
Write-Output "Volumes:" | Log $logFile
$strShowVv = cmd /c showvv -p -rcopygroup $rcgroup -showcols Name
#split Volume name's for Remote copy group
$strVolArray =  @(0..5)
$strVolArray = $strShowVv -split "`t"

$i = 0
while ($strVolArray[$i]) {
    #variable clean
    $strSnap = $null
    if ( ($strVolArray[$i] -notlike "Name*") -and ($strVolArray[$i] -notlike "total*") -and  ($strVolArray[$i] -notlike "-----*") )
    {
    Write-Output "Volume name:" $strVolArray[$i] | Log $logFile
     #split Snapshots name's for Volume
     $strSnap = cmd /c showvv -p -type vcopy -copyof $strVolArray[$i] -showcols "Name,Id" -sortcol "1,dec"
     $strSnapArray =  @(0..5)
     $strSnapArray = $strSnap -split "`t"
     $b = 0
     ###### START: Mounting snapshot block
     $TEMP = $null
     $strSnapToClone = $null
     Write-Output "#########Creating RW snapshot:" | Log $logFile
     $strSnapToClone = ( $strSnapArray[1].Substring(0,$strSnapArray[1].IndexOf(" ")) )
     $strSnapToCloneRM = $strSnapToClone+"_RM"
     Write-Output "Creating RW snapshot " $strSnapToCloneRM "from " $strSnapToClone | Log $logFile
     cmd /c createsv $strSnapToCloneRM $strSnapToClone
     Write-Output "#########Exporting RW snapshot:" | Log $logFile
     cmd /c createvlun $strSnapToCloneRM auto $RMHost
     ###### END: Mounting snapshot block             
    }
$i++
}
Write-Output "Mounting volumes" | Log $logFile
# wait 90 seconds for mounting process
Start-Sleep -s 90

Write-Output "Scanning for new disks"
# rescan to detect new disks
Invoke-Command -ComputerName $RMHost -ScriptBlock {
$dpscript = @"
rescan
"@
$dpscript | diskpart
}

# wait 30 seconds for OS to detect disks
Start-Sleep -s 30

# Bring disks online on remote host
$rmCmd = Get-WmiObject -Class Win32_Diskdrive -Computername $RMHost | where {$_.Model -eq "3PARdata VV  Multi-Path Disk Device"}
Write-Output "Disks detected on remote host" | Log $logFile
Write-Output $rmCmd | Log $logFile
foreach ($disk in $rmCmd) 
{ 
 $diskID = $disk.index
 Invoke-Command -ComputerName $RMHost -ScriptBlock {
param($diskID)
$dpscript = @"
select disk $diskID
att disk clear readonly
online disk noerr
"@
$dpscript | diskpart
} -ArgumentList $diskID | Log $logFile
}

# Get Volume Information from RM host
# credit: http://social.technet.microsoft.com/Forums/windowsserver/en-US/630c5b7f-1849-49d5-9386-58ec9625ac43/getwmiobject-class-for-diskpart-list-volume?forum=winserverpowershell
[string]$temp = Invoke-Command -Computername $RMHost -ScriptBlock {$dpscript = @"
list volume
"@;$dpscript | diskpart}
$vols = $temp -split "\s(?=V)"
$labels = ($vols[2] -split "(\s+)(?=-)")[0] -split "\s+"
$Results = $vols[3..($vols.count-1)] | %{
   New-Object PSObject -property @{
      "$($labels[0])$($labels[1])" = $_.substring(0,10).trimend()
      $labels[2] = $_.substring(13,3).trim()
      $labels[3] = $_.substring(17,11).trim()
      $labels[4] = $_.substring(30,5).trim()
      $labels[5] = $_.substring(37,10).trim()
      $labels[6] = $_.substring(49,7).trim()
      $labels[7] = $_.substring(58,9).trim()
      $labels[8] = $_.substring(67,8).trim()
   }
}

echo "Volumes detected:" $Results | Log $logFile
# Count total number of volumes
$total = $Results.Count
echo "Total volumes:" $total | Log $logFile
$i = 0

while ($i -ne $total) {
# clear attributes on hidden volumes
	if ( $Results[$i].Info -like "*Hidden*" )
	{
	echo "Hiidden volume:" | Log $logFile
	echo $Results[$i].$("Volume###") | Log $logFile
	$volID = $Results[$i].$("Volume###")
	Invoke-Command -ComputerName $RMHost -ScriptBlock {
param($volID)
$dpscript = @"
select $volID
attributes volume
att volume clear shadowcopy
att volume clear readonly
att volume clear nodefaultdriveletter
att volume clear hidden
attributes volume
"@
$dpscript | diskpart
} -ArgumentList $volID | Log $logFile
 
	}
$i++
}

Write-Output "*****END*****" | Log $logFile
Get-Date | Log $logFile
This entry was posted in 3par, Powershell and tagged , , , . Bookmark the permalink.

2 Responses to 3par Powershell Example

  1. KK says:

    Hi, Could you please give me a simple example..
    For example scripts for Daily health status, System Space information…
    I used Powershell toolkit for 3PAR, but it is having limited option.
    Thank you.

    Regards,
    KK

Leave a Reply to Naz Snidanko Cancel reply

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