Friday, February 3, 2017

Backup and restore a WFA server with powershell

If your WFA server is a key component in your environment, you will want to have backup.  Now WFA takes backups every day (keeping 5 versions), but I was always told : a backup is only a backup if it's in a different location.  So I created this PowerShell script a while ago to automate a backup/restore.  You call it a synchronization script if you'd like.



2 Copies


Now, before you start, you install WFA servers on 2 different locations and you make sure they are on the same version.

Credentials

Second, as you might know, WFA has a credential store.  These are encrypted with a key.  You need to make sure those keys are identical.  These are in fact the steps required for every backup/reinstall/restore.
Here are the actions :
  • On the backup source :
    Enter the following at the command prompt to obtain the database key : wfa.cmd -key
  • Write down the key
  • On the restore destination :
    Enter the following at the command prompt to install the database key: wfa.cmd -key=yourdatabasekey

The Backup / Restore code

Note : the backup & restore are with pure rest.  the restore was a  bit a struggle to get the multipart form ok.   The url is in the format like : http(s)://mywfa/rest/backups?full=true

<#
.SYNOPSIS
   Runs a backup on a remote backup WFA server
   Restores that backup on another local or remote WFA server
       
.VERSION
   2017-09-19  
 
.
#>
##
# DATE: 03/12/2014
# AUTHOR: Mirko Van Colen
##
param
(   
    [parameter(mandatory=$true, HelpMessage='The wfa username, assumed same for backup & restore server')]
    [String]$User,
 
    [parameter(mandatory=$true, HelpMessage='The wfa password, assumed same for backup & restore server')]
    [String]$Password,
 
    [parameter(mandatory=$true, HelpMessage='The Rest Backup Url of the backup wfa server.  http://backupserver/rest/backups')]
    [String]$BackupUrl,

    [parameter(mandatory=$true, HelpMessage='The Rest Backup Url of the restore wfa server.  http://restoreserver/rest/backups')]
    [String]$RestoreUrl,

    [parameter(mandatory=$false, HelpMessage='The full path where to create the backup')]
    [String]$Path = (Get-location).path
)

$ErrorActionPreference = "stop"

# Avoid certificate errors
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

# create creds
$secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($User, $secpasswd)
 
try {
 
    $BackupPath = $("$Path\wfa_backup.zip")
 
    # Connect to WebService
    Write-Output "Creating backup [$BackupUrl] -> [$BackupPath]"

    Invoke-WebRequest $BackupUrl -OutFile $BackupPath -Credential $mycreds
    Write-Output "Backup created"
}catch {

    $ErrorMessage = $_.Exception.Message

    if($ErrorMessage.Contains("The backup server returned an error: (401) Unauthorized")) {
        Write-Warning "Invalid credentials specified, cannot take a backup"
    } else{
        throw
    }
}

try{

    Write-Output "Restoring backup [$BackupPath] -> [$RestoreUrl]"
    $fileBin = [System.IO.File]::ReadAllBytes($BackupPath)
    $enc = [System.Text.Encoding]::GetEncoding("ISO-8859-1")
    $fileEnc = $enc.GetString($fileBin)
    $boundary = [System.Guid]::NewGuid().ToString()
    $LF = "`r`n"
    $bodyLines = (
        "--$boundary",
        "Content-Disposition: form-data; name=`"backupFile`"; filename=`"wfa_backup.zip`"",
     "Content-Type: application/zip$LF",
        $fileEnc,
        "--$boundary--$LF"
        ) -join $LF
 
    Invoke-RestMethod -Uri $RestoreUrl -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines -Credential $mycreds
    Write-Output "Backup restored successfully"
}catch {
    $ErrorMessage = $_.Exception.Message

    if($ErrorMessage.Contains("The restore server returned an error: (401) Unauthorized")) {
        Write-Warning "Invalid credentials specified, cannot restore backup"
    } elseif($ErrorMessage = "Failed to restore toolkits") {
        Write-Warning "Restore partially failed, could not restore toolkits"
    } else {
        throw
    }
}
 

10 comments :

  1. Is there a Perl version of this? We run WFA on Linux and are looking to push confiugrations from dev, to test, to prod.

    ReplyDelete
    Replies
    1. http://www.wfaguy.com/2017/04/backup-and-restore-wfa-with-perl.html#more

      Delete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. Any suggestions for the "Failed to restore toolkits"? I'm getting similar errors if I do a manual backup / restore from Host A to Host B.

    ReplyDelete
    Replies
    1. had them too. will ask the product team.

      Delete
    2. Did you get any feedback on this?

      Delete
    3. Hi, i get the feedback, that it happens if the 2 servers have a different powershell toolkit version. If always have the issue when i restore from a server to my laptop. So that's from win2012 => win10. Maybe it's the powershell version itself (version 5 vs version 4 ?)

      Delete
    4. Thanks... They're both the same right now (both 2012 boxes), they were built at the same time. I was getting the same error outside of PS, just copying over the backup and doing the restore via the GUI. I'll give it another go... I guess I could open a case too.

      Delete
  4. So some feedback on this. If you take a backup and have a look in the zip file, there are 3 things there : the sql dump, a zipped backup of the workflow help directory and a zipped backup of the perl/powershell module directory. In that directory there is the netapp powershell toolkit. It's that piece it complaints about somehow. I assume it's a lock on some files. It can definitely be ignored.

    ReplyDelete