1#!/usr/bin/env perl 2 3#This script generates YAML that defines the presence detects used 4#for FRUs. Its output is used by code that determines which FRUs 5#are present in a system. 6 7use strict; 8use warnings; 9 10use Getopt::Long; 11use mrw::Inventory; 12use mrw::Targets; 13use mrw::Util; 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); 30my %presence; 31 32findTachBasedPresenceDetects(\%presence); 33 34#Future: Find other sorts of presence detects 35 36printYAML(\%presence, $outputFile); 37 38exit 0; 39 40 41#Finds FRUs and their Presence detects where a tach reading 42#is used as the presence detect, such as when a nonzero fan RPM 43#tach reading can be used to tell that a particular fan is present. 44sub findTachBasedPresenceDetects 45{ 46 my ($presence) = @_; 47 my %tachs; 48 49 for my $target (keys %{$targets->getAllTargets()}) 50 { 51 my $connections = $targets->findConnections($target, "TACH"); 52 next if ($connections eq ""); 53 54 for my $tach (sort @{$connections->{CONN}}) 55 { 56 #Because findConnections is recursive, we can hit this same 57 #connection multiple times so only use it once. 58 next if (exists $tachs{$tach->{SOURCE}}{$tach->{DEST}}); 59 $tachs{$tach->{SOURCE}}{$tach->{DEST}} = 1; 60 61 my $fru = Util::getEnclosingFru($targets, $tach->{SOURCE}); 62 my $name = Util::getObmcName(\@inventory, $fru); 63 if (not defined $name) 64 { 65 die "$target was not found in the inventory\n"; 66 } 67 68 my $sensor = getSensor($tach->{DEST}); 69 70 #For now, assuming only fans use tachs 71 $$presence{Tach}{$name}{type} = 'Fan'; 72 73 #Multi-rotor fans will have > 1 sensors per FRU 74 push @{$$presence{Tach}{$name}{sensors}}, $sensor; 75 } 76 } 77} 78 79 80#Creates the YAML representation of the data 81sub printYAML 82{ 83 my ($presence, $outputFile) = @_; 84 open (F, ">$outputFile") or die "Could not open $outputFile\n"; 85 86 while (my ($method, $FRUs) = each(%{$presence})) 87 { 88 print F "- $method:\n"; 89 while (my ($name, $data) = each(%{$FRUs})) 90 { 91 my ($prettyName) = $name =~ /\b(\w+)$/; 92 93 print F " - PrettyName: $prettyName\n"; 94 print F " Inventory: $name\n"; 95 print F " Description:\n"; #purposely leaving blank. 96 print F " Sensors:\n"; 97 for my $s (@{$data->{sensors}}) 98 { 99 print F " - $s\n"; 100 } 101 } 102 } 103 104 close F; 105} 106 107 108#Find what hwmon will call this unit's reading by looking in 109#the child unit-hwmon-feature unit. 110sub getSensor 111{ 112 my ($unit) = @_; 113 114 my @hwmons = Util::getChildUnitsWithTargetType($targets, 115 "unit-hwmon-feature", 116 $unit); 117 die "No HWMON children found for $unit\n" unless (scalar @hwmons != 0); 118 119 my $name = $targets->getAttributeField($hwmons[0], 120 "HWMON_FEATURE", 121 "DESCRIPTIVE_NAME"); 122 die "No HWMON name for hwmon unit $hwmons[0]\n" if ($name eq ""); 123 124 return $name; 125} 126 127 128sub printUsage 129{ 130 print "$0 -i [XML filename] -o [output YAML filename]\n"; 131 exit(1); 132} 133