File Coverage

blib/lib/Cisco/CopyConfig.pm
Criterion Covered Total %
statement 28 89 31.4
branch 4 34 11.7
condition 1 14 7.1
subroutine 7 20 35.0
pod 4 14 28.5
total 44 171 25.7


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             ###
3             ### $Id: CopyConfig.pm,v 1.3 2004/11/04 22:23:19 aaronsca Exp aaronsca $
4             ###
5             ### -- Manipulate running-config of devices running IOS
6             ###
7              
8             package Cisco::CopyConfig;
9 1     1   989 use strict;
  1         2  
  1         41  
10 1     1   21401 use Socket;
  1         6298  
  1         1145  
11 1     1   2206 use Net::SNMP;
  1         152765  
  1         1446  
12             $Cisco::CopyConfig::VERSION = sprintf "%d.%02d", q$Revision: 1.3 $ =~ /(\d+)/g;
13              
14             sub new {
15             ###
16             ### -- Create a new CopyConfig object
17              
18 1     1 1 39 my($class) = shift; ## - Object class
19 1         11 my($self) = bless {
20             'err' => '', ## - Error message
21             'host' => '', ## - Default host
22             'comm' => '', ## - Default community
23             'tmout' => 2, ## - Default timeout
24             'retry' => 2 ## - Default retries
25             }, $class;
26 1         7 $self->_newarg(@_); ## - Parse arguments
27 1         7 srand(time() ^ ($$ + ($$ << 15))); ## - Seed random number
28 1         7 $self->{'snmp'} = $self->open(); ## - Get SNMP object
29 1         30658 $self;
30             }
31              
32             sub open {
33             ###
34             ### -- Create SNMP session and return object
35              
36 1     1 0 4 my($self) = shift;
37              
38 1         4 $self->_newarg(@_); ## - Parse arguments
39 1 50 33     10 unless(defined($self->{'host'}) && defined($self->{'comm'})){
40 0         0 $self->{'err'} = 'missing hostname or community string';
41 0         0 return undef;
42             }
43 1         12 $self->{'snmp'} = Net::SNMP->session( ## - Create SNMP object
44             Hostname => $self->{'host'},
45             Community => $self->{'comm'},
46             Timeout => $self->{'tmout'},
47             Retries => $self->{'retry'},
48             Version => 1
49             );
50             }
51              
52             sub close {
53             ###
54             ### -- Shut down SNMP session and destroy SNMP object
55              
56 1     1 0 366 my($self) = shift;
57 1         7 my($status) = $self->{'snmp'}->close();
58              
59 1         64 $self->{'snmp'} = undef;
60 1         6 $status;
61             }
62              
63             sub copy {
64             ###
65             ### -- Copy a running-config to a tftp server file
66              
67 0     0 1 0 my($self) = shift;
68 0   0     0 my($addr) = shift || return undef;
69 0   0     0 my($file) = shift || return undef;
70              
71 0 0       0 unless($self->_cktftp($addr, $file)){
72 0         0 return undef;
73             }
74 0         0 $self->{'rand'} = int(rand(1 << 24));
75 0         0 $self->_xfer(
76             $self->ccCopyProtocol(1),
77             $self->ccCopySourceFileType(4),
78             $self->ccCopyDestFileType(1),
79             $self->ccCopyServerAddress($addr),
80             $self->ccCopyFileName($file),
81             $self->ccCopyEntryRowStatus(4)
82             );
83             }
84              
85             sub merge {
86             ###
87             ### -- Merge a tftp server file into a running-config
88              
89 0     0 1 0 my($self) = shift;
90 0   0     0 my($addr) = shift || return undef;
91 0   0     0 my($file) = shift || return undef;
92              
93 0 0       0 unless($self->_cktftp($addr, $file)){
94 0         0 return undef;
95             }
96 0         0 $self->{'rand'} = int(rand(1 << 24));
97 0         0 $self->_xfer(
98             $self->ccCopyProtocol(1),
99             $self->ccCopySourceFileType(1),
100             $self->ccCopyServerAddress($addr),
101             $self->ccCopyFileName($file),
102             $self->ccCopyDestFileType(4),
103             $self->ccCopyEntryRowStatus(4)
104             );
105             }
106              
107             sub error {
108             ###
109             ### -- Return last error message
110              
111 0     0 1 0 my($self) = shift;
112              
113 0 0       0 defined($self->{err}) ? $self->{err} : '' ;
114             }
115              
116             sub _newarg {
117             ###
118             ### -- Parse new object arguments
119              
120 2     2   4 my($self) = shift;
121 2         6 my(%arg) = @_;
122              
123 2         9 foreach(keys %arg){
124 2 100       15 $self->{'host'} = $arg{$_}, next if /^Host$/oi; ## - SNMP host
125 1 50       13 $self->{'comm'} = $arg{$_}, next if /^Comm$/oi; ## - SNMP community
126 0 0         $self->{'tmout'} = $arg{$_}, next if /^tmout$/oi; ## - SNMP timeout
127 0 0         $self->{'retry'} = $arg{$_}, next if /^Retry$/oi; ## - SNMP timeout
128             }
129             }
130              
131             sub _cktftp {
132             ###
133             ### -- Check tftp arguments
134              
135 0     0     my($self) = shift;
136 0           my($addr) = shift;
137 0           my($file) = shift;
138              
139 0 0 0       if ($addr !~ /^[\d\.]+$/ || !defined(inet_aton($addr))) {
140 0           $self->{err} = 'invalid tftp server address';
141 0           return 0;
142             }
143 0           1;
144             }
145              
146             sub _xfer {
147             ###
148             ### -- Do actual tftp transfer
149              
150 0     0     my($self) = shift;
151 0           my(@oids) = @_; ## - OIDs to use
152 0           my($snmp) = $self->{'snmp'}; ## - Net::SNMP subclass
153 0           my($answer) = ''; ## - SNMP answer
154 0           my($status) = 0; ## - SNMP xfer status
155              
156 0           $snmp->set_request(@oids); ## - Start xfer
157 0 0         if ($snmp->error()) {
158 0           $self->{'err'} = $snmp->error();
159 0           return 0;
160             }
161 0           while($status <= 2){
162 0           $answer = $snmp->get_request($self->ccCopyState());
163 0           $status = $answer->{$self->ccCopyState()};
164 0 0         if ($status == 3) { ## Xfer succeeded
165 0           last;
166             }
167 0 0         if ($status == 4) { ## Xfer failed
168 0           $answer = $snmp->get_request($self->ccCopyFailCause());
169 0           $status = $answer->{$self->ccCopyFailCause()};
170              
171 0 0         $self->{'err'} = 'unknown error' if $status == 1;
172 0 0         $self->{'err'} = 'file access error' if $status == 2;
173 0 0         $self->{'err'} = 'tftp timeout' if $status == 3;
174 0 0         $self->{'err'} = 'out of memory' if $status == 4;
175 0 0         $self->{'err'} = 'no configuration' if $status == 5;
176 0           return 0;
177             }
178 0           sleep(2);
179             }
180 0           $snmp->set_request($self->ccCopyEntryRowStatus(6)); ## - Clear entry row
181 0           1;
182             }
183              
184             ### -- OIDs taken from CISCO-CONFIG-COPY-MIB-V1SMI.my
185             ###
186             sub ccCopyProtocol {
187 0     0 0   ('1.3.6.1.4.1.9.9.96.1.1.1.1.2.' . $_[0]->{'rand'}, INTEGER, $_[1])
188             }
189             sub ccCopySourceFileType {
190 0     0 0   ('1.3.6.1.4.1.9.9.96.1.1.1.1.3.' . $_[0]->{'rand'}, INTEGER, $_[1])
191             }
192             sub ccCopyDestFileType {
193 0     0 0   ('1.3.6.1.4.1.9.9.96.1.1.1.1.4.' . $_[0]->{'rand'}, INTEGER, $_[1])
194             }
195             sub ccCopyServerAddress {
196 0     0 0   ('1.3.6.1.4.1.9.9.96.1.1.1.1.5.' . $_[0]->{'rand'}, IPADDRESS, $_[1])
197             }
198             sub ccCopyFileName {
199 0     0 0   ('1.3.6.1.4.1.9.9.96.1.1.1.1.6.' . $_[0]->{'rand'}, OCTET_STRING, $_[1])
200             }
201             sub ccCopyEntryRowStatus {
202 0     0 0   ('1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $_[0]->{'rand'}, INTEGER, $_[1])
203             }
204             sub ccCopyState {
205 0     0 0   '1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $_[0]->{'rand'}
206             }
207             sub ccCopyFailCause {
208 0     0 0   '1.3.6.1.4.1.9.9.96.1.1.1.1.13.' . $_[0]->{'rand'}
209             }
210             1; ## - Needed for module
211              
212             __END__