function errorHandler($errno, $errstr, $errfile = NULL, $errline = NULL, $errcontext = NULL) { global $user; if (!ONLINEDEBUG || !checkUserHasPerm('View Debug Information')) { cleanSemaphore(); dbDisconnect(); printHTMLFooter(); exit; } print "Error encountered<br>\n"; switch ($errno) { case E_USER_ERROR: echo "<b>FATAL</b> [{$errno}] {$errstr}<br />\n"; echo " Fatal error in line {$errline} of file {$errfile}"; echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n"; echo "Aborting...<br />\n"; cleanSemaphore(); dbDisconnect(); exit(1); break; case E_USER_WARNING: echo "<b>ERROR</b> [{$errno}] {$errstr}<br />\n"; break; case E_USER_NOTICE: echo "<b>WARNING</b> [{$errno}] {$errstr}<br />\n"; break; default: echo "Unkown error type: [{$errno}] {$errstr}<br />\n"; break; } if (!empty($errfile) && !empty($errline)) { print "Error at {$errline} in {$errfile}<br>\n"; } if (!empty($errcontext)) { print "<pre>\n"; print_r($errcontext); print "</pre>\n"; } print "<br><br><br>\n"; print "<pre>\n"; print getBacktraceString(); print "</pre>\n"; cleanSemaphore(); dbDisconnect(); printHTMLFooter(); exit; }
function checkExpiredDemoUser($userid, $groups = 0) { global $mode, $skin, $noHTMLwrappers; if ($groups == 0) { $groups = getUsersGroups($userid, 1); } if (count($groups) != 1) { return; } $tmp = array_values($groups); if ($tmp[0] != 'demo') { return; } $query = "SELECT start " . "FROM log " . "WHERE userid = {$userid} " . "AND finalend < NOW() " . "ORDER BY start " . "LIMIT 3"; $qh = doQuery($query, 101); $expire = time() - SECINDAY * 3; $rows = mysql_num_rows($qh); if ($row = mysql_fetch_assoc($qh)) { if ($rows >= 3 || datetimeToUnix($row['start']) < $expire) { if (in_array($mode, $noHTMLwrappers)) { # do a redirect and handle removal on next page load so user can # be notified - doesn't always work, but handles a few extra # cases header("Location: " . BASEURL . SCRIPT); } else { $nodemoid = getUserGroupID('nodemo', getAffiliationID('ITECS')); $query = "DELETE FROM usergroupmembers " . "WHERE userid = {$userid}"; # because updateGroups doesn't # delete from custom groups doQuery($query, 101); updateGroups(array($nodemoid), $userid); checkUpdateServerRequestGroups($groupid); if (empty($skin)) { $skin = 'default'; require_once "themes/{$skin}/page.php"; } $mode = 'expiredemouser'; printHTMLHeader(); print "<h2>Account Expired</h2>\n"; print "The account you are using is a demo account that has now expired. "; print "You cannot make any more reservations. Please contact <a href=\""; print "mailto:" . HELPEMAIL . "\">" . HELPEMAIL . "</a> if you need "; print "further access to VCL.<br>\n"; } cleanSemaphore(); # probably not needed but ensures we do not leave stale entries printHTMLFooter(); dbDisconnect(); exit; } } }
function AJsubmitEditRequest() { global $user; $requestid = getContinuationVar('requestid'); $openend = getContinuationVar('openend'); $allownousercheck = getContinuationVar('nousercheck'); $modifystart = getContinuationVar('modifystart'); $startdays = getContinuationVar('startdays'); $lengths = getContinuationVar('lengths'); $maxextend = getContinuationVar('maxextend'); $allowindefiniteend = getContinuationVar('allowindefiniteend'); $request = getRequestInfo($requestid, 1); if (is_null($request)) { $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); sendJSON(array('status' => 'norequest', 'html' => i('The selected reservation no longer exists.') . '<br><br>', 'cont' => $cont)); return; } if ($modifystart) { $day = processInputVar('day', ARG_NUMERIC, 0); if (!in_array($day, $startdays)) { $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); sendJSON(array('status' => 'error', 'errmsg' => i('Invalid start day submitted'), 'cont' => $cont)); return; } $starttime = processInputVar('starttime', ARG_STRING); if (!preg_match('/^(([01][0-9])|(2[0-3]))([0-5][0-9])$/', $starttime, $matches)) { $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); sendJSON(array('status' => 'error', 'errmsg' => i("Invalid start time submitted"), 'cont' => $cont)); return; } preg_match('/^([0-9]{4})([0-9]{2})([0-9]{2})$/', $day, $tmp); $startdt = "{$tmp[1]}-{$tmp[2]}-{$tmp[3]} {$matches[1]}:{$matches[4]}:00"; $startts = datetimeToUnix($startdt); } else { $startdt = $request['start']; $startts = datetimeToUnix($startdt); } $endmode = processInputVar('endmode', ARG_STRING); if ($endmode == 'length') { $length = processInputVar('length', ARG_NUMERIC); if (!in_array($length, $lengths)) { $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); sendJSON(array('status' => 'error', 'errmsg' => i("Invalid duration submitted"), 'cont' => $cont)); return; } if ($modifystart) { $endts = $startts + $length * 60; } else { $tmp = datetimeToUnix($request['end']); $endts = $tmp + $length * 60; } $enddt = unixToDatetime($endts); } elseif ($endmode == 'ending') { $ending = processInputVar('ending', ARG_NUMERIC); if (!preg_match('/^([0-9]{4})([0-9]{2})([0-9]{2})(([01][0-9])|(2[0-3]))([0-5][0-9])$/', $ending, $tmp) || !checkdate($tmp[2], $tmp[3], $tmp[1])) { $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); sendJSON(array('status' => 'error', 'errmsg' => i("Invalid end date/time submitted"), 'cont' => $cont)); return; } $enddt = "{$tmp[1]}-{$tmp[2]}-{$tmp[3]} {$tmp[4]}:{$tmp[7]}:00"; $endts = datetimeToUnix($enddt); } elseif ($allowindefiniteend && $endmode == 'indefinite') { $endts = datetimeToUnix('2038-01-01 00:00:00'); $enddt = unixToDatetime($endts); } else { $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); sendJSON(array('status' => 'error', 'errmsg' => i("Invalid data submitted"), 'cont' => $cont)); return; } $updategroups = 0; $updateservername = 0; if ($request['serverrequest']) { if ($user['showallgroups']) { $groups = getUserGroups(0); } else { $groups = getUserGroups(0, $user['affiliationid']); } $admingroupid = processInputVar('admingroupid', ARG_NUMERIC); $logingroupid = processInputVar('logingroupid', ARG_NUMERIC); if ($admingroupid != 0 && !array_key_exists($admingroupid, $groups) && $admingroupid != $request['admingroupid'] || $logingroupid != 0 && !array_key_exists($logingroupid, $groups) && $logingroupid != $request['logingroupid']) { $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); sendJSON(array('status' => 'error', 'errmsg' => i("Invalid user group submitted"), 'cont' => $cont)); return; } $testadmingroupid = $admingroupid; if ($admingroupid == 0) { $testadmingroupid = ''; } $testlogingroupid = $logingroupid; if ($logingroupid == 0) { $testlogingroupid = ''; } if ($testadmingroupid != $request['admingroupid'] || $testlogingroupid != $request['logingroupid']) { $updategroups = 1; } $servername = processInputVar('servername', ARG_STRING); if (!preg_match('/^([-a-zA-Z0-9\\.\\(\\)_ ]){3,255}$/', $servername)) { $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); sendJSON(array('status' => 'error', 'errmsg' => i("The name can only contain letters, numbers, spaces, dashes(-), and periods(.) and can be from 3 to 255 characters long"), 'cont' => $cont)); return; } if ($servername != $request['servername']) { $servername = mysql_real_escape_string($servername); $updateservername = 1; } } $h = ''; $max = getMaxOverlap($user['id']); if (checkOverlap($startts, $endts, $max, $requestid)) { if ($max == 0) { $m = i("The time you requested overlaps with another reservation you currently have. You are only allowed to have a single reservation at any given time. Please select another time for the reservation."); $h .= preg_replace("/(.{1,60}([ \n]|\$))/", '\\1<br>', $m) . "<br>"; } else { $m = sprintf(i("The time you requested overlaps with another reservation you currently have. You are allowed to have %s overlapping reservations at any given time. Please select another time for the reservation."), $max); $h .= preg_replace("/(.{1,60}([ \n]|\$))/", '\\1<br>', $m) . "<br>"; } $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); sendJSON(array('status' => 'error', 'errmsg' => $h, 'cont' => $cont)); return; } if ($request['serverrequest'] && (!empty($request['fixedIP']) || !empty($request['fixedMAC']))) { $ip = $request['fixedIP']; $mac = $request['fixedMAC']; } else { $ip = ''; $mac = ''; } $imageid = $request['reservations'][0]['imageid']; $images = getImages(); $revisions = array(); foreach ($request['reservations'] as $key => $res) { $revisions[$res['imageid']][$key] = $res['imagerevisionid']; } $rc = isAvailable($images, $imageid, $revisions, $startts, $endts, 1, $requestid, 0, 0, 0, $ip, $mac); $data = array(); if ($rc < 1) { $cdata = array('now' => 0, 'start' => $startts, 'end' => $endts, 'server' => $allowindefiniteend, 'imageid' => $imageid, 'requestid' => $requestid); if (!$modifystart) { $cdata['extendonly'] = 1; } $sugcont = addContinuationsEntry('AJshowRequestSuggestedTimes', $cdata); if (array_key_exists('subimages', $images[$imageid]) && count($images[$imageid]['subimages'])) { $data['sugcont'] = 'cluster'; } else { $data['sugcont'] = $sugcont; } addChangeLogEntry($request["logid"], NULL, $enddt, $startdt, NULL, NULL, 0); } if ($rc == -3) { $msgip = ''; $msgmac = ''; if (!empty($ip)) { $msgip = " ({$ip})"; } if (!empty($mac)) { $msgmac = " ({$mac})"; } $h .= sprintf(i("The reserved IP (%s) or MAC address (%s) conflicts with another reservation using the same IP or MAC address. Please select a different time to use the image."), $msgip, $msgmac); $h = preg_replace("/(.{1,60}([ \n]|\$))/", '\\1<br>', $h); $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); $data['status'] = 'conflict'; $data['errmsg'] = $h; $data['cont'] = $cont; sendJSON($data); return; } elseif ($rc == -2) { $m = i("The time you requested overlaps with a maintenance window. Please select a different time to use the image."); $h .= preg_replace("/(.{1,60}([ \n]|\$))/", '\\1<br>', $m) . "<br>"; $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); $data['status'] = 'conflict'; $data['errmsg'] = $h; $data['cont'] = $cont; sendJSON($data); return; } elseif ($rc == -1) { $m = i("The reservation you are modifying is for an environment limited in the number of concurrent reservations that can be made. The time or duration you have requested overlaps with too many other reservations for the same image. Please select another time or duration for the reservation."); $h .= preg_replace("/(.{1,60}([ \n]|\$))/", '\\1<br>', $m) . "<br>"; $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); $data['status'] = 'conflict'; $data['errmsg'] = $h; $data['cont'] = $cont; sendJSON($data); return; } elseif ($rc > 0) { updateRequest($requestid); $serversets = array(); $reqsets = array(); if ($updategroups && $request['laststateid'] != 24) { if ($admingroupid == 0) { $admingroupid = 'NULL'; } if ($logingroupid == 0) { $logingroupid = 'NULL'; } $serversets[] = "admingroupid = {$admingroupid}"; $serversets[] = "logingroupid = {$logingroupid}"; addChangeLogEntryOther($request['logid'], "event:usergroups|admingroupid:{$admingroupid}|logingroupid:{$logingroupid}"); $reqsets[] = "stateid = 29"; } if ($updateservername) { $serversets[] = "name = '{$servername}'"; } if ($allownousercheck) { $newnousercheck = processInputVar('newnousercheck', ARG_NUMERIC); if (($newnousercheck == 1 || $newnousercheck == 0) && $newnousercheck == $request['checkuser']) { $reqsets[] = "checkuser = (1 - checkuser)"; } } if (count($serversets)) { $sets = implode(',', $serversets); $query = "UPDATE serverrequest " . "SET {$sets} " . "WHERE requestid = {$requestid}"; doQuery($query); } if (count($reqsets)) { $sets = implode(',', $reqsets); $query = "UPDATE request " . "SET {$sets} " . "WHERE id = {$requestid}"; doQuery($query); } sendJSON(array('status' => 'success')); cleanSemaphore(); return; } else { $m = i("The time period you have requested is not available. Please select a different time."); $h .= preg_replace("/(.{1,55}([ \n]|\$))/", '\\1<br>', $m) . "<br>"; $cdata = getContinuationVar(); $cont = addContinuationsEntry('AJsubmitEditRequest', $cdata, SECINDAY, 1, 0); $data['status'] = 'conflict'; $data['errmsg'] = $h; $data['cont'] = $cont; sendJSON($data); } }
sendHeaders(); printHTMLHeader(); if (checkUserHasPerm('View Debug Information')) { set_error_handler("errorHandler"); } if ($hasArg) { if (function_exists($actionFunction)) { $actionFunction($arg); } else { $obj = getContinuationVar('obj'); if (!is_null($obj) && method_exists($obj, $actionFunction)) { $obj->{$actionFunction}($arg); } else { main(); } } } else { if (function_exists($actionFunction)) { $actionFunction(); } else { $obj = getContinuationVar('obj'); if (!is_null($obj) && method_exists($obj, $actionFunction)) { $obj->{$actionFunction}(); } else { main(); } } } printHTMLFooter(); cleanSemaphore(); dbDisconnect();
function AJsubmitCompStateChange() { global $user; $newstateid = getContinuationVar('newstateid'); $compids = getContinuationVar('compids'); $states = getStates(); $ret = array('status' => 'success', 'title' => "Change State", 'clearselection' => 0, 'newstate' => $states[$newstateid], 'refreshcount' => 1); # get ids from getUserResources because that data should already be in cache $resources = getUserResources(array("imageAdmin", "imageCheckOut")); $tmp = array_keys($resources['image']); $semimageid = $tmp[0]; $semrevid = getProductionRevisionid($semimageid); if (!empty($resources['managementnode'])) { $tmp = array_keys($resources['managementnode']); $semmnid = $tmp[0]; } else { $allmns = array_keys(getManagementNodes('future')); if (empty($allmns)) { $ret = array('status' => 'error', 'errormsg' => 'No management nodes are available for controlling the submitted computers.'); sendJSON($ret); return; } $semmnid = $allmns[0]; } if ($newstateid == 2) { $fails = array('provnone' => array(), 'reserved' => array(), 'hostfail' => array(), 'hasvms' => array()); $availablenow = array(); $checkvms = array(); $checkhosts = array(); $noaction = array(); $computers = $this->getData($this->defaultGetDataArgs); $inusecompids = array(); $allids = implode(',', $compids); $query = "SELECT rs.computerid " . "FROM reservation rs, " . "request rq " . "WHERE rs.requestid = rq.id AND " . "rq.end > NOW() AND " . "rq.start < NOW() AND " . "rq.stateid NOT IN (1, 5, 11, 12) AND " . "rs.computerid IN ({$allids})"; $qh = doQuery($query); while ($row = mysql_fetch_assoc($qh)) { $inusecompids[$row['computerid']] = 1; } # check initial conditions foreach ($compids as $compid) { # already in available if ($computers[$compid]['state'] == 'available') { $noaction[] = $compid; continue; } # no provisioning engine if ($computers[$compid]['provisioning'] == 'None') { $fails['provnone'][] = $compid; continue; } # non-VM in maintenance without a vmhost entry or in hpc if ($computers[$compid]['state'] == 'hpc' || $computers[$compid]['state'] == 'maintenance' && is_null($computers[$compid]['vmprofileid']) && $computers[$compid]['type'] != 'virtualmachine') { $availablenow[] = $compid; continue; } # has active reservation if (array_key_exists($compid, $inusecompids)) { $fails['reserved'][] = $compid; continue; } # in reload, reloading, reserved, inuse, or failed with no active reservation if (preg_match('/^(reload|reloading|reserved|inuse|failed|timeout)$/', $computers[$compid]['state'])) { $availablenow[] = $compid; continue; } # vmhostinuse - check for assigned VMs if ($computers[$compid]['state'] == 'vmhostinuse') { $checkvms[] = $compid; continue; } # VM in maintenance if ($computers[$compid]['state'] == 'maintenance' && $computers[$compid]['type'] == 'virtualmachine') { $checkhosts[] = $compid; continue; } # maintenance - check for previously being a vmhost if ($computers[$compid]['state'] == 'maintenance' && !is_null($computers[$compid]['vmprofileid'])) { $checkvms[] = $compid; continue; } } if (count($checkvms)) { $ids = implode(',', $checkvms); $query = "SELECT h.id, " . "COUNT(vm.id) AS count " . "FROM computer h " . "LEFT JOIN vmhost vh ON (h.id = vh.computerid) " . "LEFT JOIN computer vm ON (vh.id = vm.vmhostid) " . "WHERE h.id IN ({$ids}) " . "GROUP BY vh.computerid"; $qh = doQuery($query); while ($row = mysql_fetch_assoc($qh)) { if ($row['count']) { $fails['hasvms'][] = $row['id']; } else { $availablenow[] = $row['id']; } } } if (count($checkhosts)) { $ids = implode(',', $checkhosts); $query = "SELECT h.stateid, " . "vm.id " . "FROM computer vm " . "LEFT JOIN vmhost vh ON (vm.vmhostid = vh.id) " . "LEFT JOIN computer h ON (vh.computerid = h.id) " . "WHERE vm.id IN ({$ids})"; $qh = doQuery($query); while ($row = mysql_fetch_assoc($qh)) { if ($row['stateid'] != 20) { $fails['hostfail'][] = $row['id']; } else { $availablenow[] = $row['id']; } } } if (count($availablenow)) { $allids = implode(',', $availablenow); $query = "UPDATE computer " . "SET stateid = 2, " . "notes = '' " . "WHERE id IN ({$allids})"; doQuery($query); } $msg = ''; if (count($noaction)) { $msg .= "The following computers were already in the available "; $msg .= "state:<br><br>\n"; foreach ($noaction as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "<br>\n"; } if (count($availablenow)) { $msg .= "The following computers were changed to the available "; $msg .= "state:<br><br>\n"; foreach ($availablenow as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "<br>\n"; } if (count($fails['provnone'])) { $msg .= "<span class=\"rederrormsg\">\n"; $msg .= "The following computers cannot be in the available state "; $msg .= "because they have no provisioning engine:</span><br><br>\n"; foreach ($fails['provnone'] as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "<br>\n"; } if (count($fails['reserved'])) { $msg .= "<span class=\"rederrormsg\">\n"; $msg .= "The following computers are currently in use and could not have "; $msg .= "their states changed at this time:</span><br><br>\n"; foreach ($fails['reserved'] as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "<br>\n"; } if (count($fails['hasvms'])) { $msg .= "<span class=\"rederrormsg\">\n"; $msg .= "The following computers currently have VMs assigned to them "; $msg .= "and cannot be moved to available until the VMs are removed:"; $msg .= "</span><br><br>\n"; foreach ($fails['hasvms'] as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "<br>\n"; } if (count($fails['hostfail'])) { $msg .= "<span class=\"rederrormsg\">\n"; $msg .= "The following VMs are not currently assigned to a host in "; $msg .= "the vmhostinuse state:</span><br><br>\n"; foreach ($fails['hostfail'] as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "<br>\n"; } } elseif ($newstateid == 10 || $newstateid == 23) { if ($newstateid == 10) { $notes = processInputVar('notes', ARG_STRING); if (get_magic_quotes_gpc()) { $notes = stripslashes($notes); } $notes = mysql_real_escape_string($notes); $notes = $user["unityid"] . " " . unixToDatetime(time()) . "@" . $notes; } $vclreloadid = getUserlistID('vclreload@Local'); $computers = $this->getData($this->defaultGetDataArgs); $noaction = array(); $changenow = array(); $changeasap = array(); $changetimes = array(); $vmwithhost = array(); $fails = array(); $semstart = unixToDatetime(time()); $semend = '2038-01-01 00:00:00'; foreach ($compids as $compid) { if ($newstateid == 10 && $computers[$compid]['type'] == 'virtualmachine' && in_array($computers[$compid]['vmhostcomputerid'], $compids)) { $vmwithhost[] = $compid; } if ($newstateid == 10 && $computers[$compid]['state'] == 'maintenance' || $newstateid == 23 && $computers[$compid]['state'] == 'hpc') { $noaction[] = $compid; continue; } # try to move future reservations off of computer moveReservationsOffComputer($compid); cleanSemaphore(); $reloadstart = getCompFinalReservationTime($compid); if ($computers[$compid]['state'] == 'vmhostinuse') { $sem = array('imageid' => $semimageid, 'revid' => $semrevid, 'mnid' => $semmnid, 'start' => $semstart, 'end' => $semend); moveReservationsOffVMs($compid, $sem); cleanSemaphore(); $reloadstart = getCompFinalVMReservationTime($compid, 1, 1); if ($reloadstart == -1) { cleanSemaphore(); $fails[] = $compid; continue; } elseif ($reloadstart > 0) { if (unixToDatetime($reloadstart) == '2038-01-01 00:00:00') { # host has a VM reserved indefintely $fails[] = $compid; continue; } # schedule tomaintenance/tohpc reservations for VMs and host $noimageid = getImageId('noimage'); $revid = getProductionRevisionid($noimageid); $startdt = unixToDatetime($reloadstart); $end = $reloadstart + SECINMONTH; $enddt = unixToDatetime($end); $query = "SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = {$compid} AND " . "vm.vmhostid = v.id"; $qh = doQuery($query); $setnoteids = array(); while ($row = mysql_fetch_assoc($qh)) { $checkstart = getExistingChangeStateStartTime($row['id'], 18); if ($checkstart) { if ($checkstart > $reloadstart) { # update start time of existing tomaintenance reservation updateExistingToState($row['id'], $startdt, 18); } # leave existing tomaintenance reservation as is } elseif (!simpleAddRequest($row['id'], $noimageid, $revid, $startdt, $enddt, 18, $vclreloadid)) { cleanSemaphore(); $fails[] = $compid; continue 2; # jump out of while, continue with foreach loop } $setnoteids[] = $row['id']; } if ($newstateid == 10 && count($setnoteids)) { $inids = implode(',', $setnoteids); $query = "UPDATE computer " . "SET notes = 'maintenance with host {$compid}' " . "WHERE id IN ({$inids})"; doQuery($query); } $start = $reloadstart + 300; # allow 5 minutes for VMs to get removed $startdt = unixToDatetime($start); # lock this computer if (!retryGetSemaphore($semimageid, $semrevid, $semmnid, $compid, $startdt, $enddt)) { cleanSemaphore(); $fails[] = $compid; continue; } if ($newstateid == 10) { $tostateid = 18; } else { $tostateid = 22; } $checkstart = getExistingChangeStateStartTime($compid, $tostateid); if ($checkstart) { if ($checkstart > $start) { # update start time of existing tomaintenance/tohpc reservation updateExistingToState($compid, $startdt, $tostateid); } # leave existing tomaintenance/tohpc reservation as is } elseif (!simpleAddRequest($compid, $noimageid, $revid, $startdt, $enddt, $tostateid, $vclreloadid)) { cleanSemaphore(); $fails[] = $compid; continue; } cleanSemaphore(); $changetimes[$compid] = $start; $changeasap[] = $compid; continue; } else { if ($newstateid == 10) { $note = "maintenance with host {$compid}"; } else { $note = "maintenance so {$compid} can go to hpc"; } # no VMs or no reservations on assigned VMs $query = "UPDATE computer c " . "INNER JOIN vmhost v ON (c.vmhostid = v.id) " . "SET c.stateid = 10, " . "c.notes = '{$note}' " . "WHERE v.computerid = {$compid}"; doQuery($query); } } elseif ($reloadstart) { if (unixToDatetime($reloadstart) == '2038-01-01 00:00:00') { # node is reserved indefintely $fails[] = $compid; continue; } # computer has reservations, schedule tomaintenance $noimageid = getImageId('noimage'); $revid = getProductionRevisionid($noimageid); $startdt = unixToDatetime($reloadstart); $end = $reloadstart + SECINMONTH; $enddt = unixToDatetime($end); # lock this computer if (!retryGetSemaphore($semimageid, $semrevid, $semmnid, $compid, $startdt, $enddt)) { $fails[] = $compid; cleanSemaphore(); continue; } if ($newstateid == 10) { $tostateid = 18; } else { $tostateid = 22; } $checkstart = getExistingChangeStateStartTime($compid, $tostateid); if ($checkstart) { if ($checkstart > $reloadstart) { # update start time of existing tomaintenance/tohpc reservation updateExistingToState($compid, $startdt, $tostateid); } else { # leave existing tomaintenance/tohpc reservation as is $reloadstart = $checkstart; } } elseif (!simpleAddRequest($compid, $noimageid, $revid, $startdt, $enddt, $tostateid, $vclreloadid)) { $fails[] = $compid; cleanSemaphore(); continue; } cleanSemaphore(); $changetimes[$compid] = $reloadstart; $changeasap[] = $compid; continue; } # change to maintenance/tohpc state and save in $changenow // if we wait and put them all in maintenance/hpc at the same time, # we may end up moving reservations to the computer later in the # loop # lock this computer if (!retryGetSemaphore($semimageid, $semrevid, $semmnid, $compid, $semstart, $semend)) { $fails[] = $compid; cleanSemaphore(); continue; } $query = "UPDATE computer " . "SET stateid = {$newstateid} " . "WHERE id = {$compid}"; doQuery($query, 101); $changenow[] = $compid; cleanSemaphore(); } if ($newstateid == 10 && (count($noaction) || count($changeasap))) { $comparr = array_merge($noaction, $changeasap); $allids = implode(',', $comparr); if (count($vmwithhost)) { $skipids = implode(',', $vmwithhost); } else { $skipids = "''"; } $query = "UPDATE computer " . "SET notes = '{$notes}' " . "WHERE id IN ({$allids}) AND " . "id NOT IN ({$skipids})"; doQuery($query, 101); $updatevms = array_intersect($vmwithhost, $comparr); if (count($updatevms)) { $inids = implode(',', $updatevms); $query = "UPDATE computer vm " . "INNER JOIN vmhost v ON (vm.vmhostid = v.id) " . "SET vm.notes = CONCAT('maintenance with host ', v.computerid) " . "WHERE vm.id IN ({$inids})"; doQuery($query); } } if ($newstateid == 10) { $newstate = 'maintenance'; } else { $newstate = 'hpc'; } $msg = ''; if (count($changenow)) { $msg .= "The following computers were immediately placed into the "; $msg .= "{$newstate} state:<br><br>\n"; $msg .= "<span class=\"ready\">\n"; foreach ($changenow as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "</span><br>\n"; } if (count($changeasap)) { $msg .= "The following computers are currently reserved "; $msg .= "and will be placed in the {$newstate} state at the time listed "; $msg .= "for each computer:\n"; $msg .= "<table>\n"; $msg .= " <tr>\n"; $msg .= " <th>Computer</th>\n"; $msg .= " <th>Time</th>\n"; $msg .= " </tr>\n"; foreach ($changeasap as $compid) { $msg .= " <tr>\n"; $msg .= " <td align=center><span class=\"wait\">{$computers[$compid]['hostname']}</span></td>\n"; $time = date('n/j/y g:i a', $changetimes[$compid]); $msg .= " <td align=center>{$time}</td>\n"; $msg .= " </tr>\n"; } $msg .= "</table>\n"; $msg .= "<br>\n"; } if (count($fails)) { $msg .= "The following computers are currently reserved "; $msg .= "but could not be scheduled to be moved to the {$newstate} state "; $msg .= "at this time:<br><br>\n"; $msg .= "<span class=\"rederrormsg\">\n"; foreach ($fails as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "</span><br>\n"; } if (count($noaction)) { $msg .= "The following computers were already in the {$newstate} state"; if ($newstateid == 10) { $msg .= " and had their notes on being in the maintenance state updated"; } $msg .= ":<br><br>\n"; foreach ($noaction as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "<br>\n"; } } elseif ($newstateid == 20) { $profileid = processInputVar('profileid', ARG_NUMERIC); $profiles = getContinuationVar('profiles'); if (!array_key_exists($profileid, $profiles)) { $ret = array('status' => 'error', 'errormsg' => 'Invalid profile submitted'); sendJSON($ret); return; } $vclreloadid = getUserlistID('vclreload@Local'); $imagerevisionid = getProductionRevisionid($profiles[$profileid]['imageid']); $computers = $this->getData($this->defaultGetDataArgs); $noaction = array(); $changenow = array(); $changenowreload = array(); $changeasap = array(); $changetimes = array(); $fails = array(); $semstart = unixToDatetime(time()); $semend = '2038-01-01 00:00:00'; $maintvmids = array(); $vmnotallowed = array(); $allvmids = array(); $allids = implode(',', $compids); $query = "SELECT v.computerid AS compid, " . "vm.id AS vmid, " . "vm.notes, " . "vm.stateid AS vmstateid " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid IN ({$allids}) AND " . "vm.vmhostid = v.id"; $qh = doQuery($query); while ($row = mysql_fetch_assoc($qh)) { if (!array_key_exists($row['compid'], $maintvmids)) { $maintvmids[$row['compid']] = array(); } if ($row['vmstateid'] == 10 && $row['notes'] == "maintenance with host {$row['compid']}") { $maintvmids[$row['compid']][] = $row['vmid']; } $allvmids[$row['compid']][] = $row['vmid']; } foreach ($compids as $compid) { if ($computers[$compid]['type'] == 'virtualmachine') { $vmnotallowed[] = $compid; continue; } # try to move future reservations off of computer moveReservationsOffComputer($compid); cleanSemaphore(); if ($computers[$compid]['state'] == 'maintenance') { if ($computers[$compid]['provisioning'] != 'None') { # schedule tovmhostinuse $start = getReloadStartTime(); # put computer in reload state so vcld will not ignore due to being in maintenance $query = "UPDATE computer " . "SET stateid = 19 " . "WHERE id = {$compid}"; doQuery($query); $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); cleanSemaphore(); if (!$rc) { $fails[] = $compid; continue; } if (!is_null($computers[$compid]['vmprofileid']) && array_key_exists($compid, $maintvmids) && count($maintvmids[$compid])) { $noimageid = getImageId('noimage'); $revid = getProductionRevisionid($noimageid); $reloadstart = $start + 1800; $reloadstartdt = unixToDatetime($reloadstart); $end = $reloadstart + 3600; $enddt = unixToDatetime($end); foreach ($maintvmids[$compid] as $vmid) { if (!retryGetSemaphore($semimageid, $semrevid, $semmnid, $vmid, $reloadstartdt, $enddt)) { continue; } simpleAddRequest($vmid, $noimageid, $revid, $reloadstartdt, $enddt, 19, $vclreloadid); # continue even if failed to schedule VM to be reloaded } cleanSemaphore(); } $changenowreload[] = $compid; } else { $query = "UPDATE computer " . "SET stateid = 20, " . "notes = '' " . "WHERE id = {$compid}"; doQuery($query); $this->updateVmhostProfile($compid, $profileid, $computers[$compid]['vmprofileid']); if (array_key_exists($compid, $maintvmids) && count($maintvmids[$compid])) { $allids = implode(',', $maintvmids[$compid]); $query = "UPDATE computer " . "SET stateid = 2, " . "notes = '' " . "WHERE id in ({$allids})"; doQuery($query); } $changenow[] = $compid; } } elseif ($computers[$compid]['state'] == 'hpc') { if ($computers[$compid]['provisioning'] != 'None') { # schedule tovmhostinuse $start = getReloadStartTime(); # put computer in reload state so vcld will not ignore due to being in maintenance $query = "UPDATE computer " . "SET stateid = 19 " . "WHERE id = {$compid}"; doQuery($query); $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); cleanSemaphore(); if (!$rc) { $fails[] = $compid; continue; } $changenowreload[] = $compid; } else { $query = "UPDATE computer " . "SET stateid = 20, " . "notes = '' " . "WHERE id = {$compid}"; doQuery($query); $this->updateVmhostProfile($compid, $profileid, $computers[$compid]['vmprofileid']); $changenow[] = $compid; } } elseif ($computers[$compid]['state'] == 'vmhostinuse') { if ($profiles[$computers[$compid]['vmprofileid']]['imageid'] != $profiles[$profileid]['imageid']) { if ($computers[$compid]['provisioning'] != 'None') { $sem = array('imageid' => $semimageid, 'revid' => $semrevid, 'mnid' => $semmnid, 'start' => $semstart, 'end' => $semend); moveReservationsOffVMs($compid, $sem); cleanSemaphore(); $reloadstart = getCompFinalVMReservationTime($compid, 1); if ($reloadstart < 0) { $fails[] = $compid; cleanSemaphore(); continue; } if ($reloadstart == 0) { $start = getReloadStartTime(); } else { $start = $reloadstart; } $noimageid = getImageId('noimage'); $revid = getProductionRevisionid($noimageid); $startdt = unixToDatetime($start); $end = $start + SECINWEEK; $enddt = unixToDatetime($end); if ($start == $reloadstart) { # check for existing reload reservations for all VMs and host $times = array(); $reqids = array(); $inids = implode(',', $allvmids[$compid]); $query = "SELECT UNIX_TIMESTAMP(MIN(rq.start)) AS start, " . "rs.computerid, " . "rq.id " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid IN ({$inids}) AND " . "rq.stateid = 19 AND " . "rs.imageid = {$noimageid} AND " . "rq.start > NOW() " . "GROUP BY rs.computerid " . "ORDER BY start"; $qh = doQuery($query); if (mysql_num_rows($qh) == count($allvmids)) { while ($row = mysql_fetch_assoc($qh)) { $times[$row['start']] = 1; $reqids[] = $row['id']; } if (count($times) == 1) { # found existing reload reservations for all VMs, now check host $hoststart = $times[0] + 300; $hoststartdt = unixToDatetime($hoststart); $hostend = $hoststart + SECINYEAR; $hostenddt = unixToDatetime($hostend); $query = "SELECT rq.id, " . "rq.start " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = {$compid} AND " . "rq.start = '{$hoststartdt}' AND " . "rq.end = '{$hostenddt}' AND " . "rs.imageid = '{$profiles[$profileid]['imageid']}' AND " . "rq.stateid = 21"; $qh = doQuery($query); if ($row = mysql_fetch_assoc($qh)) { # node was previously scheduled to be reloaded for vmhostinuse if ($times[0] > $start) { # update existing reservations $allreqids = implode(',', $reqids); $query1 = "UPDATE request " . "SET start = '{$startdt}', " . "end = '{$enddt}' " . "WHERE id IN ({$allreqids})"; # delay host by 5 minutes $start = $start + 300; $startdt = unixToDatetime($start); $end = $start + SECINYEAR; $enddt = unixToDatetime($end); # lock this computer if (!retryGetSemaphore($semimageid, $semrevid, $semmnid, $compid, $startdt, $enddt)) { $fails[] = $compid; continue; } doQuery($query1); $query2 = "UPDATE request " . "SET start = '{$startdt}', " . "end = '{$enddt}' " . "WHERE id = {$row['id']}"; doQuery($query2); $changeasap[] = $compid; $changetimes[$compid] = $start; } else { # just leave the existing ones there $changeasap[] = $compid; $changetimes[$compid] = $times[0] + 300; } cleanSemaphore(); continue; } } } } if (array_key_exists($compid, $allvmids)) { foreach ($allvmids[$compid] as $vmid) { $rc = simpleAddRequest($vmid, $noimageid, $revid, $startdt, $enddt, 19, $vclreloadid); if (!$rc) { $fails[] = $compid; cleanSemaphore(); continue 2; # jump out of this foreach to the bigger foreach } } } $start = $start + 300; # give 5 minutes for VMs $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); if (!$rc) { $fails[] = $compid; continue; } if ($reloadstart) { $changeasap[] = $compid; $changetimes[$compid] = $reloadstart; } else { $changenowreload[] = $compid; } } else { $this->updateVmhostProfile($compid, $profileid, $computers[$compid]['vmprofileid']); $changenow[] = $compid; } } else { $noaction[] = $compid; } } elseif (($reloadstart = moveReservationsOffComputer($compid)) == 0) { $start = getCompFinalReservationTime($compid, 21); $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); if (!$rc) { $fails[] = $compid; continue; } $changeasap[] = $compid; if (isset($this->startchange)) { $start = $this->startchange; } $changetimes[$compid] = $start; } else { if ($computers[$compid]['provisioning'] != 'None') { $start = getCompFinalReservationTime($compid, 21); $now = 0; if ($start == 0) { $start = getReloadStartTime(); $now = 1; } $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); if (!$rc) { $fails[] = $compid; continue; } if ($now) { $changenowreload[] = $compid; } else { $changeasap[] = $compid; $changetimes[$compid] = $start; } } else { $query = "UPDATE computer " . "SET stateid = 20, " . "notes = '' " . "WHERE id = {$compid}"; doQuery($query); $this->updateVmhostProfile($compid, $profileid, $computers[$compid]['vmprofileid']); $changenow[] = $compid; } } } $msg = ''; if (count($changenow)) { $msg .= "The following computers were placed into the vmhostinuse state "; $msg .= "or had their VM Host Profiles updated:<br><br>\n"; foreach ($changenow as $compid) { $msg .= "<span class=\"ready\">{$computers[$compid]['hostname']}</span><br>\n"; } $msg .= "<br>\n"; $ret['clearselection'] = 1; $ret['refreshcount'] = 5; } if (count($changenowreload)) { $msg .= "The following computers have been scheduled to be immediately reloaded<br>\n"; $msg .= "and placed into the vmhostinuse state:<br><br>\n"; foreach ($changenowreload as $compid) { $msg .= "<span class=\"ready\">{$computers[$compid]['hostname']}</span><br>\n"; } $msg .= "<br>\n"; $ret['clearselection'] = 1; $ret['refreshcount'] = 5; } if (count($changeasap)) { $msg .= "The following computers are currently reserved and have been scheduled<br>\n"; $msg .= "to be reloaded and placed into the vmhostinuse state at the time listed<br>\n"; $msg .= "for each computers:<br><br>\n"; $msg .= "<table>\n"; $msg .= " <tr>\n"; $msg .= " <th>Computer</th>\n"; $msg .= " <th>Reload time</th>\n"; $msg .= " </tr>\n"; foreach ($changeasap as $compid) { $msg .= " <tr>\n"; $msg .= " <td align=center><span class=\"wait\">{$computers[$compid]['hostname']}</span></td>\n"; $time = date('n/j/y g:i a', $changetimes[$compid]); $msg .= " <td align=center>{$time}</td>\n"; $msg .= " </tr>\n"; } $msg .= "</table>\n"; $msg .= "<br>\n"; } if (count($fails)) { $msg .= "Problems were encountered while trying to move the following computers<br>\n"; $msg .= "to the vmhostinuse state:<br><br>\n"; foreach ($fails as $compid) { $msg .= "<span class=\"rederrormsg\">{$computers[$compid]['hostname']}</span><br>\n"; } $msg .= "<br>\n"; } if (count($vmnotallowed)) { $msg .= "The following computers are VMs which cannot be placed into the "; $msg .= "vmhostinuse state:<br><br>\n"; foreach ($vmnotallowed as $compid) { $msg .= "<span class=\"rederrormsg\">{$computers[$compid]['hostname']}</span><br>\n"; } $msg .= "<br>\n"; } if (count($noaction)) { $msg .= "The following computers were already in the vmhostinuse state:<br><br>\n"; foreach ($noaction as $compid) { $msg .= "{$computers[$compid]['hostname']}<br>\n"; } $msg .= "<br>\n"; } } # clear user resource cache for this type $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 1, 0, 0)); unset($_SESSION['userresources'][$key]); $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 0, 0, 0)); unset($_SESSION['userresources'][$key]); $ret['msg'] = $msg; sendJSON($ret); }
function xmlRPCabort($errcode, $query = '') { global $mysql_link_vcl, $mysql_link_acct, $ERRORS, $user, $mode; global $XMLRPCERRORS; if (ONLINEDEBUG && checkUserHasPerm('View Debug Information')) { $msg = ''; if ($errcode >= 100 && $errcode < 400) { $msg .= "ERROR (" . mysql_errno($mysql_link_vcl) . ") - "; $msg .= mysql_error($mysql_link_vcl) . " {$query} "; } $msg .= $ERRORS["{$errcode}"]; $XMLRPCERRORS[100] = $msg; $faultcode = 100; } else { $message = ""; if ($errcode >= 100 && $errcode < 400) { $message .= mysql_error($mysql_link_vcl) . "\n"; $message .= mysql_error($mysql_link_acct) . "\n"; $message .= $query . "\n"; } $message .= "ERROR({$errcode}): " . $ERRORS["{$errcode}"] . "\n"; $message .= "Logged in user was " . $user["unityid"] . "\n"; $message .= "Mode was {$mode}\n\n"; if ($errcode == 20) { $urlArray = explode('?', $_SERVER["HTTP_REFERER"]); $message .= "HTTP_REFERER URL - " . $urlArray[0] . "\n"; $message .= "correct URL - " . BASEURL . SCRIPT . "\n"; } $message .= getBacktraceString(FALSE); $mailParams = "-f" . ENVELOPESENDER; mail(ERROREMAIL, "Error with VCL XMLRPC call", $message, '', $mailParams); $faultcode = 1; } printXMLRPCerror($faultcode); cleanSemaphore(); dbDisconnect(); exit; }
function AJvmFromHost() { $hostid = processInputVar('hostid', ARG_NUMERIC); $hostdata = getVMHostData($hostid); $resources = getUserResources(array("computerAdmin"), array("administer")); if (!array_key_exists($hostdata[$hostid]['computerid'], $resources['computer'])) { sendJSON(array('failed' => 'nohostaccess')); return; } $fails = array(); $vmlistids = processInputVar('listids', ARG_STRING); $vmids = explode(',', $vmlistids); $rems = array(); $checks = array(); $vclreloadid = getUserlistID('vclreload@Local'); $imageid = getImageId('noimage'); $imagerevisionid = getProductionRevisionid($imageid); $start = getReloadStartTime(); $end = $start + SECINMONTH; $start = unixToDatetime($start); $end = unixToDatetime($end); foreach ($vmids as $compid) { $compdata = getComputers(0, 0, $compid); if (!array_key_exists($compid, $resources['computer'])) { $fails[] = array('id' => $compid, 'name' => $compdata[$compid]['hostname'], 'reason' => 'noaccess'); continue; } # try to remove reservations off of computer moveReservationsOffComputer($compid); cleanSemaphore(); # check for unmovable or active reservations $query = "SELECT DATE_FORMAT(rq.end, '%l:%i%p %c/%e/%y') AS end, " . "rq.end AS end2 " . "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)) { $checks[] = array('id' => $compid, 'hostname' => $compdata[$compid]['hostname'], 'end' => strtolower($row['end']), 'end2' => $row['end2']); } else { // if no reservations on computer, submit reload # reservation so vm gets stopped on host $reqid = simpleAddRequest($compid, $imageid, $imagerevisionid, $start, $end, 18, $vclreloadid); if ($reqid == 0) { $fails[] = array('id' => $compid, 'name' => $compdata[$compid]['hostname'], 'reason' => 'nomgtnode'); } else { $rems[] = array('id' => $compid, 'hostname' => $compdata[$compid]['hostname'], 'reqid' => $reqid, 'time' => 'immediately'); } } } if (count($checks)) { $cont = addContinuationsEntry('AJvmFromHostDelayed', $checks, 120, 1, 0); } else { $cont = ''; } $arr = array('vms' => $rems, 'checks' => $checks, 'fails' => $fails, 'addrem' => 0, 'cont' => $cont); sendJSON($arr); }
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; }