1#!/usr/bin/env perl
2
3use strict;
4use warnings;
5
6use mrw::Targets;
7use mrw::Inventory;
8use mrw::Util;
9use Getopt::Long; # For parsing command line arguments
10use YAML::Tiny qw(LoadFile);
11# Globals
12my $serverwizFile  = "";
13my $debug           = 0;
14my $outputFile     = "";
15my $metaDataFile   = "";
16my $skipBrokenMrw  = 0;
17
18# Command line argument parsing
19GetOptions(
20"i=s" => \$serverwizFile,    # string
21"m=s" => \$metaDataFile,     # string
22"o=s" => \$outputFile,       # string
23"skip-broken-mrw" => \$skipBrokenMrw,
24"d"   => \$debug,
25)
26or printUsage();
27
28if (($serverwizFile eq "") or ($outputFile eq "") or ($metaDataFile eq ""))
29{
30    printUsage();
31}
32
33my $targetObj = Targets->new;
34$targetObj->loadXML($serverwizFile);
35
36#open the mrw xml and the metaData file for the fru.
37#Fetch the FRU id,type,object path from the mrw.
38#Get the metadata for that fru from the metadata file.
39#Merge the data into the outputfile
40
41open(my $fh, '>', $outputFile) or die "Could not open file '$outputFile' $!";
42my $fruTypeConfig = LoadFile($metaDataFile);
43
44my @interestedTypes = keys %{$fruTypeConfig};
45my %types;
46@types{@interestedTypes} = ();
47
48my %entityInfoDict;
49
50my @allAssoTypes = getAllAssociatedTypes($fruTypeConfig);
51my %allAssoTypesHash;
52@allAssoTypesHash{@allAssoTypes} = ();
53
54my @inventory = Inventory::getInventory($targetObj);
55for my $item (@inventory) {
56    my $isFru = 0, my $fruID = 0, my $fruType = "";
57    my $entityInstance = 1, my $entityID = 0;
58
59    #Fetch the FRUID.
60    if (!$targetObj->isBadAttribute($item->{TARGET}, "FRU_ID")) {
61        $fruID = $targetObj->getAttribute($item->{TARGET}, "FRU_ID");
62        $isFru = 1;
63    }
64    #Fetch the FRU Type.
65    if (!$targetObj->isBadAttribute($item->{TARGET}, "TYPE")) {
66        $fruType = $targetObj->getAttribute($item->{TARGET}, "TYPE");
67    }
68
69    #Skip if any one is true
70    #1) If not fru
71    #2) if the fru type is not there in the config file.
72    #3) if the fru type is in associated types.
73    #4) if FRU_ID is not defined for the target and we are asked to ignore such
74    #   targets.
75
76    next if ($skipBrokenMrw and ($fruID eq ""));
77
78    next if (not $isFru or not exists $types{$fruType} or exists $allAssoTypesHash{$fruType});
79
80    printDebug ("FRUID => $fruID, FRUType => $fruType, ObjectPath => $item->{OBMC_NAME}");
81
82    print $fh $fruID.":";
83    print $fh "\n";
84
85    $entityID = $fruTypeConfig->{$fruType}->{'EntityID'};
86
87    if (exists $entityInfoDict{$entityID}) {
88        $entityInstance = $entityInfoDict{$entityID} + 1;
89    }
90
91    printDebug("entityID => $entityID , entityInstance => $entityInstance");
92
93    $entityInfoDict{$entityID} = $entityInstance;
94
95    writeToFile($fruType,$item->{OBMC_NAME},$fruTypeConfig,$fh);
96
97    #if the key(AssociatedTypes) exists and  it is defined
98    #then make the association.
99
100    if (!defined $fruTypeConfig->{$fruType}->{'AssociatedTypes'}) {
101        next;
102    }
103
104    my $assoTypes = $fruTypeConfig->{$fruType}->{'AssociatedTypes'};
105    for my $type (@$assoTypes) {
106        my @devices = Util::getDevicePath(\@inventory,$targetObj,$type);
107        for my $device (@devices) {
108            writeToFile($type,$device,$fruTypeConfig,$fh);
109        }
110
111    }
112
113}
114close $fh;
115
116#------------------------------------END OF MAIN-----------------------
117
118# Get all the associated types
119sub getAllAssociatedTypes
120{
121   my $fruTypeConfig = $_[0];
122   my @assoTypes;
123   while (my($key, $value) = each %$fruTypeConfig) {
124        #if the key exist and value is also there
125        if (defined $value->{'AssociatedTypes'}) {
126            my $assoTypes = $value->{'AssociatedTypes'};
127            for my $type (@$assoTypes) {
128                push(@assoTypes,$type);
129            }
130        }
131   }
132   return @assoTypes;
133}
134
135#Get the metadata for the incoming frutype from the loaded config file.
136#Write the FRU data into the output file
137
138sub writeToFile
139{
140    my $fruType = $_[0];#fru type
141    my $instancePath = $_[1];#instance Path
142    my $fruTypeConfig = $_[2];#loaded config file (frutypes)
143    my $fh = $_[3];#file Handle
144    #walk over all the fru types and match for the incoming type
145
146    print $fh "  ".$instancePath.":";
147    print $fh "\n";
148    print $fh "    "."entityID: ".$fruTypeConfig->{$fruType}->{'EntityID'};
149    print $fh "\n";
150    print $fh "    "."entityInstance: ";
151    print $fh $entityInfoDict{$fruTypeConfig->{$fruType}->{'EntityID'}};
152    print $fh "\n";
153    print $fh "    "."interfaces:";
154    print $fh "\n";
155
156    my $interfaces = $fruTypeConfig->{$fruType}->{'Interfaces'};
157
158    #Walk over all the interfaces as it needs to be written
159    while ( my ($interface,$properties) = each %{$interfaces}) {
160        print $fh "      ".$interface.":";
161        print $fh "\n";
162        #walk over all the properties as it needs to be written
163        while ( my ($dbusProperty,$metadata) = each %{$properties}) {
164                    #will write property named "Property" first then
165                    #other properties.
166            print $fh "        ".$dbusProperty.":";
167            print $fh "\n";
168            for my $key (sort keys %{$metadata}) {
169                print $fh "          $key: "."$metadata->{$key}";
170                print $fh "\n";
171            }
172        }
173    }
174}
175
176# Usage
177sub printUsage
178{
179    print "
180    $0 -i [MRW filename] -m [MetaData filename] -o [Output filename] [OPTIONS]
181Options:
182    -d = debug mode
183    --skip-broken-mrw = Skip broken MRW targets
184        \n";
185    exit(1);
186}
187
188# Helper function to put debug statements.
189sub printDebug
190{
191    my $str = shift;
192    print "DEBUG: ", $str, "\n" if $debug;
193}
194
195