Commit 195fa852 authored by Leigh B Stoller's avatar Leigh B Stoller
Browse files

Several changes:

1. Encapsulate rspec2genilib in a library function.

2. Add a "check" option UpdateDiskImage() to see if any changes are
   actually going to be made so that we do not create a new version of a
   profile that is identical to the previous version.

3. Do not ever create a new version of a script based profile since we
   can never change the script (after a disk snapshot). Unless it is a
   portal converted script, we can do that by changing the rspec and
   then generating a new script.
parent 97c85e69
......@@ -66,6 +66,7 @@ my $TBOPS = "@TBOPSEMAIL@";
my $OURDOMAIN = "@OURDOMAIN@";
my $MYURN = "urn:publicid:IDN+${OURDOMAIN}+authority+cm";
my $MAINSITE = @TBMAINSITE@;
my $CONVERTER = "$TB/bin/rspec2genilib";
# Concat id/vers.
sub versid($)
......@@ -939,9 +940,9 @@ sub Unlock($)
# specified node, and if $all is set, we change all nodes with the
# same original disk image as the specified node.
#
sub UpdateDiskImage($$@)
sub UpdateDiskImage($$$$$)
{
my ($self, $node_id, $newimage, $all) = @_;
my ($self, $node_id, $newimage, $all, $impotent) = @_;
my $rspec = GeniXML::Parse($self->rspec());
if (! defined($rspec)) {
print STDERR "UpdateDiskImage: Could not parse rspec\n";
......@@ -952,78 +953,88 @@ sub UpdateDiskImage($$@)
# all with the same image.
#
my @nodes = ();
my @list = ();
my $node;
# First find the specified node.
# First find the specified node and generate list to examine.
foreach my $ref (GeniXML::FindNodes("n:node", $rspec)->get_nodelist()) {
if (GeniXML::GetVirtualId($ref) eq $node_id) {
$node = $ref;
last;
push(@list, $node);
}
elsif ($all) {
push(@list, $ref);
}
}
if (!defined($node)) {
print STDERR "$node_id not in rspec\n";
return -1;
}
if ($all) {
#
# Pull out the disk url/urn of the specified node.
#
my $Odiskref = GeniXML::GetDiskImage($node);
my $image_urn;
my $image_url;
if (defined($Odiskref)) {
$image_url = GeniXML::GetText("url", $Odiskref);
$image_urn = GeniXML::GetText("name", $Odiskref);
if (defined($image_url) || defined($image_urn)) {
# Watch for url in the name, flipflop.
if (defined($image_urn) && $image_urn =~ /^http/) {
$image_url = $image_urn;
$image_urn = undef;
}
#
# Pull out the disk url/urn of the specified node.
#
my $Odiskref = GeniXML::GetDiskImage($node);
my $image_urn;
my $image_url;
if (defined($Odiskref)) {
$image_url = GeniXML::GetText("url", $Odiskref);
$image_urn = GeniXML::GetText("name", $Odiskref);
if (defined($image_url) || defined($image_urn)) {
# Watch for url in the name, flipflop.
if (defined($image_urn) && $image_urn =~ /^http/) {
$image_url = $image_urn;
$image_urn = undef;
}
}
}
#
# Now find all nodes using the same disk urn/url and change.
#
foreach my $ref (@list) {
my $diskref = GeniXML::GetDiskImage($ref);
#
# Now find all nodes using the same disk urn/url and change.
# If the both this node and the original node did not
# specify a disk image, then we update it.
#
foreach my $ref (GeniXML::FindNodes("n:node", $rspec)->get_nodelist()) {
my $diskref = GeniXML::GetDiskImage($ref);
#
# If the both this node and the original node did not
# specify a disk image, then we update it.
#
if (!defined($diskref)) {
push(@nodes, $ref)
if (!defined($Odiskref));
next;
}
my $this_url = GeniXML::GetText("url", $diskref);
my $this_urn = GeniXML::GetText("name", $diskref);
next
if (!(defined($image_url) || defined($image_urn)));
if (!defined($diskref)) {
push(@nodes, $ref)
if (!defined($Odiskref));
next;
}
my $this_url = GeniXML::GetText("url", $diskref);
my $this_urn = GeniXML::GetText("name", $diskref);
next
if (!(defined($image_url) || defined($image_urn)));
# Watch for url in the name, flipflop.
if (defined($this_urn) && $this_urn =~ /^http/) {
$this_url = $this_urn;
$this_urn = undef;
}
if (defined($image_url)) {
push(@nodes, $ref)
if ((defined($this_url) && $this_url eq $image_url));
}
else {
push(@nodes, $ref)
if (defined($this_urn) && $this_urn eq $image_urn);
}
# Watch for url in the name, flipflop.
if (defined($this_urn) && $this_urn =~ /^http/) {
$this_url = $this_urn;
$this_urn = undef;
}
if (defined($image_url)) {
# Watch for actually needing to change, for impotent mode.
# Might not change if the cluster is not doing image
# versioning.
push(@nodes, $ref)
if (defined($this_url) && $this_url eq $image_url &&
$this_url ne $newimage);
}
else {
# Watch for actually needing to change, for impotent mode.
# Might not change if the cluster is not doing image
# versioning.
push(@nodes, $ref)
if (defined($this_urn) && $this_urn eq $image_urn &&
$this_urn ne $newimage);
}
}
else {
@nodes = ($node);
}
if (!@nodes) {
print STDERR "Could not find any nodes to update disk image\n";
return -1;
# Impotent mode, return number of nodes to be changed.
if ($impotent) {
return scalar(@nodes);
}
return 0
if (!@nodes);
foreach my $node (@nodes) {
GeniXML::SetDiskImage($node, $newimage);
}
......@@ -1752,6 +1763,38 @@ sub NodeClientIDs($)
return values(%result);
}
#
# Run a portal converted profile rspec though the converter to update
# the geni-lib script.
#
sub Convert2Genilib($)
{
my ($self) = @_;
my $profileid = $self->profileid();
my $version = $self->version();
my ($in, $filename) = tempfile("/tmp/convertXXXXX", UNLINK => 1);
if (!defined($in)) {
print STDERR "Could not open temporary file for rspec\n";
return -1;
}
print $in $self->rspec();
my $output = emutil::ExecQuiet("$CONVERTER -r $filename");
if ($?) {
print STDERR $output;
print STDERR "*** Could not convert rspec to geni-lib\n";
return -1;
}
my $safe_script = DBQuoteSpecial($output);
return -1
if (! DBQueryWarn("update apt_profile_versions set ".
" script=$safe_script ".
"where profileid='$profileid' and ".
" version='$version'"));
$self->{'DBROW'}->{'script'} = $output;
return 0;
}
###################################################################
package APT_Profile::ImageInfo;
use emdb;
......
......@@ -718,32 +718,60 @@ sub DoSnapshot()
$errcode = -2;
goto bad;
}
elsif (defined($update_profile)) {
#
# If successful, we create a new version of the profile and
# update the rspec to reflect the new image version. Note
# that we expect the CM is doing image versioning, so do not
# bother to check if the image version is actually new.
#
if ($doversions) {
$profile = $profile->NewVersion($this_user);
if (!defined($profile)) {
print STDERR "Could not create new profile version\n";
$webtask->Exited(70)
if (defined($webtask));
exit(1);
}
}
#
# We cannot change a geni-lib script profile, so no need to do this.
# But we can change a portal converted profile.
#
elsif (defined($update_profile) &&
(!defined($profile->script()) || $profile->portal_converted())) {
#
# New image. Might not have changed if the cluster is not doing
# image versions.
#
# DoImageTrackerStuff determined that we use whatever the cluster
# tells us, cause it is the home of the image.
$copyback_urn = $version_urn
#
my $newimage = $version_urn
if ($usetracker && !defined($copyback_urn));
# And fall back to url
$newimage = $version_url
if (!defined($newimage));
#
# Okay, is the rspec going to change. This is kinda annoying to
# figure out, so lets just run the code in impotent mode and have
# it tell us the number of nodes that will get updated.
#
my $changed =
$profile->UpdateDiskImage($node_id, $newimage,
($update_profile eq "all" ? 1 : 0), 1);
$profile->UpdateDiskImage($node_id,
(defined($copyback_urn) ?
$copyback_urn : $version_url),
($update_profile eq "all" ? 1 : 0));
$profile->InsertImageRecords();
if ($changed > 0) {
#
# Create a new version of the profile and update the rspec
# to reflect the new image version.
#
if ($doversions) {
$profile = $profile->NewVersion($this_user);
if (!defined($profile)) {
print STDERR "Could not create new profile version\n";
$webtask->Exited(70)
if (defined($webtask));
exit(1);
}
}
$profile->UpdateDiskImage($node_id, $newimage,
($update_profile eq "all" ? 1 : 0), 0);
$profile->InsertImageRecords();
#
# For a portal converted profile, we need to regen the script.
#
if ($profile->portal_converted()) {
if ($profile->Convert2Genilib() != 0) {
fatal("Could not convert rspec to geni-lib");
}
}
}
}
$instance->SetStatus("ready");
$aggregate->SetStatus("ready");
......
......@@ -434,9 +434,32 @@ sub CreateProfile()
$profile->Delete(1);
fatal("Did not get an image for $node_id");
}
if ($profile->UpdateDiskImage($node_id, $newimage, 0)) {
$profile->Delete(1);
fatal("Could not update image in rspec for $node_id; $newimage;");
#
# We cannot change a geni-lib script profile, so no need to do this.
# But we can change a portal converted profile (or rspec).
#
if (!defined($profile->script()) || $profile->portal_converted()) {
#
# See if anything is actually going to change, since the cluster
# might not be doing image versioning.
#
my $changed = $profile->UpdateDiskImage($node_id, $newimage, 0, 1);
if ($changed > 0) {
if ($profile->UpdateDiskImage($node_id, $newimage, 0, 0)) {
$profile->Delete(1);
fatal("Could not update image in rspec ".
"for $node_id; $newimage;");
}
#
# For a portal converted profile, we need to regen the script.
#
if ($profile->portal_converted()) {
if ($profile->Convert2Genilib() != 0) {
$profile->Delete(1);
fatal("Could not convert rspec to geni-lib");
}
}
}
}
# Tell web interface cloning has started.
$pwebtask->cloning(1);
......
Supports Markdown
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