Commit 003aef50 authored by Kirk Webb's avatar Kirk Webb

Android support: make image loading via tbadb asynchronous.

parent 98f679c5
......@@ -664,8 +664,9 @@ sub error_exit($$$) {
# log the error locally.
warn "$message\n";
# Send failure result back.
return SendRPCData($RPCOUT, EncodeError($fid, $code, $message));
# Send failure result back to caller and exit.
SendRPCData($RPCOUT, EncodeError($fid, $code, $message));
exit 1;
}
# Helper that does LRU on our image cache
......
......@@ -29,15 +29,17 @@ use POSIX ":sys_wait_h";
use Getopt::Std;
use Data::Dumper;
use IO::Socket::INET;
use File::Temp qw(tempfile);
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use libjsonrpc;
use tbadb_rpc;
use EmulabConstants;
use User;
use Node;
use Image;
use EmulabConstants;
# Func prototypes
sub cmd_setup($@);
......@@ -173,9 +175,10 @@ sub cmd_setup($@) {
# if necessary. The remote end keeps an LRU cache of images.
#
sub cmd_loadimage($@) {
my ($node_id, $imagepid, $imagename) = @_;
my ($node_id, $imagepid, $imagename, @extra) = @_;
my $nowait = 0;
# Check and untaint arguments.
# Process and untaint arguments.
die "tbadb::cmd_loadimage: missing one or more arguments (need: <project> <image_name>)!\n"
if (!$node_id || !$imagepid || !$imagename);
die "tbadb::cmd_loadimage: malformed project id!"
......@@ -184,6 +187,16 @@ sub cmd_loadimage($@) {
die "tbadb::cmd_loadimage: malformed image id/name!"
if ($imagename !~ /^([-\w]{$MINHLEN,$MAXHLEN})$/);
$imagename = $1;
foreach my $arg (@extra) {
ARGS: for ($arg) {
/^nowait$/i && do {
$nowait = 1;
last ARGS;
};
# Default
die "tbadb::cmd_loadimage: unknown argument: $arg!\n";
}
}
# Lookup image and extract some info.
my $image = Image->Lookup($imagepid, $imagename);
......@@ -210,7 +223,17 @@ sub cmd_loadimage($@) {
die("tbadb::cmd_loadimage: You do not have permission to load an image onto $node\n")
if (!$isroot && !$this_user->IsAdmin() &&
!$node->AccessCheck($this_user, TB_NODEACCESS_LOADIMAGE));
# If told not to wait, fork into the background.
my $logname;
if ($nowait) {
(undef, $logname) = tempfile("tbadb-XXXXXX", TMPDIR => 1);
die "tbadb::cmd_loadimage: Could not create temp logging file: $!\n"
if !$logname;
return 0
if (TBBackGround($logname));
}
# Grab the RPC pipe.
my ($rpcin, $rpcout) = GetRPCPipeHandles($node);
die "tbadb::cmd_reboot: Failed to get valid SSH pipe filehandles!\n"
......@@ -316,8 +339,22 @@ sub cmd_loadimage($@) {
exit 1;
}
#
# Tell stated that we've finished reloading the node if the node
# is in the RELOADUE opmode.
#
my $opmode;
if (TBGetNodeOpMode($node_id,\$opmode) &&
$opmode eq TBDB_NODEOPMODE_RELOADUE) {
TBSetNodeEventState($node_id,TBDB_NODESTATE_RELOADDONE);
TBSetNodeEventState($node_id,TBDB_NODESTATE_SHUTDOWN);
}
# Done!
print "tbadb::cmd_loadimage: Successfully loaded $imagename onto $node_id\n";
if ($nowait && $logname) {
unlink($logname);
}
return 0;
}
......
......@@ -1275,7 +1275,7 @@ sub SetupReloadUE($)
{
my $reload_info = $_[0];
my $nodeobject = $reload_info->{'nodeobj'};
my $node_id = $reload_info->{'node'};
my $node = $reload_info->{'node'};
my $image = (@{$reload_info->{'images'}})[0];
my $osid = $reload_info->{'osid'};
......@@ -1285,58 +1285,38 @@ sub SetupReloadUE($)
my $imgpid = $image->pid();
my $imgname = $image->imagename();
#
# Grab the target adb host if specified by the user. Adjust the
# tbadb command as appropriate.
#
my $thost;
my $experiment = $nodeobject->Reservation();
if ($experiment) {
$experiment->GetVirtNodeAttribute($nodeobject->vname(),
"adb_target", \$thost);
}
my $adbcmd =
$thost ? "setup $imgpid $imgname $thost" :
"loadimage $imgpid $imgname";
#
# Tell stated that we're about to start reloading
#
TBSetNodeNextOpMode($node_id,TBDB_NODEOPMODE_RELOADUE);
TBSetNodeNextOpMode($node,TBDB_NODEOPMODE_RELOADUE);
#
# The mote goes 'down', then starts to reload
#
TBSetNodeEventState($node_id,TBDB_NODESTATE_SHUTDOWN);
TBSetNodeEventState($node_id,TBDB_NODESTATE_RELOADING);
TBSetNodeEventState($node,TBDB_NODESTATE_SHUTDOWN);
TBSetNodeEventState($node,TBDB_NODESTATE_RELOADING);
#
# Invoke local script that calls the remote end that
# actually does the work.
#
my $rv = system("$TBADB -n $node_id $adbcmd");
my $rv = system("$TBADB -n $node loadimage $imgpid $imgname nowait");
if ($rv) {
tberror "$node_id: tbadb failed!";
tberror "$node: tbadb failed!";
return -1;
}
#
# Tell stated that we've finished reloading the node
# Set the boot OSID. Not that the UEs will check in via bootinfo,
# but perhaps something else will care that this is correct/consistent.
#
TBSetNodeEventState($node_id,TBDB_NODESTATE_RELOADDONE);
system("$osselect $osid $node_id");
if ($?) {
my $osinfo = OSinfo->Lookup($osid);
if (!defined($osinfo) ||
$nodeobject->OSSelect($osinfo, "next_boot_osid", 0)) {
tberror "os_select $osid failed!";
return -1;
}
#
# 'Reboot' the node (from stated's perspective, anyway)
# has been shutdown, so that the os_select will take effect
#
TBSetNodeEventState($node_id,TBDB_NODESTATE_SHUTDOWN);
return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment