Annotation of trango/Net-Telnet-Trango/scripts/update_trango.pl, Revision 1.14
1.1 andrew 1: #!/usr/bin/perl
1.14 ! andrew 2: # $RedRiver: update_trango.pl,v 1.13 2005/12/30 01:02:41 andrew Exp $
1.1 andrew 3: ########################################################################
4: # update_trango.pl *** Updates trango foxes with a new firmware
5: #
6: # 2005.11.15 #*#*# andrew fresh <andrew@mad-techies.org>
7: ########################################################################
8: use strict;
9: use warnings;
10:
1.2 andrew 11: use Net::TFTP;
1.12 andrew 12: use YAML;
13: use lib '.';
14: use Net::Telnet::Trango;
1.2 andrew 15:
1.4 andrew 16: my $config_file = shift || 'update_trango.conf';
1.9 andrew 17: my $max_tries = 3;
1.8 andrew 18:
1.2 andrew 19:
20:
1.9 andrew 21: my $l = Mylogger->new( { log_prefix => 'UT' } );
1.4 andrew 22:
23:
1.9 andrew 24: $l->sp("Reading config file '$config_file'");
1.8 andrew 25: my $conf = read_conf($config_file);
26:
1.9 andrew 27: $l->sp(" Hardware Type: $conf->{'type'}");
28: $l->sp(" File Name: $conf->{'file_name'}");
29: $l->sp(" File Size: $conf->{'file_size'}");
30: $l->sp(" File Checksum: $conf->{'file_cksum'}");
31: $l->sp(" FW Version: $conf->{'ver'}");
32: $l->sp(" FW Checksum: $conf->{'cksum'}");
33: $l->sp("");
1.4 andrew 34:
1.2 andrew 35:
36:
37:
38:
39:
1.3 andrew 40: foreach my $fox (@{ $conf->{'ips'} }) {
1.9 andrew 41: $l->sp("Updating: $fox");
1.2 andrew 42:
43: ## Connect and login.
1.14 ! andrew 44: my $t = new Net::Telnet::Trango (
1.9 andrew 45: Timeout => 5,
1.13 andrew 46: Errmode => 'return',
1.14 ! andrew 47: ) or die "Couldn't make new connection: $!";
1.9 andrew 48:
49: $l->p("Connecting to $fox");
1.14 ! andrew 50: unless ( $t->open($fox) ) {
1.13 andrew 51: $l->sp("Error connecting: $!");
1.6 andrew 52: next;
53: }
1.3 andrew 54:
1.13 andrew 55: if ($t->host_type ne $conf->{'type'}) {
56: $l->sp("Wrong type of unit ('$t->host_type' should be '$conf->{'type'}')");
1.9 andrew 57: $t->close;
1.3 andrew 58: next;
59: }
60:
1.13 andrew 61: if ($t->firmware_version eq $conf->{'ver'}) {
62: $l->sp("Already up to date with firmware version '$t->firmware_version'");
1.9 andrew 63: $t->close;
1.5 andrew 64: next;
65: }
1.2 andrew 66:
1.9 andrew 67: $l->p("Logging in");
68: $t->login($conf->{'password'}) || die "Couldn't login: $!";
1.3 andrew 69:
1.9 andrew 70: $l->p("Sending commands");
1.2 andrew 71: ## Send commands
1.14 ! andrew 72: #print Dump $t->login_banner;
! 73: #print Dump $t->sysinfo;
! 74: #print Dump $t->last_lines;
! 75: #print Dump $t->ver();
1.13 andrew 76: print Dump $t->tftpd();
77: print Dump $t->enable_tftpd();
1.14 ! andrew 78: #print Dump [ "Exit", $t->exit ];
1.13 andrew 79: print Dump $t->tftpd();
80: print Dump $t->disable_tftpd();
81: print Dump $t->tftpd();
82: #if ( upload($t, $conf->{'file_name'}) ) {
83: # $l->p("Rebooting");
84: # $t->reboot;
85: #} else {
1.9 andrew 86: $l->p("Exiting");
87: $t->exit;
1.13 andrew 88: #}
1.12 andrew 89:
1.9 andrew 90: $l->sp("");
1.2 andrew 91: }
92:
93: sub upload
94: {
1.9 andrew 95: my $t = shift;
1.2 andrew 96: my $file = shift;
1.3 andrew 97:
1.9 andrew 98: my $ver = $t->ver;
1.11 andrew 99: $l->p("Current version '$ver->{'Firmware Version'}'");
1.2 andrew 100:
101: if (
1.3 andrew 102: $ver->{'Firmware Version'} eq $conf->{'ver'} &&
103: $ver->{'Firmware Checksum'} eq $conf->{'cksum'}
1.2 andrew 104: ) {
1.9 andrew 105: $l->sp("Already updated!");
1.2 andrew 106: return 1;
107: }
108:
109: my $try = 0;
110: while (1) {
1.3 andrew 111: if ($try >= $max_tries) {
1.9 andrew 112: $l->sp("Couldn't update in $max_tries tries!");
1.3 andrew 113: return undef;
114: }
1.2 andrew 115: $try++;
116:
1.9 andrew 117: #sysinfo($self->{'_host'});
1.3 andrew 118:
1.9 andrew 119: $l->p("Enabling TFTPd");
120: $t->enable_tftpd || die "Couldn't enable tftpd";
1.2 andrew 121:
1.9 andrew 122: $l->p("Uploading file ($file)");
1.2 andrew 123: # use tftp to push the file up
1.9 andrew 124: my $tftp = Net::TFTP->new($t->Host, Mode => 'octet');
1.3 andrew 125:
126: $tftp->put($file, $file)
127: or die "Error uploading: " . $tftp->error;
1.2 andrew 128:
129: # waitfor some sort of output
130: # make sure it says 'Success.' otherwise error
1.9 andrew 131: #print "LAST: " . $self->lastline;
132: #my @lines = $self->getlines;
1.3 andrew 133: #print Dump \@lines;
1.2 andrew 134:
1.9 andrew 135: $l->p("Checking upload ($conf->{'file_cksum'})");
136: my $results = $t->tftpd;
1.2 andrew 137: # check the 'File Length' against ???
1.3 andrew 138: if ( $results->{'File Checksum'} ne $conf->{'file_cksum'}) {
1.10 andrew 139: $l->sp(
140: "File checksum '" . $results->{'File Checksum'} .
141: "does not match config file '" . $conf->{'file_cksum'} . "'!"
142: );
1.3 andrew 143: next;
1.5 andrew 144: }
1.10 andrew 145: $l->p("File checksum matches . . . ");
1.3 andrew 146:
147: if ($results->{'File Length'} !~ /^$conf->{'file_size'} bytes/) {
1.10 andrew 148: $l->sp(
149: "File length '" . $results->{'File Length'} .
150: "does not match config file '" . $conf->{'file_size'} . " bytes'!"
151: );
1.3 andrew 152: next;
153: }
1.10 andrew 154: $l->p("File length matches . . . ");
1.2 andrew 155:
1.3 andrew 156: if ( uc($results->{'File Name'}) ne uc($conf->{'file_name'}) ) {
1.10 andrew 157: $l->sp(
158: "File name '" . $results->{'File Name'} .
159: "' does not match config file '" . $conf->{'file_name'} . "'!"
160: );
1.3 andrew 161: next;
162: }
1.10 andrew 163: $l->p("File name matches . . . ");
1.2 andrew 164:
1.9 andrew 165: $l->p("Updating flash (new checksum '$conf->{'cksum'}')");
166: unless ($results = $t->updateflash(
1.13 andrew 167: args => 'mainimage ' . $ver->{'Firmware Checksum'} .
168: ' ' . $conf->{'cksum'},
169: Timeout => 90,
1.9 andrew 170: ) ) {
171: $l->sp("Couldn't update flash: $!");
172: next;
173: }
174:
1.3 andrew 175: unless (
176: defined $results->{'Checksum'} &&
177: $results->{'Checksum'} eq $conf->{'cksum'}
178: ) {
1.9 andrew 179: $l->sp("Saved checksum does not match config file!");
1.3 andrew 180: next;
1.2 andrew 181: }
1.9 andrew 182: $l->p("Uploaded checksum ($results->{'Checksum'}) " .
1.5 andrew 183: "matches ($conf->{'cksum'})");
1.3 andrew 184:
1.9 andrew 185: $l->sp("Successfully updated!");
1.3 andrew 186: return 1;
1.2 andrew 187: }
188: }
189:
1.9 andrew 190: sub read_conf
1.2 andrew 191: {
1.9 andrew 192: my $file = shift;
193: my %conf;
194: my $in_ip_list = 0;
195: open my $fh, $file or die "Couldn't open file $file: $!";
196: while (<$fh>) {
197: chomp;
198: next if /^#/;
199: next if /^$/;
200: if ($in_ip_list) {
1.10 andrew 201: s/\s+//g; # Whitespace is a no no
202:
1.9 andrew 203: if (/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.)(\d{1,3})-(\d{1,3})/) {
204: push @{ $conf{'ips'} }, $1 . $_ for ($2..$3);
205: } else {
206: push @{ $conf{'ips'} }, $_;
207: }
208: } else {
209: my ($key, $val) = split /\s+/, $_, 2;
210:
211: if (lc($key) eq 'ips') {
212: $in_ip_list = 1;
213: next;
214: }
215:
1.10 andrew 216: $key =~ s/^\s+//;
217: $key =~ s/\s+$//;
218: $val =~ s/^\s+//;
219: $val =~ s/\s+$//;
220:
1.9 andrew 221: $conf{ lc($key) } = $val;
222: }
223: }
224: close $fh;
225:
226: #print Dump \%conf;
227: foreach (
228: 'password',
229: 'file_name', 'file_size', 'file_cksum',
230: 'ver', 'cksum', 'ips',
231: ) {
232: die "No $_ specified in config file!"
233: if (not exists $conf{$_});
234: }
235:
236: #print Dump \%conf;
237: #exit;
238: return \%conf;
239: }
1.3 andrew 240:
1.9 andrew 241: package Mylogger;
242:
243: use Fcntl ':flock'; # import LOCK_* constants
244: #use YAML;
245: use constant LOG_PRINT => 128;
246: use constant LOG_SAVE => 64;
247:
248: DESTROY {
249: my $self = shift;
250: if ($self->{'MYLOG'}) {
251: $self->p("Closing log ($self->{'log_path'}/$self->{'log_file'})");
252: close $self->{'MYLOG'};
1.3 andrew 253: }
1.9 andrew 254: }
255:
256: sub new {
257: my $package = shift;
258: my $self = shift || {};
259:
260: $self->{'base_path'} ||= '.';
261: $self->{'log_path'} ||= $self->{'base_path'};
262: $self->{'log_prefix'} ||= 'LOG';
263: $self->{'log_file'} ||= GetLogName(
264: $self->{'log_prefix'},
265: $self->{'log_path'}
266: );
267: bless $self, $package;
268: }
269:
270: sub s
271: {
272: my $self = shift;
273: my $m = shift;
274: return $self->mylog($m, LOG_SAVE);
275: }
1.3 andrew 276:
1.9 andrew 277: sub p
278: {
279: my $self = shift;
280: my $m = shift;
281: return $self->mylog($m, LOG_PRINT);
282: }
1.3 andrew 283:
1.9 andrew 284: sub sp
285: {
286: my $self = shift;
287: my $m = shift;
288: return $self->mylog($m, LOG_SAVE | LOG_PRINT);
1.4 andrew 289: }
290:
291: sub mylog
292: {
1.9 andrew 293: my $self = shift;
294:
1.5 andrew 295: my $thing = shift;
296: chomp $thing;
297:
1.9 andrew 298: my $which = shift;
1.5 andrew 299:
1.9 andrew 300: my $MYLOG;
301: if ($which & LOG_PRINT) {
302: print $thing, "\n";
303: }
304:
305: if ($which & LOG_SAVE) {
306: if ($self->{'MYLOG'}) {
307: $MYLOG = $self->{'MYLOG'};
308: } else {
309: unless ($MYLOG) {
310: open ($MYLOG, '>>', $self->{'log_path'} . '/' . $self->{'log_file'})
311: or die "Couldn't open logfile!\n";
312: my $ofh = select $MYLOG;
313: $|=1;
314: select $ofh;
315: $self->{'MYLOG'} = $MYLOG;
316:
317: $self->p("Opened log ($self->{'log_path'}/$self->{'log_file'})");
318: }
1.5 andrew 319: }
320: flock($MYLOG, LOCK_EX);
321: print $MYLOG (scalar gmtime), "\t", $thing, "\n"
322: or die "Couldn't print to MYLOG: $!";
323: flock($MYLOG, LOCK_UN);
324: }
1.4 andrew 325: }
326:
327: sub GetLogName
328: {
329: my $prefix = shift || die "Invalid prefix passed for log";
330:
331: my $logdate = GetLogDate();
332: my $logver = 0;
333: my $logname;
334:
335: do {
336: $logname = $prefix . $logdate . sprintf("%02d", $logver) . '.log';
337: $logver++;
338: } until (not -e $logname);
339:
340: return $logname;
341: }
342:
343: sub GetLogDate
344: {
345: my ($sec,$min,$hour,$mday,$mon,$year,,,) = localtime();
346:
347: $mon++;
348: $year += 1900;
349:
350: if ($min < 10) { $min = "0$min" }
351: if ($sec < 10) { $sec = "0$sec" }
352: if ($hour < 10) { $hour = "0$hour" }
353: if ($mday < 10) { $mday = "0$mday" }
354: if ($mon < 10) { $mon = "0$mon" }
355:
356: my $time = $year . $mon . $mday;
357:
358: return $time;
1.3 andrew 359: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>