#!/usr/bin/perl

BEGIN { unshift (@INC, "/var/adm/invscout"); }
use VPD_List;


# ================================================================================+
#                                    M A I N                                      |
# ================================================================================+


# -- If user doesn't specify input, TM defaults to "7045" --
my ($TM)               = &checkUserInput() || "7045";

# -- The output file name --
my ($cOUTPUT_FILE_NAME) = "/var/adm/invscout/Switch.vup";


# ----------------------------------------
# -- Creating the Output File Header --
my ($header) = &createHeader();



# ----------------------------------------
# -- Getting Switch Node Number
my ($switchNumber)     = &getSwitchNetworkNumber();

if ($switchNumber < 1)
{
  # -- Invalid Switch Number
  exit(1);
}



# ----------------------------------------
# my ($vpdList)          = VPD_List->new("FederationSwitch.vpd");   # -- for Debugging --
my ($vpdList)          = VPD_List->new("/opt/hsc/bin/vpdfs -y netvpd -n $switchNumber | ");

if ( $vpdList->VPD_List_IsEmpty() )
{
  # -- Error, List is empty --
  exit(2);
}


# ----------------------------------------
my ($smallestSE_Index) = &findTheSmallestSE($TM, $vpdList);

my($vpd)               = $vpdList->get_VPD_Object($smallestSE_Index);


# ----------------------------------------
# -- This becomes the first line of "Switch.vup" --
# -- Example : 7045-xxx_1234567.vup
# -- Then followed by the rest of the VPDs --

my($lowestMTMS_FileName) = "7045-xxx_unknown.vup";  # -- default --
if ( ( $vpd->has_Keys("TM") && ($vpd->get_Value("TM") ne "") ) &&
     ( $vpd->has_Keys("SE") && ($vpd->get_Value("SE") ne "") ) )
{
  $lowestMTMS_FileName   =   $vpd->get_Value("TM") . "_" . $vpd->get_Value("SE") . ".vup";
}


print "Writing output to : $cOUTPUT_FILE_NAME\n";
print "\n";
open (fOUT, "> $cOUTPUT_FILE_NAME") || die ("Unable to write a file\n");
  print fOUT "$lowestMTMS_FileName\n";
  $header->write_Object(\*fOUT);
  $vpdList->write_Object(\*fOUT);
close (fOUT);



exit(0);
# ================================================================================





# --------------------------------------------------------------------------------+
# -- Name     : findTheSmallestSE                                                 |
# -- Function : Searches the VPD List and perform a Linear Search to find         |
# --              the VPD Block with the specified TM and contains the smallest   |
# --              SE (SerialNumber)                                               |
# -- Input    : TM       = partial TM string to be searched (ex: "7040")          |
# --            VPD_List = VPD_List object                                        |
# -- Output   : An index of the VPD_List where the smallest SE exists             |
# --------------------------------------------------------------------------------+
sub findTheSmallestSE
{
  my($inTM, $inVPD_List) = @_;

  my (@TM_List) = $inVPD_List->get_VPDsWithKey("TM", "SE");

  my ($TM_Index, $smallestSE_Index)   = ();
  my ($smallestSE) = "" . 0xFF x 9;  # -- some large Alphabet sequence --

  foreach $TM_Index (@TM_List)  # -- Linear Search --
  {
    my ($vpd) = $inVPD_List->get_VPD_Object($TM_Index);
    if (
        ( $vpd->get_Value("TM") =~ /^$inTM/ ) &&    # -- if this is the correct VPD block --
        ( ( $smallestSE gt $vpd->get_Value('SE') ) && ( $vpd->get_Value('SE') ne "" ) )
        )
    {
      $smallestSE = $vpd->get_Value('SE');
      $smallestSE_Index = $TM_Index;
    }
  }
  
  return($smallestSE_Index);
}



# --------------------------------------------------------------------------------+
# -- Name     : checkUserInput                                                    |
# -- Function : Checks the ARGV for user Input                                    |
# -- Input    : optional ARGV[0] = the value of TM                                |
# -- Output   : returns ARGV[0]                                                   |
# --------------------------------------------------------------------------------+
sub checkUserInput
{
  return ( $ARGV[0] ) if ( $ARGV[0] );
}




# --------------------------------------------------------------------------------+
# -- Name     : createHeader                                                      |
# -- Function : Creates Header for Switch.vup files.. see comments below          |
# -- Input    : None                                                              |
# -- Output   : VPD_List object representation of the header                      |
# --------------------------------------------------------------------------------+
sub createHeader
{
  # -- Header consists of stanza/data in the following order
  # --    1. Inventory Scout Stanza
  # --    2. The output of "lshsc -v"
  # --
  # -- However, Inventory Scout stanza uses data from the lshsc -v.
  # --   Therefore, we need to perform #2 first --

  # ----------------------------------------
  # -- #2. Get the Hardware Management Console's hardware VPD information in RPA VPD format
  # --     (using "lshsc -v" command)

  # my ($hmcVPD_List)    = VPD_List->new("lshsc-v.out");  # -- for debugging --
  my ($hmcVPD_List)    = VPD_List->new("/opt/hsc/bin/lshsc -v |");


  # ----------------------------------------
  # -- #1. Get Inventory Scout Stanza Header --
  my ($inventoryScoutHeader) = &createInventoryScoutStanzaHeader($hmcVPD_List);

  # ----------------------------------------
  # -- Insert the Inventory Scout Header at the beginning of the List --
  $hmcVPD_List->insert_VPD_Objects(0, $inventoryScoutHeader);

  return($hmcVPD_List);
}




# --------------------------------------------------------------------------------+
# -- Name     : createInventoryScoutStanzaHeader				  |
# -- Function : Create Inventory Scout Stanza Header for Switch.vup files..	  |
# --              See comments below for an example.				  |
# -- Input    : VPD_List object that contains the HMC VPD info 			  |
# --                 (from `lshsc -v` command)					  |
# -- Output   : returns one VPD object representation of the Header		  |
# --------------------------------------------------------------------------------+
sub createInventoryScoutStanzaHeader
{
  # -- *FC ????????
  # -- *VC 15.0
  # -- *N1  :1.3.3.0                        (script version, could pull from invscout, but not required. ) 
  # -- *N2 Tue Sep 09 19:37:22 EDT 2003     ( time stamp) 
  # -- *V3  HMC MTMS                        (gotten from VPD by lshsc -v)

  my ($inHMC_VPD_List) = @_;

  # -- Find the first stanza that contains TM and SE. 
  my ($TM_Index)       = $inHMC_VPD_List->get_VPDsWithKey("TM", "SE");
  my ($vpd, $hmcMTMS) = ();
  if (defined $TM_Index)
  {
    $vpd = $inHMC_VPD_List->get_VPD_Object($TM_Index);
    $hmcMTMS  = $vpd->get_Value('TM') . "_" . $vpd->get_Value('SE');
  }
  else
  {
    $hmcMTMS = "HMC_MTMS: Unable to get this data";  # -- can't get it from "lshsc -v" --
  }

  my($date) = `date`;   $date =~ s/\n//g;


  # ----------------------------------------
  my($outputStanza) = VPD->new();
  $outputStanza->add_Property("VC", "15.0");
#  $outputStanza->add_Property("N1", "2.0-3");   # -- for debugging --
  $outputStanza->add_Property("N1", &getInventoryScoutVersion());
  $outputStanza->add_Property("N2", $date);
  $outputStanza->add_Property("V3", $hmcMTMS);

  return($outputStanza);
}


# --------------------------------------------------------------------------------+
# -- Name     : getInventoryScoutVersion                                          |
# -- Function : Query the HMC for the IBM Inventory Scout program version         |
# --             by using the RPM command                                         |
# -- Input    : none                                                              |
# -- Output   : String representation of IBM Inventory Scout version              |
# --------------------------------------------------------------------------------+
sub getInventoryScoutVersion
{
  # -- Acquire the version using RPM command --
  # -- # rpm -q IBMinvscout
  # -- IBMinvscout-2.0-3

  my ($packageName, $invscoutVersion) = ();

  $packageName     = "IBMinvscout";
  $invscoutVersion = `rpm -q $packageName`;
  $invscoutVersion =~ s/$packageName-//;
  $invscoutVersion =~ s/\n//g;

  return ($invscoutVersion);
}



# --------------------------------------------------------------------------------+
# -- Name     : getSwitchNetworkNumber                                            |
# -- Function : Get Switch Network Number (see comments below)                    |
# -- Input    : none                                                              |
# -- Output   : returns Switch Network number                                     |
# --------------------------------------------------------------------------------+
sub getSwitchNetworkNumber
{
  # -- determine the switch network number(s) 
  # -- 
  # -- [root@c288hmc2 hscroot]# i_stub_FS dump -n
  # -- 1 1 0 0 1 16 0 0 1 16
  # -- 
  # -- the first number of each line is the network number  

  # my($switchNetworkNumber) = "1 1 0 0 1 16 0 0 1 16";  # -- for Debugging --
  my($switchNetworkNumber) = `i_stub_FS dump -n`;

  $switchNetworkNumber =~ s/\s.+//;  # -- find the first space and take out the rest --

  return($switchNetworkNumber);
}
