diff --git a/db/nfree.in b/db/nfree.in index 5b54c63a920f1df515557c2355da4d1190195d0b..635b2571594a764d5fd48985f702782d02a14f88 100755 --- a/db/nfree.in +++ b/db/nfree.in @@ -50,6 +50,7 @@ my @nodes; my @freed_nodes=(); my @dynanodes=(); my $error = 0; +my %mustzero=(); $| = 1; # Turn off line buffering on output @@ -110,34 +111,20 @@ if (@ARGV) { if ($n =~ /^([-\w]+)$/) { $n = $1; } else { die("*** $0:\n Bad node name: $n.\n"); } - # Shark hack - if ($n =~ /(sh\d+)/ ) { - # It's a shark - do the whole shelf if its not done already. - my $shelf = $1; - if ( ! (join(",", @nodes) =~ /,$shelf-\d,/)) { - # Shelf hasn't been done yet... - foreach my $n ( 1 .. 8 ) { - push(@nodes, "$shelf-$n"); - } - } - # End shark hack - } else { - # its not a shark - just add it in... - push(@nodes, $n); - - # if -x was specified, remove any - # mapping to a node which has a phys_nodeid of $n. - if ($freeDependantVirtuals) { - my $result = - DBQueryFatal("SELECT r.node_id FROM reserved AS r ". - "LEFT JOIN nodes AS n ". - "ON r.node_id=n.node_id ". - "WHERE n.phys_nodeid='$n' AND ". - "r.eid='$eid' AND r.pid='$pid'"); - while (my ($dependantVirtual) = $result->fetchrow_array()) { - if (defined $dependantVirtual && $dependantVirtual ne $n) { - push(@nodes, $dependantVirtual); - } + push(@nodes, $n); + + # if -x was specified, remove any + # mapping to a node which has a phys_nodeid of $n. + if ($freeDependantVirtuals) { + my $result = + DBQueryFatal("SELECT r.node_id FROM reserved AS r ". + "LEFT JOIN nodes AS n ". + "ON r.node_id=n.node_id ". + "WHERE n.phys_nodeid='$n' AND ". + "r.eid='$eid' AND r.pid='$pid'"); + while (my ($dependantVirtual) = $result->fetchrow_array()) { + if (defined $dependantVirtual && $dependantVirtual ne $n) { + push(@nodes, $dependantVirtual); } } } @@ -183,6 +170,16 @@ foreach my $n (@nodes) { next; } + # + # Remember if the node's disk must be zeroed + # + my $rowref = $result->fetchrow_hashref(); + if ($rowref->{'mustwipe'}) { + $mustzero{$n} = $rowref->{'mustwipe'}; + } else { + $mustzero{$n} = 0; + } + if ( $moveToOldReserved ) { # Move to holding reservation. Node is not free, but is no longer # owned by the pid/eid, so cannot be mucked with. @@ -251,6 +248,7 @@ foreach my $n (@freed_nodes) { if ($isvirt || !$imageable) { # VIRTNODE HACK: Virtual nodes are special. Do not clean or reload. $mustclean = 0; + $mustzero{$n} = 0; } elsif (defined($clean)) { # If def_boot_osid set, then $clean is defined. Otherwise not set @@ -354,9 +352,10 @@ foreach my $n (@freed_nodes) { DBQueryFatal("select node_id,image_id from scheduled_reloads " . "where node_id='$n'"); - # XXX force reload hack! - if ( !$TESTMODE && ((!$isvirt && $imageable) || $result->numrows() || - TBNodeType($n) eq "garcia")) { # XXX Garcia hack + if (!$TESTMODE && + ((!$isvirt && $imageable) || # XXX force reload hack! + $result->numrows() || $mustzero{$n} || + TBNodeType($n) eq "garcia")) { # XXX Garcia hack print "Moving $n to $reloadpid/$pendingeid.\n"; DBQueryWarn("update reserved set pid='$reloadpid',eid='$pendingeid',". diff --git a/sql/database-create.sql b/sql/database-create.sql index d16835f0cd860a73c22057ac270db4b083560de9..c66c6671f48df218fd59db8a3e421d2aaca7e3f8 100644 --- a/sql/database-create.sql +++ b/sql/database-create.sql @@ -67,6 +67,7 @@ CREATE TABLE comments ( CREATE TABLE current_reloads ( node_id varchar(32) NOT NULL default '', image_id varchar(45) NOT NULL default '', + mustwipe tinyint(4) NOT NULL default '0', PRIMARY KEY (node_id) ) TYPE=MyISAM; @@ -1490,6 +1491,7 @@ CREATE TABLE reserved ( old_eid varchar(32) NOT NULL default '', cnet_vlan int(11) default NULL, inner_elab_role enum('boss','ops','node') default NULL, + mustwipe tinyint(4) NOT NULL default '0', PRIMARY KEY (node_id), UNIQUE KEY vname (pid,eid,vname), KEY old_pid (old_pid,old_eid) diff --git a/sql/database-migrate.txt b/sql/database-migrate.txt index d74034e42b639fbddb2abd8023a364beca90be46..aeaa2de43bda6b260948eedc5744e76168d5ee1f 100644 --- a/sql/database-migrate.txt +++ b/sql/database-migrate.txt @@ -2518,3 +2518,12 @@ last_net_act,last_cpu_act,last_ext_act); alter table users add wikiname tinytext; alter table groups add wikiname tinytext; + +1.321: DB support for disk wipe-age. If 'mustwipe' is set in the reserved + table entry for a node, then when nfree'd, the disk must be reloaded + and all free blocks zeroed to prevent information leakage. + + alter table reserved add mustwipe tinyint(4) NOT NULL default '0'; + alter table current_reloads add mustwipe \ + tinyint(4) NOT NULL default '0'; + diff --git a/tbsetup/libosload.pm.in b/tbsetup/libosload.pm.in index 31a766e37ffcaf2275f452fa23b4a7bb0220cca4..39103e5d1820309647b49cf3eeb86e5a4c7d06c4 100755 --- a/tbsetup/libosload.pm.in +++ b/tbsetup/libosload.pm.in @@ -1,7 +1,7 @@ #!/usr/bin/perl -wT # # EMULAB-COPYRIGHT -# Copyright (c) 2000-2004 University of Utah and the Flux Group. +# Copyright (c) 2000-2005 University of Utah and the Flux Group. # All rights reserved. # # Osload library. Basically the backend to the osload script, but also used @@ -54,6 +54,7 @@ sub osload ($$) { my @nodes = (); my $noreboot = 0; my $asyncmode = 0; + my $zerofree = 0; # Locals my %retries = (); @@ -84,6 +85,9 @@ sub osload ($$) { if (defined($args->{'asyncmode'})) { $asyncmode = $args->{'asyncmode'}; } + if (defined($args->{'zerofree'})) { + $zerofree = $args->{'zerofree'}; + } # # Figure out who called us. Root and admin types can do whatever they @@ -197,6 +201,7 @@ sub osload ($$) { "*** osload ($node): No filename associated with $imageid!\n"; goto failednode; } + if (! -R $imagepath) { if ($ELABINELAB) { # @@ -210,6 +215,12 @@ sub osload ($$) { "Frisbee Launcher ($imageid) failed!\n"; goto failednode; } + if (! -R $imagepath) { + print STDERR + "*** osload ($node): ". + "Frisbee Launcher get not fetch $imagepath ($imageid)!\n"; + goto failednode; + } } else { print STDERR @@ -324,6 +335,7 @@ sub osload ($$) { $reload_mode = "UISP"; $reload_func = \&SetupReloadUISP; $reboot_required = 0; # We don't reboot motes to reload them + $zerofree = 0; # and we don't zero "the disk" } else { $reload_mode = "Frisbee"; $reload_func = \&SetupReloadFrisbee; @@ -339,13 +351,14 @@ sub osload ($$) { 'func' => $reload_func, 'imageid' => $imageid, 'osid' => $defosid, - 'reboot' => $reboot_required + 'reboot' => $reboot_required, + 'zerofree'=> $zerofree }; print "Setting up reload for $node (mode: $reload_mode)\n"; if (!$TESTMODE) { - if (&$reload_func($node, $imageid,$defosid) < 0) { + if (&$reload_func($node, $imageid, $defosid, $zerofree) < 0) { print STDERR "*** osload ($node): Could not set up reload. Skipping.\n"; goto failednode; @@ -465,7 +478,7 @@ sub osload ($$) { # Possible race with reboot? if (&{$reload_info->{'func'}}($node, $reload_info->{'imageid'}, - $reload_info->{'osid'}) < 0) { + $reload_info->{'osid'}, $reload_info->{'zerofree'}) < 0) { print(STDERR "*** osload ($node): ". "Could not set up reload. Skipping.\n"); @@ -529,7 +542,32 @@ sub WaitTillReloadDone($$$@) sleep(5); foreach my $node (@nodes) { if (! $done{$node}) { - my $maxwait = $maxwaits{$reload_info->{$node}{'imageid'}}; + my $maxwait; + + # + # If we have to zero fill free space, then the + # wait time has to be proportional to the disk + # size. In other words, a really, really, really + # long time. Lets assume 20MB/sec to blast zeros, + # so 50 seconds/GB. What the heck, lets call it + # 1GB/minute. Did I mention how this would take + # a really long time? + # + if ($reload_info->{$node}{'zerofree'}) { + my $disksize; + my $query_result = + DBQueryWarn("select HD from node_types,nodes ". + "where nodes.type=node_types.type". + " and node_id='$node'"); + if ($query_result && $query_result->numrows) { + ($disksize) = $query_result->fetchrow_array(); + } + $disksize = 20 + if (!$disksize); + $maxwait = ($disksize * 60); + } else { + $maxwait = $maxwaits{$reload_info->{$node}{'imageid'}}; + } my $query_result = DBQueryWarn("select * from current_reloads ". @@ -604,9 +642,9 @@ sub WaitTillReloadDone($$$@) } # Setup a reload. -sub SetupReloadFrisbee($$$) +sub SetupReloadFrisbee($$$$) { - my ($node, $imageid, $osid_notused) = @_; + my ($node, $imageid, $osid_notused, $zerofree) = @_; my $osid = $FRISBEEOSID; # @@ -628,7 +666,8 @@ sub SetupReloadFrisbee($$$) # $query_result = DBQueryWarn("replace into current_reloads ". - "(node_id, image_id) values ('$node', '$imageid')"); + "(node_id, image_id, mustwipe) values ". + "('$node', '$imageid', $zerofree)"); return -1 if (!$query_result); @@ -650,9 +689,9 @@ sub SetupReloadFrisbee($$$) # this differs from a Frisbee reload in one key way - it does the reload # right here in this code, rather than setting up a reload for later. # -sub SetupReloadUISP($$$) +sub SetupReloadUISP($$$$) { - my ($node, $imageid, $osid) = @_; + my ($node, $imageid, $osid, $zerofree_unused) = @_; # # Get the path to the image diff --git a/tbsetup/os_load.in b/tbsetup/os_load.in index d50f265d9660304478079b621ba3b39e497cfa05..f29a018d34ad89c6fb97250c45b1246e2fed54b6 100755 --- a/tbsetup/os_load.in +++ b/tbsetup/os_load.in @@ -1,7 +1,7 @@ #!/usr/bin/perl -wT # # EMULAB-COPYRIGHT -# Copyright (c) 2000-2004 University of Utah and the Flux Group. +# Copyright (c) 2000-2005 University of Utah and the Flux Group. # All rights reserved. # use English; @@ -24,14 +24,19 @@ sub usage() "Use -w to wait for the nodes to finish booting.\n". "Use -r to supress rebooting nodes - you'll need to to it yourself\n". "Use -e to reload all the nodes in an experiment.\n" . - "Use -l to get a list of images you are permitted to load.\n"); + "Use -l to get a list of images you are permitted to load.\n". + "Use -z <style> to zero all unallocated blocks on the disk\n". + " style==0: don't zero (same as not using -z)\n". + " style==1: let frisbee do the zeroing\n". + " style==2: zero disk before running frisbee\n"); exit(-1); } -my $optlist = "swldi:e:p:m:r"; +my $optlist = "swldi:e:p:m:rz:"; my $waitmode = 1; my $listonly = 0; my $debug = 0; my $noreboot = 0; +my $zerofree = 0; my @nodes = (); my $imagepid; my $imagename; @@ -81,6 +86,8 @@ $waitmode = 2 if (defined($options{"w"})); $noreboot = 1 if (defined($options{"r"})); +$zerofree = $options{"z"} + if (defined($options{"z"})); # # Figure out which nodes. Choice of nodes on command line, or all nodes in an @@ -223,6 +230,7 @@ my %failednodes = (); $osloadargs{'debug'} = $debug; $osloadargs{'waitmode'} = $waitmode; $osloadargs{'noreboot'} = $noreboot; +$osloadargs{'zerofree'} = $zerofree; $osloadargs{'nodelist'} = [ @nodes ]; # No imageid means to load the default image. $osloadargs{'imageid'} = $imageid diff --git a/tbsetup/reload_daemon.in b/tbsetup/reload_daemon.in index 7f51265932037cb860c241cab37acb1d150e97e9..64df1f1ffba82e8681bab0a89ec5eeba7354063d 100644 --- a/tbsetup/reload_daemon.in +++ b/tbsetup/reload_daemon.in @@ -64,8 +64,8 @@ my $reboot = "$TB/bin/node_reboot"; my $tbrsync = "$TB/bin/tbrsync"; my $logfile = "$TB/log/reloadlog"; my $debug = 0; -my $retry_time = 15; # in minutes -my $warn_time = 30; # in minutes +my $retry_time = 20; # in minutes +my $warn_time = $retry_time * 2; # in minutes my %retried = (); my %warned = (); my %failed = (); @@ -131,10 +131,14 @@ while (1) { # First, look for nodes that have been in the reloading experiment for # longer than $retry_time, and try rebooting them # + # XXX we count on mustwipe having the value 0, 1, 2 to represent + # ever slower forms of wipeage. For retry_time of 20 minutes that + # yields waits of 20, 40 and 60 minutes. + # $query_result = - DBQueryWarn("select node_id from reserved where pid='$RELOADPID' " . - "and eid='$RELOADEID' and " . - "(CURRENT_TIMESTAMP - INTERVAL $retry_time MINUTE) ". + DBQueryWarn("select node_id,mustwipe from reserved " . + "where pid='$RELOADPID' and eid='$RELOADEID' and " . + "(CURRENT_TIMESTAMP - INTERVAL $retry_time * (mustwipe + 1) MINUTE)". " > rsrv_time"); if (! $query_result) { @@ -142,7 +146,7 @@ while (1) { next; } - while (($node) = $query_result->fetchrow){ + while (($node, $mustwipe) = $query_result->fetchrow) { $idle=0; # # If this was a node that failed os_load, then instead of rebooting, @@ -150,7 +154,7 @@ while (1) { # if ($failed{$node}) { print "$node failed an earlier os_load. Trying again\n"; - push(@retry_list, $node); + push(@retry_list, [$node, $mustwipe]); delete $failed{$node}; # Skip any reboots. $retried{$node} = $time; @@ -187,22 +191,25 @@ while (1) { # Next, we do the same thing for nodes in the reloading experiment for # longer than $warn_time, and warn the admins. # + # XXX again, we scale by the value of mustwipe. + # $query_result = - DBQueryWarn("select node_id from reserved where pid='$RELOADPID' " . - "and eid='$RELOADEID' and " . - "(CURRENT_TIMESTAMP - INTERVAL $warn_time MINUTE) > ". - " rsrv_time"); + DBQueryWarn("select node_id,mustwipe from reserved " . + "where pid='$RELOADPID' and eid='$RELOADEID' and " . + "(CURRENT_TIMESTAMP - INTERVAL $warn_time * (mustwipe + 1) MINUTE)". + " > rsrv_time"); if (! $query_result) { print "DB Error. Waiting a bit.\n"; next; } - while (($node) = $query_result->fetchrow){ + while (($node, $mustwipe) = $query_result->fetchrow) { $idle=0; if (!$warned{$node}) { + my $toolong = $warn_time * ($mustwipe + 1); notify("Node $node has been in $RELOADPID/$RELOADEID for " . - "more than $warn_time minutes"); + "more than $toolong minutes"); } $warned{$node} = $time; } @@ -227,7 +234,8 @@ while (1) { my $CLASSCLAUSE = "(n.class='pc' or n.class='pct')"; $query_result = - DBQueryWarn("select a.node_id,b.pid,b.eid from reserved as b ". + DBQueryWarn("select a.node_id,b.pid,b.eid,b.mustwipe ". + "from reserved as b ". "left join nodes as a on a.node_id=b.node_id ". "left join last_reservation as l on l.node_id=a.node_id ". "left join node_types as n on n.type=a.type where ". @@ -249,18 +257,19 @@ while (1) { # Grab all the nodes that match my @pending_list = @retry_list; - while (%hrow = $query_result->fetchhash()) { + while (%hrow = $query_result->fetchhash()) { $node = $hrow{'node_id'}; $pid = $hrow{'pid'}; $eid = $hrow{'eid'}; + $mustwipe = $hrow{'mustwipe'}; if ($pid eq $RELOADPID && $eid eq $PENDINGEID) { - push(@pending_list,$node); + push(@pending_list, [$node,$mustwipe]); } else { - push(@other_list,$node); + push(@other_list, [$node,$mustwipe]); } } - my $nodes = join(" ", (@pending_list, @other_list)); + my $nodes = join(" ", map { $_->[0] } @pending_list, @other_list); print "Trying to reload $nodes at ".`date`; # @@ -273,7 +282,9 @@ while (1) { # my %images = (); my %imagenodes = (); - foreach $node (@pending_list) { + foreach $ref (@pending_list) { + ($node, $mustwipe) = @{$ref}; + $query_result = DBQueryWarn("select image_id from scheduled_reloads " . "where node_id='$node'"); @@ -297,15 +308,26 @@ while (1) { } # XXX End Garcia Hack + # + # We need to divide up nodes not only by the image they are + # to load (imageid) but also by if and how the disk should be + # zeroed (mustzero). So we really have a hash of hashes each + # of which is an array of nodes. However, my perl skilz are + # not up to that so just combine the imageid and mustwipe into + # a single hash key ('/' is illegal in both, so we use it as + # the separator). + # + my $idid = "$imageid/$mustwipe"; + $images{$node} = $imageid; - if (defined(@{$imagenodes{$imageid}})) { - push(@{$imagenodes{$imageid}},$node); + if (defined(@{$imagenodes{$idid}})) { + push(@{$imagenodes{$idid}},$node); } else { - $imagenodes{$imageid} = [$node]; + $imagenodes{$idid} = [$node]; } if ($debug) { - print "$node => $images{$node} == $imageid (". - join(",",@{$imagenodes{$imageid}}).")\n"; + print "$node ($mustwipe) => $images{$node} == $imageid (". + join(",",@{$imagenodes{$idid}}).")\n"; } } @@ -315,17 +337,19 @@ while (1) { # We change the reservation EID over and fire up an os_load # directly. # - my $cond = join(" or ",map("node_id='$_'",@pending_list)); + my $cond = "node_id in (" . + join(",", map("'$_->[0]'", @pending_list)) . ")"; if (! DBQueryWarn("update reserved set ". "rsrv_time=now(),eid='$RELOADEID' ". "where $cond")) { - print "Could not update EID for ".join(" ",@pending_list). - ". Waiting a bit.\n"; + print "Could not update EID for " . + join(" ", map("$_->[0]", @pending_list)) . + ". Waiting a bit.\n"; next; } else { print "Pending nodes moved to $RELOADEID at ".`date`; - foreach my $n (@pending_list) { + foreach my $n (map("$_->[0]", @pending_list)) { TBSetNodeHistory($n, TB_NODEHISTORY_OP_MOVE, $UID, $RELOADPID, $RELOADEID); } @@ -335,11 +359,13 @@ while (1) { # Now run an os_load for each image - foreach $imageid (keys %imagenodes) { + foreach my $idid (keys %imagenodes) { - my $nodelist = join(" ",@{$imagenodes{$imageid}}); + my $nodelist = join(" ",@{$imagenodes{$idid}}); my $os_load_flags = ""; + ($imageid, $mustzero) = split("/", $idid); + # XXX Garcia Hack - gross.. # We special-case garcia loading for now until the subnode->node # dependancies are worked out inside os_load. @@ -351,7 +377,7 @@ while (1) { if (system("$tbrsync upload $gimagepath $nodelist") == 0) { if (system("$reboot $nodelist") == 0) { # rsync and reboot succeeded, so free 'em up. - foreach my $gnode (@{$imagenodes{$imageid}}) { + foreach my $gnode (@{$imagenodes{$idid}}) { freefromreloading($gnode); } print "garcia reload done at ".`date`; @@ -380,7 +406,14 @@ while (1) { # the node's type # if ($imageid) { - $os_load_flags .= " -m $imageid "; + $os_load_flags .= " -m $imageid"; + } + + # + # Handle optional zeroing of the disk + # + if ($mustzero) { + $os_load_flags .= " -z $mustzero"; } print "Running '$os_load $os_load_flags $nodelist' at ".`date`; @@ -396,7 +429,7 @@ while (1) { # Record the failure list. If we get to the 15 minute # retry, call os_load again instead of rebooting. - foreach my $node (@{$imagenodes{$imageid}}) { + foreach my $node (@{$imagenodes{$idid}}) { $failed{$node} = $time; } } @@ -407,6 +440,8 @@ while (1) { } if (@other_list > 0 ) { + my $nodes = join(" ", map { $_->[0] } @other_list); + # # Call sched_reload with the "force" option, which says that if # sched_reload cannot reserve the node (cause someone just got it) @@ -417,11 +452,11 @@ while (1) { # default, and sched_reload will pick that up from the database # in the absence of a -i option. # - if (system("$sched_reload -f @other_list")) { + if (system("$sched_reload -f $nodes")) { # # Could not get it. Wait and go around again. # - print "$sched_reload failed on @other_list. Waiting a bit.\n"; + print "$sched_reload failed on $nodes. Waiting a bit.\n"; next; } diff --git a/tmcd/freebsd/rc.frisbee b/tmcd/freebsd/rc.frisbee index 4e8ea9615da578dd1b133ac26b89dd852fa99427..6516a7d56d3517f7b9d1bac0e5909d53f9a384a6 100755 --- a/tmcd/freebsd/rc.frisbee +++ b/tmcd/freebsd/rc.frisbee @@ -1,7 +1,7 @@ #!/bin/sh # # EMULAB-COPYRIGHT -# Copyright (c) 2000-2004 University of Utah and the Flux Group. +# Copyright (c) 2000-2005 University of Utah and the Flux Group. # All rights reserved. # # Optional flag argument says "do not reboot" @@ -49,6 +49,8 @@ PARTITION=${PARTITION:-'0'} PARTOS=`echo $LOADINFO | awk -F= '{ printf $4 }' | awk -F' ' '{ print $1 }'` DISK=`echo $LOADINFO | awk -F= '{ printf $5 }' | awk -F' ' '{ print $1 }'` DISK=${DISK:-'ad0'} +ZFILL=`echo $LOADINFO | awk -F= '{ printf $6 }' | awk -F' ' '{ print $1 }'` +ZFILL=${ZFILL:-'0'} if [ "$PARTITION" != "0" ]; then SLICE="-s $PARTITION" @@ -121,11 +123,20 @@ if [ x"$ADDRESS" != x ]; then MCASTIF="" fi MCASTADDR="-m $MCAST -p $PORT" + # + # ZFILL==1: use frisbee + # ZFILL==2: separate disk-wipe pass (not yet implemented) + # + if [ "$ZFILL" != "0" ]; then + ZFILL="-z" + else + ZFILL="" + fi - echo "Running $BINDIR/frisbee $LOADIP $MEMARGS $SLICE $MCASTIF $MCASTADDR /dev/$DISK at `date`" + echo "Running $BINDIR/frisbee $LOADIP $MEMARGS $ZFILL $SLICE $MCASTIF $MCASTADDR /dev/$DISK at `date`" $BINDIR/tmcc state RELOADING - $BINDIR/frisbee $LOADIP $MEMARGS $SLICE $MCASTIF $MCASTADDR /dev/$DISK + $BINDIR/frisbee $LOADIP $MEMARGS $ZFILL $SLICE $MCASTIF $MCASTADDR /dev/$DISK case $? in 0) echo "Frisbee run finished" diff --git a/tmcd/tmcd.c b/tmcd/tmcd.c index 0a6942adea8b04ee7711b9c1e294f1cc3eebeaad..09971c3d1d95c8fae98292106946d895773e3398 100644 --- a/tmcd/tmcd.c +++ b/tmcd/tmcd.c @@ -3259,17 +3259,17 @@ COMMAND_PROTOTYPE(doloadinfo) char buf[MYBUFSIZE]; char *bufp = buf, *ebufp = &buf[sizeof(buf)]; char *disktype; - int disknum; + int disknum, zfill; /* * Get the address the node should contact to load its image */ - res = mydb_query("select load_address,loadpart,OS,frisbee_pid " + res = mydb_query("select load_address,loadpart,OS,frisbee_pid,mustwipe " " from current_reloads as r " "left join images as i on i.imageid = r.image_id " "left join os_info as o on i.default_osid = o.osid " "where node_id='%s'", - 4, reqp->nodeid); + 5, reqp->nodeid); if (!res) { error("doloadinfo: %s: DB Error getting loading address!\n", @@ -3302,6 +3302,14 @@ COMMAND_PROTOTYPE(doloadinfo) bufp += OUTPUT(bufp, ebufp - bufp, "ADDR=%s PART=%s PARTOS=%s", row[0], row[1], row[2]); + + /* + * Remember zero-fill free space indicator + */ + zfill = 0; + if (row[4] && row[4][0]) + zfill = atoi(row[4]); + mysql_free_result(res); /* @@ -3326,9 +3334,10 @@ COMMAND_PROTOTYPE(doloadinfo) if (row[1] && row[1][0]) disknum = atoi(row[1]); } - OUTPUT(bufp, ebufp - bufp, " DISK=%s%d\n", disktype, disknum); + OUTPUT(bufp, ebufp - bufp, " DISK=%s%d ZFILL=%d\n", + disktype, disknum, zfill); mysql_free_result(res); - + client_writeback(sock, buf, strlen(buf), tcp); if (verbose) info("doloadinfo: %s", buf);