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