From 4003932026d68baf4b45229eddbd424faf351f83 Mon Sep 17 00:00:00 2001 From: "David M. Johnson" Date: Mon, 4 Apr 2011 00:03:52 -0600 Subject: [PATCH] Add dynamic, per-experiment blobs. Add tables for client side service blobs. Per-experiment blobs can be created by the parser, and are inserted into the blobs table at swapin based on what's in virt_blobs. We go to some effort to keep any existing filename<->uuid mapping in teh blobs table so that any caching already done by the server and client in a previous download of a blob remains intact. We also remove blobs on experiment modify that are no longer necessary. Finally, we remove dynamic blobs at swapout. --- db/Experiment.pm.in | 133 +++++++++++++++++++++++++++++++++++++++- db/VirtExperiment.pm.in | 26 ++++++++ db/xmlconvert.in | 12 ++++ tbsetup/tbswap.in | 17 +++++ 4 files changed, 187 insertions(+), 1 deletion(-) diff --git a/db/Experiment.pm.in b/db/Experiment.pm.in index 5927c2f47..f515e9617 100644 --- a/db/Experiment.pm.in +++ b/db/Experiment.pm.in @@ -138,7 +138,11 @@ $EXPT_RESOURCESHOSED = 0; "firewall_rules", "elabinelab_attributes", "virt_tiptunnels", - "ipsubnets"); + "ipsubnets", + "virt_blobs", + "virt_client_service_ctl", + "virt_client_service_hooks", + "virt_client_service_opts"); %physicalTables = ("delays" => ["node_id", "vname", "vnode0", "vnode1"], "ipport_ranges" => undef, @@ -3507,6 +3511,133 @@ sub SetupProgramAgents($) return 0; } +# +# Convert virt_blobs into real blobs. We go to some pain to keep the same +# filenames associated with the same uuid to make sure caching doesn't get +# needlessly broken on the client (on a modify). +# +sub UploadBlobs($$) +{ + my ($self,$update) = @_; + + # Must be a real reference. + return -1 + if (! ref($self)); + + my $pid = $self->pid(); + my $eid = $self->eid(); + my $idx = $self->idx(); + my $virtexp = $self->GetVirtExperiment(); + return -1 + if (!defined($virtexp)); + + my %blobs = (); + my %virt_blobs = (); + + # + # Grab the existing blobs tied to our experiment + # + my $qres = DBQueryFatal("select uuid,filename,vblob_id" . + " from blobs where exptidx=$idx"); + if (defined($qres) && $qres->numrows()) { + while (my ($uuid,$filename,$vblob_id) = $qres->fetchrow_array()) { + $blobs{$vblob_id} = [ 0,$uuid,$filename ]; + } + } + + # + # Now grab our experiment virt blobs + # + my $virt_blobs_table = $virtexp->Table("virt_blobs"); + foreach my $row ($virt_blobs_table->Rows()) { + my $vblob_id = $row->vblob_id(); + my $filename = $row->filename(); + + $virt_blobs{$vblob_id} = $filename; + } + + # + # Make sure each virt_blob is in the blobs table! + # + foreach my $vblob_id (keys(%virt_blobs)) { + my $vfilename = $virt_blobs{$vblob_id}; + + if (exists($blobs{$vblob_id}) + && $blobs{$vblob_id}->[2] eq $vfilename) { + # this one is a keeper, so mark it! + $blobs{$vblob_id}->[0] = 1; + } + else { + my $found = 0; + foreach my $rvblob_id (keys(%blobs)) { + # if this one's a keeper, skip it! + next + if ($blobs{$rvblob_id}->[0]); + + # if the filenames match, we adjust the vblob_id field + # in the blobs table to match what we have -- this leaves + # the uuid<->filename mapping intact + if ($blobs{$rvblob_id}->[2] eq $vfilename) { + my $uuid = $blobs{$rvblob_id}->[1]; + $blobs{$vblob_id} = [ 1,$blobs{$rvblob_id}->[1], + $blobs{$rvblob_id}->[2] ]; + DBQueryFatal("replace into blobs (uuid,vblob_id)" . + " values ('$uuid','$vblob_id')"); + $found = 1; + last; + } + } + + if (!$found) { + # need to add this blob fresh! + my $swapperuid = $experiment->swapper(); + DBQueryFatal("insert into blobs" . + " (uuid,filename,owner_uid,vblob_id,exptidx)" . + " values (UUID(),'$vfilename','$swapperuid'," . + " '$vblob_id',$idx)"); + } + } + } + + # + # Only remove real blobs if we're done using them (i.e., on a modify) + # + if ($update) { + foreach my $vblob_id (keys(%blobs)) { + my ($keep,$uuid,$filename) = @{$blobs{$vblob_id}}; + DBQueryFatal("delete from blobs" . + " where exptidx=$idx and vblob_id='${vblob_id}'"); + } + } + + return 0; +} + +# +# Remove any real blobs that were a result of a virt blob (i.e., those +# blobs that have our exptidx and a valid vblob_id). +# +sub RemoveBlobs($$) +{ + my ($self) = @_; + + # Must be a real reference. + return -1 + if (! ref($self)); + + my $idx = $self->idx(); + + my $qres = DBQueryFatal("delete from blobs" . + " left join virt_blobs as vblobs" . + " on blobs.vblob_id=vblobs.vblob_id" . + " where blobs.exptidx=$idx" . + " and vblobs.vblob_id is not NULL"); + + # XXX: probably should clean out blob_files stuff too! + + return 0; +} + # # Seed the virt_agents table. Each lan/link needs an agent to handle # changes to delays or other link parameters, and that agent (might be diff --git a/db/VirtExperiment.pm.in b/db/VirtExperiment.pm.in index a5ead58cd..89a0f20bb 100644 --- a/db/VirtExperiment.pm.in +++ b/db/VirtExperiment.pm.in @@ -73,6 +73,11 @@ my $debug = 0; "virt_parameters" => [ "name", "value" ], "virt_paths" => [ "pathname", "segmentname"], "experiment_blobs" => [ "path", "action" ], + "virt_blobs" => [ "vblob_id", "filename" ], + "virt_client_service_ctl" => [ "vnode", "service_idx", "env", "whence" ], + "virt_client_service_hooks"=> [ "vnode", "service_idx", "env", "whence", + "hook_vblob_id" ], + "virt_client_service_opts" => [ "vnode", "opt_name", "opt_value" ], ); # @@ -1198,6 +1203,27 @@ package VirtExperiment::VirtTableRow::experiment_blobs; use vars qw(@ISA); @ISA = "VirtExperiment::VirtTableRow"; use VirtExperiment; +use VirtExperiment; + +package VirtExperiment::VirtTableRow::virt_blobs; +use vars qw(@ISA); +@ISA = "VirtExperiment::VirtTableRow"; +use VirtExperiment; + +package VirtExperiment::VirtTableRow::virt_client_service_ctl; +use vars qw(@ISA); +@ISA = "VirtExperiment::VirtTableRow"; +use VirtExperiment; + +package VirtExperiment::VirtTableRow::virt_client_service_hooks; +use vars qw(@ISA); +@ISA = "VirtExperiment::VirtTableRow"; +use VirtExperiment; + +package VirtExperiment::VirtTableRow::virt_client_service_opts; +use vars qw(@ISA); +@ISA = "VirtExperiment::VirtTableRow"; +use VirtExperiment; # _Always_ make sure that this 1 is at the end of the file... 1; diff --git a/db/xmlconvert.in b/db/xmlconvert.in index 999101624..8d038f807 100644 --- a/db/xmlconvert.in +++ b/db/xmlconvert.in @@ -125,6 +125,18 @@ my %virtual_tables = "experiment_blobs" => { rows => undef, tag => "blobs", row => "blob"}, + "virt_blobs" => { rows => undef, + tag => "virt_blobs", + row => "virt_blob"}, + "virt_client_service_ctl" => { rows => undef, + tag => "virt_client_service_ctl", + row => "virt_client_service_ctlrow"}, + "virt_client_service_hooks"=> { rows => undef, + tag => "virt_client_service_hooks", + row => "virt_client_service_hook"}, + "virt_client_service_opts" => { rows => undef, + tag => "virt_client_service_opts", + row => "virt_client_service_opt"}, # This is a fake table. See below. If we add more, lets generalize. "external_sourcefiles" => { rows => undef, tag => "nsfiles", diff --git a/tbsetup/tbswap.in b/tbsetup/tbswap.in index a3ae0de28..cd85565ca 100644 --- a/tbsetup/tbswap.in +++ b/tbsetup/tbswap.in @@ -575,6 +575,11 @@ sub doSwapout($) { $experiment->DeleteInternalProgramAgents(); } + if ($type >= RETRY) { + print "Removing dynamic blobs.\n"; + $experiment->RemoveBlobs(); + } + if ($type >= CLEANUP) { # # Undo plab in elab specialness. @@ -1101,6 +1106,18 @@ sub doSwapin($) { } TBDebugTimeStamp("tarfiles_setup finished"); + # + # Handle virt blobs. + # + if ($type >= RETRY) { + print "Creating virt blobs.\n"; + $experiment->UploadBlobs(0); + } + elsif ($type == MODIFY) { + print "Updating virt blobs.\n"; + $experiment->UploadBlobs(1); + } + # # If there are any Plab dslice nodes in the experiment, create the # dslice now -- GitLab