[c-nsp] Monitoring Nexus 7000 platform

Lincoln Dale ltd at cisco.com
Sun Aug 16 05:41:43 EDT 2009


On 15/08/2009, at 7:37 AM, Lee wrote:

> On 8/14/09, Lincoln Dale <ltd at cisco.com> wrote:
>
>  .. snip lots of really cool examples ..
>
>> why one would ever touch SNMP willingly after using the above is
>> beyond me. :)
>
> Is there an XML equivalent to the Net-SNMP package?

i'm not aware of any standard perl modules for NetConf, however we  
(Cisco) and other vendors have sample scripts available which  
demonstrate how to make use of Netconf with the CPAN Expect and  
XML::DOM.

most sample scripts turn out to be <50 lines of code, e.g.

	#!/usr/bin/perl
	# netconf/xml sample demonstration script to gather ip arp table
	#  -- ltd at cisco.com  march 2009
	die "usage: $0 (switch) (user) (pass) (vrf)\n" if ($#ARGV != 3);
	($switch,$user,$pass,$vrf) = @ARGV;

	$debug = 1;
	$| = 1;

	use Expect;
	use XML::DOM;
	$Expect::Log_Stdout = 0 if ($debug < 2);

	# ssh to switch with netconf
	my $exp = new Expect();
	$exp->raw_pty(1);
	printf STDERR "logging into switch %s as %s\n",$switch,$user if $debug;
	die "could not spawn ssh: $!\n" if (!$exp->spawn("ssh","-s","-2","-v", 
$user."@".$switch,"xmlagent"));

	# send password and login
	$exp->expect(20,
	        [ qr/Are you sure you want /,
	          sub { my $self = shift; $self->send("yes\n");  
exp_continue; }],
	        [ qr/Name or service not known/,
	          sub { die "$switch unknown.\n"; }],
	        [ qr/password: /i,
	          sub { my $self = shift; printf STDERR "sending password\n"  
if $debug;
	                $self->send($pass."\n"); exp_continue; }],
	        [ qr#<session-id>(\d+)</session-id>(.*)#,
	          sub { my $self = shift;
	                printf STDERR "netconf session %d established\n", 
($self->matchlist)[0] if $debug;
	                $self->send(wrap_xml('
	<nc:hello xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
	  <nc:capabilities>
	    <nc:capability>urn:ietf:params:xml:ns:netconf:base:1.0</ 
nc:capability>
	  </nc:capabilities>
	</nc:hello>'));
	                exp_continue; }],
	        [ timeout =>
	          sub { die "could not login\n"; } ],
	        ']]>]]>');

	# collect statistics
	$exp->send(wrap_rpc("urib",'
	<nc:get>
	  <nc:filter type="subtree">
	    <show>
	      <ip>
	        <arp>
	          <vrf><'.$vrf.'/></vrf>
	        </arp>
	      </ip>
	    </show>
	  </nc:filter>
	</nc:get>'));

	my $raw = read_rpc(30);
	# printf STDERR "got %s\n",$raw if $debug;

	my $parser = new XML::DOM::Parser;
	my $stats = $parser->parsestring($raw);

	my $nodes = $stats->getElementsByTagName("ROW_adj");
	my $n = $nodes->getLength;

	printf STDERR "found %d adjacencies\n",$n if $debug;
	for (my $i = 0; $i < $n; $i++) {
	        my $node = $nodes->item($i);

	        # result data will be like this:
	        #  <ROW_adj>
	        #  <intf-out>mgmt0</intf-out>
	        #  <ip-addr-out>10.67.16.12</ip-addr-out>
	        #  <time-stamp>00:05:32</time-stamp>
	        #  <mac>001e.c9b4.e670</mac>

	        foreach my $stat ($node->getChildNodes) {
	                next if ($stat->getNodeType() != ELEMENT_NODE);

	                my $key = $stat->getNodeName;
	                my $value = $stat->getFirstChild->getData;
	                printf STDERR "  row %d key %s value %s\n",$i,$key, 
$value if $debug;
	        }
	}
	$stats->dispose;
	exit(0);

	###############################################
	# helper routing to format a netconf request inside rpc wrapper
	sub wrap_rpc {
	        my $xmlns = shift;
	        my $cmd = shift;
	        $rpc_message_id = 100 if (!defined $rpc_message_id);
	        $rpc_message_id++;
	        return wrap_xml('<nc:rpc message-id="'.$rpc_message_id.'"  
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="http://www.cisco.com/nxos:1.0:'.$xmlns.' 
">'.$cmd.'</nc:rpc>');
	}

	###############################################
	# helper routine to format a xml requst
	sub wrap_xml {
	        my $cmd = shift;
	        return '<?xml version="1.0"?>'.$cmd.']]>]]>';
	}

	###############################################
	# helper routine to receive a netconf/xml response
	sub read_rpc {
	        my $timeout = shift;
	        my $data = "";
	        if ($exp->expect($timeout, ']]>]]>')) {
	                $data = $exp->before().$exp->match();
	        }
	        $data =~ s/]]>]]>$//g;
	        return $data;
	}

	###############################################
	# the end

>    For example,
> finding devices that haven't had their config saved is easy with SNMP:
>
>  chgTime=`snmpget -OqUtv $DEV ccmHistoryRunningLastChanged.0`
>  savTime=`snmpget -OqUtv $DEV ccmHistoryStartupLastChanged.0`
>  if [ $savTime -lt $chgTime ]; then
>     printf "%-14s config needs to be saved\n"  $DEV
>  fi
>
> how do you do that with Netconf/XML?

good question.  the key to doing something in NetConf is to find a CLI  
command that provides the data you want.  e.g. if there was a CLI  
command that provided time/datestamps of startup-config vs running- 
config (or a flag indicating config has changed between them), then  
you'd do that command.

off the top of my head, i can't think of a command that provides that,  
however one COULD in theory ask the switch to provide a diff between  
the running-config and the startup-config, e.g.
	switch# show diff rollback-patch running-config startup-config
and if you get any changes then there is a difference.

its a bit heavyweight versus a flag, but assuming your script wanted  
to do something intelligent based on said output, could be useful.

NX-OS does support the SNMP trap for ccmCLIRunningConfigChanged so you  
could use that.

another way i can forsee that one could accomplish a simple trigger is  
an EEM event that creates a file on config-change and clears it on  
config-save, e.g.
	event manager applet set_config_changed_flag
	  event cli match "config"
	  action 1 cli echo config_changed > volatile:config_changed
	  action 2 event-default
	event manager applet clear_config_config_changed
	  event cli match "copy running-config startup-config"
	  action 1 cli delete volatile:config_changed
	  action 2 event-default

then your NetConf/XML can do the equivalent of "tail  
volatile:config_changed" and see what result it gets back.
probably overkill but you get the idea - many ways to achieve what you  
want.


cheers,

lincoln.







>
>
> Regards,
> Lee



More information about the cisco-nsp mailing list