The PowerShell script below is going to be provided as-is with little real overview, my hope is that it may save somebody else a lot of time trying to get Solarwinds and the Vivantio Service Desk to nicely sync records.
The example below retrieves all known assets in the Solarwinds Service Desk and maps that information to default and custom fields defined in Vivantio which may be scheduled to sync daily or as required.
SolarWinds Service Desk API – SolarWinds ITSM API (samanage.com)
Vivantio API – https://github.com/Vivantio/apisamples
All personal information below is given as an example only and will not actually work.
if($Response -ne $null) {
Clear-Variable "Response"
}
$SolarwindsAPIKey = "MD1DDKBRgGQl18d1-1oE1qdD-K9dgezFu9ABomabYLj59mzSQFv5nDWEDS********"
$VivantioAPIUsername = "api_Company_rO6ee*****@contoso.com"
$VivantioAPIPassword = "********"
$VivAPIKey = $VivantioAPIUsername + ":" + $VivantioAPIPassword
# Gets the hardware data from SolarWinds
$Header = @{
'X-Samanage-Authorization' = "Bearer $($SolarwindsAPIKey)
";
'Accept' = 'application/vnd.samanage.v2.1+json';
'Content-Type' = 'application/json'
}
$Response = Invoke-WebRequest https://apieu.samanage.com/hardwares.json -Head $Header -Method 'GET'
$SolarwindsAssets = $Response.Content | ConvertFrom-JSon
if($SolarwindsAssets -eq $null) {
throw "Failed to retrieve Solarwinds Assets"
}
# Define the header required to connect to Vivantio
$Creds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($VivAPIKey))
$VivantioHeader = @{
'Content-Type' = 'application/json';
'Authorization' = "Basic $($Creds)"
}
# For each SolarWinds asset, create or update the Vivantio record
for($x = 0; $x -lt $SolarwindsAssets.Count; $x++) {
$Asset = $SolarwindsAssets[$x]
# Get an existing asset from Vivantio if it exists
$ExistingItemBody = @{
"Query" = @{
"Mode" = "MatchAll"
"Items" = @(@{
"FieldName" = "SerialNumber"
"Op" = "Equals"
"Value" = $Asset.serial_number
})
}
} | convertto-json -depth 4
$VivantioResponse = Invoke-WebRequest https://webservices-uk01.vivantio.com/api/Asset/Select -Body $ExistingItemBody -Head $VivantioHeader -Method 'POST'
$ReturnedObject = $VivantioResponse.Content | convertfrom-json
if($ReturnedObject -ne $null) {
$ActiveAsset = $ReturnedObject.Results | where-object {$_.Deleted -eq $false}
}
# Handle the category and other fields depending on if there's an existing record
if ($ActiveAsset -ne $null) {
$Status = $ActiveAsset.StatusName
$Category = $ActiveAsset.CategoryLineage
$PurchaseDate = $ActiveAsset.PurchaseDate
$PurchasePrice = $ActiveAsset.PurchasePrice
} else {
$Status = $Asset.status
$Category = 'Hardware: ' + $Asset.category
$PurchaseDate = ""
$PurchasePrice = ""
}
# Define the JSON data to submit to Vivantio
$VivBody = [pscustomobject]@{
'AssetTag' = $Asset.name;
'SerialNo' = $Asset.serial_number;
'Status' = $Status
'ExternalKey' = $Asset.serial_number;
'ExternalSource' = 'SharePoint';
'CategoryLineage' = $Category
'PurchaseDate' = $PurchaseDate
'PurchasePrice' = $PurchasePrice
'CustomForms' = @{
'Hardware' = @(@{
'Model' = $Asset.model
'Manufacturer' = $Asset.bioses.manufacturer
'Processor' = $Asset.cpu
'Memory' = [math]::Round($Asset.physical_memory / 1000, 0)
'Serial Number' = $Asset.serial_number
})
'Operational' = @(@{
'Operating System' = $Asset.operating_system
'Last Login' = $Asset.username
})
};
'RecordTypeId' = 5
} | ConvertTo-Json -Depth 4
$VivantioResponse = Invoke-WebRequest https://webservices-uk01.vivantio.com/api/Asset/InsertUpdate -Body $VivBody -Head $VivantioHeader -Method 'POST'
$VivantioResponse.Content
}