use POSIX qw(:errno_h);
use Cwd qw(getcwd abs_path);
use Expect;
+use LWP::UserAgent;
+use LWP::Authen::Digest;
# always flush
$| = 1;
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://';
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); },
} 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) {
=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
Wait for reception of I<string> after establishing the the remote
connection before continuing.
+
=back
=head2 File deployment phase