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