#!/usr/bin/perl

my %CONFIG = ( "keep_sd_hourly"       => 48,
               "keep_sd_daily"        => 14,
               "keep_sd_weekly"       => 8,
               "consist_sd_hourly"    => 0,
               "consist_sd_daily"     => 1,
               "consist_sd_weekly"    => 1
             );

# Komandozeile analysieren
my ($schedule,$laufwerk) = @ARGV;

if (!exists $CONFIG{"keep_$schedule"} ||
    !exists $CONFIG{"consist_$schedule"} ||
    scalar @ARGV != 2 ) {
  die("Usage: $0 <schedule> <laufwerk>\n");
}

# 1.) Evtl alte SnapShots l”schen
my ($oldsnap) = reverse &getsnaps($schedule,$laufwerk);
my $keep = $CONFIG{"keep_$schedule"};

if ( ($oldsnap =~ /\.(\d+)/)[0] >= $CONFIG{"keep_$schedule"} ) {
  &delsnap("$schedule.".$CONFIG{"keep_$schedule"},$laufwerk);
}

# 2.) Snapshots rotieren
&rotsnap($schedule,$laufwerk,$CONFIG{"keep_$schedule"}) ||
  die "Can't rotate snapshots\n";

# 3.) Evtl. Laufwerk Applikationsseitig
#     konsistent machen
if ( $CONFIG{"consist_$schedule"} ) {
  print "Make Application consistent.\n";
} else {
  print "No need to make Application consistent.\n";
}

# 4.) Snapshot erzeugen
&dosnap("$schedule.0",$laufwerk) ||
  die("Can't create snap for $laufwerk:\n");

# 5.) Evtl. Laufwerk Applikationsseitig
#     aktivieren
if ( $CONFIG{"consist_$schedule"} ) {
  print "Restart Application.\n";
} else {
  print "No need to restart Application.\n";
}

sub dosnap {
  # ($name,$laufwerk)
  # RETRUN: BOOL

  my($name,$laufwerk) = @_;

  print "Creating Snapshot $name for $laufwerk:\n";

  open(SDCLI,"sdcli snap create -s $name -D $laufwerk |") ||
    die "Can't create snap $name for $laufwerk:\n";

  my $return = 0;

  while ( <SDCLI> ) {
    if ( /The operation completed successfully./ ) {
      $return = 1;
    }
  }

  close(SDCLI);

  return($return);
}

sub snapexists {
  # ($name,$laufwerk)
  # RETURN: BOOL

  my ($name,$laufwerk) = @_;
  my $schedule = $name;
  $schedule =~ s/\.\d+$//;
  my $snap;

  foreach $snap (&getsnaps($schedule,$laufwerk)) {
    if ($name eq $snap) {
      return(1);
    }
  }
  return(0);
}

sub getsnaps {
  # ($schedule,$laufwerk)
  # RETURN: LIST of snaps

  my($schedule,$laufwerk) = @_;
  my(@return) = ();

  open(SDCLI,"sdcli snap list -d $laufwerk |") ||
    die "Can't get snaps for $laufwerk:\n";

  while ( $_ = <SDCLI> ) {
    if ( /^($schedule\.\d+).*snapshot/ ) {
      push(@return,$1);
    }
  }

  close(SDCLI);

  @return = sort { ($a =~ /\.(\d+)/)[0] <=> ($b =~ /\.(\d+)/)[0]
                                        ||
                                 uc($b) cmp uc($a) }
            @return;

  return(@return);
}

sub delsnap {
  # ($oldsnap,$laufwerk)
  # RET: BOOL

  my($oldsnap,$laufwerk) = @_;

  print "Deleting oldest Snapshot $oldsnap for $laufwerk:\n";

  open(SDCLI,"sdcli snap delete -d $laufwerk -s $oldsnap |") ||
    die "Can't delete snap $oldsnap for $laufwerk:\n";

  my $return = 0;

  while ( <SDCLI> ) {
    if ( /The operation completed successfully./ ) {
      $return = 1;
    }
  }

  close(SDCLI);

  return($return);

}

sub rotsnap {
  # ($schedule,$laufwerk,$keep)
  # RET: BOOL

  my($schedule,$laufwerk,$keep) = @_;
  my($i);
  my($return) = 1;

  for ($i=$keep;$i>0;$i--) {   

    if ( snapexists("$schedule.".($i-1),$laufwerk) ) {

    print "Rotating Snapshot $schedule.".($i-1)." to $schedule.$i for $laufwerk:\n";

    open(SDCLI,"sdcli snap rename -d $laufwerk -o $schedule.".($i-1).
                                                  " -n $schedule.$i |") ||
      die "Can't rename snaps for $laufwerk:\n";

    my $tmpreturn = 0;

    while ( <SDCLI> ) {
      if ( /The operation completed successfully./ ) {
        $tmpreturn = 1;
      }
    }

    if ($tmpreturn == 0) {
      $return = 0;
    }

    close(SDCLI);
    }
  }

  return($return);

}

