示例#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);
     }
 }
示例#2
0
function processRequestInput()
{
    global $user;
    $baseaccess = getContinuationVar('baseaccess', 0);
    $imagingaccess = getContinuationVar('imagingaccess', 0);
    $serveraccess = getContinuationVar('serveraccess', 0);
    $openend = getContinuationVar('openend', 0);
    $nousercheck = getContinuationVar('nousercheck', 0);
    $return['imaging'] = getContinuationVar('imaging', 0);
    $maxinitial = getContinuationVar('maxinitial', 0);
    $noimaging = getContinuationVar('noimaging', array());
    $return = array('err' => 0);
    # type
    $return['type'] = processInputVar('type', ARG_STRING);
    if (!preg_match('/^basic|imaging|server$/', $return['type'])) {
        $return['err'] = 1;
        $return['errmsg'] = i('Invalid data submitted');
        return $return;
    }
    if ($return['type'] == 'basic' && !$baseaccess || $return['type'] == 'imaging' && !$imagingaccess || $return['type'] == 'server' && !$serveraccess) {
        $return['err'] = 1;
        $return['errmsg'] = i('No access to submitted reservation type');
        return $return;
    }
    # ending
    $return['ending'] = processInputVar('ending', ARG_STRING);
    if (!preg_match('/^indefinite|endat|duration$/', $return['ending'])) {
        $return['err'] = 1;
        $return['errmsg'] = i('Invalid data submitted');
        return $return;
    }
    if ($return['ending'] == 'duration' && !$baseaccess || $return['ending'] == 'indefinite' && !$serveraccess || $return['ending'] == 'endat' && !$openend && !$serveraccess) {
        $return['err'] = 1;
        $return['errmsg'] = i('No access to submitted end type');
        return $return;
    }
    # imageid
    $return['imageid'] = processInputVar('imageid', ARG_NUMERIC);
    $resources = getUserResources(array("imageAdmin", "imageCheckOut"));
    $withnocheckout = $resources['image'];
    $images = removeNoCheckout($resources["image"]);
    $extraimages = getServerProfileImages($user['id']);
    if (!array_key_exists($return['imageid'], $images) && ($return['type'] != 'server' || !array_key_exists($return['imageid'], $extraimages)) && ($return['type'] != 'imaging' || !array_key_exists($return['imageid'], $withnocheckout)) || $return['type'] == 'imaging' && array_key_exists($return['imageid'], $noimaging)) {
        $return['err'] = 1;
        $return['errmsg'] = i('No access to submitted environment');
        return $return;
    }
    # nousercheck
    $return['nousercheck'] = processInputVar('nousercheck', ARG_NUMERIC);
    if (!$nousercheck || $return['nousercheck'] != 1) {
        $return['nousercheck'] = 0;
    }
    # revisionid
    $revids = processInputVar("revisionid", ARG_STRING);
    $revids = explode(':', $revids);
    $images = getImages(0, $return['imageid']);
    $return['revisionids'] = array();
    if (array_key_exists('subimages', $images[$return['imageid']])) {
        $subimages = $images[$return['imageid']]['subimages'];
        array_unshift($subimages, $return['imageid']);
        foreach ($subimages as $key => $imgid) {
            $revisions = getImageRevisions($imgid);
            if (!array_key_exists($key, $revids) || !is_numeric($revids[$key]) || !array_key_exists($revids[$key], $revisions)) {
                $revid = getProductionRevisionid($imgid);
            } else {
                $revid = $revids[$key];
            }
            if (!array_key_exists($imgid, $return['revisionids'])) {
                $return['revisionids'][$imgid] = array();
            }
            $return['revisionids'][$imgid][] = $revid;
        }
    } elseif ($revids[0] != '' && is_numeric($revids[0])) {
        $return['revisionids'][$return['imageid']][] = $revids[0];
    } else {
        $return['revisionids'][$return['imageid']][] = getProductionRevisionid($return['imageid']);
    }
    # duration
    if ($return['ending'] == 'duration') {
        $return['duration'] = processInputVar('duration', ARG_NUMERIC, 0);
        if ($return['duration'] > $maxinitial) {
            $return['duration'] = $maxinitial;
        }
    }
    # start/end
    $return['start'] = processInputVar('start', ARG_NUMERIC);
    $return['end'] = processInputVar('end', ARG_NUMERIC, 0);
    $now = time();
    if ($return['start'] == 0) {
        $start = $now;
    } else {
        $start = $return['start'];
    }
    if ($return['ending'] == 'endat') {
        $end = $return['end'];
    }
    if ($return['ending'] == 'indefinite') {
        $end = datetimeToUnix('2038-01-01 00:00:00');
    } elseif ($return['ending'] == 'duration') {
        $end = $start + $return['duration'] * 60;
    }
    if ($start < $now) {
        $return['err'] = 1;
        $return['errmsg'] = i('The submitted start time is in the past.');
        return $return;
    }
    if ($start + 900 > $end) {
        $return['err'] = 1;
        $return['errmsg'] = i('The end time must be at least 15 minutes later than the start time.');
        return $return;
    }
    $return['ipaddr'] = '';
    $return['macaddr'] = '';
    # server specific input
    if ($return['type'] == 'server') {
        # name
        $return['name'] = processInputVar('name', ARG_STRING);
        if (!preg_match('/^([-a-zA-Z0-9_\\. ]){0,255}$/', $return['name'])) {
            $return['err'] = 1;
            $return['errmsg'] = i('The reservation name can only contain letters, numbers, spaces, dashes(-), underscores(_), and periods(.) and can be up to 255 characters long');
            return $return;
        }
        # ipaddr
        $return['ipaddr'] = processInputVar('ipaddr', ARG_STRING);
        if ($return['ipaddr'] != '') {
            # validate fixed IP address
            if (!validateIPv4addr($return['ipaddr'])) {
                $return['err'] = 1;
                $return['errmsg'] = i('Invalid IP address. Must be w.x.y.z with each of w, x, y, and z being between 1 and 255 (inclusive)');
                return $return;
            }
            # validate netmask
            $return['netmask'] = processInputVar('netmask', ARG_STRING);
            $bnetmask = ip2long($return['netmask']);
            if (!preg_match('/^[1]+0[^1]+$/', sprintf('%032b', $bnetmask))) {
                $return['err'] = 1;
                $return['errmsg'] = i('Invalid netmask specified');
                return $return;
            }
            # validate router
            $return['router'] = processInputVar('router', ARG_STRING);
            if (!validateIPv4addr($return['router'])) {
                $return['err'] = 1;
                $return['errmsg'] = i('Invalid router address. Must be w.x.y.z with each of w, x, y, and z being between 1 and 255 (inclusive)');
                return $return;
            }
            $return['network'] = ip2long($return['ipaddr']) & $bnetmask;
            if ($return['network'] != (ip2long($return['router']) & $bnetmask)) {
                $return['err'] = 1;
                $return['errmsg'] = i('IP address and router are not on the same subnet based on the specified netmask.');
                return $return;
            }
            # validate dns server(s)
            $dns = processInputVar('dns', ARG_STRING);
            $tmp = explode(',', $dns);
            $cnt = 0;
            $return['dnsArr'] = array();
            foreach ($tmp as $dnsaddr) {
                if ($cnt && $dnsaddr == '') {
                    continue;
                }
                if ($cnt == 3) {
                    $return['err'] = 1;
                    $return['errmsg'] = i('Too many DNS servers specified - up to 3 are allowed.');
                    return $return;
                }
                if (!validateIPv4addr($dnsaddr)) {
                    $return['err'] = 1;
                    $return['errmsg'] = i('Invalid DNS server specified.');
                    return $return;
                }
                $return['dnsArr'][] = $dnsaddr;
                $cnt++;
            }
            # check that a management node can handle the network
            $mappedmns = getMnsFromImage($return['imageid']);
            $mnnets = checkAvailableNetworks($return['ipaddr']);
            $intersect = array_intersect($mappedmns, $mnnets);
            if (empty($intersect)) {
                $return['err'] = 1;
                $return['errmsg'] = i('There are no management nodes that can deploy the selected image with the specified IP address.');
                return $return;
            }
        }
        # macaddr
        $return['macaddr'] = processInputVar('macaddr', ARG_STRING);
        if ($return['macaddr'] != '' && !preg_match('/^(([A-Fa-f0-9]){2}:){5}([A-Fa-f0-9]){2}$/', $return['macaddr'])) {
            $return['err'] = 1;
            $return['errmsg'] = i('Invalid MAC address. Must be XX:XX:XX:XX:XX:XX with each pair of XX being from 00 to FF (inclusive)');
            return $return;
        }
        # profileid
        $return['profileid'] = processInputVar('profileid', ARG_NUMERIC, 0);
        $resources = getUserResources(array("serverCheckOut", "serverProfileAdmin"), array("available", "administer"));
        if (!array_key_exists($return['profileid'], $resources['serverprofile'])) {
            $return['profileid'] = 0;
        } elseif ($return['profileid'] != 0) {
            $tmp = getServerProfiles($return['profileid']);
            $tmp = $tmp[$return['profileid']];
            if ($tmp['imageid'] != $return['imageid'] && ($tmp['fixedIP'] != $return['ipaddr'] && $tmp['fixedMAC'] != $return['macaddr'] || $tmp['fixedIP'] == $return['ipaddr'] && $return['ipaddr'] == '' && $tmp['fixedMAC'] == $return['macaddr'] && $return['macaddr'] == '')) {
                $return['profileid'] = 0;
            }
        }
        # admingroupid
        $usergroups = getUserGroups();
        $return['admingroupid'] = processInputVar('admingroupid', ARG_NUMERIC);
        if ($return['admingroupid'] != 0 && !array_key_exists($return['admingroupid'], $usergroups)) {
            $return['err'] = 1;
            $return['errmsg'] = i('You do not have access to use the specified admin user group.');
            return $return;
        }
        # logingroupid
        $return['logingroupid'] = processInputVar('logingroupid', ARG_NUMERIC);
        if ($return['logingroupid'] != 0 && !array_key_exists($return['logingroupid'], $usergroups)) {
            $return['err'] = 1;
            $return['errmsg'] = i('You do not have access to use the specified access user group.');
            return $return;
        }
        # monitored
        $return['monitored'] = processInputVar('monitored', ARG_NUMERIC, 0);
        if ($return['monitored'] != 0 && $return['monitored'] != 1) {
            $return['monitored'] = 0;
        }
        # configs
        # TODO configs
        /*$tmp = getUserResources(array("configAdmin"));
        		$userconfigs = $tmp['config'];
        		$initconfigs = getMappedConfigs($return['imageid']);
        		if(array_key_exists('configdata', $_POST)) {
        			if(get_magic_quotes_gpc())
        				$_POST['configdata'] = stripslashes($_POST['configdata']);
        			$configdata = json_decode($_POST['configdata']);
        		}
        		if(array_key_exists('configdata', $_POST) &&
        			isset($configdata->configs))
        			$configs = $configdata->configs;
        		else
        			$configs = (object)array();
        		$return['configs'] = array();
        		foreach($initconfigs as $id => $config) {
        			if(isset($configs->{$id}) &&
        				isset($configs->{$id}->applied) &&
        			   $configs->{$config['id']}->applied != 'true' &&
        				$configs->{$config['id']}->applied != 'false')
        				unset($configs->{$config['id']});
        			if($config['optional'] &&
        			   (! isset($configs->{$id}) ||
        			   ! $configs->{$id}->applied))
        				continue;
        			$return['configs'][$id] = array('configid' => $config['configid'],
        			                                'configmapid' => $config['configmapid'],
        			                                'imageid' => $config['subimageid']);
        			if(isset($configs->{$id}))
        				unset($configs->{$id});
        		}
        		$rescfgmapids = array();
        		foreach($configs as $id => $config) {
        			if(! array_key_exists($config->configid, $userconfigs))
        				continue;
        			$return['configs'][$id] = array('configid' => $config->configid,
        			                                'configstageid' => $config->configstageid,
        			                                'imageid' => $config->imageid);
        			$tmp = explode('/', $id);
        			$rescfgmapids[$tmp[1]] = 1;
        		}
        
        		# configvars
        		$tmp = array_splice($initconfigs, 0);
        		$initconfigvars = getImageConfigVariables($tmp);
        		if(array_key_exists('configdata', $_POST) &&
        			isset($configdata->configvars))
        			$configvars = $configdata->configvars;
        		else
        			$configvars = (object)array();
        		#print "/*";
        		#printArray($initconfigvars);
        		#printArray($configvars);
        		#print "*" . "/";
        		$return['configvars'] = array();
        		foreach($initconfigvars as $id => $configvar) {
        			$tmp = explode('/', $id);
        			$cfgid = "{$tmp[0]}/{$tmp[1]}";
        			$varid = $tmp[2];
        			if($configvar['ask'] == 0 ||
        			   ! isset($configvars->{$id}) ||
        			   ! isset($configvars->{$id}->value)) {
        				$return['configvars'][$cfgid][$varid] =
        				         array('value' => $configvar['defaultvalue']);
        			}
        			else {
        				switch($configvar['datatype']) {
        					case 'bool':
        					case 'int':
        					case 'float':
        						$value = processInputData($configvars->{$id}->value, ARG_NUMERIC);
        						break;
        					default:
        						$value = processInputData($configvars->{$id}->value, ARG_STRING);
        						break;
        				}
        				$return['configvars'][$cfgid][$varid] = array('value' => $value);
        			}
        			if(isset($configvars->{$id}))
        				unset($configvars->{$id});
        		}*/
        /*print "/*";
        		printArray($rescfgmapids);
        		foreach($configvars as $id => $var) {
        			$cfgid = explode('/', $id);
        			print "cfgid: {$cfgid[1]}\n";
        			if(! array_key_exists($cfgid[1], $rescfgmapids))
        				continue;
        			// TODO validate based on var type
        			$value = processInputData($configvars->{$id}->value, ARG_STRING);
        			$return['configvars']["{$cfgid[0]}/{$cfgid[1]}"][$cfgid[2]] = array('value' => $value);
        		}
        		printArray($configvars);*/
        #print "*/";
    }
    return $return;
}
示例#3
0
文件: utils.php 项目: gw-acadtech/VCL
function addRequest($forimaging = 0, $revisionid = array())
{
    global $requestInfo, $user;
    $startstamp = unixToDatetime($requestInfo["start"]);
    $endstamp = unixToDatetime($requestInfo["end"]);
    $now = time();
    if ($requestInfo["start"] <= $now) {
        $start = unixToDatetime($now);
        $nowfuture = "now";
    } else {
        $start = $startstamp;
        $nowfuture = "future";
    }
    addLogEntry($nowfuture, $start, $endstamp, 1, $requestInfo["imageid"]);
    $qh = doQuery("SELECT LAST_INSERT_ID() FROM log", 131);
    if (!($row = mysql_fetch_row($qh))) {
        abort(132);
    }
    $logid = $row[0];
    $query = "INSERT INTO changelog " . "(logid, " . "start, " . "end, " . "timestamp) " . "VALUES " . "({$logid}, " . "'{$start}', " . "'{$endstamp}', " . "NOW())";
    doQuery($query, 136);
    # add single entry to request table
    $query = "INSERT INTO request " . "(stateid, " . "userid, " . "laststateid, " . "logid, " . "forimaging, " . "start, " . "end, " . "daterequested) " . "VALUES " . "(13, " . "{$user['id']}, " . "13, " . "{$logid}, " . "{$forimaging}, " . "'{$startstamp}', " . "'{$endstamp}', " . "NOW())";
    $qh = doQuery($query, 136);
    $qh = doQuery("SELECT LAST_INSERT_ID() FROM request", 134);
    if (!($row = mysql_fetch_row($qh))) {
        abort(135);
    }
    $requestid = $row[0];
    # add requestid to log entry
    $query = "UPDATE log " . "SET requestid = {$requestid} " . "WHERE id = {$logid}";
    doQuery($query, 101);
    # add an entry to the reservation table for each image
    # NOTE: make sure parent image is the first entry we add
    #   so that it has the lowest reservationid
    foreach ($requestInfo["images"] as $key => $imageid) {
        if (array_key_exists($imageid, $revisionid) && !empty($revisionid[$imageid])) {
            $imagerevisionid = $revisionid[$imageid];
        } else {
            $imagerevisionid = getProductionRevisionid($imageid);
        }
        $computerid = $requestInfo["computers"][$key];
        $mgmtnodeid = $requestInfo['mgmtnodes'][$key];
        $query = "INSERT INTO reservation " . "(requestid, " . "computerid, " . "imageid, " . "imagerevisionid, " . "managementnodeid) " . "VALUES " . "({$requestid}, " . "{$computerid}, " . "{$imageid}, " . "{$imagerevisionid}, " . "{$mgmtnodeid})";
        doQuery($query, 133);
        addSublogEntry($logid, $imageid, $imagerevisionid, $computerid, $mgmtnodeid);
    }
    // release semaphore lock
    semUnlock();
    return $requestid;
}
示例#4
0
 function AJremImageConnectMethod()
 {
     $imageid = getContinuationVar('imageid');
     $methods = getContinuationVar('methods');
     $revids = getContinuationVar('revids');
     $curmethods = getImageConnectMethods($imageid);
     $remidlist = mysql_real_escape_string(processInputVar('ids', ARG_STRING));
     $remids = explode(',', $remidlist);
     $revid = processInputVar('revid', ARG_NUMERIC);
     $newimage = getContinuationVar('newimage');
     foreach ($remids as $id) {
         if (!is_numeric($id)) {
             $arr = array('error' => 'invalidinput', 'msg' => i("Non-numeric data was submitted for a connection method id."));
             sendJSON($arr);
             return;
         }
     }
     if ($revid != 0 && !in_array($revid, $revids)) {
         $arr = array('error' => 'invalidrevision', 'msg' => i("Invalid revision id submitted."));
         sendJSON($arr);
         return;
     }
     if (!$newimage) {
         if ($revid == 0) {
             $revid = getProductionRevisionid($imageid);
         }
         # delete any current entries for method and image
         $query = "DELETE FROM connectmethodmap " . "WHERE imagerevisionid = {$revid} AND " . "connectmethodid IN ({$remidlist}) AND " . "autoprovisioned IS NULL";
         doQuery($query, 101);
         # query to see if enabled for OStype or OS
         $insvals = array();
         foreach ($remids as $id) {
             $query = "SELECT cm.connectmethodid " . "FROM connectmethodmap cm, " . "image i " . "LEFT JOIN OS o ON (o.id = i.OSid) " . "LEFT JOIN OStype ot ON (ot.name = o.type) " . "WHERE i.id = {$imageid} AND " . "cm.autoprovisioned IS NULL AND " . "cm.connectmethodid = {$id} AND " . "cm.disabled = 0 AND " . "(cm.OStypeid = ot.id OR " . "cm.OSid = o.id)";
             $qh = doQuery($query, 101);
             if (mysql_num_rows($qh)) {
                 # if so, add disabled entry for image revision and method
                 $insvals[] = "({$id}, {$revid}, 1)";
             }
         }
         if (count($insvals)) {
             $allinsvals = implode(',', $insvals);
             $query = "INSERT INTO connectmethodmap " . "(connectmethodid, " . "imagerevisionid, " . "disabled) " . "VALUES {$allinsvals}";
             doQuery($query, 101);
         }
     }
     $cdata = $this->basecdata;
     $cdata['imageid'] = $imageid;
     $cdata['methods'] = $methods;
     $cdata['revids'] = $revids;
     $cdata['newimage'] = $newimage;
     $addcont = addContinuationsEntry('AJaddImageConnectMethod', $cdata, 3600, 1, 0);
     $remcont = addContinuationsEntry('AJremImageConnectMethod', $cdata, 3600, 1, 0);
     $arr = array('addcont' => $addcont, 'remcont' => $remcont);
     sendJSON($arr);
     $key = getKey(array('getImageConnectMethods', (int) $imageid, (int) $revid));
     if (array_key_exists($key, $_SESSION['usersessiondata'])) {
         unset($_SESSION['usersessiondata'][$key]);
     }
     $key = getKey(array('getImageConnectMethods', (int) $imageid, 0));
     if (array_key_exists($key, $_SESSION['usersessiondata'])) {
         unset($_SESSION['usersessiondata'][$key]);
     }
 }
示例#5
0
function getCompFinalVMReservationTime($hostid, $addsemaphores = 0, $notomaintenance = 0)
{
    global $uniqid, $mysql_link_vcl;
    if ($addsemaphores) {
        $query = "SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = {$hostid} AND " . "vm.vmhostid = v.id";
        $qh = doQuery($query);
        $compids = array();
        while ($row = mysql_fetch_assoc($qh)) {
            $compids[] = $row['id'];
        }
        if (empty($compids)) {
            return 0;
        }
        $allcompids = implode(',', $compids);
        $imageid = getImageId('noimage');
        $revid = getProductionRevisionid($imageid);
        $tmp = getManagementNodes();
        $tmp = array_keys($tmp);
        $mnid = $tmp[0];
        $query = "INSERT INTO semaphore " . "SELECT c.id, " . "{$imageid}, " . "{$revid}, " . "{$mnid}, " . "NOW() + INTERVAL " . SEMTIMEOUT . " SECOND, " . "'{$uniqid}' " . "FROM computer c " . "LEFT JOIN semaphore s ON (c.id = s.computerid) " . "WHERE c.id IN ({$allcompids}) AND " . "(s.expires IS NULL OR s.expires < NOW()) " . "GROUP BY c.id";
        doQuery($query);
        $cnt = mysql_affected_rows($mysql_link_vcl);
        if ($cnt != count($compids)) {
            return -1;
        }
    }
    $end = 0;
    $skipstates = '1,5,12';
    if ($notomaintenance) {
        $skipstates .= ',18';
    }
    $query = "SELECT UNIX_TIMESTAMP(rq.end) as end " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rq.stateid NOT IN ({$skipstates}) AND " . "rs.computerid IN (SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = {$hostid} AND " . "vm.vmhostid = v.id) " . "ORDER BY rq.end DESC " . "LIMIT 1";
    $qh = doQuery($query, 101);
    if ($row = mysql_fetch_assoc($qh)) {
        $end = $row['end'];
    }
    $query = "SELECT UNIX_TIMESTAMP(t.end) as end " . "FROM blockComputers c, " . "blockTimes t " . "WHERE c.blockTimeid = t.id AND " . "t.end > NOW() AND " . "c.computerid IN (SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = {$hostid} AND " . "vm.vmhostid = v.id) " . "ORDER BY t.end DESC " . "LIMIT 1";
    $qh = doQuery($query, 101);
    if ($row = mysql_fetch_assoc($qh)) {
        if ($row['end'] > $end) {
            $end = $row['end'];
        }
    }
    return $end;
}
示例#6
0
文件: vm.php 项目: bq-xiao/apache-vcl
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);
}
示例#7
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;
}
示例#8
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);
    }
}
示例#9
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;
}