package Service::Upgrade;
use Inventory;
use PPRO;
use Util;
use strict;
use Html;
use Process;
use Html::Flow;
use Labels;
use LockManager;

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

}

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

}


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

  print Html->body();
  print Html->header2("service.service.rev_fix");
  my $LB = Labels->read("Service::Upgrade");

 print <<EOF;
<br><table border=1 cellspacing=0 cellpadding=3 width=$Style::WIDTH bgcolor=white>
   <tr><td colspan=2 bgcolor=$Style::DARK><b><font color=white>&nbsp;$LB->{revisionMenu}
   <tr><td align=right width=50%>
         <a href=$Http::WEBPROC?GO=Service::Upgrade::fix1>$LB->{patchInstallLabel}</a></td>
        <td>$LB->{patchInstallDesc}</td>
   <tr><td align=right width=50%>
         <a href=$Http::WEBPROC?GO=Service::Upgrade::fix4>$LB->{patchUnInstallLabel}</a></td>
        <td>$LB->{patchUnInstallDesc}</td>
</table>
EOF

}

sub reportMenu {

  my($q) = @_;
  print Html->body();
  print Html->header2("service.service.rev_report");
  my $LB = Labels->read("Service::Upgrade");

  print <<EOF;
<br><table border=1 cellspacing=0 cellpadding=3 width=$Style::WIDTH bgcolor=white>
   <tr><td colspan=2 bgcolor=$Style::DARK><b><font color=white>&nbsp;$LB->{revisionReportMenu}
   <tr><td align=right width=50%>
         <a href=$Http::WEBPROC?GO=Service::Upgrade::report>$LB->{report3}</a></td>
        <td>$LB->{patchInstallReportDesc}</td>
   <tr><td align=right width=50%>
         <a href=$Http::WEBPROC?GO=Service::Upgrade::reportDown>$LB->{downreport3}</a></td>
        <td>$LB->{patchUnInstallReportDesc}</td>
</table>
EOF

}

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

print Html->body();
print Html->header2("service.service.rev_hist");
my $LB = Labels->read("Service::Upgrade");
print <<EOF;
<br><table border=1 cellspacing=0 cellpadding=3 width=$Style::WIDTH bgcolor=white>
   <tr><td colspan=2 bgcolor=$Style::DARK><b><font color=white>&nbsp;$LB->{revisionHistMenu}
   <tr><td align=right width=50%>
         <a href=$Http::WEBPROC?GO=GUI::Process::history&ID=Upgrade>$LB->{patchInstallHistLabel}</a></td>
        <td>$LB->{patchInstallHistLabelDesc}</td>
   <tr><td align=right width=50%>
         <a href=$Http::WEBPROC?GO=GUI::Process::history&ID=Downgrade>$LB->{patchUnInstallHistLabel}</a></td>
        <td>$LB->{patchUnInstallHistLabelDesc}</td>
</table>
EOF

}

sub fix1 {
  my($q) = @_;
  my $SID;
  my $info;
  my $killLabel;
  print Html->body();
  my $D = System->get_home() . "/DATA/tmp";
  my $LB = Labels->read("Service::Upgrade");
  my $just_started;
  if ($q->{kill}) {
    my ($status, $pid1) = Process->status(undef, $q->{kill});
    if ($pid1 && $pid1 =~ /^\d+$/) {
      Util->killPID($pid1);
      unlink "$D/$q->{kill}";
      unlink "$D/$q->{kill}_pid";
      my $debug = "Killed $q->{kill} ($pid1).";

      my $lock  = LockManager->new();
      my $locki = $lock->exists("system", 1) || {};
      my $date  = Util->get_today();
      my ($err_cnt, $REPORT);

      if ($locki->{info}) {
        # LOG to SUNWstade/log/cron_patch.log
        $debug .= " Upgrade process killed at $date. Releasing system reservation: $locki->{info}\n";
        $lock->unlock("system");
        $err_cnt++; $REPORT = {};
      } 
      $killLabel = Html->info($debug);

    } else {
      $killLabel = Html->warning("Cannot kill $q->{kill} (no PID)");
    }

  } elsif ($q->{ACTION_clear}) {
    unlink "$D/Upgrade";
    unlink "$D/Upgrade_pid";
    unlink "$D/Upgrade.log";
    unlink "$D/Patchlist";
    unlink "$D/Patchlist_pid";

  } elsif ($q->{ACTION_generate}) {
    $SID = "storade";
    my $command =  System->get_home() . "/bin/ras_patchlist -S $SID -b";
    system($command);
    sleep(1);
    $info = Html->info("Started $command");
    $just_started = 1;

  } elsif ($q->{ACTION_apply}) {
    &fix2($q);
    return;
  }
  my ($status, $pid1) = Process->status(undef, "Patchlist");
  my ($ins_status, $pid2) = Process->status(undef, "Upgrade");
  my ($kill1, $kill2);
  if ($pid1 && $status =~ /Running/) {
     $kill1 = "[ <a href=javascript:winKill('$Http::WEBPROC?GO=Service::Upgrade::fix1&kill=Patchlist')>$LB->{kill}</a> ]";
  }
  if ($pid2 && $ins_status =~ /Running/) {   
     $kill2 = "<a href=javascript:winKill('$Http::WEBPROC?GO=Service::Upgrade::fix1&kill=Upgrade')>$LB->{kill}</a> | ";
  }
  if ("$status $ins_status" =~ /Running/ || $just_started) {
    print "<meta http-equiv=Refresh content=\"30;URL=$Http::WEBPROC?GO=Service::Upgrade::fix1\">";
  }
  print Html->header2("service.service.rev_fix");
  my $lock = LockManager->new();
  my $locki = $lock->exists("system") || {};
  if ($locki->{pid}) {
    my ($app, $key0, $desc, $start, $mins, $ip, $name) = split(/\|/, $locki->{info});
    my $hours = int($mins / 60);
    print Html->warning($LB->expand(warn1 => $name, $start, $hours, $desc));
  }

  print $killLabel;
  #print $info;

  my ($b1);
  my $rep = Process->read(undef, "Patchlist");
  my ($out, $apply, $create, $clear);
  my $apply;
  if ($ins_status !~ /Running/) {
    if ($status !~ /Running/) {
      $create = Html::Screen->submitButton("ACTION_generate", $LB->{create});
      $clear  = Html::Screen->submitButton("ACTION_clear",   $LB->{clear});
    }
    if ($rep && $status =~ /Done/) {
      $apply = "&nbsp;"; # "<input type=submit name=ACTION_apply value=\"$LB->{select}\">";
    }
  }
  my($renv2, $devs) = PDM::ConfigFile->read();
  my %K;
  foreach my $d (@$devs) {
    $K{$d->{key}} = $d->{name};
  }
  my @L = `/usr/bin/grep \"volOper'\" /opt/SUNWstade/DATA/OLD_REPORTS/6*`;
  my $report;
  foreach my $l (@L) {
     my $l = substr($l,37);
     if ($l =~ /(.*):\s+'volume\.(u\d+vol\d+)\.volOper' => '(\w+)'/) {
        my $key = $1;
        my $vol = $2;
        my $st  = $3;
        if ($st ne "" && $st ne "OK") {
           $report .= "&nbsp;&nbsp;&nbsp; $K{$key} ($vol): $st<br>";
        }
     }
  }
  #print Html->warning("$LB->{volverify}<br>$report") if ($report);

  $status = localize_status($status);
  $ins_status = localize_status($ins_status);

  print <<EOF;
<br><div align=left><a href=$Http::WEBPROC?GO=Service::Upgrade::fix>$LB->{revisionMenu}</a>->
$LB->{patchInstallLabel}</div><br>
EOF

  print Html::Flow->display([
      [ $LB->{report1},  'Service::Upgrade::fix1',    1, 1 ],
      [ $LB->{report2},  'Service::Upgrade::fix2',   0, $apply ],
      [ $LB->{report3},  'Service::Upgrade::fix3',   0, $apply ]
        ], {width => $Style::WIDTH});

  print <<EOF;
&nbsp;
 <script>
  function win1(t) {
     var b = '$Http::WEBPROC?GO=Service::Upgrade::upgrade_log';
     var O = window.open(b,'log','menubar=no,resizable=yes,scrollbars=yes,width=500,height=600');
      O.focus();
  }
 
  function winKill(t) {
     if (confirm('Are you sure you want to kill the process ?')) {
       parent.location.href=t;
     }
  }
 </script>

 <table border=1 cellspacing=0 cellpadding=3 width=$Style::WIDTH bgcolor=white>
   <tr><td colspan=3 bgcolor=$Style::DARK><b><font color=white>&nbsp;$LB->{summ}
   <tr><td align=right bgcolor=$Style::LIGHT width=40%><form>
         <input type=hidden name=GO value=Service::Upgrade::fix1>
         <input type=hidden name=SID value=storade>
         $LB->{patch_status}:</td>
       <td>&nbsp;$status</td><td><center>&nbsp;$kill1</td>
   <tr><td align=right bgcolor=$Style::LIGHT width=30%>
         $LB->{patch_ins}:</td>
       <td>&nbsp;$ins_status</td><td><center>[&nbsp;$kill2
       <a href=javascript:win1() $Http::WEBPROC?GO=Service::Upgrade::upgrade_log>$LB->{log}</a> ]
           </td>
 </table>
 <table border=0><tr><td></table>
 <table border=0 width=$Style::WIDTH>
  <tr><td><b>$create &nbsp; $apply &nbsp; $clear
  </td>
  <td align=right>
  </table>
  </form>
EOF

}

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

  my $LB = Labels->read("Service::Upgrade");

  print Html->body(undef, {color => "white", extra => "onload=window.scroll(0,100000)" } );
  print "<meta http-equiv=Refresh content=\"10;URL=$Http::WEBPROC?GO=Service::Upgrade::upgrade_log\"></center>";
  print "<table border=0 cellspacing=0 width=100% bgcolor=$Style::DARK>
     <tr><td><b><font color=white>$LB->{rev}</table><pre>";

  open(O, System->get_home() . "/DATA/tmp/Upgrade.log");
  my($l);
  while ($l = <O>) {
     $l =~ s/</&lt;/g;
     print $l;
  }
  close(O);
}

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

  my $LB = Labels->read("Service::Upgrade");

  print Html->body(undef, {color => "white", extra => "onload=window.scroll(0,100000)" } );
  print "<meta http-equiv=Refresh content=\"10;URL=$Http::WEBPROC?GO=Service::Upgrade::downgrade_log\"></center>";
  print "<table border=0 cellspacing=0 width=100% bgcolor=$Style::DARK>
     <tr><td><b><font color=white>$LB->{downrev}</table><pre>";

  open(O, System->get_home() . "/DATA/tmp/Downgrade.log");
  my($l);
  while ($l = <O>) {
     $l =~ s/</&lt;/g;
     print $l;
  }
  close(O);
}


##################################
# GENERATE PATCHES
##################################
#

sub fix2 {
  my($q) = @_;
  print Html->body();
  print Html->header2("service.service.rev_fix");

  my $LB = Labels->read("Service::Upgrade");

  my $cli  = PPRO->cli_path();
  my $renv = System->get_renv();
  my $TO   = $renv->{"ppro.timeout"} || 30;
  my ($SID, $XML_FILE);
  my $Config = PDM::ConfigFile->read();

  print <<EOF;
<br><div align=left><a href=$Http::WEBPROC?GO=Service::Upgrade::fix>$LB->{revisionMenu}</a>->
$LB->{patchInstallLabel}</div><br>
EOF

  print Html::Flow->display([
      [ $LB->{report1},  'Service::Upgrade::fix1',    0, 1 ],
      [ $LB->{report2},  'Service::Upgrade::fix2',   1, 0 ],
      [ $LB->{report3},  'Service::Upgrade::fix3',     0, 0 ],
        ], {width => $Style::WIDTH});

  my $rep = Process->read(undef, "Patchlist");
  my $ppro = PPRO->parse($rep->{data}{report});
  if ($PPRO::ERROR) {
     print Html->warning("PPRO::parse XML Error</b>: $PPRO::ERROR");
     return;
  }

  if ($ppro->{ERRORS}) {
     print Html->warning("</b> $ppro->{ERRORS}");
     return; 
  }

  my $inv = Inventory->readInventory();
  my %IP;  # map devices by ipno
  foreach my $d (@{$inv->getDevices()}) {
     $IP{$d->{ipno}} = $d;
  }

  print <<EOF;
<table border=1 cellspacing=0 cellpadding=1 width=$Style::WIDTH bgcolor=white>
  <tr><td colspan=6 bgcolor=$Style::DARK><form>
       <input type=hidden name=GO value=Service::Upgrade::fix3>
       <input type=hidden name=SID value=$SID>
       <font color=white><b>$LB->{apply}</td>
  <tr bgcolor=$Style::LIGHT>
      <th>$LB->{dev}</th>
      <th>$LB->{dev2}</th>
      <th>$LB->{ip}</th>
      <th width=1%>$LB->{patch}</th>
      <th width=2%>$LB->{id}</th>
      <th>Info</th>
EOF
   my @GIF = ("al_ok.gif", "al_alert.gif", "al_crit.gif", "al_down.gif");
   my $State = State->getComponentState(0);

   foreach my $pp (@{$ppro->devices()}) {
      my $inv_d = $IP{$pp->key()};
      my $ip   = $pp->key();
      my $name = $inv_d->{name};
      my $type = lc($pp->type());
      my $dev  = $Config->deviceByIP($ip);
      my ($label, $k, $sev, $info);
      $sev = 0;
      if ($type eq "sunos") {
        $label = $LB->{sp};
        $k     = "sp:" . System->hostid();
      } elsif ($dev) {
        $label = "$dev->{type}: $dev->{name}";
        $k     = "$dev->{type}:$dev->{key}";
      } elsif ($name) {
        $label = "$type:$name";
      } else {
        $label = "$type:<font color=red>UNKNOWN</font>";
      }
      if (exists $State->{$k}) {
        $sev  = int($State->{$k}[0] + 0.5);
        $info = "<br><font color=red><center><small>$LB->{review}</small></center></font><br>";
      }

      my $P = $pp->patches();
      my $pcnt = $#$P +1;
      my $sel  = "<input type=checkbox name=\"sel_$ip\">" if ($pcnt > 0);
      my $t2 = $LB->{patches};
      print "\n<tr><td ><center>$sel&nbsp;<td><center><b>$label</td>
             <td ><center><b>$ip <a href=\"$Http::WEBPROC?GO=GUI::Instr::rStart&Roption=2&file=$k&host=$renv->{hostname}\">
	     <img src=/gif/$GIF[$sev] $LB->{review} border=0></a><td colspan=3>$info<center><b>$pcnt</b> $t2 &nbsp;</td>";
      my $cnt = 0;
      foreach my $patch (@$P) {
         my $pid = $patch->{patchID};
         my $syn = $patch->{synopsis};
         #my $err = $pp->error($patch->{error});
	 my $err = $patch->{error};

         my $frus;
         foreach my $fru (@{$patch->frus()}) {
	    my $fruname = "$fru->{locator}";
	    if ($fru->{class}) {
	       $fruname .= "($fru->{class})"; 
	    }

            $frus .= "$fruname, ";
         }
         if ($frus) {
            chop($frus); chop($frus);
         }
         #my $err2 = "<br><font color=red>$err->{message}" . ": " . $err->{remedy} . "</font>" if ($err->{message});
	 my $err2 = "<br><font color=red>$err</font>" if ($err);
         if ($dev->{type} =~ /6[01]20/) {
            print "<tr><td colspan=3></td>
             <td width=1%><center><input type=checkbox name=\"patch_$ip#$pid\">";
         } else {
            print "<tr><td colspan=4></td>";
         }
         print "<td width=2%>&nbsp;$pid</td>";
         my $t1 = $syn;
         $t1 .= " " if ($syn && $err2);
         $t1 .= $err2;
         $t1 .= "<br>" if (length($t1) > 1 && $frus);
         $t1 .= "<b>Frus:</b> $frus" if ($frus);
         $t1 .= "&nbsp;";
         print "<td>$t1</td>"; #<tr><td colspan=5></td>";
         $cnt++;
      }
      print "\n<tr><td></td><td></td><td></td><tr><td></td>";
   }
   print "</table>&nbsp;<br><b>" .
     Html::Screen->submitButton("ACTION_selected", $LB->{submit_sel},
                 undef, { confirm => $LB->{confirm_sel} }) . " &nbsp; " .
     Html::Screen->submitButton("ACTION_all", $LB->{submit_all} , undef,
                        { confirm => $LB->{confirm_all} }) .
               " &nbsp; </form>";

}
#  <tr><td colspan=5><center>
#    <table border=0 cellspacing=0>
#      <tr><td align=right>Run Mode:</td><td><select name=mode><option value=S>Serial<option value=P>Parallel</select></table></td>



##################################
# PATCH INSTALLATION STATUS
##################################
#
sub fix3 {
  my($q) = @_;
  print Html->body();

  my $LB = Labels->read("Service::Upgrade");
  my $meta= "<meta http-equiv=Refresh content=\"30;URL=$Http::WEBPROC?GO=Service::Upgrade::fix3\">";


  my $cli  = PPRO->cli_path();
  my $renv = System->get_renv();
  my $TO   = $renv->{"ppro.timeout"} || 30;
  my ($SID, $XML_FILE, $info);
  my $Config = PDM::ConfigFile->read();

  if ($q->{ACTION_all} || $q->{ACTION_selected}) {
    $SID         =  "storade";
    my $rep = Process->read(undef, "Patchlist");
    my $ppro = PPRO->parse($rep->{data}{report});

    if ($PPRO::ERROR) {
       print Html->warning("PPRO::parse XML Error</b>: $PPRO::ERROR");
       return;
    }

    if ($ppro->{ERRORS}) {
       print Html->warning("</b> $ppro->{ERRORS}");
       return; 
    }

    my $list;
    if ($q->{ACTION_all} ) {
      $list = "_ALL_";
      #foreach my $pp (@{$ppro->devices()}) {
      #  $list .= $pp->key() . ":";
      #}
    } else {
      my (%DEV, $err);
      foreach my $el (keys %$q) {
         if (substr($el,0,4) eq "sel_") {
            my $k = substr($el,4);
            $list .= "$k:";
            $DEV{substr($el,4)} = 1;
         }
      }
      foreach my $el (keys %$q) {
         if (substr($el,0,6) eq "patch_") {
            my($ip0, $patch0) = split(/\#/, substr($el,6));
            if (!$DEV{$ip0}) {
               $list .= substr($el,6) . ":";
            } else {
               $err .= $LB->expand(ignore => $patch0, $ip0);
            }
         }
      }
      $info .= Html->warning($err) if ($err);
    }
    chop($list) if ($list);
    if (!$list) {
       $info .= Html->warning($LB->{select_one});
    } else {
      print $meta;
      my $command =  System->get_home() . "/bin/ras_upgrade -m S -S $SID -i \"$list\" -b";
      system($command);
      sleep(1);
      #$info .= Html->info("\$LB->{taskStarted}\" $command");
    }
  }

  my $ins_status = Process->status(undef, "Upgrade");
  print $meta if ( $ins_status =~ /Running/);

  print Html->header2("service.service.rev_fix");
  print $info;

  print <<EOF;
<br><div align=left><a href=$Http::WEBPROC?GO=Service::Upgrade::fix>$LB->{revisionMenu}</a>->
$LB->{patchInstallLabel}</div><br>
EOF

  print Html::Flow->display([
      [ $LB->{report1},  'Service::Upgrade::fix1',    0, 1 ],
      [ $LB->{report2},  'Service::Upgrade::fix2',   0, 0 ],
      [ $LB->{report3},  'Service::Upgrade::fix3',   1, 1 ],
        ], {width => $Style::WIDTH});

  my ($b1);
  my $rep = Process->read(undef, "Upgrade");
  my ($out);

  if ($ins_status =~ /Done/) {
    print "<table border=0><tr><td></table>";
    &report({TITLE=> $LB->{patch_status2} } );

  } else {
    print <<EOF;
 <script>
  function win1(t) {
     var b = '$Http::WEBPROC?GO=Service::Upgrade::upgrade_log';
     var O = window.open(b,'log','menubar=no,resizable=yes,scrollbars=yes,width=500,height=600');
      O.focus();
  }

  function winKill(t) {
     if (confirm('Are you sure you want to kill the process ?')) {
       parent.location.href=t;
     }
  }
 </script>
&nbsp;
 <table border=1 cellspacing=0 cellpadding=3 width=$Style::WIDTH bgcolor=white>
   <tr><td colspan=3 bgcolor=$Style::DARK><b><font color=white>&nbsp;Patch Installation
   <tr><td align=right bgcolor=$Style::LIGHT width=30%>
         $LB->{patch_status}</td>
       <td>&nbsp;$ins_status</td>
       <td><center> [ <a href=javascript:win1() $Http::WEBPROC?GO=Service::Upgrade::upgrade_log>$LB->{log}</a> ]
 </table>
 <table border=0><tr><td></table>
EOF
  }
}




sub report {
  my($q) = @_;
  my $renv = System->get_renv();

  my $LB = Labels->read("Service::Upgrade");

  my $ID = "Upgrade";
  print Html->body();
  if (!$q->{TITLE}) {
    print Html->header2($q->{hist}?"service.service.rev_hist":"service.service.rev_report", undef, $q->{hist}?"$ID: Historical":"",undef , {noDoc=>1});
  }

  my $l;
  if ($q->{ACTION_hist}) {
     my $RF =  System->get_home() . "/DATA/tmp/Upgrade";
     my $date1 = Util->get_file_created($RF);
     $date1 =~ s/ /_/g;
     open(R, $RF);
     my $w = $renv->{hostname} . ".$date1";
     print Html->info("Copying $w to $ID history");
     open(W, ">" . System->get_home() . "/DATA/${ID}_history/$w");
     while ($l = <R>) {
#        $l =~ s/\.+/.../;
        print W $l;
     }
     close(R); close(W);
     unlink $RF;
     
  }
  my $RF;
  my $submitHistoryButton;

  if ($q->{hist}) {
    $RF =  System->get_home() . "/DATA/Upgrade_history/$q->{hist}";
    $submitHistoryButton = "";
  } else {
    $RF =  System->get_home() . "/DATA/tmp/Upgrade";
    $submitHistoryButton = Html::Screen->submitButton("ACTION_hist", $LB->{submit_move});
  }
  if (!open(O, $RF)) {
     print Html->warning($LB->{no_upgrade});
     return;
  }
  my($l,$report, $VAR1);
  while ($l = <O>) {
#     $l =~ s/\.+/.../;
     $report .= $l;
  }
  close(O);

  eval $report;
  my $run_date = $VAR1->{date};
  my $data     = $VAR1->{data};
  my $err      = $VAR1->{error_cnt};
  my $trace    = $data->{trace};
  $trace =~ s/\n/<br>\n/g;
  my $ppro     = $data->{report};

  $err = 0 if (!$err);
    
  my $inv = Inventory->readInventory();
  if (!$inv) {
    print Html->warning("No Inventory available!");
    return;
  }

  if ($trace =~ /Conflict, system already reserved/) {
    print Html->warning($trace);
    return;
  }

  my %IP;  # map devices by ipno
  foreach my $d (@{$inv->getDevices()}) {
     $IP{$d->{ipno}} = $d;
  }
  my $model = $inv->{model};
    
  # Display top level errors.
  if ($ppro->{ERRORS}) {
    print Html->warning("$ppro->{ERRORS}\n");
  }  
  print <<EOF;
<table border=1 cellspacing=0 cellpadding=1 width=$Style::WIDTH bgcolor=white>
<tr><td colspan=2 bgcolor=$Style::DARK><b><font color=white>&nbsp;$q->{TITLE} SE $model</td>
<tr><td align=right bgcolor=$Style::LIGHT>$LB->{date}:</td><td>&nbsp;$run_date</td>
<tr><td align=right bgcolor=$Style::LIGHT>$LB->{err}:</td><td>&nbsp;$err</td>
<tr><td colspan=2>$trace</td>
</table>
<table border=1 cellspacing=0 cellpadding=1 width=$Style::WIDTH bgcolor=white>
  <tr><td colspan=5 bgcolor=$Style::DARK>
  <tr bgcolor=$Style::LIGHT>
      <th>$LB->{dev2}</th><th>$LB->{ip2}</th><th>$LB->{id}</th><th>$LB->{info}</th>
EOF
   foreach my $pp (@{$ppro->devices()}) {
      my $inv_d = $IP{$pp->key()};
      my $ip   = $pp->key();
      my $name = $inv_d->{name};
      my $type = lc($pp->type());
      my $P = $pp->patches();

      my $devicelabel;

      if ($type eq "sunos") {
        $devicelabel = $LB->{sp};
      } elsif ($name) { 
        if ($type eq "t4pp") {
	    $type =  $LB->{T4};
	}
        $devicelabel = "$type:$name";
      } else {
        $devicelabel = "$type:<font color=red>UNKNOWN</font>";
      }


      print "\n<tr><td valign=top><center><b>$devicelabel</td><td valign=top><center><b>$ip
        <td colspan=2><center><b>" . ($#$P +1) . "</b> patch(es)";

      my $cnt = 0;
      foreach my $patch (@$P) {
         my $pid = $patch->{patchID};			 
         my $syn = $patch->{synopsis};
         #my $err = $pp->error($patch->{error});
	 my $err = $patch->{error};

         my $frus;
         foreach my $fru (@{$patch->frus()}) {
   	    my $fruname = "$fru->{locator}";
	    if ($fru->{class}) {
	       $fruname .= "($fru->{class})"; 
	    }

            $frus .= "$fruname, ";
         }
         if ($frus) {
            chop($frus); chop($frus);
         }
         #my $err2 = "<br><font color=red>$err->{message}" . ": " . $err->{remedy} . "</font>" if ($err->{message});
	 my $err2 = "<br><font color=red>$err</font>" if ($err);

         print "<tr><td colspan=2><td valign=top>&nbsp;$pid<td>$syn $err2";
         print "<br><b>Frus:</b> $frus" if ($frus);
         print "</td><tr><td colspan=4></td>";
         $cnt++;
      }
      print "\n<tr><td></td><td></td><td></td>";
   }
   
   print "</table><form><input type=hidden name=GO value=Service::Upgrade::report><b>".
	   $submitHistoryButton .
   " </form>";

}

sub reportDown {
  my($q) = @_;
  my $renv = System->get_renv();

  my $LB = Labels->read("Service::Upgrade");
  my $ID = "Downgrade";

  print Html->body();
  if (!$q->{TITLE}) {
    print Html->header2($q->{hist}?"service.service.rev_hist":"service.service.rev_report", undef, $q->{hist}?"$ID: Historical":"",undef , {noDoc=>1});
  }

  my $l;
  if ($q->{ACTION_downhist}) {
     my $RF =  System->get_home() . "/DATA/tmp/Downgrade";
     my $date1 = Util->get_file_created($RF);
     $date1 =~ s/ /_/g;
     open(R, $RF);
     my $w = $renv->{hostname} . ".$date1";
     print Html->info("Copying $w to $ID history");
     open(W, ">" . System->get_home() . "/DATA/${ID}_history/$w");
     while ($l = <R>) {
#        $l =~ s/\.+/.../;
        print W $l;
     }
     close(R); close(W);
     unlink $RF;
  }

  my $RF;
  my $submitHistoryButton;
  if ($q->{hist}) {
    $RF =  System->get_home() . "/DATA/Downgrade_history/$q->{hist}";
    $submitHistoryButton = "";
  } else {
    $RF =  System->get_home() . "/DATA/tmp/Downgrade";
    $submitHistoryButton = Html::Screen->submitButton("ACTION_downhist", $LB->{submit_move});
  }
  if (!open(O, $RF)) {
     print Html->warning($LB->{no_downgrade});
     return;
  }
  my($l,$report, $VAR1);
  while ($l = <O>) {
#     $l =~ s/\.+/.../;
     $report .= $l;
  }
  close(O);

  eval $report;
  my $run_date = $VAR1->{date};
  my $data     = $VAR1->{data};
  my $err      = $VAR1->{error_cnt};
  my $trace    = $data->{trace};
  $trace =~ s/\n/<br>\n/g;
  my $ppro     = $data->{report};

  $err = 0 if (!$err);

  my $inv = Inventory->readInventory();
  if (!$inv) {
    print Html->warning("No Inventory available!");
    return;
  }

  if ($trace =~ /Conflict, system already reserved/) {
    print Html->warning($trace);
    return;
  }

  my %IP;  # map devices by ipno
  foreach my $d (@{$inv->getDevices()}) {
     $IP{$d->{ipno}} = $d;
  }
  my $model = $inv->{model};

  # Display top level errors.
  if ($ppro->{ERRORS}) {
    print Html->warning("$ppro->{ERRORS}\n");
  }  
  print <<EOF;
<table border=1 cellspacing=0 cellpadding=1 width=$Style::WIDTH bgcolor=white>
<tr><td colspan=2 bgcolor=$Style::DARK><b><font color=white>&nbsp;$q->{TITLE} SE $model</td>
<tr><td align=right bgcolor=$Style::LIGHT>$LB->{date}:</td><td>&nbsp;$run_date</td>
<tr><td align=right bgcolor=$Style::LIGHT>$LB->{err}:</td><td>&nbsp;$err</td>
<tr><td colspan=2>$trace</td>
</table>
<table border=1 cellspacing=0 cellpadding=1 width=$Style::WIDTH bgcolor=white>
  <tr><td colspan=5 bgcolor=$Style::DARK>
  <tr bgcolor=$Style::LIGHT>
      <th>$LB->{dev2}</th><th>$LB->{ip2}</th><th>$LB->{id}</th><th>$LB->{info}</th>
EOF
   foreach my $pp (@{$ppro->devices()}) {
      my $inv_d = $IP{$pp->key()};
      my $ip   = $pp->key();
      my $name = $inv_d->{name};
      my $type = lc($pp->type());
      my $P = $pp->patches();

      my $devicelabel;

      if ($type eq "sunos") {
        $devicelabel = $LB->{sp};
      } elsif ($name) {
        if ($type eq "t4pp") {
	    $type =  $LB->{T4};
	}
        $devicelabel = "$type:$name";
      } else {
        $devicelabel = "$type:<font color=red>UNKNOWN</font>";
      }


      print "\n<tr><td valign=top><center><b>$devicelabel</td><td valign=top><center><b>$ip
        <td colspan=2><center><b>" . ($#$P +1) . "</b> patch(es)";

      my $cnt = 0;
      foreach my $patch (@$P) {
         my $pid = $patch->{patchID};
         my $syn = $patch->{synopsis};
         #my $err = $pp->error($patch->{error});
	 my $err = $patch->{error};
         my $frus;
         foreach my $fru (@{$patch->frus()}) {
            my $fruname = "$fru->{locator}";
	    if ($fru->{class}) {
	       $fruname .= "($fru->{class})"; 
	    }

            $frus .= "$fruname, ";

         }
         if ($frus) {
            chop($frus); chop($frus);
         }
         #my $err2 = "<br><font color=red>$err->{message}" . ": " . $err->{remedy} . "</font>" if ($err->{message});
	 my $err2 = "<br><font color=red>$err</font>" if ($err);
         print "<tr><td colspan=2><td valign=top>&nbsp;$pid<td>$syn $err2";
         print "<br><b>Frus:</b> $frus" if ($frus);
         print "</td><tr><td colspan=4></td>";
         $cnt++;
      }
      print "\n<tr><td></td><td></td><td></td>";
   }
   print "</table><form><input type=hidden name=GO value=Service::Upgrade::reportDown><b>".
     $submitHistoryButton .
    " </form>";

}

##################################
# PATCH DOWNREV create
##################################
#
sub fix4 {

  my($q) = @_;
  my $SID;
  my $info;
  my $killLabel;
  print Html->body();
  my $D = System->get_home() . "/DATA/tmp";
  my $LB = Labels->read("Service::Upgrade");
  my $just_started;
  if ($q->{kill}) {
    my ($status, $pid1) = Process->status(undef, $q->{kill});
    if ($pid1 && $pid1 =~ /^\d+$/ ) {
      Util->killPID($pid1);
      unlink "$D/$q->{kill}";
      unlink "$D/$q->{kill}_pid";

      my $debug = "Killed $q->{kill} ($pid1).";
  
      my $lock  = LockManager->new();
      my $locki = $lock->exists("system", 1) || {};
      my $date  = Util->get_today();
      my ($err_cnt, $REPORT);

      if ($locki->{info}) {
        # LOG to SUNWstade/log/cron_patch.log
        $debug .= " Patch Backout process killed at $date. Releasing system reservation: $locki->{info}\n";
        $lock->unlock("system");
        $err_cnt++; $REPORT = {};
      } 
      $killLabel = Html->info($debug);

    } else {
      $killLabel = Html->warning("Cannot kill $q->{kill} (no PID)");
    }

  } elsif ($q->{ACTION_downclear}) {
    unlink "$D/Downgrade";
    unlink "$D/Downgrade_pid";
    unlink "$D/Downgrade.log";
    unlink "$D/Patchdowngrade";
    unlink "$D/Patchdowngrade_pid";

  } elsif ($q->{ACTION_downgenerate}) {
    $SID = "storade";
    my $command =  System->get_home() . "/bin/ras_patchdowngrade -S $SID -u -b";
    system($command);
    sleep(1);
    $info = Html->info("Started $command");
    $just_started = 1;

  }elsif ($q->{ACTION_downapply}) {
    &fix5($q);
    return;
  }

  my ($status, $pid1) = Process->status(undef, "Patchdowngrade");
  my ($ins_status, $pid2) = Process->status(undef, "Downgrade");
  my ($kill1, $kill2);
  if ($pid1 && $status =~ /Running/) {
     $kill1 = "[ <a href=javascript:winKill('$Http::WEBPROC?GO=Service::Upgrade::fix4&kill=Patchdowngrade')>$LB->{kill}</a> ]";
  }
  if ($pid2 && $ins_status =~ /Running/) {
     $kill2 = "<a href=javascript:winKill('$Http::WEBPROC?GO=Service::Upgrade::fix4&kill=Downgrade')>$LB->{kill}</a> | ";
  }
  if ("$status $ins_status" =~ /Running/ || $just_started) {
    print "<meta http-equiv=Refresh content=\"30;URL=$Http::WEBPROC?GO=Service::Upgrade::fix4\">";
  }

  print Html->header2("service.service.rev_fix");
  my $lock = LockManager->new();
  my $locki = $lock->exists("system") || {};
  if ($locki->{pid}) {
    my ($app, $key0, $desc, $start, $mins, $ip, $name) = split(/\|/, $locki->{info});
    my $hours = int($mins / 60);
    print Html->warning($LB->expand(warn1 => $name, $start, $hours, $desc));
  }

  print $killLabel;
  #print $info;

  my ($b1);
  my $rep = Process->read(undef, "Patchdowngrade");
  my ($out, $apply, $create, $clear);
  my $apply;
  if ($ins_status !~ /Running/) {
    if ($status !~ /Running/) {
      $create = Html::Screen->submitButton("ACTION_downgenerate", $LB->{downcreate});
      $clear  = Html::Screen->submitButton("ACTION_downclear",   $LB->{downclear});
    }
    if ($rep && $status =~ /Done/) {
      $apply = "&nbsp;"; # "<input type=submit name=ACTION_downapply value=\"$LB->{select}\">";
    }
  }
  my($renv2, $devs) = PDM::ConfigFile->read();
  my %K;
  foreach my $d (@$devs) {
    $K{$d->{key}} = $d->{name};
  }
  my @L = `/usr/bin/grep \"volOper'\" /opt/SUNWstade/DATA/OLD_REPORTS/6*`;
  my $report;
  foreach my $l (@L) {
     my $l = substr($l,37);
     if ($l =~ /(.*):\s+'volume\.(u\d+vol\d+)\.volOper' => '(\w+)'/) {
        my $key = $1;
        my $vol = $2;
        my $st  = $3;
        if ($st ne "" && $st ne "OK") {
           $report .= "&nbsp;&nbsp;&nbsp; $K{$key} ($vol): $st<br>";
        }
     }
  }
  #print Html->warning("$LB->{downvolverify}<br>$report") if ($report);

  $status = localize_status($status);
  $ins_status = localize_status($ins_status);

  print <<EOF;
  <br><div align=left><a href=$Http::WEBPROC?GO=Service::Upgrade::fix>$LB->{revisionMenu}</a>->
$LB->{patchUnInstallLabel}</div><br>
EOF

  print Html::Flow->display([
      [ $LB->{downreport1},  'Service::Upgrade::fix4',    1, 1 ],
      [ $LB->{downreport2},  'Service::Upgrade::fix5',   0, $apply ],
       [ $LB->{downreport3},  'Service::Upgrade::fix6',   0, $apply ]
        ], {width => $Style::WIDTH});

  print <<EOF;
&nbsp;
 <script>
  function win1(t) {
     var b = '$Http::WEBPROC?GO=Service::Upgrade::downgrade_log';
     var O = window.open(b,'log','menubar=no,resizable=yes,scrollbars=yes,width=500,height=600');
      O.focus();
  }

  function winKill(t) {
     if (confirm('Are you sure you want to kill the process ?')) {
       parent.location.href=t;
     }
  }
 </script>

 <table border=1 cellspacing=0 cellpadding=3 width=$Style::WIDTH bgcolor=white>
   <tr><td colspan=3 bgcolor=$Style::DARK><b><font color=white>&nbsp;$LB->{summ}
   <tr><td align=right bgcolor=$Style::LIGHT width=40%><form>
         <input type=hidden name=GO value=Service::Upgrade::fix4>
         <input type=hidden name=SID value=storade>
         $LB->{patch_downstatus}:</td>
       <td>&nbsp;$status</td><td><center>&nbsp;$kill1</td>
   <tr><td align=right bgcolor=$Style::LIGHT width=30%>
         $LB->{patch_downreport}:</td>
       <td>&nbsp;$ins_status</td><td><center>[&nbsp;$kill2
       <a href=javascript:win1() $Http::WEBPROC?GO=Service::Upgrade::downgrade_log>$LB->{log}</a> ]
           </td>
 </table>
 <table border=0><tr><td></table>
 <table border=0 width=$Style::WIDTH>
  <tr><td><b>$create &nbsp; $apply &nbsp; $clear
  </td>
  <td align=right>

  </table>
  </form>
EOF
}

##################################
# PATCH DOWNREV List
##################################
#
sub fix5 {

  my($q) = @_;

  my $cnt = 0;

  print Html->body();
  print Html->header2("service.service.rev_fix");

  my $LB = Labels->read("Service::Upgrade");

  my $cli  = PPRO->cli_path();
  my $renv = System->get_renv();
  my $TO   = $renv->{"ppro.timeout"} || 30;
  my ($SID, $XML_FILE);
  my $Config = PDM::ConfigFile->read();

  print <<EOF;
  <br><div align=left><a href=$Http::WEBPROC?GO=Service::Upgrade::fix>$LB->{revisionMenu}</a>->
$LB->{patchUnInstallLabel}</div><br>
EOF

  print Html::Flow->display([
      [ $LB->{downreport1},  'Service::Upgrade::fix4',    0, 1 ],
      [ $LB->{downreport2},  'Service::Upgrade::fix5',   1, 0 ],
       [ $LB->{downreport3},  'Service::Upgrade::fix6',   0, 0 ]
        ], {width => $Style::WIDTH});

  my $rep = Process->read(undef, "Patchdowngrade");
  my $ppro = PPRO->parse($rep->{data}{report});
  
  if ($PPRO::ERROR) {
     print Html->warning("PPRO::parse XML Error</b>: $PPRO::ERROR");
     return;
  }

  if ($ppro->{ERRORS}) {
     print Html->warning("</b> $ppro->{ERRORS}");
     return; 
  }

  my $inv = Inventory->readInventory();
  my %IP;  # map devices by ipno
  foreach my $d (@{$inv->getDevices()}) {
     $IP{$d->{ipno}} = $d;
  }

  print <<EOF;
<table border=1 cellspacing=0 cellpadding=1 width=$Style::WIDTH bgcolor=white>
  <tr><td colspan=6 bgcolor=$Style::DARK><form>
       <input type=hidden name=GO value=Service::Upgrade::fix6>
       <input type=hidden name=SID value=$SID>
       <font color=white><b>$LB->{downapply}</td>
  <tr bgcolor=$Style::LIGHT>
      <th>$LB->{dev}</th>
      <th>$LB->{dev2}</th>
      <th>$LB->{ip}</th>
      <th width=1%>$LB->{patch}</th>
      <th width=2%>$LB->{id}</th>
      <th>Info</th>
EOF

   my @GIF = ("al_ok.gif", "al_alert.gif", "al_crit.gif", "al_down.gif");
   my $State = State->getComponentState(0);

   my $patchcount;

   foreach my $pp (@{$ppro->devices()}) {
      my $inv_d = $IP{$pp->key()};
      my $ip   = $pp->key();
      my $name = $inv_d->{name};
      my $type = lc($pp->type());
      my $dev  = $Config->deviceByIP($ip);
      my ($label, $k, $sev, $info);
      $sev = 0;
      if ($type eq "sunos") {
        $label = $LB->{sp};
        $k     = "sp:" . System->hostid();
      } elsif ($dev) {
        $label = "$dev->{type}: $dev->{name}";
        $k     = "$dev->{type}:$dev->{key}";
      } elsif ($name) {
        $label = "$type:$name";
      } else {
        $label = "$type:<font color=red>UNKNOWN</font>";
      }
      if (exists $State->{$k}) {
        $sev  = int($State->{$k}[0] + 0.5);
        $info = "<br><font color=red><center><small>$LB->{review}</small></center></font><br>";
      }

      my $P = $pp->patches();
      my $pcnt = $#$P +1;
      $patchcount = $pcnt;
      #my $sel  = "<input type=checkbox name=\"sel_$ip\">" if ($pcnt > 0);
      my $t2 = $LB->{patches};
      print "\n<tr><td ><center><td><center><b>$label</td>
             <td ><center><b>$ip <a href=\"$Http::WEBPROC?GO=GUI::Instr::rStart&Roption=2&file=$k&host=$renv->{hostname}\">
	     <img src=/gif/$GIF[$sev] $LB->{review} border=0></a><td colspan=3>$info<center><b>$pcnt</b> $t2 &nbsp;</td>";
      
      foreach my $patch (@$P) {
         my $pid = $patch->{patchID};
         my $syn = $patch->{synopsis};
         #my $err = $pp->error($patch->{error});
	 my $err = $patch->{error};
         my $frus;
         foreach my $fru (@{$patch->frus()}) {
            my $fruname = "$fru->{locator}";
	    if ($fru->{class}) {
	       $fruname .= "($fru->{class})"; 
	    }

            $frus .= "$fruname, ";
         }
         if ($frus) {
            chop($frus); chop($frus);
         }
         #my $err2 = "<br><font color=red>$err->{message}" . ": " . $err->{remedy} . "</font>" if ($err->{message});
	 my $err2 = "<br><font color=red>$err</font>" if ($err);
         if ($dev->{type} =~ /6[01]20/) {
            print "<tr><td colspan=3></td>
             <td width=1%><center><input type=checkbox name=\"patch_$ip#$pid\">";
         } else {
            print "<tr><td colspan=4></td>";
         }
         print "<td width=2%>&nbsp;$pid</td>";
         my $t1 = $syn;
         $t1 .= " " if ($syn && $err2);
         $t1 .= $err2;
         $t1 .= "<br>" if (length($t1) > 1 && $frus);
         $t1 .= "<b>Frus:</b> $frus" if ($frus);
         $t1 .= "&nbsp;";
         print "<td>$t1</td>"; #<tr><td colspan=5></td>";
         $cnt++;
      }
      print "\n<tr><td></td><td></td><td></td><tr><td></td>";
   }

   if ($cnt > 0) {
     print "</table>&nbsp;<br><b>" .
       Html::Screen->submitButton("ACTION_downgradeapply", $LB->{submit_downrev} , undef,
                        { confirm => $LB->{confirm_download} }) .
               " &nbsp; </form>";
   } else  {
       print "</table>&nbsp;<br><b>";
       print Html->warning("No patches found to downgrade!");
       print "&nbsp;</form>";
   }
}

##################################
# PATCH DOWNREV REPORT
##################################
#
sub fix6 {

   my($q) = @_;
   print Html->body();
   my $LB = Labels->read("Service::Upgrade");
   my $meta= "<meta http-equiv=Refresh content=\"30;URL=$Http::WEBPROC?GO=Service::Upgrade::fix6\">";

   my $cli  = PPRO->cli_path();
   my $renv = System->get_renv();
   my $TO   = $renv->{"ppro.timeout"} || 30;
   my ($SID, $XML_FILE, $info);
   my $Config = PDM::ConfigFile->read();

   if ($q->{ACTION_downgradeapply}) {
     $SID         =  "storade";

     my $rep = Process->read(undef, "Patchdowngrade");
     my $ppro = PPRO->parse($rep->{data}{report});

     if ($PPRO::ERROR) {
        print Html->warning("PPRO::parse XML Error</b>: $PPRO::ERROR");
        return;
     }

     if ($ppro->{ERRORS}) {
        print Html->warning("</b> $ppro->{ERRORS}");
        return; 
     }

     print $meta;
     my $command =  System->get_home() . "/bin/ras_downgrade -S $SID -U -b";
     system($command);
     sleep(1);
     #$info .= Html->info("Started $command");
  }

  my $ins_status = Process->status(undef, "Downgrade");
  print $meta if ( $ins_status =~ /Running/);

  print Html->header2("service.service.rev_fix");
  print $info;

  print <<EOF;
  <br><div align=left><a href=$Http::WEBPROC?GO=Service::Upgrade::fix>$LB->{revisionMenu}</a>->
$LB->{patchUnInstallLabel}</div><br>
EOF

  print Html::Flow->display([
      [ $LB->{downreport1},  'Service::Upgrade::fix4',    0, 1 ],
      [ $LB->{downreport2},  'Service::Upgrade::fix5',   0, 0 ],
       [ $LB->{downreport3},  'Service::Upgrade::fix6',   1, 1 ]
        ], {width => $Style::WIDTH});

  my ($b1);
  my $rep = Process->read(undef, "Downgrade");
  my ($out);

  if ($ins_status =~ /Done/) {
    print "<table border=0><tr><td></table>";
    &reportDown({TITLE=> $LB->{patch_status3} } );

  } else {
    print <<EOF;
 <script>
  function win1(t) {
     var b = '$Http::WEBPROC?GO=Service::Upgrade::downgrade_log';
     var O = window.open(b,'log','menubar=no,resizable=yes,scrollbars=yes,width=500,height=600');
      O.focus();
  }
 </script>
&nbsp;
 <table border=1 cellspacing=0 cellpadding=3 width=$Style::WIDTH bgcolor=white>
   <tr><td colspan=3 bgcolor=$Style::DARK><b><font color=white>&nbsp;$LB->{patchUnInstallLabel}
   <tr><td align=right bgcolor=$Style::LIGHT width=30%>
         $LB->{patch_downstatus}</td>
       <td>&nbsp;$ins_status</td>
       <td><center> [ <a href=javascript:win1() $Http::WEBPROC?GO=Service::Upgrade::downgrade_log>$LB->{log}</a> ]
 </table>
 <table border=0><tr><td></table>
EOF
  }
}

sub localize_status {
   my ($toLocalize) = @_;
   my $translatedStatus;
   my $LB = Labels->read("Service::Upgrade");

   if ($toLocalize eq "Running") {
       $translatedStatus = $LB->{taskRunning};
     } elsif ($toLocalize eq "Not running") {
       $translatedStatus = $LB->{taskNotRunning};
     } elsif ($toLocalize eq "Died") {
       $translatedStatus = $LB->{taskDied};
     } elsif ($toLocalize eq "Started") {
       $translatedStatus = $LB->{taskStarted};
     } elsif ($toLocalize =~ /^Done/) {
       $translatedStatus = $LB->{taskDone} . substr($toLocalize,4);
    }

   return($translatedStatus);
}

1;
