Commit 0e225c56 authored by Leigh B. Stoller's avatar Leigh B. Stoller

Move all of the save/restore/remove physical/virtual stuff from libdb

into Experiment.pm.
Also a few little protogeni additions that might get whacked later.
parent e268f181
......@@ -21,6 +21,7 @@ use User;
use Project;
use Group;
use Node;
use Interface;
use Logfile;
use English;
use Data::Dumper;
......@@ -28,8 +29,8 @@ use File::Basename;
use overload ('""' => 'Stringify');
use libtblog_simple;
use vars qw($EXPT_PRELOAD $EXPT_START $EXPT_SWAPIN
$EXPT_SWAPOUT $EXPT_SWAPMOD
use vars qw($EXPT_PRELOAD $EXPT_START $EXPT_SWAPIN $EXPT_SWAPUPDATE
$EXPT_SWAPOUT $EXPT_SWAPMOD @physicalTables @virtualTables
@EXPORT_OK);
# Configure variables
......@@ -58,14 +59,83 @@ $EXPT_START = TBDB_STATS_START();
$EXPT_SWAPIN = TBDB_STATS_SWAPIN();
$EXPT_SWAPOUT = TBDB_STATS_SWAPOUT();
$EXPT_SWAPMOD = TBDB_STATS_SWAPMODIFY();
$EXPT_SWAPUPDATE = TBDB_STATS_SWAPUPDATE();
# For stats gathering code.
my $EXPT_STARTCLOCK;
my $EXPT_RESOURCESHOSED = 0;
# Why, why, why?
@EXPORT_OK = qw($EXPT_PRELOAD $EXPT_START
$EXPT_SWAPIN $EXPT_SWAPOUT $EXPT_SWAPMOD);
@EXPORT_OK = qw($EXPT_PRELOAD $EXPT_START $EXPT_SWAPUPDATE
$EXPT_SWAPIN $EXPT_SWAPOUT $EXPT_SWAPMOD
@physicalTables @virtualTables);
#
# List of tables used for experiment removal/backup/restore.
#
@virtualTables = ("virt_nodes",
"virt_lans",
"virt_lan_lans",
"virt_lan_settings",
"virt_lan_member_settings",
"virt_trafgens",
"virt_agents",
"virt_routes",
"virt_vtypes",
"virt_programs",
"virt_node_desires",
"virt_node_startloc",
"virt_simnode_attributes",
"virt_user_environment",
"virt_parameters",
# vis_nodes is locked during update in prerender, so we
# will get a consistent dataset when we backup.
"vis_nodes",
"vis_graphs",
"nseconfigs",
"eventlist",
"event_groups",
"virt_firewalls",
"firewall_rules",
"virt_tiptunnels",
"ipsubnets");
@physicalTables = ("delays",
"ipport_ranges",
"v2pmap",
"linkdelays",
"traces",
"portmap");
# These are slots in the node table that need to be restored.
my @nodetable_fields = ("def_boot_osid",
"def_boot_path",
"def_boot_cmd_line",
"temp_boot_osid",
"next_boot_osid",
"next_boot_path",
"next_boot_cmd_line",
"pxe_boot_path",
"bootstatus",
"ready",
"rpms",
"deltas",
"tarballs",
"startupcmd",
"startstatus",
"failureaction",
"routertype",
"op_mode",
"op_mode_timestamp",
"allocstate",
"allocstate_timestamp",
"next_op_mode",
"osid",
"ipport_low",
"ipport_next",
"ipport_high",
"sshdport",
"rtabid");
# Hmm, this is silly.
if ($EVENTSYS) {
......@@ -2323,6 +2393,9 @@ sub Swap($$;$$)
$op = "out";
}
elsif ($which eq $EXPT_SWAPMOD) {
$op = "modify";
}
elsif ($which eq $EXPT_SWAPUPDATE) {
$op = "update";
}
......@@ -2461,7 +2534,6 @@ sub NodeList($;$$)
my $eid = $self->eid();
@nodenames = ExpNodes($pid, $eid);
return @nodenames
if (defined($namesonly) && $namesonly);
......@@ -2807,11 +2879,25 @@ sub BackupVirtualState($)
my $pid = $self->pid();
my $eid = $self->eid();
my $vstateDir = $self->WorkDir() . "/vstate";
my $errors = 0;
return -1
if (TBExptBackupVirtualState($pid, $eid));
if (! -e $vstateDir) {
mkdir($vstateDir, 0777)
or return -1;
return 0;
chmod(0777, $vstateDir)
or return -1;
}
foreach my $table (@virtualTables) {
DBQueryWarn("SELECT * FROM $table ".
"WHERE pid='$pid' AND eid='$eid' ".
"INTO OUTFILE '$vstateDir/$table' ")
or $errors++;
}
return $errors;
}
sub RemoveVirtualState($)
{
......@@ -2823,11 +2909,13 @@ sub RemoveVirtualState($)
my $pid = $self->pid();
my $eid = $self->eid();
my $errors = 0;
return -1
if (TBExptRemoveVirtualState($pid, $eid));
return 0;
foreach my $table (@virtualTables) {
DBQueryWarn("DELETE FROM $table WHERE pid='$pid' AND eid='$eid'")
or $errors++;
}
return $errors;
}
sub RestoreVirtualState($)
{
......@@ -2839,11 +2927,14 @@ sub RestoreVirtualState($)
my $pid = $self->pid();
my $eid = $self->eid();
my $vstateDir = $self->WorkDir() . "/vstate";
my $errors = 0;
return -1
if (TBExptRestoreVirtualState($pid, $eid));
return 0;
foreach my $table (@virtualTables) {
DBQueryWarn("LOAD DATA INFILE '$vstateDir/$table' INTO TABLE $table")
or $errors++;
}
return $errors;
}
sub ClearBackupState($)
{
......@@ -2855,8 +2946,15 @@ sub ClearBackupState($)
my $pid = $self->pid();
my $eid = $self->eid();
my $workdir = $self->WorkDir();
my $pstateDir = $workdir . "/pstate";
my $vstateDir = $workdir . "/vstate";
system("/bin/rm -rf $pstateDir")
if (-e $pstateDir);
system("/bin/rm -rf $vstateDir")
if (-e $vstateDir);
TBExptClearBackupState($pid, $eid);
return 0;
}
sub RemovePhysicalState($)
......@@ -2869,10 +2967,167 @@ sub RemovePhysicalState($)
my $pid = $self->pid();
my $eid = $self->eid();
my $errors = 0;
return -1
if (Lan->DestroyExperimentLans($self) != 0);
my @pnodenames = ExpNodes($pid, $eid, 0, 1);
if (@pnodenames) {
my $clause = join(" or ", map("node_id='$_'", @pnodenames));
# These tables are also cleaned in nfree.
foreach my $table ("vinterfaces", "interface_settings") {
DBQueryWarn("delete from $table where $clause")
or $errors++;
}
# Interfaces table is special. Also cleaned in nfree.
DBQueryWarn("update interfaces set IP='',IPaliases=NULL,mask=NULL,".
" rtabid='0',vnode_id=NULL " .
"where ($clause) and ".
" role='" . TBDB_IFACEROLE_EXPERIMENT() . "' ")
or $errors++;
}
foreach my $table (@physicalTables) {
DBQueryWarn("DELETE FROM $table WHERE pid='$pid' AND eid='$eid'")
or $errors++;
}
return $errors;
}
sub BackupPhysicalState($)
{
my ($self) = @_;
# Must be a real reference.
return -1
if (! ref($self));
my $pid = $self->pid();
my $eid = $self->eid();
my $pstateDir = $self->WorkDir() . "/pstate";
my $errors = 0;
if (! -e $pstateDir) {
mkdir($pstateDir, 0777)
or return 1;
chmod(0777, $pstateDir)
or return 1;
}
return -1
if (TBExptRemovePhysicalState($pid, $eid));
if (Lan->BackupExperimentLans($self, $pstateDir) != 0);
my @pnodenames = ExpNodes($pid, $eid, 0, 1);
if (@pnodenames) {
my $clause = join(" or ", map("node_id='$_'", @pnodenames));
foreach my $table ("vinterfaces", "interface_settings", "nodes") {
DBQueryWarn("select * from $table where $clause ".
"into outfile '$pstateDir/$table' ")
or $errors++;
}
# interfaces table is special, and this is probably wrong to do anyway
# since we overwrite columns that are fixed.
DBQueryWarn("select * from interfaces where ($clause) and ".
" role='" . TBDB_IFACEROLE_EXPERIMENT() . "' ".
"into outfile '$pstateDir/interfaces' ")
or $errors++;
}
# Reserved table is special; we do not want to bring it back in during
# the restore. We just want the info from it.
foreach my $table (@physicalTables, "reserved") {
DBQueryWarn("SELECT * FROM $table WHERE pid='$pid' AND eid='$eid' ".
"INTO OUTFILE '$pstateDir/$table' ")
or $errors++;
}
return $errors;
}
sub RestorePhysicalState($)
{
my ($self) = @_;
# Must be a real reference.
return -1
if (! ref($self));
my $idx = $self->idx();
my $pid = $self->pid();
my $eid = $self->eid();
my $pstateDir = $self->WorkDir() . "/pstate";
my $errors = 0;
return -1
if (Lan->RestoreExperimentLans($self, $pstateDir) != 0);
foreach my $table (@physicalTables, "vinterfaces", "interface_settings") {
DBQueryWarn("LOAD DATA INFILE '$pstateDir/$table' INTO TABLE $table")
or $errors++;
}
# interfaces table is special, and this is probably wrong to do anyway
# since we overwrite columns that are fixed.
if (-e "$pstateDir/interfaces") {
DBQueryWarn("load data infile '$pstateDir/interfaces' ".
"replace into table interfaces")
or $errors++;
}
return $errors
if ($errors);
#
# And bits and pieces from the reserved/node table entries, which have to
# be updated in place.
#
DBQueryWarn("create temporary table reserved_${idx} like reserved")
or return -1;
DBQueryWarn("load data infile '$pstateDir/reserved' ".
"into table reserved_${idx}")
or return -1;
my $query_result =
DBQueryWarn("select * from reserved_${idx}");
return -1
if (!$query_result);
while (my ($row) = $query_result->fetchrow_hashref()) {
my $node_id = $row->{"node_id"};
delete($row->{"node_id"});
my $sets = join(",", map("$_='" . $row->{$_} . "'", keys(%{$row})));
my $update_result =
DBQueryWarn("update reserved set $sets ".
"where node_id='$node_id' and exptidx='$idx'");
return -1
if (!$update_result);
if (!$update_result->numrows) {
print STDERR "Failed to reset reserved table entry for $node_id\n";
return -1;
}
}
DBQueryWarn("drop table reserved_${idx}");
#
# Restore the nodes table info in one shot.
#
DBQueryWarn("create temporary table nodes_${idx} like nodes")
or return -1;
DBQueryWarn("load data infile '$pstateDir/nodes' ".
"into table nodes_${idx}")
or return -1;
my $fieldlist = join(",", map("n.$_=ni.$_", @nodetable_fields));
my $update_result =
DBQueryWarn("update nodes n, nodes_${idx} ni set $fieldlist ".
"where n.node_id=ni.node_id");
return -1
if (!$update_result);
if (!$update_result->numrows) {
print STDERR "Failed to reset nodes table entries.\n";
return -1;
}
DBQueryWarn("drop table nodes_${idx}");
return 0;
}
......@@ -3383,5 +3638,38 @@ sub UnBindNonLocalUsers($)
return 0;
}
#
# Return physical interfaces for a link in an experiment.
#
sub LinkInterfaces($$$)
{
my ($self, $linkname, $pref) = @_;
my @result = ();
my $idx = $self->idx();
my $query_result =
DBQueryWarn("select i.node_id,i.uuid from virt_lans as vl ".
"left join interfaces as i on i.IP=vl.ip ".
"where vl.exptidx=$idx and vl.vname='$linkname'");
return -1
if (!$query_result || !$query_result->num_rows);
while (my ($node_id,$uuid) = $query_result->fetchrow_array()) {
my $linknode = Node->Lookup($node_id);
my $linkexp = $linknode->Reservation();
return -1
if (!defined($linkexp) || !$self->SameExperiment($linkexp));
my $interface = Interface->LookupByUUID($uuid);
return -1
if (!defined($interface));
push(@result, $interface);
}
@$pref = @result;
return 0;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -132,7 +132,7 @@ use vars qw(@ISA @EXPORT);
TBDB_STATS_SWAPIN TBDB_STATS_SWAPOUT TBDB_STATS_SWAPMODIFY
TBDB_STATS_FLAGS_IDLESWAP TBDB_STATS_FLAGS_PREMODIFY
TBDB_STATS_FLAGS_START TBDB_STATS_FLAGS_PRESWAPIN
TBDB_STATS_FLAGS_MODHOSED
TBDB_STATS_FLAGS_MODHOSED TBDB_STATS_SWAPUPDATE
TBDB_JAILIPBASE TBDB_JAILIPMASK
......@@ -192,12 +192,6 @@ use vars qw(@ISA @EXPORT);
TBNodeAdminOSID TBNodeDiskloadOSID
TBNodeType TBNodeTypeProcInfo TBNodeTypeBiosWaittime
TBExptRemoveVirtualState TBExptBackupVirtualState
TBExptRestoreVirtualState
TBExptRemovePhysicalState TBExptBackupPhysicalState
TBExptRestorePhysicalState TBExptClearBackupState
TBExptPortRange
TBDB_WIDEAREA_LOCALNODE
......@@ -252,7 +246,7 @@ require NodeType;
require Lan;
use vars qw($DBQUERY_MAXTRIES $DBCONN_MAXTRIES
$DBCONN_EXITONERR $DBQUERY_RECONNECT $DBQUERY_DEBUG
@EXPORT_OK @virtualTables @physicalTables);
@EXPORT_OK);
# Configure variables
my $TB = "@prefix@";
......@@ -641,6 +635,7 @@ sub TBDB_STATS_TERMINATE() { "destroy"; }
sub TBDB_STATS_SWAPIN() { "swapin"; }
sub TBDB_STATS_SWAPOUT() { "swapout"; }
sub TBDB_STATS_SWAPMODIFY() { "swapmod"; }
sub TBDB_STATS_SWAPUPDATE() { "swapupdate"; }
sub TBDB_STATS_FLAGS_IDLESWAP() { 0x01; }
sub TBDB_STATS_FLAGS_PREMODIFY(){ 0x02; }
sub TBDB_STATS_FLAGS_START() { 0x04; }
......@@ -2323,58 +2318,6 @@ sub TBExptContainsNodeCT($$$)
return 1;
}
#
# List of tables used for experiment removal/backup/restore.
#
@virtualTables = ("virt_nodes",
"virt_lans",
"virt_lan_lans",
"virt_lan_settings",
"virt_lan_member_settings",
"virt_trafgens",
"virt_agents",
"virt_routes",
"virt_vtypes",
"virt_programs",
"virt_node_desires",
"virt_node_startloc",
"virt_simnode_attributes",
"virt_user_environment",
"virt_parameters",
# vis_nodes is locked during update in prerender, so we
# will get a consistent dataset when we backup.
"vis_nodes",
"vis_graphs",
"nseconfigs",
"eventlist",
"event_groups",
"virt_firewalls",
"firewall_rules",
"virt_tiptunnels",
"ipsubnets");
@physicalTables = ("delays",
"ipport_ranges",
"v2pmap",
"linkdelays",
"traces",
"portmap");
#
# Clear the backup crap we create below.
#
sub TBExptClearBackupState($$)
{
my ($pid, $eid) = @_;
my $pstateDir = TBExptWorkDir($pid, $eid) . "/pstate";
my $vstateDir = TBExptWorkDir($pid, $eid) . "/vstate";
system("/bin/rm -rf $pstateDir")
if (-e $pstateDir);
system("/bin/rm -rf $vstateDir")
if (-e $vstateDir);
}
#
# Return the list of subnodes for the given node.
#
......@@ -2525,142 +2468,6 @@ sub TBNodeTypeBiosWaittime($)
return $bios_waittime;
}
#
# Remove the virtual state of an experiment from the DB,
# returning the number of queries which didn't work.
#
sub TBExptRemoveVirtualState($$)
{
my ($pid, $eid) = @_;
my $errors = 0;
foreach my $table (@virtualTables) {
DBQueryWarn("DELETE FROM $table WHERE pid='$pid' AND eid='$eid'")
or $errors++;
}
return $errors;
}
#
# Remove the physical state of an experiment from the DB,
# returning the number of queries which didn't work.
#
sub TBExptRemovePhysicalState($$)
{
my ($pid, $eid) = @_;
my $errors = 0;
my $experiment = Experiment->Lookup($pid, $eid);
return 1
if (!defined($experiment));
return 1
if (Lan->DestroyExperimentLans($experiment) != 0);
foreach my $table (@physicalTables) {
DBQueryWarn("DELETE FROM $table WHERE pid='$pid' AND eid='$eid'")
or $errors++;
}
return $errors;
}
#
# Backs up specified virtual state of pid/eid into directory in tmp.
#
sub TBExptBackupVirtualState($$)
{
my ($pid, $eid) = @_;
my $errors = 0;
my $vstateDir = TBExptWorkDir($pid, $eid) . "/vstate";
if (! -e $vstateDir) {
mkdir($vstateDir, 0777)
or return 1;
chmod(0777, $vstateDir)
or return 1;
}
foreach my $table (@virtualTables) {
DBQueryWarn("SELECT * FROM $table ".
"WHERE pid='$pid' AND eid='$eid' ".
"INTO OUTFILE '$vstateDir/$table' ")
or $errors++;
}
return $errors;
}
#
# Backs up specified physical state of pid/eid into directory in tmp.
#
sub TBExptBackupPhysicalState($$)
{
my ($pid, $eid) = @_;
my $errors = 0;
my $pstateDir = TBExptWorkDir($pid, $eid) . "/pstate";
if (! -e $pstateDir) {
mkdir($pstateDir, 0777)
or return 1;
chmod(0777, $pstateDir)
or return 1;
}
my $experiment = Experiment->Lookup($pid, $eid);
return 1
if (!defined($experiment));
return 1
if (Lan->BackupExperimentLans($experiment, $pstateDir) != 0);
foreach my $table (@physicalTables) {
DBQueryWarn("SELECT * FROM $table WHERE pid='$pid' AND eid='$eid' ".
"INTO OUTFILE '$pstateDir/$table' ")
or $errors++;
}
return $errors;
}
#
# Restores backed up virtual state of pid/eid from directory in /tmp.
#
sub TBExptRestoreVirtualState($$)
{
my ($pid, $eid) = @_;
my $errors = 0;
my $vstateDir = TBExptWorkDir($pid, $eid) . "/vstate";
foreach my $table (@virtualTables) {
DBQueryWarn("LOAD DATA INFILE '$vstateDir/$table' INTO TABLE $table")
or $errors++;
}
return $errors;
}
#
# Restores backed up virtual state of pid/eid from directory in /tmp.
#
sub TBExptRestorePhysicalState($$)
{
my ($pid, $eid) = @_;
my $errors = 0;
my $pstateDir = TBExptWorkDir($pid, $eid) . "/pstate";
my $experiment = Experiment->Lookup($pid, $eid);
return 1
if (!defined($experiment));
return 1
if (Lan->RestoreExperimentLans($experiment, $pstateDir) != 0);
foreach my $table (@physicalTables) {
DBQueryWarn("LOAD DATA INFILE '$pstateDir/$table' INTO TABLE $table")
or $errors++;
}
return $errors;
}
#
# Restores backed up virtual state of pid/eid from directory in /tmp.
#
......
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