summaryrefslogtreecommitdiffstats
path: root/INF/APC.pm
diff options
context:
space:
mode:
Diffstat (limited to 'INF/APC.pm')
-rw-r--r--INF/APC.pm504
1 files changed, 504 insertions, 0 deletions
diff --git a/INF/APC.pm b/INF/APC.pm
new file mode 100644
index 0000000..f740543
--- /dev/null
+++ b/INF/APC.pm
@@ -0,0 +1,504 @@
+#!/usr/bin/env perl
+
+package INF::APC;
+
+use SNMP::MIB::Compiler;
+use Net::SNMP qw(oid_lex_sort);
+
+use Data::Dumper;
+
+sub get_mib() {
+
+ my $compiled_dir = "/usr/local/share/inf/mibs/compiled";
+ my $mibname = 'PowerNet-MIB';
+
+ mkdir $compiled_dir;
+
+ my $mib = new SNMP::MIB::Compiler;
+ $mib->add_path('/usr/local/share/inf/mibs');
+ $mib->add_extension('.mib');
+ $mib->repository($compiled_dir);
+ $mib->{'accept_smiv1'} = 1;
+ $mib->{'accept_smiv2'} = 1;
+ $mib->{'make_dump'} = 1;
+ $mib->{'use_dump'} = 1;
+ $mib->{'do_imports'} = 1;
+ die "can't load" unless $mib->compile($mibname);
+
+ return $mib;
+}
+
+my $mib = get_mib();
+
+sub name_to_oid(@) {
+
+ my (@name) = (@_);
+
+ my @ocmp = ();
+
+ for my $cmp (@name) {
+ push @ocmp, $mib->resolve_oid($cmp);
+ }
+
+ return join( '.', @ocmp );
+}
+
+sub oid_to_name($) {
+ my $oid = shift;
+
+ $mib->convert_oid($oid);
+}
+
+sub get_snmp($$) {
+ my ( $host, $cmty ) = @_;
+
+ my ( $session, $error ) = Net::SNMP->session(
+ -hostname => $host,
+ -community => $cmty,
+ -port => 161,
+ -localport => 32130
+ );
+
+ if ( !defined($session) ) {
+ printf( "ERROR: %s.\n", $error );
+ exit 1;
+ }
+
+ return $session;
+}
+
+sub short_name($) {
+ my $name = shift;
+ my @s = split( /\./, $name );
+ my @n = ();
+
+ do {
+ $node = pop @s;
+ unshift @n, $node;
+ return $toid unless ( defined $node );
+ } until ( defined $mib->{nodes}->{$node} );
+
+ return join( '.', @n );
+}
+
+sub expand_enum($$) {
+ my ( $oid_name, $value ) = @_;
+ my @s = split( /\./, $oid_name );
+
+ do {
+ $node = pop @s;
+ return $value unless ( defined $node );
+ } until ( defined $mib->{nodes}->{$node} );
+
+ return $value unless ( $mib->{nodes}->{$node}->{type} eq 'OBJECT-TYPE' );
+
+ return $value
+ unless ( $mib->{nodes}->{$node}->{syntax}->{type} eq 'INTEGER' );
+
+ return $value
+ unless ( defined $mib->{'nodes'}->{$node}->{syntax}->{values}->{$value} );
+ return $mib->{'nodes'}->{$node}->{syntax}->{values}->{$value};
+
+}
+
+sub lookup_enum($$) {
+ my ( $oid_name, $value ) = @_;
+ my @s = split( /\./, $oid_name );
+
+ do {
+ $node = pop @s;
+ return $value unless ( defined $node );
+ } until ( defined $mib->{nodes}->{$node} );
+
+ return $value unless ( $mib->{nodes}->{$node}->{type} eq 'OBJECT-TYPE' );
+
+ return $value
+ unless ( $mib->{nodes}->{$node}->{syntax}->{type} eq 'INTEGER' );
+
+ for my $i ( keys %{ $mib->{'nodes'}->{$node}->{syntax}->{values} } ) {
+ return $i
+ if ( $mib->{'nodes'}->{$node}->{syntax}->{values}->{$i} =~ /$value/ );
+ }
+ return $value;
+
+}
+
+sub show_results($) {
+ my ($result) = @_;
+ my $v = undef;
+
+ for my $oid ( oid_lex_sort( keys( %{$result} ) ) ) {
+ my $name = oid_to_name($oid);
+ $v = expand_enum( $name, $result->{$oid} );
+
+ # print "oid=$oid\n";
+ print short_name($name);
+ print " => ";
+ print $v;
+ print "\n";
+ }
+ return $v;
+}
+
+my $mib = get_mib();
+
+sub get {
+ my $self = shift;
+
+ # print "Getting ",join('.',@_),"\n";
+
+ my $oid = name_to_oid(@_);
+
+ my $name = oid_to_name($oid);
+
+ my $result = $self->{snmp}->get_request( -varbindlist => [$oid] );
+
+ my @keys = keys %$result;
+
+ if ( scalar(@keys) != 1 ) {
+ return undef;
+ }
+
+ my $value = $result->{ $keys[0] };
+
+ $value = expand_enum( $name, $value );
+
+ return $value;
+}
+
+sub set {
+ my $self = shift;
+ my $value = shift;
+ my $type = shift;
+
+ my $oid = name_to_oid(@_);
+ my $vbl = [ ( $oid, $type, $value ) ];
+
+ # print Dumper($vbl),oid_to_name($oid),"\n";
+
+ my $result = $self->{snmp}->set_request( -varbindlist => $vbl );
+
+ return $result;
+}
+
+sub show {
+ my $self = shift;
+
+ my $oid = name_to_oid(@_);
+
+ my $name = oid_to_name($oid);
+
+ my $result = $self->{snmp}->get_request( -varbindlist => [$oid] );
+
+ show_results($result);
+}
+
+sub name_get($) {
+ my $self = shift;
+ my $ret;
+
+ if ( $self->{vmunit} ) {
+ return $self->get( 'sPDUMasterConfigVMName', $self->{vmunit} );
+ }
+
+ for my $node ('rPDUIdentName') {
+ $ret = $self->get( $node, '0' );
+ return $ret if ( defined $ret );
+ }
+ return undef;
+}
+
+sub name_set($$) {
+ my ( $self, $name ) = @_;
+
+ if ( $self->{vmunit} ) {
+ return $self->set( $name, Net::SNMP::OCTET_STRING,
+ 'sPDUMasterConfigVMName', $self->{vmunit} );
+ }
+
+ for my $node ('rPDUIdentName') {
+ $ret = $self->get( $node, '0' );
+ if ( defined $ret ) {
+ return $self->set( $name, Net::SNMP::OCTET_STRING, $node, '0' );
+ }
+ }
+ return undef;
+
+}
+
+sub port_count($) {
+ my $self = shift;
+ my $ret;
+
+ if ( $self->{vmunit} ) {
+ return $self->get( 'sPDUMasterStatusVMOutletCount', $self->{vmunit} );
+ }
+
+ for my $node ( 'sPDUOutletConfigTableSize', 'rPDUOutletDevNumCntrlOutlets' )
+ {
+ $ret = $self->get( $node, '0' );
+ return $ret if ( defined $ret );
+ }
+
+ return 8;
+}
+
+sub port_id_get_by_number($) {
+ my ( $self, $i ) = @_;
+ return $i;
+}
+
+sub port_name_get($$) {
+ my ( $self, $i ) = @_;
+ my $ret;
+
+ if ( $self->{vmunit} ) {
+ return $self->get( 'sPDUOutletConfigVMOutletName', $self->{vmunit}, 1,
+ $i );
+ }
+
+ for my $node ( 'rPDUOutletConfigOutletName', 'sPDUOutletName' ) {
+ $ret = $self->get( $node, $i );
+ return $ret if ( defined $ret );
+ }
+ return undef;
+}
+
+sub port_name_set($$$) {
+ my ( $self, $i, $name ) = @_;
+
+ if ( $self->{vmunit} ) {
+ return $self->set( $name, Net::SNMP::OCTET_STRING,
+ 'sPDUOutletConfigVMOutletName',
+ $self->{vmunit}, 1, $i );
+ }
+
+ for my $node ( 'rPDUOutletConfigOutletName', 'sPDUOutletName' ) {
+ $ret = $self->get( $node, $i );
+ if ( defined $ret ) {
+ return $self->set( $name, Net::SNMP::OCTET_STRING, $node, $i );
+ }
+ }
+ return undef;
+}
+
+sub port_state_get_no_cache($$) {
+
+ my ( $self, $i ) = @_;
+ my $ret;
+
+ if ( $self->{vmunit} ) {
+ return $self->get( 'sPDUOutletStatusVMOutletState', $self->{vmunit}, 1,
+ $i );
+ }
+
+ for my $node ( 'rPDUOutletStatusOutletState', 'sPDUOutletCtl' ) {
+ $ret = $self->get( $node, $i );
+ return $ret if ( defined $ret );
+ }
+ return undef;
+}
+
+sub port_state_get($$) {
+ my ( $self, $i ) = @_;
+ return $self->port_state_get_no_cache($i);
+}
+
+sub port_state_set($$$) {
+ my ( $self, $i, $state ) = @_;
+
+ my $ret;
+
+ if ( $self->{vmunit} ) {
+ my $ret = $self->get( 'sPDUOutletControlVMOutletCommand',
+ $self->{vmunit}, 1, $i );
+ my $oid = name_to_oid( 'sPDUOutletControlVMOutletCommand',
+ $self->{vmunit}, 1, $i );
+ my $name = oid_to_name($oid);
+
+ if ( defined $ret ) {
+ my $v = lookup_enum( $name, $state );
+ return undef if ( not defined $v );
+ return undef if ( int($v) ne $v );
+ return $self->set( $v, Net::SNMP::INTEGER,
+ 'sPDUOutletControlVMOutletCommand',
+ $self->{vmunit}, 1, $i );
+ }
+
+ return undef;
+ }
+
+ for my $node ( 'rPDUOutletControlOutletCommand', 'sPDUOutletCtl' ) {
+ my $ret = $self->get( $node, $i );
+ my $oid = name_to_oid( $node, $i );
+ my $name = oid_to_name($oid);
+
+ if ( defined $ret ) {
+ my $v = lookup_enum( $name, $state );
+
+ # print "lookup of state=$state gave value=$v\n";
+ return undef if ( not defined $v );
+ return undef if ( int($v) ne $v );
+ return $self->set( $v, Net::SNMP::INTEGER, $node, $i );
+ }
+
+ }
+ return undef;
+}
+
+sub port_cycle($$) {
+ my ( $self, $i ) = @_;
+ my $ret;
+
+ for my $cmd ( 'immediateReboot', 'outletReboot', 'immediateRebootVM' ) {
+ $ret = $self->set_outlet_state( $i, $cmd );
+ return $ret if ( defined $ret );
+ }
+ return undef;
+}
+
+sub port_off($$) {
+ my ( $self, $i ) = @_;
+ my $ret;
+
+ for my $cmd ( 'immediateOff', 'outletOff', 'immediateOffVM' ) {
+ $ret = $self->set_outlet_state( $i, $cmd );
+ return $ret if ( defined $ret );
+ }
+ return undef;
+}
+
+sub port_on($$) {
+ my ( $self, $i ) = @_;
+ my $ret;
+
+ for my $cmd ( 'immediateOn', 'outletOn', 'immediateOnVM' ) {
+ $ret = $self->set_outlet_state( $i, $cmd );
+ return $ret if ( defined $ret );
+ }
+ return undef;
+
+}
+
+sub pdu_load_get($) {
+ my $self = shift;
+ my $l;
+
+ if ( $self->{vmunit} ) {
+ $l = $self->get( 'sPDUMasterStatusVMCurrentLoad', $self->{vmunit} );
+ }
+ else {
+ $l = $self->get( 'rPDULoadStatusLoad', '1' );
+ }
+ return undef unless ( defined $l );
+ return ( 1.0 * $l ) / 10.0;
+}
+
+sub psu_status($) {
+ my $self = shift;
+
+ my $v;
+ my @vr = ();
+ my $ok = 'Ok';
+ my $unk = 'Unknown';
+
+ $v = $self->get( 'rPDUPowerSupply1Status', '0' );
+ if ( defined $v ) {
+ $ok = 'Sick' if ( $v ne 'powerSupplyOneOk' );
+ push @vr, $v;
+ $unk = undef;
+ }
+
+ $v = $self->get( 'rPDUPowerSupply2Status', '0' );
+ if ( defined $v ) {
+ $ok = 'Sick' if ( $v ne 'powerSupplyTwoOk' );
+ push @vr, $v;
+ $unk = undef;
+ }
+
+ $v = $self->get( 'rPDUPowerSupplyAlarm', '0' );
+ if ( defined $v ) {
+ $ok = 'Sick' if ( $v ne 'allAvailablePowerSuppliesOK' );
+ push @vr, $v;
+ $unk = undef;
+ }
+
+ return $unk if ( defined $unk );
+
+ return $ok . "(" . join( ' ', @vr ) . ")";
+
+}
+
+sub show_oid {
+ my $self = shift;
+ my $baseoid = name_to_oid(@_);
+
+ my $result = $self->{snmp}->get_table( -baseoid => $baseoid );
+
+ show_results($result);
+}
+
+sub show_all($) {
+ my $self = shift;
+
+ $self->show_oid('apc');
+
+}
+
+# my ( $mib, $snmp, $basename ) = @_;
+#
+# $baseoid=resolve($mib,$basename);
+#
+# my $result = $snmp->get_table( -baseoid => $baseoid );
+#
+# results($mib,$result);
+#}
+
+#sub status_show($) {
+# my $self = shift;
+#
+# $n = $self->get_n_outlets();
+#
+# print $self->{host}, " thinks it's called ", $self->get_name(), "\n";
+# print "has ", $n, " outlets\n";
+#
+# for ( my $i = 1 ; $i <= $n ; ++$i ) {
+# print "outlet $i is called ", $self->get_outlet_name($i), " and is ",
+# $self->get_outlet_status($i), "\n";
+# }
+#
+# my $l = $self->get_load;
+# if ( defined $l ) {
+# $l = $l . ' Amps';
+# }
+# else {
+# $l = 'Unknown';
+# }
+#
+# print "load ", $l, "\n";
+#
+# print "PSU status ", $self->get_psu_status(), "\n";
+#
+#}
+
+sub new ($;$) {
+ my ( $class, $parm ) = @_;
+ my $self;
+
+ $self->{host} = $parm->{host} || "redbus-ms20.mythic-beasts.com";
+ $self->{community} = $parm->{community} || "private";
+
+ if ( $self->{host} =~ /^(.*):(.*)$/ ) {
+ $self->{iphost} = $1;
+ $self->{vmunit} = $2;
+ }
+ else {
+ $self->{iphost} = $self->{host};
+ }
+
+ $self->{snmp} = get_snmp( $self->{iphost}, $self->{community} );
+
+ return bless $self, $class;
+}
+
+1;