blob: 68e31f5f3de3142197c07d830366e733535a8ce6 [file] [log] [blame]
Matt Spinlerc17001d2017-03-30 09:57:01 -05001#!/usr/bin/env perl
2
3#This script generates fan definitions from the MRW
4#and outputs them in a YAML file.
5
6use strict;
7use warnings;
8
9use Getopt::Long;
10use mrw::Inventory;
11use mrw::Targets;
12use mrw::Util;
13use Scalar::Util qw(looks_like_number);
14
15my $serverwizFile;
16my $outputFile;
17GetOptions("i=s" => \$serverwizFile,
18 "o=s" => \$outputFile) or printUsage();
19
20if ((not defined $serverwizFile) ||
21 (not defined $outputFile))
22{
23 printUsage();
24}
25
26my $targets = Targets->new;
27$targets->loadXML($serverwizFile);
28
29my @inventory = Inventory::getInventory($targets);
30
31my %fans = findFans();
32
33printFanYAML(\%fans, $outputFile);
34
35
36#This function returns a hash representing the fans in the system.
37#The hash looks like:
38# $fans{<name>}{<zone>}
39# $fans{<name>}{<profile>}
40# @fans{<name>}{sensors}
41#
42# Where:
43# <name> = inventory name
44# <zone> = cooling zone number
45# <profile> = cooling zone profile, such as air, water, or all
46# <sensors> = an array of the hwmon sensors for the fan's tachs
47sub findFans
48{
49 my %tachs;
50 my %fans;
51
52 #Find fans by looking at the TACH connections. We could also find
53 #parts of type FAN, but we need the tach connection anyway to
54 #lookup the sensors on the other end...
55 for my $target (keys %{$targets->getAllTargets()})
56 {
57 my $connections = $targets->findConnections($target, "TACH");
58 next if ($connections eq "");
59
60 for my $tach (sort @{$connections->{CONN}})
61 {
62 #Because findConnections is recursive, we can hit this same
63 #connection multiple times, so only use it once.
64 next if (exists $tachs{$tach->{SOURCE}}{$tach->{DEST}});
65 $tachs{$tach->{SOURCE}}{$tach->{DEST}} = 1;
66
67 #Note: SOURCE = tach unit on fan, DEST = tach unit on fan ctlr
68
69 my $fru = Util::getEnclosingFru($targets, $tach->{SOURCE});
70 my $name = Util::getObmcName(\@inventory, $fru);
71
72 my $sensor = getSensor($tach->{DEST});
73 push @{$fans{$name}{sensors}}, $sensor;
74
75 #Get the cooling zone and profile from the fan controller part
76 my $part = $targets->getTargetParent($tach->{SOURCE});
77 my $zone = $targets->getAttribute($part, "COOLING_ZONE");
78 if (!looks_like_number($zone))
79 {
80 die "Cooling zone '$zone' on $part is not a number\n";
81 }
82
83 #If the profile isn't set, just set it to be 'all'.
84 my $profile = "";
85 if (!$targets->isBadAttribute($part, "COOLING_ZONE_PROFILE"))
86 {
87 $profile = $targets->getAttribute($part,
88 "COOLING_ZONE_PROFILE");
89 }
90
91 if ($profile eq "")
92 {
93 $profile = "all";
94 }
95
96 $fans{$name}{profile} = lc $profile;
97 $fans{$name}{zone} = $zone;
98 }
99 }
100
101 return %fans;
102}
103
104
105#Find what hwmon will call this unit's reading by looking in
106#the child unit-hwmon-feature unit.
107sub getSensor
108{
109 my ($unit) = @_;
110
111 my @hwmons = Util::getChildUnitsWithTargetType($targets,
112 "unit-hwmon-feature",
113 $unit);
114 die "No HWMON children found for $unit\n" unless (scalar @hwmons != 0);
115
116 my $name = $targets->getAttributeField($hwmons[0],
117 "HWMON_FEATURE",
118 "DESCRIPTIVE_NAME");
119 die "No HWMON name for hwmon unit $hwmons[0]\n" if ($name eq "");
120
121 return $name;
122}
123
124
125#Creates the YAML representation of the data
126sub printFanYAML
127{
128 my ($fans, $file) = @_;
129
130 open (F, ">$file") or die "Could not open $file\n";
131
132 print F "fans:\n";
133
134 while (my ($fan, $data) = each(%{$fans}))
135 {
136 print F " - inventory: $fan\n";
137 print F " cooling_zone: $data->{zone}\n";
138 print F " cooling_profile: $data->{profile}\n";
139 print F " sensors:\n";
140 for my $s (@{$data->{sensors}})
141 {
142 print F " - $s\n";
143 }
144 }
145
146 close F;
147}
148
149
150sub printUsage
151{
152 print "$0 -i [XML filename] -o [output YAML filename]\n";
153 exit(1);
154}