From 3208e62b382f08a9ec6e2c44e0afcca12162acda Mon Sep 17 00:00:00 2001 From: root Date: Wed, 1 Sep 2021 09:25:25 +0100 Subject: add power controll to asrock, fix bug in supermicro, rename ilo -> ilo4 --- INF.pm | 6 +- INF/ASRock.pm | 70 ++++---- INF/ILO.pm | 472 ------------------------------------------------------ INF/ILO4.pm | 472 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ INF/ILO5.pm | 2 - INF/SuperMicro.pm | 5 + Makefile | 2 +- 7 files changed, 511 insertions(+), 518 deletions(-) delete mode 100644 INF/ILO.pm create mode 100644 INF/ILO4.pm diff --git a/INF.pm b/INF.pm index 47e381e..ab247b8 100644 --- a/INF.pm +++ b/INF.pm @@ -2,7 +2,7 @@ package INF; use INF::APC; use INF::DSRx020; use INF::ILO2; -use INF::ILO; #ilo 4 confusingly +use INF::ILO4; use INF::ILO5; use INF::SuperMicro; use INF::ASRock; @@ -45,10 +45,10 @@ sub new ($;$) { return INF::ILO2->new($inf); } elsif ( $inf->{inf_type} eq 'ilo' ) { - return INF::ILO->new($inf); + return INF::ILO4->new($inf); } elsif ( $inf->{inf_type} eq 'ilo4' ) { - return INF::ILO->new($inf); + return INF::ILO4->new($inf); } elsif ( $inf->{inf_type} eq 'ilo5' ) { return INF::ILO5->new($inf); diff --git a/INF/ASRock.pm b/INF/ASRock.pm index 9ae247f..d13e564 100644 --- a/INF/ASRock.pm +++ b/INF/ASRock.pm @@ -45,8 +45,6 @@ sub login($) { $self->{csrftoken} = $json->{CSRFToken}; - print "csrftoken " . $self->{csrftoken} . "\n"; - return 0; } @@ -135,33 +133,24 @@ sub get_host_power($) { $self->login() unless defined $self->{logged_in}; - my $post = POST( $self->{bmc_url} . '/cgi/ipmi.cgi' ); - my $form_content = 'op=POWER_INFO.XML&r=(0%2C0)'; + my $get = GET( $self->{bmc_url} . '/api/chassis-status' ); - $post->header( 'Content-Type' => 'application/x-www-form-urlencoded' ); - $post->header( 'Content-Length' => length($form_content) ); - $post->content($form_content); + $get->header( 'X-CSRFTOKEN' => $self->{csrftoken} ); + $get->header( 'Cookie' => 'lang=en-us' ); - my $res = $self->{ua}->request($post); + my $res = $self->{ua}->request($get); unless ( $res->is_success ) { print STDERR " get host power - did not get 200\n"; return undef; } - my $xml = new XML::Simple; - - my $c = $res->content; - - $c =~ s/^[\s\n\r]+//s; - - my $data = $xml->XMLin($c); + my $json = decode_json( $res->content ); - return undef unless defined $data->{'POWER_INFO'}; - return undef unless defined $data->{'POWER_INFO'}->{'POWER'}; - return undef unless defined $data->{'POWER_INFO'}->{'POWER'}->{'STATUS'}; + return "ON" if $json->{power_status} == "1"; + return "OFF" if $json->{power_status} == "0"; - return $data->{'POWER_INFO'}->{'POWER'}->{'STATUS'}; + return undef; } sub set_host_power($$) { @@ -169,13 +158,17 @@ sub set_host_power($$) { $self->login() unless defined $self->{logged_in}; - my $post = POST( $self->{bmc_url} . '/cgi/ipmi.cgi' ); - my $form_content = 'op=POWER_INFO.XML&r=(1%2C' . $what . ')'; + my $payload = '{"power_command":' . $what . '}'; - $post->header( 'Content-Type' => 'application/x-www-form-urlencoded' ); - $post->header( 'Content-Length' => length($form_content) ); - $post->content($form_content); + my $post = POST( $self->{bmc_url} . '/api/actions/power' ); + + $post->header( 'X-CSRFTOKEN' => $self->{csrftoken} ); + $post->header( 'Cookie' => 'lang=en-us' ); + $post->header( 'Content-Type' => 'application/json' ); + $post->header( 'Content-Length' => length($payload) ); + $post->content($payload); + my $res = $self->{ua}->request($post); unless ( $res->is_success ) { @@ -183,44 +176,35 @@ sub set_host_power($$) { return 0; } - my $xml = new XML::Simple; - - my $c = $res->content; - - $c =~ s/^[\s\n\r]+//s; - - my $data = $xml->XMLin($c); - - return 0 unless defined $data->{'POWER_INFO'}; - return 0 unless defined $data->{'POWER_INFO'}->{'POWER'}; - return 0 unless defined $data->{'POWER_INFO'}->{'POWER'}->{'STATUS'}; + my $json = decode_json( $res->content ); + return 0 unless defined $json->{power_command}; return 1; } sub reset($) { my $self = shift; - return $self->set_host_power('0'); + return $self->set_host_power('3'); } sub port_off($) { my $self = shift; - return $self->set_host_power('1'); + return $self->set_host_power('0'); } sub orderly_shutdown($) { my $self = shift; - return $self->set_host_power('2'); + return $self->set_host_power('5'); } sub port_on($) { my $self = shift; - return $self->set_host_power('3'); + return $self->set_host_power('1'); } sub port_cycle($) { my $self = shift; - return $self->set_host_power('5'); + return $self->set_host_power('2'); } sub port_state_get($$) { @@ -228,6 +212,12 @@ sub port_state_get($$) { return $self->get_host_power(); } +sub port_state_get_no_cache($$) { + my $self = shift; + return $self->get_host_power(); +} + + sub port_name_get($$) { my $self = shift; return $self->{name}; diff --git a/INF/ILO.pm b/INF/ILO.pm deleted file mode 100644 index 577d0c6..0000000 --- a/INF/ILO.pm +++ /dev/null @@ -1,472 +0,0 @@ -#!/usr/bin/env perl - -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; - -#IO::Socket::SSL::set_ctx_defaults( SSL_verify_mode => SSL_VERIFY_NONE ); -IO::Socket::SSL::set_ctx_defaults( - SSL_verify_mode => Net::SSLeay::VERIFY_NONE() ); - -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 setup_port_proxy($$$$) { - my ( $self, $local_port, $remote_host, $remote_port ) = @_; - - my $child = fork(); - - my $cmd = [ - "balance", "-d", "-f", "-b", "127.0.0.1", $local_port, - $remote_host . ":" . $remote_port - ]; - - print STDERR "PROXY CMD: " . join( ' ', @$cmd ) . "\n"; - - if ( $child == 0 ) { - - if ( defined $self->{proxy_host} ) { - my $tmp = File::Temp->new( UNLINK => 0, SUFFIX => '.cnf' ); - - select( ( select($tmp), $| = 1 )[0] ); - - print $tmp "server = 127.0.0.1\n"; - print $tmp "server_port = " . $self->{proxy_port} . "\n"; - print $tmp "local = 127.0.0.0/255.0.0.0\n"; - - $ENV{'LD_PRELOAD'} = 'libtsocks.so'; - $ENV{'TSOCKS_CONF_FILE'} = $tmp->filename; - - print "Filename is $tmp->filename\n"; - } - - exec(@$cmd); - print STDERR "failed to start port proxy"; - sleep(10000); - } - - sleep(4); - - 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} }, - $self->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} }, - $self->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 $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', - 'Cookie' => 'sessionKey=' . $self->{skey} - ); - - 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 = "" . $content . ""; - - $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( - "echo", - "appletviewer", - "-J-Djava.security.manager", - - # "-J-Djava.security.debug=access,failure,policy", - "-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" - ); - - system( - "appletviewer", - "-J-Djava.security.manager", - - # "-J-Djava.security.debug=access,failure,policy", - "-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 logout($) { - my $self = shift; -} - -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 => SSL_VERIFY_NONE, - SSL_verify_mode => Net::SSLeay::VERIFY_NONE(), - verify_hostname => 0, - ); - - if ( defined $parm->{proxy_host} ) { - $self->{ua}->proxy( [qw(http https)] => "socks://" - . $parm->{proxy_host} . ":" - . $parm->{proxy_port} ); - $self->{proxy_host} = $parm->{proxy_host}; - $self->{proxy_port} = $parm->{proxy_port}; - } - - 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', - SSL_verify_mode => Net::SSLeay::VERIFY_NONE(), - ], - ); - $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; - diff --git a/INF/ILO4.pm b/INF/ILO4.pm new file mode 100644 index 0000000..3f76ac9 --- /dev/null +++ b/INF/ILO4.pm @@ -0,0 +1,472 @@ +#!/usr/bin/env perl + +package INF::ILO4; + +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; + +#IO::Socket::SSL::set_ctx_defaults( SSL_verify_mode => SSL_VERIFY_NONE ); +IO::Socket::SSL::set_ctx_defaults( + SSL_verify_mode => Net::SSLeay::VERIFY_NONE() ); + +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 setup_port_proxy($$$$) { + my ( $self, $local_port, $remote_host, $remote_port ) = @_; + + my $child = fork(); + + my $cmd = [ + "balance", "-d", "-f", "-b", "127.0.0.1", $local_port, + $remote_host . ":" . $remote_port + ]; + + print STDERR "PROXY CMD: " . join( ' ', @$cmd ) . "\n"; + + if ( $child == 0 ) { + + if ( defined $self->{proxy_host} ) { + my $tmp = File::Temp->new( UNLINK => 0, SUFFIX => '.cnf' ); + + select( ( select($tmp), $| = 1 )[0] ); + + print $tmp "server = 127.0.0.1\n"; + print $tmp "server_port = " . $self->{proxy_port} . "\n"; + print $tmp "local = 127.0.0.0/255.0.0.0\n"; + + $ENV{'LD_PRELOAD'} = 'libtsocks.so'; + $ENV{'TSOCKS_CONF_FILE'} = $tmp->filename; + + print "Filename is $tmp->filename\n"; + } + + exec(@$cmd); + print STDERR "failed to start port proxy"; + sleep(10000); + } + + sleep(4); + + 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} }, + $self->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} }, + $self->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 $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', + 'Cookie' => 'sessionKey=' . $self->{skey} + ); + + 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 = "" . $content . ""; + + $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( + "echo", + "appletviewer", + "-J-Djava.security.manager", + + # "-J-Djava.security.debug=access,failure,policy", + "-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" + ); + + system( + "appletviewer", + "-J-Djava.security.manager", + + # "-J-Djava.security.debug=access,failure,policy", + "-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 logout($) { + my $self = shift; +} + +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 => SSL_VERIFY_NONE, + SSL_verify_mode => Net::SSLeay::VERIFY_NONE(), + verify_hostname => 0, + ); + + if ( defined $parm->{proxy_host} ) { + $self->{ua}->proxy( [qw(http https)] => "socks://" + . $parm->{proxy_host} . ":" + . $parm->{proxy_port} ); + $self->{proxy_host} = $parm->{proxy_host}; + $self->{proxy_port} = $parm->{proxy_port}; + } + + 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', + SSL_verify_mode => Net::SSLeay::VERIFY_NONE(), + ], + ); + $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; + diff --git a/INF/ILO5.pm b/INF/ILO5.pm index f406762..d2689fd 100644 --- a/INF/ILO5.pm +++ b/INF/ILO5.pm @@ -210,7 +210,6 @@ sub login($) { $self->{skey} = undef; return -1; } - print STDERR "Login good!\n"; my $json = decode_json( $res->content ); @@ -320,7 +319,6 @@ sub get_host_power($) { my $state = decode_json $res->content; return $state->{'hostpwr_state'}; - } sub set_host_power($$) { diff --git a/INF/SuperMicro.pm b/INF/SuperMicro.pm index 7284826..121d36a 100644 --- a/INF/SuperMicro.pm +++ b/INF/SuperMicro.pm @@ -226,6 +226,11 @@ sub port_state_get($$) { return $self->get_host_power(); } +sub port_state_get_no_cache($$) { + my $self = shift; + return $self->get_host_power(); +} + sub port_name_get($$) { my $self = shift; return $self->{name}; diff --git a/Makefile b/Makefile index b5b6696..51202d8 100644 --- a/Makefile +++ b/Makefile @@ -16,8 +16,8 @@ install: install -m 644 INF/INF.pm /usr/local/share/inf/INF install -m 644 INF/APC.pm /usr/local/share/inf/INF install -m 644 INF/DSRx020.pm /usr/local/share/inf/INF - install -m 644 INF/ILO.pm /usr/local/share/inf/INF install -m 644 INF/ILO2.pm /usr/local/share/inf/INF + install -m 644 INF/ILO4.pm /usr/local/share/inf/INF install -m 644 INF/ILO5.pm /usr/local/share/inf/INF install -m 644 INF/Cyclades.pm /usr/local/share/inf/INF install -m 644 INF/SuperMicro.pm /usr/local/share/inf/INF -- cgit v1.2.3