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