📄 version.pm
字号:
package Cisco::Version;## ----------------------------------------------------------------------------------------------## Cisco::Version#### Cisco "Show Version" parser.## Try to parse some useful info from the "show version" output like memory, software, flash, etc.#### $Id: Version.pm 76 2007-07-23 21:05:02Z mwallraf $## $Author: mwallraf $## $Date: 2007-07-23 23:05:02 +0200 (Mon, 23 Jul 2007) $#### This program is free software; you can redistribute it and/or## modify it under the same terms as Perl itself.## ----------------------------------------------------------------------------------------------use warnings;use strict;use Carp;require 5.002;#use Data::Dumper;our $VERSION = '0.02';my $AUTOLOAD;my $DEBUG = 1; # 0 = OFF, 1 = ERROR, 2 = WARN, 3 = INFO, 4 = DEBUGmy %CMD = ( 'bootstrap' => 'bootstrap', 'sw_type' => 'sw-type', 'sw_featureset' => 'sw-featureset', 'sw_version' => 'sw-version', 'bootldr_type' => 'bootldr-type', 'bootldr_version' => 'bootldr-version', 'bootldr_featureset' => 'bootldr-featureset', 'hostname' => 'hostname', 'uptime' => 'uptime', 'reload_reason' => 'reload-reason', 'reload_time' => 'reload-time', 'image_file' => 'image-file', 'chassis_type' => 'chassis-type', 'memory' => 'memory', 'confreg' => 'confreg', 'pwdrecovery' => 'pwdrecovery', 'flash_filesystems_sizes' => 'flash_filesystems_sizes', 'flash_largest_size' => 'flash_largest_size', );sub new() { my ($this, $show_version) = @_; my $class = ref($this) || $this; my $self = {}; $self->{'show_version'} = $show_version; # full output of "show version" $self->{'parsed'} = {}; # this will contain hash of parsed parameters $self->{'not_found'} = '<NOT FOUND>'; # this value is returned if a parameter was not found in show version## these are the possible values we can expect for now ### $self->{'parsed'}->{'bootstrap'};# $self->{'parsed'}->{'sw-type'};# $self->{'parsed'}->{'sw-featureset'};# $self->{'parsed'}->{'sw-version'};# $self->{'parsed'}->{'bootldr-type'};# $self->{'parsed'}->{'bootldr-version'};# $self->{'parsed'}->{'bootldr-featureset'};# $self->{'parsed'}->{'hostname'};# $self->{'parsed'}->{'uptime'};# $self->{'parsed'}->{'reload-reason'};# $self->{'parsed'}->{'reload-time'};# $self->{'parsed'}->{'image-file'};# $self->{'parsed'}->{'chassis-type'};# $self->{'parsed'}->{'memory'};# $self->{'parsed'}->{'confreg'};# $self->{'parsed'}->{'pwdrecovery'};# $self->{'parsed'}->{'flash_filesystems_sizes'} = [];# $self->{'parsed'}->{'flash_largest_size'}; bless($self, $class); return($self);}# This routine parses "show version"sub parse { my ($self, $sv) = @_; if (!$sv) { ($self->{'show_version'})?($sv = $self->{'show_version'}):(croak('Forgot to load "show config" output?')); } my @lines = split( /[\n\r]/, $sv); my ($line); foreach $line (@lines) { next unless ($line); &_debug("new line found", $line); if ($line =~ /^(?:Cisco|IOS).*Version ([^ ,]+)/) { $self->_process_software_version($line); }; if ($line =~ /^ROM: /) { $self->_process_rom($line); }; if ($line =~ /^BOOTLDR: /) { $self->_process_bootloader($line); }; if ($line =~ /uptime/i) { $self->_process_uptime($line); }; if ($line =~ /System returned to ROM by /) { $self->_process_reload_reason($line); }; if ($line =~ /restarted/) { $self->_process_reload_time($line); }; if ($line =~ /System image file is/) { $self->_process_image_file($line); }; if ($line =~ /^cisco.*[0-9]+K.*memory.$/i) { $self->_process_memory($line); }; if ($line =~ /of physical memory \(DRAM\)$/) { $self->_process_additional_memory($line); }; if ($line =~ /^Configuration register is/i) { $self->_process_configuration_register($line); }; if ($line =~ /password-recovery mechanism/) { $self->_process_password_recovery($line); }; if ($line =~ /^[0-9]+K .*(?:PCMCIA |[fF]lash[^-]|ATA )/) { $self->_process_flash($line); }; }}sub AUTOLOAD() { my ($self,@args) = @_; my $cmd = $Cisco::Version::AUTOLOAD; my $parm; $cmd =~ s/.*:://; $parm = $cmd; $parm =~ s/get_//; if ( ($cmd =~ /^get_/) && (defined($CMD{"$parm"})) ) { return $self->get_parameter($parm); } else { croak("function $cmd does not exist"); }}sub get_parameter() { my ($self, $parm) = @_; if (defined($self->{'parsed'}->{$CMD{"$parm"}})) { return $self->{'parsed'}->{$CMD{"$parm"}}; } else { return $self->{'not_found'}; }}#### returns a reference to the 'parsed' hash,## this contains all the elements that were found in 'show version'##sub get_summary() { my ($self) = shift; return $self->{'parsed'};}sub get_not_found_value() { my ($self) = shift; return $self->{'not_found'};}sub set_not_found_value() { my ($self, $value) = @_; $self->{'not_found'} = $value if (defined($value));}## look for bootstrap versionsub _process_rom() { my ($self, $line) = @_; my $version; &_debug("parsing bootstrap", $line); if ( ($line !~ /(?:bootstrap|ROM: [0-9]+\.[0-9]+)/i) || ($line =~ /bootstrap program/i) ) { &_info("IGNORE - $line"); } else { $line =~ /(?:version ([^ ,]+)|ROM: ([0-9].*))/i; $version = $1 || $2; if ($version) { $self->{'parsed'}->{'bootstrap'} = $version; &_debug("result = $version"); } else { &_warn("bootstrap version not found", $line); } }}sub _process_software_version() { my ($self, $line) = @_; my ($sw_version, $sw_type, $sw_featureset); &_debug("parsing software version", $line); if ($line =~ /^(?:Cisco IOS Software|IOS \(tm\))[, ]+(.*) Software \((.*)\).*Version ([^ ,]+)/) { $sw_type = $1; $sw_featureset = $2; $sw_version = $3; ($sw_type)?($self->{'parsed'}->{'sw-type'} = $sw_type):(&_warn("software type not found", $line)); ($sw_featureset)?($self->{'parsed'}->{'sw-featureset'} = $sw_featureset):(&_warn("software featureset not found", $line)); ($sw_version)?($self->{'parsed'}->{'sw-version'} = $sw_version):(&_warn("software version not found", $line)); &_debug("result = $sw_type"); &_debug("result = $sw_featureset"); &_debug("result = $sw_version"); } else { &_error("software version, type or featureset cannot be parsed", $line); }}sub _process_bootloader() { my ($self, $line) = @_; my ($bl_version, $bl_type, $bl_featureset); &_debug("parsing bootloader", $line); if ($line =~ /^BOOTLDR: (.*) (?:Software|Boot Loader) \((.*)\).*Version ([^ ,]+)/) { $bl_type = $1; $bl_featureset = $2; $bl_version = $3; ($bl_type)?($self->{'parsed'}->{'bootldr-type'} = $bl_type):(&_warn("bootloader type not found", $line)); ($bl_featureset)?($self->{'parsed'}->{'bootldr-featureset'} = $bl_featureset):(&_warn("bootloader featureset not found", $line)); ($bl_version)?($self->{'parsed'}->{'bootldr-version'} = $bl_version):(&_warn("bootloader version not found", $line)); &_debug("result = $bl_type"); &_debug("result = $bl_featureset"); &_debug("result = $bl_version"); } else { &_error("bootloader version, type or featureset cannot be parsed", $line); }}sub _process_uptime() { my ($self, $line) = @_; my ($host, $uptime); &_debug("parsing uptime", $line); if ($line =~ /^ *(?:(.*) uptime is|Switch Uptime|Uptime for this control processor is)[^0-9]+(.*minutes*)/) { if ($1 && $2) { $host = $1; $self->{'parsed'}->{'hostname'} = $host; } $uptime = $2; ($uptime)?($self->{'parsed'}->{'uptime'} = $uptime):(&_warn("uptime was not found", $line)); &_debug("result = $uptime"); } else { &_error("uptime cannot be parsed", $line); }}sub _process_reload_reason() { my ($self, $line) = @_; my $reason; &_debug("parsing reload reason", $line); if ($line =~ /System returned to ROM by (.*)/) { $reason = $1; ($reason)?($self->{'parsed'}->{'reload-reason'} = $reason):(&_warn("reload reason was not found", $line)); &_debug("result = $reason"); } else { &_error("reload reason cannot be parsed", $line); }}sub _process_reload_time() { my ($self, $line) = @_; my $time; &_debug("parsing reload time", $line); if ($line =~ /restarted.* at (.*)/) { $time = $1; ($time)?($self->{'parsed'}->{'reload-time'} = $time):(&_warn("reload time was not found", $line)); &_debug("result = $time"); } else { &_error("reload time cannot be parsed", $line); }}sub _process_image_file() { my ($self, $line) = @_; my $image; &_debug("parsing image file info", $line); if ($line =~ /System image file is \"(.*)\"/) { $image = $1; ($image)?($self->{'parsed'}->{'image-file'} = $image):(&_warn("image file was not found", $line)); &_debug("result = $image"); } else { &_error("system image file cannot be parsed", $line); }}#### tries to calculate the memory## This is no exact science so be careful ...## Here's how we do it by default to get memory in MB : (main memory + shared IO memory) / 1024## But there are a few exceptions.## sub _process_memory() { my ($self, $line) = @_; my ($memory, $chassis); my ($main_mem, $io_mem); &_debug("parsing memory", $line); if ($line =~ /cisco ([^ ]+).*with (?:([0-9]+)K |([0-9]+)K\/([0-9]+)K).*memory.*/i) { $chassis = $1; if ($3 && $4) { $main_mem = $3; $io_mem = $4; ### some exceptions # ex. for WS-C3550 if ($chassis =~ /^WS-C35/) { $memory = $main_mem; } ### default calculation else { $memory = $main_mem + $io_mem; } } elsif ($2) { $memory = $2; } # save memory in megabytes (try to round to decimal number) $memory = int(($memory / 1024) + .5); ($chassis)?($self->{'parsed'}->{'chassis-type'} = $chassis):(&_warn("chassis type was not found", $line)); ($memory)?($self->{'parsed'}->{'memory'} = $memory):(&_warn("memory was not found", $line)); &_debug("result = $chassis"); &_debug("result = $memory"); } else { &_error("memory or chassis type cannot be parsed", $line); }}#### some smaller routers have extra line with 'additional' DRAM## this should be added to the RAM we already found##sub _process_additional_memory() { my ($self, $line) = @_; my ($memory); if ($line =~ /([0-9]+)M .* of physical memory \(DRAM\)$/) { $memory = int($1 + .5); ($memory)?($self->{'parsed'}->{'memory'} = $self->{'parsed'}->{'memory'} + $memory):(&_warn("additional DRAM was not found", $line)); } else { &_error("unable to parse additional DRAM", $line); }}sub _process_configuration_register() { my ($self, $line) = @_; my ($confreg); &_debug("parsing configuration register", $line); if ($line =~ /^Configuration register is (.*)/) { $confreg = $1; ($confreg)?($self->{'parsed'}->{'confreg'} = $confreg):(&_warn("configuration register was not found", $line)); &_debug("result = $confreg"); } else { &_error("unable to parse configuration register", $line); }}sub _process_password_recovery() { my ($self, $line) = @_; my ($recovery); &_debug("parsing password recovery mechanism", $line); if ($line =~ /password-recovery mechanism is ([a-zA-Z]+)/) { $recovery = $1; ($recovery)?($self->{'parsed'}->{'pwdrecovery'} = $recovery):(&_warn("password recovery mechanism was not found", $line)); &_debug("result = $recovery"); } else { &_error("unable to parse password recovery mechanism", $line); }}#### Flash info is also difficult to parse as a chassis may have multiple## filesystems. Also not all chassis types report flash info.## Usually we're only interested in largest filesystem only so this is what ## we try to parse :#### List of all flash filesystem sizes is kept as flash_filesystems_sizes## Largest flash filesystem is reported as flash_largest_size##sub _process_flash() { my ($self, $line) = @_; my ($flash); &_debug("parsing flash info", $line); if ($line =~ /^([0-9]+)K .*(?:PCMCIA |[fF]lash[^-]|ATA )/) { $flash = int(($1 / 1024) + .5); if ($flash) { if (!defined($self->{'parsed'}->{'flash_filesystems_sizes'})) { $self->{'parsed'}->{'flash_filesystems_sizes'} = []; } push (@{$self->{'parsed'}->{'flash_filesystems_sizes'}}, $flash); if (!defined($self->{'parsed'}->{'flash_largest_size'}) || ($self->{'parsed'}->{'flash_largest_size'} < $flash)) { $self->{'parsed'}->{'flash_largest_size'} = $flash; } &_debug("result = $flash"); } else { &_warn("flash was not found", $line); } } else { &_error("unable to parse flash", $line); }}#### carp a log message, regardless of $DEBUG value##sub _log() { my ($msg, $line) = @_; if ($line) { $msg = $msg . " [$line]"; } &carp($msg);}#### carp a log message, only if $DEBUG >= 1##sub _error() { my ($msg, $line) = @_; if ($DEBUG >= 1) { &_log("ERROR: ".$msg, $line); }}#### carp a log message, only if $DEBUG >= 2##sub _warn() { my ($msg, $line) = @_; if ($DEBUG >= 2) { &_log("WARN: ".$msg, $line); }}#### carp a log message, only if $DEBUG >= 3##sub _info() { my ($msg, $line) = @_; if ($DEBUG >= 3) { &_log("INFO: ".$msg, $line); }}#### carp a log message, only if $DEBUG >= 3##
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -