blob: 55305789853da388ae7d0e440135198391724e41 [file] [log] [blame]
Vishwanatha Subbanna37066462016-12-13 17:06:18 +05301#!/usr/bin/perl
2use strict;
3use warnings;
4
5use mrw::Targets; # Set of APIs allowing access to parsed ServerWiz2 XML output
6use mrw::Inventory; # To get list of Inventory targets
7use Getopt::Long; # For parsing command line arguments
8use Data::Dumper qw(Dumper); # Dumping blob
9
10# Globals
11my $force = 0;
12my $serverwizFile = "";
13my $debug = 0;
14my $outputFile = "";
15my $verbose = 0;
16
17# Command line argument parsing
18GetOptions(
19"f" => \$force, # numeric
20"i=s" => \$serverwizFile, # string
21"o=s" => \$outputFile, # string
22"d" => \$debug,
23"v" => \$verbose,
24)
25or printUsage();
26
27if (($serverwizFile eq "") or ($outputFile eq ""))
28{
29 printUsage();
30}
31
32# Hashmap of all the LED groups with the properties
33my %hashGroup;
34
35# hash of targets to Names that have the FRU Inventory instances
36my %invHash;
37
38# Array of Enclosure Fault LED names. These are generally
39# front-fault-led and rear-fault-led
40my @encFaults;
41
42# API used to access parsed XML data
43my $targetObj = Targets->new;
44if($verbose == 1)
45{
46 $targetObj->{debug} = 1;
47}
48
49if($force == 1)
50{
51 $targetObj->{force} = 1;
52}
53
54$targetObj->loadXML($serverwizFile);
55print "Loaded MRW XML: $serverwizFile \n";
56
57# Iterate over Inventory and get all the Inventory targets.
58my @inventory = Inventory::getInventory($targetObj);
59for my $item (@inventory)
60{
61 # Target to Obmc_Name hash.
62 $invHash{$item->{TARGET}} = $item->{OBMC_NAME};
63}
64
65# For debugging purpose.
66printDebug("\nList of Inventory targets\n");
67foreach my $key (sort keys %invHash)
68{
69 printDebug("$invHash{$key}\n");
70}
71
72# Process all the targets in the XML. If the target is associated with a FRU,
73# then remember it so that when we do the FRU inventory lookup, we know if
74# that Inventory has a LED associated with it or not.
75foreach my $target (sort keys %{$targetObj->getAllTargets()})
76{
77 # Some the target instances may *not* have this MRW_TYPE attribute.
78 if($targetObj->isBadAttribute($target, "MRW_TYPE"))
79 {
80 next;
81 }
82
83 # Return true if not populated -or- not present
84 if("LED" eq $targetObj->getMrwType($target))
85 {
86 # Just for clarity.
87 my $ledTarget = $target;
88
89 # OBMC_NAME field of the FRU
90 # fruPath ex /system/chassis/motherboard/dimm1
91 # device "dimm1"
92 my $fruPath = '';
93 my $device = '';
94
95 # Get if this LED is a ENC-FAULT type.
96 if(!$targetObj->isBadAttribute($target, "LED_TYPE"))
97 {
98 if("ENC-FAULT" eq $targetObj->getAttribute($ledTarget, "LED_TYPE"))
99 {
100 push @encFaults, $targetObj->getInstanceName($ledTarget);
101 }
102 }
103
104 # Find if this LED is associated with a FRU.
105 # Example, FAN will have LED on that assembly.
106 my $conns = $targetObj->findConnections($ledTarget, "LOGICAL_ASSOCIATION");
107 if ($conns ne "")
108 {
109 # This LED is associated with a FRU
110 for my $conn (@{$conns->{CONN}})
111 {
112 my $destTarget = $conn->{DEST_PARENT};
113 # If we have found this, then that means, we do not need to
114 # hand cook a group name. delete this value from the inventory
115 # array
116 if(exists($invHash{$destTarget}))
117 {
118 # This will remove a particular {key, value} pair
119 $fruPath = $invHash{$destTarget};
120 printDebug("$destTarget : $fruPath is having associated LED\n");
121 delete ($invHash{$destTarget});
122 }
123 }
124 # fetch FruName from the device path
125 $device = getFruName($fruPath);
126 printDebug("$target; $device has device\n");
127 }
128
129 if($targetObj->isBadAttribute($ledTarget, "CONTROL_GROUPS"))
130 {
131 next;
132 }
133
134 # Need this to populate the table incase the device is empty
135 my $instance = $targetObj->getInstanceName($ledTarget);
136
137 my $controlGroup = $targetObj->getAttribute($ledTarget, "CONTROL_GROUPS");
138
139 #remove spaces, because serverwiz isn't good at removing them itself
140 $controlGroup =~ s/\s//g;
141 my @groups= split(',', $controlGroup); #just a long 16x3 = 48 element list
142
143 for (my $i = 0; $i < scalar @groups; $i += 3)
144 {
145 if (($groups[$i] ne "NA") && ($groups[$i] ne ""))
146 {
147 my $groupName = $groups[$i];
148 printDebug("$groupName\n");
149
150 my $blinkFreq = $groups[$i+1];
151 my $action = "'On'";
152 my $period = 0;
153
154 # Period in milli seconds
155 my $dutyCycle = $groups[$i+2];
156 if($blinkFreq > 0)
157 {
158 $action = "'Blink'";
159 $period = (1 / $blinkFreq) * 1000;
160 }
161
162 # Insert into hash map;
163 my $fru = ($device eq '') ? $instance : $device;
164 $hashGroup{$groupName}{$fru}{"Action"} = $action;
165 $hashGroup{$groupName}{$fru}{"Period"} = $period;
166 $hashGroup{$groupName}{$fru}{"DutyOn"} = $dutyCycle;
167 }
168 } # Walk CONTROL_GROUP
169 } # Has LED target
170} # All the targets
171
172
173# These are the FRUs that do not have associated LEDs. All of these need to be
174# mapped to some group, which will be named after this target name and the
175# elements of the group are EnclosureFaults Front and Back
176printDebug("\n======================================================================\n");
177printDebug("\nFRUs that do not have associated LEDs\n");
178foreach my $key (sort keys %invHash)
179{
180 my $device = getFruName($invHash{$key});
181
182 # For each of these device, the Group record would be this :
183 my $groupName = $device . "Fault";
184 printDebug("$device :: $groupName\n");
185
186 # Setup roll-up LEDs to the ones that are of type ENC-FAULT
187 foreach my $led (0 .. $#encFaults)
188 {
189 $hashGroup{$groupName}{$encFaults[$led]}{"Action"} = "'On'";
190 $hashGroup{$groupName}{$encFaults[$led]}{"Period"} = 0;
191 $hashGroup{$groupName}{$encFaults[$led]}{"DutyOn"} = 50;
192 }
193}
194printDebug("\n======================================================================\n");
195
196# Generate the yaml file
197generateYamlFile();
198#------------------------------------END OF MAIN-----------------------
199
200# Gven a '/' separated string, returns the leaf.
201# Ex: /a/b/c/d returns device=d
202sub getFruName
203{
204 my $path = shift;
205 my $device = '';
206 my $lastSlash=rindex($path, '/');
207 $device=substr($path, $lastSlash+1);
208}
209
210sub generateYamlFile
211{
212 my $fileName = $outputFile;
213 my $groupCopy = '';
214 my $ledCopy = '';
215 open(my $fh, '>', $fileName) or die "Could not open file '$fileName' $!";
216
217 foreach my $group (sort keys %hashGroup)
218 {
219 if($group ne $groupCopy)
220 {
221 $groupCopy = '';
222 $ledCopy = '';
223 }
224
225 foreach my $led (keys %{ $hashGroup{$group} })
226 {
227 foreach my $property (keys %{ $hashGroup{$group}{$led}})
228 {
229 if($group ne $groupCopy)
230 {
231 $groupCopy = $group;
232 print $fh "$group:\n";
233 }
234 print $fh " ";
235 if($led ne $ledCopy)
236 {
237 $ledCopy = $led;
238 print $fh "$led:\n";
239 print $fh " ";
240 }
241 print $fh " ";
242 print $fh "$property:";
243 print $fh " $hashGroup{$group}{$led}{$property}\n";
244 }
245 }
246 }
247 close $fh;
248}
249
250# Helper function to put debug statements.
251sub printDebug
252{
253 my $str = shift;
254 print "DEBUG: ", $str, "\n" if $debug;
255}
256
257# Usage
258sub printUsage
259{
260 print "
261 $0 -i [XML filename] -o [Output filename] [OPTIONS]
262Options:
263 -f = force output file creation even when errors
264 -d = debug mode
265 -v = verbose mode - for verbose o/p from Targets.pm
266
267PS: mrw::Targets can be found in https://github.com/open-power/serverwiz/
268 mrw::Inventory can be found in https://github.com/openbmc/phosphor-mrw-tools/
269 \n";
270 exit(1);
271}
272#------------------------------------END OF SUB-----------------------