Commit 33b312d7 authored by Leigh Stoller's avatar Leigh Stoller

Plumb multi image load through from the NS frontend. In other words,

you can do this in your NS file:

tb-set-node-loadlist $myboss FBSD73-S2,FBSDXX-FOO

Note that this does not replace tb-set-node-os(), cause that is a
little too special. So in practice, you would do:

tb-set-node-os $myboss FBSD73-STD
tb-set-node-loadlist $myboss FBSD73-S2,FBSDXX-FOO
parent d4181694
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
package libossetup;
......@@ -164,7 +164,7 @@ sub osmap($$;$)
# To avoid writing out all the methods.
sub AUTOLOAD {
my $self = shift;
my $type = ref($self) or die("$self is not an object\n");
my $type = ref($self) or die("$self is not an object");
my $name = $AUTOLOAD;
$name =~ s/.*://; # strip fully-qualified portion
......@@ -192,9 +192,9 @@ sub OperationList($)
# Setup a reload of a node if we can find an image.
# This goo constructs a hashed array of lists.
#
sub SetupReload($$$)
sub SetupReload($$$$)
{
my ($self, $node, $osinfo) = @_;
my ($self, $node, $osinfo, $auxload) = @_;
my $type = $node->type();
#
......@@ -210,8 +210,23 @@ sub SetupReload($$$)
}
if ((my $image = $osinfo->MapToImage($type))) {
# Mark this node as needing this image.
$node->_loadimage($image);
#
# We support aux image loading, but have to distingush between a boot
# load and an aux load, since an aux load should not change what is
# actually booted.
#
if ($auxload) {
if (!defined($node->_loadimages())) {
$node->_loadimages([]);
}
my @list = @{ $node->_loadimages() };
push(@list, $image);
$node->_loadimages(\@list);
}
else {
$node->_loadimages(undef);
$node->_loadimage($image);
}
$node->_setupoperation($RELOAD);
}
else {
......@@ -334,11 +349,9 @@ sub SetOS($$)
my $imageable = $node->imageable();
my $osid = $node->def_boot_osid();
my $osinfo = OSinfo->Lookup($osid);
my $loadlist = $node->loadlist();
my $experiment = $self->experiment();
my $pid = $experiment->pid();
# Do we use def_boot_path anymore?
my $bootpath = defined($node->def_boot_path()) &&
$node->def_boot_path() ne "";
die_noretry("Could not map $osid to its object!")
if (!defined($osinfo));
......@@ -358,7 +371,7 @@ sub SetOS($$)
$imageable = 1;
}
if (!$bootpath && $imageable) {
if ($imageable) {
#
# These checks are not necessary if the front end and web page
# are doing the right thing, but lets be careful anyway.
......@@ -366,72 +379,100 @@ sub SetOS($$)
if (! $osinfo) {
die_noretry("$node has no bootpath and no def_boot_osid set!");
}
$self->SetOSAux($node, $osinfo, 0);
#
# If there is an actual path, its an OSKit kernel not an image.
# Now look for additional loads.
#
if (! defined($osinfo->path()) || $osinfo->path() eq "") {
my $nextosinfo;
if ($loadlist) {
my @osnamelist = split(",", $loadlist);
foreach my $osname (@osnamelist) {
my $osinfo = OSinfo->Lookup($pid, $osname) ||
OSinfo->LookupByName($osname);
die_noretry("Could not map $osname to its object!")
if (!defined($osinfo));
$self->SetOSAux($node, $osinfo, 1);
}
}
}
# Remember this for later.
$node->_bootosinfo($osinfo);
print STDERR "$node_id - $osinfo\n"
if ($self->debug());
}
#
# Helper for above.
#
sub SetOSAux($$$$)
{
my ($self, $node, $osinfo, $auxload) = @_;
my $node_id = $node->node_id();
my $experiment = $self->experiment();
my $pid = $experiment->pid();
#
# If there is an actual path, its an OSKit kernel not an image.
#
if (! defined($osinfo->path()) || $osinfo->path() eq "") {
my $nextosinfo;
#
# Not an OSKit kernel.
#
if ($osinfo->IsGeneric()) {
#
# Not an OSKit kernel.
# Map generic OSID to the specific one.
#
if ($osinfo->IsGeneric()) {
#
# Map generic OSID to the specific one.
#
$nextosinfo = $osinfo->ResolveNextOSID($experiment);
if (!defined($nextosinfo)) {
die_noretry("No next mapping for $osinfo on $node!\n");
}
print "Mapping $osinfo on $node_id to $nextosinfo\n";
$osinfo = $nextosinfo;
$nextosinfo = $osinfo->ResolveNextOSID($experiment);
if (!defined($nextosinfo)) {
die_noretry("No next mapping for $osinfo on $node!\n");
}
print "Mapping $osinfo on $node_id to $nextosinfo\n";
$osinfo = $nextosinfo;
}
#
# Make sure this OSID is actually loaded on the machine.
#
my $isloaded = $node->IsOSLoaded($osinfo);
if ($isloaded < 0) {
die_noretry("Error determining if $osinfo is loaded on $node\n");
}
if ($isloaded) {
#
# Make sure this OSID is actually loaded on the machine.
# OSID is loaded, but might need to be cleaned.
#
my $isloaded = $node->IsOSLoaded($osinfo);
if ($isloaded < 0) {
die_noretry("Error determining if $osinfo ".
"is loaded on $node\n");
if ($self->dolastload() &&
defined($node->last_reservation()) &&
$node->last_reservation() ne $pid) {
$self->SetupReload($node, $osinfo, $auxload);
}
if ($isloaded) {
elsif ($nextosinfo && !$auxload) {
#
# OSID is loaded, but might need to be cleaned.
# Seems like a bad place for this; if the OS was
# mapped to something else that is already on the
# disk, need to reset def_boot_osid.
#
if ($self->dolastload() &&
defined($node->last_reservation()) &&
$node->last_reservation() ne $pid) {
$self->SetupReload($node, $osinfo);
if ($self->impotent()) {
print STDERR "$node_id:def_boot_osid --> $osinfo\n"
if ($self->debug());
}
elsif ($nextosinfo) {
#
# Seems like a bad place for this; if the OS was
# mapped to something else that is already on the
# disk, need to reset def_boot_osid.
#
if ($self->impotent()) {
print STDERR "$node_id:def_boot_osid --> $osinfo\n"
if ($self->debug());
}
elsif ($node->OSSelect($osinfo, "def_boot_osid", 0)) {
die_noretry("Could not set boot OS to ".
"$osinfo for $node");
}
elsif ($node->OSSelect($osinfo, "def_boot_osid", 0)) {
die_noretry("Could not set boot OS to $osinfo for $node");
}
}
else {
#
# OS not loaded.
#
$self->SetupReload($node, $osinfo);
}
}
else {
#
# OS not loaded.
#
$self->SetupReload($node, $osinfo, $auxload);
}
}
# Remember this for later.
$node->_bootosinfo($osinfo);
print STDERR "$node_id - $osinfo\n"
if ($self->debug());
}
#
......@@ -465,13 +506,28 @@ sub LightUpNodes($@)
if ($op == $NOSTATE);
if ($op == $RELOAD) {
my $image = $node->_loadimage();
if (!exists($reloads{$image->imageid()})) {
$reloads{$image->imageid()} = [];
my $image = $node->_loadimage();
my @images = ($image);
my $imageids = $image->imageid();
my $auxloads = $node->_loadimages();
#
# Watch for multiple loads, but remember that the boot image
# has to be last since libosload assumes that is the one to boot.
#
if (defined($auxloads)) {
foreach my $aux (@{ $auxloads }) {
my $auxid = $aux->imageid();
unshift(@images, $aux);
$imageids = "${auxid},${imageids}";
}
}
if (!exists($reloads{"$imageids"})) {
$reloads{"$imageids"} = [];
}
push(@{ $reloads{$image->imageid()} }, $node);
$action = "reloaded with $image";
push(@{ $reloads{"$imageids"} }, $node);
$action = "reloaded with @images";
}
elsif ($op == $REBOOT) {
$reboots{$node_id} = $node;
......
......@@ -1110,6 +1110,7 @@ sub LoadVirtNodes($)
$vnode->rpms(),
$vnode->startupcmd(),
$vnode->tarfiles(),
$vnode->loadlist(),
$vnode->failureaction(),
$vnode->routertype() ]);
......@@ -6073,7 +6074,7 @@ sub InitializePhysNode($$$)
#
# A normal user node (physical or virtual).
#
my ($cmdline,$rpms,$startupcmd,$tarfiles,
my ($cmdline,$rpms,$startupcmd,$tarfiles,$loadlist,
$failureaction,$routertype) = @{ $virtnode->_settings() };
$osid = (defined($virtnode->_osinfo()) ?
......@@ -6126,6 +6127,7 @@ sub InitializePhysNode($$$)
"deltas" => '',
"ready" => 0,
"startupcmd" => $startupcmd || '',
"loadlist" => $loadlist || '',
"failureaction" => $failureaction,
"routertype" => $routertype);
......
......@@ -1132,6 +1132,7 @@ sub LoadVirtNodes($)
$vnode->rpms(),
$vnode->startupcmd(),
$vnode->tarfiles(),
$vnode->loadlist(),
$vnode->failureaction(),
$vnode->routertype() ]);
......@@ -6291,7 +6292,7 @@ sub InitializePhysNode($$$)
#
# A normal user node (physical or virtual).
#
my ($cmdline,$rpms,$startupcmd,$tarfiles,
my ($cmdline,$rpms,$startupcmd,$tarfiles,$loadlist,
$failureaction,$routertype) = @{ $virtnode->_settings() };
$osid = (defined($virtnode->_osinfo()) ?
......@@ -6350,6 +6351,7 @@ sub InitializePhysNode($$$)
"deltas" => '',
"ready" => 0,
"startupcmd" => $startupcmd || '',
"loadlist" => $loadlist || '',
"failureaction" => $failureaction,
"routertype" => $routertype);
......
......@@ -66,6 +66,9 @@ Node instproc init {s} {
# table).
$self set osid ""
# And an alternate load list.
$self set loadlist ""
# We have this for a bad, bad reason. We can't expose $vhost variables
# in ns files because assign can't yet handle fixing vnodes to vhosts (or
# any other mapping constraints, since that would imply multiple levels
......@@ -177,6 +180,7 @@ Node instproc updatedb {DB} {
$self instvar type
$self instvar osid
$self instvar parent_osid
$self instvar loadlist
$self instvar cmdline
$self instvar rpms
$self instvar startup
......@@ -358,6 +362,11 @@ Node instproc updatedb {DB} {
lappend values $sharing_mode
}
if { $loadlist != "" } {
lappend fields "loadlist"
lappend values $loadlist
}
if { $numeric_id != {} } {
lappend fields "numeric_id"
lappend values $numeric_id
......
......@@ -24,6 +24,7 @@ proc tb-set-node-service {service args} {}
proc tb-add-node-service-hook {service args} {}
proc tb-set-hardware {node type args} {}
proc tb-set-node-os {node os {parentos 0}} {}
proc tb-set-node-loadlist {node loadlist} {}
proc tb-set-link-loss {src args} {}
proc tb-set-lan-loss {lan rate} {}
proc tb-set-node-rpms {node args} {}
......
......@@ -614,6 +614,19 @@ proc tb-set-node-os {node os {parentos 0}} {
$node set parent_osid $parentos
}
}
proc tb-set-node-loadlist {node loadlist} {
if {! ${GLOBALS::anonymous} && ! ${GLOBALS::passmode}} {
var_import ::TBCOMPAT::osids
set oslist [split $loadlist ","]
foreach os $oslist {
if {! [info exists osids($os)]} {
perror "\[tb-set-node-loadlist] Invalid osid $os."
return
}
}
}
$node set loadlist $loadlist
}
proc tb-set-node-cmdline {node cmdline} {
$node set cmdline $cmdline
}
......@@ -2076,8 +2089,8 @@ proc tb-set-node-inner-elab-role {node role} {
perror "\[tb-set-node-inner-elab-role] $node is not a node."
return
}
if {[lsearch -exact {boss boss+router router ops ops+fs fs node} $role] == -1} {
perror "\[tb-set-node-inner-elab-role] type must be one of boss|boss+router|router|ops|ops+fs|fs|node"
if {[lsearch -exact {boss boss+router boss+fs+router router ops ops+fs fs node} $role] == -1} {
perror "\[tb-set-node-inner-elab-role] type must be one of boss|boss+router|boss+fs+router|router|ops|ops+fs|fs|node"
return
}
$node set inner_elab_role $role
......
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