Commit c6c57bc9 authored by David Johnson's avatar David Johnson

Add the ability to load images on virtnodes. For now, we just overload

the tb-set-node-os command with a second optional argument; if that is
present, the first arg is the child OS and the second is the parent OS.
We add some new features in ptopgen (OS-parentOSname-childOSname) based
off a new table that maps which child OSes can run on which parents, and
the right desires get added to match.  We setup the reloads in os_setup
along with the parents.  Also needed a new opmode, RELOAD-PCVM, to handle
all this.

For now, users only have to specify that their images can run on pcvms, a
special hack for which type the images can run on.  This makes sense in
general since there is no point conditionalizing childOS loading on
hardware type at the moment, but rather on parentOS.  Hopefully this stuff
wiill mostly work on shared nodes too, although we'll have to be more
aggressive on the client side garbage collecting old frisbee'd images for
long-lived shared hosts.

I only made these changes in libvtop, so assign_wrapper folks are left in
the dark.

Currently, the client side supports frisbee.  Only in openvz for now, and
this probably breaks libvnode_xen.pm.  Also in here are some openvz
improvements, like ability to sniff out which network is the public
control net, and which is the fake virtual control net.
parent 5feb5f1a
......@@ -157,6 +157,11 @@ while (my ($type) = $types_result->fetchrow_array()) {
push(@mtypes_array, $type);
$xmlfields{"mtype_$type"} = ["mtype", $SLOT_OPTIONAL];
}
#
# Special hack to allow pcvm type -- see SetupReload in os_setup
#
push(@mtypes_array, "pcvm");
$xmlfields{"mtype_pcvm"} = ["mtype", $SLOT_OPTIONAL];
## printf "%s mtypes\n", $#mtypes_array + 1;
## foreach my $x (@mtypes_array) { printf "%s\n", $x; }
## print "\n";
......
......@@ -372,7 +372,13 @@ sub EditImageid($$$$)
my $redo_map = 0;
while (my ($type) = $types_result->fetchrow_array()) {
push(@mtypes_array, $type);
}
#
# Special hack to allow pcvm type -- see SetupReload in os_setup
#
push @mtypes_array, "pcvm";
foreach my $type (@mtypes_array) {
# Remember when we get one of the mtype_$type args. These aren't DB
# columns to update, but instead control re-creating the rows in the
# osidtoimageid table for this imageid, below.
......
......@@ -1916,6 +1916,10 @@ sub DeleteVnodes(@)
DBQueryWarn("delete from node_hostkeys where node_id='$vnodeid'");
DBQueryWarn("delete from node_status where node_id='$vnodeid'");
DBQueryWarn("delete from node_rusage where node_id='$vnodeid'");
# Need to clean out some additional tables since some vnodes can be
# reimaged now!
DBQueryWarn("delete from current_reloads where node_id='$vnodeid'");
DBQueryWarn("delete from partitions where node_id='$vnodeid'");
}
return 0;
......@@ -2305,5 +2309,29 @@ sub MaxShareCount($)
return $count;
}
sub IsVirtHost($)
{
my $self = shift;
return 1
if ($self->{"DBROW"}{"role"} eq 'virthost');
return 0;
}
sub GetPhysHost($) {
my $self = shift;
my $phys_nodeid = $self->{"DBROW"}{"phys_nodeid"};
if (defined($phys_nodeid) && $phys_nodeid ne '') {
return Node->Lookup($phys_nodeid);
}
return undef;
}
sub GetOsids($) {
my $self = shift;
return ($self->{"DBROW"}{"def_boot_osid"},
$self->{"DBROW"}{"temp_boot_osid"},
$self->{"DBROW"}{"next_boot_osid"});
}
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -44,7 +44,8 @@ my %FEATURES = ( "ping" => 1,
"veths" => 0,
"mlinks" => 0,
"linktest" => 1,
"linkdelays" => 0 );
"linkdelays" => 0,
"suboses" => 0 );
# Valid OS names. Mirrored in the web interface. The value is a user-okay flag.
my %OSLIST = ( "Linux" => 1,
......@@ -171,6 +172,7 @@ sub nextosid($) { return field($_[0], "nextosid"); }
sub max_concurrent($) { return field($_[0], "max_concurrent"); }
sub mfs($) { return field($_[0], "mfs"); }
sub reboot_waittime($) { return field($_[0], "reboot_waittime"); }
sub def_parentosid($) { return field($_[0], "def_parentosid"); }
#
# Create a new os_info. This installs the new record in the DB,
......@@ -229,7 +231,8 @@ sub Create($$$$$$)
foreach my $key ("old_osid", "OS", "version", "path", "machinetype",
"osfeatures", "ezid", "shared", "mustclean",
"op_mode", "nextosid", "old_nextosid",
"max_concurrent", "mfs", "reboot_waittime") {
"max_concurrent", "mfs", "reboot_waittime",
"def_parentosid") {
if (exists($argref->{$key})) {
push(@arg_slots, $key);
}
......@@ -572,5 +575,48 @@ sub FeatureSupported($$)
return grep {$_ eq $feature} split(',', $osfeatures);
}
#
# Return 1 if OS is a sub OS (i.e., has a def_parentosid).
#
sub IsSubOS($)
{
my ($self,) = @_;
my $def_parentosid = $self->def_parentosid();
return 0
if (!defined($def_parentosid) || $def_parentosid eq "");
return 1;
}
#
# Return 1 if OS is a sub OS and runs on the given parent.
#
sub RunsOnParent($$)
{
my ($self,$parent) = @_;
my ($osid,$osname) = ($self->osid(),$self->osname());
my $def_parentosid = $self->def_parentosid();
my ($posid,$posname) = ($parent->osid(),$parent->osname());
return 0
if (!$self->IsSubOS());
return 1
if ($posid == $def_parentosid);
my $result = DBQueryWarn("select osid from os_submap".
" where osid=$osid and parent_osid=$posid");
if (!$result || $result->num_rows() == 0) {
warn "Child OS $osname cannot run on any OSes!\n";
return 0;
}
return 1;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -107,8 +107,8 @@ use vars qw(@ISA @EXPORT);
TBDB_NODEOPMODE_NORMAL TBDB_NODEOPMODE_DELAYING
TBDB_NODEOPMODE_UNKNOWNOS TBDB_NODEOPMODE_RELOADING
TBDB_NODEOPMODE_NORMALv1 TBDB_NODEOPMODE_MINIMAL
TBDB_NODEOPMODE_RELOAD TBDB_NODEOPMODE_RELOADMOTE
TBDB_NODEOPMODE_NORMALv1 TBDB_NODEOPMODE_MINIMAL TBDB_NODEOPMODE_PCVM
TBDB_NODEOPMODE_RELOAD TBDB_NODEOPMODE_RELOADMOTE TBDB_NODEOPMODE_RELOADPCVM
TBDB_NODEOPMODE_DELAY
TBDB_NODEOPMODE_BOOTWHAT
TBDB_NODEOPMODE_ANY
......@@ -493,8 +493,10 @@ sub TBDB_NODEOPMODE_UNKNOWNOS { "UNKNOWNOS"; }
sub TBDB_NODEOPMODE_RELOADING { "RELOADING"; }
sub TBDB_NODEOPMODE_NORMALv1 { "NORMALv1"; }
sub TBDB_NODEOPMODE_MINIMAL { "MINIMAL"; }
sub TBDB_NODEOPMODE_PCVM { "PCVM"; }
sub TBDB_NODEOPMODE_RELOAD { "RELOAD"; }
sub TBDB_NODEOPMODE_RELOADMOTE { "RELOAD-MOTE"; }
sub TBDB_NODEOPMODE_RELOADPCVM { "RELOAD-PCVM"; }
sub TBDB_NODEOPMODE_DELAY { "DELAY"; }
sub TBDB_NODEOPMODE_BOOTWHAT { "_BOOTWHAT_"; } # A redirection opmode
sub TBDB_NODEOPMODE_UNKNOWN { "UNKNOWN"; }
......
......@@ -59,7 +59,8 @@ bootinfo_init(void)
}
int
bootinfo(struct in_addr ipaddr, struct boot_info *boot_info, void *opaque)
bootinfo(struct in_addr ipaddr, char *node_id, struct boot_info *boot_info,
void *opaque, int no_event_send)
{
int needevent = 0;
int err;
......@@ -71,11 +72,12 @@ bootinfo(struct in_addr ipaddr, struct boot_info *boot_info, void *opaque)
inet_ntoa(ipaddr), boot_info->data, boot_info->version);
#ifdef EVENTSYS
needevent = bicache_needevent(ipaddr);
if (needevent)
if (!no_event_send && needevent)
bievent_send(ipaddr, opaque,
TBDB_NODESTATE_PXEBOOTING);
#endif
err = query_bootinfo_db(ipaddr, boot_info->version, boot_whatp, boot_info->data);
err = query_bootinfo_db(ipaddr, node_id, boot_info->version,
boot_whatp, boot_info->data);
break;
case BIOPCODE_BOOTWHAT_REQUEST:
case BIOPCODE_BOOTWHAT_INFO:
......@@ -83,11 +85,11 @@ bootinfo(struct in_addr ipaddr, struct boot_info *boot_info, void *opaque)
inet_ntoa(ipaddr), boot_info->version);
#ifdef EVENTSYS
needevent = bicache_needevent(ipaddr);
if (needevent)
if (!no_event_send && needevent)
bievent_send(ipaddr, opaque,
TBDB_NODESTATE_PXEBOOTING);
#endif
err = query_bootinfo_db(ipaddr,
err = query_bootinfo_db(ipaddr, node_id,
boot_info->version, boot_whatp, NULL);
break;
......@@ -101,7 +103,7 @@ bootinfo(struct in_addr ipaddr, struct boot_info *boot_info, void *opaque)
else {
boot_info->status = BISTAT_SUCCESS;
#ifdef EVENTSYS
if (needevent) {
if (!no_event_send && needevent) {
switch (boot_whatp->type) {
case BIBOOTWHAT_TYPE_PART:
case BIBOOTWHAT_TYPE_SYSID:
......
......@@ -9,10 +9,12 @@ struct boot_info;
int open_bootinfo_db(void);
int close_bootinfo_db(void);
int bootinfo_init(void);
int bootinfo(struct in_addr ipaddr,
struct boot_info *info, void *opaque);
int query_bootinfo_db(struct in_addr ipaddr, int version,
struct boot_what *info, char *key);
int bootinfo(struct in_addr ipaddr, char *node_id,
struct boot_info *info, void *opaque,
int no_event_send);
int query_bootinfo_db(struct in_addr ipaddr, char *node_id,
int version, struct boot_what *info,
char *key);
int elabinelab_hackcheck(struct sockaddr_in *target);
extern int debug;
......
......@@ -47,7 +47,8 @@ open_bootinfo_db(void)
*/
int
query_bootinfo_db(struct in_addr ipaddr, int version, boot_what_t *info, char* key)
query_bootinfo_db(struct in_addr ipaddr, char *node_id, int version,
boot_what_t *info, char* key)
{
int nrows, rval = 0;
MYSQL_RES *res;
......@@ -84,7 +85,46 @@ query_bootinfo_db(struct in_addr ipaddr, int version, boot_what_t *info, char* k
#define DEFINED(x) (row[(x)] != NULL && row[(x)][0] != '\0')
#define TOINT(x) (atoi(row[(x)]))
if(! haskey) {
if (node_id) {
/*
* Right now, this is ONLY used for checking bootinfo for
* imageable vnodes. All bets off if you try it for something
* else!
*/
res = mydb_query("select n.def_boot_osid, n.def_boot_cmd_line, "
" odef.path, odef.mfs, pdef.partition, "
" n.temp_boot_osid, "
" otemp.path, otemp.mfs, ptemp.partition, "
" n.next_boot_osid, n.next_boot_cmd_line, "
" onext.path, onext.mfs, pnext.partition, "
" r.pid,n.pxe_boot_path "
" from nodes as n "
"left join reserved as r on n.node_id=r.node_id "
"left join partitions as pdef on "
" n.node_id=pdef.node_id and "
" n.def_boot_osid=pdef.osid "
"left join os_info as odef on "
" odef.osid=n.def_boot_osid "
"left join partitions as ptemp on "
" n.node_id=ptemp.node_id and "
" n.temp_boot_osid=ptemp.osid "
"left join os_info as otemp on "
" otemp.osid=n.temp_boot_osid "
"left join partitions as pnext on "
" n.node_id=pnext.node_id and "
" n.next_boot_osid=pnext.osid "
"left join os_info as onext on "
" onext.osid=n.next_boot_osid "
"left outer join "
" (select type,attrvalue from node_type_attributes "
" where attrkey='nobootinfo' and attrvalue='1' "
" group by type) as nobootinfo_types "
" on n.type=nobootinfo_types.type "
"where n.node_id='%s' "
" and nobootinfo_types.attrvalue is NULL",
16, node_id);
}
else if (! haskey) {
res = mydb_query("select n.def_boot_osid, n.def_boot_cmd_line, "
" odef.path, odef.mfs, pdef.partition, "
" n.temp_boot_osid, "
......
......@@ -146,7 +146,7 @@ main(int argc, char **argv)
#endif
}
else {
err = query_bootinfo_db(target.sin_addr,
err = query_bootinfo_db(target.sin_addr, NULL,
boot_info.version,
boot_whatp, NULL);
if (err) {
......
......@@ -138,7 +138,8 @@ main(int argc, char **argv)
errorc("receiving datagram packet");
exit(1);
}
err = bootinfo(client.sin_addr, &boot_info, (void *) NULL);
err = bootinfo(client.sin_addr, (char *) NULL,
&boot_info, (void *) NULL, 0);
if (err < 0)
continue;
if (boot_info.status == BISTAT_SUCCESS)
......
......@@ -2451,12 +2451,13 @@ CREATE TABLE `os_info` (
`path` tinytext,
`magic` tinytext,
`machinetype` varchar(30) NOT NULL default '',
`osfeatures` set('ping','ssh','ipod','isup','veths','veth-ne','veth-en','mlinks','linktest','linkdelays','vlans') default NULL,
`osfeatures` set('ping','ssh','ipod','isup','veths','veth-ne','veth-en','mlinks','linktest','linkdelays','vlans','suboses') default NULL,
`ezid` tinyint(4) NOT NULL default '0',
`shared` tinyint(4) NOT NULL default '0',
`mustclean` tinyint(4) NOT NULL default '1',
`op_mode` varchar(20) NOT NULL default 'MINIMAL',
`nextosid` int(8) unsigned default NULL,
`def_parentosid` int(8) unsigned default NULL,
`old_nextosid` varchar(35) NOT NULL default '',
`max_concurrent` int(11) default NULL,
`mfs` tinyint(4) NOT NULL default '0',
......@@ -2469,6 +2470,17 @@ CREATE TABLE `os_info` (
KEY `uuid` (`uuid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `os_submap`
--
DROP TABLE IF EXISTS `os_submap`;
CREATE TABLE `os_submap` (
`osid` int(8) unsigned NOT NULL default '0',
`parent_osid` int(8) unsigned NOT NULL default '0',
PRIMARY KEY (`osid`,`parent_osid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `osconfig_files`
--
......@@ -3798,6 +3810,7 @@ CREATE TABLE `virt_nodes` (
`exptidx` int(11) NOT NULL default '0',
`ips` text,
`osname` varchar(20) default NULL,
`parent_osname` varchar(20) default NULL,
`cmd_line` text,
`rpms` text,
`deltas` text,
......
......@@ -210,6 +210,7 @@ REPLACE INTO foreign_keys VALUES ('virt_nodes','osname','os_info','osname');
REPLACE INTO foreign_keys VALUES ('vlans','pid,eid','experiments','pid,eid');
REPLACE INTO foreign_keys VALUES ('nseconfigs','eid,pid,vname','virt_nodes','eid,pid,vname');
REPLACE INTO foreign_keys VALUES ('nseconfigs','eid,pid','experiments','eid,pid');
REPLACE INTO foreign_keys VALUES ('virt_nodes','parent_osname','os_info','osname');
--
-- Dumping data for table `mode_transitions`
......@@ -276,6 +277,8 @@ REPLACE INTO mode_transitions VALUES ('ALWAYSUP','SHUTDOWN','RELOAD-MOTE','SHUTD
REPLACE INTO mode_transitions VALUES ('ALWAYSUP','ISUP','RELOAD-MOTE','SHUTDOWN','ReloadStart');
REPLACE INTO mode_transitions VALUES ('ALWAYSUP','ISUP','RELOAD-MOTE','ISUP','ReloadStart');
REPLACE INTO mode_transitions VALUES ('RELOAD-MOTE','SHUTDOWN','ALWAYSUP','ISUP','ReloadDone');
REPLACE INTO mode_transitions VALUES ('PCVM','SHUTDOWN','RELOAD-PCVM','SHUTDOWN','ReloadSetup');
REPLACE INTO mode_transitions VALUES ('RELOAD-PCVM','SHUTDOWN','PCVM','SHUTDOWN','ReloadDone');
--
-- Dumping data for table `priorities`
......@@ -526,6 +529,10 @@ REPLACE INTO state_transitions VALUES ('GARCIA-STARGATEv1','TBSETUP','TBFAILED',
REPLACE INTO state_transitions VALUES ('GARCIA-STARGATEv1','TBFAILED','SHUTDOWN','RebootAfterFail');
REPLACE INTO state_transitions VALUES ('RELOAD','RELOADSETUP','RELOADOLDMFS','');
REPLACE INTO state_transitions VALUES ('RELOAD','RELOADOLDMFS','SHUTDOWN','');
REPLACE INTO state_transitions VALUES ('RELOAD-PCVM','RELOADSETUP','RELOADING','ReloadStart');
REPLACE INTO state_transitions VALUES ('RELOAD-PCVM','RELOADING','RELOADDONE','ReloadDone');
REPLACE INTO state_transitions VALUES ('RELOAD-PCVM','RELOADDONE','SHUTDOWN','ReloadDone');
REPLACE INTO state_transitions VALUES ('RELOAD-PCVM','SHUTDOWN','RELOADSETUP','ReloadSetup');
--
-- Dumping data for table `state_triggers`
......@@ -543,6 +550,7 @@ REPLACE INTO state_triggers VALUES ('*','RELOAD-MOTE','RELOADDONE','RELOADDONE')
REPLACE INTO state_triggers VALUES ('*','OPSNODEBSD','ISUP','SCRIPT:opsreboot');
REPLACE INTO state_triggers VALUES ('*','NORMALv2','WEDGED','POWERCYCLE');
REPLACE INTO state_triggers VALUES ('*','RELOAD','RELOADOLDMFS','RELOADOLDMFS');
REPLACE INTO state_triggers VALUES ('*','RELOAD-PCVM','RELOADDONE','RESET, RELOADDONE');
--
-- Dumping data for table `table_regex`
......@@ -693,6 +701,7 @@ REPLACE INTO table_regex VALUES ('virt_nodes','failureaction','text','regex','^(
REPLACE INTO table_regex VALUES ('virt_nodes','routertype','text','regex','^(none|ospf|static|manual|static-ddijk|static-old)$',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_nodes','fixed','text','redirect','default:tinytext',0,128,NULL);
REPLACE INTO table_regex VALUES ('virt_nodes','sharing_mode','text','regex','^[-\\w]+$',1,32,NULL);
REPLACE INTO table_regex VALUES ('virt_nodes','parent_osname','text','redirect','os_info:osname',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_programs','pid','text','redirect','projects:pid',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_programs','eid','text','redirect','experiments:eid',0,0,NULL);
REPLACE INTO table_regex VALUES ('virt_programs','vnode','text','redirect','virt_nodes:vname',0,0,NULL);
......
#
# Updates to add support for subOSes (only for vnodes right now)
#
use strict;
use libdb;
sub DoUpdate($$$)
{
my ($dbhandle, $dbname, $version) = @_;
#
# Update the schema...
#
# Add a new osfeature
DBQueryFatal("ALTER TABLE os_info MODIFY COLUMN osfeatures" .
" set('ping','ssh','ipod','isup','veths','veth-ne'," .
" 'veth-en','mlinks','linktest','linkdelays','vlans'," .
" 'suboses') default NULL");
# Add the def_parentosid column so that OSes that can be subOSes will
# always have a potential parent even if the user does not specify.
DBQueryFatal("ALTER TABLE os_info ADD COLUMN" .
" def_parentosid int(8) unsigned default NULL" .
" AFTER nextosid");
# Add a table that describes which (sub)osids can run on which osids.
DBQueryFatal("CREATE TABLE os_submap (" .
" osid int(8) unsigned NOT NULL default '0'," .
" parent_osid int(8) unsigned NOT NULL default '0'," .
" PRIMARY KEY (osid,parent_osid))");
# Add the parent_osname column since we currently have no handle for
# virthosts in ns files, and we want to set both the subOS and parent
# OS potentially, for a virtnode. This can go away when assign can
# handle virthosts explicitly defined in ns files.
DBQueryFatal("ALTER TABLE virt_nodes ADD COLUMN" .
" parent_osname varchar(20) default NULL" .
" AFTER osname");
#
# Add some database-fill stuff...
#
DBQueryFatal("REPLACE INTO foreign_keys VALUES" .
" ('virt_nodes','parent_osname','os_info','osname')");
DBQueryFatal("REPLACE INTO mode_transitions VALUES" .
" ('PCVM','SHUTDOWN','RELOAD-PCVM','SHUTDOWN','ReloadSetup')");
DBQueryFatal("REPLACE INTO mode_transitions VALUES" .
" ('RELOAD-PCVM','SHUTDOWN','PCVM','SHUTDOWN','ReloadDone')");
DBQueryFatal("REPLACE INTO state_transitions VALUES" .
" ('RELOAD-PCVM','RELOADSETUP','RELOADING','ReloadStart')");
DBQueryFatal("REPLACE INTO state_transitions VALUES" .
" ('RELOAD-PCVM','RELOADING','RELOADDONE','ReloadDone')");
DBQueryFatal("REPLACE INTO state_transitions VALUES" .
" ('RELOAD-PCVM','RELOADDONE','SHUTDOWN','ReloadDone')");
DBQueryFatal("REPLACE INTO state_transitions VALUES" .
" ('RELOAD-PCVM','SHUTDOWN','RELOADSETUP','ReloadSetup')");
DBQueryFatal("REPLACE INTO state_triggers VALUES" .
" ('*','RELOAD-PCVM','RELOADDONE','RESET, RELOADDONE')");
DBQueryFatal("REPLACE INTO table_regex VALUES" .
" ('virt_nodes','parent_osname','text','redirect','" .
" os_info:osname',0,0,NULL)");
return 0;
}
1;
......@@ -64,6 +64,7 @@ sub osload ($$) {
my $zerofree = 0;
my $prepare = 0;
my $swapinfo = 0;
my %nodeflags = ();
# Locals
my %retries = ();
......@@ -90,7 +91,7 @@ sub osload ($$) {
$debug = $args->{'debug'};
}
if (defined($args->{'imageid'})) {
@imageids = split /,/, $args->{'imageid'};
@imageids = split(/,/, $args->{'imageid'});
$usedefault = 0;
}
if (defined($args->{'imageids'})) {
......@@ -106,10 +107,12 @@ sub osload ($$) {
if (defined($args->{'prepare'})) {
$prepare = $args->{'prepare'};
}
if (defined($args->{'swapinfo'})) {
$swapinfo = $args->{'swapinfo'};
}
if (defined($args->{'nodeflags'})) {
%nodeflags = %{$args->{'nodeflags'}};
}
#
# Start a new logging sub-process
......@@ -224,26 +227,31 @@ sub osload ($$) {
}
# Get default imageid for this node.
my $default_imageid = $nodeobject->default_imageid();
if (! defined($default_imageid)) {
tberror "$node: No default imageid defined!";
goto failednode;
}
my @default_imageids = split/,/, $default_imageid;
my @default_images;
foreach my $default_imageid (@default_imageids) {
my $default_image = Image->Lookup($default_imageid);
if (!defined($default_image)) {
tberror("Could not map $default_imageid to its object!");
return -1;
# NOTE that virtnodes don't have default imageids -- they are only
# loaded (and thus arrive here) if the user specifically set a loadable
# subOS for the node.
if (!$nodeobject->isvirtnode()) {
my $default_imageid = $nodeobject->default_imageid();
if (! defined($default_imageid)) {
tberror "$node: No default imageid defined!";
goto failednode;
}
my @default_imageids = split(/,/, $default_imageid);
my @default_images;
foreach my $default_imageid (@default_imageids) {
my $default_image = Image->Lookup($default_imageid);
if (!defined($default_image)) {
tberror("Could not map $default_imageid to its object!");
return -1;
}
push @default_images, $default_image;
}
push @default_images, $default_image;
}
if ($usedefault) {
$prepare = 1;
@imageids = @default_imageids;
@images = @default_images;
if ($usedefault) {
$prepare = 1;
@imageids = @default_imageids;
@images = @default_images;
}
}
my @imageidxs = (0 .. $#imageids);
......@@ -426,6 +434,7 @@ sub osload ($$) {
my $type = $nodeobject->type();
my $class = $nodeobject->class();
my $isremote = $nodeobject->isremotenode();
my $isvirtnode = $nodeobject->isvirtnode();
my $reload_mode;
my $reload_func;
my $reboot_required;
......@@ -439,6 +448,11 @@ sub osload ($$) {
$reload_func = \&SetupReloadFrisbee;
$reboot_required = !$noreboot; # Reboot unless $noreboot flag set
if (defined($nodeflags{$node})
&& defined($nodeflags{$node}{'noreboot'})) {
$reboot_required = !$nodeflags{$node}{'noreboot'};
}
foreach my $i (@imageidxs) {
# This is passed along so that remote node can request the file.
# Make sure the image object has an access key defined.
......@@ -468,7 +482,8 @@ sub osload ($$) {
'zerofree' => $zerofree,
'prepare' => $prepare,
'maxwait' => $maxwait,
'isremote' => $isremote
'isremote' => $isremote,
'isvirtnode' => $isvirtnode
};
print "Setting up reload for $node (mode: $reload_mode)\n";
......@@ -768,6 +783,16 @@ sub WaitTillReloadDone($$$@)
} else {
$maxwait = $reload_info->{$node}{'maxwait'};
}
#
# If it's a virtnode, we need to add a bunch of time based
# on how long the parent might take. This is a fool's errand,
# given how synchronous our scripts are, so give it 8 mins
# for now.
#
if ($reload_info->{$node}{'isvirtnode'}) {
$maxwait += 8 * 60;
}
my $query_result =
DBQueryWarn("select * from current_reloads ".
......@@ -853,6 +878,7 @@ sub SetupReloadFrisbee($)
my $imageids = $reload_info->{'imageids'};
my $zerofree = $reload_info->{'zerofree'};
my $prepare = $reload_info->{'prepare'};
my $isvirtnode = $reload_info->{'isvirtnode'};
my $osid = TBNodeDiskloadOSID($node);
#
......@@ -881,6 +907,12 @@ sub SetupReloadFrisbee($)
tberror "os_select $osid failed!";
return -1;
}
# Need to kick virtnodes so stated picks up the next_op_mode from os_select
if ($isvirtnode) {
TBSetNodeEventState($node,TBDB_NODESTATE_SHUTDOWN);
}
foreach my $imageid (@$imageids) {
system("$FRISBEELAUNCHER " . ($debug ? "-d ": "") . "$imageid");
if ($?) {
......
......@@ -178,7 +178,7 @@ sub nodereboot($$)
foreach my $node (@nodes) {
my $nodeobject = Node->Lookup($node);
my $rebootable = $nodeobject->rebootable();
$nodeobjects{$node} = $nodeobject;
push(@temp,$node) if $rebootable;
}
......
......@@ -767,6 +767,7 @@ sub LoadVirtNodes($)
my $type = $vnode->type();
my $fixed = $vnode->fixed();
my $osname = $vnode->osname();
my $parent_osname = $vnode->parent_osname();
# XXX
# If its a vtype, there will not be any node_type data. This
......@@ -837,6 +838,9 @@ sub LoadVirtNodes($)
# The mapped osname to actual osinfo structure.
$vnode->_osinfo(undef);
# If the virtnode tries to specify its parent os in addition to its own,
# store that osinfo here.
$vnode->_parent_osinfo(undef);
# Eventual physical mapping.
$vnode->_physnode(undef);
# Handy to combine these.
......@@ -920,6 +924,25 @@ sub LoadVirtNodes($)
$vnode->_osinfo($osinfo);
}
#
# Map the parent_osname to an OSID now.
#
if (defined($parent_osname) && $parent_osname ne "") {
my $osinfo = OSinfo->Lookup("$pid,$parent_osname");
if (!defined($osinfo)) {
$osinfo = OSinfo->LookupByName($parent_osname);
if (!defined($osinfo)) {
tberror({cause => 'user', type => 'primary',
severity => SEV_ERROR,
error => ['invalid_os', undef, $parent_osname, $pid]},
"Invalid parent OS $parent_osname in project $pid!");
return -1;
}
}
$vnode->_parent_osinfo($osinfo);
}
#
# Add in desires.
#
......@@ -1256,14 +1279,35 @@ sub GenVirtNodes($)
# osidtoimageid for it, and thus we leave it off of the desire list
if (defined($vnode->_osinfo())) {
my $osinfo = $vnode->_osinfo();
#
# Support subOSes with a multi-OS desire. Since the pnodes
# will have features like OS-parent and OS-parent-subos, we
# generate desire to match. Parent is major since then this
# all works seamlessly with non-subos stuff.
#
my $posinfo = $vnode->_parent_osinfo();
if ($vnode->_sharedokay()) {
my $jailosid = $self->nodejailosid($vnode);
if (!defined($posinfo)) {
my $jailosid = $self->nodejailosid($vnode);
$desirestr .= " OS-$jailosid:1";
$desirestr .= " OS-$jailosid:1";
}
else {
$desirestr .= " OS-" . $posinfo->osid() . ":1";
$desirestr .= " OS-" . $posinfo->osid() .
"-" . $osinfo->osid() . ":1";
}
}
elsif (!defined($osinfo->path()) || $osinfo->path() eq "") {
$desirestr .= " OS-" . $osinfo->osid() . ":1";
if (!defined($posinfo)) {
$desirestr .= " OS-" . $osinfo->osid() . ":1";
}
else {
$desirestr .= " OS-" . $posinfo->osid() . ":1";
$desirestr .= " OS-" . $posinfo->osid() .
"-" . $osinfo->osid() . ":1";
}
}
}
......@@ -1473,7 +1517,16 @@ sub GenVirtLans($)
# Doing this before assign chooses the node, is silly
# but no choice right now.
#
if (defined($virtnode->_osinfo())) {
# And now, we only map in this way IF the parent_osid
# is not set (it gets set if the user chooses a subOS and
# a parent is assigned by default in the parser, or
# if they choose both a subOS and a specific parent OS).
#
if (defined($virtnode->_parent_osinfo())) {
$osinfo = $virtnode->_parent_osinfo();
$osid = $osinfo->osid();
}
elsif (defined($virtnode->_osinfo())) {
$osid = $self->nodejailosid($virtnode);
if (!defined($osid)) {
tberror("No jailosid for $virtnode\n");
......@@ -2915,6 +2968,8 @@ sub ReadTextSolution($$)
{
my ($self, $input) = @_;
$self->ClearSolution();
#
# Still using the old assign format.
#
......@@ -4690,8 +4745,13 @@ sub InitializePhysNode($$$)
#
# A node hosting virtnodes (like jails).
#
$osid = ($self->option("jail_osid") ||
$self->nodejailosid($virtnode));
if (defined($virtnode->_parent_osinfo())) {
$osid = $virtnode->_parent_osinfo()->osid();
}
else {
$osid = ($self->option("jail_osid") ||
$self->nodejailosid($virtnode));
}
return -1
if (!defined($osid));