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

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

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