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.

Triggering discovery of SNMPV2 device through JSON API

FormerMember
FormerMember

Folks;

Triggering discovery of SNMPV2 device through JSON API:

Hats off to tdanner for this, I've modified it to suit my needs, and verified that it works.emoticons_happy.png

You will need to make your own modifications as necessary.

Be advised it returns right away, and the only way to tell if the discovery worked is to query for the node some time later (not sure how much later), and if the node does not exist, then clearly discovery did not work.   For now, rinse and repeat as necessary with your own iterative process...

Testing:

I have verified this works with a single IP, but I have not tested whether or not it works with a network range.

Perl 5.10 on Redhat 6.5  and 5.18.2 for OSX Yosemite test just fine.

Disclaimer:

No warranty expressed or implied.  Use at your own risk. Your mileage may vary. Fasten Seat Belts. Objects in code may be larger than they appear. Use in a well ventilated area of over 1,000 square meters. Should code ignite, treat it as one would burning metals.


--begin code--

sub orion_DiscoverSNMPv2Device() {

  my ($self,$ManagementIP,$Region,$snmpCommunityString,$engineID) = @_;

  #my $ManagementIP = $self->get_RemedyManagementIP($self->{RemedyDevice});

  my @Results = ();

  if ( $ipAddress ne "" ) {

    my $SWQuery = sprintf("select NodeID, NodeName, IPAddress from Orion.Nodes where NodeName = '%s' OR NodeName like '%s.%%';", $self->{RemedyDevice}->{raw}->{DeviceName},$self->{RemedyDevice}->{raw}->{DeviceName});

    my @Results = $self->orion_Query($SWQuery,$self->{engineconfig}->{OrionConfig}->{"$Region"});

    my $NodeID = undef;

    if ( @Results == 0 ) {

    printf("We do not have this node within solar winds... I shall add it for you.\n");

    if ( $engineID eq "" ) {

  $engineID = 1;

    }

    if ($snmpCommunityString eq "") {

  $snmpCommunityString = $self->{RemedyDevice}->{normalized}->{ROv2SNMPCommunityString};

    }

   

    my $discoveryProfileXml = <<"END";

<PluginItems xmlns="http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Discovery">

  <knownTypes>

  <ArrayOfstring xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

  <string>SolarWinds.Orion.Core.Models.Discovery.CoreDiscoveryPluginConfiguration,SolarWinds.Orion.Core.Models</string>

  </ArrayOfstring>

  </knownTypes>

  <pluginItem>

  <ArrayOfDiscoveryPluginConfigurationBase xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

  <DiscoveryPluginConfigurationBase i:type="d2p1:CoreDiscoveryPluginConfiguration" xmlns:d2p1="http://schemas.solarwinds.com/2008/Orion">

  <d2p1:AddressRange/>

  <d2p1:AgentsAddresses xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>

  <d2p1:BulkList xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">

  <d3p1:string>$ipAddress</d3p1:string>

  </d2p1:BulkList>

  <d2p1:Credentials>

  <d2p1:credentials>

  <knownTypes>

  <ArrayOfstring xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">

  <string>SolarWinds.Orion.Core.Models.Credentials.SnmpCredentialsV2,SolarWinds.Orion.Core.Models</string>

  </ArrayOfstring>

  </knownTypes>

  <pluginItem>

  <d2p1:ArrayOfCredential>

  <d2p1:Credential i:type="d2p1:SnmpCredentialsV2">

  <d2p1:Description i:nil="true"/>

  <d2p1:ID i:nil="true"/>

  <d2p1:IsBroken>false</d2p1:IsBroken>

  <d2p1:Name>mud</d2p1:Name>

  <d2p1:Owner i:nil="true"/>

  <d2p1:Community>$snmpCommunityString</d2p1:Community>

  </d2p1:Credential>

  </d2p1:ArrayOfCredential>

  </pluginItem>

  </d2p1:credentials>

  </d2p1:Credentials>

  <d2p1:DiscoverAgentNodes>false</d2p1:DiscoverAgentNodes>

  <d2p1:SharedCredentials xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>

  <d2p1:SubnetList/>

  <d2p1:WmiRetries>1</d2p1:WmiRetries>

  <d2p1:WmiRetryInterval>PT10S</d2p1:WmiRetryInterval>

  </DiscoveryPluginConfigurationBase>

  </ArrayOfDiscoveryPluginConfigurationBase>

  </pluginItem>

</PluginItems>

END

    my @pluginConfigurationItems = ({ PluginConfigurationItem => "$discoveryProfileXml" });

   

    my %startDiscoveryConfiguration = (

    Name => 'json discovery test' ,

    EngineID => $engineID,

    JobTimeoutSeconds => 3600,

    SearchTimeoutMiliseconds => 2000,

    SnmpTimeoutMiliseconds => 3000,

  SnmpRetries => 1,

  RepeatIntervalMiliseconds => 1800,

  SnmpPort => 161,

  HopCount => 0,

  PreferredSnmpVersion => 'SNMP2c',

  DisableIcmp => 0,

  AllowDuplicateNodes => 0,

  IsAutoImport => 1,

  IsHidden => 1,

  PluginConfigurations => \@pluginConfigurationItems

    );

   

    my @verbArguments = (\%startDiscoveryConfiguration);

    my $SWServer = $self->{engineconfig}->{OrionConfig}->{"$Region"};

    my $swhostname = $SWServer->{OrionServer}; # fill in a hostname

    my $swport = $SWServer->{JSONPort};

    my $swprotocol = $SWServer->{Protocol};

    my $SWCredentials = $self->get_credentials($SWServer->{CredentialSetName});

    my $username = $SWCredentials->{username};

    my $password = $self->decrypt_password($SWCredentials->{password});

   

    my $uri = "https://$swhostname:$swport/SolarWinds/InformationService/v3/Json/Invoke/Orion.Discovery/StartDiscovery";

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

    $rest->getUseragent()->proxy(['https']);

    $rest->getUseragent()->ssl_opts(verify_hostname => 0);

    my $headers = {

  Authorization => 'Basic ' . MIME::Base64::encode_base64($username . ':' . $password),

  'Content-Type' => 'application/json'

    };

    my $json = JSON->new->allow_nonref->utf8;

    my $json_text = $json->space_after->encode(\@verbArguments);

   

    #print "$json_text\n";

    my $response = $rest->POST($uri, $json_text, $headers);

    return($response);

    #sleep(1);

    }

  } else {

    return(undef);

  }

}

--end code--

  • Here is a nice way to do it via C# if interested as well I took a different approach and waited for the node to complete and get the swis url then update the node.

           public HttpResponseMessage Post([FromBody]NodeInfo info)

            {

                 CustomNodeInfo cnInfo = new CustomNodeInfo();

                #region Hard Coded Values

                info.EngineID = 1;

                cnInfo.Custom1= "Stuff";

                cnInfo.Custom2= "MoreStuff";

                cnInfo.Custom3= "EverStuff";

                //End Hard Coded

                #endregion

                info.ObjectSubType = "SNMP";

                info.SNMPVersion = "2";

                info.EntityType = "Orion.Nodes";

                info.DynamicIP = false;

                info.Status = 1;

                info.UnManaged = false;

                info.Allow64BitCounters = false;

                if (ModelState.IsValid)

                {

                    string query = "{\"query\":\"SELECT PropertyValue FROM Orion.EngineProperties WHERE EngineID=@e AND PropertyName='Orion.Standard.Polling'\",\"parameters\":{\"e\":" + info.EngineID + "}}";

                    JObject pollingRate = JObject.Parse(SWJsonCall.Post("Json/Query", query));

                    int curRate = (Int32)pollingRate["results"][0]["PropertyValue"];

                    if (curRate < 85)

                    {

                        #region Start Discovery on New Node

                        var dis = new DiscoveryInfo

                        {

                            Name = "API Add Node " + info.IPAddress,

                            EngineID = info.EngineID,

                            JobTimeoutSeconds = 3600,

                            SearchTimeoutMiliseconds = 5000,

                            SnmpTimeoutMiliseconds = 5000,

                            SnmpRetries = 2,

                            RepeatIntervalMiliseconds = 1800,

                            SnmpPort = 161,

                            HopCount = 0,

                            PreferredSnmpVersion = "SNMP2c",

                            DisableIcmp = false,

                            AllowDuplicateNodes = true,

                            IsAutoImport = true,

                            IsHidden = false,

                        };

                        dis.PluginConfigurations = new List<PluginItems> { new PluginItems { PluginConfigurationItem = DiscoveryProfiles.SNMPv2(info.Community, info.IPAddress) } };

                        DiscoveryInfo[] disArray = new DiscoveryInfo[] { dis };

                        string createDiscovery = SWJsonCall.Post("Json/Invoke/Orion.Discovery/StartDiscovery", JsonConvert.SerializeObject(disArray));

                        #endregion

                        JObject disStatus = null;

                        Stopwatch time = new Stopwatch();

                        time.Start();

                        do

                        {

                            string statusQuery = "{\"query\":\"SELECT Status,StatusDescription FROM Orion.DiscoveryProfiles where ProfileID=@id\",\"parameters\":{\"id\":\"" + createDiscovery + "\"}}";

                            disStatus = JObject.Parse(SWJsonCall.Post("Json/Query", statusQuery));

                            if (time.ElapsedMilliseconds > 120000) return Request.CreateResponse(HttpStatusCode.RequestTimeout, "This has taken over 120 seconds it should not take that long this might be something wrong with the information provided.");

                        } while (disStatus["results"][0]["Status"].ToString() == "0" || disStatus["results"][0]["Status"].ToString() == "1" || !disStatus["results"].HasValues);

                        if (disStatus["results"][0]["Status"].ToString() == "2")

                        {

                            string nodeQuery = "{\"query\":\"SELECT Uri,NodeID FROM Orion.Nodes where IPAddress=@ip AND EngineID=@e\",\"parameters\":{\"ip\":\"" + info.IPAddress + "\", \"e\": " + info.EngineID + "}}";

                            JObject nodeStatus = JObject.Parse(SWJsonCall.Post("Json/Query", nodeQuery));

                            string swisUrl = nodeStatus["results"][0]["Uri"].ToString();

                            string updateProps = SWJsonCall.Post("Json/" + swisUrl + "/CustomProperties", JsonConvert.SerializeObject(cnInfo));

                        }

                        else return Request.CreateResponse(HttpStatusCode.ExpectationFailed, disStatus["results"][0]["StatusDescription"].ToString());

                        return new HttpResponseMessage(HttpStatusCode.Created);

                    }

                    else

                    {

                        return Request.CreateResponse(HttpStatusCode.InternalServerError, "Polling rate at dangerous level " + curRate + "%. Please consult Admins, node NOT added.");

                    }

                }

                else

                {

                    var message = string.Join(" | ", ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage));

                    var execption = string.Join(" | ", ModelState.Values.SelectMany(v => v.Errors).Select(e => e.Exception));

                    return Request.CreateResponse(HttpStatusCode.BadRequest, "Error - " + message + " : " + execption);

                }

            }