#!/usr/bin/perl
#
#  $Id: sm_upgrade teetov $
# -----------------------------------------------------------------------------
#  SM_UPGRADE - small tool for clean/migrate 
# -----------------------------------------------------------------------------
#  Author: Alex Titov
#  QA by:
#  Copyright: videoNEXT LLC
# -----------------------------------------------------------------------------
#
# notes:
#   1. command line tool
#
# usage: 
#  sm_upgrade CLEAN   <uuid>
#  sm_upgrade CONVERT <uuid>


use warnings;
use strict;
use Data::Dumper;
use File::Basename qw(dirname);    
use lib dirname(__FILE__).'/../lib';              # find  SM::Config here
use SM::Config ':all';

# CONS ------------------------------------------------------------------------
my $APL=$ENV{APL};
my $SMUPDATE=(split(/\//,$0))[-1];	          # the actual name of the prog
my $SM_VER  =SM_VER;
my $CLEAN   ="sudo $APL/sm/sbin/sm_alien CLEAN   $SM_VER";
my $CONVERT ="sudo $APL/sm/sbin/sm_alien CONVERT $SM_VER";
my $UMOUNT  ="sudo $APL/sm/sbin/sm_umount";       # mount by root operation
my $MIGRATE ="$APL/sm/bin/convert";               # scripts for converting 

# VARS ------------------------------------------------------------------------
my $vol=SM_Wheels(); #configs of active volumes ex: $vol->{$uuid}->{LIMIT_WRITE}
# SUBS ------------------------------------------------------------------------

#print Dumper($vol);


#-----------------------------------------------------------------
# restart_spindle initiates status sequence from begining
# note: workaround since clean and convert are not in state model
#-----------------------------------------------------------------
sub restart_spindle {
  my $uuid=shift;
#  SM_LOG->info("unmounting $uuid");
#  `$UMOUNT $uuid`;
  SM_LOG->info("stopping the spindle $uuid (will be restarted by engine)");
  SM_StopSpindle($uuid);
}

sub clean {
 my $uuid=shift;
 SM_LOG->info("call $CLEAN $uuid");
 SM_info ($uuid,"start cleaning");
 $_=`$CLEAN $uuid`;
 SM_LOG->info("$CLEAN $uuid: $_");
 SM_info ($uuid,"cleaning finishes with $_");
 restart_spindle($uuid) if $? == 0;
}

sub convert {
 my $uuid=shift;
 SM_LOG->info("call $CONVERT $uuid");
 SM_info ($uuid,"prepare for CONVERT");
 $_=`$CONVERT $uuid`;
 SM_LOG->info("$CONVERT $uuid: $_");
 SM_info ($uuid,"prepare for CONVERT finises with $_");
 if(/SUCCESS/) {
 #------------------------------- ACTUAL CONVERT OPERATIONS
 # 
 # 1. if dev{OLD_DEVID} is defined then it will be used in conversion
 #
 # 2. Only present devices will be converted, other will be moved to TO-BE-DELETED
 #
 # 3. volume dirs and store links should be converted as
 # old: /vasm/store/va-2.6.2/101/091103/10.0000->/vasm/<uuid>/va-2.6.2/101/091103/10.0000
 # new: /vasm/store/va-2.6.2/101/091103/10.0000-01->/vasm/<uuid>/va-2.6.2/101/091103/10.0000-01
 # 4. important! attribut OLD_DEVID should only present after conversion and destroed during backup
 my $devs =SM_Devices(); 
 my $dst  ="/vasm/$uuid/$SM_VER";
 my $store="/vasm/store/$SM_VER";
 my $tasks="$dst/TO-BE-CONVERTED";
 opendir(DIR,$tasks) || SM_LOG->logdie("Cannot read dir $tasks");
 my @files = sort grep {/^va-\d\.\d\.\d$/} readdir(DIR);
 close DIR;
 foreach my $oldver (@files) {      # we only supously have one for conversion i.e. oldver=va-2.6.3
   my $update_script="$MIGRATE/$oldver";
   $update_script='' if not -e $update_script; # clean udpate_script name if script does not exist
   foreach my $dev (keys %$devs) {
     my $srcdev=$dev;
     if(defined $devs->{$dev}->{OLD_DEVID} and $devs->{$dev}->{OLD_DEVID} ne '') {
        $srcdev=$devs->{$dev}->{OLD_DEVID}; 
     }
     next if not -d "$tasks/$oldver/$srcdev"; # dev is not present in archive
     SM_LOG->info("$uuid: converting $devs->{$dev}->{OBJID}");
     SM_info ($uuid,"converting $devs->{$dev}->{OBJID}");
     mkdir("$dst/$dev",  0755);
     mkdir("$store/$dev",0755);
     opendir(DAYS,"$tasks/$oldver/$srcdev") || SM_LOG->logdie("Cannot read dir $tasks/$oldver/$srcdev");
     my @days= sort grep {/^\d{6}$/} readdir(DAYS);
     close DAYS;
     foreach my $day (@days) {
       opendir(HOURS,"$tasks/$oldver/$srcdev/$day") || SM_LOG->logdie("Cannot read dir $tasks/$oldver/$srcdev/$day");
       my @hours= sort grep {/^\d\d\.\d{4}/} readdir(HOURS);
       close HOURS;
       mkdir("$dst/$dev/$day",  0755);
       mkdir("$store/$dev/$day",0755);
       foreach my $hour (@hours) {      # 
         my $old_hour=$hour;            # remember the old name of the hour
         $hour="$hour-01" if $hour=~/^\d\d\.\d{4}$/;  # change 12.2356 to 12.2356-01 (prior va-263)
#------------------------------------ version conversion begin ----------------------------------
         if($update_script) {
           my $ret=`$update_script $tasks/$oldver/$srcdev/$day/$old_hour 2>&1`;
           chomp($ret);
           if ($ret eq 'OK') {
             # SM_LOG->info("$uuid: conversion OK for $oldver/$srcdev/$day/$old_hour");
           } else {
              SM_LOG->warn("$uuid: conversion FAILS for $oldver/$srcdev/$day/$old_hour($ret)");
           }
         }
#------------------------------------ version conversion end ------------------------------------
         rename ("$tasks/$oldver/$srcdev/$day/$old_hour","$dst/$dev/$day/$hour");
         symlink("$dst/$dev/$day/$hour","$store/$dev/$day/$hour");
       }
       # at this point day should be empty dir, try to remove it, error does not meter
       rmdir("$tasks/$oldver/$srcdev/$day"); 
     }
     # at this point $dev directory should be empty, try to remove it, error does not meter
     rmdir("$tasks/$oldver/$srcdev");
   }
   # at this point $oldver should be empty, try to remove it or move to-be-removed
   rmdir("$tasks/$oldver") || rename("$tasks/$oldver","$dst/TO-BE-REMOVED");
 }
 SM_LOG->info("$uuid: completing CONVERT");
 SM_info ($uuid,"completing CONVERT");
 rmdir("$tasks") || rename("$tasks","$dst/TO-BE-REMOVED");
 rmdir("$dst/TO-BE-REMOVED") || rename("$dst/TO-BE-REMOVED","$dst/to-be-removed");
 #------------------------------- END    CONVERT OPERATIONS
 restart_spindle($uuid);
 }
}

sub get_task {
 return ('') if not defined $ARGV[0];
 my $task=$ARGV[0];
 return ('') if not $task=~/^(CLEAN|CONVERT)$/;
 return ('') if not defined $ARGV[1];
 my $uuid=$ARGV[1];
 if(not defined $vol->{$uuid}) {
   print "Volume '$uuid' is not found in wheels group\n";
   return ('');
 }
 if($vol->{$uuid}->{ost} ne 'Alien') {
   print "OST='Alien' is expected for volume '$uuid' instead of '$vol->{$uuid}->{ost}' \n";
   return (''); 
 }
 return ($task,$uuid);
}

# MAIN =======================================================================


my ($task,$uuid)=get_task;
if(not $task) {
  print "\n\nUsage:\n\t$SMUPDATE CLEAN <uuid>\n"
       ."\t$SMUPDATE CONVERT <uuid>\n";
  exit 1;
}

exit(  clean($uuid))  if $task eq 'CLEAN';
exit(convert($uuid))  if $task eq 'CONVERT';

