summaryrefslogtreecommitdiffstats
path: root/INF
diff options
context:
space:
mode:
authorJames <git@panaceas.org>2014-03-17 11:20:42 +0000
committerJames <git@panaceas.org>2014-03-17 11:20:42 +0000
commitdafb8e9f1b0c0d7cfe092ddb467a7650109efb51 (patch)
treeb04072f8ab91f058c8fc3541367ed9524d543181 /INF
downloadinf-dafb8e9f1b0c0d7cfe092ddb467a7650109efb51.tar.gz
inf-dafb8e9f1b0c0d7cfe092ddb467a7650109efb51.tar.bz2
inf-dafb8e9f1b0c0d7cfe092ddb467a7650109efb51.zip
fish
Diffstat (limited to 'INF')
-rw-r--r--INF/APC.pm504
-rw-r--r--INF/DSRx020.pm635
2 files changed, 1139 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;
diff --git a/INF/DSRx020.pm b/INF/DSRx020.pm
new file mode 100644
index 0000000..591f367
--- /dev/null
+++ b/INF/DSRx020.pm
@@ -0,0 +1,635 @@
+#!/usr/bin/env perl
+
+IO::Socket::SSL::set_ctx_defaults( SSL_verify_mode => SSL_VERIFY_NONE );
+
+package INF::DSRx020;
+
+use IO::Socket::SSL qw();
+use HTML::TreeBuilder;
+use HTTP::Request::Common;
+use LWP::UserAgent;
+use URI::Escape;
+use File::Temp qw/ tempfile tempdir /;
+use XML::Simple;
+use Data::Dumper;
+
+my $prefix = "/usr/local/share/inf/avocent/";
+
+my $jars = [
+ $prefix . "avctLinuxLib.jar",
+ $prefix . "avctMacOSXLib.jar",
+ $prefix . "avctSolarisLib.jar",
+ $prefix . "avctVideo.jar",
+ $prefix . "avctVM.jar",
+ $prefix . "avctWin32Lib.jar",
+ $prefix . "avmLinuxLib.jar",
+ $prefix . "avmMacOSXLib.jar",
+ $prefix . "avmSolarisLib.jar",
+ $prefix . "avmWin32Lib.jar",
+ $prefix . "jpcscdll.jar",
+ $prefix . "jpcscso.jar"
+];
+
+sub trim($) {
+ my $s = shift;
+
+ if ( defined $s ) {
+ $s =~ s/a^\s+//g;
+ $s =~ s/\s+$//g;
+ }
+
+ return $s;
+}
+
+sub flush($) {
+ my $self = shift;
+ delete $self->{names};
+ delete $self->{ports};
+ delete $self->{statuses};
+}
+
+sub login($) {
+ my $self = shift;
+
+ my $post = POST(
+ $self->{kvm_url} . 'file=login',
+ [
+ action => "SAVE",
+ saveParms => "login",
+ filename => "login",
+ spcDevice => "(NULL)",
+ spcSocket => "(NULL)",
+ spcInlet => "(NULL)",
+ userindex => "(NULL)",
+ id => "(NULL)",
+ index => "(NULL)",
+ loginUsername => $self->{user},
+ loginPassword => $self->{password},
+ htmlLanguage => '0'
+ ]
+ );
+
+ my $res = $self->{ua}->request($post);
+
+ unless ( $res->is_success ) {
+ print STDERR "Login failed - did not get 200\n";
+ $self->{uid} = undef;
+ return -1;
+ }
+ my $content = $res->content;
+
+ if ( $content =~ /errorMsg/ ) {
+ print STDERR "Login failed - invalid password\n";
+ $self->{uid} = undef;
+ return -1;
+ }
+
+ my $refresh = $res->headers->header('refresh');
+
+ unless ( $refresh =~ /userid=(\d+)$/i ) {
+ print STDERR "Login failed - no uid found\n";
+ $self->{uid} = undef;
+ return -1;
+ }
+
+ $self->{uid} = $1;
+
+ # print "userid = ", $self->{uid}, "\n";
+
+ return 0;
+}
+
+sub do_get($$) {
+ my ( $self, $args ) = @_;
+ my @uea;
+ my $url;
+
+ do {
+
+ $url = $self->{kvm_url};
+ @uea = ();
+
+ for my $key ( keys %$args ) {
+ push @uea, $key . '=' . uri_escape( $args->{$key} );
+ }
+ push @uea, 'userID=' . $self->{uid};
+
+ $url .= join( '&', @uea );
+
+ # print STDERR "get from url=$url\n";
+
+ my $get = GET($url);
+
+ my $res = $self->{ua}->request($get);
+
+ return undef unless $res->is_success;
+
+ return $res unless $res->content =~ /form name="loginForm"/;
+
+ return undef if $self->login;
+
+ } while (1);
+
+}
+
+sub do_post($$$) {
+ my ( $self, $args, $postargs ) = @_;
+ my @uea;
+ my $url;
+
+ do {
+
+ $url = $self->{kvm_url};
+ @uea = ();
+
+ for my $key ( keys %$args ) {
+ push @uea, $key . '=' . uri_escape( $args->{$key} );
+ }
+ push @uea, 'userID=' . $self->{uid};
+
+ $url .= join( '&', @uea );
+
+ # print STDERR "post to url=$url\n";
+
+ my $post = POST( $url, [ @{$postargs}, userID => $self->{uid} ] );
+
+ my $res = $self->{ua}->request($post);
+
+ return undef unless $res->is_success;
+
+ return $res unless $res->content =~ /form name="loginForm"/;
+
+ return undef if $self->login;
+
+ } while (1);
+
+}
+
+sub spc_set_power($$$$) {
+ my ( $self, $spc, $socket, $action ) = @_;
+
+ my $res = $self->do_post(
+ { file => 'overview-spc', spcDevice => $spc, spcSocket => $socket },
+ [
+ file => 'overview-spc',
+ saveParms => 'overview-spc',
+ spcDevice => $spc,
+ spcSocket => $socket,
+ action => $action,
+ ]
+ );
+
+ $self->flush();
+
+ #name=>Test+power+port
+ #oids=>','.$socket
+
+ return undef unless $res->is_success;
+
+ return "Success";
+}
+
+sub port_cycle($$) {
+ my ( $self, $port ) = @_;
+
+ if ( $port =~ /P(\d+)\.(\d+)/ ) {
+ return $self->spc_set_power( $1, $2, 'POWER_CYCLE' );
+ }
+ else {
+ return undef;
+ }
+}
+
+sub port_on($$) {
+ my ( $self, $port ) = @_;
+
+ if ( $port =~ /P(\d+)\.(\d+)/ ) {
+ return $self->spc_set_power( $1, $2, 'POWER_ON' );
+ }
+ else {
+ return undef;
+ }
+}
+
+sub port_off($$) {
+ my ( $self, $port ) = @_;
+
+ if ( $port =~ /P(\d+)\.(\d+)/ ) {
+ return $self->spc_set_power( $1, $2, 'POWER_OFF' );
+ }
+ else {
+ return undef;
+ }
+}
+
+sub spc_get_state($$$) {
+ my ( $self, $spc, $socket ) = @_;
+
+ my $res = $self->do_get(
+ { file => 'overview-spc', spcDevice => $spc, spcSocket => $socket } );
+
+ return undef unless defined $res;
+
+ my $tree = HTML::TreeBuilder->new;
+
+ $tree->parse( $res->content );
+
+ my $thing = $tree->look_down( 'id' => 'status-label-power-1' );
+
+ if ( not defined $thing ) {
+ $tree->delete;
+ return undef;
+ }
+
+ my $ret = "";
+ for my $c ( $thing->content_list ) {
+ $ret .= $c unless ref $c;
+ }
+
+ $tree->delete;
+
+ $ret = trim($ret);
+
+ return $ret;
+}
+
+sub spc_get_name($$$) {
+ my ( $self, $spc, $socket ) = @_;
+
+ my $res = $self->do_get(
+ { file => 'overview-spc', spcDevice => $spc, spcSocket => $socket } );
+
+ return undef unless defined $res;
+
+ my $tree = HTML::TreeBuilder->new;
+
+ $tree->parse( $res->content );
+
+ my $thing = $tree->look_down( 'name' => 'spcsocketname' );
+
+ if ( not defined $thing ) {
+ $tree->delete;
+ return undef;
+ }
+
+ my $ret = $thing->attr('value');
+
+ print "ret=$ret\n";
+
+ $tree->delete;
+
+ $ret = trim($ret);
+
+ return $ret;
+}
+
+sub spc_set_name($$$$) {
+ my ( $self, $spc, $socket, $name ) = @_;
+
+ my ( $self, $spc, $socket, $action ) = @_;
+
+ my $res = $self->do_post(
+ { file => 'overview-spc', spcDevice => $spc, spcSocket => $socket },
+ [
+ file => 'overview-spc',
+ saveParms => 'overview-spc',
+ spcDevice => $spc,
+ spcSocket => $socket,
+ spcsocketname => $name,
+ action => 'SAVE',
+ ]
+ );
+
+ $self->flush();
+
+ return undef unless $res->is_success;
+
+ return "Success";
+}
+
+sub elm_to_txt($) {
+ my $e = shift;
+ my $ret = "";
+ for my $c ( $e->content_list ) {
+ $ret .= $c unless ref $c;
+ }
+
+ return $ret;
+}
+
+sub elm_to_txt_with_spaces($) {
+ my $e = shift;
+ my $ret = "";
+ for my $c ( $e->content_list ) {
+ $ret .= $c unless ref $c;
+ $ret .= " ";
+ }
+ return $ret;
+}
+
+sub get_names($) {
+ my $self = shift;
+
+ my $res = $self->do_get( { file => 'view-units-by-target-devices' } );
+
+ return -1 unless defined $res;
+
+ my $tree = HTML::TreeBuilder->new;
+
+ $tree->parse( $res->content );
+
+ $self->{ports} = [];
+ $self->{names} = {};
+ $self->{statuses} = {};
+
+ for my $thing (
+ $tree->look_down(
+ 'title' =>
+'Unique name of target device. Clicking moves to the Unit Overview window for the TD.'
+ )
+ )
+ {
+
+ my $p = $thing->parent();
+ my $tr = $p->parent->parent;
+ my $href = $p->attr('href');
+
+ my $status = "";
+ my $name = elm_to_txt($thing);
+
+ for my $span (
+ $tr->look_down( sub { $_[0]->attr('id') =~ /status-label-unit/ } ) )
+ {
+ $status .= elm_to_txt_with_spaces($span);
+ }
+
+ $name = trim($name);
+ $status = trim($status);
+
+ $status =~ s/Idle/On/;
+
+ #print "href=$href name=$name\n";
+ #$p->dump();
+
+ if ( $href =~ /file=overview-spc.*spcDevice=(\d+)&spcSocket=(\d+)/ ) {
+ my $port = 'P' . $1 . '.' . $2;
+ push @{ $self->{ports} }, $port;
+ $self->{names}->{$port} = $name;
+ $self->{statuses}->{$port} = $status;
+ }
+
+ if ( $href =~ /file=overview-dsr.*index=(\d+)/ ) {
+ my $port = 'K' . $1;
+ push @{ $self->{ports} }, $port;
+ $self->{names}->{$port} = $name;
+ $self->{statuses}->{$port} = $status;
+ }
+
+ }
+
+ $tree->delete;
+
+ return 0;
+}
+
+sub port_name_set($$$) {
+ my ( $self, $port, $name ) = @_;
+
+ if ( $port =~ /P(\d+)\.(\d+)/ ) {
+ return $self->spc_set_name( $1, $2, $name );
+ }
+ else {
+ return undef;
+ }
+}
+
+sub port_state_get_no_cache($$) {
+ my ( $self, $port ) = @_;
+
+ if ( $port =~ /P(\d+)\.(\d+)/ ) {
+ return $self->spc_get_state( $1, $2 );
+ }
+ else {
+ return "Unknown";
+ }
+}
+
+sub port_state_get($$) {
+ my ( $self, $port ) = @_;
+ return $self->{statuses}->{$port} if defined $self->{statuses};
+ return $self->port_state_get_no_cache($port);
+}
+
+sub port_name_get($$) {
+ my ( $self, $port ) = @_;
+
+ return $self->{names}->{$port} if defined $self->{ports};
+ $self->get_names();
+ return $self->{names}->{$port};
+}
+
+sub port_id_get_by_number($$) {
+ my ( $self, $n ) = @_;
+ return $self->{ports}->[ $n - 1 ];
+}
+
+sub port_count($) {
+ my $self = shift;
+
+ return scalar( @{ $self->{ports} } ) if defined $self->{ports};
+
+ $self->get_names();
+ return scalar( @{ $self->{ports} } );
+}
+
+sub view($$) {
+ my ( $self, $port ) = @_;
+
+ return unless $port =~ /K(\d+)/;
+
+ my $res = $self->do_get(
+ {
+ file => 'jnlp',
+ index => $1
+ }
+ );
+
+ return undef unless defined $res;
+
+ my $xml = new XML::Simple;
+
+ my $c = $res->content;
+
+ $c =~ s/^[\s\n\r]+//s;
+
+ my $data = $xml->XMLin($c);
+
+ return undef unless defined $data->{'application-desc'};
+
+ my $args = $data->{'application-desc'}->{'argument'};
+
+ return undef unless defined $args;
+
+ my $cp = join( ':', @$jars );
+
+ mkdir $ENV{HOME} . "/.avocent_kvm";
+ chdir $ENV{HOME} . "/.avocent_kvm";
+
+#print join( ' ', ( "java", "-cp", $cp, "com.avocent.video.Stingray", @$args ) ), "\n";
+
+ system( "java", "-cp", $cp, "com.avocent.video.Stingray", @$args );
+
+}
+
+sub pdu_load_get($) {
+
+ my $self = shift;
+ my $ret = [];
+ my $res = $self->do_get( { file => 'view-spcs' } );
+
+ return undef unless defined $res;
+
+ my $tree = HTML::TreeBuilder->new;
+ $tree->parse( $res->content );
+
+ my $t1 = $tree->look_down( 'class' => 'list-filter-row' );
+ return undef unless defined $t1;
+ my $div = $t1->parent;
+ return undef unless defined $div;
+
+ my $tables = [];
+ for my $t ( $div->content_list ) {
+ next unless ref $t;
+ push @$tables, $t if $t->tag eq 'table';
+ }
+
+ my $t2 = $tables->[1];
+ return undef unless defined $t2;
+ my $t3 = [ $t2->look_down( "_tag" => 'table' ) ];
+
+ return undef unless scalar(@$t3) > 1;
+
+ my $table = $t3->[1];
+
+ return undef unless defined $table;
+
+ my $rows = [ $table->look_down( "_tag" => 'tr' ) ];
+ return undef unless scalar(@$rows) > 1;
+
+ my $r1 = [ $rows->[0]->look_down( "_tag" => 'td' ) ];
+ my $r2 = [ $rows->[1]->look_down( "_tag" => 'td' ) ];
+
+ for ( my $i = 0 ; $i < scalar(@$r1) ; ++$i ) {
+
+ my $title = $r1->[$i];
+ my $value = $r2->[$i];
+
+ next unless defined $title;
+ next unless defined $value;
+
+ $title = elm_to_txt($title);
+ $value = elm_to_txt($value);
+
+ trim($value);
+
+ push @$ret, $value . " " if $title =~ /current/i;
+ }
+
+ return join( ",", @$ret );
+}
+
+sub psu_status($) {
+ return undef;
+}
+
+sub name_get($) {
+ my $self = shift;
+
+ my $res = $self->do_get( { file => 'appliance-overview' } );
+
+ return undef unless defined $res;
+
+ my $tree = HTML::TreeBuilder->new;
+
+ $tree->parse( $res->content );
+
+ my $thing = $tree->look_down( 'name' => 'appliancename' );
+
+ return undef unless defined $thing;
+ my $ret = $thing->attr('value');
+
+ $tree->delete;
+
+ $ret = trim($ret);
+
+ return $ret;
+}
+
+sub name_set($$) {
+ my ( $self, $name ) = @_;
+
+ my $res = $self->do_post(
+ { file => 'appliance-overview' },
+ [
+ file => 'appliance-overview',
+ saveParms => 'appliance-overview',
+ appliancename => $name,
+ spcSocket => $socket,
+ action => 'SAVE',
+ ]
+ );
+
+ #name=>Test+power+port
+ #oid=>'148737',
+ #oids=>''
+
+ return -1 unless $res->is_success;
+
+ return 0;
+}
+
+sub new ($;$) {
+ my ( $class, $parm ) = @_;
+ my $self;
+
+ $self->{ua} = my $ua = LWP::UserAgent->new;
+
+ $self->{host} = $parm->{host} || "127.0.0.1";
+
+ $self->{user} = $parm->{user} || "Admin";
+ $self->{password} = $parm->{password} || "";
+
+ $self->{kvm_url} = $parm->{kvm_url}
+ || 'https://' . $self->{host} . '/cgi-bin/kvm.cgi?&';
+ $self->{userid} = undef;
+
+ $self->{ua}->ssl_opts(
+ SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
+ verify_hostname => 0,
+ );
+
+ return bless $self, $class;
+
+}
+
+1;
+
+#my $dsr = new DSRx020(
+# {
+# # host => 'https://freyja-brisingamen.uk.bromium.net',
+# #host => 'http://localhost:81',
+# host => 'https://10.32.95.20',
+# user => 'Admin',
+# password=>'Woow7See'
+# }
+#);
+#
+##$dsr->login();
+#
+##print "1.8 is called ", $dsr->spc_get_name( 1, 8 ), "\n";
+##print "1.8 is state ", $dsr->spc_get_state( 1, 8 ), "\n";
+##print "1.8 power off: ", $dsr->spc_power_off( 1, 8 ), "\n";
+##print "1.8 is state ", $dsr->spc_get_state( 1, 8 ), "\n";
+#
+#$dsr->get_names();
+