ec2import-image.pl 6.36 KB
Newer Older
Srikanth Raju's avatar
Srikanth Raju committed
1
2
3
#!/usr/bin/perl -d:Trace
#
# Copyright (c) 2013 University of Utah and the Flux Group.
4
#
Srikanth Raju's avatar
Srikanth Raju committed
5
# {{{EMULAB-LICENSE
6
#
Srikanth Raju's avatar
Srikanth Raju committed
7
# This file is part of the Emulab network testbed software.
8
#
Srikanth Raju's avatar
Srikanth Raju committed
9
10
11
12
# 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.
13
#
Srikanth Raju's avatar
Srikanth Raju committed
14
15
16
17
# 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.
18
#
Srikanth Raju's avatar
Srikanth Raju committed
19
20
# 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/>.
21
#
Srikanth Raju's avatar
Srikanth Raju committed
22
23
24
25
26
# }}}
#
use English;
use Getopt::Std;
use strict;
Srikanth Raju's avatar
Srikanth Raju committed
27
use POSIX;
Srikanth Raju's avatar
Srikanth Raju committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

# 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: ec2import-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;


51
my $TB       = "/usr/testbed";
Srikanth Raju's avatar
Srikanth Raju committed
52
53
54
55
56
#
# No configure vars.
#
my $WORK_BASE  = "/q/import_temp/";
my $IN_BASE  = "/q/indir/";
57
#TODO something in some script that creates these two directorieso
Srikanth Raju's avatar
Srikanth Raju committed
58
59
60
61
my $TAR      = "tar";
my $sudo;
my $zipper   = "/usr/local/bin/imagezip";
my $uploader = "/usr/local/etc/emulab/frisupload";
Srikanth Raju's avatar
Srikanth Raju committed
62
my $error    = 0;
Srikanth Raju's avatar
Srikanth Raju committed
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

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();
}
79

Srikanth Raju's avatar
Srikanth Raju committed
80
81
82
83
if (@ARGV != 5) {
    usage();
}

84
85
86
87
88
my $remote = $ARGV[0];
my $project = $ARGV[1];
my $user = $ARGV[2];
my $osid = $ARGV[3];
my $outfile = $ARGV[4];
Srikanth Raju's avatar
Srikanth Raju committed
89

90
91
#my $ruser = split('@',$remote)[0];
#my $raddr = split('@',$remote)[1];
Srikanth Raju's avatar
Srikanth Raju committed
92
93
94
95
96

my $infile = $IN_BASE . $project . "/" . $user . "/" . $osid . ".tar.gz";
my $workdir = $WORK_BASE . $project . "/" . $user . "/" . $osid . "-tmp";

# Man, this really needs some exception handling
Srikanth Raju's avatar
Srikanth Raju committed
97
98
99

# Check if we can connect to the machine using publickey only
if(system("ssh -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no" .
Srikanth Raju's avatar
Srikanth Raju committed
100
        " -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" .
Srikanth Raju's avatar
Srikanth Raju committed
101
102
103
        " -o ChallengeResponseAuthentication=no $remote 'exit'")){
    print STDERR "*** Couldn't connect to $remote\n";
    print STDERR "    Ensure that Emulabs public key is in the authorized_hosts\n";
Srikanth Raju's avatar
Srikanth Raju committed
104
105
106
    print STDERR "    command: ssh -o PasswordAuthentication=no" .
        " -o KbdInteractiveAuthentication=no" .
        " -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" .
Srikanth Raju's avatar
Srikanth Raju committed
107
108
109
110
111
        " -o ChallengeResponseAuthentication=no $remote 'exit'";
    $error = 1;
    goto cleanup;
}

Srikanth Raju's avatar
Srikanth Raju committed
112
113
if(system("echo \"mkdir -p ~/.emulab\" | ssh -o UserKnownHostsFile=/dev/null ".
        "-o StrictHostKeyChecking=no $remote bash")){
Srikanth Raju's avatar
Srikanth Raju committed
114
115
116
    print STDERR "*** Couldn't mkdir ~/.emulab";
    $error = 1;
    goto cleanup;
Srikanth Raju's avatar
Srikanth Raju committed
117
118
119
}

# Remotely execute the export script
Srikanth Raju's avatar
Srikanth Raju committed
120
121
if(system("scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ".
        "$TB/sbin/export-template-remote.rb $remote:~/.emulab/export.rb")){
Srikanth Raju's avatar
Srikanth Raju committed
122
    print STDERR "*** Couldn't scp exporter script into $remote\n";
Srikanth Raju's avatar
Srikanth Raju committed
123
    $error = 1;
Srikanth Raju's avatar
Srikanth Raju committed
124
125
126
    goto cleanup;
}

Srikanth Raju's avatar
Srikanth Raju committed
127
# Check if Ruby exists
Srikanth Raju's avatar
Srikanth Raju committed
128
if(system("ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ".
Srikanth Raju's avatar
Srikanth Raju committed
129
130
        "$remote 'which ruby unzip'")){
    print STDERR "*** Could not find either ruby or unzip on remote machine!";
Srikanth Raju's avatar
Srikanth Raju committed
131
132
133
    $error = 1;
    goto cleanup;
}
134

Srikanth Raju's avatar
Srikanth Raju committed
135

Srikanth Raju's avatar
Srikanth Raju committed
136
137
if(system("ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ".
        "-t -t $remote 'sudo ruby -C ~/.emulab < ~/.emulab/export.rb'")){
Srikanth Raju's avatar
Srikanth Raju committed
138
    print STDERR "*** Remote image creation failed\n";
Srikanth Raju's avatar
Srikanth Raju committed
139
    $error = 1;
Srikanth Raju's avatar
Srikanth Raju committed
140
141
142
143
144
    goto cleanup;
}

# SCP back the generated image file
# TODO Saner name for tar and .emulab?
Srikanth Raju's avatar
Srikanth Raju committed
145
146
if(system("scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ".
        "$remote:~/.emulab/emulab.tar.gz $infile")){
Srikanth Raju's avatar
Srikanth Raju committed
147
    print STDERR "*** Couldn't scp image back into ops\n";
Srikanth Raju's avatar
Srikanth Raju committed
148
    $error = 1;
Srikanth Raju's avatar
Srikanth Raju committed
149
150
151
152
153
154
    goto cleanup;
}

# Process the tar blah image
if (! -e $infile){
    print STDERR "*** Input tar image not found.\n";
Srikanth Raju's avatar
Srikanth Raju committed
155
    print STDERR "    Looking for:" . $infile . "\n";
Srikanth Raju's avatar
Srikanth Raju committed
156
    $error = 1;
Srikanth Raju's avatar
Srikanth Raju committed
157
158
    goto cleanup;
}
159

Srikanth Raju's avatar
Srikanth Raju committed
160
161
# Unzip into the working dir
if (system("mkdir -p $workdir")){
Srikanth Raju's avatar
Srikanth Raju committed
162
    print STDERR "*** Couldn't mkdir $workdir \n";
Srikanth Raju's avatar
Srikanth Raju committed
163
    $error = 1;
Srikanth Raju's avatar
Srikanth Raju committed
164
165
166
167
    goto cleanup;
}

if (system("tar -xvzf $infile -C $workdir")){
Srikanth Raju's avatar
Srikanth Raju committed
168
    print STDERR "*** Failed to extract $infile \n";
Srikanth Raju's avatar
Srikanth Raju committed
169
    $error = 1;
Srikanth Raju's avatar
Srikanth Raju committed
170
171
172
    goto cleanup;
}

Srikanth Raju's avatar
Srikanth Raju committed
173
my $filesize = ceil((-s "$workdir/emulab-image")/(1024*1024*1024));
Srikanth Raju's avatar
Srikanth Raju committed
174
175
$filesize = $filesize + 4;

176
177
178
179
180
181
182
183
184
185
my $console = 'hvc0';
if (-e "$workdir/bootopts") {
    if(open(my $bo, "<", "/mnt/$imagename/bootopts")) {
        my $bootopts = join('', <$bo>);
        if ($bootopts =~ /xvc0/){
            $extra =~ s/hvc0/xvc0/g;
        }
    }
}
    
Srikanth Raju's avatar
Srikanth Raju committed
186
187
188
189
190
191
192
193
194
# Create the "special" xm.conf
my $heredoc = <<XMCONF;
disksizes = 'xvda2:2.00g,xvda1:$filesize.00g'
memory = '256'
disk = ['phy:/dev/xen-vg/pcvm666-1,xvda1,w','phy:/dev/xen-vg/pcvm666.swap,xvda2,w']
kernel = 'kernel'
ramdisk = 'initrd'
vif = ['mac=02:bf:bb:b9:ae:9c, ip=172.19.140.1, bridge=xenbr0']
name = 'pcvm666-1'
195
extra = 'root=/dev/xvda1 boot_verbose=1 xencons=tty console=$console selinux=0'
Srikanth Raju's avatar
Srikanth Raju committed
196
197
198
199
200
201
202
203
204
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
205
if (system("$zipper -o -l $workdir/emulab-image $workdir/xvda1")) {
Srikanth Raju's avatar
Srikanth Raju committed
206
    print STDERR "*** Failed to greate image!\n";
Srikanth Raju's avatar
Srikanth Raju committed
207
    print STDERR "    command: $zipper -o -l $workdir/emulab-image $workdir/xvda1\n";
Srikanth Raju's avatar
Srikanth Raju committed
208
209
    $error = 1;
    goto cleanup;
Srikanth Raju's avatar
Srikanth Raju committed
210
211
212
213
214
215
216
217
}


# Tar everything up and then imagezip
my $cmd = "$TAR zcf - -C $workdir xvda1 xm.conf kernel initrd | $zipper -f - $outfile";
if (system("$cmd")) {
    print STDERR "*** Failed to create image!\n";
    print STDERR "    command: '$cmd'\n";
Srikanth Raju's avatar
Srikanth Raju committed
218
    $error = 1;
Srikanth Raju's avatar
Srikanth Raju committed
219
220
221
222
223
224
225
    goto cleanup;
}

cleanup:
# Clean up the directory.
print STDOUT "Performing cleanup...\n";
system("$sudo /bin/rm -rf $workdir 2>/dev/null");
Srikanth Raju's avatar
Srikanth Raju committed
226
227
system("echo 'rm -Rf ~/.emulab' | ssh -o UserKnownHostsFile=/dev/null ".
            "-o StrictHostKeyChecking=no $remote bash");
Srikanth Raju's avatar
Srikanth Raju committed
228

Srikanth Raju's avatar
Srikanth Raju committed
229
exit($error);