The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Net::SolarWinds::CookBook - General User Documentation

DESCRIPTION

This is a general go to guide on how to use the Net::SolarWinds modules. Most of the heavy lifting is done by the Net::SolarWinds::REST::Batch module.

HowTo(s)

  • How to manage Objects

    The v3 broker service manages objects via individual 'URL'. Often times an object will contain a url field when it is returned. The Url field can most of the time be used to update the object or make changes to it.

    Example

    use Net::SolarWinds::REST::Batch;
    
    my $rest=new Net::SolarWinds::REST::Batch;
    
    # Read Mode: $result->get_data contains the details of the node
    my $result=$rest->UpdateUri('swis://localhost/Orion/Orion.Nodes/NodeID=16956');
    
    # Write mode: Update the caption:
    my $result=$rest->UpdateUri('swis://localhost/Orion/Orion.Nodes/NodeID=16956',{Caption=>'NewCaption'});
    
    # Bulk Update example:
    my $result=$self->BulkUpdate({
      uris=>[
        "swis://dev-che-mjag-01./Orion/Orion.Nodes/NodeID=4/Volumes/VolumeID=1",
        "swis://dev-che-mjag-01./Orion/Orion.Nodes/NodeID=4/Volumes/VolumeID=2",
        "swis://dev-che-mjag-01./Orion/Orion.Nodes/NodeID=4/Volumes/VolumeID=3"
      ],
      properties=>{
        "NextPoll"=>"7/1/2014 9:06:19 AM",
        "NextRediscovery"=>"7/1/2014 2:59:09 PM"
      }
    });
    
    # delete can be handled via the BulkDelete Interfaces
    my $result=$self->BulkDelete({
      uris=>[
        "swis://dev-che-mjag-01./Orion/Orion.Nodes/NodeID=4/Volumes/VolumeID=1",
        "swis://dev-che-mjag-01./Orion/Orion.Nodes/NodeID=4/Volumes/VolumeID=2",
        "swis://dev-che-mjag-01./Orion/Orion.Nodes/NodeID=4/Volumes/VolumeID=3"
      ]
    });
  • How to enable logging

    use Net::SolarWinds::REST::Batch;
    use Net::SolarWinds::Log;
    
    my $log=new Net::SolarWinds::Log('/var/log/script.log');
    my $rest=new Net::SolarWinds::REST::Batch(log=>$log);
    
    # To change the log level to warn
    $log->set_loglevel($log->LOG_WARN);
    
    # To change the log level to error
    $log->set_loglevel($log->LOG_ERROR);
    
    # To change the log level to DEBUG
    # this will dump out actual raw http requests
    $log->set_loglevel($log->LOG_DEBUG);
  • How to find a node

    use Net::SolarWinds::REST::Batch;
    use Data::Dumper;
    
    my $rest=new Net::SolarWinds::REST::Batch;
    
    # use the hostname method
    my $result=$rest->get_node("hostname");
    if($result) {
      my $data=$result->get_data;
      print Dumper($data);
    } else {
      print "Error Fetching: hostname, error was: $result\n";
    }
    
    # use the id method method
    my $result=$rest->get_node(212);
    if($result) {
      my $data=$result->get_data;
      print Dumper($data);
    } else {
      print "Error Fetching node by id: 212, error was: $result\n";
    }
    
    # use the ip address method
    my $result=$rest->get_node("192.168.1.74");
    if($result) {
      my $data=$result->get_data;
      print Dumper($data);
    } else {
      print "Error Fetching: 192.168.1.74, error was: $result\n";
    }
  • Adding an interface

    To add an interface, you will need to do a number of things. 1. Get the NodeID, 2. Poll the interfaces on the device, 3. Add the interface. Note: The pollers added by SolarWinds are inconsistent, you may want to audit and add any missing pollers.

    So here is how to add an interface

      use Net::SolarWinds::REST::Batch;
      use Net::SolarWinds::Log;
    
      # its always best to enable logging!
      my $log=new Net::SolarWinds::Log('/var/log/script.log');
      my $rest=new Net::SolarWinds::REST::Batch(log=>$log);
    
      # Node id
      my $nodeid=212;
    
      # fetch our best guess when it comes to default poller maps
      my $pm={};
      if(my $result=$rest->getPollerInterfaceMap($nodeid)) {
        $pm=$result->get_data;
      } else {
        $log->log_warn("Failed to get poller map for $nodeid");
      }
    
      # discover the interfaces
      my $result=$rest->DiscoverInterfacesOnNode($nodeid);
      my $ifname='eth0';
      
      if($result) {
        foreach my $int (@{$result->get_data->{DiscoveredInterfaces}}) {
    
          # never try to add an interface that all ready exists!
          next if $int->{InterfaceID}!=0;
    
          next unless $int->{Manageable};
    
          # The actual name may never be literal, so we fix that here
          my $caption=$int->{Caption};
          # clean up the returned data
          $caption=~ s/\s\x{b7}.*$//s;
          my ($desc,$ifname)=split /\s-\s/,$caption;
          my $matched;
    
          # one of the above strings will contain our literal interface name
          foreach my $string ($caption,$desc,$ifname) {
            next unless defined($string);
    	if($string eq $ifname) {
    	  $matched=$string;
    	  last;
    	}
          }
    
          next unless defined($matched);
          my $result=$rest->NodeInterfaceAddDefaultPollers($nodeid,[$int]);
          if($result) {
            my $intid=$result->get_data->{DiscoveredInterfaces}->[0]->{InterfaceID};
    	my $result=$rest->NodeInterfaceCustomProperties($nodeid,$intid,{Some=>"Custom Property"});
    	$log->log_error("Failed to set custom property for $ifname") unless $result;
    
    	# now we add any pollers that were missed by default
    
    	# fetch the interface map
    	my $result=$result=$rest->get_poller_map($intid,'I');
    	my $map=$result->get_data;
    
    	if(exists $pm->{$int->{ifType}}) {
    	  my $list=$pm->{$int->{ifType}};
    	  foreach my $poller (@{$list}) {
    	    next if exists $map->{$poller};
    	    my $result=$rest->add_poller($intid,'I',$poller);
    	    $log->log_error("Failed to add $poller to interface: $intid error was $result") unless $result;
    	  }
    	}
          } else {
            $log->log_error("Failed to add $ifname error was: $result");
          }
        }
      }
  • Adding a node based on on existing node

    The Net::SolarWinds::REST::Batch module offers a very high level interface that allows for reverse engineering existing node configurations: pollers, file systems, templates, interfaces, etc. These reverse engired templates can be used to build new device configurations.

    The process itself is broken out into 4 steps. 1. Clone the config, 2. Save the config to a file, 3. Edit the options for the new node, 4. Create the new node.

    use Storable qw(dclone store retrieve);
    use Net::SolarWinds::REST::Batch;
    
    my $rest=new Net::SolarWinds::REST::Batch();
    
    my $node='192.168.1.182';
    
    
    my $config;
    my $config_file='config.storable';
    
    # cache the config on disk( save it any way you want )
    if(-e $config_file) {
      $config=retrieve($config_file);
    } else {
      my $result=$rest->get_management_config($node);
      die "Could not get config for: $node error was: $result" unless $result;
      $config=$result->get_data;
      store $config,$config_file;
    }
    
    # get a copy of our config ( in case we want to apply this to multiple nodes and change more things! )
    my $new_config=dclone($config);
    
    # adjust your config here
    # depending on the version of NPM you may need to delete some of the node columns
    delete @{$new_config->{"node"}}{qw(EngineID Caption)};
    
    $new_config->{"node"}->{"IPAddress"}="192.168.101.38";
    $new_config->{"node"}->{"Caption"}="192.168.101.38";
    
    # now we create our new node!
    my $result=$rest->manage_node($new_config);

AUTHOR

Michael Shipper