#!/usr/bin/perl -d:Trace
#
# Copyright (c) 2013 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file 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 Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see .
#
# }}}
#
use English;
use Getopt::Std;
use strict;
# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
#
# Take a raw image and make a proper emulab image based off of it
#
sub usage()
{
print STDOUT "Usage: import-image remote-user remote-addr project user osid";
exit(-1);
}
my $optlist = "";
#
# Turn off line buffering on output
#
$| = 1;
# Need this for predicates.
use libsetup;
#
# No configure vars.
#
my $WORK_BASE = "/q/import_temp/";
my $IN_BASE = "/q/indir/";
#TODO something in some script that creates these two directories
my $TAR = "tar";
my $sudo;
my $zipper = "/usr/local/bin/imagezip";
my $uploader = "/usr/local/etc/emulab/frisupload";
for my $path (qw#/usr/local/bin /usr/bin#) {
if (-e "$path/sudo") {
$sudo = "$path/sudo";
last;
}
}
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (@ARGV != 5) {
usage();
}
my $ruser = $ARGV[0];
my $remote = $ARGV[1];
my $project = $ARGV[2];
my $user = $ARGV[3];
my $osid = $ARGV[4];
my $infile = $IN_BASE . $project . "/" . $user . "/" . $osid . ".tar.gz";
my $workdir = $WORK_BASE . $project . "/" . $user . "/" . $osid . "-tmp";
#
# Untaint the arguments.
#
# Note different taint check (allow /).
#TODO UNTAINT
# Remotely execute the export script
if(system("scp export-template-remote.rb $ruser\@$remote:~/export.rb")){
print STDERR "Couldn't scp exporter script into $remote\n";
goto cleanup;
}
if(system("ssh -t -t -l $ruser $remote 'sudo ruby < ~/export.rb'")){
print STDERR "Remote image creation failed\n";
goto cleanup;
}
# SCP back the generated image file
if(system("scp $ruser\@$remote:~/emulab.tar.gz $infile")){
print STDERR "Couldn't scp image back into ops\n";
goto cleanup;
}
# Process the tar blah image
if (! -e $infile){
print STDERR "*** Input tar image not found.\n";
print STDERR "Looking for:" . $infile . "\n";
goto cleanup;
}
# Unzip into the working dir
if (system("mkdir -p $workdir")){
print STDERR "Couldn't mkdir $workdir \n";
goto cleanup;
}
if (system("tar -xvzf $infile -C $workdir")){
print STDERR "Failed to extract $infile \n";
goto cleanup;
}
# TODO: Proper xvda1 size based on image size?
# TODO: Maybe handle bootopts
# Create the "special" xm.conf
my $heredoc = <', "$workdir/xm.conf") or goto cleanup;
print FH $heredoc;
close(FH);
# Image zip the raw image
if (system("$zipper -o -l $workdir/image $workdir/xvda1")) {
print STDERR "*** Failed to greate image!\n";
print STDERR " command: $zipper -o -l $workdir/image $workdir/xvda1\n";
}
# Tar everything up and then imagezip
my $cmd = "$TAR zcf - -C $workdir xvda1 xm.conf kernel initrd | $zipper -f - $osid.ndz";
if (system("$cmd")) {
print STDERR "*** Failed to create image!\n";
print STDERR " command: '$cmd'\n";
goto cleanup;
}
cleanup:
# Clean up the directory.
system("$sudo /bin/rm -rf $workdir 2>/dev/null");