From dafb8e9f1b0c0d7cfe092ddb467a7650109efb51 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 17 Mar 2014 11:20:42 +0000 Subject: fish --- INF/DSRx020.pm | 635 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 635 insertions(+) create mode 100644 INF/DSRx020.pm (limited to 'INF/DSRx020.pm') 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(); + -- cgit v1.2.3