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.

How to modify a custom property for multiple nodes with Powershell

So, 

I have been working on several  powershell scripts...  Here is what i have.

#Author: John Johnson
#Last Modified: 3/8/22
#Summary: Set Node Custom Properties in SolarWinds

# Be sure to install the SwisPowershell module on Powershell 5 or lower prior to use
# Install-Module SwisPowershell

#Designate Hostname

$server = 'host'

$creds = Get-Credential

$swis = Connect-Swis -HostName $server -Credential $creds

#$nodes = Get-SwisData $swis 'SELECT NodeID, Caption, DNS, IPAddress, Uri FROM Orion.Nodes'

## Export data from SWQL and arrange it in Excel first
## CSV Import Approach
$updates = Import-Csv C:\Users\list.csv

foreach ($update in $updates)
    {
        Write-Host "Updating"$($update.IPAddress)"@"$($update.Uri)
        $properties = ''
        $properties = $update.psobject.properties | where-object {($_.Name -ne "Uri") -and ($_.Name -ne "NodeID") -and ($_.Name -ne "IPAddress")}

        $record = @{}
        foreach ($property in $properties)
            {
                if (($($property.Value) -ne $null) -and ($($property.Value) -ne ''))
                    {
                        $record += @{$($property.Name)=$($property.Value)}
                    }
            }

        Set-SwisObject $swis -Uri $($update.Uri) -properties $record
    
    }

i have a custom property 'NodesCustomProperties.ServiceNow_Owner_1'

how would i be able to use a serverlist.csv, to modify all servers in the list...and modify the custom property above?

Parents
  • , So below is a script that I have that can do a bulk import of External Nodes and then modifies a Custom Property during that time. It should have the requirements you need to get it to work with some modification. Some key difference between yours and mine is that it looks like you take and build out a URI, mine queries SWQL directly for the URI, which i find helps reduce errors i've seen when trying to rebuild the URI within the script. But in essence much of it is the same, at a high level you'd just need a second set of property definitions for the CP, and then a second Set-SwisObject to modify the CP's for that node.

     # Pre-Reqs:
    # 1. Ensure that the SolarWinds SDK, and powershell modules are installed on machine running the script
    # 2. CSV that contains IP in the first column, Desired Caption in the Second Column, and a CommunityString in the third column (will default to public if none identified), and desired Custom Properties in the remaining columns (IF ADDING CUSTOM PROPERTIES ENSURE THAT YOU UPDATE LINE 39 AND 82 WITH THE APPROPRIATE REFERENCES!!) No Column Headers.
    
    import-Module SwisPowerShell
    # Connect to SWIS
    
    
    $hostname = 'localhost'
    $swis = Connect-Swis -host $hostname -Certificate
    
    #Import New Nodes
    if ($names -eq $true) {
    $names = $null
    }
    #$names = import-csv \\server\file.txt
    $filename = Read-Host -Prompt "Enter CSV Location (\\server\file or C:\dir\file)"
    if (Test-Path $filename) {
    Write-Output "File exists"
    
    $ExternalNodes= import-csv $filename -Header 'IP','Caption','CommunityString','Test1'
    $count = $ExternalNodes.length
    }
    else {
    Write-Output "Bad file, exiting....."
    exit
    Write-Output $ExternalNodes
    }
    
    
    $wait = $false
    while ($wait -eq $false) {
    
    $check = Read-Host "About to add $($count) External Nodes to Orion Instance: $($hostname) Proceed? (y/n)"
    if ($check -eq 'y') {
    $wait = $true
    }
    else { if ($check -ne 'n') {
    $wait = $false
    }
    else {
    Write-host "Process Aborted.  Exiting....."
    exit 0
    }
    }
    }
    foreach($ExternalNode in $ExternalNodes){
    # Set Properties for New External Node
       $newNodeProps = @{
        IPAddress = $($ExternalNode.IP)
        EngineID = 1
        ObjectSubType = "ICMP"
        External = "true"
         Community = "$($ExternalNode.CommunityString)"
        DNS = "$($ExternalNode.Caption)"
        SysName = "$($ExternalNode.Caption)"
        Caption = "$($ExternalNode.Caption)"
    }
    Write-Output "Adding node $($ExternalNode.Caption)"
    New-SwisObject $swis -EntityType "Orion.Nodes" -Properties $newNodeProps
    sleep -m 200
    
    #Add Custom Properties
    $CustomPropsUpdate = @{ Test1="$($ExternalNode.Test1)"}
    #Build URI
    $uri = Get-swisdata $swis -query "SELECT n.CustomProperties.Uri FROM Orion.Nodes n where IP = '$($ExternalNode.IP)'"
    Write-Output "Setting Custom Properties for $($ExternalNode.Caption)"
    Write-Output "URI for update is $uri"
    set-swisobject $swis -Uri $uri -Properties $CustomPropsUpdate
    sleep -m 200 
    }
    Write-Output "Script Complete.  Exiting..."
     
    

Reply
  • , So below is a script that I have that can do a bulk import of External Nodes and then modifies a Custom Property during that time. It should have the requirements you need to get it to work with some modification. Some key difference between yours and mine is that it looks like you take and build out a URI, mine queries SWQL directly for the URI, which i find helps reduce errors i've seen when trying to rebuild the URI within the script. But in essence much of it is the same, at a high level you'd just need a second set of property definitions for the CP, and then a second Set-SwisObject to modify the CP's for that node.

     # Pre-Reqs:
    # 1. Ensure that the SolarWinds SDK, and powershell modules are installed on machine running the script
    # 2. CSV that contains IP in the first column, Desired Caption in the Second Column, and a CommunityString in the third column (will default to public if none identified), and desired Custom Properties in the remaining columns (IF ADDING CUSTOM PROPERTIES ENSURE THAT YOU UPDATE LINE 39 AND 82 WITH THE APPROPRIATE REFERENCES!!) No Column Headers.
    
    import-Module SwisPowerShell
    # Connect to SWIS
    
    
    $hostname = 'localhost'
    $swis = Connect-Swis -host $hostname -Certificate
    
    #Import New Nodes
    if ($names -eq $true) {
    $names = $null
    }
    #$names = import-csv \\server\file.txt
    $filename = Read-Host -Prompt "Enter CSV Location (\\server\file or C:\dir\file)"
    if (Test-Path $filename) {
    Write-Output "File exists"
    
    $ExternalNodes= import-csv $filename -Header 'IP','Caption','CommunityString','Test1'
    $count = $ExternalNodes.length
    }
    else {
    Write-Output "Bad file, exiting....."
    exit
    Write-Output $ExternalNodes
    }
    
    
    $wait = $false
    while ($wait -eq $false) {
    
    $check = Read-Host "About to add $($count) External Nodes to Orion Instance: $($hostname) Proceed? (y/n)"
    if ($check -eq 'y') {
    $wait = $true
    }
    else { if ($check -ne 'n') {
    $wait = $false
    }
    else {
    Write-host "Process Aborted.  Exiting....."
    exit 0
    }
    }
    }
    foreach($ExternalNode in $ExternalNodes){
    # Set Properties for New External Node
       $newNodeProps = @{
        IPAddress = $($ExternalNode.IP)
        EngineID = 1
        ObjectSubType = "ICMP"
        External = "true"
         Community = "$($ExternalNode.CommunityString)"
        DNS = "$($ExternalNode.Caption)"
        SysName = "$($ExternalNode.Caption)"
        Caption = "$($ExternalNode.Caption)"
    }
    Write-Output "Adding node $($ExternalNode.Caption)"
    New-SwisObject $swis -EntityType "Orion.Nodes" -Properties $newNodeProps
    sleep -m 200
    
    #Add Custom Properties
    $CustomPropsUpdate = @{ Test1="$($ExternalNode.Test1)"}
    #Build URI
    $uri = Get-swisdata $swis -query "SELECT n.CustomProperties.Uri FROM Orion.Nodes n where IP = '$($ExternalNode.IP)'"
    Write-Output "Setting Custom Properties for $($ExternalNode.Caption)"
    Write-Output "URI for update is $uri"
    set-swisobject $swis -Uri $uri -Properties $CustomPropsUpdate
    sleep -m 200 
    }
    Write-Output "Script Complete.  Exiting..."
     
    

Children
  • That's pretty intense  LOL

    The nodes I will be modifying are already in SolarWinds...

    I simply want to update the custom properties...

    If these custom properties have data or are null, i want to be able to update them in powershell..

    I appreciate your help, and have been working on this since March.. LOL   

  • Here's a basic example of how to modify custom properties of nodes already in SolarWinds from within PowerShell.

    Now if you already are exporting the data into CSV / Excel and making updates there you could just re-import within the GUI too if it's a one-off.

    Import-Module -Name SwisPowerShell
    
    $hostname = 'myOrionServer'
    
    $creds = Get-Credential
    
    $swis = Connect-Swis -Hostname $hostname -Credential $creds
    
    $query = @"
    	SELECT
    		 n.Caption
    		,n.IP_Address
    		,n.Uri
    		,n.CustomProperties.ServiceNow_Owner_1
    	FROM Orion.Nodes AS n
    "@
    
    $selection = Get-SwisData -SwisConnection $swis -Query $query
    
    ForEach ($node in $selection) {
    
    	$cpUri = $node.Uri + "/CustomProperties"
    
    	Write-Output("Working on " + $node.Caption)
    	
    	If ($node.ServiceNow_Owner_1 -ne "myExpected Value" -or [string]::IsNullOrEmpty($node.ServiceNow_Owner_1)) {
    	
    		Set-SwisObject -SwisConnection $swis -Uri $cpUri -Properties @{
    		
    			ServiceNow_Owner_1 = "myUpdatedValue"
    		
    		}
    		
    		Write-Output("`tValue for ServiceNow_Owner_1 updated...")
    	
    	} Else {
    	
    		Write-Output("`tNo updates necessary...")
    	
    	}
    
    }

    Here's a take on using Read-Host to pull in some input from the console and using it in a query...

    Import-Module -Name SwisPowerShell
    
    $hostname = 'myOrionServer'
    
    $creds = Get-Credential
    
    $swis = Connect-Swis -Hostname $hostname -Credential $creds
    
    $prompt1 = "Enter the Node Name (Caption) of the node to edit properties on: "
    
    $CaptionFilter = Read-Host -Prompt $prompt1
    
    $prompt2 = "Which property would you like to edit on '" + $CaptionFilter + "'?"
    
    $customPropertyName = Read-Host -Prompt $prompt2
    
    $query = @"
    	SELECT TOP 1
    		 n.Caption
    		,n.IP_Address
    		,n.Uri
    		,n.CustomProperties.$customPropertyName
    	FROM Orion.Nodes AS n
    	WHERE n.Caption = '$CaptionFilter'
    "@
    
    $node = Get-SwisData -SwisConnection $swis -Query $query
    
    $cpUri = $node.Uri + "/CustomProperties"
    
    $prompt3 = "What would you like to change the property '" + $customPropertyName + "' to?"
    
    $customPropertyValue = Read-Host -Prompt $prompt3
    
    Set-SwisObject -SwisConnection $swis -Uri $cpUri -Properties @{
    
    	$customPropertyName = $customPropertyValue
    
    }

    Warning: that's untested but should give you the idea. Slight smile

  • , you trying to update them via a CSV through powershell?

  • So,

    We have thousands of servers...  

    lets say i want to only one server 

    $nodes = Get-SwisData $swis 'SELECT NodeID, Caption, DNS, IPAddress, Uri FROM Orion.Nodes WHERE Caption -eq 'jwj-man01''
    I have tried this, but it doesn't work...
    If the powershell script asked me, 'what node do you want to modify'
    i could put the node caption or IP address... and then it could ask 'what custom property do you want to change?'
    don't know if that is doable.. but it would be great...
    and then also have the option of importing node captions from xlsx...   
  • $query = @"
    SELECT
    n.Caption
    ,n.IP_Address
    ,n.Uri
    ,n.CustomProperties.ServiceNow_Owner_1
    FROM Orion.Nodes AS n
    "@

    Awesome, this worked but pulled 3700 servers... LOL

    how would i filter it?  like by caption or subnet?

  • Heh... look at the Read-Host command within PowerShell.

    docs.microsoft.com/.../read-host

  • I'll update my prior response with the read-host and a filter based off that input.

  • That would be the option for multiple nodes... 

  • - does that help and/or do you have any more questions?

  • So, I was able to select one node this way...

    $query = @"
    SELECT
    n.Caption
    ,n.IP_Address
    ,n.Uri
    ,n.CustomProperties.ServiceNow_Owner_1
    FROM Orion.Nodes AS n
    WHERE n.Caption LIKE 'JWJ-MAN01'
    "@