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