#!/usr/bin/perl -w
#
# vs-init.pl -- view and edit the order in which vservers are started and stopped.
# Copyright (C) 2011 KKoncepts Ltd. - <support@kkoncepts.net>
#
# vs-init.pl is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# vs-init.pl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You can view the full GPL at <http://www.gnu.org/licenses/>.
#

use strict;
$|++;

#Change these if your locations are different
my $binary = '/usr/sbin/vserver';
my $confdir = '/etc/vservers';
my $markfile = 'apps/init/mark';
my $priofile = 'apps/init/startorder';
my $default = 'default';

my %vservers = &readconf;

my @sortedvs = sort {$vservers{$a} <=> $vservers{$b}} keys %vservers;

unless ($ARGV[0]) {
 if (@sortedvs) {
  print "Vservers are started in the following order:\n";
  my $i=1;
  my $need_rewrite=0;
  foreach (@sortedvs) { 
    print qq($i\t$_\n); 
    $need_rewrite=1 if $vservers{$_} != $i;
    $i++; 
  }
  &rewrite(@sortedvs) if $need_rewrite;
 } else {
  print "There are no vservers on this node\n";
 }
}
else {
if ($ARGV[0] eq "ls") {
 if (@sortedvs) {
  my ($host,$prio,$stop);
format STDOUT_TOP =
VSERVER         START   STOP
.
format STDOUT = 
@<<<<<<<<<<<<  @>>>>  @>>>>
$host,          $prio, $stop 
.

  foreach (sort keys %vservers) { 
    $host = $_;
    $prio = $vservers{$_};
    $stop = (scalar @sortedvs) + 1 - $prio;
    write;
  }
 } else {
  print "There are no vservers on this node\n";
 }
}

elsif ($ARGV[0] eq "find") {
  &usage unless $ARGV[1];
  unless ($vservers{$ARGV[1]}) { 
    if (-d "$confdir/$ARGV[1]") { 
      print qq("$ARGV[1]" is a vserver on this host, but it is not configured to start automatically.\n); 
      print qq(Use 'vs-init assign $ARGV[1] X' to assign it to start in position 'X'.\n);
    } else {
      print qq("$ARGV[1]" is not a vserver on this host.\n);
    }
  } else {
    print qq($ARGV[1]\t$vservers{$ARGV[1]} out of ), scalar @sortedvs, "\n";
  }
}

elsif ($ARGV[0] eq "assign") {
  &assign($ARGV[1],$ARGV[2]);
}

elsif ($ARGV[0] eq "remove") {
  &assign($ARGV[1],0);
}

else {&usage;}
}
exit 0;

sub readconf() {
  my @dirs;
  if (opendir DIRS, "$confdir") {
    @dirs =  grep  ! /^\./, readdir DIRS;
    closedir DIRS;
  }

  my %vservers;
  foreach (@dirs) {
    next unless -s "$confdir/$_/$priofile";
    open (IN, "$confdir/$_/$priofile") and do {
      $vservers{$_} = <IN>;
      close IN;
    }
  }
  chomp %vservers;
  return %vservers;
}

sub rewrite() {
  my $i = 1;
  foreach (@_) {
    open (OUT, ">$confdir/$_/$priofile") and do {
      print OUT "$i\n";
      close OUT;
    };
    open (OUT, ">$confdir/$_/$markfile") and do {
      print OUT "$default\n";
      close OUT;
    };
    $i++;
  }
}

sub assign() {
  my ($vsname, $vsprio) = @_;
  die qq(Please specify a vserver to assign a start order\n) unless $vsname;
  die qq("$vsname" is not an existing vserver.\n) unless -d "$confdir/$vsname";
  die qq(Please specify a start order for vserver "$vsname"\n) unless defined($vsprio);
  die qq(Start order must be a number.\n) unless $vsprio =~ /^\d+$/;
  my @tmp = grep ! /^$vsname$/, @sortedvs;
  if ($vsprio) { 
    if ($vsprio > $#tmp+1) { push @tmp, $vsname; }
    else { splice @tmp, $vsprio-1, 0, $vsname; }
  } else {
    unlink "$confdir/$vsname/$priofile" if -e "$confdir/$vsname/$priofile";
    unlink "$confdir/$vsname/$markfile" if -e "$confdir/$vsname/$markfile";
  }
  &rewrite(@tmp);
}
   
sub usage() {
  print qq(USAGE:\n);
  print qq("vs-init.pl" to display start order.\n);
  print qq("vs-init.pl ls" to display start and stop order alphabetically by vserver.\n);
  print qq("vs-init.pl assign VSERVER POSITION" to assign a start order to a vserver.\n);
  print qq("vs-init.pl remove VSERVER" to remove the start order and stop a vserver from starting automatically.\n);
  print qq("vs-init.pl find VSERVER" to display the start order for VSERVER.\n);
  exit 0;
}

