From 6be507416ab6d408bb84e27a2b018cdf7cc7ec10 Mon Sep 17 00:00:00 2001 From: Leigh B Stoller Date: Fri, 29 Jan 2016 09:12:20 -0700 Subject: [PATCH] New syntax for pre-reserving specific nodes: boss> wap perl prereserve lbsbox pcxxx pcyyy ... Overall pre-reserve handling is unchanged; if there is a another higher priority type pre-reserve, it will be filled first. Moral, be sure to think about the priority argument, which you had to do anyway. --- db/Node.pm.in | 20 ++++++-- sql/database-create.sql | 12 +++++ sql/updates/4/494 | 23 +++++++++ utils/prereserve.in | 103 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 148 insertions(+), 10 deletions(-) create mode 100644 sql/updates/4/494 diff --git a/db/Node.pm.in b/db/Node.pm.in index ea7488a16..4f7870337 100755 --- a/db/Node.pm.in +++ b/db/Node.pm.in @@ -3664,7 +3664,8 @@ sub CheckPreReserve($$) my $type = $self->type(); my $node_id = $self->node_id(); - DBQueryWarn("lock tables project_reservations write, nodes write") + DBQueryWarn("lock tables project_reservations write, nodes write, ". + " node_reservations write") or return undef; # @@ -3677,12 +3678,13 @@ sub CheckPreReserve($$) " project_reservations.pid=nodes.reserved_pid ". "where nodes.node_id='$node_id'"); + # numrows would be zero if the node was suddenly deleted. goto done if (!defined($query_result) || !$query_result->numrows); # # If there is a reserved pid already set for this node, check to see - # if the reervation request is still active. If not, we can clear it, + # if the reservation request is still active. If not, we can clear it, # which will allow it to be set again below, if needed. # my ($pid,$count,$active) = $query_result->fetchrow_array(); @@ -3712,13 +3714,25 @@ sub CheckPreReserve($$) if ($query_result->numrows) { my ($pid,$count) = $query_result->fetchrow_array(); + # + # See if this is fullfulling a specific node reservation request. + # Need to delete that row if so. + # + my $noderes_result = + DBQueryWarn("select node_id from node_reservations ". + "where node_id='$node_id' and pid='$pid'"); + goto done + if (!$noderes_result); if (DBQueryWarn("update nodes set reserved_pid='$pid' ". "where node_id='$node_id'")) { DBQueryWarn("update project_reservations set count=count-1 ". "where pid='$pid'"); - + if ($noderes_result->numrows) { + DBQueryWarn("delete from node_reservations ". + "where node_id='$node_id'"); + } $result = $pid; if ($count == 1) { diff --git a/sql/database-create.sql b/sql/database-create.sql index cf3b08207..8a67ed7b1 100644 --- a/sql/database-create.sql +++ b/sql/database-create.sql @@ -3997,6 +3997,18 @@ CREATE TABLE `project_reservations` ( PRIMARY KEY (`pid_idx`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +-- +-- Table structure for table `node_reservations` +-- + +DROP TABLE IF EXISTS `node_reservations`; +CREATE TABLE `node_reservations` ( + `node_id` varchar(32) NOT NULL default '', + `pid` varchar(48) NOT NULL default '', + `pid_idx` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`node_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + -- -- Table structure for table `project_stats` -- diff --git a/sql/updates/4/494 b/sql/updates/4/494 new file mode 100644 index 000000000..357ce5d27 --- /dev/null +++ b/sql/updates/4/494 @@ -0,0 +1,23 @@ +use strict; +use libdb; +use Image; +use EmulabFeatures; + +sub DoUpdate($$$) +{ + my ($dbhandle, $dbname, $version) = @_; + + if (!DBTableExists("node_reservations")) { + DBQueryFatal("CREATE TABLE `node_reservations` ( ". + " `node_id` varchar(32) NOT NULL default '', ". + " `pid` varchar(48) NOT NULL default '', ". + " `pid_idx` mediumint(8) unsigned NOT NULL default '0', ". + " PRIMARY KEY (`node_id`) ". + ") ENGINE=MyISAM DEFAULT CHARSET=latin1"); + } + return 0; +} + +# Local Variables: +# mode:perl +# End: diff --git a/utils/prereserve.in b/utils/prereserve.in index ddcb96e80..e4dac585d 100644 --- a/utils/prereserve.in +++ b/utils/prereserve.in @@ -32,7 +32,7 @@ use Date::Parse; sub usage() { print STDERR "Usage: prereserve [-t typelist] [-n priority] ". - "[-s start] [-e end [-r]] pid count\n"; + "[-s start] [-e end [-r]] pid [count | node_id node_id ...\n"; print STDERR " prereserve -c [-r] pid\n"; print STDERR " prereserve -i pid\n"; print STDERR " prereserve -a pid\n"; @@ -59,6 +59,7 @@ my $clear = 0; my $revoke = 0; my $sendmail = 0; my $activate = 0; +my @nodelist = (); my $starttime; my $endtime; my $typelist; @@ -168,10 +169,25 @@ elsif ($activate) { } else { usage() - if (@ARGV != 2); + if (@ARGV < 2); - $pid = $ARGV[0]; - $count = $ARGV[1]; + $pid = shift(@ARGV); + $count = shift(@ARGV); + + if ($count !~ /^\d+$/) { + if (defined($typelist)) { + fatal("Not allowed to specify types and a node list together"); + } + @nodelist = ($count, @ARGV); + $count = scalar(@nodelist); + + foreach my $nodeid (@nodelist) { + my $node = Node->Lookup($nodeid); + if (!defined($node)) { + fatal("No such node $nodeid"); + } + } + } if ($priority && ! ($priority =~ /^\d*$/)) { usage(); @@ -203,7 +219,7 @@ if ($list) { my $endtime = $row->{'end'}; my $active = $row->{'active'}; my $current = 0; - + my $current_result = DBQueryFatal("select count(*) from nodes where reserved_pid='$pid'"); @@ -253,6 +269,7 @@ my $pid_idx = $project->pid_idx(); # if ($info) { my $current = 0; + my $pending = 0; my $nodes_result = DBQueryFatal("select node_id from nodes where reserved_pid='$pid'"); @@ -310,6 +327,27 @@ if ($info) { printf("%-15s %-10s %-32s\n", $node_id, $type, $pideid); } } + my $noderes_result = + DBQueryFatal("select node_id from node_reservations ". + "where pid_idx='$pid_idx'"); + if ($noderes_result->numrows) { + print "-------------------------------------------------------------\n"; + print "Still waiting for these nodes\n"; + printf("%-15s %-10s %-32s\n", + "NodeID", "Type", "Pid/Eid"); + print "-------------------------------------------------------------\n"; + + while (my ($node_id) = $noderes_result->fetchrow_array()) { + my $node = Node->Lookup($node_id); + my $type = $node->type(); + my $pideid = "--"; + + if ($node->IsReserved()) { + $pideid = $node->pid() . "/" . $node->eid(); + } + printf("%-15s %-10s %-32s\n", $node_id, $type, $pideid); + } + } exit(0); } @@ -331,6 +369,7 @@ if ($UID) { # Clear and exit. # if ($clear) { + DBQueryFatal("delete from node_reservations where pid_idx='$pid_idx'"); DBQueryFatal("delete from project_reservations where pid_idx='$pid_idx'"); if ($revoke) { DBQueryFatal("update nodes set reserved_pid=null ". @@ -384,10 +423,26 @@ if ($endtime) { my $tmp = str2time($endtime); $endarg = ",end=FROM_UNIXTIME($tmp)"; } +DBQueryFatal("lock tables project_reservations write, ". + " node_reservations write"); DBQueryFatal("insert into project_reservations set ". " pid='$pid', pid_idx='$pid_idx', count='$count', ". " creator='$uid', creator_idx='$uid_idx', ". " created=now(),active=0 $typearg $startarg $endarg"); +if (@nodelist) { + foreach my $node_id (@nodelist) { + if (!DBQueryWarn("insert into node_reservations set ". + " pid='$pid', pid_idx='$pid_idx', ". + " node_id='$node_id'")) { + DBQueryWarn("delete from project_reservations ". + "where pid_idx='$pid_idx'"); + DBQueryWarn("delete from node_reservations ". + "where pid_idx='$pid_idx'"); + exit(-1); + } + } +} +DBQueryFatal("unlock tables"); print "Node reservation request for $count nodes has been created.\n"; # @@ -408,8 +463,12 @@ sub StartReservation($) my ($pid) = @_; DBQueryFatal("lock tables nodes write, node_types read, ". - " project_reservations write, reserved read"); - + " project_reservations write, ". + " node_reservations write, reserved write"); + + my $noderes_result = + DBQueryFatal("select node_id from node_reservations where pid='$pid'"); + my $query_result = DBQueryFatal("select * from project_reservations where pid='$pid'"); if (!$query_result->numrows) { @@ -444,6 +503,36 @@ sub StartReservation($) } } + # + # If we have a node list, then we do not do any type stuff, we + # operate on specific nodes. + # + if ($noderes_result->numrows) { + @types = (); + + while (my ($node_id) = $noderes_result->fetchrow_array()) { + my $query_result = + DBQueryFatal("select pid,eid from reserved ". + "where node_id='$node_id'"); + + if ($query_result->numrows) { + my ($curpid) = $query_result->fetchrow_array(); + if ($curpid ne $pid) { + # + # Someone else still has it, skip. + # + next; + } + } + # Free or we already have it. + $current++; + DBQueryFatal("delete from node_reservations ". + "where node_id='$node_id'"); + DBQueryFatal("update nodes set reserved_pid='$pid' ". + "where node_id='$node_id'"); + } + } + # # Then check free/allocated nodes of each type. # -- GitLab