#!/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;
use Registration;


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  = ",sequencer_set,sequencer_list,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," . 
   "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,update_frequency,shutdown_device,".
   "ra_control,".
#   "rs_setup_upd,rs_setup_show," .
#   "rs_device_update,rs_list,rs_transport_test," .
    "";


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

  Commands
  -h | help      : This page
  host_list      : List of hosts.
  update_frequency: Update the polling frequency of devices.
  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.
  get_serial     : Get SerialNo (cust_no).
  site_info      : get site information.
  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.
  sequencer_list : list powersequecer relay stats(6940 only)
  sequencer_set  : set powersequecer relay stats(6940 only)
  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.
  shutdown_device: Issue a shutdown command to the specified device.
  ra_control     : Remote Access Controls.


  \n\n";
}

#  rs_setup_upd     : Setup remote service
#  rs_setup_show    : Show remote service settings
#  rs_device_update : Update remote service level for a specific device.
#  rs_list          : List device remote service status.
#  rs_transport_test: Test remote service transport.

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


if(!$renv->{customer}){
    print "**************************************************************************\n";
    print "Site information has not been setup yet. Please run 'ras_admin site_info_upd'\n";
    print "to complete installation.\n";
    print "**************************************************************************\n";

}

#if($renv->{activation_complete} ne "YES"){
#    print "**************************************************************************\n";
#    print "Remote service has not been setup yet. Please run 'ras_admin rs_setup_upd'\n";
#    print "to complete installation.\n";
#    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();
  my $ip = Util->name2ip($name);
  `/opt/SUNWsespsw/bin/admin_dhcp_client -D -i $ip`;
  print "/opt/SUNWsespsw/bin/admin_dhcp_client -D -i $ip";
  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";
  my $ip = Util->name2ip($name);
  $ether =~ s/\://g;
  if ($name =~ /psq/){
        `/opt/SUNWsespsw/bin/admin_dhcp_client -A -i $ip -m $ether -B y >>/tmp/x`;
        print "/opt/SUNWsespsw/bin/admin_dhcp_client -A -i $ip -m $ether -B y\n";
  } else {
        `/opt/SUNWsespsw/bin/admin_dhcp_client -A -i $ip -m $ether -B n`;
        print "/opt/SUNWsespsw/bin/admin_dhcp_client -A -i $ip -m $ether -B n\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/3320/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",
            trap => "SNMP Trap",
      netconnect => "NetConnect",
             sae => "DataHost",
            ssrr => "SSRR",
       };
  my @LIST;
  if ($renv->{solution} eq "N") {
     @LIST = ('netconnect','sunmc','trap', 'sae');
  } else {
     @LIST = ('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 '0'){
        $level = "Info";
     }elsif($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|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 entry for trap provider.\n";
   print "    'ras_admin provider_list' will show current trap entries.\n";
   print "    This option is only needed if you are deleting a trap.\n";
   print " -o port, Default is 162 for trap provider. There is no default for datathost.\n";
   print " -l info: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";
   print "ras_admin provider_on -p trap -l warning -i hostname -o 162\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,netconnect,sae,ssrr,sunmc,trap,", ",$opts{p},") < 0) {
            &provider_usage($flag);
  }
  my ($update, $ori_active);

  
  if ($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;
     if($flag eq "Y"){
       update_ssrr_info();
     }
     $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);
     # remove last_sunmc_topo
     my $suntop = System->get_home() . "/DATA/last_sunmc_topo";
     if(-e $suntop){
        unlink $suntop;
     }

     $update =1;

  } elsif ($opts{p} eq "trap") {
     my $trap_num = $opts{t};
     
     if ($trap_num <1 || $trap_num > 5){
        if($flag ne "Y"){
           &provider_usage($flag);
	}
     }
     my $ip = $opts{i};
     my $level;
     if($opts{l} eq 'down'){
        $level = '3';
     }elsif($opts{l} eq 'error'){
        $level = '2';
     }elsif($opts{l} eq 'warning'){
        $level = '1';
     }elsif($opts{l} eq 'info'){
        $level = '0';
     }elsif($flag eq "Y"){
        &provider_usage($flag);
     }
     my $port;
     if($opts{o}){
        $port = $opts{o};
     }else{
        $port = "162";
     }
     my $x;
     for ($x=1; $x <= 5; $x++ ) {
        my $ip     = $renv->{"pro.trap$x.ip"};
	last if (!$ip);
     }
     if(($x > 5) && ($flag eq "Y") ){
       print "\n\n";
       print "The maximum amount of traps have already been entered.\n";
       print "'ras_admin provider_list' will show current traps.\n";
       print "You must remove a trap before adding a new trap\n";
       print "'ras_admin provider_off -p trap -t NUMBER' will remove an existing trap\n";
       print "\n";
       exit;
     }

     if($flag eq "Y") {
       $trap_num = $x;
     }
     &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"};
       # Must resort list
       my $open_trap = $trap_num;
       for ($x=$trap_num +1; $x <= 5; $x++ ) {
        my $ip     = $renv->{"pro.trap$x.ip"};
	next if (!$ip);
	$renv->{"pro.trap$open_trap.ip"}    = $renv->{"pro.trap$x.ip"};
        $renv->{"pro.trap$open_trap.port"}  = $renv->{"pro.trap$x.port"}; 
        $renv->{"pro.trap$open_trap.level"} = $renv->{"pro.trap$x.level"};
	delete $renv->{"pro.trap$x.ip"};
        delete $renv->{"pro.trap$x.port"};
        delete $renv->{"pro.trap$x.level"};

	$open_trap++;
     }

     }
     my $trapcount = 0;

     for ($x=1; $x <= 5; $x++ ) {
        my $ip     = $renv->{"pro.trap$x.ip"};
	next if (!$ip);
	$trapcount++;
     }
     $renv->{"pro.trap.total"} = $trapcount;
     $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 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/Territory          : $renv->{site_country}
#Primary Contact            : $renv->{site_contact}
#Primary Telephone Number   : $renv->{site_phone}
#Primary Extension          : $renv->{site_extension}
#Primary Contact Email      : $renv->{site_email}
#Secondary Contact          : $renv->{site_contact_secondary}
#Secondary Telephone Number : $renv->{site_phone_secondary}
#Secondary Extension        : $renv->{site_extension_secondary}
#Secondary Contact Email    : $renv->{site_email_secondary}
#SMTP Server for Email      : $renv->{sendmail_server}
#
#
#EOF

my $title = $renv->{solution} eq "N" ? "CustNo" : "SerialNo";

  print <<EOF;
Company Name               : $renv->{customer} 
Contract Number            : $renv->{contract}
$title                   : $renv->{cust_no} 
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/Territory          : $renv->{site_country}
Primary Contact            : $renv->{site_contact}
Primary Telephone Number   : $renv->{site_phone}
Primary Extension          : $renv->{site_extension}
Primary Contact Email      : $renv->{site_email}

EOF
}

sub sequencer_list {
  use Agent::PS;
  my $off_count=0;
  my $ps = new Agent::PS;
  my $H =$ps->getRackRelayStates();
  my $zone;
  foreach my $seq (sort keys(%$H)){
    print "$seq:\n";
    my $zones = $H->{$seq};
    my $zone =0;
    foreach my $relay (@$zones){
      print "\tZone $zone is ";
      if ($relay eq 1){
        print "On\n";
      }else{
        print "Off\n";
        $off_count++;
      }
      $zone++;
    }
  }
  exit($off_count);
}

sub sequencer_set{
  if (!getopts("r:z:s:", \%opts) || $opts{'h'} || !$opts{'r'} || !$opts{'s'})  {
    print "usage:\n\t ras_admin sequencer_set -r rack1a|...|rack3b|rack1|...rack3|all -z 5 -s Off|On\n";
    return;
  }
  my $seq = $opts{r};
  my $zone = $opts{z};
  my $state = $opts{s};
  use Agent::PS;
  my $ps = new Agent::PS;
  my $newState;
  if($state eq "On"){
     $newState = 1;
  }elsif($state eq "Off"){
     $newState = 0;
  }else{
     print "Error: must set -s to On of Off: -s $state\n"
  }
  my @seqs;
  if($seq eq "all"){@seqs=("rack3a","rack3b","rack2a","rack2b","rack1a","rack1b");}
  elsif($seq eq "rack1"){@seqs=("rack1a","rack1b");}
  elsif($seq eq "rack2"){@seqs=("rack2a","rack2b");}
  elsif($seq eq "rack3"){@seqs=("rack3a","rack3b");}
  else{push(@seqs, $seq);}
  my @zones;
  if (!$zone){ @zones = (0,1,2,3,4,5,6,7,8,9,10,11); }
  else{push(@zones, $zone);}
  foreach my $s (@seqs){
    foreach my $z (@zones){
      my $H =$ps->setRackRelayState($s, $z, $newState);
    }
  }
}
#
# Issues a shutdown command to the specified array.
#
sub shutdown_device
{
   my($deviceid) = @ARGV;

   if (!$deviceid)
   {
     print "\nUsage: ras_admin shutdown_device <deviceid> \n";
     print "deviceid must be a unique identifier for the device\n";
     print "IE: ras_admin shutdown_device array00\n\n";
     exit(1);
   }

   my $props = Java::TreefrogControls::getProperties($deviceid);
   my $devType = $props->{type};
   my $rval = "Command not issued";

   if ("6140" eq $devType)
   {
      print "Issuing shutdown command to $deviceid\n";
      $rval = Java::TreefrogControls->powerDownArray($deviceid);
   }
   else
   {
      $rval = "Not supported for $devType type devices";
   }

   print "\nShutdown status: $rval\n\n";

}

sub update_frequency {
   my($ftime) = @ARGV;

   if (!$ftime || $ftime =~ /-h/ || $ftime =~ /\D/ || $ftime < 5 || $ftime >1440) {
     print "Usage: ras_admin update_frequency time [-h] \n";
     print "time must be at least 5 minutes but no greater than 1440 minutes(24 hours).\n";
     print "IE: ras_admin update_frequency 10\n";
     exit(1);
   }
   my $ori = $renv->{frequency};
   $renv->{frequency} = $ftime;

   PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
   print "Frequency updated from $ori minutes to $ftime minutes.\n";

}
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_agent} || $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_agent}|| $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.16s\n";
  my $host  = lc($opts{h});

  printf($f, "MonitoredOn","Device","Type","IP", "WWN", "Active");
  printf($f, &lines(6));
  
  foreach my $d (@$devices) {

     my $active = $d->{active};

     if(!$d->{host}){
        $d->{host} = $renv->{hostname};
	if($renv->{active_agent} =~ /N/){
	  $active = "N (Host off)";
	}
	if($renv->{categories} !~ /$d->{type}/){
	   $active = "N (Category off)";
	}
     }else{
       foreach my $h (@$hosts) {
	  if($d->{host} =~ /$h->{hostname}/){
	    if($h->{active_agent} =~ /N/){
	       $active = "N (Host off)";
	    }
	    if($h->{categories} !~ /$d->{type}/){
	       $active = "N (Category off)";
	    }
	  }
       }
     }  

     next if ($host && lc($d->{host}) !~ /^$host/);
     printf($f, 
            $d->{host},
            $d->{name}, 
            $d->{type}, 
            $d->{ipno},
            $d->{wwn}, 
            $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";
  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{'s'})  ) {
     print "Usage: ras_admin email_add -e email_address -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}){
     print "Option p is no longer used\n";
     $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 ras_setup_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,sub_find_country:site_country*=Country," .
    #        "site_contact*=Primary Contact Name,site_phone*=Primary Telephone Number," .
    #	    "site_extension=Primary Extension,site_email*=Primary Contact Email," .
    #	    "site_contact_secondary=Secondary Contact Name,site_phone_secondary=Secondary Telephone Number," .
    #	    "site_extension_secondary=Secondary Extension,site_email_secondary=Secondary Contact Email," .
    #	    "sendmail_server=SMTP Server for Email"
    #        );
     $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*=Primary Contact Name,site_phone=Primary Telephone Number," .
    	    "site_extension=Primary Extension,site_email*=Primary Contact Email"); 



	    # Do something special:
	    # sendmail_server
  }


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

  print "Site information has been saved.\n";

  

}


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_agent} = "Y";
        print "Agent Activated\n";
     } else {
        $renv->{active_agent} = "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_agent} = $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_func = undef;
       my ($var, $label) = split(/=/, $el);
       if($var =~ /^sub_(.*):(.*)/){
         $var = $2;
	 $var_func = $1;
       }
       #my $label = ucfirst($el); $label =~ s/_/ /g;
       my $mand;
       my $req;
       if (substr($var,-1) eq "*") {
          $mand = 1 ; chop($var);
	  $req = "*";
       }
       while (1) {
         if($var_func){
	    my ($ans2, $var_ans2);
	    ($ans, $var_ans2, $ans2) = &$var_func();
	    if($ans2){
	      $q{$var_ans2} = $ans2;
	    }
	 }else{
	    my $default;
	    $default = "($renv->{$var})" if $renv->{$var};
            printf("%-${width}s %s:$default ",  "Enter $label${req}");
            $ans = <STDIN>; chop($ans);
	    if(!$ans){
	      if($renv->{$var}){
	         $ans = $renv->{$var};
	      }
	    }
	 }
         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);
       if($var =~ /^sub_(.*):(.*)/){
         $var = $2;
	 my $var_func = $1;
       }
       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";
   }
}


sub update_ssrr_info(){

   if (opendir(DIR, "/var/remote.support/scripts")) {
    # package directory exists
    closedir(DIR);

    my $old = $renv->{'pro.ssrr.active'};

    # check to see if myname is set
    open(O, "/etc/uucp/Permissions");
    my @l = <O>; close(O);
    my $l = "@l";
    $l =~ /MYNAME=(.*) MACHINE=/;
    my $machine = $1;
    if ($machine) {
      if ($old ne "Y") {
        system("/bin/rm /var/opt/SUNWstade/DATA/OLD_REPORTS/*");
      }

      if (open(O, "/var/remote.support/files/rss_params")) {
        my($l, %H);
        while ($l = <O>) {
          if ($l =~ /([^\s]+)=(.*)/) {
            my $name  = $1;
            my $val   = $2;
            $val      =~ s/"//g;
            $H{$name} = $val;
          }
        }
        close(O);
        $renv->{customer}      = $H{CUSTOMER_NAME};
        $renv->{site_name}     = $H{SYSTEM_NAME};
        $renv->{cust_no}       = $H{SYSTEM_ID}           if ($H{SYSTEM_ID});
        $renv->{site_city}     = $H{SYSTEM_CITY};
        $renv->{site_state}    = $H{SYSTEM_STATE};
        $renv->{site_zip}      = $H{SYSTEM_ZIP}          if ($H{SYSTEM_ZIP});
        $renv->{site_address}  = $H{SYSTEM_ADDRESS}      if ($H{SYSTEM_ADDRESS});
        $renv->{site_country}  = $H{SYSTEM_COUNTRY}      if ($H{SYSTEM_COUNTRY});
        $renv->{site_contact}  = $H{CUSTOMER_CONTACT}    if ($H{CUSTOMER_CONTACT});
        $renv->{site_email}    = $H{CUSTOMER_EMAIL}      if ($H{CUSTOMER_EMAIL});
        $renv->{site_phone} = $H{CUSTOMER_PHONE} if ($H{CUSTOMER_PHONE});
      }
    } else {
      # could not find machine name
      print "Couldn't find machine name in /etc/uucp/Permissions\n";
      print "SSRR may not be installed correctly.\n";
      print "Config file not updated\n";
      exit(2);
    }
    
  } else {
    # package directory does not exist
    print "Couldn't open /var/remote.support/scripts directory.\n";
    print "SSRR may not be installed correctly.\n";
    print "Config file not updated\n";
    exit(2);
  }

}


sub find_country{

   open(O, "$HOME/System/country_codes.txt");
   my @l = <O>; close(O);
   my $x =1;
   my $default_country;
   my $default_code;
   foreach my $code(@l){
     if($code =~ /(.*):(.*)/){
	my $country = $1;
	if($country eq $renv->{site_country}){
	   $default_country = $country;
	   $default_code = $x;
	}
        print "$x:$country\n";
        $x++;
     }
    }
   while(1){
      my $pr_code;
      if($default_code){
        $pr_code = "($default_code)";
      }
      print "Please Enter the Country/Territory Code from above list: $pr_code";
      my $ans = <STDIN>; chop($ans);
      if(!$ans){
        if($default_code){
	  $ans = $default_code;
	}
      }

      if($ans > 0 && ($ans <= $x)){
         my $code = $l[$ans-1];
         if($code =~ /(.*):(.*)/){
	    my $country_no = $2;
	    my $country = $1;
	    return ($country, "site_country_no", $country_no);
	 }
      }
      my $valid = $x;
      print "Invalid selection. Valid entries are 1 - $valid, please re-enter selection.\n";

   }
}


sub rs_setup_upd{
   if (!getopts("h", \%opts) || $opts{'h'}){
      print "Usage: ras_admin rs_setup_upd [-h]\n";
      exit(1);
   }
   print "1 = Remote Monitoring\n";   #remote_monitoring
   print "2 = No Remote Reporting\n";  #remote_none
   while(1){
      print "Select Remote Service Level from above: ";
      my $ans = <STDIN>; chop($ans);
      if(($ans >0) && ($ans <=  2)){
         $renv->{rsLevel} = rs_level($ans);
	 last;
      }
      print "Invalid answer, please try again. Valid responses are 1-2\n";
   }
   
   if($renv->{rsLevel} eq remote_observation){

     print "Please see the release notes for a complete explanation of what \n";
     print "benefits remote monitoring can provide.\n";
     print "Enter 'c' to confirm you do not want remote monitoring turned on\n";
     print "Press any other key to accept remote monitoring: ";
     my $ans = <STDIN>; chop($ans);
     if($ans eq 'c'){
        
        $renv->{activation_complete}="YES";
        $renv->{transport}="https";
        PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
	print "Remote reporting has been turned off.\n";
        return;
     }
   }
   $renv->{transport}="https";
   print "\n";
   
   print "Enter Https Proxy: ";
   my $ans = <STDIN>; chop($ans);
   $renv->{'pro.https.proxy'} = $ans;
   print "Enter Https Proxy Port: ";
   my $ans = <STDIN>; chop($ans);
   $renv->{'pro.https.proxy_port'} = $ans;
 
   while(1){
      print "\n";
      print "Does the Activation Contact Information match the Primary Contact Information?\n";
      print "Name       : $renv->{'site_contact'}\n";
      print "Telephone  : $renv->{'site_phone'}\n";
      print "Extension  : $renv->{'site_extension'}\n";
      print "Email      : $renv->{'site_email'}\n";
      print "Please enter (y/n): ";

      
      my $ans = <STDIN>; chop($ans);
      if($ans eq 'y'){
        $renv->{'actreg_contact_use_primary'} = 'Y';
        $renv->{'actreg_contact_name'}        = $renv->{'site_contact'};
        $renv->{'actreg_contact_phone'}       = $renv->{'site_phone'};
        $renv->{'actreg_contact_phone_ext'}   = $renv->{'site_extension'};
        $renv->{'actreg_contact_email'}       = $renv->{'site_email'};
	last;
      }elsif($ans eq 'n'){
	$renv->{'actreg_contact_use_primary'} = 'N';

	while(1){
	   print "Enter Activation Contact Name*: ";
           my $ans = <STDIN>; chop($ans);
           $renv->{'actreg_contact_name'}        = $ans;
	   last if ($ans);
	   print "Must enter a Contact Name.\n";
	}
	while(1){
	   print "Enter Activation Contact Phone Number*: ";
           my $ans = <STDIN>; chop($ans);
           $renv->{'actreg_contact_phone'}       = $ans;
	   last if ($ans);
	   print "Must enter a Phone Number.\n";

	}
	print "Enter Activation Contact Phone Extension: ";
        my $ans = <STDIN>; chop($ans);
        $renv->{'actreg_contact_phone_ext'}   = $ans;
	while(1){
	   print "Enter Activation Contact Email*: ";
           my $ans = <STDIN>; chop($ans);
           $renv->{'actreg_contact_email'}       = $ans;
	   last if ($ans);
	   print "Must enter a Contact Email.\n";
	}
	last;
      }
      print "Invalid response, must be y or n.\n";
    }




   while(1){
      print "\n";
      print "*******************************************************************\n";
      print "Information entered:\n";
      rs_setup_show();
      print "Would you like to save this information (y/n)? ";
      my $ans = <STDIN>; chop($ans);
      if($ans eq 'y'){
	 $renv->{activation_complete}="YES";
         PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
	 print "Information has been saved.\n";
	 last;
      }
      if($ans eq 'n'){
        print "Information not saved\n";
	exit;
      }
      print "Invalid response. Enter either y or n.\n";
   }

}


sub rs_setup_show{

  if (!getopts("h", \%opts) || $opts{'h'} ) {
     print "Usage: ras_admin rs_setup_show [-h] \n";
     exit(1);
  }
  my $rslevel = $renv->{rsLevel};
  $rslevel =~ s/_/ /;
  if($rslevel =~ /observation/){
    $rslevel = "None";
  }

  print "Remote Service Level   : $rslevel\n";
  print "\n";
  print "Transport Type         : $renv->{transport}\n";
  if($renv->{transport} =~ /https/){
    print "Http proxy             : $renv->{'pro.https.proxy'}\n";
    print "Http Port              : $renv->{'pro.https.proxy_port'}\n";
  }
  print "\n";
  if($renv->{'actreg_contact_use_primary'} eq 'N'){
     print "Activiation Name       : $renv->{'actreg_contact_name'}\n";
     print "Activiation Telephone  : $renv->{'actreg_contact_phone'}\n";
     print "Activiation Extension  : $renv->{'actreg_contact_phone_ext'}\n";
     print "Activiation Email      : $renv->{'actreg_contact_email'}\n";
  }else{
     print "Activiation Name       : $renv->{'site_contact'}\n";
     print "Activiation Telephone  : $renv->{'site_phone'}\n";
     print "Activiation Extension  : $renv->{'site_extension'}\n";
     print "Activiation Email      : $renv->{'site_email'}\n";
  }

}
sub rs_transport_test{

   if (!getopts("h", \%opts) || 
                     $opts{'h'}
      ){
         print "Usage: ras_admin rs_transport_test\n";
	 exit;
   }

   print "Test https transport\n";
   my $server= $renv->{"pro.https.server"} || "remotemonitoring.sun.com";
   my $proxy = $renv->{"pro.https.proxy"};
   my $port  = $renv->{"pro.https.proxy_port"};
   my $F     = $HOME . "/DATA/rasagent.conf";

   my $transfer = $HOME . "/sbin/https_transfer $server $F";
   if ($proxy && $port) {
      $transfer .= " $proxy $port";
   }
   my @rc = `$transfer 2>&1`;
   if ("@rc" =~ /ERROR/i) {
     my $err = "$rc[0] $rc[1] $rc[2]"; 
     print "Error detected with https transport:\n";
     print "$err\n";
     exit 1;
   } else {
      print "Https transport successful\n";
   }
}

sub rs_level{
  my($level) = @_;

  if($level =~ /1/){
      return "remote_monitoring";
   }
   return "remote_observation";

}

sub rs_device_update_usage{
   print "Usage: ras_admin rs_device_update -d {devicekey} -l Level [-h] \n";
   print " -h : List usage/help.\n";
   print " -d : device key from ras_admin rs_list\n";
   print " -l : Level of monitoring\n";
   print "      1 = Remote Monitoring\n";  #remote_monitoring
   print "      2 = No Remote Reporting\n";  #remote_none
   print " IE: ras_admin rs_device_update -d 100000c0dd06f6c0  -l 1\n";

   exit;

}
sub rs_device_update{
   if (!getopts("h,d:l:", \%opts) || $opts{'h'}  || !$opts{d} || !$opts{l} ||
         (index("1,2,", $opts{'l'}) < 0)) {
      rs_device_update_usage();
   }
   my $found = 0;
   my $ACTIVE_TYPES = Registration->ACTIVE_TYPES;

   foreach my $dev (@$devices) {
      if($dev->{key} eq $opts{d}){
         print "Found device\n";
	 if (index($ACTIVE_TYPES, ",$dev->{type},") < 0){
	    print "This device is not supported by remote monitoring.\n";
	    print "No changes made\n";

	    exit;
	 }

	 $found = 1;
         $dev->{rsLevel} = rs_level($opts{'l'});

      }  
   }
   if(!$found){
      print "Couldn't find device key: $opts{d}\n";
      rs_device_update_usage();
   }

   PDM::ConfigFile->write($renv, $devices, $hosts, $notifs);
   my $level = rs_level($opts{'l'});
   $level =~ s/_/ /;
   if($level =~ /observation/){
     $level = "None";
   }
   print "Device key $opts{d} has been updated to: " . $level;


}

sub rs_list{

   if (!getopts("h,a,d", \%opts) || $opts{'h'} || ($opts{'a'} && $opts{'d'})) {
      print "Usage: ras_admin rs_list [-h] [-a] [-d] \n";
      print " -h : List usage/help.\n";
      print " -a : Display only active remote monitored devices.\n";
      print " -d : Display only deactivated remote monitored devices.\n";
      exit;
   }

   my $next_var; 
   if($opts{'a'}){
       $next_var = ",true,";
   }
   if($opts{'d'}){
       $next_var = ",false,na,";
   }
   my $ll = "%-20.20s %-11.11s %-9.9s %-24s\n";
   printf($ll, "Device","Type", "Active", "Key");
   printf($ll, &lines(4));
   my $ACTIVE_TYPES = Registration->ACTIVE_TYPES;

   foreach my $dev (@$devices) {
      next if (index($ACTIVE_TYPES, ",$dev->{type},") < 0);

      my($rsLevel, $transport, $rsActivated) = Registration->rsLevel($dev, $renv);
      my @f = split(/\./, $dev->{key});
      my $serial = $f[$#f];
      $dev->{host} = $renv->{hostname} if (!$dev->{host});
      if($next_var){
        next if(index($next_var, $rsActivated)<0);
      }
      printf($ll, 
            $dev->{name}, 
            $dev->{type}, 
            $rsActivated, 
	    $dev->{key}

            );
   }

}

sub ra_disclaimer{

         print <<EOF;

  Disabling the remote access feature will prevent Sun from remotely
  repairing your storage device and will likely increase time to
  repair. While the remote access connection can be enabled manually
  during a service event, this activity increases the time required
  to resolve an issue. 

EOF
 
}

sub ra_control{

  if (!getopts("h,e,d,a,s", \%opts) || $opts{'h'} || ($opts{'e'} && $opts{'d'})) {
     print "Usage: ras_admin ra_control [-h] [-e] [-d] [-a] [-s]\n";
     print " -h : List usage/help.\n";
     print " -e : Enable remote access.\n";
     print " -d : Disable remote access.\n";
     print " -a : Accept disabling remote access disclaimer.\n";
     print " -s : Shows current state of remote access.\n";
     exit;
  }
  if($renv->{solution_model} ne "6940"){
    print "This command is not supported on this installation.\n";
    print "This can only be used on a 6940.\n";
    exit 2;
  }

  my $cli = "/var/remote.support/scripts/remote_access_control";
  #my $cli = "/opt/SUNWstade/lib/Client/modem_test.utest";

  if(! -x $cli){
     print "Modem controls are not installed.\n";
     print "ras_admin cannot control modem access at this time.\n";
     exit 1;
  }

  if ($opts{d}) {
    ra_disclaimer();
    if (!$opts{a}) {
      print "\n\nUser must acknowledge the above disclaimer with the -a option when disabling remote access.\n";
      print "The remote access has not been changed.\n";

      exit;
    }

    my $exit_value  = system ("$cli -d >> /dev/null 2>&1 ");
    if($exit_value){
       $exit_value = $exit_value >>8;
       print "Disabling remote access failed. Return value: $exit_value\n";
       exit(1);
    }
    print "Disabling remote access was successfull.\n";
    return;
   
  }

  if ($opts{e}) {
    my $exit_value  = system ("$cli -e >> /dev/null 2>&1 ");
    if($exit_value){
       $exit_value = $exit_value >>8;
       print "Enabling remote access failed. Return value: $exit_value\n";
       exit(1);
    }
    print "Enabling remote access was successfull.\n";
   
  }

  if ($opts{s}) {
    my $exit_value  = system ("$cli -s >> /dev/null 2>&1 ");

    if($exit_value){
       $exit_value = $exit_value >>8;
    }

    if ($exit_value == 255){
       # This is really -1
       print "Remote Access is enabled\n";
    }elsif($exit_value == 254){
       # This is really -2
       print "Remote Access is disabled\n";
    } else {
       print "Couldn't determine the state of remote access. Return value: $exit_value\n";
       exit(1);
    }
   
  }

  return;

}
