import-image.pl 4.26 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/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 <http://www.gnu.org/licenses/>.
# 
# }}}
#
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")){
Srikanth Raju's avatar
Srikanth Raju committed
96
    print STDERR "Couldn't scp exporter script into $remote\n";
97
98
99
100
    goto cleanup;
}

if(system("ssh -t -t -l $ruser $remote 'sudo ruby < ~/export.rb'")){
Srikanth Raju's avatar
Srikanth Raju committed
101
    print STDERR "Remote image creation failed\n";
102
103
104
105
    goto cleanup;
}

# SCP back the generated image file
Srikanth Raju's avatar
Srikanth Raju committed
106
107
108
109
if(system("scp $ruser\@$remote:~/emulab.tar.gz $infile")){
    print STDERR "Couldn't scp image back into ops\n";
    goto cleanup;
}
110
111
112
113
114
115
116
117
118

# 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
Srikanth Raju's avatar
Srikanth Raju committed
119
120
121
122
123
124
125
126
127
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;
}
128

Srikanth Raju's avatar
Srikanth Raju committed
129
# TODO: Proper xvda1 size based on image size?
130
131
132
# TODO: Maybe handle bootopts
# Create the "special" xm.conf
my $heredoc = <<XMCONF;
Srikanth Raju's avatar
Srikanth Raju committed
133
disksizes = 'xvda2:2.00g,xvda1:12.00g'
134
memory = '256'
135
disk = ['phy:/dev/xen-vg/pcvm666-1,xvda1,w','phy:/dev/xen-vg/pcvm666.swap,xvda2,w']
136
137
138
139
kernel = 'kernel'
ramdisk = 'initrd'
vif = ['mac=02:bf:bb:b9:ae:9c, ip=172.19.140.1, bridge=xenbr0']
name = 'pcvm666-1'
140
extra = 'root=/dev/xvda1 boot_verbose=1 vfs.root.mountfrom=ufs:/dev/da0a kern.bootfile=/boot/kernel/kernel console=xvc0 selinux=0'
141
142
143
144
145
146
147
148
149
XMCONF

open(FH, '>', "$workdir/xm.conf") or goto cleanup;

print FH $heredoc;

close(FH);

# Image zip the raw image
Srikanth Raju's avatar
Srikanth Raju committed
150
if (system("$zipper -o -l $workdir/image $workdir/xvda1")) {
151
    print STDERR "*** Failed to greate image!\n";
Srikanth Raju's avatar
Srikanth Raju committed
152
    print STDERR "    command: $zipper -o -l $workdir/image $workdir/xvda1\n";
153
154
155
156
}


# Tar everything up and then imagezip
Srikanth Raju's avatar
Srikanth Raju committed
157
my $cmd = "$TAR zcf - -C $workdir xvda1 xm.conf kernel initrd | $zipper -f - $osid.ndz";
158
159
160
161
162
163
164
165
166

if (system("$cmd")) {
    print STDERR "*** Failed to create image!\n";
    print STDERR "    command: '$cmd'\n";
    goto cleanup;
}

cleanup:
# Clean up the directory.
Srikanth Raju's avatar
Srikanth Raju committed
167
system("$sudo /bin/rm -rf $workdir 2>/dev/null");
168