]> rtime.felk.cvut.cz Git - novaboot.git/commitdiff
Added support of Intel AMT
authorVaclav Fanfule <v.fanfule@gmail.com>
Mon, 3 Feb 2014 23:48:02 +0000 (00:48 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Fri, 14 Feb 2014 17:26:49 +0000 (18:26 +0100)
novaboot

index 0a79023ff033f0beeba7abaad6caffc51ce1b442..012acff268fbe93b57a1e397987271e9519db9e2 100755 (executable)
--- a/novaboot
+++ b/novaboot
@@ -28,6 +28,8 @@ use IPC::Open2;
 use POSIX qw(:errno_h);
 use Cwd qw(getcwd abs_path);
 use Expect;
+use LWP::UserAgent;
+use LWP::Authen::Digest;  
 
 # always flush
 $| = 1;
@@ -99,7 +101,7 @@ read_config($_) foreach $cfg or reverse @cfgs;
 my $explicit_target;
 GetOptions ("target|t=s" => \$explicit_target);
 
-my (@append, $bender, @chainloaders, $concat, $config_name_opt, $dhcp_tftp, $dump_opt, $dump_config, @exiton, @expect_raw, $gen_only, $grub_config, $grub_prefix, $grub_preamble, $grub2_prolog, $grub2_config, $help, $iprelay, $iso_image, $interactive, $kernel_opt, $make, $man, $no_file_gen, $off_opt, $on_opt, $pulsar, $pulsar_root, $qemu, $qemu_append, $qemu_flags_cmd, $remote_cmd, $remote_expect, $reset_cmd, $rom_prefix, $rsync_flags, @scriptmod, $scons, $serial, $server, $stty, $uboot, $uboot_init);
+my ($amt, @append, $bender, @chainloaders, $concat, $config_name_opt, $dhcp_tftp, $dump_opt, $dump_config, @exiton, @expect_raw, $gen_only, $grub_config, $grub_prefix, $grub_preamble, $grub2_prolog, $grub2_config, $help, $iprelay, $iso_image, $interactive, $kernel_opt, $make, $man, $no_file_gen, $off_opt, $on_opt, $pulsar, $pulsar_root, $qemu, $qemu_append, $qemu_flags_cmd, $remote_cmd, $remote_expect, $reset_cmd, $rom_prefix, $rsync_flags, @scriptmod, $scons, $serial, $server, $stty, $uboot, $uboot_init);
 
 $rsync_flags = '';
 $rom_prefix = 'rom://';
@@ -126,6 +128,7 @@ sub handle_send
 Getopt::Long::Configure(qw/no_ignore_case no_pass_through/);
 my %opt_spec;
 %opt_spec = (
+    "amt=s"         => \$amt,
     "append|a=s"     => \@append,
     "bender|b"       => \$bender,
     "build-dir=s"    => sub { my ($n, $v) = @_; $builddir = File::Spec->rel2abs($v); },
@@ -543,6 +546,98 @@ elsif ($serial) {
 } elsif ($remote_cmd) {
     print "novaboot: Running: $remote_cmd\n";
     $exp = Expect->spawn($remote_cmd);
+} elsif (defined $amt){    
+    sub genXML { #HOST, username, password, schema, className, pstate
+        my ($host, $username, $password, $schema, $className, $pstate) = @_;
+        #AMT numbers for PowerStateChange: 2 on, 4 standby, 7 hibernate, 8 off, 
+        #10 reset, 11 MNI interupt(on windows->bluescreen;-)) 
+        my %pstates = ("on", 2,
+                    "standby", 4,
+                    "hibernate", 7,
+                    "off", 8,
+                    "reset", 10,
+                    "MNI", 11);
+        my $text = <<END;
+               <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">
+               <s:Header><a:To>http://$host:16992/wsman</a:To>
+               <w:ResourceURI s:mustUnderstand="true">$schema</w:ResourceURI>
+               <a:ReplyTo><a:Address s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>
+               <a:Action s:mustUnderstand="true">$schema$className</a:Action>
+               <w:MaxEnvelopeSize s:mustUnderstand="true">153600</w:MaxEnvelopeSize>
+               <a:MessageID>uuid:709072C9-609C-4B43-B301-075004043C7C</a:MessageID>
+               <w:Locale xml:lang="en-US" s:mustUnderstand="false" />
+               <w:OperationTimeout>PT60.000S</w:OperationTimeout>
+               <w:SelectorSet><w:Selector Name="Name">Intel(r) AMT Power Management Service</w:Selector></w:SelectorSet>
+               </s:Header><s:Body>
+               <p:RequestPowerStateChange_INPUT xmlns:p="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService">
+               <p:PowerState>$pstates{$pstate}</p:PowerState>
+               <p:ManagedElement><a:Address>http://$host:16992/wsman</a:Address>
+               <a:ReferenceParameters><w:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem</w:ResourceURI>
+               <w:SelectorSet><w:Selector Name="Name">ManagedSystem</w:Selector></w:SelectorSet>
+               </a:ReferenceParameters></p:ManagedElement>
+               </p:RequestPowerStateChange_INPUT>
+               </s:Body></s:Envelope>
+END
+        return $text;
+    }
+  
+    sub sendPOST{ #ip, username, password, content
+        my ($host, $username, $password, $content)=@_;+
+        my $req = HTTP::Request->new(POST => "http://$host:16992/wsman");
+        my $ua = LWP::UserAgent->new();
+        my $res = $ua->request($req);
+        die ($res->status_line) unless $res->code==401;
+        my $header = $res->header("WWW-Authenticate");
+        my $digRealm = "Digest realm=\"";
+        my $posRealm = index($header,$digRealm)+length($digRealm);
+        my $realm = substr($header,$posRealm,index($header,"\"",$posRealm)-$posRealm);
+        
+        $ua = LWP::UserAgent->new();
+        $ua->agent("novaboot");
+        $ua->credentials("$host:16992",$realm,  $username => $password); 
+        # Create a request
+        $req = HTTP::Request->new(POST => "http://$host:16992/wsman");
+        $req->content_type('application/x-www-form-urlencoded');
+        $req->content($content);
+        $res = $ua->request($req);
+        die ($res->status_line) unless $res->is_success;
+        $res->content() =~ /<g:ReturnValue>(\d+)<\/g:ReturnValue>/;
+        return $1;
+    }
+
+    sub powerChange  {#IP, username, password, pstate
+        my ($host, $username, $password, $pstate)=@_;
+        my $schema="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService";
+        my $className="/RequestPowerStateChange";
+        my $content = genXML($host, $username, $password ,$schema, $className, $pstate);
+        return sendPOST($host, $username, $password, $content);
+    }  
+
+       my (@amt_info, $len, $amt_password, $result, $host, $port, $user);
+       ($user,$amt_password,$host,$port) = ($amt =~ /(?:(.*?)(?::(.*))?@)?([^:]*)(?::([0-9]*))?/);;
+       $len=@amt_info;
+       die "AMT host not specified" unless $host;
+       $user ||= "admin";
+       $port ||= 16994;
+    $amt_password ||= $ENV{'AMT_PASSWORD'} || die "AMT password not specified";
+       $target_power_off = sub {
+               $result = powerChange($host,$user,$amt_password, "off");
+               die "Cannot turn off the computer, somebody is connected or computer is already off" unless $result==0;
+       };
+       
+       $target_power_on = sub {
+               $result = powerChange($host,$user,$amt_password, "on");
+       };
+       
+       $target_reset = sub {
+               $result = powerChange($host,$user,$amt_password, "off");
+               print "Warning: host was off or somebody is connected to it." unless $result==0;
+               $result = powerChange($host,$user,$amt_password, "on");
+               select(undef, undef, undef, 2); 
+               #if not using pause, connection to AMT machine is initiated before reset and fails after restart
+               $exp = Expect->spawn("amtterm -u $user -p $amt_password $host $port"); 
+               #expect must be here because AMT doesnt allow to reset/on/off computer when somebody is connected
+       };      
 }
 
 if ($remote_expect) {
@@ -1132,6 +1227,14 @@ user/instance.
 
 =over 8
 
+=item --amt=I<"[user[:password]@]host[:port]>
+
+Use Intel AMT to connect to target. Using SOL redirection and WS management 
+to powercycle it. The IP address or FQDN of the PC is given by I<host>
+parameter. If I<password> is not specified, environment variable 
+AMT_PASSWORD is used. I<port> is defining port number for SOL, 
+if not specified, default is 16992. Default I<user> is admin.
+
 =item --iprelay=I<addr[:port]>
 
 Use TCP/IP relay and serial port to access the target's serial port
@@ -1164,6 +1267,7 @@ example C<ssh server 'cu -l /dev/ttyS0'>.
 Wait for reception of I<string> after establishing the the remote
 connection before continuing.
 
+
 =back
 
 =head2 File deployment phase