#!/usr/bin/env perl
# generate the image for mic 
# Since the root file system for mic is generated on the host by
# micctrl command, this script only help to generate the /etc/hosts,
# /root/.ssh from the management node to the root file system.

BEGIN
{
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";

use strict;
use File::Path;
use File::Basename;
use File::Copy;
use File::Find;
use Getopt::Long;
Getopt::Long::Configure("bundling");
Getopt::Long::Configure("pass_through");

use FindBin;
use lib "$FindBin::Bin/../imgutils";
use imgutils;
use xCAT::Table;


my $arch;
my $profile;
my $osver;
my $pkglist;
my $srcdir;
my $otherpkglist;
my $rootimg_dir;
my $srcdir_otherpkgs;
my $tempfile;
GetOptions(
   'a=s' => \$arch,
   'p=s' => \$profile,
   'o=s' => \$osver,
   'pkglist=s' => \$pkglist,
   'srcdir=s' => \$srcdir,
   'otherpkglist=s' => \$otherpkglist,
   'otherpkgdir=s' => \$srcdir_otherpkgs,
   'tempfile=s' =>\$tempfile,
);

$rootimg_dir = "$srcdir/overlay/package/";
my @yumdirs;
my $imagename;
if (@ARGV > 0) {
    $imagename=$ARGV[0];
}
unless ($imagename) {
    print "Error: osimage name needs be specified.\n";
    exit 1;
}

sub isyumdir {
   if ($File::Find::name =~ /\/repodata$/) {
      my $location = $File::Find::name;
      $location =~ s/\/repodata$//;
      push @yumdirs,$location;
   }
}

if ($otherpkglist) {

    # get the distroname
    my $oitab = xCAT::Table->new('osimage');
    unless ($oitab) {
        print "Error: Cannot open table osimage.\n";
        return 1;
    }
    # generate the yum configuration file
    
    my $aiddistro;
    my $oient = $oitab->getAttribs({'imagename'=>$imagename}, 'osdistroname');
    if ($oient && $oient->{'osdistroname'}) {
        $aiddistro = $oient->{'osdistroname'};
    }
    
    my $distrotab = xCAT::Table->new('osdistro');
    unless ($distrotab) {
        print "Error: Cannot open table osdistro.\n";
        return 1;
    }
    my $aiddistrodir;
    my $distroent = $distrotab->getAttribs({'osdistroname'=>$aiddistro}, 'dirpaths');
    if ($distroent && $distroent->{'dirpaths'}) {
        $aiddistrodir = $distroent->{'dirpaths'}
    }
    
    my @pkgdirs = split(",", $aiddistrodir); 
    foreach my $dir (@pkgdirs) {
       find(\&isyumdir, <$dir/>);
       if (!grep /$dir/, @yumdirs) {
           print "The repository for $dir should be created before running the genimge. Try to run [createrepo $dir].\n";
       }
    }
    
    my $yumconfig;
    open($yumconfig,">","/tmp/genimage.$$.yum.conf");
    my $repnum=0;
    foreach $srcdir (@yumdirs) {
      print $yumconfig "[$aiddistro-$repnum]\nname=$aiddistro-$repnum\nbaseurl=file://$srcdir\ngpgpcheck=0\n\n";
      $repnum += 1;
    }
    $repnum-=1;
    close($yumconfig);
    mkpath "$rootimg_dir/etc";

    my %extra_hash = imgutils::get_package_names($otherpkglist);
    my %extrapkgnames; 

    my %repohash;
    if (keys(%extra_hash) > 0) {
      open($yumconfig,">>","/tmp/genimage.$$.yum.conf");
      my $index=1;
      my $pass;
      foreach $pass (sort {$a <=> $b} (keys(%extra_hash))) {
        foreach (keys(%{$extra_hash{$pass}})) {

            if($_ eq "INCLUDEBAD")  {
             print "Unable to open the following pkglist files:\n".join("\n",@{$extra_hash{$pass}{INCLUDEBAD}});
               exit 1;
            }

            if (($_ eq "PRE_REMOVE") || ($_ eq "POST_REMOVE") || ($_ eq "ENVLIST")) { next;} 
            print $yumconfig "[otherpkgs$index]\nname=otherpkgs$index\nbaseurl=file://$srcdir_otherpkgs/$_\ngpgpcheck=0\n\n";
            $repohash{$pass}{$index} = 1;
            $index++;
            my $pa=$extra_hash{$pass}{$_};
            $extrapkgnames{$pass} .= " " . join(' ', @$pa);
        }
      }
      close($yumconfig);
      $index--;
      my $yumcmd_base = "yum -y -c /tmp/genimage.$$.yum.conf --installroot=$rootimg_dir/ --disablerepo=* ";
      foreach (0..$repnum) {
          $yumcmd_base .= "--enablerepo=$aiddistro-$_ ";
      }

      foreach $pass (sort {$a <=> $b} (keys(%extra_hash))) {
          my $yumcmd = $yumcmd_base;
          foreach my $repo_index ( keys %{$repohash{$pass}} ) {
              $yumcmd .= "--enablerepo=otherpkgs$repo_index ";
          }

          system("$yumcmd clean all");

          my $envlist;
          if(exists($extra_hash{$pass}{ENVLIST})){
              $envlist = join(' ', @{$extra_hash{$pass}{ENVLIST}});
          }
          # remove the packages that are specified in the otherpkgs.list files with leading '-'
          my $yumcmd_remove= "$yumcmd erase ";
          if (exists ($extra_hash{$pass}{'PRE_REMOVE'})) {
              my $pa=$extra_hash{$pass}{'PRE_REMOVE'};
              my $rm_packges= join(' ', @$pa);
              if ($rm_packges) {
                  print "$envlist $yumcmd_remove $rm_packges\n";
                  my $rc = system("$envlist $yumcmd_remove $rm_packges");
                  if ($rc) {
                      print "yum invocation failed\n";
                      exit 1;
                  }
              }
          }

          # install extra packages
          $yumcmd .= "install ";
          # append extra pkg names to yum command 
          if ($extrapkgnames{$pass}) {
              $yumcmd .= " $extrapkgnames{$pass} ";
	      $yumcmd =~ s/ $/\n/;
	      
	      print "$envlist $yumcmd\n"; 
	      my $rc = system("$envlist $yumcmd");
	      if ($rc) { 
		  print "yum invocation failed\n";
		  exit 1;
	      }
          } else {
	      print "No Packages marked for install\n";
          }
	
          # remove the packages that are specified in the otherpkgs.list files with leading '--'
          if (exists ($extra_hash{$pass}{'POST_REMOVE'})) {
              my $pa=$extra_hash{$pass}{'POST_REMOVE'};
              my $rm_packges= join(' ', @$pa);
              if ($rm_packges) {
                  print "$envlist $yumcmd_remove $rm_packges\n";
                  my $rc = system("$envlist $yumcmd_remove $rm_packges");
                  if ($rc) {
                      print "yum invocation failed\n";
                      exit 1;
                  }
              }
          }
      }
    }
}




my $fsdir = "$srcdir/";
my $systemdir = "$fsdir/system";
mkpath ($systemdir);

# this is the file list which includes the files which should be copied 
# from MN to the root file system
my @sysfilelist = (
  "/etc/hosts", 
  "/etc/group", 
  "/etc/passwd", 
  "/etc/shadow",
  "/etc/resolv.conf", 
  "/etc/nsswitch.conf",
  "/etc/ssh/ssh_host_rsa_key",
  "/etc/ssh/ssh_config",
  "/etc/ssh/ssh_host_key",
  "/etc/ssh/sshd_config",
  "/etc/ssh/ssh_host_dsa_key",
  "/etc/ssh/ssh_host_key.pub",
  "/root/.ssh/id_rsa",
  "/root/.ssh/id_rsa.pub",
  "/root/.ssh/authorized_keys",);

# do the copy
foreach my $file (@sysfilelist) {
    my $dirname = dirname("$systemdir/$file");
    unless (-d $dirname) {
        mkpath ($dirname);
    }
    copy ($file, "$systemdir/$file");
}


# Create emtpy common dir and common.filelist for later using
mkpath ("$fsdir/common");
system ("touch $fsdir/common.filelist");

print "Genimage for mic has been done.\n";

1;