[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.30

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

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