Unity Snapshot creation

Short: This script can be used to automate the snapshot creation for DellEMC Unity systems to leverage the Veeam Backup & Replication option to backup from native storage snapshots.

Veeam Backup & Replication NAS Backup

With Veeam bringing the new NAS backup functionality in the next main release, a few of my colleagues and myself decided to build some scripts to leverage one very cool feature.

In the advanced settings for the file share definition, you have the option to backup from various sources of the share.

First option is to Backup directly from the file share which might bring you into a situation where files are locked by other users and cannot be backed up during a job run. The other thing you might need to think about is more related to larger shares. If the job runs for a longer time, users might change files that still need to be processed. This will left you with a backup that is not exactly from the same time of all files.

The second option you have is to leverage VSS snapshots on the storage. In detail we are talking about RVSS (Remote Volume Shadow Copy Service) here. This function is implemented in some NAS storage systems in the SMB 3.0 already and can make life very easy when it comes to backup.

The third option gives you the cool feature to backup from native storage snapshots.

But what does this really mean?

You can define an alternative path from where you want to drag the files from. This path will be a mounted snapshot in the most cases, and to prepare this you can run a pre-backup script in the backup job:

Every vendor builds it´s NAS storage systems differently, so what did I do to make use of this for Unity systems? Keep on reading…

Prerequisites

First, Erwan Quélin created a nice PowerShell module for managing Unity arrays, find it here on Github: https://github.com/equelin/Unity-Powershell

It actually uses the RestAPI of the Unity to manage the system. Big kudos to him for creating that and honestly, I was really surprised that DellEMC is not providing a PowerShell integration by themselves, btw. same story goes for Isilon systems.

He also published this module to the PowerShell Gallery, so you can easily download and install it directly within a PowerShell command window:

Install-Module Unity-Powershell

Second thing you need to think of is the user account the script needs to runs Since this will be triggered by Veeam Backup & Replication, the context most likely will be the System user. To be able to use encrypted credentials in a xml file, this should be created with PSEXEC to have the decryption right for the System user. Marco Hostmann has written a nice little article on how to do this: https://horstmann.in/store-powershell-credentials-encrypted/

Veeam Backup & Replication settings

To make things easier, you can simply create a SMB share for the root folder of the file system, but this might be a security issue for some environments.

This path is then used in Veeam Backup & Replication to add the system as File Share:

After adding the shares to protect in a backup job we can proceed to add the script in the advanced settings at the storage settings:

In this example the scripting line looks like this and the next section will explain the parameters:

c:\scripts\Invoke-UnityNASBackup.ps1 -Name unity01mgmt -Share root -CredentialFile C:\Scripts\credential-system-unity01.xml

The Script

Once you are settled up with the basics, you can go ahead and start using a PowerShell script, in this case the one for Unity I dropped here: https://github.com/wcbuerste/Veeam/tree/master/NAS/Unity

This script creates a snapshot in a DellEMC Unity system for the path of a defined SMB share. The snapshot should be normally presented in a .ckpt folder which did not work for me on various systems. I could not get an answer from DellEMC so far why this is not working, so I created a workaround that ignores this issue.

The Unity-Powershell module is lagging a parameter to present a newly created snapshot as a certain SMB share. To realize this, I simply run a RestAPI call to the Unity to perform the mounting:

Invoke-WebRequest -Uri $URI -ContentType "application/json" -Body $json -Websession $UnitySession.Websession -Headers $UnitySession.headers -Method POST -TimeoutSec 6000 -UseBasicParsing

Let´s have a look at the parameter you need to run the script:

UnityName : With this parameter you specify the Unity DNS name or IP
UnityShare : With this parameter you secify the source SMB share
UnityCredentialFile : This parameter is a filename of a saved credentials file for authentification
SnapshotName : With this parameter you can change the default snapshot name “VeeamNASBackup” to your own name
SnapExpireSeconds : Set the seconds when the snapshot should be expired. The default value is 172800, which is 2 days
LogFile : You can set your own path for log files from this script. Default path is the same VBR uses by default “C:\ProgramData\Veeam\Backup\UnityNASBackup.log”

As an example, the script can be called prior a file backup job like this:

c:\scripts\Invoke-UnityNASBackup.ps1 -Name unity01mgmt -Share share01 -CredentialFile C:\Scripts\credential-system-unity01.xml

Functions
If you want to dig deeper, here are some words on the important bits.

function Get-FilesystemID

$objShare = Get-UnityCIFSShare -Name $UnityShare -session $UnitySession
$filesystemID = $objShare.filesystem.id

This function is getting the ID of the file system where the provided share is running in. When the file system ID is known, the storage resource for the file system need to be located:

function Get-StorageResource

$objFilesystem = Get-UnityFilesystem -ID $filesystemID -session $UnitySession
$StorageResource = $objFilesystem.storageResource.id

Once this is done, the main part of the snapshot creation can be started. The function Create-NewSnapShot is searching for an existing snapshot with the same name and if there is one present, it will be deleted. A new snapshot is finally created for the storage resource:

function Create-NewSnapShot($StorageResource) {
Write-Log -Info "Trying to create a new snapshot for $StorageResource" -Status Info
#check if there is a snapshot with the same name
try {
if($ExistingSnap = Get-UnitySnap -session $UnitySession -name $SnapshotName) {
#save the snapshot ID
$ExistingSnapID = $ExistingSnap.id
#get the creation time of the snapshot
$SnapCreationTime = get-date($ExistingSnap.creationTime) -Format yyyy-mm-dd_HH-mm-ss
Write-Log -Info "Existing snapshot $ExistingSnapID with date $SnapCreationTime found, trying to remove it." -Status Info
try {
#remove the existing snapshot
Remove-UnitySnap -session $UnitySession -ID $ExistingSnapID -Confirm:$false
Write-Log -Info "Snapshot $ExistingSnapID removed" -Status Info
}
catch {
Write-Log -Info "$_" -Status Error
Write-Log -Info "Removing the old snapshot failed" -Status Error
exit 1
}
}
}
catch {
Write-Log -Info "No existing snapshot found" -Status Info
}
#create a new snapshot for the share
try {
$objSnapshot = New-UnitySnap -storageResource $StorageResource -session $UnitySession -name $SnapshotName -Description "Veeam Backup Snapshot" -retentionDuration $SnapExpireSeconds -filesystemAccessType Protocol -Confirm:$false
$SnapShotID = $objSnapshot.ID
Write-Log -Info "New snapshot named $SnapshotName created, ID: $SnapShotID" -Status Info
return($SnapShotID)
}
catch {
Write-Log -Info "$_" -Status Error
Write-Log -Info "Snapshot creation failed" -Status Error
exit 1
}
}

As mentioned earlier, the snapshot will not be mounted to a SMB share at this stage. So this needs to be done in an extra step and will be performed through a RestAPI call.

function create-NewBackupShare($SnapShotID){
#creat a new share for the newly created snapshot. This has to be done with a direct RestAPI call since the needed option is missing in the Unity powershell module.
try {
#Build the json body
$json = @{
name=$SnapShotName
path='/'
snap=@{
id=$SnapShotID
}
} | ConvertTo-Json
#Build the RestAPI URL string
$resourceurl = "/api/types/cifsShare/instances"
$uri = "https://" + $UnitySession.Server + $resourceurl
# Invoke the RestAPI call
$objSnapShare = Invoke-WebRequest -Uri $URI -ContentType "application/json" -Body $json -Websession $UnitySession.Websession -Headers $UnitySession.headers -Method POST -TimeoutSec 6000 -UseBasicParsing
$objSnapShareContent = $objSnapShare.Content | convertfrom-json
$SnapID = $objSnapShareContent.content.id
Write-Log -Info "New cifs share named $SnapShotName created, ID: $SnapID" -Status Info
}
catch {
Write-Log -Info "$_" -Status Error
Write-Log -Info "CIFS share creation failed" -Status Error
exit 1
}
}

The Invoke-WebRequest command needs to be run with the parameter -UseBasicParsing to avoid error related to the Internet Explorer settings.

Conclusion

As you have learned now, the usage of a script for backing up NAS storages from snapshots with Veeam Backup & Replication can be a nice addition to simply accessing the files shares directly.

If you are searching something similar for NetApp systems, please head over to Marco again and find instructions and scripting there: https://horstmann.in/advanced-veeam-nas-backup/

In a different blog post I´m going through the process for a DellEMC Isilon system.