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


Reply via email to