#!/opt/SUNWstade/bin/perl -I/opt/SUNWstade/lib

# 
# currently only works on the master.
#
use strict 'vars';
use System;
use Util::Http;
use Util;
use Getopt::Std;
use PDM::ConfigFile;
use Data::Dumper;

my $local_p   = $INC[0];
my($ix)    = rindex($local_p, "/");
my(%opts);

my $HOME      = substr($local_p,0,$ix);
mkdir "$HOME/DATA/Discover",0777 if (!-d "$HOME/DATA/Discover");

System->set_home($HOME);
my $RASPORT   = System->getConfigPort($HOME);
System->set_rasport($RASPORT);

my $MASTER    = Util->findMaster();
my $COMMANDS  = ",site_info,host_list,host_detail,device_list,device_detail," .
   "email_list,site_info_upd,agent,review_config,t3_add,switch_add,".
   "discover_subnet,login_add,login_delete,login_update,login_list," . 
   "host_delete,push_config,report_list,report,provider_on,provider_off,alert_delete,alert_list," . 
   "event_list,discover_switch,discover_3510,discover_deviceIP,device_delete_all,topo_list,topo,provider_list,".
   "ethers_list,ethers_add,ethers_delete,discover_a5k,discover_t3,password_change,";

sub usage {
  print "
 Usage   : ras_admin command [options]
 Commands:
  site_info      : get site information.
  host_list      : List of hosts.
  host_detail    : details about host(s).
  host_delete    : delete a host from the config .
  device_list    : list of devices.
  device_detail  : details about device(s).
  device_delete_all: Delete all devices.
  email_list     : list email set for notifications.
  site_info_upd  : Update Site Information.
  agent          : Start/Stop agent.
  review_config  : Review the configuration.
  t3_add         : Add a t3 to the config if valid.
  switch_add     : Add a Sun Switch to the config if valid.
  discover_a5k   : Discover a5k on master/slaves.
  discover_3510  : Discover 3310/3510 on master/slaves.
  discover_subnet: find t3 and switches on the subnet.
  discover_t3    : find t3 from the message.t3 logfile.
  discover_switch: discover switches entered in /etc/fcswitch.conf. 
  discover_deviceIP: discover devices entered in /etc/deviceIP.conf.
  login_list     : list all logins.
  login_add      : add new login.
  login_delete   : delete a login.
  login_update   : update password or roles of a login.
  push_config    : Update Slave configuration.
  report_list    : list all available instrumentation reports.
  report         : display report/reports.
  provider_list  : List status of providers.
  provider_on    : turn/on notification provider.
  provider_off   : turn/off notification provider.
  alert_list     : Show current alerts (warnings/errors).
  alert_delete   : Delete selected alerts.
  topo_list      : List of Topologies.
  topo           : Display a topology.
  ethers_list    : list ethers file.
  ethers_add     : Add entry to ethers file.
  ethers_delete  : Delete entry from ethers file.
  password_change: Change the password of a device.
  \n\n";
}
#  event_list     : Show X most recent alerts.

my $command = shift @ARGV;

if ($command eq "help" || $command eq "usage") {
   &usage();
   exit;
}

if (index($COMMANDS, ",$command,") < 0) {
   &usage();
   exit;
}
my($renv, $devices, $hosts, $notifs) = PDM::ConfigFile->read();

if(!$renv){
   print "Must run ras_install before executing this command\n";
   exit(1);
}

System->set_renv($renv);

&$command();
print "\n";
exit(0);


sub ethers_list {
  require Logic::Ethers;
  if (!getopts("h", \%opts) || $opts{'h'} ) {
     print "Usage: ras_admin ethers_list [-h] \n";
  }
  my $E = Logic::Ethers->read();
  my $f = "%-14.14s %-20.20s \n";
  printf($f, "IP","Ether");
  printf($f, &lines(2));
  foreach my $name (sort keys %$E) {
    printf($f, $name, $E->{$name});
  }
}

sub ethers_delete_usage{
 print "Usage: ras_admin ethers_delete -n 'name'[-h] \n";
 print "-n is IP name to be deleted\n";
 print "IE: ras_admin ethers_delete -n t401\n"

}
sub ethers_delete {
  require Logic::Ethers;
  if (!getopts("hn:", \%opts) || $opts{'h'} ) {
     ethers_delete_usage();
     exit(1);
  }
  my $name = $opts{n};
  if (!$name) {
     print "Error: name must be entered!\n";
     ethers_delete_usage();
     exit(1);
  }
  my $E = Logic::Ethers->read();
  my $H = Logic::Ethers->readHosts();


  if (!$H->nameExists($name)) {
     print "Error: this name is invalid ($name)!\n";
     exit(1);
  }
  delete($E->{$name});
  $E->write();
  print "Ether entry $name deleted!\n";
  &ethers_list();
}


sub ethers_add_usage{
   print "Usage: ras_admin ethers_add -n 'name' -e 'ether_address' [-h] \n";
   print "-n IP name from /etc/hosts\n";
   print "-e ether address of new device\n";
   print "IE: ras_admin ethers_add -n t401 -e 00:C0:DD:00:B2:44\n";
}


sub ethers_add {
  require Logic::Ethers;
  if (!getopts("hn:e:", \%opts) || $opts{'h'} ) {
     ethers_add_usage();
     exit(1);
  }
  my $name = $opts{n};
  my $ether = $opts{e};
  if (!$name || !$ether) {
     print "Error: both name and ether_address must be entered!\n";
     ethers_add_usage();
     exit(1);
  }
  my $E = Logic::Ethers->read();
  my $H = Logic::Ethers->readHosts();


  if (!Logic::Ethers->valid($ether)) {
     print "Error: ether is invalid ($ether)!\n";
     exit(1);
  }
  if (!$H->nameExists($name)) {
     print "Error: this name is invalid ($name)!\n";
     exit(1);
  }
  $E->{$name} = $ether;
  $E->write();
  print "Ethers file updated!\n";
  &ethers_list();
}


#  PASSWORD

sub password_change {
  if (!getopts("i:p:h", \%opts) || $opts{'h'} ) {
     print "Usage: ras_admin password_change -i <ip_number> -p <password> [-h] \n";
     print " Note: Use -p \"\" to clear the password\n";
  }
  my $name = $opts{i};
  if (!$name) {
     print "Error: Enter a key or a ipno!\n";
     exit(1);
  }
  my $found;
  foreach my $dev (@$devices) {
     if ( ($opts{i} && $dev->{ipno} eq $opts{i}) ){
        $found = 1;
        if (!$opts{p}) {
           $dev->{telnet} = "";
        } else {
           $dev->{telnet} = Util->encodeAll($opts{p});
        }
        last;
     }
  }
  if ($found) {
    print "Password updated for $name\n";
    PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
  } else {
    print "No device found for $name\n";
  }

}



use Roles;

sub login_list {
  if (!getopts("h", \%opts) || $opts{'h'} ) {
     print "Usage: ras_admin login_list [-h] \n";
  }
  my $db = Roles->read();
  my $list = $db->userList();
  my $f = "%-20.20s %-20.20s %-30.30s\n";

  printf($f, "Login","Name","Roles");
  printf($f, &lines(3));
  foreach my $e (@$list) {
    printf($f, $e->{user}, $e->{name}, $e->{roles});
  }
}



sub login_add {
  if (!getopts("l:p:r:h", \%opts) || $opts{'h'} || !$opts{l} || !$opts{p} ) {
     print "Usage: ras_admin login_add -l login -p password -r role1:role2.. [-h] \n";
     print "       Roles: user|admin|script|test \n";
     exit(1);
  }
  my $role;
  foreach my $e (split(/\:/, $opts{r}))  {
     if (index(",user,admin,script,test,expert,", ",$e,") < 0) {
        print "Invalid role: $e \n";
        exit(1);
     }
     $role .= "$e|";
  }
  chop($role) if ($role);
  my $db = Roles->read();
  $db->addUser($opts{l}, $opts{l}, $opts{p}, $role);
  $db->write();
}

sub login_delete {
  if (!getopts("l:h", \%opts) || $opts{'h'} || !$opts{l}) {
     print "Usage: ras_admin login_delete -l login  [-h] \n";
     exit(1);
  }
  my $login = $opts{l};
  if (($login eq "peer") ||($login eq "srm") ) {
     print "Cannot delete user $login\n";
     exit(1);
  }


  my $db = Roles->read();
  if ($login ne "storade") {
    $db->deleteUser($login);
    $db->write();
  }
}

sub login_update {
  if (!getopts("l:p:r:h", \%opts) || $opts{'h'} || !$opts{l}) {
     print "Usage: ras_admin login_update -l login -p password -r role1:role2 [-h] \n";
     print "       Roles: user:admin:script:test:expert \n";
     exit(1);
  }
  my $role;
  foreach my $e (split(/\:/, $opts{r})) {
     if (index(",user,admin,script,test,expert,", ",$e,") < 0) {
        print "Invalid role: $e \n";
        exit(1);
     }
     $role .= "$e|";
  }
  chop($role) if ($role);
  my $db = Roles->read();
  my $user = $db->getUser($opts{l});
  if ($user) {
     $user->{roles}  = $role if ($role);
     $user->{password} = Roles->encode($opts{p}) if ($opts{p});
     $db->write();
  } else {
     print "Cannot find $opts{l} \n";
     exit(1);
  }
}

sub push_config {
  if (!getopts("h:?", \%opts) || $opts{'?'} || !$opts{h} ) {
     print "Usage: ras_admin push_config -h hostname|ALL [-?] \n";
     exit(1);
  }
  require Logic::Slave;
  my $pushed = 0;
  foreach my $h (@$hosts) { 
    if (lc($h->{hostname}) eq lc($opts{h}) || $opts{h} eq "ALL") {
	if($h->{dh} =~ /Y/){
	  print "Skipping $h->{hostname} because it is a datahost\n";
	  next;
	}
        $pushed = 1;
        my $rc = Logic::Slave->push($h) ;
	if($rc =~ /OK/){
	  print "Push Succeeded for $h->{hostname} \n";
	}else{
           print substr($rc,3) . $h->{hostname}  if ($rc);
	}
    }
  }
  if($pushed == 0)
  {
     print "Didn't push configs - No slave host(s) detected\n";
  }else{
     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
  }

}

sub topo {
  if (!getopts("?t:hnswdv", \%opts) || $opts{'?'} || !$opts{t}) {
     print "Usage: ras_admin topo -t topo_name [-h|-n|-s|-w] [-?] \n";
     print "  -h : Hba only\n";
     print "  -s : Switches only\n";
     print "  -d : Storage only\n";
     print "  -t : Topology \n";
     print "  -w : wwn to port mapping\n";
     print "  -v : verbose Output\n";
     print "Example: ras_admin topo -t MERGE-MASTER \n";
     exit(1);
  }
  require TO;
  my $to = TO->readExistingTopo($opts{t});
  if (!$to) {
    print "Error: invalid topology: $opts{t}\n";
    exit(1);
  }
  my $numopts =0;
  if ($opts{h}) {
     &topo_hba($to, $opts{v});
     $numopts++;
  }
  if ($opts{s}){
     &topo_switch($to, $opts{v} );
     $numopts++;
  } 
  if ($opts{d}){
     &topo_storage($to, $opts{v} );
     $numopts++;
  } 
  if ($opts{w}) {
     &topo_wwn($to, $opts{v} );
     $numopts++;
  } 
  if($numopts==0) {
     print $to->toC2();
  }
}

sub topo_wwn {
print "WWN Info\n";
print "================================================================================\n";
  my($to, $verbose) = @_;
  my $wwns = $to->wwnList();
  my %H;
  foreach my $el (keys %$wwns) {
     $H{$wwns->{$el}} = $el;
  }
  foreach my $el (sort keys %H) {
     my $wwn = $H{$el};
     my ($target, $p_no) = $to->nodeByName($el);
     next if (!$target);
     my $target_name = $target->boxName();
     my $target_type = $target->type();

     if (!defined($p_no)) {
       print "$wwn => $target_type $target_name \n";
     } else {
       print "$wwn => $target_type $target_name: port $p_no \n";
     }
  }
}

sub topo_hba {
print "HBA Info\n";
print "================================================================================\n";
  my($to, $verbose) = @_;
  my ($x);
  my $hosts = $to->hostList(); 
  foreach my $h (@$hosts) {
     my $pis = $h->portInfo();
     my $ps  = $h->port();
     my $type = "hba";
     for ($x=0; $x <= $#$pis; $x++) {
        my $pi = $pis->[$x];
        my $p  = $ps->[$x];
        my ($target, $p_no) = $to->nodeByName($p);
        next if (!$target);
        my $target_name = $target->boxName();
        print $h->boxName().":hba port $x \n";
        if (defined($verbose)){
	  print "\tType: ". $type."\n";
	  print "\tPortWWN: ". $pi->{PortWWN}."\n";
	  print "\tNodeWWN: ". $pi->{NodeWWN}."\n";
          print "\tPATH:$pi->{path}\n";
	}
        print "\thba port $x => $target_name: port $p_no\n";
     }
  }
}
sub topo_switch{
print "Switch Info\n";
print "================================================================================\n";
  my($to, $verbose) = @_;
  my ($x);
  my $switchs= $to->switchList(); 
  foreach my $s (@$switchs) {
    print $s->boxName()."\n";
    if (defined($verbose)){
      my $Type = $s->type(); # host, t3, a5k, 
      print "\tType: $Type\n";
      print "\tIP: $s->{info}->{sw_ipAddr}\n" if (defined($s->ip()));
    }
    my $pis = $s->portInfo(); 
    my $ps  = $s->port(); 
    for ($x=0; $x <= $#$pis; $x++) { 
      my $pi = $pis->[$x];
      my $p  = $ps->[$x];
      my ($target, $p_no) = $to->nodeByName($p);
      next if (!$target);
      my $target_name = "UNDEF";
      $target_name = $target->boxName().": " if(defined($target));
      $p_no = "port ".$p_no if(defined($target));
      if (defined($verbose) || $target_name ne "UNDEF"){
        print "\t$x: $pi->{path} => $target_name $p_no\n";
      }
	
   }
  }
}

sub topo_storage{
print "Storage Info\n";
print "================================================================================\n";
  my($to, $verbose) = @_;
  my ($x);
  my $storage = $to->storageList(); 
  foreach my $s (@$storage) {
    print $s->boxName()."\n";
    if (defined($verbose)){
      my $Type = $s->type(); # host, t3, a5k, 
      print "\tType: $Type\n";
    }
    my $ports = ($s->{port});
    for (my $x=0; $x<=$#$ports; $x++){
      my $target_name = "UNDEF";
      my ($target, $p_no) = $to->nodeByName($ports->[$x]);
      next if (!$target);
      $target_name = $target->boxName().": " if(defined($target));
      $p_no = "port ".$p_no if(defined($target));
      print "\tport $x: => $target_name $p_no\n";
    }
    if (defined($s->volInfo()) && defined($verbose)){
      my $info = $s->volInfo(); 
      foreach my $volume (keys %$info){
	my $vol = $info->{$volume};
        print "\t\tLogical Path: $volume\n"; 
        print "\t\tPort WWN: $vol->{PortWWN}\n"; 
        print "\t\tNode WWN: $vol->{NodeWWN}\n"; 
        print "\t\tCapacity: $vol->{Capacity}\n"; 
      }
    }
    if (defined($s->diskInfo()) && defined($verbose)){
      my $info = $s->diskInfo();
      foreach my $disk (keys %$info) {
        my $disk = $info->{$disk};
        print "\t\tLogical Path: $disk->{LogicalPath}\n";
        print "\t\tDevice ID: $disk->{devID}\n";
        print "\t\tPort WWN: $disk->{PortWWN}\n";
        print "\t\tNode WWN: $disk->{NodeWWN}\n";
        print "\t\tVendor ID: $disk->{VendorID}\n";
      }
    }
    print "\n"; 
  }
}
     


sub topo_list {
  if (!getopts("?h:", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin topo_list [-?] \n";
     exit(1);
  }
  require TO;
  my $topos = TO->topoList();
  my $D = System->get_home() . "/DATA/topo";
  my $f = "%-30.30s %s\n";
  printf($f, "Name","Date");
  printf($f, &lines(2));
  foreach my $topo (@$topos) {
    next if (substr($topo,0,1) eq ".");
    my $created = Util->get_file_created("$D/$topo");
    printf($f, $topo, $created);
  }
  print "Done.\n";
}

sub report_list {
  if (!getopts("?h:", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin report_list -h host [-?] \n";
     exit(1);
  }
  require Report;
  my $list = Report->reportList();
  my $f = "%-10.10s %-25.25s %-20.20s %s\n";

  printf($f, "Type","Host","Name/Device", "ReportKey");
  printf($f, &lines(4));

  my $list = Report->reportList();

  my $cnt;
  foreach my $key (sort keys %$list) {
     my $v = $list->{$key};
     next if ($opts{h} && lc($opts{h}) ne $v->[0]);
     printf($f, $v->[1], $v->[0], $v->[4], $key);
     $cnt++;
  }
  print "Count: $cnt\n";
}

sub report_usage{
   print "Usage: ras_admin report -k reportKey -h host [-a] [-?] \n";
   print "-k reportKey from report_list\n";
   print "-h host from report_list\n";
   print "-a print all reports\n";

}
sub report {
   if (!getopts("?k:ah:", \%opts) || $opts{'?'} || (!$opts{k} && !$opts{a})) {

     report_usage();
     exit(1);
  }
  require Report;

  if($opts{a}){
    print "Dump all\n";
    my $list = Report->reportList();
    foreach my $key (sort keys %$list) {
     my $v = $list->{$key};
     print "Report for key: $key, Host: $v->[0]\n";
     my ($err, $report) = Report->readReport($key, $v->[0]);
     if ($err) {
        print "ERROR: $err \n";
        report_usage();
        exit(1);
     }
  
     print $report->toString({summary => 1});
     print "\n";

   }



  }else{
     my ($err, $report) = Report->readReport($opts{k}, $opts{h});
     if ($err) {
        print "ERROR: $err \n";
        report_usage();
        exit(1);
     }
  
     print $report->toString({summary => 1});
  }
}

sub provider_list {
  my $f = "%-10.10s %-6.6s %-15.15s %-20s\n";
  printf($f, "Provider","Active", "Heartbeat (hrs)", "IP");
  printf($f, &lines(4));
  my $outdata = {sunmc => "SunMC", nscc_email => "Email", trap => "Trap", srs => "SRS", netconnect => "NetConnect", sae => "SAE", ssrr => "SSRR"};
  foreach my $p ('nscc_email','netconnect','sae','srs','ssrr','sunmc','trap',) {
     my $act = $renv->{"pro.$p.active"} || "N";
     $act = "  $act";
     printf($f, $outdata->{$p}, $act,
                $renv->{"pro.$p.frequency"},
                $renv->{"pro.$p.ip"},
           );
  }

  print "\n";
  my $f = "%-8.8s %-15.15s %-8.8s %-8s\n";

  printf($f, "Trap #",   "IP Name/Address",  "Port" ,"Min Alert Level");

  printf($f, &lines(4));
  my $act = $renv->{"pro.trap.active"} || "N";
  $act = "  $act";
  for (my $x=1; $x <= 5 ; $x++) {
     my $level = "";
     if($renv->{"pro.trap$x.level"} eq '1'){
        $level = "Warning";
     }elsif($renv->{"pro.trap$x.level"} eq '2'){
        $level = "Error";
     }elsif($renv->{"pro.trap$x.level"} eq '3'){
        $level = "Down";
     }

     printf($f, $x,
                $renv->{"pro.trap$x.ip"},
                $renv->{"pro.trap$x.port"},
		$level
           );
  }
}


sub provider_on {
  &set_provider('Y');
}

sub provider_off {
  &set_provider('N');
}

sub provider_usage {
  my($flag) = @_;
  my $providers = "-p datahost|nscc_email|netconnect|sae|srs|ssrr|sunmc|trap";
  print "\n";
  if($flag eq 'Y'){
   print "Usage: ras_admin provider_on $providers -f frequency -i ipaddr [-?] \n";
   print " -c Y:N - Turns on or off component events for SAE provider. Default is N.\n";
   print " -t trap number for trap provider. Valid numbers are 1 through 5.\n";
   print " -o port, Default is 162 for trap provider. There is no default for datathost.\n";
   print " -l warning:error:down trap level for trap provider. Default is warning.\n";
   print "IE:\n";
   print "ras_admin provider_on datahost -i 10.10.10.1 -o 7654\n";
  }else{
     print "Usage: ras_admin provider_off $providers \n";
     print "   -t trap number for trap provider. Valid numbers are 1 through 5.\n";
     print " Note: 'ras_admin provider_off -p trap -t trap_number'\n      will remove this trap entry and will turn off all traps.\n";

  }
  print "\n";
  exit(1);
}
  

sub set_provider {
  my( $flag) = @_;
  $opts{p} = lc($opts{p});

  if (!getopts("p:?f:i:c:t:o:l:", \%opts) || $opts{'?'}  ||
         index(",datahost,nscc_email,netconnect,sae,srs,ssrr,sunmc,trap,", ",$opts{p},") < 0) {
            &provider_usage($flag);
  }

  
  if ($opts{p} eq "nscc_email") {
     $renv->{'pro.nscc_email.active'}     = $flag;
     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);

  } elsif ($opts{p} eq "datahost") {
     my $ip = $opts{i};
     my $port = $opts{o};
     &provider_usage($flag) if ((!$ip) && ($flag eq 'Y'));
     &provider_usage($flag) if ((!$port) && ($flag eq 'Y'));

     $renv->{'pro.sae.dh_active'}   = $flag;
     $renv->{'pro.sae.datahost'}    = "$ip:$port";
     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
  
  }elsif ($opts{p} eq "netconnect") {
     $renv->{'pro.netconnect.active'}     = $flag;
     $renv->{'pro.netconnect.max'}        = 2000;
     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
  
  } elsif ($opts{p} eq "sae") {
     my $ip = $opts{i};
     my $comp;
     if($opts{c} eq 'Y'){
       $comp = 'Y';
     }else{
       $comp = 'N';
     }
     &provider_usage($flag) if ((!$ip) && ($flag eq 'Y'));
     $renv->{'pro.sae.active'}     = $flag;
     $renv->{'pro.sae.frequency'}  = ($opts{f} + 0) || 6;
     $renv->{'pro.sae.ip'}         = $ip;
     $renv->{'pro.sae.components'} = $comp;
     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);


  } elsif ($opts{p} eq "srs") {
     my $ip = $opts{i};
     &provider_usage($flag) if ((!$ip) && ($flag eq 'Y'));
     $renv->{'pro.srs.active'}     = $flag;
     $renv->{'pro.srs.frequency'}  = ($opts{f} + 0) || 6;
     $renv->{'pro.srs.ip'}         = $ip;
     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);


  }elsif ($opts{p} eq "ssrr") {
     $renv->{'pro.ssrr.active'} = $flag;
     $renv->{'pro.ssrr.frequency'}  = ($opts{f} + 0) || 6;
     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);

  } elsif ($opts{p} eq "sunmc") {
     my $ip = $opts{i};
     &provider_usage($flag) if (!$ip && $flag eq "Y");
     $renv->{'pro.sunmc.active'}     = $flag;
     $renv->{'pro.sunmc.frequency'}  = ($opts{f} + 0) || 6;
     $renv->{'pro.sunmc.ip'}         = $ip if ($ip);
     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);

  } elsif ($opts{p} eq "trap") {
     my $trap_num = $opts{t};
     
     if ($trap_num <1 || $trap_num > 5){
        &provider_usage($flag);
     }
     my $ip = $opts{i};
     my $level;
     if($opts{l} eq 'error'){
        $level = '2';
     }elsif($opts{l} eq 'down'){
        $level = '3';
     }elsif($opts{l} eq 'warning'){
        $level = '1';
     }elsif($flag eq "Y"){
        &provider_usage($flag);
     }
     my $port;
     if($opts{o}){
        $port = $opts{o};
     }else{
        $port = "162";
     }
     &provider_usage($flag) if (!$trap_num && $flag eq "Y");

     $renv->{'pro.trap.active'}     = $flag;
     if($flag eq "Y"){
        $renv->{"pro.trap$trap_num.ip"} = $ip;
        $renv->{"pro.trap$trap_num.port"} = $port;
        $renv->{"pro.trap$trap_num.level"} = $level;
     }else{
       delete $renv->{"pro.trap$trap_num.ip"};
       delete $renv->{"pro.trap$trap_num.port"};
       delete $renv->{"pro.trap$trap_num.level"};
     }


     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);

  }

  print "$opts{p} is " . ($flag eq "Y" ? "on" : "off") . "!\n";

}

sub event_list {
  if (!getopts("?h:", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin event_list -h host [-?] \n";
     exit(1);
  }
  print "not yet\n";
}

sub alert_delete {
 if (!getopts("?d:f:s:A", \%opts) || $opts{'?'} ) {
     print "\nUsage: ras_admin alert_delete  -f type[:key[:comp]] -s [1|2|3] -? \n";
     
     print "  -f : DeviceID filter: Enter all or part of the Device key. \n";
     print "  -s : Severity       : Enter 1=warning,2=error, 3=error-critical. \n";
     print "  -A : Delete all alerts entries. \n";
     exit(1);
  }
  
  require State;
  my $comps = State->components();
  my $links = State->links();

  my $dev_filter = $opts{f};
  my $sev_filter = $opts{s};
  my $printed = 0;

  if ($opts{A}) {
    State->clearAllComponents();
    State->clearAllLinks();
    my $del = State->write();
    $del += 0;
    print "Deleted $del entries! \n";
    return;
  }

  my $cnt = 0;
  if ($sev_filter || $dev_filter) {
    State->clearAllComponents($sev_filter, $dev_filter);
    State->clearAllLinks($sev_filter, $dev_filter);
    my $del = State->write();

    my $pat  = "sev=$sev_filter, " if ($sev_filter);
       $pat .= "key=$dev_filter"   if ($dev_filter);
    $del += 0;
    print "Deleted $del entries with $pat \n";
  } 
}


sub alert_list {
 if (!getopts("?d:f:s:", \%opts) || $opts{'?'} ) {
     print "\nUsage: ras_admin alert_list -d desc_pattern -f type[:key[:comp]] -s [1|2|3] -? \n";
     
     print "  -f : DeviceID filter   : Enter all or part of the Device key. \n";
     print "  -s : Severity          : Enter 1=warning,2=error, 3=error-critical. \n";
     print "  -d : Description filter: Pattern against the event description. \n\n";
     exit(1);
  }
  
  require State;
  my $list = State->getStateList();
  my $f = "%-7.7s %-5.5s %-20s %-20s %-40s\n";
  my @S = ('Normal','Warning','Errors','Down');
  my %T = ('C' => 'Comp.', L => 'Link');
  my $dev_filter = $opts{f};
  my $sev_filter = $opts{s};
  my $printed = 0;
  my $cnt;
  foreach my $sev (3,2,1, 0) {
    foreach my $l (@$list) {
      if ($l->[1] == $sev) {
         my $name;
         if ($l->[0] eq 'C') {
           $name = "Name    : $l->[5]";
         } else {
           $name = "Device2 : $l->[3]";
         }
         my $x = 0;
         my $desc;
         my $d = $l->[4];
         while (length($d) > 0) {
            $desc .= substr($d,0,60);
            $d = substr($d,60);
            $desc .= "\n        : " if (length($d) > 0);
         }
         next if ($dev_filter && $l->[2] !~ /^$dev_filter/);
         next if ($sev_filter && $l->[1] ne $sev_filter);
	 next if ($opts{d} && ( $desc !~ /$opts{d}/) );
	 $printed = 1;
         $cnt++;
         print <<EOF;
Severity: $S[$l->[1]] 
Type    : $T{$l->[0]}
Device1 : $l->[2]
$name
Descrip.: $desc

EOF
      }
    }
  }

  if ($cnt) {
    print "Found $cnt alerts entries in Health database.\n";
  } else {
    print "\nNo alerts found.\n";
  } 

}

sub site_info() {
    
  if (!getopts("?", \%opts) || $opts{'?'} ) {
     print "Usage: ras_admin site_info [-?] \n";
     exit(1);
  }

  print <<EOF;
Customer  : $renv->{customer} 
Contract  : $renv->{contract},  CustNo : $renv->{cust_no} 
Address   : $renv->{site_address}, $renv->{site_city}
          : $renv->{site_state}, $renv->{site_zip}, $renv->{site_country}
Contact   : $renv->{site_contact}, Phone: $renv->{site_contact_phone}
Email     : $renv->{site_email}
Production: $renv->{production}

EOF
}

sub host_list {
  if (!getopts("?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin host_list [-?] \n";
     exit(1);
  }
  my ($x, @X) ;
  $hosts = &sort($hosts, "hostname");
  &push_master($hosts, $renv);

  my $f = "%-25.25s %-25.25s %-6.6s %-4.4s %-10.10s %-5.5s\n";

  printf($f, "Hostname","IP","Active","Role", "SE-Model", "Freq.");
  printf($f, &lines(6));
  
  foreach my $h (@$hosts) {
     printf($f, $h->{hostname}, $h->{ipno}||$h->{ip}, $h->{active}, 
            $h->{role}, 
            $h->{solution_model},
            $h->{frequency}, 
            );
  }
  
}

# delete only slaves

sub host_delete {
  if (!getopts("n:d?", \%opts) || $opts{'?'} || !$opts{n} ) {
     print "Usage: ras_admin host_delete -n hostname -d [-?]\n";
     print " -d : delete devices\n";
     exit(1);
  }
  my $x;
  my $name = lc($opts{n});
  my $found;
  for ($x=0; $x <= $#$hosts; $x++) {
     my $h = $hosts->[$x];
     if ($name eq lc($h->{hostname}) ) {
        $hosts->[$x] = {};
        $found = 1;
     }
  }
  if ($found) {
      print "$name deleted.\n";
  } else {
      print "$name not found.\n";
  }
  my $cnt = 0;
  if ($opts{d}) {
     for ($x=0; $x <= $#$devices; $x++) {
         my $dev = $devices->[$x];
         my $h = $dev->{host} || $renv->{hostname};
         if (lc($h) eq $name) {
             $devices->[$x] = {}; $cnt++;
         }
    } 
  } 
  print "$cnt devices deleted.\n";
  PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
}



sub host_detail {
  if (!getopts("n:i:?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin host_detail -n hostname -i ip [-?] \n";
     exit(1);
  }
  my $name = lc($opts{n});
  my $ip   = lc($opts{i});
  &push_master($hosts, $renv);
  foreach my $h (@$hosts) {
     next if ($name && lc($h->{hostname}) !~ /^$name/);
     next if ($ip && lc($h->{ipno}) !~ /^$ip/);
     print <<EOF;
------------------------------------------
Hostname   : $h->{hostname}
Hostid     : $h->{hostid}
IP         : $h->{ipno}
Role       : $h->{role}
SE-Model   : $h->{solution} / $h->{solution_model}
Categories : $h->{categories}
Frequency  : $h->{frequency}
Logfile    : $h->{logfile}
T3Logfile  : $h->{t300logfile}
InBand Mon.: $h->{datahost}
EOF
  }
}

sub device_list {
  if (!getopts("s:h:?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin device_list -s sort -h host [-?] \n";
     print " Sort  : type | host | name \n";
     print " Filter: show devices monitored by this host only \n";
     exit(1);
  }
  if ($opts{s} && index("type,host,name", $opts{s}) < 0) {
     print "Error: Invalid sort name \n";
     exit(1);
  }

  my $f = "%-20.20s %-18.18s %-10.10s %-16.16s %-18.18s %-6.6s\n";
  my $host  = lc($opts{h});

  printf($f, "MonitoredOn","Device","Type","IP", "WWN", "Active");
  printf($f, &lines(6));
  foreach my $d (@$devices) {
     $d->{host} = $renv->{hostname} if (!$d->{host});
     next if ($host && lc($d->{host}) !~ /^$host/);
     printf($f, 
            $d->{host},
            $d->{name}, 
            $d->{type}, 
            $d->{ipno},
            $d->{wwn}, 
            $d->{active}
            );
  }
}

sub device_detail {
  if (!getopts("h:n:i:t:?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin host_detail -h host -n devicename -i ip -t type [-?] \n";
     exit(1);
  }
  my $host = lc($opts{h});
  my $name = lc($opts{n});
  my $ip   = lc($opts{i});

  foreach my $d (@$devices) {
     my $found = 0;
     $d->{host} = $renv->{hostname} if (!$d->{host});
     next if ($host && lc($d->{host})  !~ /^$host/);
     next if ($name && lc($d->{name})  !~ /^$name/);
     next if ($ip &&   lc($d->{ipno})  !~ /^$ip/);

     print <<EOF;
------------------------------------------
DeviceName : $d->{name}
Type       : $d->{type}
Ip         : $d->{ipno}
MonitoredOn: $d->{host}
Key        : $d->{key}
Active     : $d->{active}
Wwn        : $d->{wwn}
EOF
     foreach my $el (sort keys %$d) {
       next if (substr($el,0,1) eq "_" || $el eq "class");
       if (index(",name,host,type,ipno,key,active,wwn,", $el) < 0 && $d->{$el}) {
           printf "%-11.11s: %s\n", ucfirst($el), $d->{$el};
       }
     }
  }
}


sub device_delete_all {
  if (!getopts("?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin device_delete_all [-?]\n";
     exit(0);
  }
  my $x;
  for ($x=0; $x <= $#$devices; $x++) {
     $devices->[$x]{_name} = "";
  }
  PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
  print "All devices deleted!\n";
}

  

  
sub email_list {
  if (!getopts("?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin email_list [-?] \n";
     exit(1);
  }
  my ($x, @X) ;

  my $f = "%-30.30s %-10.10s %-10.10s %-10.10s %-10.10s\n";
  printf $f, "Email/Events", "Type", "Device", "Priority", "Events";
  printf $f, &lines(5);

  foreach my $n (@$notifs) {
     my $dev = $n->{device} eq "*" ? "All" : $n->{device};
     my $prio= $n->{priority} eq "*" ? "All" : $n->{priority};
     my $ev;
     if ($n->{event} eq "*") {
         $ev = "All";
     } else {
       my @E = split(/\|/, $n->{event});
       $ev = $#E + 1;
     }
     printf $f , $n->{email}, $n->{type}, $dev, $prio, $ev;
     print "     " . $n->{event} . "\n" if ($n->{event} ne "*");
     print "     Run:" . $n->{script} . "\n" if ($n->{script});
  }
}

sub site_info_upd {
  if (!getopts("e:n:i?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin site_info_upd  -e new_email -n new_name -i interactive [-?] \n";
     exit(1);
  }
  my $upd = 0;
  if ($opts{e}) {
     $renv->{site_email} = $opts{e};
     $upd = 1;
  }
  if ($opts{n}) {
     $renv->{customer} = $opts{n};
     $upd = 1;
  }
  if ($opts{i} || !$upd) {
     print "\n";
     $upd = &enter($renv, "customer*,contract,cust_no,site_name*,site_address,site_city*,site_state,site_zip*,site_country*," .
            "site_contact*,site_contact_phone,site_email*");
  }
  PDM::ConfigFile->write($renv, $devices, $hosts, $notifs) if ($upd);
}


sub agent {
  if (!getopts("sph:?", \%opts) || $opts{'?'} || (!$opts{s} && !$opts{p}) ) {
     print "  Usage: ras_admin agent [-s|-p]  -h host [-?] \n";
     print "    -s : Start\n";
     print "    -p : Stop \n";
     print "Example: ras_admin agent -s -h host1 \n";
     exit(1);
  }
  if (!$opts{h}) {
     my $F = System->get_home() . "/DATA/start";
     if ($opts{s}) {
        open(O, ">$F"); print O "\n"; close(O);
        print "Agent started!\n";
     } else {
        unlink $F;
        print "Agent stopped!\n";
     }
     return;
  }
  my $host;
  if (!($host = findHost($opts{h}) )) {
     print "Error: Host $opts{h} does not exist!\n";
     print "If this is the Master host, do not use the -h option\n";
     return;
  }
  if ($opts{s}) {
     my $rc =  Util::Http->getCommand($host, "CREAT&file=start", 10);
     print $rc . "\n";
  } else {
     my $rc =  Util::Http->getCommand($host, "DELET&file=start", 10);
     print $rc . "\n";
  }
}

sub review_config {
  if (!getopts("?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin review_config [-?] \n";
     exit(1);
  }
  require GUI::Review;
  my $L = GUI::Review::run_();
  my $cnt=1;
  foreach my $el (@$L) {
    $el =~ s/<a href=[^>]+>//;
    $el =~ s/<\/*font[^>]*>//g;
    $el =~ s/<[\/abrp]+>//g;
    printf "%3.3d. %s\n\n",  $cnt, $el;
    $cnt++;
  }
  if ($#$L < 0) {
     print "No error found in configfile!\n";
  }

}

#######
# T3
#######

sub t3_add {
  if (!getopts("n:i:h:p:?", \%opts) || $opts{'?'} || !$opts{n} || !$opts{i} ) {
     print "Usage: ras_admin t3_add -n name -i ip -h host -p password [-?] \n";
     exit(1);
  }
  if ($opts{h} && !findHost($opts{h}) ) {
    print "Invalid Hostname! \n";
    print "If this is the Master host, do not use the -h option\n";
    return;
  }
  require Logic::T3;
  my ($err, $dev) = Logic::T3->addToConfig(
          { name => $opts{n},
              ip => $opts{i},
            host => $opts{h},
           telnet=> $opts{p},
          });
  if ($err) {
     print $err->toString() . "\n";
  } elsif ($dev) {
     print "Device $opts{n} added ! \n";
     print Dumper($dev);
  } else {
     print "Unknown error \n";
  }
}

##########
# SWITCH
##########


sub switch_add {
  if (!getopts("n:i:h:p:?", \%opts) || $opts{'?'} || !$opts{n} || !$opts{i} ) {
     print "Usage: ras_admin switch_add -n name -i ip -h host -p password [-?] \n";
     exit(1);
  }
  if ($opts{h} && !findHost($opts{h}) ) {
    print "Invalid Hostname! \n";
    print "If this is the Master host, do not use the -h option\n";

    return;
  }
  require Logic::SWITCH;
  my ($err, $nodes) = Logic::SWITCH->addToConfig(
          { name => $opts{n},
              ip => $opts{i},
            host => $opts{h},
	    password => $opts{p}
          });

  if ($err) {
     print $err->toString() . "\n";

  } elsif ($#$nodes >= 0) {
     print "" . ($#$nodes + 1) . " device(s) added! \n";
     foreach my $d (@$nodes) {
        print Dumper($d);
     }
  } else {
     print "Unknown error \n";
  }
}

###############
#  3310
###############

sub discover_3510 {

  if (!getopts("h:?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin discover_3510 -h host [-?] \n";
     print "   Ex: ras_admin discover_3510 -h local \n";
     print "       ras_admin discover_3510      # discover on all hosts \n";
  }
  print "\n";
  require Logic::3310;
  Logic::3310->discover( $opts{h} , "Sun 3310/3510", 0 );
  
}



###############
#  A5K
###############

sub discover_a5k {
  require GUIAdmin;

  if (!getopts("h:?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin discover_a5k -h host [-?] \n";
     print "   Ex: ras_admin discover_a5k -h local \n";
     print "       ras_admin discover_a5k      # discover on all hosts \n";
  }
  print "\n";
  GUIAdmin::luxDiscover({select_host => $opts{h},  
                                TYPE => "a5k", 
                                DESC => 'A5000',
                              FILTER => "SENA",
                              noHtml => 1
                         });
  
}



###############
#  SUBNET
###############


sub discover_subnet {
  require Logic::Subnet;

  if (!getopts("h:s:ap:m?", \%opts) || $opts{'?'} || !$opts{s}) {
     print "Usage: ras_admin discover_subnet -h host -s subnet -a -p prefix -m [-?] \n";
     print "   -a: Use hostname as prefix\n";
     print "   -m: monitoring off\n";
     exit(1);
  }
  my $mon = 1 if (!$opts{m});
  my ($err, $nodes, $info) = Logic::Subnet->addToConfig(
          { host => $opts{h},
            SUB1  => $opts{s},
            prefixT => $opts{a},
            prefix  => $opts{p},
            monitor_on => $mon,
          });
  print $info;
  if ($err) {
     print $err->toString() . "\n";
  } elsif ($#$nodes >= 0) {
     print "found " . ($#$nodes+1) . " devices \n";
  }

}

sub discover_t3 {
  require Logic::T3;
  if (!getopts("pf:?", \%opts) || $opts{'?'} ) {
     print "Usage: ras_admin discover_t3 -f [logfile] [-?] \n";
     exit(1);
  }
  my $file = $opts{f};
  if (!$file) {
    foreach my $f ('messages.t300','messages.t3','messages.6120'){ 
      if (-f "/var/adm/$f") {
        $file = "/var/adm/$f"; last;
      }
    }
  }
  return if (!$file);

  my $list = Logic::T3->find_message_ip($file);  # ['ip1','ip2']
  my $ID = "arrayFromLog";
  my $log = "/tmp/$ID.conf";

  open(O, ">$log");
  foreach my $l (@$list) {
     print O "$l\n";
  }
  close(O);
  &push_devices($ID, $log);
}

sub discover_switch {
  if (!getopts("ph:?", \%opts) || $opts{'?'} ) {
     print "Usage: ras_admin discover_switch [-?] -h host (default is local) \n";
     exit(1);
  }
  
  my $host;
  if ($opts{h} && !findHost($opts{h}) ) {
     print "Error: Host $opts{h} does not exist!\n";
     print "If this is the Master host, do not use the -h option\n";
     return;
  }
  require Logic::SWITCH;
  my ($err, $nodes, $info);					  

  if ($opts{p}) {  # push data into file on master,
     &push_devices("fcswitch", "/etc/fcswitch.conf");
     return;
  }
  if ($opts{h} ){
     ($err, $nodes, $info) = Logic::SWITCH->addFromFile({
                                host => $opts{h},
				monitor_on => 1,
				fileToUse => "/etc/fcswitch.conf",
				select_host => $opts{h}} );
  }else{
     ($err, $nodes, $info) = Logic::SWITCH->addFromFile({
                                host => $opts{h},
				monitor_on => 1,
				fileToUse => "/etc/fcswitch.conf",
				select_host => "local" } );
  }					   
  if ($err) {
    print $err->toString() . "\n";
  } else {
    print "$info\n" if ($info);
  }
}

sub push_devices {
  my($tag, $file) = @_;
  require Logic::SWITCH;

     my $l = System->findProcess("ras_admin discover");
     my $out;
     if ("@$l" !~ /ras_admin/) {
       my $dd = Logic::SWITCH::get_infoFromFile({LOCAL => 1, 
                     fileToUse => $file});
       foreach my $d (@$dd) {
        $out .= "$d\n";
       }
     } else {
       $out .= "ERR|ras_admin discover is already running!\n";
     }
     my $master = Util->findMaster();
     $out .= "#END\n";
     if (!$master) {
        open(O, ">>" . System->get_home() . "/DATA/Discover/$tag.local");
        print O $out;
        close(O);
     } else {
        my $h = $renv->{hostname};
        Util::Http->appendFile($master, "Discover/$tag.$h", $out);
     }
}

sub discover_deviceIP {
  if (!getopts("ph:?", \%opts) || $opts{'?'} ) {
     print "Usage: ras_admin discover_deviceIP [-?]\n";
     exit(1);
  }
  
  my $host;
  if ($opts{h} && !findHost($opts{h}) ) {
     print "Error: Host $opts{h} does not exist!\n";
     print "If this is the Master host, do not use the -h option\n";
     return;
  }
  require Logic::SWITCH;
  my ($err, $nodes, $info);					  

  if ($opts{p}) {  # push data into file on master,
     &push_devices("deviceIP", "/etc/deviceIP.conf");
     return;
  }

  if ($opts{h} ){
     ($err, $nodes, $info) = Logic::SWITCH->addFromFile({
                                host => $opts{h},  TEXT => 1,
				monitor_on => 1, silent => 1,
				fileToUse => "/etc/deviceIP.conf",
				select_host => $opts{h}} );
  }else{
     ($err, $nodes, $info) = Logic::SWITCH->addFromFile({
                                host => $opts{h},  TEXT => 1,
				monitor_on => 1, silent => 1,
				fileToUse => "/etc/deviceIP.conf",
				select_host => "local" } );
  }
  if ($err) {
    print $err->toString() . "\n";
  } else {
    print "$info\n" if ($info);
  }
}
  

###############
# SUBROUTINES
###############

sub findHost {
  my($host) = @_;
  foreach my $h (@$hosts) {
      if (lc($h->{hostname}) eq lc($host)) {
         return $h->{hostname};
      }
  }
  return undef;
}

sub enter {
  my($renv, $l) = @_;
  my @E = split(/,/, $l);
  my $width = 0;
  foreach my $el (@E) {
     $width = length($el) if (length($el) > $width);
  }
  $width += 7;
  my (%q, $ans);
  while (1) {
    foreach my $el (@E) {
       my $label = ucfirst($el); $label =~ s/_/ /g;
       my $mand;
       if (substr($label,-1) eq "*") {
          $mand = 1 ; chop($el);
       }
       while (1) {
         printf("%-${width}s: ",  "Enter $label");
         $ans = <STDIN>; chop($ans);
         last if ($ans || !$mand);
       }
       $q{$el} = $ans;
    }
    print "\n------ You entered ------ \n";
    foreach my $el (@E) {
       printf("%-${width}s: %s\n", ucfirst($el), $q{$el});
    }
    print "Do you want to save these values [y=yes, n=no, q=quit]: ";
    my $yn = <STDIN>;
    chop($yn);
    return undef if (lc($yn) eq "q");
    last if (lc($yn) eq "y");
  }
  foreach my $el (keys %q) {
     $renv->{$el} = $q{$el};
  }
  return 1;
}

sub sort {
   my($h, $key) = @_;
   my (@X, $x, @NEW);
   for ($x=0; $x <= $#$h; $x++)  {
      my $el = $h->[$x];
      push(@X, "$el->{$key} | $x");
   }
   foreach my $el (sort @X) {
       my($v, $ix) = split(/ \| /, $el);
       push(@NEW, $h->[$ix]);
   }
   return \@NEW;
}
         

sub lines {
  my ($cnt) = @_;
  my (@L, $x);
  for ($x=1; $x <= $cnt; $x++) {
     push(@L, "-------------------------------");
  }
  return @L;
}


sub push_master {
  my($hosts, $renv) = @_;
  my %H;
  foreach my $el ('active','categories','frequency','hostid','hostname','ip','ipno','logfile',
         'role','solution','solution_model') {
     $H{$el} = $renv->{$el};
  }
  $H{role} = 'M';
  $H{active} = (-f System->get_home() . "/DATA/start")? "Y":"N";
  unshift(@$hosts, \%H);
}

