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; }
function isAvailable($images, $imageid, $imagerevisionid, $start, $end, $holdcomps, $requestid = 0, $userid = 0, $ignoreprivileges = 0, $forimaging = 0, $ip = '', $mac = '', $skipconcurrentcheck = 0) { global $requestInfo, $user; $requestInfo["start"] = $start; $requestInfo["end"] = $end; $requestInfo["imageid"] = $imageid; $requestInfo["ipwarning"] = 0; $allocatedcompids = array(0); if (!is_array($imagerevisionid)) { $imagerevisionid = array($imageid => array($imagerevisionid)); } elseif (empty($imagerevisionid)) { $imagerevisionid = array($imageid => array(getProductionRevisionid($imageid))); } if (schCheckMaintenance($start, $end)) { return debugIsAvailable(-2, 1, $start, $end, $imagerevisionid); } if (!array_key_exists($imageid, $images)) { return debugIsAvailable(0, 20, $start, $end, $imagerevisionid); } if ($requestInfo["start"] <= time()) { $now = 1; $nowfuture = 'now'; } else { $now = 0; $nowfuture = 'future'; } $scheduleids = getAvailableSchedules($start, $end); $requestInfo["computers"] = array(); $requestInfo["computers"][0] = 0; $requestInfo["images"][0] = $imageid; $requestInfo["imagerevisions"][0] = $imagerevisionid[$imageid][0]; # build array of subimages # TODO handle mininstance if (!$forimaging && $images[$imageid]["imagemetaid"] != NULL) { $count = 1; foreach ($images[$imageid]["subimages"] as $imgid) { $requestInfo['computers'][$count] = 0; $requestInfo['images'][$count] = $imgid; if (array_key_exists($imgid, $imagerevisionid) && array_key_exists($count, $imagerevisionid[$imgid])) { $requestInfo['imagerevisions'][$count] = $imagerevisionid[$imgid][$count]; } else { $requestInfo['imagerevisions'][$count] = getProductionRevisionid($imgid); } $count++; } } $startstamp = unixToDatetime($start); $endstamp = unixToDatetime($end + 900); if (!empty($mac) || !empty($ip)) { # check for overlapping use of mac or ip $query = "SELECT rq.id " . "FROM reservation rs, " . "request rq, " . "serverrequest sr " . "WHERE '{$startstamp}' < (rq.end + INTERVAL 900 SECOND) AND " . "'{$endstamp}' > rq.start AND " . "sr.requestid = rq.id AND " . "rs.requestid = rq.id AND " . "(sr.fixedIP = '{$ip}' OR " . "sr.fixedMAC = '{$mac}') AND " . "rq.stateid NOT IN (1,5,11,12) "; if ($requestid) { $query .= "AND rq.id != {$requestid} "; } $query .= "LIMIT 1"; $qh = doQuery($query, 101); if (mysql_num_rows($qh)) { return debugIsAvailable(-3, 2, $start, $end, $imagerevisionid); } # check for IP being used by a management node $query = "SELECT id " . "FROM managementnode " . "WHERE IPaddress = '{$ip}' AND " . "stateid != 1"; $qh = doQuery($query, 101); if (mysql_num_rows($qh)) { return debugIsAvailable(-4, 16, $start, $end, $imagerevisionid); } } if ($requestid) { $requestData = getRequestInfo($requestid); } $vmhostcheckdone = 0; $ignorestates = "'maintenance','vmhostinuse','hpc','failed'"; if ($now) { $ignorestates .= ",'reloading','reload','timeout','inuse'"; } foreach ($requestInfo["images"] as $key => $imageid) { # check for max concurrent usage of image if (!$skipconcurrentcheck && $images[$imageid]['maxconcurrent'] != NULL) { if ($userid == 0) { $usersgroups = $user['groups']; } else { $testuser = getUserInfo($userid, 0, 1); if (is_null($testuser)) { return debugIsAvailable(0, 17, $start, $end, $imagerevisionid); } $usersgroups = $testuser['groups']; } $decforedit = 0; $compids = array(); $reloadid = getUserlistID('vclreload@Local'); $query = "SELECT rs.computerid, " . "rq.id AS reqid " . "FROM reservation rs, " . "request rq " . "WHERE '{$startstamp}' < (rq.end + INTERVAL 900 SECOND) AND " . "'{$endstamp}' > rq.start AND " . "rs.requestid = rq.id AND " . "rs.imageid = {$imageid} AND " . "rq.stateid NOT IN (1,5,11,12,16,17) AND " . "rq.userid != {$reloadid}"; $qh = doQuery($query, 101); while ($row = mysql_fetch_assoc($qh)) { $compids[] = $row['computerid']; if ($row['reqid'] == $requestid) { $decforedit = 1; } } $usagecnt = count($compids); $allids = implode("','", $compids); $ignoregroups = implode("','", array_keys($usersgroups)); $query = "SELECT COUNT(bc.imageid) AS currentusage " . "FROM blockComputers bc, " . "blockRequest br, " . "blockTimes bt " . "WHERE bc.blockTimeid = bt.id AND " . "bt.blockRequestid = br.id AND " . "bc.imageid = {$imageid} AND " . "bc.computerid NOT IN ('{$allids}') AND " . "br.groupid NOT IN ('{$ignoregroups}') AND " . "'{$startstamp}' < (bt.end + INTERVAL 900 SECOND) AND " . "'{$endstamp}' > bt.start AND " . "bt.skip != 1 AND " . "br.status != 'deleted'"; $qh = doQuery($query); if (!($row = mysql_fetch_assoc($qh))) { cleanSemaphore(); return debugIsAvailable(0, 3, $start, $end, $imagerevisionid); } if ($usagecnt + $row['currentusage'] - $decforedit >= $images[$imageid]['maxconcurrent']) { cleanSemaphore(); return debugIsAvailable(-1, 4, $start, $end, $imagerevisionid); } } $platformid = getImagePlatform($imageid); if (is_null($platformid)) { cleanSemaphore(); return debugIsAvailable(0, 5, $start, $end, $imagerevisionid); } # get computers $imageid maps to $compids = getMappedResources($imageid, "image", "computer"); if (!count($compids)) { cleanSemaphore(); return debugIsAvailable(0, 6, $start, $end, $imagerevisionid); } $mappedcomputers = implode(',', $compids); // if $ip specified, only look at computers under management nodes that can # handle that network if ($ip != '') { $mappedmns = getMnsFromImage($imageid); $mnnets = checkAvailableNetworks($ip); $intersect = array_intersect($mappedmns, $mnnets); $tmpcompids = array(); foreach ($intersect as $mnid) { $tmp2 = getMappedResources($mnid, 'managementnode', 'computer'); $tmpcompids = array_merge($tmpcompids, $tmp2); } $tmpcompids = array_unique($tmpcompids); $newcompids = array_intersect($compids, $tmpcompids); if (!count($newcompids)) { cleanSemaphore(); return debugIsAvailable(0, 18, $start, $end, $imagerevisionid); } $mappedcomputers = implode(',', $newcompids); } #get computers for available schedules and platforms $computerids = array(); $currentids = array(); $blockids = array(); $altRemoveBlockCheck = 0; // if we are modifying a request and it is after the start time, only allow // the scheduled computer(s) to be modified if ($requestid && datetimeToUnix($requestData["start"]) <= time()) { $altRemoveBlockCheck = 1; foreach ($requestData["reservations"] as $key2 => $res) { if ($res["imageid"] == $imageid) { $compid = $res["computerid"]; unset($requestData['reservations'][$key2]); break; } } array_push($computerids, $compid); array_push($currentids, $compid); $query = "SELECT scheduleid " . "FROM computer " . "WHERE id = {$compid}"; $qh = doQuery($query, 128); $row = mysql_fetch_row($qh); if (!in_array($row[0], $scheduleids)) { cleanSemaphore(); return debugIsAvailable(0, 7, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids); } // set $virtual to 0 so that it is defined later but skips the additional code $virtual = 0; } else { # determine if image is bare metal or virtual $query = "SELECT OS.installtype " . "FROM image i " . "LEFT JOIN OS ON (i.OSid = OS.id) " . "WHERE i.id = {$imageid}"; $qh = doQuery($query, 101); if (!($row = mysql_fetch_assoc($qh))) { cleanSemaphore(); return debugIsAvailable(0, 8, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids); } # TODO might need to check for other strings for KVM, OpenStack, etc if (preg_match('/(vmware)/', $row['installtype'])) { $virtual = 1; } else { $virtual = 0; } # get list of available computers if (!$ignoreprivileges) { $resources = getUserResources(array("imageAdmin", "imageCheckOut"), array("available"), 0, 0, $userid); $usercomputers = implode("','", array_keys($resources["computer"])); $usercomputers = "'{$usercomputers}'"; } $alloccompids = implode(",", $allocatedcompids); # get list of computers we can provision image to $schedules = implode(',', $scheduleids); #image.OSid->OS.installtype->OSinstalltype.id->provisioningOSinstalltype.provisioningid->computer.provisioningid $query = "SELECT DISTINCT c.id, " . "c.currentimageid, " . "c.imagerevisionid " . "FROM state s, " . "image i " . "LEFT JOIN OS o ON (o.id = i.OSid) " . "LEFT JOIN OSinstalltype oi ON (oi.name = o.installtype) " . "LEFT JOIN provisioningOSinstalltype poi ON (poi.OSinstalltypeid = oi.id) " . "LEFT JOIN computer c ON (poi.provisioningid = c.provisioningid) " . "LEFT JOIN semaphore se ON (c.id = se.computerid) " . "WHERE i.id = {$imageid} AND " . "c.scheduleid IN ({$schedules}) AND " . "c.platformid = {$platformid} AND " . "c.stateid = s.id AND " . "s.name NOT IN ({$ignorestates}) AND " . "c.RAM >= i.minram AND " . "c.procnumber >= i.minprocnumber AND " . "c.procspeed >= i.minprocspeed AND " . "c.network >= i.minnetwork AND " . "c.deleted = 0 AND " . "(c.type != 'virtualmachine' OR c.vmhostid IS NOT NULL) AND "; if (!$ignoreprivileges) { $query .= "c.id IN ({$usercomputers}) AND "; } $query .= "c.id IN ({$mappedcomputers}) AND " . "c.id NOT IN ({$alloccompids}) AND " . "(se.expires IS NULL OR se.expires < NOW()) " . "ORDER BY RAM, " . "(c.procspeed * c.procnumber), " . "network"; $qh = doQuery($query, 129); while ($row = mysql_fetch_assoc($qh)) { array_push($computerids, $row['id']); if ($row['currentimageid'] == $imageid && $row['imagerevisionid'] == $requestInfo['imagerevisions'][$key]) { array_push($currentids, $row['id']); } } # get computer ids available from block allocations $blockdata = getAvailableBlockComputerids($imageid, $start, $end, $allocatedcompids); $blockids = $blockdata['compids']; } # return 0 if no computers available if (empty($computerids) && empty($blockids)) { return debugIsAvailable(0, 21, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual); } #remove computers from list that are already scheduled $usedComputerids = array(); $query = "SELECT DISTINCT rs.computerid " . "FROM reservation rs, " . "request rq " . "WHERE '{$startstamp}' < (rq.end + INTERVAL 900 SECOND) AND " . "'{$endstamp}' > rq.start AND " . "rq.id != {$requestid} AND " . "rs.requestid = rq.id AND " . "rq.stateid NOT IN (1, 5, 12)"; # deleted, failed, complete $qh = doQuery($query, 130); while ($row = mysql_fetch_row($qh)) { array_push($usedComputerids, $row[0]); } $computerids = array_diff($computerids, $usedComputerids); $currentids = array_diff($currentids, $usedComputerids); $blockids = array_diff($blockids, $usedComputerids); // if modifying a reservation and $computerids is now empty, return 0 if ($requestid && empty($computerids)) { cleanSemaphore(); return debugIsAvailable(0, 9, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual); } # return 0 if no computers available if (empty($computerids) && empty($currentids) && empty($blockids)) { return debugIsAvailable(0, 19, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual); } # remove computers from list that are allocated to block allocations if ($altRemoveBlockCheck) { if (editRequestBlockCheck($computerids[0], $imageid, $start, $end)) { cleanSemaphore(); return debugIsAvailable(0, 10, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual); } } elseif (!count($blockids)) { # && ! $altRemoveBlockCheck $usedBlockCompids = getUsedBlockComputerids($start, $end); $computerids = array_diff($computerids, $usedBlockCompids); $currentids = array_diff($currentids, $usedBlockCompids); } if ($virtual && empty($currentids) && !empty($computerids)) { # find computers whose hosts can handle the required RAM - we don't # need to do this if there are VMs with the requested image already # available because they would already fit within the host's available # RAM if (!$vmhostcheckdone) { $vmhostcheckdone = 1; $query = "DROP TEMPORARY TABLE IF EXISTS VMhostCheck"; doQuery($query, 101); $query = "CREATE TEMPORARY TABLE VMhostCheck ( " . "RAM mediumint unsigned NOT NULL, " . "allocRAM mediumint unsigned NOT NULL, " . "vmhostid smallint unsigned NOT NULL " . ") ENGINE=MEMORY"; doQuery($query, 101); $query = "INSERT INTO VMhostCheck " . "SELECT c.RAM, " . "SUM(i.minram), " . "v.id " . "FROM vmhost v " . "LEFT JOIN computer c ON (v.computerid = c.id) " . "LEFT JOIN computer c2 ON (v.id = c2.vmhostid) " . "LEFT JOIN image i ON (c2.currentimageid = i.id) " . "WHERE c.stateid = 20 " . "GROUP BY v.id"; doQuery($query, 101); } $inids = implode(',', $computerids); // if want overbooking, modify the last part of the WHERE clause $query = "SELECT c.id " . "FROM VMhostCheck v " . "LEFT JOIN computer c ON (v.vmhostid = c.vmhostid) " . "LEFT JOIN image i ON (c.currentimageid = i.id) " . "WHERE c.id IN ({$inids}) AND " . "(v.allocRAM - i.minram + {$images[$imageid]['minram']}) < v.RAM " . "ORDER BY c.RAM, " . "(c.procspeed * c.procnumber), " . "c.network"; $qh = doQuery($query, 101); $newcompids = array(); while ($row = mysql_fetch_assoc($qh)) { $newcompids[] = $row['id']; } $computerids = $newcompids; } # check for use of specified IP address, have to wait until here # because there may be a computer already assigned the IP that # can be used for this reservation if (!empty($ip) && $now) { $allcompids = array_merge($computerids, $blockids); if (empty($allcompids)) { return debugIsAvailable(0, 13, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual); } $inids = implode(',', $allcompids); $query = "SELECT id " . "FROM computer " . "WHERE id NOT IN ({$inids}) AND " . "deleted = 0 AND " . "stateid != 1 AND " . "IPaddress = '{$ip}' AND " . "(type != 'virtualmachine' OR " . "vmhostid IS NOT NULL)"; $qh = doQuery($query); if (mysql_num_rows($qh)) { if ($now) { return debugIsAvailable(-4, 18, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual); } $requestInfo['ipwarning'] = 1; } $query = "SELECT id " . "FROM computer " . "WHERE id in ({$inids}) AND " . "IPaddress = '{$ip}'"; if ($requestid) { $query .= " AND id != {$compid}"; } # TODO test this $qh = doQuery($query); $cnt = mysql_num_rows($qh); if ($cnt > 1) { if ($now) { return debugIsAvailable(-4, 19, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual); } $requestInfo['ipwarning'] = 1; } elseif ($cnt == 1) { $row = mysql_fetch_assoc($qh); $computerids = array($row['id']); $blockids = array(); } } # remove any recently reserved computers that could have been an # undetected failure $failedids = getPossibleRecentFailures($userid, $imageid); $shortened = 0; if (!empty($failedids)) { $origcomputerids = $computerids; $origcurrentids = $currentids; $origblockids = $blockids; if (!empty($computerids)) { $testids = array_diff($computerids, $failedids); if (!empty($testids)) { $shortened = 1; $computerids = $testids; $currentids = array_diff($currentids, $failedids); } } if (!empty($blockids)) { $testids = array_diff($blockids, $failedids); if (!empty($testids)) { $shortened = 1; $blockids = $testids; } } } # allocate a computer $_imgrevid = $requestInfo['imagerevisions'][$key]; $comparr = allocComputer($blockids, $currentids, $computerids, $startstamp, $endstamp, $nowfuture, $imageid, $_imgrevid, $holdcomps, $requestid); if (empty($comparr) && $shortened) { $comparr = allocComputer($origblockids, $origcurrentids, $origcomputerids, $startstamp, $endstamp, $nowfuture, $imageid, $_imgrevid, $holdcomps, $requestid); } if (empty($comparr)) { cleanSemaphore(); return debugIsAvailable(0, 11, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, $failedids, $virtual); } $requestInfo["computers"][$key] = $comparr['compid']; $requestInfo["mgmtnodes"][$key] = $comparr['mgmtid']; $requestInfo["loaded"][$key] = $comparr['loaded']; $requestInfo['fromblock'][$key] = $comparr['fromblock']; if ($comparr['fromblock']) { $requestInfo['blockdata'][$key] = $blockdata[$comparr['compid']]; } array_push($allocatedcompids, $comparr['compid']); } return debugIsAvailable(1, 12, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual); }