blob: ef9e95c54514b1d1e88cc9324cd03f86810fbb33 [file] [log] [blame]
Vishwanatha Subbannad0039432017-03-30 00:10:47 +05301#!/usr/bin/env perl
Vishwanatha Subbanna37066462016-12-13 17:06:18 +05302use 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
Vishwanatha Subbannad0039432017-03-30 00:10:47 +05309use List::Util qw(first);
Vishwanatha Subbanna37066462016-12-13 17:06:18 +053010
11# Globals
12my $force = 0;
13my $serverwizFile = "";
14my $debug = 0;
15my $outputFile = "";
16my $verbose = 0;
17
18# Command line argument parsing
19GetOptions(
20"f" => \$force, # numeric
21"i=s" => \$serverwizFile, # string
22"o=s" => \$outputFile, # string
23"d" => \$debug,
24"v" => \$verbose,
25)
26or printUsage();
27
28if (($serverwizFile eq "") or ($outputFile eq ""))
29{
30 printUsage();
31}
32
33# Hashmap of all the LED groups with the properties
34my %hashGroup;
35
36# hash of targets to Names that have the FRU Inventory instances
37my %invHash;
38
39# Array of Enclosure Fault LED names. These are generally
40# front-fault-led and rear-fault-led
41my @encFaults;
42
Vishwanatha Subbannad0039432017-03-30 00:10:47 +053043# These groups are a must in all the systems.
44# Its fine if they don't map to any physical LED
45my @defaultGroup = ("BmcBooted", "PowerOn");
46
Vishwanatha Subbannac5e127d2017-05-15 12:08:42 +053047# This group contains all the LEDs with the action Blink
48my $lampTest = "LampTest";
49
Vishwanatha Subbanna37066462016-12-13 17:06:18 +053050# API used to access parsed XML data
51my $targetObj = Targets->new;
52if($verbose == 1)
53{
54 $targetObj->{debug} = 1;
55}
56
57if($force == 1)
58{
59 $targetObj->{force} = 1;
60}
61
62$targetObj->loadXML($serverwizFile);
63print "Loaded MRW XML: $serverwizFile \n";
64
65# Iterate over Inventory and get all the Inventory targets.
66my @inventory = Inventory::getInventory($targetObj);
67for my $item (@inventory)
68{
69 # Target to Obmc_Name hash.
70 $invHash{$item->{TARGET}} = $item->{OBMC_NAME};
71}
72
73# For debugging purpose.
74printDebug("\nList of Inventory targets\n");
75foreach my $key (sort keys %invHash)
76{
77 printDebug("$invHash{$key}\n");
78}
79
80# Process all the targets in the XML. If the target is associated with a FRU,
81# then remember it so that when we do the FRU inventory lookup, we know if
82# that Inventory has a LED associated with it or not.
83foreach my $target (sort keys %{$targetObj->getAllTargets()})
84{
85 # Some the target instances may *not* have this MRW_TYPE attribute.
86 if($targetObj->isBadAttribute($target, "MRW_TYPE"))
87 {
88 next;
89 }
90
91 # Return true if not populated -or- not present
92 if("LED" eq $targetObj->getMrwType($target))
93 {
94 # Just for clarity.
95 my $ledTarget = $target;
96
97 # OBMC_NAME field of the FRU
98 # fruPath ex /system/chassis/motherboard/dimm1
99 # device "dimm1"
100 my $fruPath = '';
101 my $device = '';
102
103 # Get if this LED is a ENC-FAULT type.
104 if(!$targetObj->isBadAttribute($target, "LED_TYPE"))
105 {
106 if("ENC-FAULT" eq $targetObj->getAttribute($ledTarget, "LED_TYPE"))
107 {
108 push @encFaults, $targetObj->getInstanceName($ledTarget);
109 }
110 }
111
112 # Find if this LED is associated with a FRU.
113 # Example, FAN will have LED on that assembly.
114 my $conns = $targetObj->findConnections($ledTarget, "LOGICAL_ASSOCIATION");
115 if ($conns ne "")
116 {
117 # This LED is associated with a FRU
118 for my $conn (@{$conns->{CONN}})
119 {
120 my $destTarget = $conn->{DEST_PARENT};
121 # If we have found this, then that means, we do not need to
122 # hand cook a group name. delete this value from the inventory
123 # array
124 if(exists($invHash{$destTarget}))
125 {
126 # This will remove a particular {key, value} pair
127 $fruPath = $invHash{$destTarget};
128 printDebug("$destTarget : $fruPath is having associated LED\n");
129 delete ($invHash{$destTarget});
130 }
131 }
132 # fetch FruName from the device path
133 $device = getFruName($fruPath);
134 printDebug("$target; $device has device\n");
135 }
136
137 if($targetObj->isBadAttribute($ledTarget, "CONTROL_GROUPS"))
138 {
139 next;
140 }
141
Vishwanatha Subbannaa9660422017-05-05 16:06:21 +0530142 # By default, Blink takes higher priority
143 my $priority = "'Blink'";
144
145 # Get the priority. Since rest everything is populated,
146 # default to Blink than err'ing out. Not checking for
147 # validity of this since it must be present.
148 if($targetObj->getAttribute($ledTarget, "LED_PRIORITY") eq "ON")
149 {
150 $priority = "'On'";
151 }
152
Vishwanatha Subbanna37066462016-12-13 17:06:18 +0530153 # Need this to populate the table incase the device is empty
154 my $instance = $targetObj->getInstanceName($ledTarget);
155
156 my $controlGroup = $targetObj->getAttribute($ledTarget, "CONTROL_GROUPS");
157
158 #remove spaces, because serverwiz isn't good at removing them itself
159 $controlGroup =~ s/\s//g;
160 my @groups= split(',', $controlGroup); #just a long 16x3 = 48 element list
161
162 for (my $i = 0; $i < scalar @groups; $i += 3)
163 {
164 if (($groups[$i] ne "NA") && ($groups[$i] ne ""))
165 {
166 my $groupName = $groups[$i];
167 printDebug("$groupName\n");
168
169 my $blinkFreq = $groups[$i+1];
170 my $action = "'On'";
171 my $period = 0;
172
173 # Period in milli seconds
174 my $dutyCycle = $groups[$i+2];
175 if($blinkFreq > 0)
176 {
177 $action = "'Blink'";
178 $period = (1 / $blinkFreq) * 1000;
179 }
180
181 # Insert into hash map;
182 my $fru = ($device eq '') ? $instance : $device;
183 $hashGroup{$groupName}{$fru}{"Action"} = $action;
184 $hashGroup{$groupName}{$fru}{"Period"} = $period;
185 $hashGroup{$groupName}{$fru}{"DutyOn"} = $dutyCycle;
Vishwanatha Subbannaa9660422017-05-05 16:06:21 +0530186 $hashGroup{$groupName}{$fru}{"Priority"} = $priority;
Vishwanatha Subbannac5e127d2017-05-15 12:08:42 +0530187
188 # Need to update the LampTest group.
189 $hashGroup{$lampTest}{$fru}{"Action"} = "'Blink'";
190 $hashGroup{$lampTest}{$fru}{"Period"} = 1000;
191 $hashGroup{$lampTest}{$fru}{"DutyOn"} = 50;
Vishwanatha Subbannaa9660422017-05-05 16:06:21 +0530192 $hashGroup{$lampTest}{$fru}{"Priority"} = "'Blink'";
Vishwanatha Subbanna37066462016-12-13 17:06:18 +0530193 }
194 } # Walk CONTROL_GROUP
195 } # Has LED target
196} # All the targets
197
198
199# These are the FRUs that do not have associated LEDs. All of these need to be
200# mapped to some group, which will be named after this target name and the
201# elements of the group are EnclosureFaults Front and Back
202printDebug("\n======================================================================\n");
203printDebug("\nFRUs that do not have associated LEDs\n");
204foreach my $key (sort keys %invHash)
205{
206 my $device = getFruName($invHash{$key});
207
208 # For each of these device, the Group record would be this :
209 my $groupName = $device . "Fault";
210 printDebug("$device :: $groupName\n");
211
212 # Setup roll-up LEDs to the ones that are of type ENC-FAULT
213 foreach my $led (0 .. $#encFaults)
214 {
215 $hashGroup{$groupName}{$encFaults[$led]}{"Action"} = "'On'";
216 $hashGroup{$groupName}{$encFaults[$led]}{"Period"} = 0;
217 $hashGroup{$groupName}{$encFaults[$led]}{"DutyOn"} = 50;
Vishwanatha Subbannaa9660422017-05-05 16:06:21 +0530218 $hashGroup{$groupName}{$encFaults[$led]}{"Priority"} = "'Blink'";
Vishwanatha Subbanna37066462016-12-13 17:06:18 +0530219 }
220}
221printDebug("\n======================================================================\n");
222
223# Generate the yaml file
224generateYamlFile();
225#------------------------------------END OF MAIN-----------------------
226
227# Gven a '/' separated string, returns the leaf.
228# Ex: /a/b/c/d returns device=d
229sub getFruName
230{
231 my $path = shift;
232 my $device = '';
233 my $lastSlash=rindex($path, '/');
234 $device=substr($path, $lastSlash+1);
235}
236
237sub generateYamlFile
238{
239 my $fileName = $outputFile;
240 my $groupCopy = '';
241 my $ledCopy = '';
242 open(my $fh, '>', $fileName) or die "Could not open file '$fileName' $!";
243
244 foreach my $group (sort keys %hashGroup)
245 {
246 if($group ne $groupCopy)
247 {
Vishwanatha Subbannad0039432017-03-30 00:10:47 +0530248 # If one of these is a default group, then delete it from the array
249 # that is being maintained to create one by hand if all default ones
250 # are not defined
251 my $index = first {$defaultGroup[$_] eq $group} 0..$#defaultGroup;
252 if (defined $index)
253 {
254 splice @defaultGroup, $index, 1;
255 }
256
Vishwanatha Subbanna37066462016-12-13 17:06:18 +0530257 $groupCopy = '';
258 $ledCopy = '';
259 }
260
Vishwanatha Subbannac5e127d2017-05-15 12:08:42 +0530261 foreach my $led (sort keys %{ $hashGroup{$group} })
Vishwanatha Subbanna37066462016-12-13 17:06:18 +0530262 {
Vishwanatha Subbannac5e127d2017-05-15 12:08:42 +0530263 foreach my $property (sort keys %{ $hashGroup{$group}{$led}})
Vishwanatha Subbanna37066462016-12-13 17:06:18 +0530264 {
265 if($group ne $groupCopy)
266 {
267 $groupCopy = $group;
268 print $fh "$group:\n";
269 }
270 print $fh " ";
271 if($led ne $ledCopy)
272 {
273 $ledCopy = $led;
274 print $fh "$led:\n";
275 print $fh " ";
276 }
277 print $fh " ";
278 print $fh "$property:";
279 print $fh " $hashGroup{$group}{$led}{$property}\n";
280 }
281 }
282 }
Vishwanatha Subbannad0039432017-03-30 00:10:47 +0530283 # If we need to hand create some of the groups, do so now.
284 foreach my $name (@defaultGroup)
285 {
286 print $fh "$name:\n";
287 }
Vishwanatha Subbanna37066462016-12-13 17:06:18 +0530288 close $fh;
289}
290
291# Helper function to put debug statements.
292sub printDebug
293{
294 my $str = shift;
295 print "DEBUG: ", $str, "\n" if $debug;
296}
297
298# Usage
299sub printUsage
300{
301 print "
302 $0 -i [XML filename] -o [Output filename] [OPTIONS]
303Options:
304 -f = force output file creation even when errors
305 -d = debug mode
306 -v = verbose mode - for verbose o/p from Targets.pm
307
308PS: mrw::Targets can be found in https://github.com/open-power/serverwiz/
309 mrw::Inventory can be found in https://github.com/openbmc/phosphor-mrw-tools/
310 \n";
311 exit(1);
312}
313#------------------------------------END OF SUB-----------------------