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