package NWS::T3;
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2001, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>

#  $Id: T3.pm,v 1.10 2004/11/04 23:51:19 edunning Exp $

use Report;
use CIM::Instance;
use Data::Dumper;
use Health::T3;
use strict;
use Report;
use Ilist;
use PDM;
use NWS;
sub revision {'$Revision: 1.10 $'}

sub newSystem {
  my ($class, $rep) = @_;
  my(@pil, $i, $dd, $a, $j, $k, $k1, $v);
  my $UNITS;
  my $wwn  = $rep->get('id.wwn'); # really the key now
  my $wwn1 = $rep->get('port.u1p1.portWWN');
  my $renv = System->get_renv();
  my $type = $rep->get("id.device_type");
  my $ctrl_cnt = $rep->get('system.fruCtlrCount');
  $ctrl_cnt = 2 if ($ctrl_cnt > 2);

  my($p1) = CIM::Instance->new('NWS_System',[
                    [Name 		=> $wwn ],
                    [OtherIdentifyingInfo  => "wwn=$wwn1" ],
                    [SystemName         => $rep->get('id.name')],
                    [LogInfo            => $rep->get('info.syslog')],
                    [IP 		=> $rep->get('system.sysIpAddr')],
                    [FruCount 		=> $rep->get('system.fruCount')],
                    [FruCtlrCount 	=> $ctrl_cnt ],
                    [FruDiskDriveCount 	=> $rep->get('system.fruDiskCount')],
                    [FruLoopCount 	=> $rep->get('system.fruLoopCount')],
                    [FruPowerCount 	=> $rep->get('system.fruPowerCount')],
                    [VolCount 		=> $rep->get('system.volCount')],
                    [SysBootDelay 	=> $rep->get('system.sysBootDelay')],
                    [SysBootMode 	=> $rep->get('system.sysBootMode')],
                    [SysCacheMirror	=> $rep->get('system.sysCacheMirror')],
                    [SysCacheMode 	=> $rep->get('system.sysCacheMode')],
                    [SysRevision 	=> $rep->get('system.sysRevision')],
                    [Caption            => uc($type)],
                ]);

  my($p2) = CIM::Instance->new('CIM_PhysicalFrame', [
                  [Tag 			=> $wwn],
                  [Name			=> $wwn],
                  [Manufacturer 	=> $rep->get("system.sysVendor")],
                  [Model 		=> $rep->get("system.sysModel")],
                  ]);

  my($a2) = CIM::Instance->new('CIM_ComputerSystemPackage', [
                  [Antecedent          => $p1],
                  [Dependent           => $p2],
                  ]);

  my($l1) = NWS->location($rep);
  
  my($al1) = CIM::Instance->new('NWS_PhysicalFrameLocation', [
                  [Element 		=> $p2],
                  [PhysicalLocation 	=> $l1],
                  ]);
               
  push (@pil, $p1, $p2, $a2, $l1, $al1);

  $UNITS=  $rep->get('unit.count') || $rep->get('controller.count');

  for ($i = 1; $i <= $UNITS; $i++) {
    if (Health::T3::controller_present($UNITS, $i)) {
      $dd = $class->newController($rep,"controller.u${i}ctr", $i);
      next if (!$dd);
      $a = CIM::Instance->new('CIM_Container', [
                   [GroupComponent  => $p2],
                   [PartComponent => $dd->[1]],
                   [LocationWithinContainer => "controller.u${i}ctr"],
                   ]);
      push (@pil, @$dd);
      push (@pil, $a);
    }
  }


  for ($i = 1; $i <= $UNITS; $i++) {
    $dd = $class->newMidplane($rep,"midplane.u${i}mpn");
    if ($dd) {
      $a = CIM::Instance->new('CIM_Container', [
                   [GroupComponent  => $p2],
                   [PartComponent => $dd->[1]],
                   [LocationWithinContainer => "midplane.u${i}mpn"],
                   ]);
 
      push (@pil, @$dd);
      push (@pil, $a);
    }
  }


  for ($i = 1; $i <= $UNITS; $i++) {
    for ($j = 1; $j <= 2; $j++) {
      $dd = $class->newPowerUnit($rep,"power.u${i}pcu$j");
      next if (!$dd);
      $a = CIM::Instance->new('CIM_Container', [
                   [GroupComponent  => $p2],
                   [PartComponent => $dd->[1]],
                   [LocationWithinContainer => "power.u${i}pcu$j"],
                   ]);
      push (@pil, @$dd);
      push (@pil, $a);


      $dd = $class->newBattery($rep,"power.u${i}pcu$j");
      if ($dd) {
        $a = CIM::Instance->new('CIM_Container', [
                   [GroupComponent  => $p2],
                   [PartComponent => $dd->[1]],
                   [LocationWithinContainer => "power.u${i}pcu$j"],
                   ]);
 
        push (@pil, @$dd);
        push (@pil, $a);
      }
    }
  }

  for ($i = 1; $i <= $UNITS; $i++) {
    for ($j = 1; $j <= 2; $j++) {
      $dd = $class->newLoopCard($rep,"loopcard.u${i}l$j");
      next if (!$dd);
      $a = CIM::Instance->new('CIM_Container', [
                   [GroupComponent  => $p2],
                   [PartComponent => $dd->[1]],
                   [LocationWithinContainer => "loopcard.u${i}l$j"],
                   ]);
      push (@pil, @$dd);
      push (@pil, $a);
    }
  }

  my(@vols);
  my($volCnt) = 0;
  my(%DSK) = ();
  for ($i = 1; $i <= $UNITS; $i++) {
    for ($v=1; $v <= 2; $v++) { # see of volumes exist (max 2).
       if (($rep->get("volume.u${i}vol$v.volName")) &&
           ($rep->get("volume.u${i}vol$v.volStatus") =~ /mounted/)) {

          my $p0 = "u${i}vol$v";
          $vols[$v] = $class->newVolume0($p0, $wwn, $rep);
          push (@pil, $vols[$v] );
          $volCnt++;
        }
    }

    my $voldisks = $class->newVolDisk($i, 0, $rep, \@vols);
    push(@pil, @$voldisks);        # unit $i, all volumes.

    my $diskTotal = $rep->get('disk.count') || 9;
    for ($j = 1; $j<= $diskTotal; $j++) {
      $dd = $class->newDiskDrive($rep,"disk.u${i}d$j");
      next if (!$dd);
      $a = CIM::Instance->new('CIM_Container', [
                   [GroupComponent  => $p2],
                   [PartComponent => $dd->[1]],
                   [LocationWithinContainer => "disk.u${i}d$j"],
                   ]);
      push(@pil, @$dd, $a);
    }
  }

  return Ilist->new(\@pil);
}

sub newVolume {
  my($class, $unit, $vol, $wwn, $rep) = @_;

  my $p0 = "u${unit}vol$vol";
  my $volume = $class->newVolume0($p0, $wwn, $rep);
  my @volumes;
  $volumes[$vol] = $volume;
  my $disks = $class->newVolDisk($unit, $vol, $rep, \@volumes);
  my(@list);
  push(@list, $volume);
  push(@list, @$disks);
  return Ilist->new(\@list);
}
  
  
sub newVolDisk {
  my($class, $unit, $vol, $rep, $volumes) = @_;
  my($j, $k1, %DSK, @pil, $k);

  my $diskTotal = $rep->get('disk.count') || 9;

  for ($j = 1; $j <= $diskTotal; $j++) {
      my $dd = $class->newDiskDrive($rep,"disk.u${unit}d$j");
      next if (!$dd);
      $DSK{"u${unit}d$j"} = $dd->[0];
  }
    
  for ($k1 = 1;$k1 <= 2; $k1++) {
     next if ($vol && $vol != $k1);
     for ($k=0; $k <= $diskTotal-1; $k++) {
          my($dfid) = $rep->get("volume_disk.u${unit}vol${k1}-d-$k.volDiskFruId");
          if (substr($dfid,3,1) eq "0") {
             $dfid = substr($dfid,0,3) . substr($dfid,4,1);
          }
          if ($dfid && $DSK{$dfid}) {
            push(@pil, 
                  CIM::Instance->new('CIM_MediaPresent', [
                       [Antecedent => $DSK{$dfid}  ],  # the NWS_DiskDrive
                       [Dependent  => $volumes->[$k1]   ],
                       ]));
          }
     }
  }
  return \@pil;
}


sub newVolume0 {
  my($class, $p0, $wwn, $rep) = @_;
  my $p = "volume.$p0";
  my $raid =  $rep->get("volume.$p0.volRaidLevel");
  $raid =~ s/raid//;
  my $vol= CIM::Instance->new('NWS_StorageVolume', [
                    [ SystemName        => "Volume"         ],
                    [ DeviceID          => "$wwn.$p"     ],
                    [ Name              => "$wwn.$p"     ],
                    [ VolWWN            => substr($rep->get("$p.volWWN"),0,50) ],
                    [ VolName           => $rep->get("$p.volName") ],
                    [ Capacity          => $rep->get("$p.volCapacity") ],
                    [ VolErrors         => $rep->get("$p.volErrors") ],
                    [ VolFirmwareErrors => $rep->get("$p.volFirmErrors") ],
                    [ VolIndex          => $rep->get("$p.volIndex") ],
                    [ VolId             => $p0       ],
                    [ VolCacheMirror    => $rep->get("$p.volCacheMirror") ],
                    [ VolCacheMode      => $rep->get("$p.volCacheMode") ],
                    [ VolRaidLevel      => $raid     ],
                    [ VolStatus         => $rep->get("$p.volStatus") ],
                    ]);
   return $vol;
}

# create instances of NWS_DiskDrive, CIM_Realizes, CIM_PhysicalPackage, 
# CIM_MediaPresent and CIM_StorageExtent, CIM_SoftwareElement, CIM_DeviceSoftware
#  $disk = NWS::T3->newDiskDrive($rep, "u1d1");

sub copyKey {
  my($class, $cd, $from, $to) = @_;
  $to->{"$cd.fruVendor"} =  $from->{"$cd.fruVendor"};
  $to->{"$cd.fruModel"} =  $from->{"$cd.fruModel"};
  $to->{"$cd.fruSerialNo"} =  $from->{"$cd.fruSerialNo"};
}

sub getKey {
  my($class, $rep, $cd) = @_;

  return undef if (!exists $rep->{"$cd.fruVendor"});
  return "" if (! $rep->get("$cd.fruVendor") && !$rep->get("$cd.fruSerialNo"));

  my($k) = $rep->get("$cd.fruVendor") . "." .  $rep->get("$cd.fruModel") . ".";

  my($ser) = $rep->get("$cd.fruSerialNo");

  $k .= ($ser)? $ser : $cd;


  return $k;
}

sub getState {
  my($class, $rep, $cd) = @_;
  my($map) = PDM->getDeviceStateMap("t3.availability");
  my $val  = $rep->get("$cd.fruStatus") . "-" . $rep->get("$cd.fruState");
  return $map->get("fruStatus.$val");
}

sub newDiskDrive {
  my($class, $rep, $cd) = @_;
  my(@il, $p1, $c1, $a1, $c2, $a2);

  my($serial_no) = $class->getKey($rep, $cd);

  return undef if (!$serial_no);
  my($status) = $rep->get("$cd.fruStatus") . "-" . 
                $rep->get("$cd.fruState");


  $p1 = CIM::Instance->new('NWS_DiskDrive', [
                [SystemName 		=> $rep->get("$cd.fruVendor")." DiskDrive"],
                [DeviceID 	=> $serial_no],
                [Name     	=> $serial_no],
                [FruDiskRole        => $rep->get("$cd.fruDiskRole")],
                [FruDiskIsExpendable=> $rep->get("$cd.fruDiskIsExpendable")],
                [FruDiskIsRebuildable=> $rep->get("$cd.fruDiskIsRebuildable")],
                [FruDiskTemperature => $rep->get("$cd.fruDiskTemp")],
                [FruDiskCapacity    => $rep->get("$cd.fruDiskCapacity")],
                [FruErrors          => $rep->get("$cd.fruErrors")],
                [Port1State         => $rep->get("$cd.fruDiskPort1State")],
                [Port2State         => $rep->get("$cd.fruDiskPort2State")],
                [StatusInfo         => $status],
                [Status             => $class->getState($rep, $cd)],
                 ]);
  push(@il,$p1);

  $c1 = CIM::Instance->new('CIM_PhysicalPackage', [
                [Removable 	=> "Yes"],
                [Replaceable 	=> $rep->get("$cd.fruDiskIsExpendable")],
                [Tag 	        => $serial_no],
                [Name    	=> $serial_no],
                [SerialNumber 	=> $rep->get("$cd.fruSerialNo") ],
                [Manufacturer 	=> $rep->get("$cd.fruVendor")],  
                [Model 		=> $rep->get("$cd.fruModel")],  
                [Version 	=> $rep->get("$cd.fruRevision")],  
                    ]);

  push(@il, $c1);
  $a1 = CIM::Instance->new('CIM_Realizes', [
                    [Antecedent => $c1],
                    [Dependent => $p1],
                    ]);
                    
  push(@il,$a1);

  return Ilist->new(\@il);

}

sub newMidplane {
  my($class, $rep, $cd) = @_;
  my(@il, $p1, $c1, $a1, $c2, $a2);

  my $serial_no = $class->getKey($rep, $cd);

  return undef if (!$serial_no);

  $serial_no .= ".mpn";

  my($status) = $rep->get("$cd.fruStatus") . "-" .
                $rep->get("$cd.fruState");


  $p1 = CIM::Instance->new('NWS_Midplane', [
                [SystemName     => $rep->get("$cd.fruVendor")." Midplane"],
                [DeviceID       => $serial_no],
                [Name           => $serial_no],
                [IsEnabled      => $rep->get("$cd.fruIsEnabled")],
                [IsSubstituted  => $rep->get("$cd.fruIsSubstituted")],
                [StatusInfo         => $status],
                [Status             => $class->getState($rep, $cd)],
                 ]);
  push(@il,$p1);

  $c1 = CIM::Instance->new('CIM_PhysicalPackage', [
                [Removable      => "Yes"],
                [Replaceable    => "No"],
                [Tag            => $serial_no],
                [Name           => $serial_no],
                [SerialNumber   => $rep->get("$cd.fruSerialNo") ],
                [Manufacturer   => $rep->get("$cd.fruVendor")],  
                [Model          => $rep->get("$cd.fruModel")],
                [Version        => $rep->get("$cd.fruRevision")],   
                    ]);

  push(@il, $c1);
  $a1 = CIM::Instance->new('CIM_Realizes', [
                    [Antecedent => $c1],
                    [Dependent => $p1],
                    ]);

  push(@il,$a1);

  return Ilist->new(\@il);

}


# create instances of NWS_Controller, CIM_Realizes, CIM_Card, CIM_SoftwareElement and
#CIM_DeviceSoftware (Note: All attributes related to T3's software will be in the
#controller's CIM_SoftwareElement class.

sub newController {
  my($class, $rep, $cd, $index) = @_;
  my(@il, $p1, $c1, $a1);
  
  my($wwn) = $rep->get('id.wwn');

  my $serial_no = $class->getKey($rep, $cd);

  return undef if (!$serial_no);
  my($port) = substr($cd,11,-3) . "p1";
  my($status) = $rep->get("${cd}.fruStatus") . "-" . 
                $rep->get("${cd}.fruState");
  my $ix = index($cd, ".");
  my $unit = substr($cd, $ix+1, 2);
  $wwn = $rep->{"port.$unit" . "p1.portWWN"};

  $p1 = CIM::Instance->new('NWS_Controller', [
                    [SystemName  =>  "Controller"],
                    [DeviceID     => $serial_no],
                    [Name         => $serial_no],
                    [FruErrors    => $rep->get("${cd}.fruErrors")],
                    [Role         => $rep->get("${cd}.fruCtlrRole")],
                    [PortErrors   => $rep->get("port.$port.portErrors")],
                    [PortStatus   => $rep->get("port.$port.portStatus")],
                    [PortSunHost  => $rep->get("port.$port.portSunHost")],
                    [PortType     => $rep->get("port.$port.portType")],
                    [StatusInfo   => $status],
                    [Status       => $class->getState($rep, $cd)],
                    ]);
  push(@il,$p1);

  my $v1 = $rep->get("${cd}.fruCtlrVersion") || $rep->get("${cd}.fruRevision");
  $c1 = CIM::Instance->new('CIM_Card', [
                [Removable 			=> "Yes"],
                [Replaceable 		=> $rep->get("${cd}.fruCtlrIsExpendable")],
                [Tag 			=> $serial_no],
                [WWN 			=> $wwn      ],
                [Name  			=> $serial_no],
                [SerialNumber 		=> $rep->get("${cd}.fruSerialNo") ],
                [Manufacturer 		=> $rep->get("${cd}.fruVendor")],  
                [Model 			=> $rep->get("${cd}.fruModel")],  
                [HwVersion 		=> $rep->get("${cd}.fruRevision")],  
                [Version 		=> $v1 ],
                    ]);

  push(@il, $c1);
  $a1 = CIM::Instance->new('CIM_Realizes', [
                [Antecedent => $c1],
                [Dependent => $p1],
                    ]);
                    
  push(@il,$a1);

  return Ilist->new(\@il);

}

# create instances of NWS_LoopCard, CIM_Realizes, CIM_Card
sub newLoopCard {
  my($class, $rep, $cd) = @_;
  my(@il, $a1, $c1, $p1);
  
  my($serial_no) = $class->getKey($rep, $cd);

  return undef if (!$serial_no);
  my($status) = $rep->get("${cd}.fruStatus") . "-" . 
                $rep->get("${cd}.fruState");
  $p1 = CIM::Instance->new('NWS_LoopCard', [
               [SystemName => $rep->get("${cd}.fruVendor")." LoopCard"],
               [DeviceID   => $serial_no ],
               [Name       => $serial_no ],
               [FruLoopCable1State=> $rep->get("${cd}.fruLoopCable1State")],
               [FruLoopCable2State=> $rep->get("${cd}.fruLoopCable2State")],
               [FruLoopMode       => $rep->get("${cd}.fruLoopMode")],
               [FruLoopTemp       => $rep->get("${cd}.fruLoopTemp")],
               [FruErrors         => $rep->get("${cd}.fruErrors")],
               [StatusInfo        => $status],
               [Status            => $class->getState($rep, $cd)],
                    ]);
  push(@il,$p1);

  my $v1= $rep->get("${cd}.fruLoopVersion") || $rep->get("${cd}.fruRevision");
  $c1 = CIM::Instance->new('CIM_Card', [
               [Removable 			=> "Yes"],
               [Tag 				=> $serial_no],
               [Name 				=> $serial_no],
               [SerialNumber 		=> $rep->get("${cd}.fruSerialNo")],
               [Manufacturer 		=> $rep->get("${cd}.fruVendor")],  
               [Model 			=> $rep->get("${cd}.fruModel")],  
               [HwVersion 		=> $rep->get("${cd}.fruRevision")],  
               [Version 		=> $v1 ],
                    ]);
  push(@il, $c1);
  $a1 = CIM::Instance->new('CIM_Realizes', [
                [Antecedent 	=> $c1],
                [Dependent 		=> $p1],
                    ]);
  push(@il,$a1);

  return Ilist->new(\@il);
}

# create instances of NWS_PowerUnit, CIM_Realizes, CIM_PhysicalPackage,CIM_Container 

sub newBattery {
  my($class, $rep, $cd) = @_;
  my(@il, $p1 ,$c1, $a1);
  
  my($status) = $rep->get("${cd}.fruPowerBatState");

  my($serial_no) = $rep->get("${cd}.fruPowerBatSerialNo");

  return undef if (!$serial_no);

  my($revision) = $rep->get("${cd}.fruPowerBatRevision");
  my $install = CIM->date2cim($rep->get("${cd}.fruPowerBatMdate"));
  my $uniqueID;
  $uniqueID .= $rep->get("${cd}.fruPowerBatVendor")."." 
    if($rep->get("${cd}.fruPowerBatVendor"));
  $uniqueID .= $rep->get("${cd}.fruPowerBatModel")."."
    if($rep->get("${cd}.fruPowerBatModel"));
  $uniqueID .= $serial_no;
  my ($junk, $name) = split(/\./, $cd);

  $p1 = CIM::Instance->new('NWS_Battery', [
               [SystemName  => $rep->get("${cd}.fruPowerBatVendor")." BATTERY"],
               [DeviceID              => $uniqueID],
               [Name                  => $uniqueID],
               [StatusInfo            => $rep->get("${cd}.fruPowerBatState")],
               [InstallDate           => $install ],
               [Status                => $status],
               [OtherIdentifyingInfo  => $rep->get("${cd}.fruPowerBatModel")],
                    ]);
  push(@il,$p1);

  $c1 = CIM::Instance->new('CIM_PhysicalPackage', [
               [Removable	=> "Yes/No"],
               [Tag 		=> $uniqueID],
               [Name         	=> $uniqueID],
               [SerialNumber 	=> $serial_no],
               [Manufacturer 	=> $rep->get("${cd}.fruPowerBatVendor")],  
               [Model 		=> $rep->get("${cd}.fruPowerBatModel")],  
               [Version		=> $revision],
                    ]);

  push(@il, $c1);
  $a1 = CIM::Instance->new('CIM_Realizes', [
               [Antecedent 		=> $c1],
               [Dependent 		=> $p1],
                    ]);
                    
  push(@il,$a1);

  return Ilist->new(\@il);
}
sub newPowerUnit {
  my($class, $rep, $cd) = @_;
  my(@il, $p1 ,$c1, $a1);
  
  my($status) = $rep->get("${cd}.fruStatus") . "-" . 
                $rep->get("${cd}.fruState");

  my($serial_no) = $class->getKey($rep, $cd);

  return undef if (!$serial_no);
  my($revision) = $rep->get("${cd}.fruRevision");
  if ($revision =~ /refer to/) {
    $revision = "";
  }
  $p1 = CIM::Instance->new('NWS_PowerUnit', [
               [SystemName   => $rep->get("${cd}.fruVendor")." PCU"],
               [DeviceID     => $serial_no],
               [Name         => $serial_no],
               [FruBatLife   => $rep->get("${cd}.fruPowerBatLife")],
               [FruErrors    => $rep->get("${cd}.fruErrors")],
               [Fan1State    => $rep->get("${cd}.fruPowerFan1State")],
               [Fan2State    => $rep->get("${cd}.fruPowerFan2State")],
               [StatusInfo   => $status],
               [Status       => $class->getState($rep, $cd)],
                    ]);
  push(@il,$p1);

  $c1 = CIM::Instance->new('CIM_PhysicalPackage', [
               [Removable 		=> "Yes"],
               [Tag 			=> $serial_no],
               [Name         	=> $serial_no],
               [SerialNumber 	=> $rep->get("${cd}.fruSerialNo") ],
               [Manufacturer 	=> $rep->get("${cd}.fruVendor")],  
               [Model 			=> $rep->get("${cd}.fruModel")],  
               [Version 		=> $revision],
                    ]);

  push(@il, $c1);
  $a1 = CIM::Instance->new('CIM_Realizes', [
               [Antecedent 		=> $c1],
               [Dependent 		=> $p1],
                    ]);
                    
  push(@il,$a1);

  return Ilist->new(\@il);
}

1;
