#!/usr/bin/perl
# Script for creating a skel that contains the infrastructure
# for all virtual servers (RedHat GNU/Linux version).
# Copyright (c) 1999, 2000 Idaya Ltd.
#
# This file is part of the Virtual Server Administrator (FreeVSD)
#
# FreeVSD 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 2, or (at your option)
# any later version.
#
# FreeVSD 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 should have received a copy of the GNU General Public License
# along with FreeVSD; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

# command syntax:
#   vsd-genskel.pl <mnt point>
#
#   mntpoint - mount point of the disk to contain virtual servers
#
#  Will create a skel on every partition defined in vsd.conf, unless a directory is
#  given on the command line

use Sys::Hostname;
use IO::File;
use File::Copy;
use File::Find;
use VSD;
use VSD::Config;
use Getopt::Long;

# use strict; # FIX not yet, cause of freevsd.conf

# Some useful constants
my $DEBUG = 0;
my $VERSION_NUMBER = "1.4.10";
my $APPNAM = ($0 =~ m/\/([0-9A-Za-z_.-]+)$/g)[-1];

# FIXME: Obtain the hostname of the localhost, so we can use vsdadm, BAD.
my $hstserver = `hostname`;

my $vsdconf = VSD::Config->new( file => $path{vsdconf} );

my @skel_name = '';
my @partition_args = ();
my @partitions = ();
my $help = 0;
my $version = 0;

my $return_value = &GetOptions ( "skelname:s" => \$skel_name,
                                  "partition:s" => \@partition_args,
                                  "help" => \$help,
                                  "version" => \$version
                                );

if (@ARGV != 0 || $return_value == 0)
  {
    usage ();
    exit;
  }

# check for help, print help and exit:
if ($help)
  {
    usage ();
    exit 0;
  }

# check for version, print and exit:
if ($version)
  {
    version ();
    exit 0;
  }

foreach (@partition_args)
  {
    push (@partitions, split (',', $_));
  }

if (! @partitions)
  {
    my %configured_partitions = $vsdconf->getval ('Partition');
    @partitions = keys %configured_partitions;
  }

print "\nGenerating skel on partition[s]: @partitions\n\n";


#print "\n  Please enter a name for this skel [default]: ";
#my $skel_name = <>;
#chomp $skel_name;
$skel_name eq '' && ($skel_name = 'skel');

# FIX when more than one partition ... move code down into loop..?
#print "\n  Would you like this skel to be the default skel";
#print "\n   that virtual servers are linked to? [Y]: ";
#my $default_skel = ( (<>) =~ /n/i ) ? '' : $skel_name ;



my $skels_created = 0;

foreach my $partition (@partitions){
    my $mntpoint, $skelroot;

    # $partition can be a path, if obtained from the command line,
    #  or a name, if read from vsd.conf...
    if ( @paths ) {
	$mntpoint = $partition;
	defined ($partition = mntpoint_configured ( $mntpoint )) || do {
	    print "\n    There is currently no partition configured";
	    print "\n     at $mntpoint. Do you want to create this";
	    print "\n     and register it with VSD ? [N]: ";
	    # FIX functionality not available yet...
	    print "\n\n    THIS FUNCTIONALITY WILL BE AVAILABLE SOON\n";
	    next
	};
    }
    else {
        defined ($mntpoint = $vsdconf->getval ('Partition', "$partition", 'Mount')) || do {
	    print "$APPNAM: error: could not obtain the mountpoint for partition $partition";
	    next };
    }

    if (!-d "$mntpoint") {
	`/bin/mkdir $mntpoint`;
    }
	
    if (!-d "$mntpoint/skel") {
	`/bin/mkdir $mntpoint/skel`;
    }
	
    $skelroot = "$mntpoint/skel/$skel_name";
	
    if (-d $skelroot) {
      print "-- old skel found, removing $mntpoint/skel/$skel_name ...\n";
      `rm -rf $skelroot/*`
    } else {
	mkdir "$skelroot", 0755;
    }
	
   # FIX do this someotherhow so that can use strict...
    do "$path{freevsdconf}";

    # Create the skel repository.  Copy lots of files from the server
    # system disk.
    print "-- creating skel, $skelroot\n";
    # Create top-level directory structure
    foreach $dir ("bin", "dev", "etc", "home", "lib", "proc", "tmp",
    	      "usr", "sbin") {
        mkdir ("$skelroot/$dir", 0755);
    }

    print "-- merging /bin programs\n";
    foreach $file (@bin_progs) {
        `cp -a /bin/$file $skelroot/bin/$file`;
    }

    print "-- merging /sbin programs\n";
    foreach $file (@sbin_progs) {
        `cp -a /sbin/$file $skelroot/sbin/$file`;
    }

    print "-- merging /lib\n";
    `cp -a /lib $skelroot/`;

    print "-- merging /usr\n";
    `cp -a /usr $skelroot/`;
    `rm -r -f $skelroot/usr/local`;

    print "-- merging /usr/sbin programs\n";
    `rm -r -f $skelroot/usr/sbin`;
    mkdir ("$skelroot/usr/sbin", 0755);
    foreach $file (@usr_sbin_progs) {
        `cp -a /usr/sbin/$file $skelroot/usr/sbin/$file`;
    }
    # FIXME BAD HACK. Do this somewhere else.
    `chmod 04755 $skelroot/usr/sbin/atd`;
    `chmod 04755 $skelroot/usr/sbin/crond`;
    if (-l "$skelroot/usr/info/dir") {
      unlink ("$skelroot/usr/info/dir");
      `cp /etc/info-dir $skelroot/usr/info/dir`;
    }

    print "-- merging /usr/libexec programs\n";
    `rm -r -f $skelroot/usr/libexec`;
    mkdir ("$skelroot/usr/libexec", 0755);
    foreach $file (@usr_libexec_progs) {
        `cp -a /usr/libexec/$file $skelroot/usr/libexec/$file`;
    }

    print "-- merging skel repositories\n";
    if (! defined ($os_skelrepo)) {
      die "/etc/freevsd.conf requires a os_skelrepo definition";
    }
    if (-d "$os_skelrepo") {
        $skelsrc = $os_skelrepo;
        find \&skelcopy, $os_skelrepo;
    } else {
        die "$os_skelrepo does not exist";
    }

    # If --enable-addons was set in the FreeVSD build then
    # we will install all the RPMs from the specified directory
    # into the skel.
    if (defined ($add_ons)) {
        print "-- installing third party rpms\n";
        die "add_ons gives a non-directory" if (! -d "$add_ons");
        @rpms = glob ("$add_ons/*.rpm");
        # Create temporary var directory for rpm to do its business
        mkdir ("$skelroot/var", 0755);
        mkdir ("$skelroot/var/lib", 0755);
        mkdir ("$skelroot/var/tmp", 0755);
        `cp -a /var/lib/rpm $skelroot/var/lib`;
        system ("rpm","-ivh", "--force", "--root=$skelroot", @rpms); 
        # Clean up.
        `rm -rf $skelroot/var`;
    }

    print "-- deleting extra files\n";
    foreach $file (@delete_progs) {
        system ("rm -r -f $skelroot/$file");
    }

    # Do site specific skel installation
    if (defined ($site_skel_install)) {
      if (-x "$site_skel_install") {
          do "$site_skel_install";
      }
    }

    # Add info to vsd.conf...
    # FIXME: setval is replaced by call to vsdadm, BADDD, need a better way for this
    # $vsdconf->setval ( 'Partition', $partition, 'Skel', $skel_name );
    # system ("$sbindir/vsdadm", "part_skeladd", "$hstserver", "$skel_name");

    $skels_created++;
}


#$default_skel && $skels_created && do {
#    # FIXME: setval is replaced by call to vsdadm, BADDD, need a better way for this
#    #$vsdconf->setval ('Global', 'Skel', "$default_skel");
#    system ("$sbindir/vsdadm", "part_setskelglobal", "$skelname");

#    print "\n\n  Default skel is set to $default_skel\n";
#};


print "\n\n...finished.\n\n";






sub skelcopy {
    my ($temp, $temp1, $mode);
    $temp = $File::Find::name;
    $mode = ((stat ("$temp"))[2]) & 07777;
    ($temp1 = $temp) =~ s/$skelsrc\///;
    if (-d $temp && $temp !~ /CVS/) {
        mkdir ("$skelroot/$temp1", 0755);
    } elsif ($temp !~ /CVS/) {
	`cp -a $temp $skelroot/$temp1`;
	chown 0, 0, "$skelroot/$temp1";
	chmod $mode, "$skelroot/$temp1";
    }
}



sub mntpoint_configured {
    my $mount = shift;
    my %configured_partitions = $vsdconf->getval( 'Partition' );
    foreach ( keys %configured_partitions ) {
	my $conf_mount = $vsdconf->getval( 'Partition', $_ , 'Mount');
	$mount =~ /^$conf_mount\/?$/ and return $_;
    }
    return undef;
}



sub confirmy {
  $_ = <>;
  return 1 if (/^n.*/i);
  return 0;
}

sub confirmn {
    $_ = <>;
    return 1 if (/^y.*/i);
    return 0;
}

sub version {
  print "$APPNAM (freeVSD) $VERSION_NUMBER\n\n";
  print "VSD - Virtual Server Daemon\n";
  print "Copyright (c) 2000 - 2001 Idaya Ltd.\n\n";
  print "VSD is free software; you can redistribute it and/or\n";
  print "modify it under the terms of the GNU General Public License\n";
  print "as published by the Free Software Foundation; either \n";
  print "version 2 of the license, or (at your option) any later version.\n\n";
}

sub usage {
  print "Usage: $APPNAM [OPTION]... \n";
  print "freeVSD skel generation.\n\n";
  print "  -s, --skelname=SKEL      specify the name of the skel (default: 'skel')\n";
  print "  -p, --partition=P1,P2    specify the partitions on which to generate a skel\n";
  print "                           [partition number (default: all configured)]\n";
  print "      --help               output this help and exit\n";
  print "      --version            output version information and exit\n\n";
}
