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