diff --git a/xCAT-server/lib/perl/xCAT/IPMI.pm b/xCAT-server/lib/perl/xCAT/IPMI.pm index 60bef36fa..2055eafa7 100644 --- a/xCAT-server/lib/perl/xCAT/IPMI.pm +++ b/xCAT-server/lib/perl/xCAT/IPMI.pm @@ -360,7 +360,7 @@ sub subcmd { if ($self->{confalgo}) { $type = $type | 0b10000000; #add secrecy } - $self->sendpayload(payload=>\@payload,type=>$type); + $self->sendpayload(payload=>\@payload,type=>$type,delayxmit=>$args{delayxmit}); } sub waitforrsp { @@ -739,10 +739,18 @@ sub sendpayload { my @msg = (0x6,0x0,0xff,0x07); #RMCP header is constant in IPMI my $type = $args{type} & 0b00111111; $sessions_waiting{$self}={}; - $sessions_waiting{$self}->{timeout}=time()+$self->{timeout}; $sessions_waiting{$self}->{ipmisession}=$self; my @payload = @{$args{payload}}; $self->{pendingargs} = \%args; + if ($args{delayxmit}) { + $sessions_waiting{$self}->{timeout}=time()+$args{delayxmit}; + $self->{timeout}=1; #since we are burning one of the retry attempts, start the backoff algorithm faster to make it come out even + undef $args{delayxmit}; + return; #don't actually transmit packet, use retry timer to start us off + } else { + $sessions_waiting{$self}->{timeout}=time()+$self->{timeout}; + } + push @msg,$self->{'authtype'}; # add authtype byte (will support 0 only for session establishment, 2 for ipmi 1.5, 6 for ipmi2 if ($self->{'ipmiversion'} eq '2.0') { #TODO: revisit this to see if assembly makes sense push @msg, $args{type}; diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index 5d5400eba..124e78966 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -1247,6 +1247,21 @@ sub power_with_context { return; } } elsif ($subcommand eq "suspend") { + my $waitforsuspend; + if (@{$sessdata->{extraargs}} > 1) { + @ARGV=@{$sessdata->{extraargs}}; + use Getopt::Long; + unless(GetOptions( + 'w:i' => \$waitforsuspend + )) { + xCAT::SvrUtils::sendmsg([1,"Error parsing arguments"],$callback,$sessdata->{node},%allerrornodes); + return; + } + } + if (defined $waitforsuspend) { + if ($waitforsuspend == 0) { $waitforsuspend=30; } + $sessdata->{waitforsuspend}=time()+$waitforsuspend; + } $sessdata->{ipmisession}->subcmd(netfn=>0x3a,command=>0x1d,data=>[0,3],callback=>\&power_response,callback_args=>$sessdata); return; } elsif ($subcommand eq "wake") { @@ -1271,9 +1286,34 @@ sub power_response { unless ($text) { $text = sprintf("Unknown response %02xh",$rsp->{code}); } xCAT::SvrUtils::sendmsg([1,$text],$callback,$sessdata->{node},%allerrornodes); } + if ($sessdata->{waitforsuspend}) { #have to repeatedly power stat until happy or timeout exceeded + $sessdata->{ipmisession}->subcmd(netfn=>0x3a,command=>0x1d,data=>[1],callback=>\&power_wait_for_suspend,callback_args=>$sessdata); + return; + } xCAT::SvrUtils::sendmsg($sessdata->{subcommand},$callback,$sessdata->{node},%allerrornodes); } +sub power_wait_for_suspend { + my $rsp = shift; + my $sessdata = shift; + if ($rsp->{error}) { + xCAT::SvrUtils::sendmsg([1,$rsp->{error}],$callback,$sessdata->{node},%allerrornodes); + return; + } + if ($rsp->{code} == 0) { + if ($rsp->{data}->[0] == 3) { + $sessdata->{acpistate} = "suspend"; + } + } + if ($sessdata->{acpistate} eq "suspend") { + xCAT::SvrUtils::sendmsg("suspend",$callback,$sessdata->{node},%allerrornodes); + } elsif ($sessdata->{waitforsuspend} <= time()) { + xCAT::SvrUtils::sendmsg([1,"Failed to enter suspend state"],$callback,$sessdata->{node},%allerrornodes); + } else { + $sessdata->{ipmisession}->subcmd(netfn=>0x3a,command=>0x1d,delayxmit=>5,data=>[1],callback=>\&power_wait_for_suspend,callback_args=>$sessdata); + } +} + sub generic { my $subcommand = shift; my $netfun;