Author: jfthomps
Date: Wed Mar 11 19:09:12 2009
New Revision: 752583
URL: http://svn.apache.org/viewvc?rev=752583&view=rev
Log:
VCL-78
xmlrpcWrappers.php:
-added XMLRPCblockAllocation
-added XMLRPCprocessBlockTime
utils.php:
-added dbLastInsertID as an easier way to get the last insert id for inserts
into tables with auto incremented ids
-modified isAvailable: added $ignoreprivileges as an optional argument which
allows for user access privileges to be ignored when allocating computers
-modified getAvailableBlockComputerids: added $allocatedcompids as an argument
which is an array of computers that should not be included in the returned list
-modified xmlrpccall: added XMLRPCblockAllocation and XMLRPCprocessBlockTime as
registered functions
Modified:
incubator/vcl/trunk/web/.ht-inc/utils.php
incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php
Modified: incubator/vcl/trunk/web/.ht-inc/utils.php
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/utils.php?rev=752583&r1=752582&r2=752583&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/utils.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/utils.php Wed Mar 11 19:09:12 2009
@@ -1279,6 +1279,20 @@
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn dbLastInsertID()
+///
+/// \return last insert id for $mysql_link_vcl
+///
+/// \brief calls mysql_insert_id for $mysql_link_vcl
+///
+////////////////////////////////////////////////////////////////////////////////
+function dbLastInsertID() {
+ global $mysql_link_vcl;
+ return mysql_insert_id($mysql_link_vcl);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn getOSList()
///
/// \return $oslist - array of OSs
@@ -1317,7 +1331,7 @@
/// \b minprocspeed - minimum speed of processor(s) needed for image\n
/// \b minnetwork - minimum speed of network needed for image\n
/// \b maxconcurrent - maximum concurrent usage of this iamge\n
-/// \b reloadtime - time in minutes for image to loaded\n
+/// \b reloadtime - time in minutes for image to be loaded\n
/// \b deleted - 'yes' or 'no'; whether or not this image has been deleted\n
/// \b test - 0 or 1; whether or not there is a test version of this image\n
/// \b resourceid - image's resource id from the resource table\n
@@ -3359,7 +3373,7 @@
////////////////////////////////////////////////////////////////////////////////
///
/// \fn isAvailable($images, $imageid, $start, $end, $os, $requestid,
-/// $userid)
+/// $userid, $ignoreprivileges)
///
/// \param $images - array as returned from getImages
/// \param $imageid - imageid from the image table
@@ -3370,6 +3384,10 @@
/// timeslot to update a request, pass the request id that will be updated;
/// otherwise, don't pass this argument
/// \param $userid - (optional) id from user table
+/// \param $ignoreprivileges (optional, default=0) - 0 (false) or 1 (true) -
set
+/// to 1 to look for computers from any that are mapped to be able to run the
+/// image; set to 0 to only look for computers from ones that are both mapped
+/// and that $userid has been granted access to through the privilege tree
///
/// \return -1 if $imageid is limited in the number of concurrent reservations
/// available, and the limit has been reached
@@ -3380,7 +3398,7 @@
///
////////////////////////////////////////////////////////////////////////////////
function isAvailable($images, $imageid, $start, $end, $os, $requestid=0,
- $userid=0) {
+ $userid=0, $ignoreprivileges=0) {
global $requestInfo;
$requestInfo["start"] = $start;
$requestInfo["end"] = $end;
@@ -3525,10 +3543,12 @@
// otherwise, build a list of computers
else {
# get list of available computers
- $resources = getUserResources(array("imageAdmin",
"imageCheckOut"),
- array("available"), 0, 0,
$userid);
- $computers = implode("','",
array_keys($resources["computer"]));
- $computers = "'$computers'";
+ if(! $ignoreprivileges) {
+ $resources =
getUserResources(array("imageAdmin", "imageCheckOut"),
+
array("available"), 0, 0, $userid);
+ $usercomputers = implode("','",
array_keys($resources["computer"]));
+ $usercomputers = "'$usercomputers'";
+ }
$alloccompids = implode(",", $allocatedcompids);
$schedules = implode(',', $scheduleids);
@@ -3554,9 +3574,10 @@
. "c.RAM >= i.minram AND "
. "c.procnumber >= i.minprocnumber AND "
. "c.procspeed >= i.minprocspeed AND "
- . "c.network >= i.minnetwork AND "
- . "c.id IN ($computers) AND "
- . "c.id IN ($mappedcomputers) AND "
+ . "c.network >= i.minnetwork AND ";
+ if(! $ignoreprivileges)
+ $query .= "c.id IN ($usercomputers) AND ";
+ $query .= "c.id IN ($mappedcomputers) AND "
. "c.id NOT IN ($alloccompids) "
. "ORDER BY (c.procspeed * c.procnumber) DESC, "
. "RAM DESC, "
@@ -3569,7 +3590,8 @@
}
}
# get computer ids available from block reservations
- $blockids = getAvailableBlockComputerids($imageid,
$start, $end);
+ $blockids = getAvailableBlockComputerids($imageid,
$start, $end,
+
$allocatedcompids);
}
#remove computers from list that are already scheduled
@@ -3791,7 +3813,8 @@
}
}
# get computer ids available from block reservations
- $blockids = getAvailableBlockComputerids($imageid, $start,
$end);
+ $blockids = getAvailableBlockComputerids($imageid, $start, $end,
+ $allocatedcompids);
# remove computers from list that are already scheduled
$usedComputerids = array();
@@ -6360,11 +6383,13 @@
////////////////////////////////////////////////////////////////////////////////
///
-/// \fn getAvailableBlockComputerids($imageid, $start, $end)
+/// \fn getAvailableBlockComputerids($imageid, $start, $end, $allocatedcompids)
///
/// \param $imageid - id of an image
/// \param $start - starting time in unix timestamp form
/// \param $end - ending time in unix timestamp form
+/// \param $allocatedcompids - array of computer ids that have already been
+/// allocated while processing this request
///
/// \return an array of computer ids
///
@@ -6372,7 +6397,7 @@
/// in user is a part of that are available between $start and $end
///
////////////////////////////////////////////////////////////////////////////////
-function getAvailableBlockComputerids($imageid, $start, $end) {
+function getAvailableBlockComputerids($imageid, $start, $end,
$allocatedcompids) {
global $user;
$compids = array();
$groupids = implode(',', array_keys($user['groups']));
@@ -6380,6 +6405,7 @@
$groupids = "''";
$startdt = unixToDatetime($start);
$enddt = unixToDatetime($end);
+ $alloccompids = implode(",", $allocatedcompids);
$query = "SELECT c.computerid "
. "FROM blockComputers c, "
. "blockRequest r, "
@@ -6387,15 +6413,16 @@
. "state s, "
. "computer c2 "
. "WHERE r.groupid IN ($groupids) AND "
- . "r.imageid = $imageid AND "
+ . "c.computerid = c2.id AND "
+ . "c2.currentimageid = $imageid AND "
. "r.expireTime > NOW() AND "
. "t.blockRequestid = r.id AND "
. "c.blockTimeid = t.id AND "
. "t.start < '$enddt' AND "
. "t.end > '$startdt' AND "
- . "c.computerid = c2.id AND "
. "c2.stateid = s.id AND "
- . "s.name != 'failed' "
+ . "s.name != 'failed' AND "
+ . "c2.id NOT IN ($alloccompids) "
. "ORDER BY s.name";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
@@ -8069,6 +8096,8 @@
xmlrpc_server_register_method($xmlrpc_handle,
"XMLRPCgetRequestConnectData", "xmlRPChandler");
xmlrpc_server_register_method($xmlrpc_handle, "XMLRPCendRequest",
"xmlRPChandler");
xmlrpc_server_register_method($xmlrpc_handle, "XMLRPCgetRequestIds",
"xmlRPChandler");
+ xmlrpc_server_register_method($xmlrpc_handle, "XMLRPCblockAllocation",
"xmlRPChandler");
+ xmlrpc_server_register_method($xmlrpc_handle, "XMLRPCprocessBlockTime",
"xmlRPChandler");
print xmlrpc_server_call_method($xmlrpc_handle, $HTTP_RAW_POST_DATA,
'');
xmlrpc_server_destroy($xmlrpc_handle);
Modified: incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php?rev=752583&r1=752582&r2=752583&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php Wed Mar 11 19:09:12 2009
@@ -448,6 +448,294 @@
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn XMLRPCblockAllocation($imageid, $start, $end, $requestcount,
+/// $usergroupid, $ignoreprivileges)
+///
+/// \param $imageid - id of the image to be used
+/// \param $start - mysql datetime for the start time (i.e. requests should be
+/// prep'd and ready by this time)
+/// \param $end - mysql datetime for the end time
+/// \param $requestcount - number of computers to allocate
+/// \param $usergroupid - id of user group for checking user access to machines
+/// \param $ignoreprivileges (optional, default=0) - 0 (false) or 1 (true) -
set
+/// to 1 to select computers from any that are mapped to be able to run the
+/// image; set to 0 to only select computers from ones that are both mapped and
+/// that users in the usergroup assigned to this block request have been
granted
+/// access to through the privilege tree
+///
+/// \return an array with blockTimesid as an index with the value of the newly
+/// created block time and at least one other index named 'status' which will
+/// have one of these values\n
+/// \b error - error occurred; there will be 2 additional elements in the
array:
+/// \li \b errorcode - error number\n
+/// \li \b errormsg - error string\n
+/// \b success - blockTimesid was processed; there will be two additional
+/// elements in this case:\n
+/// \li \b allocated - total number of desired requests that have been
+/// allocated\n
+/// \li \b unallocated - total number of desired requests that have not been
+/// allocated\n
+/// \b warning - there was a non-fatal issue that occurred while processing
+/// the call; there will be four additional elements in this case:\n
+/// \li \b warningcode - warning number\n
+/// \li \b warningmsg - warning string\n
+/// \li \b allocated - total number of desired requests that have been
+/// allocated\n
+/// \li \b unallocated - total number of desired requests that have not been
+/// allocated\n
+/// note that status may be warning, but allocated may be 0 indicating there
+/// were no errors that occurred, but there simply were not any machines
+/// available\n
+///
+/// \brief creates and processes a block reservation according to the passed
+/// in criteria
+///
+////////////////////////////////////////////////////////////////////////////////
+function XMLRPCblockAllocation($imageid, $start, $end, $requestcount,
+ $usergroupid, $ignoreprivileges=0) {
+ $ownerid = getUserlistID('vclrel...@local');
+ $name = "API:$start";
+ $managementnodes = getManagementNodes('future');
+ if(empty($managementnodes)) {
+ return array('status' => 'error',
+ 'errorcode' => 12,
+ 'errormsg' => 'could not allocate a management
node to handle block allocation');
+ }
+ $mnid = array_rand($managementnodes);
+ $query = "INSERT INTO blockRequest "
+ . "(name, "
+ . "imageid, "
+ . "numMachines, "
+ . "groupid, "
+ . "repeating, "
+ . "ownerid, "
+ . "admingroupid, "
+ . "managementnodeid, "
+ . "expireTime) "
+ . "VALUES "
+ . "('$name', "
+ . "$imageid, "
+ . "$requestcount, "
+ . "$usergroupid, "
+ . "'list', "
+ . "$ownerid, "
+ . "0, "
+ . "$mnid, "
+ . "'$end')";
+ doQuery($query, 101);
+ $brid = dbLastInsertID();
+ $query = "INSERT INTO blockTimes "
+ . "(blockRequestid, "
+ . "start, "
+ . "end) "
+ . "VALUES "
+ . "($brid, "
+ . "'$start', "
+ . "'$end')";
+ doQuery($query, 101);
+ $btid = dbLastInsertID();
+ $return = XMLRPCprocessBlockTime($btid, $ignoreprivileges);
+ $return['blockTimesid'] = $btid;
+ return $return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn XMLRPCprocessBlockTime($blockTimesid, $ignoreprivileges)
+///
+/// \param $blockTimesid - id from the blockTimes table
+/// \param $ignoreprivileges (optional, default=0) - 0 (false) or 1 (true) -
set
+/// to 1 to select computers from any that are mapped to be able to run the
+/// image; set to 0 to only select computers from ones that are both mapped and
+/// that users in the usergroup assigned to this block request have been
granted
+/// access to through the privilege tree
+///
+/// \return an array with at least one index named 'status' which will have
+/// one of these values\n
+/// \b error - error occurred; there will be 2 additional elements in the
array:
+/// \li \b errorcode - error number\n
+/// \li \b errormsg - error string\n
+/// \b completed - blockTimesid was previously successfully processed\n
+/// \b success - blockTimesid was processed; there will be two additional
+/// elements in this case:\n
+/// \li \b allocated - total number of desired requests that have been
+/// allocated\n
+/// \li \b unallocated - total number of desired requests that have not been
+/// allocated\n
+/// \b warning - there was a non-fatal issue that occurred while processing
+/// the call; there will be four additional elements in this case:\n
+/// \li \b warningcode - warning number\n
+/// \li \b warningmsg - warning string\n
+/// \li \b allocated - total number of desired requests that have been
+/// allocated\n
+/// \li \b unallocated - total number of desired requests that have not been
+/// allocated\n
+/// note that status may be warning, but allocated may be 0 indicating there
+/// were no errors that occurred, but there simply were not any machines
+/// available\n
+///
+/// \brief processes a block reservation for the blockTimes entry associated
+/// with blockTimesid
+///
+////////////////////////////////////////////////////////////////////////////////
+function XMLRPCprocessBlockTime($blockTimesid, $ignoreprivileges=0) {
+ global $requestInfo;
+ $return = array('status' => 'success');
+ $query = "SELECT bt.start, "
+ . "bt.end, "
+ . "br.imageid, "
+ . "br.numMachines, "
+ . "br.groupid, "
+ . "br.expireTime "
+ . "FROM blockRequest br, "
+ . "blockTimes bt "
+ . "WHERE bt.blockRequestid = br.id AND "
+ . "bt.id = $blockTimesid";
+ $qh = doQuery($query, 101);
+ if(! $rqdata = mysql_fetch_assoc($qh)) {
+ return array('status' => 'error',
+ 'errorcode' => 8,
+ 'errormsg' => 'unknown blockTimesid');
+ }
+ if(datetimeToUnix($rqdata['expireTime']) < time()) {
+ return array('status' => 'error',
+ 'errorcode' => 9,
+ 'errormsg' => 'expired block reservation');
+ }
+
+ $images = getImages(0, $rqdata['imageid']);
+ if(empty($images)) {
+ return array('status' => 'error',
+ 'errorcode' => 10,
+ 'errormsg' => 'invalid image associated with block
request');
+ }
+
+ # check to see if all computers have been allocated
+ $query = "SELECT COUNT(computerid) AS allocated "
+ . "FROM blockComputers "
+ . "WHERE blockTimeid = $blockTimesid";
+ $qh = doQuery($query, 101);
+ if(! $row = mysql_fetch_assoc($qh)) {
+ return array('status' => 'error',
+ 'errorcode' => 15,
+ 'errormsg' => 'failure to communicate with
database');
+ }
+ $compCompleted = $row['allocated'];
+ $compsPerRequest = 1 + count($images[$rqdata['imageid']]['subimages']);
+ $toallocate = ($rqdata['numMachines'] * $compsPerRequest) -
$compCompleted;
+ if($toallocate == 0)
+ return array('status' => 'completed');
+ $reqToAlloc = $toallocate / $compsPerRequest;
+
+ if(! $ignoreprivileges) {
+ # get userids in user group
+ $tmp = getUserGroupMembers($rqdata['groupid']);
+ if(empty($tmp)) {
+ return array('status' => 'error',
+ 'errorcode' => 11,
+ 'errormsg' => 'empty user group and
ignoreprivileges set to 0');
+ }
+ $userids = array_keys($tmp);
+ # make length of $userids match $reqToAlloc by duplicating or
trimming some users
+ while($reqToAlloc > count($userids))
+ $userids = array_merge($userids, $userids);
+ if($reqToAlloc < count($userids))
+ $userids = array_splice($userids, 0, $reqToAlloc);
+ }
+
+ # staggering: stagger start times for this round (ie, don't worry about
+ # previous processing of this block time) such that there is 1 minute
+ # between the start times for each request
+ $stagExtra = $reqToAlloc * 60;
+
+ # determine estimated load time
+ $imgLoadTime = getImageLoadEstimate($rqdata['imageid']);
+ if($imgLoadTime == 0)
+ $imgLoadTime = $images[$rqdata['imageid']]['reloadtime'] * 60;
+ $loadtime = $imgLoadTime + (10 * 60); # add 10 minute fudge factor
+ $unixstart = datetimeToUnix($rqdata['start']);
+ if((time() + $loadtime + $stagExtra) > $unixstart) {
+ $return['status'] = 'warning';
+ $return['warningcode'] = 13;
+ $return['warningmsg'] = 'possibly insufficient time to load
machines';
+ }
+ $start = unixToDatetime($unixstart - $loadtime);
+ $unixend = datetimeToUnix($rqdata['end']);
+
+ $userid = 0;
+ $allocated = 0;
+ $vclreloadid = getUserlistID('vclrel...@local');
+ $revisionid = getProductionRevisionid($rqdata['imageid']);
+ $blockCompVals = array();
+ # FIXME (maybe) - if some subset of users in the user group have
available
+ # computers, but others do not, $allocated will be less than the desired
+ # number of machines; however, calling this function enough times will
+ # result in enough machines being allocated because they will continue
to be
+ # allocated based on the ones with machines available; this seems like
odd
+ # behavior
+ $stagCnt = 0;
+ for($i = 0; $i < $reqToAlloc; $i++) {
+ $stagunixstart = $unixstart - $loadtime - ($stagCnt * 60);
+ $stagstart = unixToDatetime($stagunixstart);
+ if(! $ignoreprivileges)
+ $userid = array_pop($userids);
+ # use end of block time to find available computers, but...
+ $rc = isAvailable($images, $rqdata['imageid'], $stagunixstart,
+ $unixend, 0, 0, $userid, $ignoreprivileges);
+ if($rc < 1)
+ continue;
+
+ $stagCnt++;
+
+ $compid = $requestInfo['computers'][0];
+ # ...use start of block time as end of reload reservation
+ $reqid = simpleAddRequest($compid, $rqdata['imageid'],
$revisionid,
+ $stagstart, $rqdata['start'], 19,
$vclreloadid);
+ $allocated++;
+ $blockCompVals[] = "($blockTimesid, $compid,
{$rqdata['imageid']})";
+
+ # process any subimages
+ for($key = 1; $key < count($requestInfo['computers']); $key++) {
+ $subimageid = $requestInfo['images'][$key];
+ $subrevid = getProductionRevisionid($subimageid);
+ $compid = $requestInfo['computers'][$key];
+ $mgmtnodeid = $requestInfo['mgmtnodes'][$key];
+ $blockCompVals[] = "($blockTimesid, $compid,
$subimageid)";
+
+ $query = "INSERT INTO reservation "
+ . "(requestid, "
+ . "computerid, "
+ . "imageid, "
+ . "imagerevisionid, "
+ . "managementnodeid) "
+ . "VALUES "
+ . "($reqid, "
+ . "$compid, "
+ . "$subimageid, "
+ . "$subrevid, "
+ . "$mgmtnodeid)";
+ doQuery($query, 101);
+ }
+ semUnlock();
+ $blockComps = implode(',', $blockCompVals);
+ $query = "INSERT INTO blockComputers "
+ . "(blockTimeid, computerid, imageid) "
+ . "VALUES $blockComps";
+ doQuery($query, 101);
+ $blockCompVals = array();
+ }
+ if($allocated == 0) {
+ $return['status'] = 'warning';
+ $return['warningcode'] = 14;
+ $return['warningmsg'] = 'unable to allocate any machines';
+ }
+ $return['allocated'] = ($compCompleted / $compsPerRequest) + $allocated;
+ $return['unallocated'] = $rqdata['numMachines'] - $return['allocated'];
+ return $return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn XMLRPCtest($string)
///
/// \param $string - a string