#!/usr/bin/perl

use strict;
use warnings;

our $VERSION = 3.1;

=head1 NAME

restore_config - 

=head1 DESCRIPTION

TBD

=cut

use Data::Dumper;
use Config::General;
use File::Find;
use File::Compare;
use Params::Validate qw(:all);
use Archive::Tar;
use File::Temp qw(tempfile);
use File::Path qw(mkpath);

use FindBin qw($RealBin);

use lib "$RealBin/../lib";

use perfSONAR_PS::NPToolkit::BackingStore::Config qw(parse_config);
use perfSONAR_PS::NPToolkit::BackingStore::Utils  qw(load_live_device mount_data_store);

my $CONF_FILE = "$RealBin/../etc/backingstore.conf";
my $CONF_DIRECTORY = "$RealBin/../etc/backingstore.conf.d";

my $data_store_location;
my $data_store_device;
my $data_store_version;
my $original_cd_location;

my ($status, $res);

($status, $res) = parse_config({ base_config_file => $CONF_FILE, config_directory => $CONF_DIRECTORY });
if ($status != 0) {
    print "Problem parsing configuration: $res";
    exit -1;
}

my $conf = $res;

($status, $res) = load_live_device();
if ($status != 0) {
    print "Problem loading original CD: $res";
    exit -1;
}

$original_cd_location = $res->{directory};

($status, $res) = mount_data_store();
if ($status != 0) {
    print "Couldn't find data store: $res";
    exit -1;
}

$data_store_location = $res->{directory};
$data_store_device   = $res->{device};
$data_store_version  = $res->{version};
$data_store_version  = "" unless ($data_store_version);

# Run any pre-restore scripts 
if ($conf->{restore_pre_run}) {
    $conf->{restore_pre_run} = [ $conf->{restore_pre_run} ] unless (ref $conf->{restore_pre_run});

    foreach my $pattern (@{ $conf->{restore_pre_run} }) {
        my @scripts = glob($pattern);

        foreach my $script (@scripts) {
            my @cmd = ();

            push @cmd, $script;
            push @cmd, ("-v", $data_store_version);
            push @cmd, ("-s", $data_store_location);
            push @cmd, ("-c", $original_cd_location);

            my $status = system(@cmd);
            if ($status != 0) {
                my $exit_value  = $? >> 8;
                my $signal_num  = $? & 127;
                my $dumped_core = $? & 128;

                print "Problem executing: ".join(",", @cmd).": ".$exit_value."\n";
            }
        }
    }
}

# bind mount the given directories on the backing store over the original. If
# the directory already exists on the ISO, copy its contents over. If not, just
# make the directory.
if ($conf->{store}) {
    $conf->{store} = [ $conf->{store} ] unless (ref $conf->{store});

    foreach my $directory (@{ $conf->{store} }) {
        if (-d $data_store_location."/NPTools/".$directory) {
            # do nothing since the directory already exists
        }
        elsif (-d $original_cd_location."/".$directory) {
            my ($fh, $filename) = tempfile;

            close(*$fh);

            $Archive::Tar::DEBUG = 1;

            # Tar up the directory from the original location
            chdir($original_cd_location);
            my @file_list = ();
            find({ wanted => sub { push @file_list, $File::Find::name }, no_chdir => 1 }, ".".$directory);
            Archive::Tar->create_archive($filename, "", @file_list);

            # Untar is under the new location
            #chdir($data_store_location."/NPTools");

            # XXX: Archive::Tar isn't preserving ownership of directories when
            # it untars so we have to use the tar command manually.
            #Archive::Tar->extract_archive($filename);
            `/bin/tar -x -C $data_store_location/NPTools -f $filename`;

            unlink($filename);
        }
        else {
            # make an empty directory if it doesn't already exist on the CD
            my $error;

            mkpath($data_store_location."/NPTools/".$directory, { error => \$error });
            if ($error) {
                # XXX: complain
            }
        }

        unless (-d "/".$directory) {
            my $error;

            mkpath("/".$directory, { error => \$error });
        }

        my @cmd = ();
        push @cmd, "mount";
        push @cmd, "--bind";
        push @cmd, $data_store_location."/NPTools/".$directory;
        push @cmd, "/".$directory;

        my $status = system(@cmd);
        if ($status != 0) {
            my $exit_value  = $? >> 8;
            my $signal_num  = $? & 127;
            my $dumped_core = $? & 128;

            print "Problem executing: ".join(",", @cmd).": ".$exit_value."\n";
        }
    }
}

if (-e $data_store_location."/NPTools/".$conf->{configuration_tarball}) {
    # Untar is under the new location
    chdir("/");
    Archive::Tar->extract_archive($data_store_location."/NPTools/".$conf->{configuration_tarball});
}

# Run any post-restore scripts 
if ($conf->{restore_post_run}) {
    $conf->{restore_post_run} = [ $conf->{restore_post_run} ] unless (ref $conf->{restore_post_run});

    foreach my $pattern (@{ $conf->{restore_post_run} }) {
        my @scripts = glob($pattern);

        foreach my $script (@scripts) {
            my @cmd = ();

            push @cmd, $script;
            push @cmd, ("-v", $data_store_version);
            push @cmd, ("-s", $data_store_location);
            push @cmd, ("-c", $original_cd_location);

            my $status = system(@cmd);
            if ($status != 0) {
                my $exit_value  = $? >> 8;
                my $signal_num  = $? & 127;
                my $dumped_core = $? & 128;

                print "Problem executing: ".join(",", @cmd).": ".$exit_value."\n";
            }
        }
    }
}

exit 0;

__END__

=head1 SEE ALSO

L<Config::General>, L<FindBin>

To join the 'perfSONAR Users' mailing list, please visit:

  https://mail.internet2.edu/wws/info/perfsonar-user

The perfSONAR-PS subversion repository is located at:

  http://anonsvn.internet2.edu/svn/perfSONAR-PS/trunk

Questions and comments can be directed to the author, or the mailing list.
Bugs, feature requests, and improvements can be directed here:

  http://code.google.com/p/perfsonar-ps/issues/list

=head1 VERSION

$Id$

=head1 AUTHOR

Aaron Brown, aaron@internet2.edu

=head1 LICENSE

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

=head1 COPYRIGHT

Copyright (c) 2004-2010, Internet2 and the University of Delaware

All rights reserved.

=cut
