Vishwanatha Subbanna | 3706646 | 2016-12-13 17:06:18 +0530 | [diff] [blame] | 1 | #!/usr/bin/perl |
| 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 |
| 9 | |
| 10 | # Globals |
| 11 | my $force = 0; |
| 12 | my $serverwizFile = ""; |
| 13 | my $debug = 0; |
| 14 | my $outputFile = ""; |
| 15 | my $verbose = 0; |
| 16 | |
| 17 | # Command line argument parsing |
| 18 | GetOptions( |
| 19 | "f" => \$force, # numeric |
| 20 | "i=s" => \$serverwizFile, # string |
| 21 | "o=s" => \$outputFile, # string |
| 22 | "d" => \$debug, |
| 23 | "v" => \$verbose, |
| 24 | ) |
| 25 | or printUsage(); |
| 26 | |
| 27 | if (($serverwizFile eq "") or ($outputFile eq "")) |
| 28 | { |
| 29 | printUsage(); |
| 30 | } |
| 31 | |
| 32 | # Hashmap of all the LED groups with the properties |
| 33 | my %hashGroup; |
| 34 | |
| 35 | # hash of targets to Names that have the FRU Inventory instances |
| 36 | my %invHash; |
| 37 | |
| 38 | # Array of Enclosure Fault LED names. These are generally |
| 39 | # front-fault-led and rear-fault-led |
| 40 | my @encFaults; |
| 41 | |
| 42 | # API used to access parsed XML data |
| 43 | my $targetObj = Targets->new; |
| 44 | if($verbose == 1) |
| 45 | { |
| 46 | $targetObj->{debug} = 1; |
| 47 | } |
| 48 | |
| 49 | if($force == 1) |
| 50 | { |
| 51 | $targetObj->{force} = 1; |
| 52 | } |
| 53 | |
| 54 | $targetObj->loadXML($serverwizFile); |
| 55 | print "Loaded MRW XML: $serverwizFile \n"; |
| 56 | |
| 57 | # Iterate over Inventory and get all the Inventory targets. |
| 58 | my @inventory = Inventory::getInventory($targetObj); |
| 59 | for my $item (@inventory) |
| 60 | { |
| 61 | # Target to Obmc_Name hash. |
| 62 | $invHash{$item->{TARGET}} = $item->{OBMC_NAME}; |
| 63 | } |
| 64 | |
| 65 | # For debugging purpose. |
| 66 | printDebug("\nList of Inventory targets\n"); |
| 67 | foreach 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. |
| 75 | foreach 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 |
| 176 | printDebug("\n======================================================================\n"); |
| 177 | printDebug("\nFRUs that do not have associated LEDs\n"); |
| 178 | foreach 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 | } |
| 194 | printDebug("\n======================================================================\n"); |
| 195 | |
| 196 | # Generate the yaml file |
| 197 | generateYamlFile(); |
| 198 | #------------------------------------END OF MAIN----------------------- |
| 199 | |
| 200 | # Gven a '/' separated string, returns the leaf. |
| 201 | # Ex: /a/b/c/d returns device=d |
| 202 | sub getFruName |
| 203 | { |
| 204 | my $path = shift; |
| 205 | my $device = ''; |
| 206 | my $lastSlash=rindex($path, '/'); |
| 207 | $device=substr($path, $lastSlash+1); |
| 208 | } |
| 209 | |
| 210 | sub 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. |
| 251 | sub printDebug |
| 252 | { |
| 253 | my $str = shift; |
| 254 | print "DEBUG: ", $str, "\n" if $debug; |
| 255 | } |
| 256 | |
| 257 | # Usage |
| 258 | sub printUsage |
| 259 | { |
| 260 | print " |
| 261 | $0 -i [XML filename] -o [Output filename] [OPTIONS] |
| 262 | Options: |
| 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 | |
| 267 | PS: 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----------------------- |