summaryrefslogtreecommitdiffstats
path: root/INF/DSRx020.pm
diff options
context:
space:
mode:
Diffstat (limited to 'INF/DSRx020.pm')
-rw-r--r--INF/DSRx020.pm635
1 files changed, 635 insertions, 0 deletions
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();
+