diff --git a/db/Image.pm.in b/db/Image.pm.in index 2def9f6332ce6c7585aadca354ed48b85060a531..7d3e1c239727435f0b94d07c234fb5488dbb6f79 100644 --- a/db/Image.pm.in +++ b/db/Image.pm.in @@ -212,7 +212,7 @@ sub ActiveImages($) # sub ListAll($$$) { - my ($class, $format, $pid); + my ($class, $format, $pid) = @_; my @result = (); my $clause = ""; @@ -886,6 +886,36 @@ sub GetUpdate($$) return -1; } +# +# Get the disk offset at which the image will be loaded. +# For a "whole disk" (loadpart == 0) image, it is always 0. +# For a "partition" image, it depends on the MBR type of the image. +# +# Returns -1 if the offset could not be determined (e.g., unknown MBR). +# +sub GetDiskOffset($) +{ + my ($self) = @_; + + # XXX these should come out of the DB or not exist at all! + my %mbr = ( + "1" => [0, 63, 6281415, 12562830, 12819870], + "2" => [0, 63, 12305853, 24611643, 26712000] + ); + + # Must be a real reference. + return -1 + if (! ref($self)); + + return -1 + if (! exists($mbr{$self->mbr_version()})); + + return -1 + if ($self->loadpart() > 4); + + return $mbr{$self->mbr_version()}[$self->loadpart()]; +} + # # Mark the update time in the record, # @@ -950,24 +980,51 @@ sub SetHash($$) return 0; } +# +# Set the size. +# +sub SetSize($$) +{ + my ($self, $size) = @_; + + # Must be a real reference. + return -1 + if (! ref($self)); + + my $imageid = $self->imageid(); + + return -1 + if (! DBQueryWarn("update images set size=$size " . + "where imageid='$imageid'")); + + return 0; +} + # # Set the sector range of an image. +# Note that lba_size and reloc flag are left alone unless explicitly specified. # -sub SetRange($$$;$) +sub SetRange($$$;$$) { - my ($self,$start,$end,$ssize) = @_; + my ($self,$start,$end,$ssize,$isreloc) = @_; # Must be a real reference. return -1 if (! ref($self)); my $imageid = $self->imageid(); - $ssize = 512 - if (!defined($ssize)); + + my $clause = ""; + if (defined($ssize)) { + $clause .= ",lba_size=$ssize"; + } + if (defined($isreloc)) { + $clause .= ",relocatable=$isreloc"; + } return -1 if (! DBQueryWarn("update images set ". - " lba_low=$start,lba_high=$end,lba_size=$ssize ". + " lba_low=$start,lba_high=$end$clause ". "where imageid='$imageid'")); return 0; diff --git a/sql/database-create.sql b/sql/database-create.sql index 33c9d4977a1e80dafe432aa218983cac181e7354..34ef99a1dfff9e9fd779dc9e3d3afb40a5fa0b27 100644 --- a/sql/database-create.sql +++ b/sql/database-create.sql @@ -1930,6 +1930,7 @@ CREATE TABLE `images` ( `lba_low` bigint(20) unsigned NOT NULL default '0', `lba_high` bigint(20) unsigned NOT NULL default '0', `lba_size` int(10) unsigned NOT NULL default '512', + `relocatable` tinyint(1) NOT NULL default '0', `locked` datetime default NULL, `locker_pid` int(11) default '0', `metadata_url` tinytext, diff --git a/sql/database-fill.sql b/sql/database-fill.sql index c2694754188902a789f64b4fe3b25e34b0afe348..069bfb616541738fe75a85f5af80c56dd4880364 100644 --- a/sql/database-fill.sql +++ b/sql/database-fill.sql @@ -1061,6 +1061,7 @@ REPLACE INTO `table_regex` VALUES ('images','size','int','redirect','default:big REPLACE INTO `table_regex` VALUES ('images','lba_low','int','redirect','default:bigint',0,0,NULL); REPLACE INTO `table_regex` VALUES ('images','lba_high','int','redirect','default:bigint',0,0,NULL); REPLACE INTO `table_regex` VALUES ('images','lba_size','int','redirect','default:int',0,0,NULL); +REPLACE INTO table_regex VALUES ('images','relocatable','text','redirect','default:boolean',0,0,NULL); REPLACE INTO table_regex VALUES ('node_types','new_type','text','redirect','default:tinytext',0,0,NULL); REPLACE INTO table_regex VALUES ('node_types','node_type','text','regex','^[-\\w]+$',1,30,NULL); REPLACE INTO table_regex VALUES ('node_types','class','text','regex','^[\\w]+$',1,30,NULL); diff --git a/sql/updates/4/392 b/sql/updates/4/392 new file mode 100644 index 0000000000000000000000000000000000000000..9a8129a415fea0aa5fefbfffaac3b5d48679b397 --- /dev/null +++ b/sql/updates/4/392 @@ -0,0 +1,26 @@ +# +# Add the relocatable flag to indicate whether the lba_low field must +# be respected (0) or whether the image is "position independent" (1). +# +use strict; +use libdb; + +sub DoUpdate($$$) +{ + my ($dbhandle, $dbname, $version) = @_; + + if (!DBSlotExists("images", "relocatable")) { + DBQueryFatal("ALTER TABLE images ADD ". + "`relocatable` tinyint(1) NOT NULL default '0' ". + " AFTER lba_size"); + + DBQueryFatal("REPLACE INTO table_regex VALUES ". + "('images','relocatable','text','redirect',". + "'default:boolean',0,0,NULL)"); + } + return 0; +} + +# Local Variables: +# mode:perl +# End: diff --git a/utils/imageinfo.in b/utils/imageinfo.in index 9799bbae3929ce6cd90603bb1a73d2cfaee77507..2093a60929680308396f8bde326d0e8b888c9cb3 100644 --- a/utils/imageinfo.in +++ b/utils/imageinfo.in @@ -1,6 +1,6 @@ #!/usr/bin/perl -w # -# Copyright (c) 2012 University of Utah and the Flux Group. +# Copyright (c) 2012-2014 University of Utah and the Flux Group. # # {{{EMULAB-LICENSE # @@ -138,21 +138,32 @@ if (! -R $imagepath) { } } -my ($isize, $imtime, $secmin, $secmax); +my ($isize, $imtime, $secmin, $secmax, $relocatable); # -# Use imagedump to get the sector range. It prints: +# Use imagedump to get the sector range and whether the image is relocatable. +# It prints: # ... +# 1 relocations covering 276 bytes # covered sector range: [0-12305790] # ... +# Note that even if an image has no relocations, it might still be relocatable. +# But, this is the best we can do! # +$relocatable = 0; if ($showrange) { if (-x $imagedump) { foreach my $line (`$imagedump $imagepath 2>&1`) { if ($line =~ /covered sector range: \[(\d+)-(\d+)\]/) { $secmin = $1; $secmax = $2; - last; + next; + } + if ($line =~ /(\d+) relocations covering/) { + if ($1 > 0) { + $relocatable = 1; + } + next; } } } @@ -198,6 +209,7 @@ if ($showall) { printf "minsect=%lu\n", $secmin; printf "maxsect=%lu\n", $secmax; printf "secsize=512\n"; + printf "relocatable=%d\n", $relocatable; } exit(0);