To work around this limitation I wrote a PowerShell script which uses cURL to interact with the UX2000 web interface to create a backup of the configuration - cURL is "a command line tool for transferring data with URL syntax".
In a nutshell, the script creates an authenticated session by submitting a username and password to the login form, gets the session ID from the returned header, uses the authenticated session ID to get the backup file, then logs out.
Once the backup file is downloaded the script uses MD5 hashes to compare the new backup with the next most recent, and discards the new file if they are the same - this way I only have to save backup files when something in the configuration has actually changed.
This entire backup process takes just a few seconds for each UX2000 in my deployment - a massive time saving compared to creating all the backups manually, and because backups are only retained when something changes, I can schedule the script to run as often as I like.
# Record a transcript Start-Transcript -Path ".\logfile.log" # Set the working directory [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath # Function to create an MD5 hash for file comparison Function Get-MD5Hash ($Filename) { $MD5provider = New-Object System.Security.Cryptography.MD5CryptoServiceProvider $FileInfo = New-Object System.IO.FileInfo($Filename) $Stream = $FileInfo.OpenRead() $MD5Bytes = $MD5provider.ComputeHash($Stream) [void] $Stream.Close() ForEach ($Byte in $MD5Bytes) { $Hash = $Hash + $Byte.ToString("X2") } Return $Hash } # Array of all the UX gateways $Gateways = ( "ux2000-nyc.example.com", "ux2000-tyo.example.com", "ux2000-lon.example.com", ) # Login credentials $Username = "admin" $Password = "password" # Backup each gateway ForEach ($Gateway in $Gateways) { # Output the gateway name $Gateway # Create a folder for this gateway's backups If (-Not (Test-Path $Gateway.Split(".")[0])) { $Null = New-Item -Name $Gateway.Split(".")[0] -Type Directory} # Use the gateway name and the date to create the filename for this backup $Filename = "$($Gateway.Split(".")[0])\$($Gateway.Split(".")[0])_$(Get-Date -uformat "%Y-%m-%d-%H%M").tar.gz" # Create a temp file name $TempFilename = "$($Gateway.Split(".")[0])\$(Get-Date -uformat "%Y%m%d-%H%M").tmp" # Get the name of the most recent backup file $Backups = Get-ChildItem $Gateway.Split(".")[0] | Sort-Object -Property LastWriteTime -Desc If (($Backups | Measure-Object).Count -eq 1) { $PreviousFilename = $Gateway.Split(".")[0] + "\" + ($Backups).Name } ElseIf (($Backups | Measure-Object).Count -gt 1) { $PreviousFilename = $Gateway.Split(".")[0] + "\" + ($Backups)[0].Name } Else { $PreviousFilename = $Null } # Login to the UX and get the session ID $Login = .\curl --insecure https://$Gateway/cgi/login/login_do.php --data "username=$Username&password=$Password&passwordNonce-Hidden=password&loginbutton=Login" -i -s $SessionID = $Login[1].split("=;")[1] # Get the backup .\curl.exe --cookie PHPSESSID=$SessionID --insecure https://$Gateway/cgi/system/configBackup.php?action=backup --data "action=backup" -o $TempFilename # If we made a backup, and there is an older one, compare it to the last one and discard it if they are the same If (($PreviousFilename -ne $null) -and (Test-Path $TempFilename)) { # Get an MD5 Hash of both files $PreviousHash = Get-MD5Hash ("$PreviousFilename") $TempHash = Get-MD5Hash ("$TempFilename") Write-Host Write-Host $PreviousFilename,"=",$PreviousHash Write-Host $TempFilename,"=",$TempHash # Remove today's backup file if the hashes match If ($TempHash -eq $PreviousHash) { Write-Host Write-Host "File hashes match, discarding temp file" Remove-Item $TempFilename } Else { Write-Host Write-Host "File hashes don't match, keeping backup file" Move-Item $TempFilename $Filename -Force } } $Logout = .\curl.exe --cookie PHPSESSID=$SessionID --insecure --silent https://$Gateway/cgi/login/logout.php Write-Host Write-Host } Stop-TranscriptDownload Script
In order to use this script in your own deployment you would need to change the $Username, $Password, and $Gateways variables to suit your needs, and the user account specified must exist on each gateway to be backed up.
The cURL executable needs to be in the same directory as the PowerShell script and working (try it in a command prompt first) - the current version of cURL needs the Visual C++ 2010 redistributable package installed.
- Ben
Updated to support UX software release 2.0.0.
ReplyDelete- Ben
Updated to support UX software release 2.2.0
ReplyDelete- Ben
Awesome script....however, my configs are being backed up daily without changes. If I run the script back to back then the MD5 hash detect they are the same and skips. However, when I run this as a scheduled task it backs up everyday. The scheduled task (and the manual run) is running on a Virtual(VMware) Windows 2003 R2 server. Any ideas?
ReplyDelete