Example #1
0
 function scheduleVMsToAvailable($vmids)
 {
     # TODO test with vcld that will handle reservation for noimage okay
     # schedule $vmids to have noimage "loaded" on them in 15 minutes
     $allids = implode(',', $vmids);
     $query = "UPDATE computer " . "SET stateid = 5, " . "notes = '' " . "WHERE id IN ({$allids})";
     doQuery($query);
     $imageid = getImageId('noimage');
     $revid = getProductionRevisionid($imageid);
     $start = time() + 900;
     $end = $start + 3600;
     $startdt = unixToDatetime($start);
     $enddt = unixToDatetime($end);
     $vclreloadid = getUserlistID('vclreload@Local');
     foreach ($vmids as $vmid) {
         // if simpleAddRequest fails, vm is left assigned and in failed state, which is fine
         simpleAddRequest($vmid, $imageid, $revid, $startdt, $enddt, 19, $vclreloadid);
     }
 }
Example #2
0
function AJvmFromHostDelayed()
{
    $data = getContinuationVar();
    $vclreloadid = getUserlistID('vclreload@Local');
    foreach ($data as $comp) {
        $end = datetimeToUnix($comp['end2']) + SECINMONTH;
        $end = unixToDatetime($end);
        simpleAddRequest($comp['id'], 4, 3, $comp['end2'], $end, 18, $vclreloadid);
    }
    header('Content-Type: text/json-comment-filtered; charset=utf-8');
    $cont = addContinuationsEntry('vmhostdata');
    $arr = array('msg' => 'SUCCESS', 'cont' => $cont);
    print '/*{"items":' . json_encode($arr) . '}*/';
}
Example #3
0
function AJvmFromHostDelayed()
{
    $data = getContinuationVar();
    $vclreloadid = getUserlistID('vclreload@Local');
    $imageid = getImageId('noimage');
    $imagerevisionid = getProductionRevisionid($imageid);
    $fails = array();
    foreach ($data as $comp) {
        $end = datetimeToUnix($comp['end2']) + SECINMONTH;
        $end = unixToDatetime($end);
        if (!simpleAddRequest($comp['id'], $imageid, $imagerevisionid, $comp['end2'], $end, 18, $vclreloadid)) {
            $fails[] = array('name' => $comp['hostname'], 'reason' => 'nomgtnode');
        }
    }
    $cont = addContinuationsEntry('vmhostdata');
    $arr = array('msg' => 'SUCCESS', 'cont' => $cont, 'fails' => $fails);
    sendJSON($arr);
}
Example #4
0
function XMLRPCprocessBlockTime($blockTimesid, $ignoreprivileges = 0)
{
    global $requestInfo, $user, $xmlrpcBlockAPIUsers;
    if (!in_array($user['id'], $xmlrpcBlockAPIUsers)) {
        return array('status' => 'error', 'errorcode' => 34, 'errormsg' => 'access denied for managing block allocations');
    }
    $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('vclreload@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;
        }
        $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);
        if ($reqid == 0) {
            continue;
        }
        $stagCnt++;
        $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;
}
Example #5
0
function submitCompStateChange()
{
    global $user;
    print "<H2>Change State of Computers</H2>\n";
    $data = getContinuationVar();
    $computers = getComputers(1);
    # switching to available
    if ($data['stateid'] == 2) {
        $compids = implode(',', $data['computerids']);
        $query = "UPDATE computer " . "SET stateid = 2, " . "notes = '' " . "WHERE id IN ({$compids})";
        doQuery($query, 101);
        print "The following computers were changed to the available state:\n";
        print "<TABLE>\n";
        foreach ($data['computerids'] as $compid) {
            print "  <TR>\n";
            print "    <TD>{$computers[$compid]['hostname']}</TD>\n";
            print "  </TR>\n";
        }
        print "</TABLE>\n";
    } elseif ($data['stateid'] == 10) {
        $data['notes'] = processInputVar('notes', ARG_STRING);
        if (get_magic_quotes_gpc()) {
            $data['notes'] = stripslashes($data['notes']);
        }
        $data['notes'] = mysql_escape_string($data['notes']);
        $data["notes"] = $user["unityid"] . " " . unixToDatetime(time()) . "@" . $data["notes"];
        $vclreloadid = getUserlistID('vclreload@Local');
        // get semaphore lock
        if (!semLock()) {
            abort(3);
        }
        $noaction = array();
        $changenow = array();
        $changeasap = array();
        $changetimes = array();
        foreach ($data['computerids'] as $compid) {
            if ($computers[$compid]['state'] == 'maintenance') {
                array_push($noaction, $compid);
            } else {
                array_push($changeasap, $compid);
            }
        }
        $passes = array();
        $fails = array();
        foreach ($changeasap as $compid) {
            # TODO what about blockComputers?
            # try to move future reservations off of computer
            moveReservationsOffComputer($compid);
            # get end time of last reservation
            $query = "SELECT rq.end " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = {$compid} AND " . "rq.stateid NOT IN (1,5,12) " . "ORDER BY end DESC " . "LIMIT 1";
            $qh = doQuery($query, 101);
            # create a really long reservation starting at that time in state tomaintenance
            if ($row = mysql_fetch_assoc($qh)) {
                $start = $row['end'];
                $changetimes[$compid] = $start;
                $end = datetimeToUnix($start) + SECINWEEK;
                // hopefully keep future reservations off of it
                $end = unixToDatetime($end);
                if (simpleAddRequest($compid, 4, 3, $start, $end, 18, $vclreloadid)) {
                    $passes[] = $compid;
                } else {
                    $fails[] = $compid;
                }
            } else {
                $query = "UPDATE computer " . "SET stateid = 10, " . "notes = '{$data['notes']}' " . "WHERE id = {$compid}";
                doQuery($query, 101);
                unset_by_val($compid, $changeasap);
                array_push($changenow, $compid);
            }
        }
        // release semaphore lock
        semUnlock();
        if (count($noaction) || count($changeasap)) {
            $comparr = array_merge($noaction, $changeasap);
            $compids = implode(',', $comparr);
            $query = "UPDATE computer " . "SET notes = '{$data['notes']}' " . "WHERE id IN ({$compids})";
            doQuery($query, 101);
        }
        if (count($changenow)) {
            print "The following computers were immediately placed into the ";
            print "maintenance state:\n";
            print "<TABLE>\n";
            foreach ($changenow as $compid) {
                print "  <TR>\n";
                print "    <TD><font color=\"#008000\">{$computers[$compid]['hostname']}</font></TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
        if (count($passes)) {
            print "The following computers currently have reservations on them ";
            print "and will be placed in the maintenance state at the time listed ";
            print "for each computer:\n";
            print "<TABLE>\n";
            print "  <TR>\n";
            print "    <TH>Computer</TH>\n";
            print "    <TH>Maintenance time</TH>\n";
            print "  </TR>\n";
            foreach ($passes as $compid) {
                print "  <TR>\n";
                print "    <TD align=center><font color=\"ff8c00\">{$computers[$compid]['hostname']}</font></TD>\n";
                $time = date('n/j/y g:i a', datetimeToUnix($changetimes[$compid]));
                print "    <TD align=center>{$time}</TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
        if (count($fails)) {
            print "The following computers currently have reservations on them ";
            print "but no functional management node was found for them. Nothing ";
            print "be done with them at this time:\n";
            print "<TABLE>\n";
            print "  <TR>\n";
            print "    <TH>Computer</TH>\n";
            print "  </TR>\n";
            foreach ($passes as $compid) {
                print "  <TR>\n";
                print "    <TD align=center><font color=\"ff0000\">{$computers[$compid]['hostname']}</font></TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
        if (count($noaction)) {
            print "The following computers were already in the maintenance ";
            print "state and had their notes on being in the maintenance state ";
            print "updated:\n";
            print "<TABLE>\n";
            foreach ($noaction as $compid) {
                print "  <TR>\n";
                print "    <TD>{$computers[$compid]['hostname']}</TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
    } elseif ($data['stateid'] == 20) {
        $profileid = processInputVar('profileid', ARG_NUMERIC);
        if (!array_key_exists($profileid, $data['profiles'])) {
            $keys = array_keys($data['profiles']);
            $profileid = $keys[0];
        }
        $noaction = array();
        $changenow = array();
        $changeasap = array();
        $changetimes = array();
        foreach ($data['computerids'] as $compid) {
            if ($computers[$compid]['state'] == 'vmhostinuse') {
                array_push($noaction, $compid);
            } else {
                array_push($changeasap, $compid);
            }
        }
        if (!semLock()) {
            abort(3);
        }
        foreach ($changeasap as $compid) {
            # TODO what about blockComputers?
            moveReservationsOffComputer($compid);
            # get end time of last reservation
            $query = "SELECT rq.end " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = {$compid} AND " . "rq.stateid NOT IN (1,5,12) " . "ORDER BY end DESC " . "LIMIT 1";
            $qh = doQuery($query, 101);
            if ($row = mysql_fetch_assoc($qh)) {
                // if there is a reservation, leave in $changeasap so we can
                #   notify that we can't change this one
            } else {
                # create a reload reservation to load machine with image
                #   corresponding to selected vm profile
                $start = getReloadStartTime();
                $end = $start + SECINYEAR;
                # don't want anyone making a future reservation for this machine
                $start = unixToDatetime($start);
                $end = unixToDatetime($end);
                $imagerevisionid = getProductionRevisionid($data['profiles'][$profileid]['imageid']);
                $vclreloadid = getUserlistID('vclreload@Local');
                simpleAddRequest($compid, $data['profiles'][$profileid]['imageid'], $imagerevisionid, $start, $end, 21, $vclreloadid);
                unset_by_val($compid, $changeasap);
                array_push($changenow, $compid);
                # check for existing vmhost entry
                $query = "SELECT id, " . "vmprofileid " . "FROM vmhost " . "WHERE computerid = {$compid}";
                $qh = doQuery($query, 101);
                if ($row = mysql_fetch_assoc($qh)) {
                    if ($row['vmprofileid'] != $profileid) {
                        # update vmprofile
                        $query = "UPDATE vmhost " . "SET vmprofileid = {$profileid} " . "WHERE id = {$row['id']}";
                        doQuery($query, 101);
                    }
                } else {
                    # create vmhost entry
                    $query = "INSERT INTO vmhost " . "(computerid, " . "vmlimit, " . "vmprofileid) " . "VALUES ({$compid}, " . "2, " . "{$profileid})";
                    doQuery($query, 101);
                }
            }
        }
        // release semaphore lock
        semUnlock();
        if (count($changenow)) {
            print "The following computers were placed into the ";
            print "vmhostinuse state:\n";
            print "<TABLE>\n";
            foreach ($changenow as $compid) {
                print "  <TR>\n";
                print "    <TD><font color=\"#008000\">{$computers[$compid]['hostname']}</font></TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
        if (count($changeasap)) {
            print "The following computers currently have reservations on them ";
            print "and cannot be placed in the vmhostinuse state at this time:\n";
            print "<TABLE>\n";
            foreach ($changeasap as $compid) {
                print "  <TR>\n";
                print "    <TD><font color=\"ff0000\">{$computers[$compid]['hostname']}</font></TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
        if (count($noaction)) {
            print "The following computers were already in the vmhostinuse ";
            print "state:\n";
            print "<TABLE>\n";
            foreach ($noaction as $compid) {
                print "  <TR>\n";
                print "    <TD>{$computers[$compid]['hostname']}</TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
    } elseif ($data['stateid'] == 23) {
        $noaction = array();
        $changenow = array();
        $changeasap = array();
        $changetimes = array();
        foreach ($data['computerids'] as $compid) {
            if ($computers[$compid]['state'] == 'hpc') {
                array_push($noaction, $compid);
            } else {
                array_push($changeasap, $compid);
            }
        }
        if (!semLock()) {
            abort(3);
        }
        foreach ($changeasap as $compid) {
            # TODO what about blockComputers?
            moveReservationsOffComputer($compid);
            # get end time of last reservation
            $query = "SELECT rq.end " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = {$compid} AND " . "rq.stateid NOT IN (1,5,12) " . "ORDER BY end DESC " . "LIMIT 1";
            $qh = doQuery($query, 101);
            if ($row = mysql_fetch_assoc($qh)) {
                // if there is a reservation, leave in $changeasap so we can
                #   notify that we can't change this one
            } else {
                $query = "UPDATE computer " . "SET stateid = 23 " . "WHERE id = {$compid}";
                doQuery($query, 101);
                unset_by_val($compid, $changeasap);
                array_push($changenow, $compid);
            }
        }
        // release semaphore lock
        semUnlock();
        if (count($changenow)) {
            print "The following computers were placed into the ";
            print "hpc state:\n";
            print "<TABLE>\n";
            foreach ($changenow as $compid) {
                print "  <TR>\n";
                print "    <TD><font color=\"#008000\">{$computers[$compid]['hostname']}</font></TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
        if (count($changeasap)) {
            print "The following computers currently have reservations on them ";
            print "and cannot be placed in the hpc state at this time:\n";
            print "<TABLE>\n";
            foreach ($changeasap as $compid) {
                print "  <TR>\n";
                print "    <TD><font color=\"ff0000\">{$computers[$compid]['hostname']}</font></TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
        if (count($noaction)) {
            print "The following computers were already in the hpc ";
            print "state:\n";
            print "<TABLE>\n";
            foreach ($noaction as $compid) {
                print "  <TR>\n";
                print "    <TD>{$computers[$compid]['hostname']}</TD>\n";
                print "  </TR>\n";
            }
            print "</TABLE>\n";
            print "<br>\n";
        }
    } else {
        abort(50);
    }
}
Example #6
0
function XMLRPCprocessBlockTime($blockTimesid, $ignoreprivileges = 0)
{
    global $requestInfo, $user, $xmlrpcBlockAPIUsers;
    if (!in_array($user['id'], $xmlrpcBlockAPIUsers)) {
        return array('status' => 'error', 'errorcode' => 34, 'errormsg' => 'access denied for managing block allocations');
    }
    # validate $blockTimesid
    if (!is_numeric($blockTimesid)) {
        return array('status' => 'error', 'errorcode' => 77, 'errormsg' => 'Invalid blockTimesid specified');
    }
    # validate ignoreprivileges
    if (!is_numeric($ignoreprivileges) || $ignoreprivileges < 0 || $ignoreprivileges > 1) {
        return array('status' => 'error', 'errorcode' => 86, 'errormsg' => 'ignoreprivileges must be 0 or 1');
    }
    $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 allocation');
    }
    $images = getImages(0, $rqdata['imageid']);
    if (empty($images)) {
        return array('status' => 'error', 'errorcode' => 10, 'errormsg' => 'invalid image associated with block allocation');
    }
    $unixstart = datetimeToUnix($rqdata['start']);
    $unixend = datetimeToUnix($rqdata['end']);
    $revisionid = getProductionRevisionid($rqdata['imageid']);
    $imgLoadTime = getImageLoadEstimate($rqdata['imageid']);
    if ($imgLoadTime == 0) {
        $imgLoadTime = $images[$rqdata['imageid']]['reloadtime'] * 60;
    }
    $vclreloadid = getUserlistID('vclreload@Local');
    $groupmembers = getUserGroupMembers($rqdata['groupid']);
    $userids = array_keys($groupmembers);
    # add any computers from future reservations users in the group made
    if (!empty($groupmembers)) {
        ## find reservations by users
        $allids = implode(',', $userids);
        $query = "SELECT rq.id AS reqid, " . "UNIX_TIMESTAMP(rq.start) AS start, " . "rq.userid " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rq.userid IN ({$allids}) AND " . "rq.start < '{$rqdata['end']}' AND " . "rq.end > '{$rqdata['start']}' AND " . "rs.imageid = {$rqdata['imageid']} AND " . "rs.computerid NOT IN (SELECT computerid " . "FROM blockComputers " . "WHERE blockTimeid = {$blockTimesid})";
        $qh = doQuery($query);
        $donereqids = array();
        $blockCompVals = array();
        $checkstartbase = $unixstart - $imgLoadTime - 300;
        $reloadstartbase = unixToDatetime($checkstartbase);
        $rows = mysql_num_rows($qh);
        while ($row = mysql_fetch_assoc($qh)) {
            if (array_key_exists($row['reqid'], $donereqids)) {
                continue;
            }
            $donereqids[$row['reqid']] = 1;
            if ($row['start'] < datetimeToUnix($rqdata['start'])) {
                $checkstart = $row['start'] - $imgLoadTime - 300;
                $reloadstart = unixToDatetime($checkstart);
                $reloadend = unixToDatetime($row['start']);
            } else {
                $checkstart = $checkstartbase;
                $reloadstart = $reloadstartbase;
                $reloadend = $rqdata['start'];
            }
            # check to see if computer is available for whole block
            $rc = isAvailable($images, $rqdata['imageid'], $revisionid, $checkstart, $unixend, 1, $row['reqid'], $row['userid'], $ignoreprivileges, 0, '', '', 1);
            // if not available for whole block, just skip this one
            if ($rc < 1) {
                continue;
            }
            $compid = $requestInfo['computers'][0];
            # create reload reservation
            $reqid = simpleAddRequest($compid, $rqdata['imageid'], $revisionid, $reloadstart, $reloadend, 19, $vclreloadid);
            if ($reqid == 0) {
                continue;
            }
            # add to blockComputers
            $blockCompVals[] = "({$blockTimesid}, {$compid}, {$rqdata['imageid']}, {$reqid})";
            # 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}, {$reqid})";
                $query = "INSERT INTO reservation " . "(requestid, " . "computerid, " . "imageid, " . "imagerevisionid, " . "managementnodeid) " . "VALUES " . "({$reqid}, " . "{$compid}, " . "{$subimageid}, " . "{$subrevid}, " . "{$mgmtnodeid})";
                doQuery($query, 101);
            }
        }
        if (count($blockCompVals)) {
            $blockComps = implode(',', $blockCompVals);
            $query = "INSERT INTO blockComputers " . "(blockTimeid, computerid, imageid, reloadrequestid) " . "VALUES {$blockComps}";
            doQuery($query);
        }
        cleanSemaphore();
    }
    # 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'];
    if (array_key_exists('subimages', $images[$rqdata['imageid']])) {
        $compsPerAlloc = 1 + count($images[$rqdata['imageid']]['subimages']);
    } else {
        $compsPerAlloc = 1;
    }
    $toallocate = $rqdata['numMachines'] * $compsPerAlloc - $compCompleted;
    if ($toallocate == 0) {
        if (count($blockCompVals)) {
            return array('status' => 'success', 'allocated' => $rqdata['numMachines'], 'unallocated' => 0);
        }
        return array('status' => 'completed');
    }
    $reqToAlloc = $toallocate / $compsPerAlloc;
    if (!$ignoreprivileges) {
        # get userids in user group
        if (empty($groupmembers)) {
            return array('status' => 'error', 'errorcode' => 11, 'errormsg' => 'empty user group and ignoreprivileges set to 0');
        }
        # 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, do not worry about
    #   previous processing of this block time) such that there is 1 minute
    #   between the start times for each allocation
    $stagExtra = $reqToAlloc * 60;
    # determine estimated load time
    $loadtime = $imgLoadTime + 10 * 60;
    # add 10 minute fudge factor
    if (time() + $loadtime + $stagExtra > $unixstart) {
        $return['status'] = 'warning';
        $return['warningcode'] = 13;
        $return['warningmsg'] = 'possibly insufficient time to load machines';
    }
    $start = unixToDatetime($unixstart - $loadtime);
    $userid = 0;
    $allocated = 0;
    $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;
    $stagTime = 60;
    # stagger reload reservations by 1 min
    if ($imgLoadTime > 840) {
        // if estimated load time is > 14 min
        $stagTime = 120;
    }
    #    stagger reload reservations by 2 min
    for ($i = 0; $i < $reqToAlloc; $i++) {
        $stagunixstart = $unixstart - $loadtime - $stagCnt * $stagTime;
        $stagstart = unixToDatetime($stagunixstart);
        if (!$ignoreprivileges) {
            $userid = array_pop($userids);
        }
        # use end of block time to find available computers, but...
        $rc = isAvailable($images, $rqdata['imageid'], $revisionid, $stagunixstart, $unixend, 1, 0, $userid, $ignoreprivileges);
        if ($rc < 1) {
            continue;
        }
        $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);
        if ($reqid == 0) {
            continue;
        }
        $stagCnt++;
        $allocated++;
        $blockCompVals[] = "({$blockTimesid}, {$compid}, {$rqdata['imageid']}, {$reqid})";
        # 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}, {$reqid})";
            $query = "INSERT INTO reservation " . "(requestid, " . "computerid, " . "imageid, " . "imagerevisionid, " . "managementnodeid) " . "VALUES " . "({$reqid}, " . "{$compid}, " . "{$subimageid}, " . "{$subrevid}, " . "{$mgmtnodeid})";
            doQuery($query, 101);
        }
        $blockComps = implode(',', $blockCompVals);
        $query = "INSERT INTO blockComputers " . "(blockTimeid, computerid, imageid, reloadrequestid) " . "VALUES {$blockComps}";
        doQuery($query, 101);
        cleanSemaphore();
        $blockCompVals = array();
    }
    if ($allocated == 0) {
        $return['status'] = 'warning';
        $return['warningcode'] = 14;
        $return['warningmsg'] = 'unable to allocate any machines';
    }
    $return['allocated'] = $compCompleted / $compsPerAlloc + $allocated;
    $return['unallocated'] = $rqdata['numMachines'] - $return['allocated'];
    return $return;
}