xcat-core/xCAT-server/lib/xcat/plugins/energy.pm

1036 lines
38 KiB
Perl

#!/usr/bin/perl
# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
=head3 xCAT_plugin::energy
This plugin module is used to handle the renergy command for:
FSP based Power 8 machine.
1. mgt=fsp, mtm=(p8); 2. mgt=ipmi, arch=ppc64le;
=cut
package xCAT_plugin::energy;
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";
use strict;
use warnings "all";
use Getopt::Long;
use xCAT::Usage;
use xCAT::CIMUtils;
use xCAT::MsgUtils;
use xCAT::Table;
use xCAT::FSPUtils;
use xCAT::NetworkUtils;
sub handled_commands {
return {
renergy => 'nodehm:mgt=ipmi|fsp',
}
}
# The hash includes all valid attribute for quering
my %QUERY_ATTRS = (
'savingstatus' => 1,
'dsavingstatus' => 1,
'cappingstatus' => 1,
'cappingmaxmin' => 1,
'cappingvalue' => 1,
'cappingsoftmin' => 1,
'averageAC' => 1,
'averageAChistory' => 1,
'averageDC' => 1,
'averageDChistory' => 1,
'ambienttemp' => 1,
'ambienttemphistory' => 1,
'exhausttemp' => 1,
'exhausttemphistory' => 1,
'CPUspeed' => 1,
'CPUspeedhistory' => 1,
'fanspeed' => 1,
'fanspeedhistory' => 1,
'syssbpower' => 1,
'sysIPLtime' => 1,
# for FFO, only supported when communicating to fsp directly
'ffoMin' => 1,
'ffoVmin' => 1,
'ffoTurbo' => 1,
'ffoNorm' => 1,
'fsavingstatus' => 1,
'ffovalue' => 1,
);
# The hash includes all valid attribute for writting
my %SET_ATTRS = (
'savingstatus' => 1,
'dsavingstatus' => 1,
'cappingstatus' => 1,
'cappingwatt' => 1,
'cappingperc' => 1,
# for FFO
'fsavingstatus' => 1,
'ffovalue' => 1,
);
=head3 parse_args
DESCRIPTION:
Parse the arguments from the command line of renergy command
ARGUMENTS:
The request hash from preprocess_request or process_request
RETURN
First element: rc: 0 -success; 1 - fail
Second element:
1. a string: a message for display;
2. a reference to a hash: {verbose}, {query_list} and {set_pair}.
=cut
sub parse_args {
my $request = shift;
my $opt = ();
my $cmd = $request->{command}->[0];
my $args = $request->{arg};
my $nodes = $request->{node};
my @query_list = (); # The attributes list for query operation
my @set_pair = (); # The attribute need to be set. e.g. savingstatus=on
my $set_flag = (); # Indicate there's setting param in the argv
my $query_flag = (); # Indicate there's param in the argv
# set the usage subroutine
local *usage = sub {
my $add_msg = shift;
my $usage_string = xCAT::Usage->getUsage($cmd);
if ($add_msg) {
return("$add_msg\n".$usage_string);
} else {
return($usage_string);
}
};
# handle the arguments
if ($request->{arg}) {
@ARGV = @{$request->{arg}};
$Getopt::Long::ignorecase = 0;
Getopt::Long::Configure( "bundling" );
if (!GetOptions( 'V' => \$::VERBOSE,
'h|help' => \$::HELP,
'v|version' => \$::VERSION)) {
return (1, &usage());
}
if ($::HELP && $::VERSION) {
return (1, &usage());
}
if ($::HELP) {
return (0, &usage());
}
if ($::VERSION) {
my $version_string = xCAT::Usage->getVersion('renergy');
return(0, $version_string);
}
if ($::VERBOSE) {
$opt->{verbose} = 1;
}
}
# if the request has node range
if ($nodes) {
# the default option is query all attributes
if ($#ARGV < 0) {
$ARGV[0] = "all";
}
# Check the validity of the parameters of Query and Set
# Forbid to perform both query and set
foreach my $attr (@ARGV) {
my ($set_attr, $set_value) = split (/=/, $attr);
if (defined($set_value)) {
if ($query_flag) {
return (1, &usage("Cannot perform both Query and Set."));
}
# make sure the attribute is valid
if ($SET_ATTRS{$set_attr} != 1) {
return (1, &usage("Invalid attribute."));
}
if ($set_flag) {
return (1, &usage("Only supports to perform one setting at invoke."));
}
# make sure the value for attirbute is valid
if (($set_attr eq "savingstatus" || $set_attr eq "fsavingstatus")
&& ($set_value ne "on" && $set_value ne "off")) {
return (1, &usage("Incorrect Value"));
} elsif ($set_attr eq "dsavingstatus"
&& ($set_value ne "off"
&& $set_value ne "on-norm" && $set_value ne "on-maxp")) {
return (1, &usage("Incorrect Value"));
} elsif ($set_attr eq "cappingstatus"
&& ($set_value ne "on" && $set_value ne "off")) {
return (1, &usage("Incorrect Value"));
} elsif ( ($set_attr eq "cappingwatt"
|| $set_attr eq "cappingperc" || $set_attr eq "ffovalue")
&& $set_value =~ /\D/) {
return (1, &usage("Incorrect Value"));
}
push @set_pair, $set_attr."=".$set_value;
$set_flag = 1;
} else {
if ($set_flag) {
return (1, &usage("Cannot perform both Query and Set."));
}
# replace the 'all' with all valid attribute
if ($attr eq "all") {
foreach my $q_attr (keys %QUERY_ATTRS) {
# do not include 'history' related attributes for all keyword
if ($q_attr =~ /history$/) {
next;
}
if (!grep (/^$q_attr$/, @query_list)) {
push @query_list, $q_attr;
}
}
} else {
# make sure the query attribute is valid
if ($QUERY_ATTRS{$attr} != 1) {
return (1, &usage("Invalid attribute."));
}
if (!grep (/^$attr$/, @query_list)) {
push @query_list, $attr;
}
}
$query_flag = 1;
}
}
} else {
# no noderange, do nothing
return (1, &usage());
}
if (@query_list) {
$opt->{'query_list'} = join(',', @query_list);
} elsif (@set_pair) {
$opt->{'set_pair'} = join(',',@set_pair);
}
return (0, $opt);
}
sub preprocess_request
{
my $req = shift;
my $callback = shift;
# Exit if the packet has been preprocessed
if (defined ($req->{_xcatpreprocessed}->[0]) && $req->{_xcatpreprocessed}->[0] == 1) { return [$req]; }
my ($rc, $args) = parse_args($req);
if ($rc) {
# error or message display happens
xCAT::MsgUtils->message("E", {error => [$args], errorcode => [$rc]}, $callback);
return [];
} else {
unless (ref($args)) {
xCAT::MsgUtils->message("I", {data => [$args]}, $callback);
return [];
}
}
# do nothing if no query or setting required.
unless (defined ($args->{query_list}) || defined($args->{set_pair})) {
return [];
}
# This plugin only handle the node which is 1. mgt=fsp, mtm=(p8); 2. mgt=ipmi, arch=ppc64le;
# otherwise, make other plugin to handle it
my (@mpnodes, @fspnodes, @bmcnodes, @nohandle);
xCAT::Utils->filter_nodes($req, \@mpnodes, \@fspnodes, \@bmcnodes, \@nohandle);
# Find the nodes which are not handled by mp (@mpnodes), fsp (@fspnodes) and bmc (@bmcnods), and not in @nohandle.
# They are the one of p8_fsp nodes which should be handled by this plugin
my %tmphash = map {$_ => 1} (@mpnodes, @fspnodes, @bmcnodes, @nohandle);
my @nodes = grep {not $tmphash{$_}} @{$req->{node}};
# build request array
my @requests;
if (@nodes) {
my $sn = xCAT::ServiceNodeUtils->get_ServiceNode( \@nodes, 'xcat', 'MN' );
# Build each request for each service node
foreach my $snkey ( keys %$sn ) {
my $reqcopy = {%$req};
$reqcopy->{node} = $sn->{$snkey};
$reqcopy->{'_xcatdest'} = $snkey;
$reqcopy->{_xcatpreprocessed}->[0] = 1;
if (defined($args->{verbose})) {
$reqcopy->{verbose} = $args->{verbose};
}
if (defined($args->{query_list})) {
$reqcopy->{query_list} = $args->{query_list};
}
if (defined($args->{set_pair})) {
$reqcopy->{set_pair} = $args->{set_pair};
}
push @requests, $reqcopy;
}
return \@requests;
}
return [];
}
sub process_request {
my $request = shift;
my $callback = shift;
my $subreq = shift;
my $verbose;
my $nodes = $request->{node};
my $args = $request->{arg};
if (defined($request->{verbose})) {
$verbose = $request->{verbose};
}
# get the password for the nodes
my $user_default = "admin";
my $password_default = "admin";
my $ipmi_tab = xCAT::Table->new('ipmi', -create=>0);
my $ipmi_hash;
if ($ipmi_tab) {
$ipmi_hash = $ipmi_tab->getNodesAttribs($request->{node}, ['bmc', 'username','password']);
}
my $ppc_tab = xCAT::Table->new('ppc', -create=>0);
my $ppc_hash;
my @ppc_all_entry;
my $cec2fsp;
if ($ppc_tab) {
$ppc_hash = $ppc_tab->getNodesAttribs($request->{node}, ['hcp', 'nodetype']);
}
my $nodehm_tab = xCAT::Table->new('nodehm', -create => 0);
my $nodehm_hash;
if ($nodehm_tab) {
$nodehm_hash = $nodehm_tab->getNodesAttribs($request->{node}, ['mgt']);
}
my $ppcdirect_tab = xCAT::Table->new('ppcdirect', -create=>0);
foreach my $node (@{$request->{node}}) {
my $user = $user_default;
my $password = $password_default;
my $hcp_ip;
if (defined ($nodehm_hash->{$node}->[0]->{mgt})) {
my $mgt = $nodehm_hash->{$node}->[0]->{mgt};
if ($mgt eq 'fsp') {
# This is Power node which is running in PowerVM mode
unless (@ppc_all_entry) {
@ppc_all_entry = $ppc_tab->getAllNodeAttribs(['node', 'parent', 'hcp', 'nodetype']);
foreach my $ppcentry (@ppc_all_entry) {
if (defined($ppcentry->{parent})) {
$cec2fsp->{$ppcentry->{parent}} .= "$ppcentry->{node},";
}
}
}
$hcp_ip = $cec2fsp->{$node};
# Get the user/password for the node
if ($ppcdirect_tab) {
my $ppcdirect_hash = $ppcdirect_tab->getAttribs({hcp => $node, username => $user}, 'password');
if ($ppcdirect_hash) {
$password = $ppcdirect_hash->{'password'};
}
}
} elsif ($mgt eq 'ipmi') {
if (defined ($ipmi_hash->{$node}->[0]->{bmc})){
# This is a ipmi managed node. (should be a ppcle)
$hcp_ip = $ipmi_hash->{$node}->[0]->{bmc};
if (defined ($ipmi_hash->{$node}->[0]->{username})){
$user = $ipmi_hash->{$node}->[0]->{username};
$password = $ipmi_hash->{$node}->[0]->{password};
}
} else {
xCAT::MsgUtils->message("E", {data => ["$node: Missed attribute [bmc]."]}, $callback);
return 1;
}
} else {
xCAT::MsgUtils->message("E", {data => ["$node: Support the valid mgt [fsp, ipmi]."]}, $callback);
return 1;
}
} else {
xCAT::MsgUtils->message("E", {data => ["$node: Missed important attributes [mgt] to know how to handle this node."]}, $callback);
return 1;
}
unless ($hcp_ip) {
xCAT::MsgUtils->message("E", {data => ["$node: Cannot find HCP"]}, $callback);
return 1;
}
foreach my $ip (split(',', $hcp_ip)) {
unless ($ip) { next; }
my $real_ip = xCAT::NetworkUtils->getipaddr($ip);
unless ($real_ip) {
xCAT::MsgUtils->message("E", {error => ["$node: Cannot get ip for $ip"], errorcode => 1}, $callback);
next;
}
my %args = (
node => $node,
ip => $real_ip,
port => '5989',
method => 'POST',
user => $user,
password => $password);
if ($verbose) {
$args{verbose} = 1;
$args{callback} = $callback;
xCAT::MsgUtils->message("I", {data => ["$node: Access hcp [$ip], user [$user], passowrd [$password]"]}, $callback);
}
# call the cim utils to connect to cim server
my $ret = run_cim ($request, $callback, \%args);
# 0 - success; 1 - cim error; 10 - ip is not pingable; 11 - this ip is a standby fsp
unless ($ret == 10 || $ret == 11) {
last;
}
}
}
}
=head3 query_pum
DESCRIPTION:
Query the attribute for instance of FipS_PUMService class
ARGUMENTS:
$http_params - refer to the HTTP_PARAMS in xCAT::CIMUtils.pm
RETURN
$ret - return code and messages
$pum - a hash includes all the attributes
$namepath - the name path of pum instance
=cut
sub query_pum
{
my $http_params = shift;
my %cimargs = ( classname => 'FipS_PUMService' );
my ($ret, $value, $namepath) = xCAT::CIMUtils->enum_instance($http_params, \%cimargs);
if ($ret->{rc}) {
return ($ret);
}
# parse the return xml to get all the property of pum instance
my $pum;
if ($value && @$value) {
my $instance = $$value[0];
foreach my $pname (keys %{$instance->{property}}) {
$pum->{$pname} = $instance->{property}->{$pname}->{value};
}
}
return ($ret, $pum, $namepath);
}
=head3 query_cec_drawer
DESCRIPTION:
Query the attribute for instance of FipS_CECDrawer class
ARGUMENTS:
$http_params - refer to the HTTP_PARAMS in xCAT::CIMUtils.pm
RETURN
$ret - return code and messages
$cec_drawer - a hash includes all the attributes
=cut
sub query_cec_drawer
{
my $http_params = shift;
my %cimargs = ( classname => 'FipS_CECDrawer' );
my ($ret, $value, $namepath) = xCAT::CIMUtils->enum_instance($http_params, \%cimargs);
if ($ret->{rc}) {
return ($ret);
}
# parse the return xml to get all the property of pum instance
my $cec_drawer;
if ($value && @$value) {
my $instance = $$value[0];
foreach my $pname (keys %{$instance->{property}}) {
$cec_drawer->{$pname} = $instance->{property}->{$pname}->{value};
}
} else {
return ({rc => 1, msg => "Cannot find instance for FipS_CECDrawer class"});
}
return ($ret, $cec_drawer, $namepath);
}
=head3 query_metric
DESCRIPTION:
Query the attribute for instance of FipS_*metricValue class
ARGUMENTS:
$http_params - refer to the HTTP_PARAMS in xCAT::CIMUtils.pm
$option - the specified operation
RETURN
$ret - return code and messages
$array - a hash includes all the attributes
=cut
sub query_metric
{
my $http_params = shift;
my $classname = shift;
my $matching_string = shift;
my $value_unit = shift;
if (!defined($value_unit)) {
$value_unit = 1;
}
my %cimargs = ( classname => "$classname" );
my ($ret, $value) = xCAT::CIMUtils->enum_instance($http_params, \%cimargs);
if ($ret->{rc}) {
return $ret;
}
my ($matching_key, $matching_value) = split /:/,$matching_string;
my %instances_hash = ();
foreach my $instance (@$value) {
my $instance_element = undef;
my $timestamp = undef;
if (defined ($instance->{property}->{$matching_key}) and $instance->{property}->{$matching_key}->{value} !~ /$matching_value/) {
next;
}
if (defined ($instance->{property}->{InstanceID})) {
$instance_element = $instance->{property}->{InstanceID}->{value};
$instance_element =~ s/ .*$//;
}
if (!defined($instance_element)) {
next;
}
if (defined ($instance->{property}->{MeasuredElementName})) {
$instances_hash{$instance_element}->{MeasuredElementName} = $instance->{property}->{MeasuredElementName}->{value};
} else {
next;
}
if (defined ($instance->{property}->{TimeStamp})) {
$timestamp = $instance->{property}->{TimeStamp}->{value};
$timestamp =~ s/\..*$//;
}
if (defined ($instance->{property}->{MetricValue})) {
if (defined($timestamp)) {
$instances_hash{$instance_element}->{MetricValue}->{$timestamp} = $instance->{property}->{MetricValue}->{value} / $value_unit;
}
}
}
return ($ret, \%instances_hash);
}
=head3 query_tmp
DESCRIPTION:
Require the input and output temperature
=cut
sub query_tmp
{
&query_metric(@_, "FipS_ThermalMetricValue", "InstanceID:InletAirTemp|ExhaustAirTemp", 100);
}
=head3 query_cpuspeed
DESCRIPTION:
Require the cpuspeed history
=cut
sub query_cpuspeed
{
&query_metric(@_, "FipS_CPUUsageMetricValue", "InstanceID:AvgCPUUsage");
}
=head3 query_fanspeed
DESCRIPTION:
Require the fanspeed history
=cut
sub query_fanspeed
{
&query_metric(@_, "FipS_FanSpeedMetricValue", "InstanceID:FansSpeed");
}
=head3 query_powermetric
DESCRIPTION:
Require the AC and DC power comsume history
=cut
sub query_powermetric
{
my $http_params = shift;
$http_params->{timeout} = 500;
my ($ret, $return_hash) = &query_metric($http_params, "FipS_PowerMetricValue", "InstanceID:AvgInputPwr");
if ($ret->{rc}) {
return $ret;
}
my %instances = ();
foreach my $ins (keys %$return_hash) {
if ($return_hash->{$ins}->{MeasuredElementName} =~ /Power Supply/) {
foreach my $timestamp (keys %{$return_hash->{$ins}->{MetricValue}}) {
if (!exists($instances{"averageAC"}->{MetricValue}->{$timestamp})) {
$instances{"averageAC"}->{MetricValue}->{$timestamp} = $return_hash->{$ins}->{MetricValue}->{$timestamp};
} else {
$instances{"averageAC"}->{MetricValue}->{$timestamp} += $return_hash->{$ins}->{MetricValue}->{$timestamp};
}
}
} else {
$instances{"averageDC"}->{MetricValue} = $return_hash->{$ins}->{MetricValue};
}
}
return ($ret, \%instances);
}
=head3 run_cim
DESCRIPTION:
Handle the Query and Setting of Energy via CIM
ARGUMENTS:
$request
$callback
$http_params - refer to the HTTP_PARAMS in xCAT::CIMUtils.pm
RETURN
First element: rc: 0 -success; 1 - cim error; 10 - ip is not pingable; 11 - this ip is a standby fsp
=cut
sub run_cim
{
my $request = shift;
my $callback = shift;
my $http_params = shift;
my $node = $http_params->{node};
my $output;
my $verbose;
my $query_list;
my $set_pair;
if (defined($request->{verbose})) {
$verbose = $request->{verbose};
}
if (defined($request->{query_list})) {
$query_list = $request->{query_list};
}
if (defined($request->{set_pair})) {
$set_pair = $request->{set_pair};
}
# Try to connect CIM Server to Enumerate CEC object;
# If cannot access this ip, return 10 for caller to connect to the next ip
my $cimargs = {
classname => 'fips_cec',
};
$http_params->{timeout} = 5;
my ($ret, $value) = xCAT::CIMUtils->enum_instance($http_params, $cimargs);
if ($ret->{rc}) {
if ($ret->{msg} =~ /Couldn't connect to server/) {
xCAT::MsgUtils->message("E", data => ["$node: Couldn not connect to server [$http_params->{ip}]."], $callback);
return 10;
} else {
xCAT::MsgUtils->message("E", {data => ["$node: $ret->{msg}"]}, $callback);
return 1;
}
}
delete $http_params->{timeout};
# check whether the primary ip of fsp is the IP we are accessing
if (defined ($value->[0]->{property}->{PrimaryFSP_IP}->{value}) && $value->[0]->{property}->{PrimaryFSP_IP}->{value} ne $http_params->{ip}) {
# run against the standby fsp, do the next one
return 11;
}
# ======start to handle the query and setting======
# Pre-query some specific instances since some instances are common for multiple energy attributes
#my $query_pum_capabilities_flag; # set to query the instance for [FipS_PUMServiceCapabilities]
my $query_pum_flag; # set to query the instance for [FipS_PUMService]
my $query_pum_value; # the pre-queried PUM instance
my $namepath_pum; # the name path of PUM instance
my $query_drawer_flag; # set to query the instance for [FipS_CECDrawer]
my $query_drawer_value; # the pre-queried cec drawer instance
my %query_return_hash = (); # the hash store the returned hashes for query functions
my $query_tmp_value; # the requrest for FipS_ThermalMetricValue class
my $query_cpuspeed_value; # the request for FipS_CPUUsageMetricValue class
my $query_fanspeed_value; # the request for FipS_FanSpeedMetricValue class
my $query_powermetric_value; # the request for FipS_PowerMetricValue class
if ($query_list) {
foreach my $attr (split(',', $query_list)) {
if ($attr =~ /^(savingstatus|dsavingstatus|fsavingstatus|ffoMin|ffoVmin|ffoTurbo|ffoNorm|ffovalue)$/) {
$query_pum_flag = 1;
} elsif ($attr =~ /^(syssbpower|sysIPLtime)$/) {
$query_drawer_flag = 1;
} elsif ($attr =~ /^(ambienttemp|exhausttemp)/) {
$query_tmp_value = 1;
} elsif ($attr =~ /^CPUspeed/) {
$query_cpuspeed_value = 1;
} elsif ($attr =~ /^fanspeed/) {
$query_fanspeed_value = 1;
} elsif ($attr =~ /^(averageAC|averageDC)/) {
$query_powermetric_value = 1;
}
}
}
if ($set_pair) {
my ($set_name, $set_value) = split('=', $set_pair);
if ($set_name =~/^(savingstatus|dsavingstatus|fsavingstatus|ffovalue)$/) {
$query_pum_flag = 1;
}
}
# query the pre required instances
if ($query_pum_flag) {
($ret, $query_pum_value, $namepath_pum) = query_pum($http_params);
if ($ret->{rc}) {
xCAT::MsgUtils->message("E", {data => ["$node: $ret->{msg}"]}, $callback);
return ($ret->{rc});
}
}
if ($query_drawer_flag) {
($ret, $query_drawer_value) = query_cec_drawer($http_params);
if ($ret->{rc}) {
xCAT::MsgUtils->message("E", {data => ["$node: $ret->{msg}"]}, $callback);
return ($ret->{rc});
}
}
if ($query_powermetric_value) {
my ($tmpret, $tmpvalue) = query_powermetric($http_params);
if ($tmpret->{rc}) {
xCAT::MsgUtils->message("E", {data => ["$node: $ret->{msg}"]}, $callback);
return ($tmpret->{rc});
}
$query_return_hash{query_powermetric} = $tmpvalue;
}
if ($query_fanspeed_value) {
$http_params->{timeout} = 200;
my ($tmpret, $tmpvalue) = query_fanspeed($http_params);
if ($tmpret->{rc}) {
xCAT::MsgUtils->message("E", {data => ["$node: $ret->{msg}"]}, $callback);
return ($tmpret->{rc});
}
$query_return_hash{query_fanspeed} = $tmpvalue;
}
if ($query_cpuspeed_value) {
my ($tmpret, $tmpvalue) = query_cpuspeed($http_params);
if ($tmpret->{rc}) {
xCAT::MsgUtils->message("E", {data => ["$node: $ret->{msg}"]}, $callback);
return ($tmpret->{rc});
}
$query_return_hash{query_cpuspeed} = $tmpvalue;
}
if ($query_tmp_value) {
$http_params->{timeout} = 200;
my ($tmpret, $tmpvalue) = query_tmp($http_params);
if ($tmpret->{rc}) {
xCAT::MsgUtils->message("E", {data => ["$node: $ret->{msg}"]}, $callback);
return ($tmpret->{rc});
}
$query_return_hash{query_tmp} = $tmpvalue;
}
# perform the query request
if ($query_list) {
foreach my $attr (split(',', $query_list)) {
# Query the power saving status
if ($attr =~ /^(savingstatus|dsavingstatus|fsavingstatus)$/) {
if ($query_pum_flag) {
if (defined ($query_pum_value->{PowerUtilizationMode})) {
# 2 = None; 3 = Dynamic; 4 = Static; 32768 = Dynamic Favor Performance; 32769 = FFO
if ($query_pum_value->{PowerUtilizationMode} eq "2") {
push @{$output->{$node}}, "$attr: off";
} elsif ($query_pum_value->{PowerUtilizationMode} eq "3") {
if ($attr eq "dsavingstatus") {
push @{$output->{$node}}, "$attr: on-norm";
} else {
push @{$output->{$node}}, "$attr: off";
}
} elsif ($query_pum_value->{PowerUtilizationMode} eq "4") {
if ($attr eq "savingstatus") {
push @{$output->{$node}}, "$attr: on";
} else {
push @{$output->{$node}}, "$attr: off";
}
} elsif ($query_pum_value->{PowerUtilizationMode} eq "32768") {
if ($attr eq "dsavingstatus") {
push @{$output->{$node}}, "$attr: on-maxp";
} else {
push @{$output->{$node}}, "$attr: off";
}
} elsif ($query_pum_value->{PowerUtilizationMode} eq "32769") {
if ($attr eq "fsavingstatus") {
push @{$output->{$node}}, "$attr: on";
} else {
push @{$output->{$node}}, "$attr: off";
}
}
} else {
push @{$output->{$node}}, "$attr: na";
}
} else {
push @{$output->{$node}}, "$attr: na";
}
}
# Query the FFO settings
if ($attr =~ /^(ffoMin|ffoVmin|ffoTurbo|ffoNorm|ffovalue)$/) {
if ($query_pum_flag) {
if (defined ($query_pum_value->{FixedFrequencyPoints}) && defined ($query_pum_value->{FixedFrequencyPointValues})) {
my @ffo_point = split (',', $query_pum_value->{FixedFrequencyPoints});
my @ffo_point_value = split (',', $query_pum_value->{FixedFrequencyPointValues});
foreach my $index (0..$#ffo_point) {
if ($ffo_point[$index] eq '2' && $attr eq 'ffoNorm') { # Norminal
push @{$output->{$node}}, "$attr: $ffo_point_value[$index] MHZ";
} elsif ($ffo_point[$index] eq '3' && $attr eq 'ffoTurbo') { # Turbo
push @{$output->{$node}}, "$attr: $ffo_point_value[$index] MHZ";
} elsif ($ffo_point[$index] eq '4' && $attr eq 'ffoVmin') { # Vmin
push @{$output->{$node}}, "$attr: $ffo_point_value[$index] MHZ";
} elsif ($ffo_point[$index] eq '5' && $attr eq 'ffoMin') { # Min
push @{$output->{$node}}, "$attr: $ffo_point_value[$index] MHZ";
}
}
} else {
push @{$output->{$node}}, "$attr: na";
}
} else {
push @{$output->{$node}}, "$attr: na";
}
}
# Query the FFO Value
if ($attr eq 'ffovalue') {
if ($query_pum_flag) {
if (defined ($query_pum_value->{FixedFrequencyOverrideFreq})) {
if ($query_pum_value->{FixedFrequencyOverrideFreq} eq '4294967295') {
push @{$output->{$node}}, "$attr: 0 MHZ";
} else {
push @{$output->{$node}}, "$attr: $query_pum_value->{FixedFrequencyOverrideFreq} MHZ";
}
} else {
push @{$output->{$node}}, "$attr: na";
}
} else {
push @{$output->{$node}}, "$attr: na";
}
}
# Query the attribute sysIPLtime and syssbpower
if ($attr =~ /^(syssbpower|sysIPLtime)$/) {
if ($query_drawer_flag) {
if (defined ($query_drawer_value->{AverageTimeToIPL}) && $attr eq "sysIPLtime") {
push @{$output->{$node}}, "$attr: $query_drawer_value->{AverageTimeToIPL} S";
} elsif (defined ($query_drawer_value->{StandbyPowerUtilization}) && $attr eq "syssbpower") {
push @{$output->{$node}}, "$attr: $query_drawer_value->{StandbyPowerUtilization} W";
} else {
push @{$output->{$node}}, "$attr: na";
}
} else {
push @{$output->{$node}}, "$attr: na";
}
}
if ($attr =~ /^ambienttemp/) {
my $tmphash = $query_return_hash{query_tmp};
foreach my $ins (keys %$tmphash) {
if ($ins =~ /InletAirTemp/) {
my @times = sort keys %{$tmphash->{$ins}->{MetricValue}};
if ($attr eq "ambienttemp") {
#push @{$output->{$node}}, "$attr ($tmphash->{$ins}->{MeasuredElementName}): $tmphash->{$ins}->{MetricValue}->{$times[-1]}";
push @{$output->{$node}}, "$attr: $tmphash->{$ins}->{MetricValue}->{$times[-1]} C";
} else {
foreach my $time (@times) {
#push @{$output->{$node}}, "$attr ($tmphash->{$ins}->{MeasuredElementName}): $tmphash->{$ins}->{MetricValue}->{$time}: $time";
push @{$output->{$node}}, "$attr: $tmphash->{$ins}->{MetricValue}->{$time} C: $time";
}
}
}
}
} elsif ($attr =~ /^exhausttemp/) {
my $tmphash = $query_return_hash{query_tmp};
foreach my $ins (keys %$tmphash) {
if ($ins =~ /ExhaustAirTemp/) {
my @times = sort keys %{$tmphash->{$ins}->{MetricValue}};
if ($attr eq "exhausttemp") {
#push @{$output->{$node}}, "$attr ($tmphash->{$ins}->{MeasuredElementName}): $tmphash->{$ins}->{MetricValue}->{$times[-1]}";
push @{$output->{$node}}, "$attr: $tmphash->{$ins}->{MetricValue}->{$times[-1]} C";
} else {
foreach my $time (@times) {
#push @{$output->{$node}}, "$attr ($tmphash->{$ins}->{MeasuredElementName}): $tmphash->{$ins}->{MetricValue}->{$time}: $time";
push @{$output->{$node}}, "$attr: $tmphash->{$ins}->{MetricValue}->{$time} C: $time";
}
}
}
}
} elsif ($attr =~ /^CPUspeed/) {
my $tmphash = $query_return_hash{query_cpuspeed};
foreach my $ins (keys %$tmphash) {
if ($ins =~ /AvgCPUUsage/) {
my @times = sort keys %{$tmphash->{$ins}->{MetricValue}};
if ($attr eq "CPUspeed") {
#push @{$output->{$node}}, "$attr ($tmphash->{$ins}->{MeasuredElementName}): $tmphash->{$ins}->{MetricValue}->{$times[-1]}";
push @{$output->{$node}}, "$attr: $tmphash->{$ins}->{MetricValue}->{$times[-1]} MHZ";
} else {
foreach my $time (@times) {
#push @{$output->{$node}}, "$attr ($tmphash->{$ins}->{MeasuredElementName}): $tmphash->{$ins}->{MetricValue}->{$time}: $time";
push @{$output->{$node}}, "$attr: $tmphash->{$ins}->{MetricValue}->{$time} MHZ: $time";
}
}
}
}
} elsif ($attr =~ /^fanspeed/) {
my $tmphash = $query_return_hash{query_fanspeed};
foreach my $ins (keys %$tmphash) {
if ($ins =~ /FansSpeed/) {
my @times = sort keys %{$tmphash->{$ins}->{MetricValue}};
if ($attr eq "fanspeed") {
push @{$output->{$node}}, "$attr ($tmphash->{$ins}->{MeasuredElementName}): $tmphash->{$ins}->{MetricValue}->{$times[-1]} RPM";
} else {
foreach my $time (@times) {
push @{$output->{$node}}, "$attr ($tmphash->{$ins}->{MeasuredElementName}): $tmphash->{$ins}->{MetricValue}->{$time} RPM: $time";
}
}
}
}
$query_fanspeed_value = 1;
} elsif ($attr =~ /^(averageAC|averageDC)/) {
my $tmpattr = $1;
my $tmphash = $query_return_hash{query_powermetric};
my @times = sort keys %{$tmphash->{$tmpattr}->{MetricValue}};
if ($attr =~ /history$/) {
foreach my $time (@times) {
push @{$output->{$node}}, "$attr: $tmphash->{$tmpattr}->{MetricValue}->{$time} W: $time";
}
} else {
push @{$output->{$node}}, "$attr: $tmphash->{$attr}->{MetricValue}->{$times[-1]} W";
}
}
}
}
# Perform the setting request
if ($set_pair) {
my ($set_name, $set_value) = split('=', $set_pair);
if ($set_name =~/^(savingstatus|dsavingstatus|fsavingstatus|ffovalue)$/) {
if ($query_pum_flag) {
if (defined ($query_pum_value->{PowerUtilizationMode})) {
# set the power saving value
my $ps_value;
if ($set_name eq "savingstatus") {
if ($set_value eq 'on') {
$ps_value = '4';
} elsif ($set_value eq 'off') {
$ps_value = '2';
}
} elsif ($set_name eq "dsavingstatus") {
if ($set_value eq 'on-norm') {
$ps_value = '3';
} elsif ($set_value eq 'on-maxp') {
$ps_value = '32768';
}elsif ($set_value eq 'off') {
$ps_value = '2';
}
} elsif ($set_name eq "fsavingstatus") {
if ($set_value eq 'on') {
$ps_value = '32769';
} elsif ($set_value eq 'off') {
$ps_value = '2';
}
}
if ($set_name eq "ffovalue") {
# set ffo value
$cimargs = {
propertyname => 'FixedFrequencyOverrideFreq',
propertyvalue => $set_value,
namepath => $namepath_pum,
};
$ret = xCAT::CIMUtils->set_property($http_params, $cimargs);
if ($ret->{rc}) {
push @{$output->{$node}}, "Set $set_name failed. [$ret->{msg}]";
} else {
push @{$output->{$node}}, "Set $set_name succeeded";
}
} else {
# set the power saving
if ($ps_value eq $query_pum_value->{PowerUtilizationMode}) { # do nothing if it already was the correct status
push @{$output->{$node}}, "Set $set_name succeeded";
} else {
# perform the setting
$cimargs = {
propertyname => 'PowerUtilizationMode',
propertyvalue => $ps_value,
namepath => $namepath_pum,
};
$ret = xCAT::CIMUtils->set_property($http_params, $cimargs);
if ($ret->{rc}) {
push @{$output->{$node}}, "Set $set_name failed. [$ret->{msg}]";
} else {
push @{$output->{$node}}, "Set $set_name succeeded";
}
}
}
} else {
push @{$output->{$node}}, "Set $set_name failed";
}
} else {
push @{$output->{$node}}, "Set $set_name failed";
}
}
}
# Display the output
foreach my $node (keys (%{$output})) {
my @newoutput;
if ($query_list && $query_list !~ /history/) {
@newoutput = sort (@{$output->{$node}});
} else {
@newoutput = @{$output->{$node}};
}
foreach (@newoutput) {
my $rsp;
$rsp->{node}->[0]->{name} = $node;
push @{$rsp->{node}->[0]->{data}->[0]->{contents}}, $_;
xCAT::MsgUtils->message("N", $rsp, $callback);
}
}
return 0;
}
1;