[BACK]Return to update_trango.pl CVS log [TXT][DIR] Up to [local] / trango / Net-Telnet-Trango / scripts

Annotation of trango/Net-Telnet-Trango/scripts/update_trango.pl, Revision 1.26

1.16      mike        1: #!/usr/bin/perl
1.26    ! andrew      2: # $RedRiver: update_trango.pl,v 1.25 2007/02/02 17:50:09 andrew 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;
1.26    ! andrew    155:
        !           156:   if (! (
        !           157:     $ver->{$fw_type . ' Version'}  &&
        !           158:     $ver->{$fw_type . ' Checksum'}
        !           159:   )) {
        !           160:     $l->sp("Error getting current version numbers");
        !           161:        return;
        !           162:   }
1.16      mike      163:
                    164:   if (
1.19      andrew    165:     $ver->{$fw_type . ' Version'}  eq $conf->{'ver'} &&
                    166:     $ver->{$fw_type . ' Checksum'} eq $conf->{'cksum'}
1.16      mike      167:   ) {
1.21      mike      168:     return 0;
1.16      mike      169:   }
                    170:
1.23      andrew    171:   $l->sp("Config information:");
                    172:   $l->sp("  Hardware Type: $conf->{'type'}");
                    173:   $l->sp("  File Name:     $conf->{'file_name'}");
                    174:   $l->sp("  File Size:     $conf->{'file_size'}");
                    175:   $l->sp("  File Checksum: $conf->{'file_cksum'}");
                    176:   $l->sp("  Conf Version:  $conf->{'ver'}");
                    177:   $l->sp("  Cur  Version:  $ver->{$fw_type . ' Version'}");
                    178:   $l->sp("  Conf Checksum: $conf->{'cksum'}");
                    179:   $l->sp("  Cur  Checksum: $ver->{$fw_type . ' Checksum'}");
                    180:
                    181:   $l->sp("Updating");
1.16      mike      182:   my $try = 0;
                    183:   while (1) {
                    184:     if ($try >= $max_tries) {
                    185:       $l->sp("Couldn't update in $max_tries tries!");
1.23      andrew    186:       return;
1.16      mike      187:     }
                    188:     $try++;
                    189:
                    190:     #sysinfo($self->{'_host'});
                    191:
                    192:     $l->p("Enabling TFTPd");
1.22      andrew    193:     unless ($t->enable_tftpd) {
                    194:       $l->sp("Couldn't enable tftpd");
                    195:       next;
                    196:     }
1.16      mike      197:
                    198:     $l->p("Uploading file ($file)");
                    199:     # use tftp to push the file up
                    200:     my $tftp = Net::TFTP->new($t->Host, Mode => 'octet');
                    201:
1.21      mike      202:     unless ($tftp->put($file, $file)) {
1.22      andrew    203:       $l->sp("Error uploading: " . $tftp->error);
1.21      mike      204:       next;
                    205:     }
1.16      mike      206:
                    207:     $l->p("Checking upload ($conf->{'file_cksum'})");
                    208:     my $results = $t->tftpd;
                    209:     # check the 'File Length' against ???
                    210:     if ( $results->{'File Checksum'} ne $conf->{'file_cksum'}) {
                    211:       $l->sp(
                    212:         "File checksum '" . $results->{'File Checksum'} .
1.20      mike      213:         " does not match config file '" . $conf->{'file_cksum'} . "'!"
1.16      mike      214:       );
                    215:       next;
                    216:     }
                    217:     $l->p("File checksum matches . . . ");
                    218:
                    219:     if ($results->{'File Length'}   !~ /^$conf->{'file_size'} bytes/) {
                    220:       $l->sp(
                    221:         "File length '" . $results->{'File Length'} .
                    222:         "does not match config file '" . $conf->{'file_size'} . " bytes'!"
                    223:       );
                    224:       next;
                    225:     }
                    226:     $l->p("File length matches . . . ");
                    227:
1.24      mike      228:     if ( uc($results->{'File Name'}) ne uc($file) ) {
1.16      mike      229:       $l->sp(
                    230:         "File name '" . $results->{'File Name'} .
1.24      mike      231:         "' does not match config file '" . $file . "'!"
1.16      mike      232:       );
                    233:       next;
                    234:     }
                    235:     $l->p("File name  matches . . . ");
                    236:
1.19      andrew    237:     my $image_type = 'mainimage';
                    238:     if ($fw_type eq 'FPGA') {
                    239:       $image_type = 'fpgaimage';
                    240:     }
                    241:     $l->p("Updating $image_type (new checksum '$conf->{'cksum'}')");
1.16      mike      242:     unless ($results = $t->updateflash(
1.19      andrew    243:       args => $image_type . ' ' . $ver->{$fw_type . ' Checksum'} .
1.16      mike      244:               ' '          . $conf->{'cksum'},
                    245:       Timeout => 90,
                    246:     ) ) {
                    247:       $l->sp("Couldn't update flash: $!");
                    248:       next;
                    249:     }
                    250:
                    251:     unless (
                    252:       defined $results->{'Checksum'} &&
                    253:       $results->{'Checksum'} eq $conf->{'cksum'}
                    254:     ) {
1.17      mike      255:       $l->sp("Saved checksum " . $results->{'Checksum'} . " does not match config file " .  $conf->{'cksum'} . "!");
1.16      mike      256:       next;
                    257:     }
                    258:     $l->p("Uploaded checksum ($results->{'Checksum'}) " .
                    259:           "matches ($conf->{'cksum'})");
                    260:
                    261:     $l->sp("Successfully updated!");
                    262:     return 1;
                    263:   }
                    264: }
                    265:
                    266: package Mylogger;
                    267:
                    268: use Fcntl ':flock'; # import LOCK_* constants
                    269: #use YAML;
                    270: use constant LOG_PRINT => 128;
                    271: use constant LOG_SAVE  =>  64;
                    272:
                    273: DESTROY {
                    274:   my $self = shift;
                    275:   if ($self->{'MYLOG'}) {
                    276:     $self->p("Closing log ($self->{'log_path'}/$self->{'log_file'})");
                    277:     close $self->{'MYLOG'};
                    278:   }
                    279: }
                    280:
                    281: sub new {
                    282:   my $package = shift;
                    283:   my $self = shift || {};
                    284:
                    285:   $self->{'base_path'}  ||= '.';
                    286:   $self->{'log_path'}   ||= $self->{'base_path'};
                    287:   $self->{'log_prefix'} ||= 'LOG';
                    288:   $self->{'log_file'}   ||= GetLogName(
                    289:     $self->{'log_prefix'},
                    290:     $self->{'log_path'}
                    291:   );
                    292:   bless $self, $package;
                    293: }
                    294:
                    295: sub s
                    296: {
                    297:   my $self = shift;
                    298:   my $m = shift;
                    299:   return $self->mylog($m, LOG_SAVE);
                    300: }
                    301:
                    302: sub p
                    303: {
                    304:   my $self = shift;
                    305:   my $m = shift;
                    306:   return $self->mylog($m, LOG_PRINT);
                    307: }
                    308:
                    309: sub sp
                    310: {
                    311:   my $self = shift;
                    312:   my $m = shift;
                    313:   return $self->mylog($m, LOG_SAVE | LOG_PRINT);
                    314: }
                    315:
                    316: sub mylog
                    317: {
                    318:   my $self = shift;
                    319:
                    320:   my $thing = shift;
                    321:   chomp $thing;
                    322:
                    323:   my $which = shift;
                    324:
                    325:   my $MYLOG;
                    326:   if ($which & LOG_PRINT) {
                    327:     print $thing, "\n";
                    328:   }
                    329:
                    330:   if ($which & LOG_SAVE) {
                    331:     if ($self->{'MYLOG'}) {
                    332:       $MYLOG = $self->{'MYLOG'};
                    333:     } else {
                    334:       unless ($MYLOG) {
                    335:                open ($MYLOG, '>>', $self->{'log_path'} . '/' . $self->{'log_file'})
                    336:           or die "Couldn't open logfile!\n";
                    337:         my $ofh = select $MYLOG;
                    338:         $|=1;
                    339:         select $ofh;
                    340:         $self->{'MYLOG'} = $MYLOG;
                    341:
                    342:         $self->p("Opened log ($self->{'log_path'}/$self->{'log_file'})");
                    343:       }
                    344:     }
                    345:     flock($MYLOG, LOCK_EX);
                    346:     print $MYLOG (scalar gmtime), "\t", $thing, "\n"
                    347:       or die "Couldn't print to MYLOG: $!";
                    348:     flock($MYLOG, LOCK_UN);
                    349:   }
                    350: }
                    351:
                    352: sub GetLogName
                    353: {
                    354:   my $prefix  = shift || die "Invalid prefix passed for log";
                    355:
                    356:   my $logdate = GetLogDate();
                    357:   my $logver  = 0;
                    358:   my $logname;
                    359:
                    360:   do {
                    361:     $logname = $prefix . $logdate . sprintf("%02d", $logver) . '.log';
                    362:     $logver++;
                    363:   } until (not -e $logname);
                    364:
                    365:   return $logname;
                    366: }
                    367:
                    368: sub GetLogDate
                    369: {
                    370:   my ($sec,$min,$hour,$mday,$mon,$year,,,) = localtime();
                    371:
                    372:   $mon++;
                    373:   $year += 1900;
                    374:
                    375:   if ($min  < 10) { $min  = "0$min"  }
                    376:   if ($sec  < 10) { $sec  = "0$sec"  }
                    377:   if ($hour < 10) { $hour = "0$hour" }
                    378:   if ($mday < 10) { $mday = "0$mday" }
                    379:   if ($mon  < 10) { $mon  = "0$mon"  }
                    380:
                    381:   my $time = $year . $mon . $mday;
                    382:
                    383:   return $time;
                    384: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>