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

use Util;
use System;
use strict "vars";
use Modules;
use Html;
use Html::Tabs;
use Html::List;
use GUI::Graph;
use Util::Http;
use PDM::ConfigFile;
use Thresholds;
use Data::Dumper;
use Util::Http;
use TO;
use FC;
use Html::Tabs;
use FCConfig::Python;
use Agent;


# 'SWITCHAgent' => {
#    'data' => {
#      '|100000c0dd00885d|port.002|switch' => '0 0  0  0  0  141  63  1010',
#    },
#    'enc' => {
#      '100000c0dd008849' => 'python_switch',
#      '100000c0dd00885d' => 'switch-diag196',
#    },


sub merge_topo {
  my($q) = @_;
  my($l);
  my($mach);
  my $G = Labels->read();
  my $L = Labels->read('GUI::SAN')->section('merge');

  if ( Util->findMaster()) {
    print "\n<body bgcolor=white><h1><center>This function is not allowed on a slave!";
    return;
  }

  my $deny = Roles->verifyRole($q, "admin");
  my($button1, $button2);

  if (!$deny) {
    $button1 = "<input type=submit name=ACTION_delete value=\"$L->{submit_del}\">";
    $button2 = "<input type=submit name=ACTION_create value=$L->{submit_create}>";
  } else {
    $q->{ACTION} = "";
  }

  my($F) = System->get_home() . "/DATA/topo_merge";
  my($err);
  print Html->body();
  print Html->header2("admin.topo.merge", "90%");

  if ($q->{ACTION_delete}) {
    my($dels);
    foreach my $x (keys %$q) {
       if (substr($x, 0, 4) eq "del_") {
          $dels .= substr($x,4) . ",";
       }

    }
    if (!$dels) {
      $err = Html->error($L->{err_no_topo});
    } else {
      open(O, $F);
      my(@a) = <O>; close(O);
      open(W, ">$F");
      foreach my $m (@a) {
        my(@b) = split(/\|/, $m);
        if (index(",$dels" , "$b[0],") < 0) {
           print W $m;
        } else {
           unlink System->get_home() . "/DATA/topo/SAN-$b[0]";
        }
      }
      close(W);
      $err = Html->info($L->expand('info_1', $dels));
    }

  } elsif ($q->{ACTION_create}) {
    while (1) {
     if ($q->{merge}) {
        $q->{merge} =~ s/ /_/g;
        $q->{merge} = "master" if ($q->{merge} eq "MASTER");
        open(O, $F);
        my(@a) = <O>; close(O);
        foreach my $m (@a) {
          chop($m);
          my(@b) = split(/\|/, $m);
          if ($b[0] eq $q->{merge}) {
             $err = Html->error($L->expand('err_2', $b[0]));
             last;
          }
        }
        last if ($err);
        my($members);
        my($cnt);
        foreach my $x (keys %$q) {
           if (substr($x, 0, 4) eq "sel_") {
              $members .= substr($x,4) . "\t";
              $cnt++;
           }
        }
        open(O, ">>$F");
        my($today) = Util->get_today();
        print O "$q->{merge}|$today|$members\n";
        close(O);
        $err = Html->info($L->expand('info_2',$q->{merge}));
        unlink System->get_home() . "/DATA/topo/MERGE-$q->{merge}";
        
        last;       
     } else {
        $err = Html->error($L->{err_3});  # no name
        last;
     }
    }
  }
  open(O, $F);
  my(@a) = <O>; close(O);

  print "
 $err
 <table border=1 cellspacing=0 width=90% bgcolor=white>
 <form><input type=hidden name=GO value=GUI::SAN::merge_topo>
 <tr><td bgcolor=#666699 colspan=4><table border=0><tr><td>
    <font color=white><b>$L->{label1}</table></td>
 <tr bgcolor=#DDDDFF>
     <th width=10%>$L->{l1}
     <th width=30%>$L->{l2}
     <th>$L->{l3}
     <th>$L->{l4}
    ";

  my($cnt) = 0;
  my(%M);
  foreach my $m (sort @a) {
    chop($m);
    
    my(@b) = split(/\|/, $m);
    $b[2] =~ s/\.com\t/\t/g;
    $b[2] =~ s/\t/, /g;
    my($toponame) = $b[0];
    $M{$b[0]} = 1;
    my $ck = ($b[0] ne "MASTER")? "<input type=checkbox name=del_$b[0]>" : "&nbsp;";
    print "<tr>
   <td><center>$ck</td>
   <td width=30%>&nbsp;$toponame
   <td>&nbsp;$b[1]
   <td>$b[2]
    ";
    $cnt++;
  }
  my $tlist = TO->topoList();
  foreach my $x (@$tlist) {
     if (substr($x,0,5) eq "MERGE" && !$M{substr($x,6)}) {
         unlink System->get_home() . "/DATA/topo/$x";
     }
  }
  if (!$cnt) {
    print "<tr><td colspan=4><b>$L->{err_4}</table>";
 
  } else {
    print "</table><b>
    <table border=1 cellspacing=0 cellpadding=0 width=90%><tr><td><b>
     $button1
    </table>
     ";
  }
  print "&nbsp;";

  my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read;

  print "</table>
  &nbsp;
  <table border=1 cellspacing=0 width=90% bgcolor=white>
  <tr><td colspan=3 bgcolor=#666699>
    <table border=0><tr><td><font color=white><b>$L->{label2}</table></td>
  <tr bgcolor=#DDDDFF>
     <th width=10%>$L->{select}
     <th >$L->{name}
     <th >$L->{created}
      ";


  $cnt =0;

  my $D2 =  System->get_home() . "/DATA/topo";
  opendir(O, $D2);
  my(@topos) = readdir(O); closedir(O);
  foreach my $h (@topos) {
     next if (substr($h,0,1) eq "." || substr($h,0,6) eq "MERGE-");
     next if (-d "$D2/$h");
     my($name) = $h;
     my $created = Util->get_file_created("$D2/$h");
     print "<tr>";
     print "<td ><center><input type=checkbox name=sel_$name>
            <td >&nbsp;$name</td>
            <td >&nbsp;$created</td>
            ";
     $cnt++;
  }
  print "</table>";

  if ($cnt > 0) {
    print "
    <table border=1 cellspacing=0 cellpadding=0 width=90%><b>
    <tr><td colspan=3>
     <table border=0 cellspacing=0 cellpadding=0 width=95%><tr>
     <td align=right><b>$L->{info_3}:</td>
     <td><input type=text name=merge size=20></td>
     <td><b>$button2</td>
     </table>
    </table>";
  }
  print "</form>";
  
}
#   <td><b>&nbsp;Show all devices:<input type=checkbox name=allports></td>

sub start_topo {
  my($q) = @_;
  system(System->get_home() . "/bin/sendNewTopo $q->{master}&");
}

sub display_topo {
   my($f) = @_;
   my $out;
   my $ix = rindex($f, ".");
   my($to) = substr($f, 0, $ix);
   my($date) = substr($f, $ix+1);
   $out = "<table border=1 cellspacing=0 width=100% bgcolor=#DDDDFF>
    <tr><td><b>&nbsp;Topology for $to /$date</table>";
   my($out2, $running) = GUI::Graph::genApplet(
                          {topo   => $f, 
                           HIST   => 1, 
                           NOFUNC => 1, 
                           offy => 75 , zoom => 2
                           });
   $out .= $out2;
   return $out;
}

sub snapHistory {
  my($q) = @_;
  my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read();
  my $TH = System->get_home() . "/DATA/topohist";

  my $G = Labels->read();
  my $L = Labels->read("GUI::SAN")->section('snapHistory');

  print Html->body();
  print Html->header2("admin.topo.history", "95%" );

  if ($q->{ACTION_compare}) {
     my ($t1, $t2, $t3);
     foreach my $x (keys %$q) {
         next if (substr($x,0,4) ne "del_");
         if (!$t1) {
             $t1 = substr($x,4);
         } elsif (!$t2) {
             $t2 = substr($x,4);
         }elsif (!$t3) {
             $t3 = substr($x,4);
             last;
         }

     }
     if($t3){
        # more than 2 were selected
	print Html->warning($L->expand('err_1'));
     }elsif (!$t1 || !$t2) {
         print Html->warning($L->expand('err_2'));
     }
     else {
         my(@t1stat, @t2stat);
	 @t1stat = stat($TH . $t1);
	 @t2stat = stat($TH . $t2);
	 # compare file times
         if ($t1stat[9] gt $t2stat[9]) {
	   # move the oldest file to the first position
           my $save = $t1; $t1 = $t2; $t2 = $save;
         }

         my $topo1 = Util->deserialize("topohist/$t1");
         my $topo2 = Util->deserialize("topohist/$t2");
         my $diff = TO->diff($topo1, $topo2, 2);
         my $out;
         my ($cnt, $ll);
         foreach my $l (@$diff) {
            if ($ll ne $l->[0]) {
               $out .= "<tr><td colspan=2 bgcolor=#CCCCFF><b>$l->[0] changes</td>";
               $ll = $l->[0];
            }
            $out .= "<tr><td></td><td>$l->[2]</td>";
         }
         $out = "<b>$L->{nodiff}" if ($#$diff < 0);
         print "
    <script>
    function openw(a, count) {
      var b = '$Http::WEBPROC?GO=GUI::SAN::snapHistory&topo=' + a;
      var O = window.open(b,'hist','menubar=no,resizable=yes,scrollbars=yes,width=700,height=500');
      O.focus();
    }
    </script>
           <table border=1 cellspacing=0 cellpadding=3 bgcolor=white width=95%>
           <tr><td bgcolor=#666699 colspan=2>
            <table border=0 width=100% cellspacing=0>
              <tr><td><font color=white><b>$L->{compare}</td>
              <td align=right><b><font color=white>
                 [<a href=$Http::WEBPROC?GO=GUI::SAN::snapHistory><font color=white>$L->{back}</font></a> ]</table></td>
  
           <tr><td width=10% bgcolor=#CCCCFF align=right><b>$L->{topo1}:</td><td><a href=javascript:openw('$t1','1')>$t1</a></td>
           <tr><td bgcolor=#CCCCFF align=right><b>$L->{topo2}:</td><td><a href=javascript:openw('$t2','2')>$t2</a></td>
           <tr><td colspan=2><b>&nbsp;</td>
             $out
           </table>
          &nbsp;<br> ";
         return;
     }

  } 
  elsif ($q->{ACTION_delete}) {
     foreach my $x (keys %$q) {
         next if (substr($x,0,4) ne "del_");
         if (substr($x,4,2) eq "..") {
            print "$L->{cannot_delete}<br>";
            next;
         }
         print "Deleting " . substr($x,4) . "<br>"; 
         unlink "$TH/" . substr($x,4);
     }

  } elsif ($q->{topo}) {
     print &display_topo($q->{topo});
     return;
  }
  &clean_history();

  opendir(O, $TH);
  my @D = readdir(O); closedir(O);
  my($curr);
  print "<table border=1 cellspacing=0 width=95% bgcolor=white>
   <form><input type=hidden name=GO value=GUI::SAN::snapHistory>
   <tr><td colspan=5 bgcolor=#666699><font color=white><b>$L->{title}</td>
   <tr bgcolor=#DDDDFF>
     <th>$L->{host}
     <th>$L->{current}
     <th>$L->{date1}
     <th>$L->{date2}
     <th>$L->{date3}</td>";
  my $cnt;
  foreach my $f  (sort @D) {
     next if (substr($f,0,1) eq ".");
     my $ix = rindex($f, ".");
     my($to) = substr($f, 0, $ix);
     my($date) = substr($f, $ix+1);
     if ($to ne $curr) {
       print "<tr><td></td><td></td>" if ($curr);
       print "<tr><td>&nbsp;<b>$to</td><td><center><input type=checkbox name=\"del_../topo/$to\">";
       $cnt = 0;
       $curr = $to;
     }
     print "<tr><td></td><td></td>" if ($cnt % 3 == 0 && $cnt > 0);
        
     print "<td>&nbsp;<input type=checkbox name=\"del_$f\"><small>&nbsp; <a href=$Http::WEBPROC?GO=GUI::SAN::snapHistory&topo=$f>$date</a>";
     $cnt++;
  }
  print "</table>
  <table border=0 width=90%><tr><td>
  <b><input type=submit name=ACTION_compare value=\"$L->{submit_comp}\">
  <td>
  <b><input type=submit name=ACTION_delete value=\"$L->{submit_del}\"
      onclick=\"return confirm('$L->{confirm_del}')\">
  </table>
  </form>";
  
}


sub clean_history {
  my $renv = System->get_renv();
  my (%T, $x);
  my $cnt = $renv->{topo_history_size} || 5;
  my $DIR = System->get_home() . "/DATA/topohist";
  opendir(O, $DIR);
  my @D = readdir(O); closedir(O);
  foreach my $f (sort @D) {
    next if (substr($f,0,1) eq ".");
    my $ix = rindex($f , ".");
    if ($ix > 0) {
       $T{substr($f,0,$ix)} .= substr($f,$ix+1) . "|";
    }
  }
  my $delete;
  foreach my $f (keys %T) {
     my @X = split(/\|/, $T{$f});
     for ($x=$#X-$cnt; $x >= 0; $x--) {
         unlink "$DIR/$f." . $X[$x];
         $delete++;
     }
  }
  if ($delete) {
     print "deleted $delete topologies!";
  }
}


#
# send master topo to all slaves, also create wwn_map
sub create_master {
   my($master,$mlist, $hosts, $TM) = @_;
   my($info, $err);
   my($temp_hosts);
   #my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read();
   my($renv, $devs, $temp_hosts,$notifs) = PDM::ConfigFile->read();

   $master->saveTopo("MERGE-MASTER");

   my $topoList = TO->topoList();
   foreach my $t (@$topoList) {
     my $to1 = TO->readTopo($t);
     next if (!$to1);
     my $sts = $to1->storageList();
     my $wwns;
     foreach my $st (@$sts) {
       next if ($st->type() ne "a5k");
       my $disks = $st->diskInfo();
       foreach my $disk (keys %$disks) {
          my $ix = index($disk, "_");
          my $dd = $disk;
          my $slot;
          $dd = substr($dd,0,$ix) if ($ix > 0);
          if (substr($dd,0,1) eq "f") {
             $slot = "front." . substr($dd,1);
          } else {
             $slot = "rear." . substr($dd,1);
          }
          $wwns .= $disks->{$disk}{PortWWN} . 
                  "=Box:$st->{info}{BoxName}\tDRIVE:$slot\t" . 
                  "Box WWN:" .substr($st->{info}{name},4) ."\tLogical Path:".
                  " $disks->{$disk}{LogicalPath}" .  "\n";
       }
     }
     if ($t eq $renv->{hostname}) {
        open(O, ">" . System->get_home() . "/DATA/WWN_MAP");
        print O $wwns;
        close(O);
     } else {
        my $rc = Util::Http->saveFile($t, "/WWN_MAP", $wwns);
     }
   }


   my $date1 = Util->get_today();
   my($new, $l);
   if (open(O, $TM)) {
      while ($l = <O>) {
        next if (substr($l,0,7) eq "MASTER|");
        $new .= $l;
      }
      close(O);
   }
   open(O, ">$TM");
   print O $new;
   my($today) = Util->get_today();
   print O "MASTER|$today|" . join("\t", @$mlist) . "\n";
   close(O);
   $info .= "Master Topology created! <br>\n";

   foreach my $h (@$hosts) {
      my $rc = Util::Http->sendFile($h->{ipno}|| $h->{ip}, "/topo/MERGE-MASTER");
      $info .= "Sending to $h->{hostname}: $rc <br>";
      if ($rc =~ /OK/) {
        $h->{last_master_topo} = $date1;
      }
   }
   return $info;
}


sub errors {
  my($q) = @_;
  my $out;
  my $h = Html->header("Topology Error","99%","","");
  print "<body bgcolor=#F0F0F0>
   $h
   <table border=0 cellspacing=0 cellpadding=3 width=100% bgcolor=#666699 bgcolor=white>
     <tr> <td colspan=2><b><font color=white>Host: $q->{topo}
   </table>";

  print "<table border=1 cellspacing=0 cellpadding=1 width=100% bgcolor=white>";

  my $to = TO->readExistingTopo($q->{topo});

  my $errs = $to->[6];
  my $head;
  my $cnt = 0;
  foreach my $k (keys %$errs) {
     $head = 0;
     my $p = $errs->{$k};
     foreach my $k1 (keys %$p) {
       if ($p->{$k1}) {
         if (!$head) {
            $out .= "<tr bgcolor=#CCCCFF><td colspan=3>&nbsp;<b>$k</td>";
            $head = 1; $cnt++;
         }
         $out .= "<tr><td></td><td>$k1</td><td>$p->{$k1}" ;
       }
     }
  }
  if (!$cnt) {
     print "<tr><td colspan=2><b><center>No Errors found!</td>";
  }
  $out .= "</table>";
  print $out;

}



#
# generate snapshots
#

sub snapshot {
  my($q) = @_;

  my($mach, $meta, $metaflag, $out);
  my $G = Labels->read();
  my $L = Labels->read("GUI::SAN")->section('snapshot');
  if ( Util->findMaster()) {
    print Html->body();
    print "<h1><center>$G->{e_101}";
    return;
  }
  if ( my $deny = Roles->verifyRole($q, "admin")) {
     print Html->body();
     print $deny;
     return;
  }
  my $START = Util->deserialize("snapshot_db");
  $START = {} if (!$START);
  my($TM) = System->get_home() . "/DATA/topo_merge";
  my $WARN;

  my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read;

  my $head = Html->header2("admin.topo.snapshot", "90%");

  my($x) = Util->readHtdocs("topo_snap");
  my $MW = System->get_home() . "/DATA/master_warning";
  my @MWlines;
  if (-f $MW) {
    open(O, $MW); @MWlines = <O> ; close(O);
    $WARN .= "<table border=0 width=90%><tr><td>Warnings: @MWlines</table>";
  }
  unlink ($MW);

  my $TD = System->get_home() . "/DATA/topo/";

  if ($q->{ACTION} eq "Clear") {
     $START->{$q->{host}} = undef;
     Util->serialize("snapshot_db", $START);

  } elsif ($q->{ACTION_merge} ) {
     my ($master, $mlist) = TO->mergeAll();
     if ($master) {
       my $info = &create_master($master,$mlist, $hosts, $TM);
       $WARN .= $info if ($info);
       PDM::ConfigFile->write( $renv, $devs, $hosts, $notifs);
     } else {
        $WARN .= $L->{err_1};
     }


  } elsif ($q->{ACTION_delete}) {
     my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read;
     foreach my $k (keys %$q) {
        next if (substr($k,0,4) ne "del_");
        if ($k eq "del_LOCAL") {
           unlink "$TD/$renv->{hostname}";
           $WARN .= "<font color=red>$renv->{hostname} $L->{err_2}.</font><br>";
        } else {
           my $host = substr($k,4);
           Util::Http->getCommand($host, "DELET&file=topo/$host", 20);

           unlink "$TD/$host";
           $WARN .= "<font color=red>$host $L->{err_2}</font><br>";
        }
     }
     unlink(System->get_home() . "/DATA/tmp/topoindex");
 
  } elsif ($q->{ACTION_create}) {
     my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read;
     my $topo_selected;
     foreach my $k (keys %$q) {
        next if (substr($k,0,4) ne "sel_");
	$topo_selected = 1;
        if ($k eq "sel_LOCAL") {
           my $date1 = Util->get_file_created("$TD/$renv->{hostname}");
           $START->{$renv->{hostname}} = $date1 || '1';
           Util->copyToHistory("topo/$renv->{hostname}","topohist",$renv->{hostname}, $date1, $renv->{topo_history_size});
           Util->copyToHistory("tmp/topoxy_$renv->{hostname}*", "tmphist", "topoxy_$renv->{hostname}", $date1, $renv->{topo_history_size});
           system(System->get_home() . "/bin/sendNewTopo&");
           $WARN .="Discovery started on  $renv->{hostname}<br>";
        } else {
           my ($ipno, $host) = split(/_/, substr($k,4), 2);
           my $date1 = Util->get_file_created("$TD/$host") || '1';
           $START->{$host} = $date1;
           Util->copyToHistory("topo/$host", "topohist", $host, $date1, $renv->{topo_history_size});
           Util->copyToHistory("tmp/topoxy_${host}*", "tmphist", "topoxy_$host", $date1, $renv->{topo_history_size});
           my $ip = Util->name2ip();
           Util::Http->remoteCommand($ipno, "sendNewTopo $ip", 20);
           $WARN .= $L->expand('started',  $host) . "<br>";
        }
     }
     if($topo_selected){
        Util->serialize("snapshot_db", $START);
        $metaflag = 1;
        unlink(System->get_home() . "/DATA/tmp/topoindex");
     }else{
        print Html->warning($L->{no_host_selected});
     }

  }
  my($created) = Util->get_file_created("$TD/$renv->{hostname}");
  my $status;
  my $st = $START->{$renv->{hostname}};
  my $ck = "<input type=checkbox name=sel_LOCAL>";
  my $clear;
  if ($st) {
    if ($created gt $st) {
      my($er1, $std1) = TO->errors($renv->{hostname});
      $status = "<font color=green>$G->{done}</font>";
      $status .= " <font color=red>(Error:$er1)" if ($er1);
    }
    else {
      $status = "<font color=red>$G->{running}</font>";
      $clear = "[ <a href=$Http::WEBPROC?GO=GUI::SAN::snapshot&ACTION=Clear&host=$renv->{hostname}>Clear</a> ]";
      $metaflag = 1;
      $ck = "";
    }
  }

  my $d1 = Util->get_file_created(System->get_home() ."/DATA/topo/MERGE-MASTER");
  my ($c, $err);
  if ($created and !$d1) {
    $c= "<font color=red>";
    $err = $L->{err_3} .  " ";
  } elsif ($created gt $d1) {
    $c= "<font color=red>";
    $err = $L->{err_4} . " ";

  }

  my $comment = GUI->needToPush($hosts);
  $out .=<<EOF;
<script>
function win1(a) {
  var b = '$Http::WEBPROC?GO=GUI::SAN::errors&topo=' + a ;
  var O = window.open(b,'err','menubar=no,resizable=yes,scrollbars=yes,width=400,height=500');
  O.focus();
}
</script>

   $comment
<table border=1 bgcolor=white width=90% cellspacing=0>
<form><input type=hidden name=GO value=GUI::SAN::snapshot>
<tr bgcolor=#666699><td colspan=7><b><font color=white>$L->{label}
<tr bgcolor=#E0E0E0>
    <th width=10%>$L->{select}
    <th>$L->{topo}
    <th>$L->{last}
    <th>$L->{last_m}
    <th>$L->{st}
    <th>$L->{err}
    <th width=10%>$L->{del}
<tr><td><center>&nbsp;$ck
    <td>&nbsp;$renv->{hostname} ($G->{local})
    <td nowrap>&nbsp;$created
    <td nowrap>$c&nbsp;$d1
    <td><b><center>&nbsp;$status
    <td><b><center><a href=javascript:win1('$renv->{hostname}')>$L->{review}</a>
    <td><center>$clear&nbsp;</td>
EOF
  my %DONE;
  $DONE{$renv->{hostname}} = 1;
  
  foreach my $h (@$hosts) {
     $created = Util->get_file_created($TD . $h->{hostname});
     my $st = $START->{$h->{hostname}};
     my($status, $c);
     if ($created gt $h->{last_master_topo}) {
        $err .= $L->expand('err_5', $h->{hostname}) . " ";
        $c = "<font color=red>";
     }
         
     $clear = undef;
     my $sel = "$h->{ipno}_$h->{hostname}";
     $ck = "<input type=checkbox name=sel_$sel>";
     #print "created=$created, start=$st<br>";
     if ($st) {
        if ($created gt $st) {
           my($er1, $std1) = TO->errors($h->{hostname});
           $status = "<font color=green>$L->{done}</font>";
           $status .= " <font color=red>(Error:$er1)" if ($er1);
        } else {
           $status = "<font color=red>$L->{running}</font>";
           $clear = "[ <a href=$Http::WEBPROC?GO=GUI::SAN::snapshot&ACTION=Clear&host=$h->{hostname}>$L->{clear}</a> ]";
           $ck = ""; $metaflag = 1;
        }
     }
     $out .= "
     <tr><td width=10%>&nbsp;<center>$ck</td>
     <td>&nbsp;$h->{hostname}
     <td nowrap>&nbsp;$created
     <td nowrap>$c&nbsp;$h->{last_master_topo}
     <td><b><center>&nbsp;$status
     <td><b><center><a href=javascript:win1('$h->{hostname}')>$L->{review}</a>
     <td><center>$clear &nbsp;
     ";
     $DONE{$h->{hostname}} = 1;
  }
  opendir(O, $TD);
  my @topos = readdir(O); closedir(O);
  my $del;
  foreach my $t (@topos) {
     next if (-d "$TD/$t");
     next if (substr($t,0,1) eq "_");
     next if (substr($t,0,1) eq "." || substr($t,0,6) eq "MERGE-");
     next if ($DONE{$t});
     $created = Util->get_file_created("$TD/$t");
     $del = 1;
     $out .= "<tr>
    <td width=10%><center>&nbsp;</td>
    <td>&nbsp;$t <font color=red>$L->{warn_1}
    <td>&nbsp;$created
    <td>&nbsp;
    <td>&nbsp;
    <td width=10%><center><input type=checkbox name=del_$t></td>
     ";
  }

  $out .= "</table><br>
   <table border=0 cellspacing=0 cellpadding=0 width=90%>
     <tr><td><b>
       <input type=submit name=ACTION_create value=\"$L->{submit_create}\">
     <td valign=top><b>
       <input type=submit name=ACTION_merge value=\"$L->{submit_merge}\">
      ";
  if ($del) {
    $out .= "<td valign=top align=right><b><input type=submit name=ACTION_delete value=\"$L->{submit_delete}\">";
  }
  $out .= "</table></form>";
  print Html->body();

  if ($metaflag) {
    print "\n<meta http-equiv=Refresh content=\"20;URL=$Http::WEBPROC?GO=GUI::SAN::snapshot\">\n";
  }
  print $WARN;
  print $head;
  if ($err) {
    print "<table border=0 cellspacing=0 cellpadding=4 width=90% bgcolor=white>
     <tr><td><font color=red><b>$G->{warning}: $err</table>";
  }
  print $out;

}


sub print_topo {
  my($q) = @_;

  my($to) = TO->readTopo();
  print "<table border=1 width=90% cellspacing=0 cellpadding=4 bgcolor=white><tr><td><pre>";
  print $to->toString();
  print "</table>";
}


sub utilities {
  my($q) = @_;
  my($h);
  if ( my $deny = Roles->verifyRole($q, "expert") ) {
     print $deny;
     return;
  }
  if ($q->{ACTION} =~ /Enter SAN/) {

     print <<EOF;
<frameset cols=140,* border=0>
     <frame src=/fcutil.html name=fctop scrolling=no>
     <frame src=/fcutil_welcome.html name=detail scrolling=auto>
 </frameset>
EOF

     return;
  }
  my($mach);
  $h = Html->header("SAN Utilities", "90%", $mach);
  my($x) = Util->readHtdocs("san_utilities_login");
     
  print "\n<body bgcolor=$main'BGCOLOR><center> $h 
  <table border=1 width=90% cellspacing=0 cellpadding=4 
     bgcolor=white><tr><td>$x</table>";

  print <<EOF;
<form target=_parent><input type=hidden name=GO value=GUI::SAN::utilities>
  <table border=0><tr><td>
  <b><input type=submit name=ACTION value=\"Enter SAN Utilties\">
  </table>
EOF

}

# name:type:ip

sub findSelected {
  my($q) = @_;
  my($RF) =  System->get_home() . "/DATA/tmp/reallist";
  my(@A, @S, @T, $l, @a);

  open(O, $RF);
  while ($l = <O>) {
      chop($l);
      @a = split(/:/, $l);
      if ($a[1] eq "s") {
        push(@S, "$a[0]:$a[2]");
      } elsif ($a[1] eq "a") {
        push(@A, $a[0]);
      } elsif ($a[1] eq "t") {
        push(@T, $a[2]);
      }
  }
  close(O);
  return (\@A, \@S, \@T);
}




sub real_list {
  my($q) = @_;
  my($F) =  System->get_home() . "/DATA/tmp/reallist";
  print "\n<body bgcolor=#E0E0E0><center>";

  my $mach = Util->select_hosts("GUI::SAN::real_list");
  my $hostname = System->hostname();
  print Html->header("List (on $hostname)", "90%", $mach);
  


  my($x, $name, $l, @a, $cnt, $ck, $type);
  if ($q->{ACTION} eq "Update") {
     open(O,">$F");
     foreach $x (keys %$q) {
       if (substr($x,0,3) eq "ck_") {
          $name = substr($x,3);
          print O "$name\n";
       }
     }
     close(O);
     print "<b>List Updated.</b>";
  }
  my($renv, $dev, $host,$notifs) = PDM::ConfigFile->read;

  print "<center>
 <form>
 <table border=0 bgcolor=white width=95% cellpadding=4><tr><td>
    Check the devices that you want to display in the Graph and Data Section of this page.
 </table>
  <table border=0><tr><td></table>
  <table border=1 cellspacing=0 bgcolor=white width=95%>
   <input type=hidden name=GO value=GUI::SAN::real_list>
   <input type=hidden name=option value=1>
  <tr bgcolor=#666699>
      <th width=1%><center><font color=white>Select
      <th><font color=white>Device
      <th><font color=white>Adddress
      <td> </td>
      <th width=1%><center><font color=white>Select
      <th><font color=white>Device
      <th><font color=white>Adddress
  ";
  my(%DEV);
  open(O, $F);
  while ($l = <O>) {
    chop($l);
    @a = split(/:/, $l);
    $DEV{$a[0]} = 1;
  }
  close(O);
  $cnt= 0;
  my %EX;
  foreach my $d (@$dev) {
     if ($d->{type} eq "switch" || $d->{type} eq "a5k" || $d->{type} eq "t3") {
        next if ($EX{$d->{type} . $d->{name}});
        $EX{$d->{type} . $d->{name}} = 1;
        print "<tr>" if ($cnt % 2 == 0);
        $ck = ($DEV{$d->{name}})? "checked":"";
        $type = substr($d->{type},0,1);
        print "<td><center><input type=checkbox name=\"ck_$d->{name}:$type:$d->{ip}\" $ck>
             <td>" . substr($d->{type},0,2) . "-$d->{name}</td>
             <td>&nbsp;$d->{ip}</td>
             ";
        print "<td>" if ($cnt % 2 == 0);
        $cnt++;
     }
  }
  print "<form></table>";
  print "<b><input type=submit name=ACTION value=Update><br>\n";
}





1;
