Quantcast
Channel: THWACK: All Content - Orion SDK
Viewing all 2677 articles
Browse latest View live

CreateContainerWithParent with multiple Children

$
0
0

We are migrating from another Network Monitoring System to Solarwinds and it is my job to automate the transfer of monitoring.

We want to maintain the tree-like group structure we had in the previous NMS, so my eye fell on the 'CreateContainerWithParent' verb. I couldn't find proper documentation for it, but did find out through some experimentation that it takes it's first argument as the ID of the Parent group.

This works wonderfully, except that it will ignore any child definition specified after the first.

So in this case, it will create the group 'Test_Group', under parent group '3', with it's only child being the node with NodeID '724'.

 

So my question is: is there a way to let this verb accept multiple children, or do I have to manually(through AddDefinition) add children to this group? The latter would be less desirable since it adds more API calls and there are a lot of nodes to transfer.

 

group_id = swis.invoke('Orion.Container', 'CreateContainerWithParent',     '3',     'Test_Group',     'Core',      60,      0,     'Test_Group',      True,     [          {'Name': 'Test_Node', 'Definition' : 'swis://XXXX-XXXX./Orion/Orion.Nodes/NodeID=724'},          {'Name': 'Apples', 'Definition' : 'swis://XXXX-XXXX./Orion/Orion.Nodes/NodeID=725'}     ]
)

 

Thanks!

 

P.S. For bonus points: where does the 'Name' in the Name/Definition thing go? I've looked around in newly created groups and the nodes in them, but couldn't really find where this information goes.

P.P.S. For additional bonus points: where do groups go when you don't assign 'Core' as their owner? Before I found CreateContainerWithParent, I tried to simply change the owner to the parent group I wanted. The query succeeded and did return a groupID, but when I try to open a webpage for that ID, it doesn't exist.


Is there a connection between IPAM.IpNode and Orion.Nodes?

$
0
0

I think I understand they are completely different, however I might as well ask a question to clarify my understanding.

 

Swiss Schema for the entities in question:

https://solarwinds.github.io/OrionSDK/schema/Orion.Nodes.html

https://solarwinds.github.io/OrionSDK/schema/IPAM.IPNode.html

 

I'm using SolarWinds IPAM, and trying to research the API. I understand that some entities used in IPAM come from the core Orion namespace.

 

My question is, is there any connection between IPAM.IpNode and Orion.Nodes? It seems to me an IpNode is part of a SubNet, and no direct connection exists to an actual Node entity.

 

If that's the case, my follow up question is: Does SolarWinds IPAM have a concept of a device? Some entity that can share multiple IpNodes and relate them together? Currently I'm thinking this is not part of the functionality of SolarWinds IPAM, but I'm double checking here on Thwack to be sure.

 

Thanks~

Removing Groups with swispowershell

$
0
0

#

#.SYNOPSIS

# Gets SolarWinds groups.

#

#.EXAMPLE

# Get-SWGroup

#

function Get-SWGroup {

    Write-Information ("The name of this function is: {0} " -f $MyInvocation.MyCommand)

    Get-SwisData -SwisConnection $swis -Query 'SELECT ContainerID,Name,URI FROM Orion.Container'

}

 

#

#.SYNOPSIS

# Remove-SWGroup

#

#.EXAMPLE

# Remove-SWGroup

#

Function Remove-SWGroup {

    Param (

    [Parameter(Mandatory=$True)]

        $Group

   )

    Remove-SWISObject $swis -Uri (Get-SWGroup|where {$_.Name -eq $Group}).URI

}

 

 

 

Remove-SWISObject : Operation not supported on Orion.Groups

At C:\Program Files\WindowsPowerShell\Modules\ITDSolarWinds\ITDSolarWinds.psm1:1227 char:5

+     Remove-SWISObject $swis -Uri (Get-SWGroup|where {$_.Name -eq $Gro ...

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [Remove-SwisObject], FaultException`1

    + FullyQualifiedErrorId : SwisError,SwisPowerShell.RemoveSwisObject

 

 

 

Can anyone provide me working example?

Why doesn't it just work??

$
0
0

I work for a MSP that manages many customer networks. Despite Solarwinds not being the proper tool for multi-tenancy monitoring, we have done a pretty good job with it so far. There is one thing that bothers me though, every time Soalrwinds comes out with a new feature, it seems like they overlook a few things and it doesn't work the way its supposed to. We have been on an initiative to automate as much stuff as we can to handle our increasing work load, but I have been getting nothing but roadblocks with Solarwinds.

 

My idea was to take a list of IP address and create a script using the orionSDK to automate loading the devices into the platform. In theory it should work fine, but in reality; it doesn't. Here are the issues that I have run into. If anyone has any viable work-arounds; I'm all ears.

 

Adding Devices

1. Adding devices through the API using swis.create('Orion.Nodes', **props). This should essentially be the same thing as adding a single node through the web UI. You supply the IP, and SNMP creds and it gets added, but it doesn't work like that. For some reason, Solarwinds decided it would be fun to make us search for, and manually configure all the default pollers that would normally get automatically added when doing it through the UI. Why do I have to supply that through the API when it is automatically detected when adding a node through the UI?? The functionality should be the same regardless of how I'm adding a device. We support a multitude of device vendors, and if I'm going to build a dictionary or database table with all the default pollers for each vendor so my script can add the correct ones, then I may as well just build my own NMS...

 

2. Adding devices using the discovery API. For this, there are 2 options:

     Option A: Setup and run the discovery, but don't import the nodes automatically. This defeats the purpose of automation as we will then have to go into the UI and find the discovery results and finish adding interfaces/volumes. This just saves 8 clicks of the 'Next' button when having to manually configure the discovery.

     Option B: Setup and run the discovery, and automatically import the nodes. When reading through the documentation, this seemed like it would be the best way to go. In my mind, it should discover the devices and apply the default pollers, then add them to the system with no interfaces or volumes, we could then add specific interfaces using the AddInterfacesOnNode verb. But, as with everything else I have tried, this doesn't work as expected either. When I run the script to add just the nodes (there is no PluginConfigurationItem configured for the Interfaces in my script), it discovers the device, and brings in all Up/Up interfaces as well as every Volume (including A:). Once again this defeats the purpose of automation because now I have to go back to every node I create and remove the resources I didn't need. The options for configuring the Interfaces PluginConfigurationItem are the same options that you get when configuring the discovery through the web. It seems like it would work until you realize that the filters for interface names are treated as AND instead of OR which basically keeps any interfaces from matching your filters and you end up with nothing.

 

Creating User Accounts

Here is another feature that doesn't work like it should. I have successfully created a script that can create a list of user accounts. There are 2 problems with the API though:

1. All attempts at creating/applying account limitations to the user accounts through the API have failed, so I still have to manually add them after the accounts are created.

2. While the accounts appear to get created successfully,  They are missing the options to set which menu bars are visible to the account. The options don't appear in the account properties until the account has logged into the Web UI at least once. This does not apply to accounts created through the UI, those are fine. In order to make this 'feature' remotely useful (we often get asked to create 10-15 accounts per customer) I had to make another method that logs each user into the web so that I can configure their menu bars. I ended up using Google's Selenium package in python to accomplish this, and while it works; its something that I shouldn't have had to do at all.

 

There seems to be a big disconnect between UI functionality, and the functionality/efficacy of the API. It makes me wonder if the developers have ever had to use their platform at all, or fully test the features that they implement in the API.

Please accept and fix this bug: API accepts null values when it should not

$
0
0

I have code that sets node and interface properties like stat collection and polling intervals.

 

When the script was run last Friday, everything seemed fine, but today I noticed our polling engine percent utilization went from 86% to 13%, so I started investigating.

 

Once I found the correct log, collector.Service.log, I was seeing PolllingPlan process failed Solarwind.Intefaces.SNMP Data is null and the stack trace.

 

I stated looking at the polling tables and other various tables to see what might be null and I couldn't find anything. After a few hours I decided to take the DLL's with similar names and reverse engineer what the SQL query was. I could have also used SQL profiler, but there is so much activity, I think it would have been harder.

 

I finally found in the SolarWinds.Interfaces.Collector DLL, the method for GetStatusPollingDescriptions and the data reader for the InterfacesDAL.

 

I believe these lines in the code are throwing the exception:

@interface.PollInterval = reader.IsDBNull(ordinal4) ? 120 : reader.GetInt32(ordinal4);

@interface.PollInterval = reader.IsDBNull(ordinal4) ? 120 : reader.GetInt32(ordinal4);

 

A check for null is performed on the result, but the schema doesn't allow it to be null; when the reader.GetInt32(ordinal4) is called an exception is thrown.

 

IMO, I think the API should have returned a bad request or some other error if the value isn't supported in the schema.

 

Regards,

 

Daniel

Error Cannot find assembly when running Invoke-SwisVerb $swis Orion.NPM.Interfaces DiscoverInterfacesOnNode $nodeId

$
0
0

I am playing around with the Orion SDK and i am trying to discover interfaces on a node. We are running SolarWinds SAM.

I am testing this script:

 

Import-Module SwisPowerShell

$swis = Connect-Swis -Hostname solarwinds -Trusted

 

# The node ID to discovery interfaces on

$nodeId = 3

 

# Discover interfaces on the node

$discovered = Invoke-SwisVerb $swis Orion.NPM.Interfaces DiscoverInterfacesOnNode $nodeId

 

if ($discovered.Result -ne "Succeed") {

    Write-Host "Interface discovery failed."

}

else {

    # Uncomment one of the following to limit the interfaces that get added:

 

    # No. 1: Remove interfaces that are NOT ifType 6 (FastEthernet)

    #$discovered.DiscoveredInterfaces.DiscoveredLiteInterface | ?{ $_.ifType -ne 6 } | %{ $discovered.DiscoveredInterfaces.RemoveChild($_) | Out-Null }

 

    # No. 2: Remove interfaces that have a caption of 'lo' (Loopback)

    #$discovered.DiscoveredInterfaces.DiscoveredLiteInterface | ?{ $_.Caption.InnerText -eq 'lo' } | %{ $discovered.DiscoveredInterfaces.RemoveChild($_) | Out-Null }

 

    # Add the remaining interfaces

    #Invoke-SwisVerb $swis Orion.NPM.Interfaces AddInterfacesOnNode @($nodeId, $discovered.DiscoveredInterfaces, "AddDefaultPollers") | Out-Null

    $discovered

}

 

When running this script i get the error Invoke-SwisVerb : Verb Orion.NPM.Interfaces.DiscoverInterfacesOnNode: Cannot find assembly. Anyone knows why i get this? Is this command only for the NPM part of Solarwinds?

TC18: Customize Polling Intervals With the Orion SDK

$
0
0

This script was featured on the TWHACKcamp 2018 session "There's an API for That," which you can watch in its entirety here. The two scripts I used are attached to this post.

 

My goal here is to explain the idea behind the script as well as point out any major design points within the code. But there are a few things I need to clear up before I begin:

 

First, you will probably notice that this script is written in Perl, a language with a long, illustrious, and glorious history as a text processing tool, and yet not a language which lends itself to process-oriented tasks. I selected the language because:

  1. I am old, and writing in Perl brings back memories of my youthful glory days.
  2. I am stubborn, and they said Perl wasn't the right tool for this job so I had to prove them wrong.
  3. It underscores the flexibility of the Orion API—if your programming language supports REST, then you can use it.

 

Second, you'll notice that I've had to load a few different packages at the start of the script to make this all work. I'll describe them in detail below, but should you decide to follow in my footsteps, you will need to get comfortable loading CPAN modules before any of this will run.

 

Third, I need to take a moment and express my extreme gratitude and deepest thanks to @tdanner, @kmsigma, @Zackm, and @ironman84 for their help, encouragement, support, and patience.

 

However, the biggest thank-you goes to Steven Klassen (a.k.a. @mrxinu), who took significant time out of his day(s) to help clean up the spaghetti that was my original attempt at this script. The best thing you could say about my original was “it ran.” After his assistance, you can say “it ran with a bit of grace and style.”

 

Background: What Problem Are We Solving?

When you load up a bunch of nodes in Orion® (whether you're using Network Performance Monitor, Server & Application Monitor, or some other module) you "get" a certain level of monitoring for "free." (God as my witness, the legal team insisted I use those air quotes because they're afraid someone will really think it's free.) That monitoring includes availability (up/down of the node, interfaces, disks, etc.) and statistic collection (CPU, RAM, disk space, etc.). Generally speaking, the availability data is collected by default every 120 seconds, and the statistic data is collected every 5 to 10 minutes. Which is fine, IN GENERAL.

 

BUT... there are some devices in your environment that need to be monitored, but not that aggressively. Like the under-the-desk server in the training room. Or the media server that plays HR training videos for new hires. Or the internet-connected coffee pot. At the other end of the spectrum are business-critical systems that need much more aggressive monitoring.

 

The good news is that Orion allows you to set a global standard for polling frequency, and also adjust the that frequency on a per-machine basis. The bad news is that this is, by necessity, a manual process. You have to pick the machine(s) you want to adjust and adjust them. And generally speaking, this is the right choice.

 

But what if you wanted to base polling frequency on a variable? What if you had a custom property that indicated the criticality of the system, and you wanted Orion to just naturally adjust polling based on that field? In that way, you could monitor a system that was in the "build" stage very lightly just to get baselines, but turn it up to 11 when you moved to "burn-in" stage, and then ratchet the polling frequency down to normal levels when the criticality was "prod-sev-3."

 

That's what this script does. It reads the value of a database field for each node, and adjusts the polling values accordingly.

 

The Values

For the sake of example, here's what I have set up:

  • I have a custom property called "Polling_Level"
  • The "Polling_Level" values and their availability (in seconds) / statistics (in minutes) frequency are:
    • Decommissioned (600/60)
    • Training (300/30)
    • Build (300/15)
    • Dev (120/15)
    • Prod-Sev-5 (300/10)
    • Prod-Sev-4 (240/5)
    • Prod-Sev-3 (120/5)
    • Prod-Sev-2 (60/2)
    • Prod-Sev-1 (30/2)
    • Scrutiny (10/1)

 

The Nitty Gritty (that one line of code)

The main line of code—the one that does all the heavy lifting—is here:

$response = $client->POST('/SolarWinds/InformationService/v3/Json/'.$clienturi, $newpolljson, {"Content-Type"=>"application/json"} );

 

But to understand it, you need a little bit of background.

 

Syntax of “That One Line of Code”

There are actually two syntaxes you need to understand: the syntax of the Orion API and the syntax of Perl as it relates to the API.

 

Regarding the API, you need to understand that you're doing an update operation (https://github.com/solarwinds/OrionSDK/wiki/REST#update-request), which requires 3 things:

  1. The URI of the object you want to update, including the SolarWinds Information Service (SWIS) prefix
  2. The value(s) you want to set the object to
  3. The content-type

In this example, my values are going to be set to:

  1. "/SolarWinds/InformationService/v3/Json/" plus the URI of the node (which is the variable $clienturi in my sample code)
  2. The field StatCollection set to a certain number of minutes, and the field PollInterval set to a certain number of seconds
  3. The content type is "application/json." Period. No decisions here, it just has to be included for the command to work.

Meanwhile, the Perl syntax happening here includes:

  1. '/SolarWinds/InformationService/v3/Json/'.$clienturi combines (concatenates) the $clienturi variable with the SWIS prefix elements
  2. To create an array of values to update, the format in Perl is: '
    StatCollection'=>"5", "PollInterval"=>"60" 
    (SEE NOTE BELOW)
  3. The content type gets enclosed in French brackets like this:
    {Content-Type"=>"application/json"}

 

NOTE: that's how you would manually set the variables. In my code, I'm creating a hash earlier, looking up the matching value in the "Polling Level" custom field, and taking the resulting values.

 

Other Important Elements for "That One Line of Code"

As I just mentioned, I'm looking up the custom property value, finding it in my hash array, and extracting those values. If you were to assign it manually, it would look like this:

%newpollvalue = ('StatCollection'=>"5", "PollInterval"=>"60");

 

The next thing I want to point out is converting the hashed values into JSON-compatible data. The following like does just that, using the encode_json function that comes in the "JSON" package.

my $newpolljson = encode_json \%newpollvalue;

 

All of that being said, if this main line was running in a complete vacuum, this this is all you would need. Of course, it's NOT running in a vacuum and I need to explain a few other dependencies.

 

Packages and Dependencies

At the top of the script, you'll find a few packages being invoked. Here's where each of them comes into play.

 

use REST::Client;

This sets up the initial REST-full connection to the SolarWinds® server, which you see in the following line.

my $client = REST::Client->new();

 

use MIME::Base64;

You should never keep username/passwords in clear text in your script. That’s just lazy (and also dumb, but I’m trying not to judge). Even though my sample script DOES give you the option (commented out) just in case you are having problems you think are due to authentication, it really uses an encrypted password. (More about that in a separate section of this post.) That’s what this module and the following line of code is for.

encode_base64("$username:$password", ''));

 

use Crypt::RC4;

This is used to decrypt the password when using secure (i.e., CORRECT) password handling to connect to the SolarWinds server.

 

use URI::Encode qw(uri_encode);

When you pass a query via REST, it needs to be encapsulated as a universal resource indicator (URI). This module facilitates that behavior, as in:

uri_encode($query));

 

use JSON::Parse ':all';

When you get a JSON response back (as when you get the record containing node details), you need to split it up into something readable. That's how the parse command works.

parse_json $client->responseContent();

 

use JSON; 

Finally, as mentioned in the previous section, the values you want to push to the server need to be JSON-ified, and that's what this module does.

my $newpolljson = encode_json \%newpollvalue;

 

Connecting to Orion

NOTE: This section is a complete aside, but also a pet peeve. Connecting correctly (i.e., safely) to your Orion instance is one of those good habits you should have, like eating right, getting enough sleep, and avoiding sweets before bedtime. Which is to say: (almost) everyone understands it's a good idea, but many will find excuses why they don't. So skip this section if you must, but understand that it *is* important to your overall Orion API health and welfare.

 

There are two basic options to connect your script to Orion:

  1. The quick and dirty way that makes security professionals weep and likely gets you in trouble with the auditors.
  2. The safe and correct way that will let you (and your company) sleep easier at night knowing you haven’t thrown the gates of security wide open to the ravenous hordes of hackers that lurk just outside.

 

The Quick and Dirty Way

This is what I use when I am first throwing a script together and don't want to worry that something about the way I'm passing credentials is slowing me down.

 

my $username = 'knightswhosayni';
my $password = 'icky-icky-ptang-ptang';
my $hostname = '10.110.69.72';
my $client = REST::Client->new();
$client->getUseragent()->ssl_opts(verify_hostname => 0);
$client->getUseragent()->ssl_opts(SSL_verify_mode => 'SSL_VERIFY_NONE');
$client->setHost('https://' . $hostname . ':17778');
$client->addHeader('Authorization', 'Basic ' . encode_base64("$username:$password", ''));

 

The Right Way

This process uses an encrypted password which can be decrypted with a key. The key is in one file on your system ("swkeyfile.txt") and the encrypted password in another ("$swhashfile.txt"). While this script makes it easy by putting everything in the same directory as the script itself, we're going to remind you that both files should be in protected areas and should only be read-able by the account the script is running under. Otherwise you have no security at all.

 

Step 1: Get the Key:

$keyfile = "swkeyfile.txt";
open($fh1, '<', $keyfile) or die "Could not open file '$keyfile' $!";
while ($row = <$fh1>) {   chomp $row;   $key=$row;
}
close $fh1;

 

Step 2: Get the Encrypted Password:

$hashfile = "swhashfile.txt";
open($fh2, '<', $hashfile) or die "Could not open file '$hashfile' $!";
while ($row = <$fh2>) {   chomp $row;   $enc_hash=$row;
}
close $fh2;

 

Step 3: Unencrypt the Password

$decoded = decode_base64($enc_hash);
$swpassword = RC4($key, $decoded);

 

Step 4: Use the Password to Connect to the Orion Server

#Set up the REST connection to the server
$client = REST::Client->new();
$client->getUseragent()->ssl_opts(verify_hostname => 0);
$client->getUseragent()->ssl_opts(SSL_verify_mode => 'SSL_VERIFY_NONE');
$client->setHost('https://' . $hostname . ':17778');
$client->addHeader('Authorization', 'Basic ' . encode_base64("$username:$swpassword", ''));

 

Step Zero: Create the Key and Hashed Password Files in the First Place

Yes, step zero. Before you can use the safe technique I describe in steps 1-4, you have to create those two files. This is a one-time process, but if you don't do it, none of the rest of it will work. This is the script you'll need.

#!/usr/bin/perl
use strict;
use warnings;
use Crypt::RC4;
use MIME::Base64;
use Bytes::Random::Secure qw(random_bytes random_bytes_base64 random_bytes_hex);    #see https://metacpan.org/pod/release/DAVIDO/Bytes-Random-Secure-0.29/lib/Bytes/Random/Secure.pm for full usage

#Generate random key and store it in a file
my $keyfile = "swkeyfile.txt";
my $key = random_bytes(32); # A string of 32 random bytes.
open(my $fh1, '>', $keyfile) or die "Could not open file '$keyfile' $!";
print $fh1 $key;
close $fh1;

#Now take the SolarWinds user password and encrypt it using the key
my $swpassword = "YOUR PASSWORD GOES HERE";
my $encrypted = RC4($key, $swpassword);
my $encoded = encode_base64($encrypted);
my $hashfile = "swhashfile.txt";
open(my $fh2, '>', $hashfile) or die "Could not open file '$hashfile' $!";
print $fh2 $encoded;
close $fh2;

 

Additional Resources

If you want to learn more about about the Orion API, then you ought to check out the following:

 

If you, for some insane reason, need to know about using the Orion API via Perl, then this sample offers a lot of examples:

https://github.com/solarwinds/OrionSDK/blob/master/Samples/Perl/query.pl

 

 

The Mostly Un-Necessary Summary

The rest of the script is just your usual jumble of error checking, table lookups, etc. I've tried to comment the code so that it's easier to follow, but I welcome your questions (@adatole on thwack.com or @leonadato on Twitter).

 

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.

TC18: Exporting Network Atlas Map Files

$
0
0

THWACKcamp 2018

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.

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.

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.


powershell script to search node and delete

$
0
0

Please note that this script was based on this thwack message.

All I did was to change the swsql query used to get the URI and to search and delete a node via PowerShell

 

# This script will search for  node and delete it if exists

#

################################## Attention ###############################################

# You must have Orion SDK installed and set-execution policy must be set to unrestricted!!#

#Before running you must setup your hashed encrypted password using the line below.       #

###########################################################################################

 

#### Prerequisites ###

#  run the line below save credentials to be used by this script on a encrypted file

#GET-CREDENTIAL –Credential "EnterTheOrionUserNamehere” | EXPORT-CLIXML C:\Scripts\SecureCredentialsSAM.xml

## Load the SolarWinds Powershell snapin.

##Needed in order to execute the script.

##Requires the Orion SDK 2.0 installed on the machine this script is running from.

Add-PSSnapinSwisSnapin

# SolarWinds username and password section.

# It is recommended to use a local account create within SAM with only. I strongly recommend that you don't use a MS local account or domain account.

# This section allows the password to be embedded in this script. Without it, the script will not work.

#This is using the hashed encrypted password

$MyCredentials=IMPORT-CLIXMLC:\Scripts\SecureCredentialsSam.xml

$ORIONSERVERNAME= 'yourserver.domain.com'

#This is connecting to SAM to pull the info we need need with the info given

$swis=Connect-Swis-Credential$MyCredentials-host$orionservername

$nodename=read-host"Enter node Name"

$nodeuri=Get-SwisData$swis"SELECT Uri FROM Orion.Nodes WHERe NodeName LIKE '%$nodename'"

if (!$nodeuri) {Write-Host"node does not exist on SAM"}

if ($nodeuri) {

Write-Host"node exist, uri: $nodeuri"

Remove-SwisObject$swis$nodeUri

Write-Host"node has been removed"

}

How to Create a Discovery Profile using Orion API in PHP

$
0
0

Hi Everyone,

 

I've been trying to get a PHP page I've been writing to start a Discovery Profile, but it seems to be getting hung up on getting the XML Context into JSON format so that I can send it it the REST API via cURL.

 

Has anyone been able to do this before, and if not, does anyone have any ideas?

 

I am relatively new to PHP and curl, so I'm sure I've missed some obvious things.

 

I've set the following XML equal to the variable $core_plugin which I later try to pass into an Invoke call.

<CorePluginConfigurationContext xmlns='http://schemas.solarwinds.com/2012/Orion/Core' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>        <BulkList>                <IpAddress>                        <Address>                        </Address>                </IpAddress>        </BulkList>        <Credentials>                <SharedCredentialInfo>                        <CredentialID>1</CredentialID>                        <Order>1</Order>                </SharedCredentialInfo>        </Credentials>        <WmiRetriesCount>0</WmiRetriesCount>        <WmiRetryIntervalMiliseconds>1000</WmiRetryIntervalMiliseconds></CorePluginConfigurationContext>

 

which I then do this is PHP

// Construct the Core Plugin XML Document, then Have Solarwinds Build the Plugin
$info = simplexml_load_string($core_plugin);
$info->BulkList->IpAddress->Address = "10.10.10.10";
$updated_core_plugin = $info->asXML();
$core_plugin_url = "https://solarwindsServer.com:17778/SolarWinds/InformationService/v3/Json/Invoke/Orion.Discovery/CreateCorePluginConfiguration";
$core_plugin_data = array('context' => "$updated_core_plugin");
$json_core_plugin = json_encode($core_plugin_data);
$finished_core_plugin = CallAPI($core_plugin_url, $json_core_plugin);

function CallAPI($url, $data = false) {
   $ch = curl_init();    // Authentication:  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);  curl_setopt($ch, CURLOPT_USERPWD, "username:password");  curl_setopt($ch, CURLOPT_URL, $url);  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  curl_setopt($ch, CURLOPT_VERBOSE, true);  curl_setopt($ch, CURLOPT_POSTFIELDS, $data);  curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                        'Content-type: application/json',                                        'Content-length: ' . strlen($data)                                      ));  $result = curl_exec($ch);  $response = curl_getinfo($ch, CURLINFO_HTTP_CODE);  $error = curl_error($ch);  $info = curl_getinfo($ch);  curl_close($ch);    if ($result == false) {  echo "Response: " . $response . "
";  echo "Error: " . $error . "
";  echo "Info: " . print_r($info);  die();  }  return $result;
}

 

 

If you need anything else from me, please let me know.

 

Just FYI, the curl section was from another user on Thwack.

 

Thanks,

 

Jordan

REST - HTTP Post - SWIS Invoke Orion.Container/CreateContainer Issue

$
0
0

Hello All,

 

I'm trying to do a http post to create a container and I can't seem to get the syntax right.

I've tried almost every possible combination for the memberDefinition section and nothing seems to work...

 

URL:

https://localhost:17778/SolarWinds/InformationService/v3/Json/Invoke/Orion.Container/CreateContainer

 

POST DATA:

{"name":"Orion123","owner":"Core","frequency":60,"statusCalculator":0,"description":"testing container creation","pollingEnabled":"true","memberDefinitions":[<ArrayOfMemberDefinitionInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.solarwinds.com/2008/Orion"><MemberDefinitionInfo><Name>Testy123</Name><Definition>filter:/Orion.Nodes[CustomProperties.IT_Service='WAN' AND CustomProperties.Site_Code='USA']</Definition></MemberDefinitionInfo></ArrayOfMemberDefinitionInfo>]}

 

from SWQL Studio if I populate the values through the Invoke function (right click on the CreateContainer option) I have no issue, so I'm assuming there must be some error with my JSON formatting.

 

The above example is using the following format:

"memberDefinitions":[%data%]

 

I've also tried using another example found on thwack as well:

 

{"name":"Orion123","owner":"Core","frequency":"60","statusCalculator":"0","description":"hello","pollingEnabled":"true","memberDefinitions":["name":"Test1234","definition":"filter:/Orion.Nodes[CustomProperties.IT_Service='WAN' AND CustomProperties.Site_Code='USA']"]}

 

If anyone can assist with this, it would be greatly appreciated... trying to automate container creation, and hopefully group dependencies after -

 

Help me DTANNER AND THWACK COMMUNITY, you're my only hope

GetFirstAvailableIp Not working in 4.7

$
0
0

We were running IPAM version 4.5 and the following command to obtain the next available IP address for a subnet; Invoke-SwisVerb $swis IPAM.SubnetManagement GetFirstAvailableIp @.

 

We upgraded to version 4.7 and we have two issues; 1) Domain accounts will not authenticate/run APIs.  We have to use local orion accounts to progress. 2) Once a local account is used, the above command is returning....

 

Invoke-SwisVerb : Incorrect syntax near 's'.

Unclosed quotation mark after the character string '

UNION ALL

SELECT obj.[GroupId],obj.[ParentId],obj.[GroupType],obj.[Address],obj.[AddressN],obj.[AddressEnd],obj.[AddressMask],obj.[CIDR],obj.[FriendlyName],obj.[Comments],obj.[VLA

N],obj.[Location],obj.[LastDiscovery],obj.[Status],obj.[ScanInterval],obj.[TransientPeriod],obj.[RetainUserData],obj.[NodeExpungeInterval],obj.[UsedCount],obj.[Available

Count],obj.[ReservedCount],obj.[TransientCount],obj.[DisableAutoScanning],obj.[TotalCount],obj.[PercentUsed],obj.[HasLicenceOverflow],obj.[DisableNeighborScanning],obj.[

NeighborScanAddress],obj.[NeighborScanInterval],obj.[DnsZoneId],obj.[EngineId],obj.[ClusterId] FROM [IPAM_Group]  AS obj

INNER JOIN GroupTree ON obj.ParentId = GroupTree.GroupId

)

SELECT * FROM GroupTree

'.

At C:\Users\admin-jcrowe\Downloads\getIP.ps1:4 char:10

+ $NEWIP = Invoke-SwisVerb $swis IPAM.SubnetManagement GetFirstAvailableIp @("10.2 ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [Invoke-SwisVerb], FaultException`1

    + FullyQualifiedErrorId : SwisError,SwisPowerShell.InvokeSwisVerb

TC18: Creating and Updating Orion Custom Properties with PowerShell

$
0
0

THWACKcamp 2018

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

 

OVERVIEW / REFERENCES:

This is a small script I used as a demo during a wonderful experience that I was able to share with 2 of my favorite people ( KMSigma and adatole ). While I am not the most gifted scripter (reminder: Scripting != Coding), I was blessed to be invited to join my fellow MVPs in a session devoted to evangelizing the majesty of all things scripting.

 

While we obviously didn't have enough time to teach our session to granular detail, we did attempt to provide a decent amount of information in-session and all of the scripts are available here in the Orion SDK forum. Here are some good resources for the topics covered by my personal script:

  • GitHub: Orion SDK - THE place to start all of your API adventures!
  • Managing Custom Properties - The SDK Wiki entry that directly applies to the information in this post
  • Orion SDK (you've obviously already found this, but who can sleep at night without thanking THWACK?)
  • about_Functions - PowerShell documentation. It's a manual sure, but you'd be remiss to pass this one up. I constantly find myself going back there and learning a new thing (or 10)
  • Hey, Scripting Guy! blog - This blog is a goldmine of information for anyone new to PowerShell. While not always the most detailed, I can usually use the knowledge here as a starting point to get into the "Google-Rabbit Hole" of blogs and how-to's that surround the inter-webs.
  • Learn Windows PowerShell in a Month of Lunches - This seminal book has been a foundation of new beginnings into PowerShell, but some of us are a bit more visual learners. Luckily, Don Jones has us covered in video form as well!

 

THE PROBLEM:

Manually adding all of your custom properties back in after a net-new installation, manipulating thousands of records via automation, or even simply expanding your comfort level into scripting. All are valid reasons to get "hooked" (yeah, I went there) into the SolarWinds Orion API. In this session, I presented a small script that outlines some foundational concepts of API usage via PowerShell, as well as provides what I hope will become a real-world use-case for you!

More specifically, I am presenting a script that uses PowerShell functions to do the following:

  • Connect to the SolarWinds Information Services (SWIS)
  • Create a new Custom Property
  • Update the value of a Custom Property for an object

 

CHOICE OF LANGUAGE:

While the very essence of a REST API is surrounded by the beauty of being language-agnostic, at some point everyone has to choose a language. (at least per script) For ease of presentation, I decided to use PowerShell as it's Windows-native (just like the Orion platform), and has a LARGE amount of support for both the Orion Module, and modules that allow you to easily interact with a lot of other systems. (SQL Databases, Microsoft Excel, Amazon Web Services, Azure, etc.) The idea being that you may use posts like these to self-start into a journey of further discovery, and starting in a more complex language that has less built-in support and may require compilation can be daunting for your first jump into the pool. Enter PowerShell: No Muss, No Fuss.

 

AUTOMATE ALL THE THINGS:

I've been known to say time and again that the absolute best admins I have ever worked with in IT are L-A-Z-Y. IM(not so)HO, it is a waste of time/energy/resources to do anything manually that you can do with a script. There's always exceptions to the rule of course, but I cannot stress how much more effective my team is due to automation scripts. We have a team of 3 engineers handling the work of (from jbiggley's estimates) 15. That's in no small part directly attributed to our ability to utilize almost any platform's API to handle the mundane "Click Here, Enter Text, Next, Next, Submit" tasks that we all face every day in IT.

I could spend a lifetime posting articles and reasons to adopt scripting into your world, but I instead will challenge you to find one thing. Find one single task that you repeat more than 3 times per week. No matter what it is, try and create a script for it. Even if the end result is that you save yourself 5 minutes per task; that's 15 minutes per week; which is 13 hours annually that you can use to script other things, which then opens up more time to script even more things... Ever heard of compound interest? Let's apply that to life.

 

SCRIPT SUMMARY:

OK, so what we're doing with this script is basically outlined as such:

  • Create 3 functions for each of our tasks
  • Execute those functions

 

Sounds simple? Well, it somewhat is, but when I first started it seemed like I was trying to read and write sanskrit, and not even in one of the common dialects! Trust me that with time (and Google) it gets easier. Plus, you a member of the BEST ONLINE COMMUNITY OF IT PROFESSIONALS IN THE WORLD!!! If you can't find the answer on THWACK, it simply doesn't exist.

 

You may end up asking yourself, "But Zack, why are you making functions to do something so simple? I mean you've even thrown up the Wiki entry that shows precisely how to do all this, no functions necessary!" Well, the answer is twofold. First, I wanted to show you a small sample of how functions can create a great deal of manageability in a script as you can reduce the amount of times you need to enter the same syntax. Second, functions are, in their own way, a process of automating your script writing. #Scriptception

 

To be fair, I should REALLY find the time to take the 50-something Orion SDK functions I have built in my personal stores and roll them into something pretty like the PowerOrion module. That takes you even deeper into automation-vana by allowing you to call all of your "functions" (cmdlets in a module) with a single line at the top of your script. It's the golden snitch of the PowerShell scripter's world.

 

THE BACON BITS:

The most important parts of this script are within the functions themselves. You can find the full text of the script below, full of comments and tidbits of help.

  • Set-SwisConnection (Lines 30 and 269)
  • New-CustomProperty (Lines 62 and 272)
    • This creates a new custom property for either NPM or SAM. This could easily be expanded to any other module, I was sticking with these for simplicity.
  • Set-CustomPropertyValue (Lines 119 and 274)
    • This will update/set the value of an existing custom property for a target object (Node, Application Monitor, etc.)

 

THE SCRIPT:

#region Top of Script

#requires -version 2
<#
.SYNOPSIS     Examples of Functions to Create and Update Custom Properties via Orion SDK

.DESCRIPTION 
    https://github.com/solarwinds/OrionSDK/wiki/Managing-Custom-Properties

.NOTES
    Version:        1.0    Author:         Zack Mutchler    Creation Date:  March 21, 2018    Purpose/Change: Initial Script development.    Version:        1.1    Author:         Zack Mutchler    Creation Date:  May 28, 2018    Purpose/Change: Added Set-CustomPropertyValue Function
#>

#endregion

#####-----------------------------------------------------------------------------------------#####

#region Functions

# Create a function to connect to the SolarWinds Information Service (SWIS)
Function Set-SwisConnection {
        [ cmdletbinding() ]    Param(        [ Parameter( Mandatory = $true, HelpMessage = "What SolarWinds server are you connecting to (Hostname or IP)?" ) ] [ string ] $SolarWindsServer,        [ Parameter( Mandatory = $true, HelpMessage = "Do you want to use the credentials from PowerShell (Trusted), or a new login (Explicit)?" ) ] [ ValidateSet( 'Trusted', 'Explicit' ) ] [ string ] $ConnectionType    )    # Import the SolarWinds PowerShell Module    Import-Module SwisPowerShell    # Connect to SWIS    IF ( $ConnectionType -eq 'Trusted'  ) {        $swis = Connect-Swis -Trusted -Hostname $SolarWindsServer        }    ELSE {            $creds = Get-Credential -Message "Please provide a Domain or Local Login for SolarWinds"        $swis = Connect-Swis -Credential $creds -Hostname $SolarWindsServer    }

RETURN $swis

}

# Create a function to create a new Custom Property
Function New-CustomProperty {
        [ cmdletbinding() ]    Param(        [ Parameter( Mandatory = $true, HelpMessage = "Value from the Set-SwisConnection Function" ) ] [ object ] $SwisConnection,        [ Parameter( Mandatory = $true, HelpMessage = "What Object Type is this custom property for?" ) ] [ ValidateSet( 'Alerts', 'Applications', 'Groups', 'Interfaces', 'Nodes', 'Reports', 'Volumes' ) ] [ string ] $PropertyType,        [ Parameter( Mandatory = $true, HelpMessage = "What name would you like to give this custom property?" ) ] [ string[] ] $PropertyName,        [ Parameter( Mandatory = $true, HelpMessage = "What description would you like to give this custom property?" ) ] [ string ] $Description,        [ Parameter( Mandatory = $true, HelpMessage = "What data type should be used?" ) ] [ ValidateSet( 'string', 'integer', 'datetime', 'single', 'double', 'boolean' ) ] [ string ] $ValueType,        [ Parameter( Mandatory = $false, HelpMessage = "OPTIONAL: What is the maximum size, if using a 'string' data type? (Max 4000)" ) ] [ ValidateRange( 0,4000 ) ] [ int ] $Size,        [ Parameter( Mandatory = $false, HelpMessage = "OPTIONAL: What values would you like to set for the drop down?" ) ] [ string[] ] $DropDown    )

# Example: New-CustomProperty -SwisConnection $swis -PropertyType "string" -PropertyName "array" -Description "string" -ValueType "string" -Size "optional integer" -DropDown "optional array" -Mandatory <adding this argument = $true> -Default "optional string"        # Set the Custom Property Usages to all available options so you're not limited    # IsForEntityDetail is required to utilize new popover options in Orion Platform 2018.2 (https://thwack.solarwinds.com/docs/DOC-194255)    $Usages = @{ 'IsForAlerting' = $true; 'IsForAssetInventory' = $true; 'IsForEntityDetail' = $true; 'IsForFiltering' = $true; 'IsForGrouping' = $true; 'IsForReporting' = $true }    # Set the Entity Object to be used to create your Custom Property    # Note these options are going to be based on the SolarWinds modules you have installed    # The below options reflect NPM and SAM        If( $PropertyType -eq "Alerts" ) {            $Entity = "Orion.AlertConfigurationsCustomProperties"        }        If( $PropertyType -eq "Applications" ) {            $Entity = "Orion.APM.ApplicationCustomProperties"        }        If( $PropertyType -eq "Groups" ) {            $Entity = "Orion.GroupCustomProperties"        }        If( $PropertyType -eq "Interfaces" ) {            $Entity = "Orion.NPM.InterfacesCustomProperties"        }        If( $PropertyType -eq "Nodes" ) {            $Entity = "Orion.NodesCustomProperties"        }        If( $PropertyType -eq "Reports" ) {            $Entity = "Orion.ReportsCustomProperties"        }        If( $PropertyType -eq "Volumes" ) {            $Entity = "Orion.VolumesCustomProperties"        }    # Create the new custom properties    Foreach( $n in $PropertyName ) {        Invoke-SwisVerb $SwisConnection $Entity CreateCustomPropertyWithValues @( $n, $Description, $ValueType, $Size, $null, $null, $null, $null, $null, $null, $DropDown, $Usages )        Write-Host "Creating Custom Property: $( $n ) for Entity Type: $( $Entity )" -ForegroundColor Yellow    }
}

# Create a function to modify/set object values on existing Custom Property
# https://github.com/solarwinds/OrionSDK/blob/master/Samples/PowerShell/CRUD.SettingCustomProperty.ps1
# This could be enhanced in several ways, most notably by using Dynamic Parameters for the ID and Value entries based on the $NodeCP parameter
Function Set-CustomPropertyValue {

    [ cmdletbinding() ]    Param (        [ Parameter( Mandatory = $true, HelpMessage = "Value from the Set-SwisConnection Function" ) ] [ object ] $SwisConnection,        [ Parameter( Mandatory = $true, HelpMessage = "Primary Polling Engine Name" ) ] [ string ] $PrimaryPoller,        [ Parameter( Mandatory = $true, HelpMessage = "Custom Property Name" ) ] [ string ] $CustomProperty,        [ Parameter( Mandatory = $true, HelpMessage = "Is this a NODE Custom Property?" ) ] [boolean] $NodeCP,        [ Parameter( HelpMessage = "NodeID for Custom Property assignment, REQUIRED for Nodes/Applications/Interfaces/Volumes" ) ] [ int ] $NodeID,        [ Parameter( ParameterSetName = 'AlertID' ) ] [ int ] $AlertID,        [ Parameter( ParameterSetName = 'ReportID' ) ] [ int ] $ReportID,        [ Parameter( ParameterSetName = 'ApplicationID' ) ] [ int ] $ApplicationID,        [ Parameter( ParameterSetName = 'InterfaceID' ) ] [ int ] $InterfaceID,        [ Parameter( ParameterSetName = 'VolumeID' ) ] [ int ] $VolumeID,        [ Parameter( ParameterSetName = 'StringValue' ) ] [ string ] $StringValue,        [ Parameter( ParameterSetName = 'IntegerValue' ) ] [ int ] $IntegerValue,        [ Parameter( ParameterSetName = 'DateTimeValue' ) ] [ datetime ] $DateTimeValue,        [ Parameter( ParameterSetName = 'SingleValue' ) ] [ single ] $SingleValue, #Float with 7 digits of precision        [ Parameter( ParameterSetName = 'DoubleValue' ) ] [ double ] $DoubleValue, #Float with 15-16 digits of precision        [ Parameter( ParameterSetName = 'BooleanValue' ) ] [ boolean ] $BooleanValue # $true|$false    )<# Examples:    Node CP: Set-CustomPropertyValue -SwisConnection $swis -PrimaryPoller <> -CustomProperty <> -NodeCP $true -NodeID <> [ $StringValue|$IntegerValue|$DateTimeValue|$SingleValue|$DoubleValue|$BooleanValue ]    Alert CP: Set-CustomPropertyValue -SwisConnection $swis -PrimaryPoller <> -CustomProperty <> -NodeCP $false -AlertID <> [ $StringValue|$IntegerValue|$DateTimeValue|$SingleValue|$DoubleValue|$BooleanValue ]     Report CP: Set-CustomPropertyValue -SwisConnection $swis -PrimaryPoller <> -CustomProperty <> -NodeCP $false -ReportID <> [ $StringValue|$IntegerValue|$DateTimeValue|$SingleValue|$DoubleValue|$BooleanValue ]    Application CP: Set-CustomPropertyValue -SwisConnection $swis -PrimaryPoller <> -CustomProperty <> -NodeCP $false -NodeID <> -ApplicationID <> [ $StringValue|$IntegerValue|$DateTimeValue|$SingleValue|$DoubleValue|$BooleanValue ]    Interface CP: Set-CustomPropertyValue -SwisConnection $swis -PrimaryPoller <> -CustomProperty <> -NodeCP $false -NodeID <> -InterfaceID <> [ $StringValue|$IntegerValue|$DateTimeValue|$SingleValue|$DoubleValue|$BooleanValue ]    Volume CP: Set-CustomPropertyValue -SwisConnection $swis -PrimaryPoller <> -CustomProperty <> -NodeCP $false -NodeID <> -VolumeID <> [ $StringValue|$IntegerValue|$DateTimeValue|$SingleValue|$DoubleValue|$BooleanValue ]
#>

# Set your object URI
If ( $NodeCP -eq $true ) {
    $uri = 'swis://' + $PrimaryPoller + '/Orion/Orion.Nodes/NodeID=' + $NodeID + '/CustomProperties'    Write-Host "Setting URI from Node Custom Property" -ForegroundColor Yellow
}
If ( $NodeCP -eq $false -and $AlertID ) {    $uri = 'swis://' + $PrimaryPoller + 'Orion/Orion.AlertConfigurations/AlertID=' + $AlertID + '/CustomProperties'    Write-Host "Setting URI from Alert Custom Property" -ForegroundColor Yellow
}
If ( $NodeCP -eq $false -and $ReportID ) {    $uri = 'swis://' + $PrimaryPoller + 'Orion/Orion.Report/ReportID=' + $ReportID + '/CustomProperties'    Write-Host "Setting URI from Report Custom Property" -ForegroundColor Yellow
}
If ( $NodeCP -eq $false -and $ApplicationID -and $NodeID ) {    $uri = 'swis://' + $PrimaryPoller + '/Orion/Orion.Nodes/NodeID=' + $NodeID + '/Applications/ApplicationID=' + $ApplicationID + '/CustomProperties'    Write-Host "Setting URI from Application Custom Property" -ForegroundColor Yellow
}
If ( $NodeCP -eq $false -and $InterfaceID -and $NodeID ) {    $uri = 'swis://' + $PrimaryPoller + '/Orion/Orion.Nodes/NodeID=' + $NodeID + '/Interfaces/InterfaceID=' + $InterfaceID + '/CustomProperties'    Write-Host "Setting URI from Interface Custom Property" -ForegroundColor Yellow
}
If ( $NodeCP -eq $false -and $VolumeID -and $NodeID ) {    $uri = 'swis://' + $PrimaryPoller + '/Orion/Orion.Nodes/NodeID=' + $NodeID + '/Volumes/VolumeID=' + $VolumeID + '/CustomProperties'    Write-Host "Setting URI from Volume Custom Property" -ForegroundColor Yellow
}
If ( $NodeCP -eq $false -and (!( $NodeID ) ) -and ( $ApplicationID -or $InterfaceID -or $VolumeID ) ) {    Write-Warning "Missing NodeID Parameter for Application, Interface, or Volume Custom Property"
}
If ( $NodeCP -eq $true -and (!( $NodeID ) ) ) {    Write-Warning "Missing NodeID Parameter for Node Custom Property"
}

# Set the Custom Property Value
If ( $StringValue ) {
    $cp = @{        $CustomProperty=$StringValue    }    Write-Host "String Value = $( $cp.Values )" -ForegroundColor Yellow
}
If ( $IntegerValue ) {    $cp = @{        $CustomProperty=$IntegerValue    }    Write-Host "Integer Value = $( $cp.Values )" -ForegroundColor Yellow
}
If ( $DateTimeValue ) {    $cp = @{        $CustomProperty=$DateTimeValue    }    Write-Host "DateTime Value = $( $cp.Values )" -ForegroundColor Yellow
}
If ( $SingleValue ) {    $cp = @{        $CustomProperty=$SingleValue    }    Write-Host "Single Value = $( $cp.Values )" -ForegroundColor Yellow
}
If ( $DoubleValue ) {    $cp = @{        $CustomProperty=$DoubleValue    }    Write-Host "Double Value = $( $cp.Values )" -ForegroundColor Yellow
}
If ( $BooleanValue ) {    $cp = @{        $CustomProperty=$BooleanValue    }    Write-Host "Boolean Value = $( $cp.Values )" -ForegroundColor Yellow
}

# Set the Custom Property Value
Write-Host "Setting Custom Property '$( $CustomProperty )':`n    $( $uri )`n    $( $cp.Keys )`n    $( $cp.Values )" -ForegroundColor Yellow

Set-SwisObject -SwisConnection $SwisConnection -Uri $uri -Properties $cp 

}

#endregion Functions


#####-----------------------------------------------------------------------------------------#####

#region Variables

# Set the SolarWinds server to connect to
$hostname = Read-Host -Prompt "Which SolarWinds server would you like to connect to?"

# Create a Name for the Custom Properties you want to create
$nodeCP = 'dark_theme_is_life'

# CP Description
$description = 'Should this object be presented in a glorious #DarkTheme?'

# CP Value Type
$valueType = 'string'

# CP String Size (ignored for non-string Value Types)
$size = 4000

# CP Drop Down Values
$dropDown = New-Object string[] 4
    $dropDown[0] = 'Go Sign Up for a UX session!'    $dropDown[1] = 'http://thwack.ux-group.sgizmo.com/s3/'    $dropDown[2] = 'Dark Theme All The Things'    $dropDown[3] = 'Kevin made me use 4 options...'

# Target NodeID
$nodeID = 10

$nodeCPString = 'Dark Theme All The Things'

#endregion Variables

#####-----------------------------------------------------------------------------------------#####

#region Execution

# Connect to SWIS
$swis = Set-SwisConnection -SolarWindsServer $hostname -ConnectionType Explicit

# Example: New-CustomProperty
New-CustomProperty -SwisConnection $swis -PropertyType Nodes -PropertyName $nodeCP -Description $description -ValueType string -Size $size -DropDown $dropDown

#Example: Set-CustomPropertyValue
Set-CustomPropertyValue -SwisConnection $swis -PrimaryPoller $hostname -CustomProperty $nodeCP -NodeCP $true -NodeID $nodeID -StringValue $nodeCPString

#endregion Execution

 

 

Enjoy, and have fun challenging yourselves! If you have any questions about this, or any other scripts, please feel free to ask! Happy Thwacking!

 

ZackM

 

#DarkThemeIsLife

 

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.

Not able to connect Orion Server using SWQL

$
0
0

Hi

Anyone experience this issue. I always able to connect Orion server from this Polling Engine but right now i can not. There is no change in configuration on Polling Engine but Orion Server recently moved to new VM environment.

I checked the same thing from other polling engine, i can connect successfully. Not sure how to trace out the issue for this specific polling engine. Polling engine is running on Windows 2012 R2 standard.

 

SWQL version : 2.3.0.123

Orion Server: 2017.3.5

 

 

/msarkar

SWIS connection problem - part 2

$
0
0

1)We have 2 Solarwinds silos.  With one silo we are able to connect and run queries with accounts that have read access to Solarwinds.

 

$swis = Connect-Swis -Hostname silo1

Get-SwisData -SwisConnection $swis -Query 'SELECT DNS FROM Orion.Nodes'

 

 

2)With silo 2, we get an error message.  We can only run queries that have Admin in the Solarwinds console and that are in the administrative group on primary application server.  We get this error message:

 

$swis = Connect-Swis -Hostname silo2

Get-SwisData -SwisConnection $swis -Query 'SELECT DNS FROM Orion.Nodes'

 

PS C:\Users\wh24xu> C:\Powershell\SWIS\SWIS-get-node-names-ATC.ps1

cmdlet Connect-Swis at command pipeline position 1

Supply values for the following parameters:

(Type !? for Help.)

Get-SwisData : An error occurred when verifying security for the message.

At C:\Powershell\SWIS\SWIS-get-node-names-ATC.ps1:2 char:1

+ Get-SwisData -SwisConnection $swis -Query 'SELECT DNS FROM Orion.Node ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [Get-SwisData], MessageSecurityException

    + FullyQualifiedErrorId : SwisError,SwisPowerShell.GetSwisData

 

 

We opened a support case, but they do not support troubleshooting these problems.  I am thinking there is some type of permission we need to set on silo 2's application/primary poller.  I'm just not sure what security setting we need to set.  I get this error if I use an account that has admin in the Solarwinds console, but does not have admin on the app server.  We need to provide accounts with read access the ability to run SWIS queries.

 

Thanks in advance.

 


Add UDT ports via API

$
0
0

I have not found a way to do this, but maybe I'm not looking in the right place. We've got Python scripts for discovering and adding nodes and interfaces via API no problem. We're using corePluginConfig  and  interfacesPluginConfig to accomplish this. But I have not seen a similar "ports" PluginConfig (i.e. portsPluginConfig). When we started down the road of automating device entry, we assumed UDT ports would also be available to us via API. Like when we import discovered results in the web console, the Interfaces screen (with all of its selection criteria and filtering) is followed by an almost identical Ports screen. So it seemed safe to assume we would be able to include UDT ports when automating device entry via API.

 

Hopefully I'm just missing something and the option to do this is available.

 

Thanks!

Changing a Performance Counter Instance Name, Overriding a Template

$
0
0

Hey all,

 

I currently have a template that is applied to multiple servers to collect windows performance counter information for some custom software.  The issue is, the instance names changes on a server, and there can be more than one instance of the counters on each server (each with a unique name).  I'm looking for a way to override the template's instance name setting and update each individual component's Instance.  Alternatively, I suppose I could use PowerShell to retrieve which counters and instances exist on each server (Already have the ability to obtain that information via script) and then hopefully use Invoke-SwisVerb to create individual templates, applications and components - but I'm not sure where to start with scripting the creation of solarwinds portion.

 

From enacting the change manually via the web console and then running a SWQL query, I can see that the overriding setting is held in Orion.APM.ComponentSetting with a Key of "Instance" and a "Value" of the instance name I entered (Along with ComponentID for the individual component of the application, as well as ValueType = 0 and Required = False)

 

I'm not finding any Swis Verbs to invoke in order to update a specific component like this - does anyone have any guidance?

 

I know the above is rather vague - if I can provide more information to facilitate a solution, please let me know.

Python SDK Set Dynamic Thresholds

$
0
0

Good afternoon,

I am wondering if it is currently possible to set interfaces to use dynamic thresholds for RX and TX utilization and discards/errors using the Python SDK? (or Powershell if the Python is not supported).

 

My immediate need is to select, out of ~15k interfaces, ones which I would like to set the &{USE_BASELINE*} macro and set it. I have found that the SDK is ideal for this type of task.

 

Ideally, I would also like to be able to use the same method for CPU Load, Percent Memory Used, Response Time, and Percent Loss on Nodes as well and even Percent Disk Usage on Volumes.

 

Tangentially, does anyone know if it is possible to set an interface to go into warning/critical if the % utilization is either greater than or less than x times the standard deviation? Effectively alerting on the change? (I attempted to do this within an alert, but no luck)

 

 

Thank you!

Timeout When Invoking AddInterfacesOnNode

$
0
0

Greetings Thwack,

 

I have been working on using the SDK to automatically add relevant interfaces to monitoring. Since the lite discovery is missing a lot of data I need to make decisions on what interfaces I want to monitor, I've been leveraging the results of my weekly NCM inventory to add interfaces which meet the necessary criteria. This has been working great, but on some nodes I'm encountering a timeout when invoking AddInterfacesOnNode. Despite the fact that I'm not invoking DiscoverInterfacesOnNode, the AddInterfacesOnNode verb seems to still run a discovery before adding the interfaces.

 

The nodes I'm having issues with are expected to take between 8 and 10 minutes to complete discovery because of the number of interfaces that exist (nearly 5000 per device). I followed along with the troubleshooting in this thread (Discover Interfaces on node (powershell and curl) ) and was not able to get the timeout to increase. To be specific, I increased the timeouts in C:\Program Files (x86)\SolarWinds\Orion\NPM\SolarWinds.NPM.BusinessLayer.dll.config for "NPM.NetTcpBinding" to 15 minutes, and {ORION_INSTALL_PATH}\SolarWinds\Orion\Information Service\3.0\Plugins\SolarWinds.Data.Providers.NPM.v3.dll.config for "DiscoverTimeout" also to 15 minutes.

 

The information service log file shows the following when the AddInterfacesOnNode verb times out:

 

2018-10-04 16:31:29,217 [96] WARN  SolarWinds.InformationService.Core.InformationService - (null) (null)  Support! -- LONG RUNNING QUERY: OperationContextId e28970b5-35c5-49fb-83ad-13587a3a0808 - Query took 300093.2922 ms: Verb Orion.NPM.Interfaces.AddInterfacesOnNode

 

If I invoke AddInterfacesOnNode against one of the problem nodes using SWQL Studio, I receive the following error:

 

 

<Return z:Id="1" xmlns="http://schemas.datacontract.org/2004/07/SolarWinds.InformationService.Contract" xmlns:d1p1="http://schemas.solarwinds.com/2008/NPM" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"> <d1p1:DiscoveredInterfaces i:nil="true" /><d1p1:Result>GenericError</d1p1:Result></Return>

 

Any assistance you can offer would be greatly appreciated. Thanks!

Unable to restart service on the node using SWQL Studio

$
0
0

Hello All.

When trying to restart Windows service using SWQL using Orion.APM.ServerManagement.RestartService getting the following error (provided correct nodeID, credentialId, serviceName):

-<Faultxmlns="http://www.w3.org/2003/05/soap-envelope">

 

 

-<Code>

 

 

<Value>Sender</Value>

 

</Code>

 

-<Reason>

 

 

<Textxml:lang="en-US">Orion.APM.ServerManagement.RestartService failed, check fault information. Specified argument was out of the range of valid values. Parameter name: id</Text>

 

</Reason>

 

-<Detail>

 

 

-<InformationServiceFaultContractxmlns:i="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://schemas.solarwinds.com/2007/08/informationservice">

 

 

<Message>Specified argument was out of the range of valid values. Parameter name: id</Message>

 

</InformationServiceFaultContract>

</Detail>

</Fault>

 

Looks like error message from completely different area, Orion does not understand valid ID of WMI Credentials of type "System.Int32", and very much looks like a bug...

Is anyone experienced it and is there any workaround?

Viewing all 2677 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>