This discussion has been locked. The information referenced herein may be inaccurate due to age, software updates, or external references.
You can no longer post new replies to this discussion. If you have a similar question you can start a new discussion in this forum.

TC18: Exporting Network Atlas Map Files

1803_thwack_thwackcamp_session-screens_promoplaceholder.png

This script was featured during the There's an API for That: Introduction to the SolarWinds Orion SDK​ at THWACKcamp 2018​.

Network Atlas is one of the premier ways to get information visualized for your environment.  It gives you a way to understand, at a glance, how you are going to be spending your day.

pastedImage_1.png

But there does exist a small problem with Network Atlas - everything is stored in the database.  Now for a migration this is ideal because if you move the database, you move the files.  So this is a win-some, lose-some situation, right?

The Problem

Unlike many SolarWinds Orion admins, I'm frequently running multiple copies of Orion across different environments.  Then it occurred to me that I may not be that different: many people probably run separate Dev, Test, and Production environments.

For me, I like to develop most of my changes (be they maps, scripts, templates, or reports) on a development machine.  You can easily export the reports, scripts, and templates, but there's no easy way to export the icons or backgrounds that I've used in maps.  Those are stored within the  SQL database... in binary.  Not the easiest thing to work with.

Choice of Language

For anyone who has read anything that I've written here or elsewhere, you know that my preferred scripting language is (and probably always will be) PowerShell.  Now, sometimes I get guff about this from some other scripters who prefer *ahem* older languages like Perl (you know who you are).

"Why do you use PowerShell?" - I get the question often enough, so I think I'll answer it here for you.  I go into more details during the session, but the simple answer is this: the Orion Platform runs on Windows Servers, PowerShell is native to Windows, ergo there's nothing new to install*.

How I Learned to Stop Worrying and Love the SDK

Sometimes I get bored at work.  That's not to say that I stop working, but sometimes I have to wait for things to compile and have a few spare minutes.  On one such day a few years ago I decided that I needed to spend a little more time digging in the Orion SDK.  This particular day, I happened upon the MapStudioFiles table.

pastedImage_4.png

Looking into the fields in that table, I saw the file name (with a path) and a file data field.  Turns out that the file data field is a series of bytes that make up the files in the file name field.  Eureka!  Now I just needed to move these out of the database.  Now that I've "found" the files, I needed to so something with them.  That's where things got interesting.

The Pseudocode

Select a location where to save the files.

Connect to the SolarWinds Information Service (SWIS).

Get a list of all (non-deleted) map files from SWIS.

Check to see if the possible export path is valid.

Export the file by encoding the data to bytes.

Do the next file until we're out of files.

The Important Single Line

If there's one line in the code that's super important, then that would be line 55 which is:

$SwiFile.FileData | Set-Content -Path $ExportFullPath -Encoding Byte -Force

What's this line do?  This line takes the information in the FileData field, and sends that to a path that we calculated, encoding it as bytes.  This line is then done over and over again for each entry.

The Code

I'm posting my complete code here.  You'll have to make a few changes for your specific environment, but it should would with just a few tweaks.

<#
Name:            Export-OrionMaps.ps1
Author:          KMSigma [https://thwack.solarwinds.com/people/KMSigma]
Purpose:         Export the files needed for Network Atlas Maps - useful for when you want to re-use the graphics (Prod <--> Test <--> Dev migrations)
Version History: 1.0 (2018-07-17)
                 - Initial build for THWACKcamp 2018
                 1.1 (2018-10-17)
                 - Updated with progress bars to make it more useful for a large count of files.
Requires:
    SolarWinds PowerShell Module (SwisPowerShell) which is documented with the SolarWinds Orion SDK [https://github.com/solarwinds/OrionSDK]
    If you do not have it installed, you can install it in one of two ways:
    1) Install-Module -Name SwisPowerShell
       Installs to the default user's profile
    2) Install-Module -Name SwisPowerShell -Scope AllUsers
       Installs to the computer's profile (available to all users) <-- this is my preferred method
#>
Import-Module -Name SwisPowerShell -ErrorAction SilentlyContinue
$SwiCreds = Get-Credential -Message "Enter your Orion Credentials"
$SwiHost  = "10.196.3.11"
$SaveLocation = "D:\Data"
# There are multiple ways to connect to the SolarWinds Information Service
# This example uses the "Orion" credentials.
# Other examples are:
#   Connect-Siws -HostName $SwiHost -Trusted [Logs is as the currently logged in Windows User]
#   Connect-Swis -HostName $SwiHost -Username "admin" -Password "KeepItSecretKeepItSafe" [same as below, but with the username & password in plain text]
$SwisConnection = Connect-Swis -Hostname $SwiHost -Credential $SwiCreds
$SwqlQuery = @"
SELECT FileName, FileData
FROM Orion.MapStudioFiles
WHERE IsDeleted = False
ORDER BY FileName
"@
Write-Host "Let's get some data!" -ForegroundColor Yellow
$TimeToQuery = Measure-Command -Expression { $SwiFiles = Get-SwisData -SwisConnection $SwisConnection -Query $SwqlQuery }
Write-Host "Query took: $( $TimeToQuery.TotalSeconds ) seconds and returned $( $SwiFiles.Count ) files"
# Cycle through each file and display a counter
$i = 0
ForEach ( $SwiFile in $SwiFiles )
{
   
    # Progress bar showing the how we're progressing
    Write-Progress -Activity "Exporting Map Files" -Status "Exporting $( $SwiFile.FileName )" -PercentComplete ( ( $i / $SwiFiles.Count ) * 100 )
   
    # Build the output path for the file by combining the save location defined above and the file name
    $ExportFullPath = Join-Path -Path $SaveLocation -ChildPath $SwiFile.FileName
    # Check to see if the full path exists - it might not.  Let's build it.
    if ( -not ( Test-Path -Path ( Split-Path -Path $ExportFullPath ) -ErrorAction SilentlyContinue ) )
    {
        Write-Warning -Message "Creating [$( ( Split-Path -Path $ExportFullPath ) )] Folder"
        New-Item -Path ( Split-Path -Path $ExportFullPath ) -ItemType Directory | Out-Null
    }
   
    # Finally, let's export it.
    Write-Host "Exporting $ExportFullPath from Orion" -ForegroundColor Green -NoNewline
    $SwiFile.FileData | Set-Content -Path $ExportFullPath -Encoding Byte -Force
    Write-Host " [$( $SwiFile.FileData.Length ) bytes written]" -ForegroundColor Yellow
    $i++ # incement counter
}
# Close the progress bar
Write-Progress -Activity "Exporting Map Files" -Completed
# Cleanup - get rid of the SolarWinds-specific variables
Get-Variable -Name Swi* | Remove-Variable

I'm pretty good with commenting my code - especially when I know it's going to be shared with people, but if there's anything that I've missed, please feel free to let me know and I'll answer any questions.

The SolarWinds trademarks, service marks, and logos are the exclusive property of SolarWinds Worldwide, LLC or its affiliates.  All other trademarks are the property of their respective owners.