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

# 
use strict 'vars';
use System;
use Util::Http;
use Util;
use Getopt::Std;
use PDM::ConfigFile;
use Data::Dumper;
use Process;
use Catalog::Register;
use DiscoveryObject;
use Discover;
use Http;


my $local_p   = $INC[0];
my($ix)    = rindex($local_p, "/");
my(%opts);
use vars qw($REMOTE);
$ENV{PATH} = "/bin:/usr/bin";

# Force HOME for System1 CLI
#my $HOME      = substr($local_p,0,$ix);
my $HOME      = "/opt/SUNWstade";
mkdir "$HOME/DATA/Discover",0777 if (!-d "$HOME/DATA/Discover");
Debug->level($ENV{RAS_DEBUG} || 1);


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_component_list,email_list,email_add,email_delete,site_info_upd,agent,review_config,".
   "discover_subnet,discover_inband,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_deviceIP,device_delete_all,topo_list,topo,provider_list,".
   "show_alarms,ethers_list,ethers_add,ethers_delete,discover_a5k,password_change,discover_subnetp," .
   "advisor,start_cron,stop_cron,get_serial,device_delete,discover_admin,register_catalog," .
   "set_global_password,";

sub usage {
  print "
  Usage: ras_admin command [options]

  Commands
  -h | help      : This page
  site_info      : get site information.
  get_serial     : Get SerialNo (cust_no).
  host_list      : List of hosts.
  stop_cron      : stop agent cron.
  start_cron     : start agent cron.
  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.
  device_delete  : Delete specific devices.
  email_list     : list email set for notifications.
  email_add      : Add email notifications.
  email_component_list: List possible components to receive email on.
  email_delete   : Remove email notification.
  site_info_upd  : Update Site Information.
  agent          : Activate/Deactivate agent.
  review_config  : Review the configuration.
  discover_inband: discover using 'luxadm': a5k,tape,v880disk,internal disks.
  discover_subnet: find t3 and switches on the subnet.
  discover_deviceIP: discover devices entered in /etc/deviceIP.conf.
  discover_a5k   : Discover a5k on master/slaves.
  discover_admin : List and process Discovery Queue.
  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).
  show_alarms    : Show alarms.
  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.
  set_global_password: Change the global password for a general device type.
  register_catalog: Register new device monitoring agent.
  advisor        : Display advisor information for an eventCode.
  \n\n";
}
#  event_list     : Show X most recent alerts.

my $command = shift @ARGV;

if ($command eq "help" || $command eq "-h") {
   &usage();
   exit;
}
if ($command eq "-r") { # running remotely
   $REMOTE = 1;
   $command = shift @ARGV;
}

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

eval {
  ($renv, $devices, $hosts, $notifs, $Config) = PDM::ConfigFile->read();
};

print "Error reading ConfigFile: $@\n" if ($@);


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

System->set_renv($renv);
System->set_Config($Config);

&$command();
Http->clearCache();

print "\n";
exit(0);


sub stop_cron {
  require Rasagent;
  my $rc = Rasagent->startstop_cron('P');  # stop
  print "$rc";
}
sub start_cron {
  require Rasagent;
  my $insp = "Y" if ($renv->{solution} ne "N");
  my $rc = Rasagent->startstop_cron('C', $insp); # start
  print "$rc";
}

sub advisor {
  if (!getopts("e:h", \%opts) || $opts{'h'} || !$opts{e}) {
     print "Usage: ras_admin advisor -e event_code [-h] \n";
  }
  require Grid;

  my $ev = Grid->getInfo("","", {gridno => $opts{e}} );
  print Grid->format($ev);
}
 

 

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();
}

sub register_catalog {
  my $oerr = getopts("ucht:d:", \%opts);
  my $type = $opts{'t'};
  my $dir  = $opts{'d'};

  if ($opts{'h'} || (!$type) ) {
	 if (!$type){
		print "Error: missing type parameter.\n";
	 }
	 print "Usage: ras_admin register_catalog [-uc] <-t <type>> <-d <dev_catalog_dir>>\n";
	 print "  -u Unregister\n";
	 print "  -c Check catalog only.\n";
	 print "  -t <type> A new device type to be added for monitoring.\n";
	 print "  -d <dev_catalog_dir> A directory containing files needed for\n";
	 print "                    monitoring a new plug in device.\n";
	 if ($opts{'h'}){
		exit(0);
	 }
	 exit(1);
  }

  if ($opts{u}){ # unregister
	 Catalog::Register->unregister($type, $dir);
	 exit(0);
  }
  if (!$dir) {
	 print "Error: dev_catalog_dir is required.\n";
	 exit(1);
  }
  if (!Catalog::Register->checkXML($type, $dir)){
	 print "Error: Catalog needs to be fixed.\n";
	 exit(2);
  }
  if (!$opts{c}){ # -c check only
	 my $err = Catalog::Register->register($type, $dir);
	 if ($err){
		print "Error: $err\n";
	 }
  }
}



#  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";
     exit(1);
  }
  my $name = $opts{i};
  if (!$name) {
     print "Error: Enter a key or a ipno!\n";
  }
  my $found;
  foreach my $dev (@$devices) {
     if ( ($opts{i} && $dev->{ipno} eq $opts{i}) ){
        $found = 1;
        if (!$opts{p}) {
           $dev->{telnet} = "";
        } else {
           require MIME::Base64;
           $dev->{telnet} = MIME::Base64::encode($opts{p});
           chomp($dev->{telnet});
        }
        last;
     }
  }
  if ($found) {
    print "Password updated for $name\n";
    PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
  } else {
    print "No device found for $name\n";
  }

}
sub set_global_password_usage{

   print "\n\n";  
   print "Usage: ras_admin set_global_password -t <device type> -p <password> [-h] \n";
   print " This command is used to set the global password for devices.\n";
   print " Note: Use -p \"\" to clear the password.\n";
   print " Valid types are:\n";
   print " minnow  - used to set Sun 3310/3510/3511 device type passwords.\n";
   print " array   - Used to set Sun Storage Array device type passwords.\n";
   print " switch  - Used to set Sun Switch device type passwords.\n";
   print " brocade - Used to set Brocade switch device type passwords.\n";
   print " IE: ras_admin set_global_password -t minnow -p mypassword\n";

}

sub set_global_password {
  if (!getopts("t:p:h", \%opts) || $opts{'h'} ) {
     set_global_password_usage();
     exit(1);
  }
  my $list = ",minnow,array,switch,brocade,";

  my $name = $opts{t};
  if ((!$name) || (index($list, ",$name,") < 0)) {
     print "\n\nError: Enter a valid device type.\n";
     set_global_password_usage();

     exit(1);
  }

  my $pass = $opts{p};

  System->setPassword($name, $pass);

  print "Password has been successfully updated.\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 => "NSCC EMAIL",
            trap => "SNMP Trap",
      netconnect => "NetConnect",
             sae => "DataHost",
            ssrr => "SSRR",
       };
  my @LIST;
  if ($renv->{solution} eq "N") {
     @LIST = ('nscc_email','netconnect','sunmc','trap', 'sae');
  } else {
     @LIST = ('nscc_email','ssrr','trap');
  }
  foreach my $p (@LIST) {
     my $act = $renv->{"pro.$p.active"} || $renv->{"pro.$p.dh_active"} || "N";
     $act = "  $act";
     my $ip = $renv->{"pro.$p.ip"} || $renv->{"pro.$p.datahost"};
     printf($f, $outdata->{$p}, $act,
                $renv->{"pro.$p.frequency"},
                $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++) {
     next if (!$renv->{"pro.trap$x.ip"});
     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|ssrr|sunmc|trap";
  print "\n";
  if($flag eq 'Y'){
   print "Usage: ras_admin provider_on $providers -f frequency -i ipaddr [-?] \n";
   print " -p provider name to update\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 -p 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,ssrr,sunmc,trap,", ",$opts{p},") < 0) {
            &provider_usage($flag);
  }
  my ($update, $ori_active);

  
  if ($opts{p} eq "nscc_email") {
     $ori_active = $renv->{'pro.nscc_email.active'};
     $renv->{'pro.nscc_email.active'}     = $flag;
     $update = 1;

  } 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'));

     $ori_active = $renv->{'pro.sae.dh_active'};
     $renv->{'pro.sae.dh_active'}   = $flag;
     $renv->{'pro.sae.datahost'}    = "$ip:$port";
     $update = 1;
  
  }elsif ($opts{p} eq "netconnect") {

     if($flag eq "Y"){
      my $package_base = System->getPackageInfo("", "SUNWnc01", "BASEDIR");
      if (!$package_base) {
         my $t1 = System->getPackageInfo("", "SUNWsrsvp", "_ALL_");
         if (!$t1->{VERSION}) {
	    # Netconnect not installed, can't enable netconnect
	    print "\n\n***********************************************************\n";
	    print "No Netconnect Package is installed (SUNWnc01 or SUNWsrsvp).\n";
	    print "Cannot enable netconnect notification.\n";
	    print "***********************************************************\n\n";

	    exit(1);
         }
      }

     }
     $ori_active = $renv->{'pro.netconnect.active'};
     $renv->{'pro.netconnect.active'}     = $flag;
     $renv->{'pro.netconnect.max'}        = 2000;
     $update = 1;
  
  } 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'));
     $ori_active = $renv->{'pro.sae.active'};

     $renv->{'pro.sae.active'}     = $flag;
     $renv->{'pro.sae.frequency'}  = ($opts{f} + 0) || 6;
     $renv->{'pro.sae.ip'}         = $ip;
     $renv->{'pro.sae.components'} = $comp;
     $update = 1;


  }elsif ($opts{p} eq "ssrr") {

     $ori_active = $renv->{'pro.ssrr.active'};
     $renv->{'pro.ssrr.active'} = $flag;
     $renv->{'pro.ssrr.frequency'}  = ($opts{f} + 0) || 6;
     $update =1;

  } elsif ($opts{p} eq "sunmc") {
     my $ip = $opts{i};
     &provider_usage($flag) if (!$ip && $flag eq "Y");
     $ori_active = $renv->{'pro.sunmc.active'};
     $renv->{'pro.sunmc.active'}     = $flag;
     $renv->{'pro.sunmc.frequency'}  = ($opts{f} + 0) || 6;
     $renv->{'pro.sunmc.ip'}         = $ip if ($ip);
     $update =1;

  } 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");
     $ori_active = $renv->{'pro.trap.active'};
     $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"};
     }
     $update =1;

  }
  
  if (uc($flag) eq "Y" && uc($flag) ne $ori_active) {
     $renv->{request_data_flush} = time;
     $update = 1;
  }
  if ($update) {
     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{'?'} || (!$opts{'A'} && (!$opts{'s'} && !$opts{'f'})) ) {
     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 $dev_filter = $opts{f};
  my $sev_filter = $opts{s};

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

  my $cnt = 0;
  if ($sev_filter || $dev_filter) {
    my $del = State->clearAllComponents($sev_filter, $dev_filter);
    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);
  }
  my %NAME;
  if ($renv->{solution} ne "N") {
    foreach my $d (@$devices) {
      $NAME{$d->{key}} = $d->{name};
    }
  }
  
  require State;
  require Grid;
  my $list = State->getStateList();
  my $f = "%-7.7s %-5.5s %-20s %-20s %-40s\n";
  my @S = ('Normal','Warning/Major','Error/Critical','Down');
  my $dev_filter = $opts{f};
  my $sev_filter = $opts{s};
  my $cnt;
  foreach my $sev (3,2,1) {

    foreach my $l (@$list) {
      if ($l->[1] == $sev) {
         my $x = 0;
         my $desc;
         my $d = $l->[4];
         my $date = substr($d,0,19);
         $d = substr($l->[4],20) if (length($l->[4]) > 20);
         my $hash = State->eventHash($l->[7]);
         my $gno  = Grid->getNo($hash->{GridCode});
         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}/) );
         my $device = $NAME{$l->[5]} || $hash->{TargetName};
         $cnt++;
         print <<EOF;
Severity: $S[$l->[1]] 
Type    : $hash->{EventType}
Topic   : $hash->{Component}
Event Code  : $gno
Date    : $date
Device  : $device [$l->[5]]
Descrip.: $desc

EOF
      }
    }
  }

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

}





sub show_alarms {
 if (!getopts("?f:ewndx", \%opts) || $opts{'?'} ) {
     print "\nUsage: ras_admin show_alarms -f <outfile> -e -w -n -d -x \n";
     
     print "  -f : Output to this file \n";
     print "  -x : Output in XML \n";
     print "  -d : Show down status alarms \n";
     print "  -e : Show errors \n";
     print "  -w : Show warnings \n";
     print "  -n : Show notices \n\n";

     print "Default format is tab-delimited, one event per line:
          device_type|device_key|topic|severity|event_desc|event_type|device_name|grid_code|device_ip  \n";
     exit(1);
  }
  
  require State;
  my $State = State->read();
  my $Comp  = $State->hash();
  my $out;

  foreach my $el (keys %$Comp) {
     my $comp = $Comp->{$el};
     foreach my $topic (keys %$comp) {
       my $sev = int($comp->{$topic}[0] + 0.5);
       next if ($opts{d} && $sev != 3);
       next if ($opts{e} && $sev != 2);
       next if ($opts{w} && $sev != 1);
       next if ($opts{n} && $sev != 0);

       my($type, $wwn) = split(/\:/, $el);
       my $desc = $comp->{$topic}[1];
       my $eh   = State->eventHash($comp->{$topic}[4]);
       my $out1;
       if ($opts{x}) {
          $out1 =<<EOF;
<event>
  <type>$type</type>
  <key>$wwn</key>
  <topic>$topic</topic>
  <severity>$sev</severity>
  <desc>$desc</desc>
  <eventType>$eh->{EventType}</eventType>
  <deviceName>$eh->{TargetName}</deviceName>
  <gridCode>$eh->{GridCode}</gridCode>
  <ip>$eh->{SourceIP}</ip>
</event>
EOF

       } else {
          $out1 = "$type\t$wwn\t$topic\t$sev\t$desc\t$eh->{EventType}\t$eh->{TargetName}\t$eh->{GridCode}\t$eh->{SourceIP}\n";
       }
       $out .= $out1;
     }
  }

  if ($opts{f}) {
     open(OO, ">$opts{f}");
     print OO $out;
     close(OO);
  } else {
     print $out;
  }
}


sub get_serial {
  print $renv->{cust_no};
}


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

  print <<EOF;
Company Name     : $renv->{customer} 
Contract Number  : $renv->{contract}
Site Name        : $renv->{site_name}
Address          : $renv->{site_address}
Address 2        : $renv->{site_address2}
Mail Stop        : $renv->{site_mailStop}
City             : $renv->{site_city}
State            : $renv->{site_state}
Zip Code         : $renv->{site_zip}
Country          : $renv->{site_country}
Contact          : $renv->{site_contact}
Telephone Number : $renv->{site_phone}
Extension        : $renv->{site_extension}
Contact Email    : $renv->{site_email}

EOF
}

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

  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));
  # Do this host
  my $role = $renv->{role} || "M";
  printf($f, $renv->{hostname}, $renv->{ipno}||$renv->{ip} || System->local_ip, $renv->{active}, 
            $role, 
            $renv->{solution_model},
            $renv->{frequency}, 
            );

  foreach my $h (@$hosts) {
     $role = $h->{role} || "M";
     printf($f, $h->{hostname}, $h->{ipno}||$h->{ip}, $h->{active}, 
            $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;
  my $valid_hosts;
  for ($x=0; $x <= $#$hosts; $x++) {
     my $h = $hosts->[$x];
     $valid_hosts .= "$h->{hostname}\n";
     if ($name eq lc($h->{hostname}) ) {
        $hosts->[$x] = {};
        $found = 1;
     }
  }
  if ($found) {
      print "$name deleted.\n";
  } else {
      print "$name not found. No hosts were deleted.\n";
      print "\nValid host names to delete:\n";
      print "$valid_hosts\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,telnet,", $el) < 0 && $d->{$el}) {
           printf "%-11.11s: %s\n", ucfirst($el), $d->{$el};
       }
     }
  }
}

sub  device_delete {
  if (!getopts("i:k:n:?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin device_delete -n name -i ip -k key [-?]\n";
     exit(0);
  }
  my $name = $opts{n};
  my $ip   = $opts{i};
  my $key  = $opts{k};
  my $x;
  my $deleted = 0;
  for ($x=0; $x <= $#$devices; $x++) {
     if ($name && $devices->[$x]{name} eq $name) {
       $devices->[$x]{_name} = "";
       $deleted = 1;
     } elsif ($ip && $devices->[$x]{ipno} eq $ip) {
       $devices->[$x]{_name} = "";
       $deleted = 1;
     } elsif ($key && $devices->[$x]{key} eq $key) {
       $devices->[$x]{_name} = "";
       $deleted = 1;
     }
  }
  PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
  if($deleted){
     print "Selected device deleted!\n";
  }else{
    print "No devices were deleted\n";
    print "Usage: ras_admin device_delete -n name -i ip -k key [-?]\n";
  }
}


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_component_list{

   my($select);
   my($cat) = Agent->findSelectableAgents();
   my ($c0);
   print "The following is a list of valid selectable components that can be used\n";
   print "in setting up email.\n";
   foreach $c0 (@$cat) {
     my ($c, $c2) = split(/\=/, $c0);
     my $n1 = Util->abb(lc($c) . ".medium") || $c;
     print sprintf("%-10s = %s\n", $c, $n1);

  }

}
  
sub email_list {
  if (!getopts("?", \%opts) || $opts{'?'}) {
     print "Usage: ras_admin email_list [-?] \n";
     exit(1);
  }
  my ($x, @X) ;
  print "SMTP server = $renv->{sendmail_server}\n";
  print "Path to email program = $renv->{mailer}\n\n\n";
  my $f = "%-6.6s %-29.29s %-10.10s %-10.10s %-15.15s %-9.9s %-7.7s\n";
  printf $f, "Entry", "Email/Events", "Type", "Device", "Priority", "Events", "Active";
  printf $f, &lines(7);
  my $count = 0;

  my $phash = {
                 9  => "Major and Above",
		 91 => "Crit. & Above",
		 3  => "Down",
		 2  => "Critical",
		 1  => "Major",
		 };


  foreach my $n (@$notifs) {
     $count++;
     my $dev = $n->{device} eq "*" ? "All" : $n->{device};
     my $prio = $n->{priority} eq "*" ? "All" : $phash->{$n->{priority}};
     my $act= $n->{active} eq "N" ? "No" : "Yes";


     

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

sub email_add {
  if (!getopts("t:l:c:h:p:s:e:", \%opts) || $opts{'h'} || (!$opts{'e'} && !$opts{'p'} && !$opts{'s'})  ) {
     print "Usage: ras_admin email_add -e email_address -p path_to_email_program -c -t type list -l priority -s SMTP_server [-h] \n";
     print "-c is a list of components enclosed by \"'s to send notification on.\n";
     print "   IE: -c \"t3 switch\"\n";
     print "   If no -c option is given, all device notifications will be sent.\n";
     print "-l is the priority of of alerts to be sent\n";
     print "   Valid options are:\n";
     print "   ALL, Major_and_above, Critical_and_above, Down, Critical, Major, Information\n";
     print "   IE: -l Major_and_above\n";
     print "   If no -l option is given, Critical and above emails will be sent\n";
     print "-t is the type of notification, email or pager.\n";
     print "   IE: -t pager\n";
     print "   If no -t option is given, email will be sent.\n";
       
     exit(1);
  }

  if($opts{e}){
     my $x = $#$notifs + 1;
     $notifs->[$x]{_name}     = "notification" . ($x+1);
     $notifs->[$x]{email}     = "$opts{e}";
     $notifs->[$x]{device}    = "*";
     $notifs->[$x]{groups}    = "";
     $notifs->[$x]{language}  = "";
     $notifs->[$x]{email_type} = "C";
     $notifs->[$x]{script}    = "";
     $notifs->[$x]{apply_filters}  = "N";
     $notifs->[$x]{active}  = "Y";

     $notifs->[$x]{skip_agg}  = "1";
     if($opts{t} =~ /pager/){
        $notifs->[$x]{type}      = "Pager";
     }elsif(!$opts{t}){
        $notifs->[$x]{type}      = "Email";
     }else{
       print "Invalid -t option: $opts{t}\n";
       exit;
     }
       
     if($opts{l}){
        my $phash = {ALL => "*",
	             Major_and_above => "9",
		     Critical_and_above => "91",
		     Down => "3",
		     Critical => "2",
		     Major  => "1",
		     Information => "*",
		    } ;

	if($phash->{$opts{l}} ){
	   $notifs->[$x]{priority}  = $phash->{$opts{l}};
	}else{
	  print "Invalid priority: $opts{l}\n";
	  exit;
	}
	  
     }else{
        $notifs->[$x]{priority}  = "91";
     }

     if($opts{c}){
	my($select);
        my($cat) = Agent->findSelectableAgents();
        my ($c0);
	my $valid_comp = ",";
        foreach $c0 (@$cat) {
           my ($c, $c2) = split(/\=/, $c0);
	   $valid_comp  = $valid_comp . "$c,";
        }
        my @L = split(/ +/, $opts{c});
	my $devices;
	foreach my $x (@L) {
	   if($valid_comp =~ /,$x,/){
	     $devices = $devices . " $x";
	   }else{
	     print "Invalid component name: $x\n";
	     chop($valid_comp);
	     print "valid components are:\n";
	     print substr($valid_comp,1);
	     print "\n";
	     exit;
	   }
	     
	}
	$notifs->[$x]{device}    = $devices;
     }else{
        $notifs->[$x]{device}    = "*";
     }
     $notifs->[$x]{event}     = "*" ;

     #$notifs->[$x]{apply_filters}  = $q->{filters} ? "Y" : "N";
     #$notifs->[$x]{skip_agg} = $q->{skip_agg} ? 1:0;
     #$notifs->[$x]{no_grid}  = $q->{no_grid} ? "Y" : "N";
     #$notifs->[$x]{type}     = $q->{type};
  }
  if($opts{p}){
     $renv->{mailer} = $opts{p};
  }
  if($opts{s}){
    $renv->{sendmail_server} = $opts{s};
  }

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

  email_list();
}

sub email_delete {
  if (!getopts("h:e:", \%opts) || $opts{'h'} || !$opts{'e'} ) {
     print "Usage: ras_admin email_delete -e entry#|email [-h] \n";
     exit(1);
  }
  if ($opts{e} =~ /^\d+$/) { # USE EMAIL#
    my $x = $opts{e}-1;
    my $max = $#$notifs + 1;

    if ($x <= $#$notifs) {
      $notifs->[$x]{_name} = "";
      PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
      ($renv, $devices, $hosts, $notifs) = PDM::ConfigFile->read();
      email_list();
    } else {
      print "Invalid entry: -e $opts{e}\n";
      print "Maximum entry is: $max\n";
      print "No updates were performed\n";
    }
  } else {  # USE EMAIL ADDRESS
    my($x, $found);
    for ($x=0; $x <= $#$notifs; $x++) {
       if ($notifs->[$x]{email} eq $opts{e}) {
         $notifs->[$x]{_name} = ""; $found = 1;
       }
    }
    if ($found) {
      PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
      ($renv, $devices, $hosts, $notifs) = PDM::ConfigFile->read();
    } else {
      print "Invalid entry: -e $opts{e}\n";
    }
    email_list();
  }
}
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) {
     if ($REMOTE) {
       print "Interactive command is not supported remotely!\n";
       return;
     }
     print "\n";
     $upd = &enter($renv, "customer*=Company Name,contract=Contract Number," .
            "site_name*=Site Name,site_address=Address,site_address2=Address 2,".
            "site_mailStop=Mail Stop,site_city*=City,site_state=State," .
	    "site_zip=Zip Code,site_country*=Country," .
            "site_contact*=Contact,site_phone=Telephone Number," .
	    "site_extension=Extension,site_email*=Contact Email"
               );
  }
  PDM::ConfigFile->write($renv, $devices, $hosts, $notifs) if ($upd);
}


sub agent {
  if (!getopts("adsph:?", \%opts) || $opts{'?'} || (!$opts{s} && !$opts{p} && !$opts{a} && !$opts{d} ) ) {
     print "  Usage: ras_admin agent [-a|-d]  -h host [-?] \n";
     print "    -a : Activate\n";
     print "    -d : Deactivate\n";
     print "Example: ras_admin agent -a -h host1 \n";
     exit(1);
  }

  my $master = Util->findMaster();
  if ($master) {
     print "Error: This command only works on a master! \n";
     exit(1);
  }

  # change local agent
  if (!$opts{h}) {
     if ($opts{s} || $opts{a}) {
        $renv->{active} = "Y";
        print "Agent Activated\n";
     } else {
        $renv->{active} = "N";
        print "Agent Deactivated\n";
     }
     PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);

     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";
     print_valid_slaves();
     return;
  }
  my $val;
  if ($opts{s} || $opts{a}) {
     my $rc =  Util::Http->getCommand($host, "CREAT&file=start", 10);
     $val = "Y";
     print "Agent on '$host' is now active\n";
  } else {
     my $rc =  Util::Http->getCommand($host, "DELET&file=start", 10);
     print "Agent on '$host' is not active anymore\n";
     $val = "N";
  }
  foreach my $h (@$hosts) {
      if (lc($h->{hostname}) eq lc($host)) {
         $h->{active} = $val;
         last;
      }
  }
  PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
}

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";
  }

}


use vars qw (@SAVE $TAG);

sub clear_queue{
  my($method) = @_;
  my $tot = Discover->stats(1);
     foreach my $el (sort keys %$tot) {
       if (lc($method) eq "all" || $el =~ /^$method/) {
          unlink System->get_home() . "/DATA/Discover/$el";
       }
     }

}

sub discover_admin {
  if (!getopts("c:d:m:ulph?", \%opts) || $opts{'h'} || $opts{'?'}) {
     print <<EOF;
  Usage:
   ras_admin discover_admin  [-l] [-d method | -u | -m method | -c method]  [-?]
      -l : List discovery queues summary.
      -u : process queue(s), update configuration.
      -d "deviceIP|subnet|inband|all" : list queues with device details.
      -m "deviceIP|subnet|inband|all" : monitor queue.
      -c "deviceIP|subnet|inband|all" : clear selected queue(s).
EOF
  exit;
  }

#
# CLEAR QUEIE

  if ($opts{c}) {
     clear_queue($opts{c});
     exit;
  }


# MONITOR QUEUE
#
  if ($opts{m}) {
     delete $opts{u};
     &monitor_queue($opts{m});
  }

# WRITE QUEUE IN CONFIGURATION
#
  if ($opts{u}) {
     Discover->process_discovery({ TRACE => 1 });
     return;
  }

# DISPLAY QUEUES (default)
#
  &display_queue($opts{d});
}

sub monitor_queue {
  my($method) = @_;
  while (&display_queue()) {
      sleep 5;
  }
}


sub display_queue {
  my($details) = @_;
  use Discover;
  my $f = "%-20.20s %-10.10s %-10.10s %-10.10s %-10.10s\n";
  print "\n";
  printf($f, "Discovery","Agent","Agent", "Agent", "Device" );
  printf($f, "Method","Started","Running","Processed", "Found");
  printf($f, &lines(5));
  my $tot = Discover->stats($details ? 1:0);
 
  my $all_running;
  foreach my $el (sort keys %$tot) {
     my $v = $tot->{$el};
     my $running = $v->{start} - $v->{stop};
     $all_running += $running;

     if ($details eq "all" || $el =~ /^$details/ || !$details) {
        printf($f, $el, $v->{start}, $running, $v->{processed}, $v->{lines});
     }

     next if (!$details);
     if ($details eq "all" || $el =~ /^$details/) {
       my $object_list = Discover->read($el);
       foreach my $o (@$object_list) {
         my $name = $o->{name} || $o->{username};
         print sprintf("         >%-10s %-20.20s %s\n", $o->{type}, $name, $o->{ipno});
       }
       print "\n";
     }
  }
  return $all_running;
}


##########################
#  A5K DISCOVERY
##########################

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";
  Discover->beginTopo();
  GUIAdmin::luxDiscover({select_host => $opts{h},  
                                TYPE => "a5k", 
                                DESC => 'A5000',
                              FILTER => "SENA",
                              noHtml => 1
                         });
  Discover->endTopo();
  
}

##########################
# SUBNET DISCOVERY 
##########################

sub discover_subnet {
  require Logic::Subnet;

  my $master = Util->findMaster();
  my $renv   = System->get_renv();
  my $tag = $TAG = "subnet";

  if (!getopts("t:h:I:MP:p?", \%opts) ||  $opts{'?'} || !$opts{I}) {
    print <<EOF;
   Usage: ras_admin discover_subnet [-h host] -I ip_list [-P prefix] [-M] [-p] [-t device_type] [-?]
           -I 'ip-list': list of ip or ip prefix
                Example: -I '10.10.10.10,11.11.11,12.12.12.10-20'
           -h 'host' : run this command on this host.
           -t 'type' : optional.
           -M : turn off monitoring.
           -P : prefix label for device name.
           -p : write to discovery queue only.
EOF
   exit;
  }
  if ($opts{h}) {
    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";
       print_valid_slaves();
       return;
    }
    #request that subnet runs on a slave.
    my $opt_p = "-p" if ($opts{p});
    my $err = Discover->ras_admin($host, "discover_subnet $opt_p -I\"$opts{I}\" ",
                          $renv, $hosts, "subnet",
                           {      prefix => $opts{P},
                              monitor_on => $opts{M} ? "N" : "Y",
                            });
    if ($err) {
      print "Error encountered\n";
      print $err;
    } else {
      sleep(10);
      &monitor_queue('subnet');
    }
    return;
  }


  my $status = Process->status(undef, "subnet");
  my($out);
  if ($status =~ /Running/) {
    print "Discovery process already running.\n";

  } elsif (Process->startIf("subnet")) {
    System->set_traceFile("/opt/SUNWstade/DATA/tmp/subnet_trace");
    Debug->trace("discover_subnet @ARGV", 1);

    Discover->beginTopo();
    Discover->logit("#START " . Util->get_today(), "subnet", 1);
    require Logic::Subnet;

    my $data = Logic::Subnet::discover_ip_list({
               ip_list => $opts{I},
                prefix => $opts{P},
                type   => $opts{t},
              access_mode => "OOB",
            monitor_on => $opts{M} ? "N" : "Y",
              callback => "subnet",
                     });      

    my $hname = $master ? $renv->{hostname} : "";
    Discover->logit("#END " . Util->get_today(), "subnet");
    if (!$opts{p}) {  # no -p (push), process immediately
       Discover->processQueue("subnet");
    }
    Discover->endTopo();
    Process->done("subnet");
  }

}




sub log1 {
  my($l) = @_;
  open(OO, ">>/tmp/xx"); print OO "$l\n"; close(OO);
}


##########################
# INBAND DISCOVERY 
##########################

# Function: discover_inband()
# can be used with -p :
#    (push to master Discover Dir but does not write in config file).

sub discover_inband {
  if (!getopts("l:MP:ph:?", \%opts) || $opts{'?'} ) {
     print <<EOF;
   Usage: ras_admin discover_inband [-h host] [-P prefix] [-M] [-p] [-?] [-l level]
           -h 'host' : run this command on this host.
           -M : turn off monitoring.
           -l level: 0=InBand,1=0+OutOfBand from Inband IP, 2=All
           -P : prefix for device name.
           -p : write to discovery queue only.
EOF
     exit(1);
  }
  
  my $host;
  if ($opts{h}) {
    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";
       print_valid_slaves();
       return;
    }
    #request that inband runs on a slave.
    my $opt_p = "-p" if ($opts{p});
    $opt_p .= " -l $opts{l}" if (exists $opts{l});
    my $err = Discover->ras_admin($host, "discover_inband $opt_p ",
                          $renv, $hosts, "inband",
                           {      prefix => $opts{P},
                              monitor_on => $opts{M} ? "N" : "Y",
                            });
    if ($err) {
      print $err;
    } else {
      &monitor_queue('inband');
    }
    return;
  }

  # RUN Locally on Slave or Master, push to the Master
  my ($err, $nodes, $info);					  


  my $master = Util->findMaster();
  my $renv   = System->get_renv();
  my $tag = $TAG = "inband";

  my $status = Process->status(undef, "inband");
  my($out);
  if ($status =~ /Running/) {
    print "Discovery process already running.\n";

  } elsif (Process->startIf("inband")) {
    System->set_traceFile("/opt/SUNWstade/DATA/tmp/inband_trace");
    Debug->trace("discover_inband @ARGV", 1);

    Discover->beginTopo();
    Discover->logit("#START " . Util->get_today(), "inband", 1);

    require Logic::Inband;
    $DB::single=1;
    my $data = Logic::Inband::get_devices({ 
                   callback => "inband",
                 monitor_on => $opts{M} ? "N" : "Y",
                disco_level => $opts{l},
                     prefix => $opts{P},
                    });

    sleep(2);
    Discover->logit("#END " . Util->get_today(), "inband");
    if (!$opts{p}) {  # no -p (push), process immediately
       Discover->processQueue("inband");
    }
    Discover->endTopo();
    Process->done("inband");
  }
}

##########################
# DEVICE-IP DISCOVERY 
##########################

sub discover_deviceIP {
  if (!getopts("h:AP:Mp?", \%opts) || $opts{'?'} ) {
     print <<EOF;
  Usage: ras_admin discover_deviceIP [-h host] [-?] [-A] [-M] [-P] [-p] [-P prerfix] 
           -p : write to discovery queue only.
           -h 'host' : run this command on this host.
           -M : turn off monitoring.
           -P : prefix label for device name.
           -A : process all entries, including what is already in the agent configuration.
EOF
     exit(1);
  }

  my $host;
  if ($opts{h}) {
    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";
       print_valid_slaves();
       return;
    }
    #request that inband runs on a slave.
    my $opt_p = "-p" if ($opts{p});
    my $err = Discover->ras_admin($host, "discover_deviceIP $opt_p ",
                          $renv, $hosts, "deviceIP",
                           {      prefix => $opts{P},
                              monitor_on => $opts{M} ? "N" : "Y",
                            });
    if ($err) {
      print $err;
    } else {
      &monitor_queue('deviceIP');
    }
    return;
  }
  
  require Logic::SWITCH;
  my ($err, $nodes, $info);					  


  my $tag        = "deviceIP";
  my $file       =  "/etc/deviceIP.conf";
  my $prefix     =  $opts{P};
  my $all_devices=  $opts{A};
  my $opts_p     =  $opts{p};

  my $master = Util->findMaster();
  my $renv   = System->get_renv();

  $TAG = $tag;

  my $status = Process->status(undef, "deviceIP");
  my($out);
  if ($status =~ /Running/) {
    print "Discovery process already running.\n";

  } elsif (Process->startIf("deviceIP")) {
    System->set_traceFile("/opt/SUNWstade/DATA/tmp/deviceIP_trace");
    Debug->trace("discover_deviceIP @ARGV", 1);

    Discover->logit("#START " . Util->get_today(), $tag, 1);
    Discover->beginTopo();

    my $dd = Logic::SWITCH::get_infoFromFile({
                                        LOCAL => 1, 
                                    fileToUse => $file, 
                                   monitor_on => $opts{M} ? "N" : "Y",
                                     callback => $tag,
				       prefix => $opts{P},
                                   access_mode=> "OOB",   
                                  all_devices => $all_devices,
                                    });
    sleep 2;
    Discover->logit("#END " . Util->get_today(), $tag);
    if (!$opts_p) {  # no -p (push), process immediately
       Discover->processQueue("deviceIP");
    }
    Discover->endTopo();
    Process->done("deviceIP");
  }
}
  

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

sub findHost {
  my($host) = @_;
  foreach my $h (@$hosts) {
      if (lc($h->{hostname}) eq lc($host)) {
         return $h->{hostname};
      }
  }
  # Didn't match on full name try first part of name
  foreach my $h (@$hosts) {
      my $ix = index($h->{hostname}, ".");
      if($ix > 0){
        my $short = substr($h->{hostname}, 0, $ix);
        if (lc($short) eq lc($host)) {
         return $h->{hostname};
	}
      }
  }

  return undef;
}

sub enter {
  my($renv, $l) = @_;
  my @E = split(/,/, $l);
  my $width = 0;
  foreach my $el (@E) {
     my ($var, $label) = split(/=/, $el);
     $width = length($label) if (length($label) > $width);
  }
  $width += 7;
  my (%q, $ans);
  print "Type 'q' to quit \n";
  while (1) {
    foreach my $el (@E) {
       my ($var, $label) = split(/=/, $el);
       #my $label = ucfirst($el); $label =~ s/_/ /g;
       my $mand;
       my $req;
       if (substr($var,-1) eq "*") {
          $mand = 1 ; chop($var);
	  $req = "*";
       }
       while (1) {
         printf("%-${width}s %s: ",  "Enter $label$req");
         $ans = <STDIN>; chop($ans);
         last if ($ans || !$mand);
       }
       last if ($ans eq "q");
       $q{$var} = $ans;
    }
    print "\n------ You entered ------ \n";
    foreach my $el (@E) {
       my ($var, $label) = split(/=/, $el);
       my ($var, $label) = split(/=/, $el);
       if (substr($var,-1) eq "*") {
          chop($var);
       }

       printf("%-${width}s: %s\n", $label, $q{$var});
    }
    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(substr($yn,0,1)) eq "y");
    # Reset array
    @E = split(/,/, $l);

  }
  foreach my $el (keys %q) {
     my ($var, $label) = split(/=/, $el);
     if (substr($var,-1) eq "*") {
          chop($var);
     }

     $renv->{$var} = $q{$var};
  }
  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} = $renv->{active};
  $H{ipno}   = Util->name2ip();
  $H{hostid} = System->hostid();
  unshift(@$hosts, \%H);
}

sub print_valid_slaves{
   print "Valid slave hosts are:\n";
   foreach my $h (@$hosts) {
     print "  $h->{hostname}\n";
   }
}

