#!/usr/bin/perl -w

use Getopt::Long;
use POSIX "sys_wait_h";
use File::Basename;

#globals
my $session_file;
my %config;
my $rc = 0;
my $pid;

if (init()) {
    exit 1;
}

$rc = start_servers(\%config);
if ($rc) {
    print STDERR "WARNING: failed to start iod on remote node $rc, trying to recover\n";
    
    $rc = recover_from_bad(\%config, $rc);
    exit($rc);
}

if ($config{'MOUNT_FS'} == 1) {
    $rc = do_fs_mount(\%config);
    if ($rc) {
    	print STDERR "WARNING: failed to mount FS on remote node $rc\n";
	exit(-1);
    }
}

exit(0);

sub start_servers{
    my $href = shift;

    my @nodes = ();
    my $rc = 0;

    @nodes = (@{$href->{'IONODES'}}, @{$href->{'MGR'}});
    # quite possibly some or all of the IONODES are also META servers
    @nodes = uniq(sort(@nodes));

    my $binary;
    if ($href->{'COPYBINS'} > 0) {
    	$binary = $href->{'BINDIR'} . "/pvfs2-server";
    } else {
    	$binary = $href->{'SERVER'};
    }
    my $serverconf = $href->{'WORKINGDIR'} . "/fs.conf";
    my $localconf = $href->{'WORKINGDIR'} . "/server.conf";

    # once to make the storage space, then a second time to run the servers

    my $cmd = "%node $binary  -f $serverconf -a %node";
    $rc = do_remote_command($href->{'RCMDPROG'}, 8, 30, $cmd, undef, undef, @nodes);

    $cmd = "%node $binary $serverconf -a %node";
    $rc = do_remote_command($href->{'RCMDPROG'}, 8, 30, $cmd, undef, undef, @nodes);
    return($rc);
}

sub do_fs_mount{
    my $href = shift;

    my @nodes = ();
    my $rc = 0;

    @nodes = @{$href->{'COMPNODES'}};

    my $cmd = "%node mkdir $href->{'MOUNTPOINT'}";
    $rc = do_remote_command($href->{'RCMDPROG_ROOT'}, 8, 30, $cmd, undef, undef, @nodes);

    my $kmod = $href->{'PVFS_KMOD'};
    $cmd = "%node /sbin/insmod $kmod";
    $rc = do_remote_command($href->{'RCMDPROG_ROOT'}, 8, 30, $cmd, undef, undef, @nodes);

    my $pvfs2_client = $href->{'PVFS_CLIENT'};
    $cmd = "%node $pvfs2_client";
    $rc = do_remote_command($href->{'RCMDPROG_ROOT'}, 8, 30, $cmd, undef, undef, @nodes);

    my @metas = @{$href->{'MGR'}};
    # from create_pvfs2tab:
    my $big = $href->{'PROTOCOL'};
    $big =~ y/a-z/A-Z/;
    my $var = "PVFS" . $big . "PORT"; # PVFSGMPORT, PVFSIBPORT, etc

    # mount -t pvfs2 gm://pmeta0:5/pvfs2-fs /mnt/pvfs2
    $cmd = "%node /bin/mount -t pvfs2 " . $href->{'PROTOCOL'} . "://" . $metas[0] . ":" . $href->{$var} . "/pvfs2-fs " . $href->{'MOUNTPOINT'}; 
    $rc = do_remote_command($href->{'RCMDPROG_ROOT'}, 8, 30, $cmd, undef, undef, @nodes);

    return($rc);
} 

sub usage {

    print<<EOF;
Usage: $prog_name [option]
-s -session       session file for PAV to use
-sd -sessiondir   directory containing session file 'pvfs_autosession'
-rsh              remote shell command to use (default 'ssh')
-rcp              remote copy command to use (default 'scp')
-h -help          display this message
EOF
}

sub init {
    GetOptions(\%args,
	       's|session:s',
	       'sd|sessiondir:s',
	       'rsh:s',
	       'rcp:s',
	       'r|root:s',
	       'h|help'
	       );

    $prog_name = $0;
    $pid = $$;

    if ($args{'h'}) {
	usage();
	return(1);
    }

    if ($args{'s'}) {
	$session_file = $args{'s'};
    } elsif ($args{'sd'}) {
	$session_file = $args{'sd'} . "/pvfs_autosession";
    } else {
	usage();
	return(1);
    }

    if (!-f $session_file) {
	print STDERR "ERROR: cannot find session file: $session_file\n";
	return(1);
    }

    %config = ('RCMDPROG' => "ssh",
	       'RCPPROG' => "scp",
	       'PROGROOT' => "./",
	       'COPYBINS' => 0,
	       );

    $config{'PROGROOT'} = $args{'r'} || real_dir($0) || $config{'PROGROOT'};
    my $prog_root = $config{'PROGROOT'};
    require "$prog_root/pav_lib.pl";

    $rc = read_sessionfile($session_file, \%config);
    if ($rc) {
	print STDERR "ERROR: cannot read session file\n";
	return(1);
    }

    $config{'RCMDPROG'} = $args{'rsh'} || $config{'RCMDPROG'};
    $config{'RCPPROG'} = $args{'rcp'} || $config{'RCPPROG'};

    return(0);
}

sub real_dir {
   my ($file, $reldir, $suffix) = fileparse(shift);
   my ($realdir, $envpwd);

   if ($reldir =~ /^\//) {
      $realdir = $reldir;
   } else {
      if (!$ENV{PWD}) {
         chomp($envpwd = `pwd`);
      } else {
         $envpwd = $ENV{PWD};
      }
      $realdir = $envpwd . "/$reldir";
   }
   $realdir .= '/';
   $realdir =~ s#/./#/#g;
   $realdir =~ s#//#/#g;
   return($realdir);
}
