diff options
Diffstat (limited to 'INF/ILO.pm')
-rw-r--r-- | INF/ILO.pm | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/INF/ILO.pm b/INF/ILO.pm new file mode 100644 index 0000000..9af27c4 --- /dev/null +++ b/INF/ILO.pm @@ -0,0 +1,401 @@ +#!/usr/bin/env perl + +IO::Socket::SSL::set_ctx_defaults( SSL_verify_mode => SSL_VERIFY_NONE ); + +package INF::ILO; + +use HTTP::Daemon::SSL; +use HTTP::Server::Brick; +use HTTP::Status; + +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; +use JSON::PP; + +sub read_file($) { + my ($name) = @_; + + my $fh = new IO::File "<" . $name; + local $/; + my $guts = $fh->getline; + $fh->close; + undef $fh; + + return $guts; +} + +sub setup_port_proxy($$$) { + my ( $local_port, $remote_host, $remote_port ) = @_; + + my $child = fork(); + + print STDERR "balance ", + join( + ' ', + ( + "balance", "-d", "-f", "127.0.0.1", $local_port, + $remote_host . ":" . $remote_port + ) + ), + "\n"; + + if ( $child == 0 ) { + + exec( "balance", "-d", "-f", "-b", "127.0.0.1", $local_port, + $remote_host . ":" . $remote_port ); + print STDERR "failed to start port proxy"; + sleep(10000); + } + + print "Setup proxy $local_port -> $remote_host:$remote_port\n"; + + return $child; +} + +sub proxy($$$) { + my ( $self, $req, $res ) = @_; + + if ( $req->uri->as_string =~ /^\/html\/java_irc.html/ ) { + + $res->header( 'Content-type' => 'text/html' ); + $res->add_content( $self->{java_html} ); + $res->code(200); + + return; + + } + + if ( $req->uri->as_string =~ /^\/html\/intgapp_.*\.jar/ ) { + + $res->header( 'Content-type' => 'application/x-ms-application' ); + $res->add_content( + read_file('/usr/local/share/inf/ilo/intgapp_221.jar') ); + $res->code(200); + + return; + } + + my $proxy_req = + HTTP::Request->new( $req->method, $self->{ilo_url} . $req->uri->as_string, + [], $req->content ); + + $proxy_req->header( 'cookie' => 'sessionKey=' . $self->{skey} ); + + my $proxy_res = $self->{ua}->request($proxy_req); + + unless ( $proxy_res->is_success ) { + print STDERR "request failed - did not get 200\n"; + } + + print "URI:", $req->uri->as_string, " code ", $proxy_res->code, " type ", + $proxy_res->header('Content-type'), "\n"; + + $res->code( $proxy_res->code ); + $res->header( 'Content-type' => $proxy_res->header('Content-type') ); + + my $content = $proxy_res->content; + + if ( $req->uri->as_string =~ /^\/json\/rc_info/ ) { + + my $local_port = int( rand(30000) ) + 30000; + + $content =~ s/"rc_port":(\d+),/"rc_port":$local_port,/; + push @{ $self->{to_kill} }, + setup_port_proxy( $local_port, $self->{host}, $1 ); + + $local_port = int( rand(30000) ) + 30000; + + $content =~ s/"vm_port":(\d+),/"vm_port":$local_port,/; + push @{ $self->{to_kill} }, + setup_port_proxy( $local_port, $self->{host}, $1 ); + + } + + $res->add_content($content); + +} + +sub login($) { + my $self = shift; + + my $post = POST( $self->{ilo_url} . '/json/login_session' ); + my $json = + '{"method":"login","user_login":"' + . $self->{user} + . '","password":"' + . $self->{password} . '"}'; + + $post->header( 'Content-Type' => 'application/json' ); + $post->header( 'Content-Length' => length($json) ); + $post->content($json); + + #my $get = GET( $self->{ilo_url}."/html/login.html" ); + + my $res = $self->{ua}->request($post); + + unless ( $res->is_success ) { + print STDERR "Login failed - did not get 200\n"; + + print Dumper($res); + + $self->{skey} = undef; + return -1; + } + + my $json = decode_json( $res->content ); + + $self->{skey} = $json->{session_key}; + + # print "Session key ".$self->{skey}."\n"; + + return 0; +} + +sub view($) { + my $self = shift; + + $self->login() unless defined $self->{skey}; + + my $get = GET( $self->{ilo_url} . '/html/java_irc.html?lang=en' ); + + my $res = $self->{ua}->request($get); + + unless ( $res->is_success ) { + print STDERR "IRC frequest failed - did not get 200\n"; + return -1; + } + my $content = $res->content; + + unless ( $content =~ /Netscape'\) {(.*)}[\s\n]*else if/s ) { + print STDERR "returned html doesn't look right\n"; + return -1; + } + + $content = $1; + + #$content=~ s/document.writeln\("(.*)"\);$/\1/m; + $content =~ s/^\s*document.writeln\("(.*)"\);\s*$/\1/mg; + $content =~ s/\\//g; + + $content =~ s/RCINFO1=.*$/RCINFO1="$self->{skey}"/m; + $content =~ s/RCINFO6=.*$/RCINFO6="17990"/m; + $content =~ s/RCINFOLANG=.*$/RCINFOLANG="en"/m; + $content =~ s%(archive=)(/.*)$%\1$self->{proxy_url}\2%m; + + $content = "<html><head></head><body>" . $content . "</body></html>"; + + $self->{java_html} = $content; + + my $webserver_pid = fork(); + + if ( $webserver_pid == 0 ) { + $SIG{INT} = sub { kill 'KILL', ( @{ $self->{to_kill} } ); die; }; + $SIG{TERM} = sub { kill 'KILL', ( @{ $self->{to_kill} } ); die; }; + + $self->{server}->start; + print STDERR "failed to web server"; + sleep(100000); + } + + push @{ $self->{to_kill} }, $webserver_pid; + + $SIG{INT} = sub { kill 'INT', ( @{ $self->{to_kill} } ); die; }; + $SIG{TERM} = sub { kill 'TERM', ( @{ $self->{to_kill} } ); die; }; + + system( + "appletviewer", + "-J-Djava.security.manager", + "-J-Djava.security.policy=/usr/local/share/inf/ilo/mypolicy", + "-J-Djavax.net.ssl.trustStore=/usr/local/share/inf/ilo/server.jks", + $self->{proxy_url} . "/html/java_irc.html" + ); + + kill 'TERM', ( @{ $self->{to_kill} } ); +} + +sub get_host_power($) { + my ($self) = @_; + + $self->login() unless defined $self->{skey}; + + my $get = GET( $self->{ilo_url} . '/json/host_power' ); + + $get->header( 'cookie' => 'sessionKey=' . $self->{skey} ); + + my $res = $self->{ua}->request($get); + + unless ( $res->is_success ) { + print STDERR " get host power - did not get 200\n"; + return undef; + } + + my $state = decode_json $res->content; + + return $state->{'hostpwr_state'}; + +} + +sub set_host_power($$) { + my ( $self, $what ) = @_; + + $self->login() unless defined $self->{skey}; + + my $post = POST( $self->{ilo_url} . '/json/host_power' ); + my $json = + '{"method":"' . $what . '","session_key":"' . $self->{skey} . '"}'; + $post->header( 'Content-Type' => 'application/json' ); + $post->header( 'Content-Length' => length($json) ); + $post->content($json); + $post->header( 'cookie' => 'sessionKey=' . $self->{skey} ); + + my $res = $self->{ua}->request($post); + + unless ( $res->is_success ) { + print STDERR " $what - did not get 200\n"; + return 0; + } + + return 1; +} + +sub cold_boot($) { + my $self = shift; + return $self->set_host_power('system_coldboot'); +} + +sub reset($) { + my $self = shift; + return $self->set_host_power('system_reset'); +} + +sub off($) { + my $self = shift; + if ( $self->get_host_power =~ /ON/i ) { + return $self->set_host_power('hold_power_button'); + } + return 1; +} + +sub on($) { + my $self = shift; + if ( $self->get_host_power =~ /OFF/i ) { + return $self->set_host_power('press_power_button'); + } + return 1; +} + +sub port_on($$) { + my $self = shift; + return $self->on(); +} + +sub port_off($$) { + my $self = shift; + return $self->off(); +} + +sub port_cycle($$) { + my $self = shift; + return $self->cold_boot(); +} + +sub port_state_get_no_cache($$) { + my $self = shift; + return $self->get_host_power(); +} + +sub port_state_get($$) { + my $self = shift; + return $self->get_host_power(); +} + +sub port_name_get($$) { + my $self = shift; + return $self->{name}; +} + +sub name_get($) { + my $self = shift; + return $self->{name}; +} + +sub pdu_load_get($) { + return "N/A"; +} + +sub psu_status($) { + return "N/A"; +} + +sub port_count($) { + return 1; +} + +sub port_id_get_by_number($$) { + return "K0"; +} + +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} || "Administrator"; + $self->{password} = $parm->{password} || ""; + + $self->{name} = $parm->{name} || $self->{host}; + + $self->{ilo_url} = $parm->{ilo_url} + || 'https://' . $self->{host}; + $self->{userid} = undef; + + $self->{ua}->ssl_opts( + SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE, + verify_hostname => 0, + ); + + my + + $local_port = int( rand(30000) ) + 30000; + + $self->{proxy_url} = 'https://127.0.0.1:' . $local_port; + + $self->{server} = HTTP::Server::Brick->new( + port => $local_port, + daemon_class => 'HTTP::Daemon::SSL', + daemon_args => [ + LocalAddr => '127.0.0.1', + SSL_key_file => '/usr/local/share/inf/ilo/server.key', + SSL_cert_file => '/usr/local/share/inf/ilo/server.crt', + ], + ); + $self->{server}->mount( + '/' => { + handler => sub { + my ( $req, $res ) = @_; + + $self->proxy( $req, $res ); + 1; + }, + wildcard => 1, + } + ); + + $self->{skey} = undef; + $self->{to_kill} = []; + + return bless $self, $class; + +} + +1; + |