1 Reply Latest reply on Mar 17, 2016 4:13 PM by azabielski Branched from an earlier discussion.

    Triggering discovery of SNMPV2 device through JSON API

    kvesterling

      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.

      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--

        • Re: Triggering discovery of SNMPV2 device through JSON API
          azabielski

          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);

                      }

                  }