aboutsummaryrefslogtreecommitdiffstats
path: root/doc
Commit message (Expand)AuthorAgeFilesLines
...
* Add raw sources of tutorial 'How to simulate an UART VHDL code with ghdl}' by...1138-4EB2017-12-1044-2/+3510
* Remove duplicated option1138-4EB2017-12-101-8/+2
* Add reference issues for docker1138-4EB2017-12-101-0/+4
* Describe commands as options. Fix internal refs to options. Apply1138-4EB2017-12-108-363/+310
* Meta.rst added to changelog1138-4EB2017-12-103-4/+23
* Files in the root not capitalized.1138-4EB2017-12-1011-894/+556
* Remove scrollbar in small screens1138-4EB2017-12-105-54/+25
* Add theme_overrrides.css1138-4EB2017-12-1017-487/+563
* README.md, index, WhatIsVHDL, WhatIsGHDL ready for review.1138-4EB2017-12-1012-112/+124
* Allow markdown1138-4EB2017-12-1013-290/+194
* Update README.md with shield, pros/cons table...1138-4EB2017-12-101-21/+0
* Move split ols txts to doc/oldmds. Add shields to README. Change target of li...1138-4EB2017-12-109-8/+386
* Remove <topic> from TODOs1138-4EB2017-12-106-26/+30
* Fix changelog1138-4EB2017-12-103-7/+8
* Add dots to TODOs1138-4EB2017-12-108-32/+10
* Removed numbers from folder names.1138-4EB2017-12-1026-28/+0
* File extensions must be rst, not rst.txt1138-4EB2017-12-108-9/+91
* Moving old content to new structure1138-4EB2017-12-1021-2715/+2952
* Moved introduction text.Patrick Lehmann2017-12-101-14/+12
* Added Python (PIP) requirements file. Request Sphinx >= 1.5.2.Patrick Lehmann2017-12-102-1/+6
* Fixed used theme to allow local building.Patrick Lehmann2017-12-101-1/+1
* New documentation structure for GHDL.Patrick Lehmann2017-12-1039-25/+688
* add gen-depends commandJulius Rakow2017-09-301-0/+14
* Fix wave-opt option names in doc.Tristan Gingold2017-09-051-2/+2
* Add doc/requirements.txtTristan Gingold2017-02-191-0/+1
* Regenerate ghdl.texiTristan Gingold2017-02-181-108/+236
* doc/conf.py: get version from git describeTristan Gingold2017-02-181-11/+10
* Doc: fix sphinx diagnostic about duplicate option.Tristan Gingold2017-02-181-2/+4
* doc/conf.py: add traces to investigate RTD builds.Tristan Gingold2017-02-181-0/+3
* doc/conf.py: tabifyTristan Gingold2017-02-181-1/+1
* doc/conf.py: set version in case of failure.Tristan Gingold2017-02-181-3/+3
* Fix #2211138-4EB2017-02-181-3/+11
* Add color diagnostics, show diagnostic option.Tristan Gingold2017-02-061-2/+36
* get documentation version from latest Git tag.Patrick Lehmann2016-12-101-4/+17
* Use -fpic if gcc is configured with --enable-default-pieTristan Gingold2016-12-061-1/+13
* Support added for * and **. Please note that wildcards inside names like /top...Jonas Baggett2016-11-021-4/+22
* There is a new --write-opt-file option that will create a wave option file wi...Jonas Baggett2016-11-011-1/+18
* doc: clarify -e/-r and --wor
#!/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 $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;