# Given a vname, is it a node in the topo (or something else like a delay).sub isatoponode($$) { return exists($_[0]->vnodes()->{$_[1]}); }sub isadelaynode($$) { return exists($_[0]->delaynodes()->{$_[1]}); }

################################################################################ Virtual Nodes. A separate package so we can create objects for each one# and then add local stuff to them.#package libvtop::virt_node;use Carp;use vars qw($AUTOLOAD);

}################################################################################ Virtual Lans Member. A separate package so we can create objects for# each one and then add local stuff to them.#package libvtop::virt_lan_member;use Carp;use vars qw($AUTOLOAD);

# # Ug, it just gets worse and worse. We also need to map between the # auxtypes that a node (its physical type) can take on. For example, # a link between two pcvm nodes is really a link between a pc600 and # pc850. # $query_result = DBQueryFatal("select distinct n.type,at.type from node_auxtypes as at ". "left join nodes as n on n.node_id=at.node_id"); while (my ($phystype, $auxtype) = $query_result->fetchrow()) { next if (!exists($node_type_linkbw{$phystype})); $node_type_linkbw{$auxtype} = $node_type_linkbw{$phystype}; } # # Here it goes getting even worse - we have to do a similar thing for # vtypes. #

# # Add the pnode node to the oldreserved list for nfree. # See the comment below. We cannot use p2v because we # might not own all those nodes, if on a shared node. # We do not add the ppnode. It will get added in the # next clause if we actually own it. # $self->oldreservednodes()->{$pnode->node_id()} = $pnode;

# # Add the pnode node to the oldreserved list for nfree. # See the comment below. We cannot use p2v because we # might not own all those nodes, if on a shared node. # $self->oldreservednodes()->{$pnode->node_id()} = $pnode;

$vnode->failureaction(), $vnode->routertype() ]); # # If a subnode, kill the fixed mapping. That was just to # tell us the connection. We do not want to overload "fixed" # within assign wrapper since its already overloaded. # if ($issub) { # Must be a parent. Set in the parser, either explicitly, or else # one is created if the user leaves it out. if (!defined($fixed) || $fixed eq "") {

foreach my $ipinfo (@iplist) { my ($port,$ip) = split(":",$ipinfo); $self->{'IPS'}->{"$vname:$port"} = $ip; } # # Map the osname to an OSID now so that we can check max_concurrent. # This also avoids the work and *check* later after we have done 90% # of assign_wrapper. If no osname was specified, we have to wait and # use the default for the type of phys node that assign picks. # if (defined($osname) && $osname ne "") {

} $vnode->_atttributes($attrs); # # Need to set a default. But this needs to be seen on # the client too, via virt_node_attributes. # # We need a way to associate these defaults with the virtualization # type, but that is a function of the image. Needs more thought. #

} if (!exists($vnode->_desires()->{"?+ram"})) { $self->printdb("Setting VM memsize to $defmem for $vname\n"); $vnode->_desires()->{"?+ram"} = $defmem; } else { # # If the user wants a shared node, they are not allowed to # ask for more then the max, unless its an admin. # if ($vnode->_desires()->{"?+ram"} > $maxmem && $vnode->_sharedokay() && !$self->user()->IsAdmin()) {

$self->{'COUNTERS'}->{'simcount'}++ if ($issim); $self->{'COUNTERS'}->{'remotecount'}++ if ($isremote); $self->{'COUNTERS'}->{'virtcount'}++ if ($isvirt); $self->{'COUNTERS'}->{'plabcount'}++ if ($isplab);

# It is silly to fix a node to yourself, so what this probably # means is that the user really wants to fix to a physical node # of the same name. # if (!defined($fixnode) || $vnode->_fixedvm() eq $vname) {

# # Load up the blockstore stuff since we have to spit out the # attributes as desires. # foreach my $virt_bs ($self->virt_blockstores()->Rows()) { # # The blockstore is fixed to a node in the topo. # my $fixnode = $self->vnodes()->{$virt_bs->fixed()}; if (!defined($fixnode)) { tberror("Blockstore $virt_bs is fixed to non-existent node\n"); return -1; }

# # We need a place to hang the attributes, but they are split # between the blockstore and the blockstore_attributes. Another # wrinkle is that the blockstore is assigned to a node in the # topo, and it is that node that we have to hang the desires off. # $self->blockstores()->{$virt_bs->vname()} = $fixnode; $fixnode->_blockstore($virt_bs); $fixnode->_sanhostname("sanhost-" . $virt_bs->vname()); $fixnode->_blockstore_attributes({}); # XXX Are these always in shared mode? $fixnode->_sharedokay(1); $self->{'COUNTERS'}->{'bstorecount'}++; }

# If this is a persistent blockstore (identified by a lease # index attribute) then make sure the user has appropriate # access to the lease and that the associated blockstore is # not already mapped in a conflicting way. # # We also check and make sure that leases in the grace state are # only mounted RO. We make this check in the parser as well, but # the state of the lease can change between parses. # # Note: we do not make these checks during a pre-assign pass. # # Exclusive use semantics: # # If the sitevar "simultaneous_ro_datasets" is zero (or unset) # or the dataset has the "exclusive_use" attribute set, only one # mapping at a time can be in effect for a dataset whether it # is RO or RW. This condition is embodied in the IsExclusiveUse() # Lease method. # # Shared use semantics: # # To be shared, the global "simultaneous_ro_datasets" sitevar # must be non-zero and a dataset's "exclusive_use" attribute must # either not exist or be set to zero (!IsExclusiveUse). Additionally, # the dataset must have a snapshot. Currently a snapshot is created # upon termination of any RW mapping (see Blockstore->Release). # Snapshot creation may be explicit in the future. #