You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by jf...@apache.org on 2014/09/11 18:01:49 UTC
svn commit: r1624325 [10/13] - in /vcl/trunk/web: ./ .ht-inc/
.ht-inc/authmethods/ css/ js/ js/resources/
Modified: vcl/trunk/web/.ht-inc/utils.php
URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/utils.php?rev=1624325&r1=1624324&r2=1624325&view=diff
==============================================================================
--- vcl/trunk/web/.ht-inc/utils.php (original)
+++ vcl/trunk/web/.ht-inc/utils.php Thu Sep 11 16:01:48 2014
@@ -20,6 +20,7 @@ require_once(".ht-inc/secrets.php");
@include_once("itecsauth/itecsauth.php");
require_once(".ht-inc/authentication.php");
require_once(".ht-inc/phpseclib/Crypt/AES.php");
+require_once(".ht-inc/spyc-0.5/spyc.php");
if(file_exists(".ht-inc/vcldocs.php"))
require_once(".ht-inc/vcldocs.php");
@@ -35,14 +36,10 @@ define("ARG_STRING", 1 << 1);
define("ARG_MULTINUMERIC", 1 << 2);
/// used for processInputVar, means the input variable should be an array of strings
define("ARG_MULTISTRING", 1 << 3);
-/// define semaphore key
-define("SEMKEY", 192365819256598);
/// global array used to hold request information between calling isAvailable
/// and addRequest
$requestInfo = array();
-#$requestInfo["freeComputerids"] = array();
-#$requestInfo["imageids"] = array();
/// global array to cache arrays of node parents for getNodeParents
$nodeparents = array();
@@ -62,20 +59,25 @@ $printedHTMLheader = 0;
////////////////////////////////////////////////////////////////////////////////
function initGlobals() {
global $mode, $user, $remoteIP, $authed, $oldmode, $semid;
- global $semislocked, $days, $phpVer, $keys, $pemkey, $AUTHERROR;
+ global $days, $phpVer, $keys, $pemkey, $AUTHERROR;
global $passwdArray, $skin, $contdata, $lastmode, $inContinuation;
- global $totalQueries, $ERRORS, $queryTimes, $actions;
+ global $ERRORS, $actions;
global $affilValFunc, $addUserFunc, $updateUserFunc, $addUserFuncArgs;
+ global $uniqid;
define("SECINDAY", 86400);
define("SECINWEEK", 604800);
define("SECINMONTH", 2678400);
define("SECINYEAR", 31536000);
+ # TODO validate security of this
+ if(array_key_exists("PATH_INFO", $_SERVER)) {
+ $pathdata = explode("/", $_SERVER["PATH_INFO"]);
+ $tmp = explode('.', $pathdata[1]);
+ $_GET["mode"] = $tmp[0];
+ }
$mode = processInputVar("mode", ARG_STRING, 'main');
- $totalQueries = 0;
$inContinuation = 0;
$contdata = array();
- $queryTimes = array();
$contuserid = '';
$continuation = processInputVar('continuation', ARG_STRING);
if(! empty($continuation)) {
@@ -101,6 +103,7 @@ function initGlobals() {
$days = array(_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday'));
$phpVerArr = explode('.', phpversion());
$phpVer = $phpVerArr[0];
+ $uniqid = uniqid($_SERVER['HTTP_HOST'] . "-" . getmypid() . "-");
$passwdArray = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
@@ -185,10 +188,6 @@ function initGlobals() {
$mode = "auth";
}
if($mode == 'xmlrpccall' || $mode == 'xmlrpcaffiliations') {
- // get the semaphore id
- if(! ($semid = sem_get(SEMKEY, 1, 0666, 1)))
- abort(2);
- $semislocked = 0;
require_once(".ht-inc/xmlrpcWrappers.php");
require_once(".ht-inc/requests.php");
require_once(".ht-inc/serverprofiles.php");
@@ -257,29 +256,11 @@ function initGlobals() {
$updateUserFunc[$id] = create_function('', 'return NULL;');
}
- // get the semaphore id
- if(! ($semid = sem_get(SEMKEY, 1, 0666, 1)))
- abort(2);
- $semislocked = 0;
-
# include appropriate files
switch($actions['pages'][$mode]) {
case 'blockAllocations':
require_once(".ht-inc/blockallocations.php");
break;
- case 'manageComputers':
- require_once(".ht-inc/computers.php");
- break;
- case 'managementNodes':
- require_once(".ht-inc/managementnodes.php");
- break;
- case 'manageImages':
- require_once(".ht-inc/images.php");
- require_once(".ht-inc/requests.php");
- break;
- case 'manageSchedules':
- require_once(".ht-inc/schedules.php");
- break;
case 'help':
require_once(".ht-inc/help.php");
break;
@@ -305,6 +286,20 @@ function initGlobals() {
case 'dashboard':
require_once(".ht-inc/dashboard.php");
break;
+ case 'siteconfig':
+ require_once(".ht-inc/siteconfig.php");
+ break;
+ case 'resource':
+ case 'config':
+ case 'image':
+ case 'computer':
+ case 'managementnode':
+ case 'schedule':
+ require_once(".ht-inc/resource.php");
+ break;
+ case 'storebackend':
+ require_once(".ht-inc/storebackend.php");
+ break;
case 'serverProfiles':
require_once(".ht-inc/serverprofiles.php");
require_once(".ht-inc/requests.php");
@@ -316,6 +311,21 @@ function initGlobals() {
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn __autoload($class)
+///
+/// \param $class - name of a class
+///
+/// \brief handles loading class implementation file for a specified class
+///
+////////////////////////////////////////////////////////////////////////////////
+function __autoload($class) {
+ $class = strtolower($class);
+ require_once(".ht-inc/resource.php");
+ require_once(".ht-inc/$class.php");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn checkAccess()
///
/// \brief gets the user's access level to the locker from the ptsowner_admin
@@ -346,6 +356,11 @@ function checkAccess() {
exit;
}
}
+ if(! array_key_exists('HTTP_X_PASS', $_SERVER) || strlen($_SERVER['HTTP_X_PASS']) == 0) {
+ printXMLRPCerror(3); # access denied
+ dbDisconnect();
+ exit;
+ }
$xmlpass = $_SERVER['HTTP_X_PASS'];
if(get_magic_quotes_gpc())
$xmlpass = stripslashes($xmlpass);
@@ -439,16 +454,16 @@ function checkAccess() {
exit;
}
}
- elseif($authMechs[$authtype]['type'] == 'redirect'){
- $affilid = $authMechs[$authtype]['affiliationid'];
- if(!(isset($apiValidateFunc) && is_array($apiValidateFunc) &&
- array_key_exists($affilid, $apiValidateFunc) &&
- $apiValidateFunc[$affilid]($xmluser, $xmlpass))){
- printXMLRPCerror(3); # access denied
- dbDisconnect();
- exit;
- }
- }
+ elseif($authMechs[$authtype]['type'] == 'redirect') {
+ $affilid = $authMechs[$authtype]['affiliationid'];
+ if(!(isset($apiValidateFunc) && is_array($apiValidateFunc) &&
+ array_key_exists($affilid, $apiValidateFunc) &&
+ $apiValidateFunc[$affilid]($xmluser, $xmlpass))) {
+ printXMLRPCerror(3); # access denied
+ dbDisconnect();
+ exit;
+ }
+ }
else {
printXMLRPCerror(6); # unable to auth passed in X-User
dbDisconnect();
@@ -491,16 +506,6 @@ function checkAccess() {
if(! $inContinuation) {
# check that user has access to this area
switch($mode) {
- case 'viewRequests':
- $requests = getUserRequests("all", $user["id"]);
- if(! in_array("imageCheckOut", $user["privileges"]) &&
- ! in_array("imageAdmin", $user["privileges"]) &&
- ! count($requests)) {
- $mode = "";
- $actionFunction = "main";
- return;
- }
- break;
case 'viewGroups':
if(! in_array("groupAdmin", $user["privileges"])) {
$mode = "";
@@ -508,34 +513,6 @@ function checkAccess() {
return;
}
break;
- case 'selectImageOption':
- if(! in_array("imageAdmin", $user["privileges"])) {
- $mode = "";
- $actionFunction = "main";
- return;
- }
- break;
- case 'viewSchedules':
- if(! in_array("scheduleAdmin", $user["privileges"])) {
- $mode = "";
- $actionFunction = "main";
- return;
- }
- break;
- case 'selectComputers':
- if(! in_array("computerAdmin", $user["privileges"])) {
- $mode = "";
- $actionFunction = "main";
- return;
- }
- break;
- case 'selectMgmtnodeOption':
- if(! in_array("mgmtNodeAdmin", $user["privileges"])) {
- $mode = "";
- $actionFunction = "main";
- return;
- }
- break;
case 'serverProfiles':
if(! in_array("serverProfileAdmin", $user["privileges"]) &&
! in_array("serverCheckOut", $user["privileges"])) {
@@ -756,6 +733,7 @@ function clearPrivCache() {
$_SESSION['userhaspriv'] = array();
$_SESSION['compstateflow'] = array();
$_SESSION['usersessiondata'] = array();
+ $_SESSION['variables'] = array();
unset($_SESSION['user']);
unset($_SESSION['locales']);
}
@@ -808,6 +786,8 @@ function setupSession() {
$_SESSION['compstateflow'] = array();
if(! array_key_exists('usersessiondata', $_SESSION))
$_SESSION['usersessiondata'] = array();
+ if(! array_key_exists('variables', $_SESSION))
+ $_SESSION['variables'] = array();
}
////////////////////////////////////////////////////////////////////////////////
@@ -899,7 +879,8 @@ function abort($errcode, $query="") {
$message = "";
if($errcode >= 100 && $errcode < 400) {
$message .= mysql_error($mysql_link_vcl) . "\n";
- $message .= mysql_error($mysql_link_acct) . "\n";
+ if($ENABLE_ITECSAUTH)
+ $message .= mysql_error($mysql_link_acct) . "\n";
$message .= $query . "\n";
}
$message .= "ERROR($errcode): " . $ERRORS["$errcode"] . "\n";
@@ -926,10 +907,10 @@ function abort($errcode, $query="") {
print HELPEMAIL . "</a> " . _("for further assistance. Please include the ");
print _("steps you took that led up to this problem in your email message.");
}
+ // release semaphore lock
+ cleanSemaphore();
dbDisconnect();
printHTMLFooter();
- // release semaphore lock
- semUnlock();
exit;
}
@@ -1115,10 +1096,9 @@ function dbDisconnect() {
////////////////////////////////////////////////////////////////////////////////
function doQuery($query, $errcode=101, $db="vcl", $nolog=0) {
global $mysql_link_vcl, $mysql_link_acct, $user, $mode, $ENABLE_ITECSAUTH;
- global $totalQueries, $queryTimes;
- $totalQueries++;
if($db == "vcl") {
- if((! $nolog) && preg_match('/^(UPDATE|INSERT|DELETE)/', $query)) {
+ if((! $nolog) && preg_match('/^(UPDATE|INSERT|DELETE)/', $query) &&
+ strpos($query, 'UPDATE continuations SET expiretime = ') === FALSE) {
$logquery = str_replace("'", "\'", $query);
$logquery = str_replace('"', '\"', $logquery);
if(isset($user['id']))
@@ -1137,7 +1117,12 @@ function doQuery($query, $errcode=101, $
. "'$logquery')";
mysql_query($q, $mysql_link_vcl);
}
- $qh = mysql_query($query, $mysql_link_vcl) or abort($errcode, $query);
+ for($i = 0; ! ($qh = mysql_query($query, $mysql_link_vcl)) && $i < 3; $i++) {
+ if(mysql_errno() == '1213') # DEADLOCK, sleep and retry
+ usleep(50);
+ else
+ abort($errcode, $query);
+ }
}
elseif($db == "accounts") {
if($ENABLE_ITECSAUTH)
@@ -1172,7 +1157,8 @@ function dbLastInsertID() {
///
////////////////////////////////////////////////////////////////////////////////
function getOSList() {
- $qh = doQuery("SELECT id, name, prettyname, type FROM OS", "115");
+ $query = "SELECT id, name, prettyname, type, installtype FROM OS ORDER BY prettyname";
+ $qh = doQuery($query, "115");
$oslist = array();
while($row = mysql_fetch_assoc($qh))
$oslist[$row['id']] = $row;
@@ -1197,6 +1183,8 @@ function getOSList() {
/// \b osid - osid for the os on the image\n
/// \b os - os the image contains\n
/// \b installtype - method used to install image\n
+/// \b ostypeid - id of the OS type in the image\n
+/// \b ostype - name of the OS type in the image\n
/// \b minram - minimum amount of RAM needed for image\n
/// \b minprocnumber - minimum number of processors needed for image\n
/// \b minprocspeed - minimum speed of processor(s) needed for image\n
@@ -1255,14 +1243,17 @@ function getImages($includedeleted=0, $i
. "CONCAT(u.unityid, '@', a.name) AS user, "
. "i.datecreated, "
. "DATE_FORMAT(i.datecreated, '%c/%d/%y %l:%i %p') AS prettydate, "
+ . "i.deleted, "
+ . "i.datedeleted, "
. "i.production, "
. "i.imagename "
. "FROM imagerevision i, "
. "affiliation a, "
. "user u "
- . "WHERE i.deleted = 0 AND "
- . "i.userid = u.id AND "
- . "u.affiliationid = a.id";
+ . "WHERE i.userid = u.id AND ";
+ if(! $includedeleted)
+ $query .= "i.deleted = 0 AND ";
+ $query .= "u.affiliationid = a.id";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$id = $row['imageid'];
@@ -1281,6 +1272,8 @@ function getImages($includedeleted=0, $i
. "i.OSid AS osid, "
. "o.name AS os, "
. "o.installtype, "
+ . "ot.id AS ostypeid, "
+ . "ot.name AS ostype, "
. "i.minram AS minram, "
. "i.minprocnumber AS minprocnumber, "
. "i.minprocspeed AS minprocspeed, "
@@ -1297,6 +1290,7 @@ function getImages($includedeleted=0, $i
. "FROM image i, "
. "platform p, "
. "OS o, "
+ . "OStype ot, "
. "resource r, "
. "resourcetype t, "
. "user u, "
@@ -1306,6 +1300,7 @@ function getImages($includedeleted=0, $i
. "t.name = 'image' AND "
. "r.subid = i.id AND "
. "i.OSid = o.id AND "
+ . "o.type = ot.name AND "
. "i.ownerid = u.id AND "
. "u.affiliationid = a.id ";
if(! $includedeleted)
@@ -1313,7 +1308,11 @@ function getImages($includedeleted=0, $i
$query .= "ORDER BY i.prettyname";
$qh = doQuery($query, 120);
while($row = mysql_fetch_assoc($qh)) {
+ if(is_null($row['maxconcurrent']))
+ $row['maxconcurrent'] = 0;
$imagelist[$includedeleted][$row["id"]] = $row;
+ $imagelist[$includedeleted][$row["id"]]['checkuser'] = 1;
+ $imagelist[$includedeleted][$row["id"]]['rootaccess'] = 1;
if($row["imagemetaid"] != NULL) {
if(array_key_exists($row['imagemetaid'], $allmetadata)) {
$metaid = $row['imagemetaid'];
@@ -1331,7 +1330,7 @@ function getImages($includedeleted=0, $i
}
}
else
- $row["imagemetaid"] = NULL;
+ $imagelist[$includedeleted][$row["id"]]["imagemetaid"] = NULL;
}
if(array_key_exists($row['id'], $allrevisiondata))
$imagelist[$includedeleted][$row['id']]['imagerevision'] = $allrevisiondata[$row['id']];
@@ -1344,6 +1343,131 @@ function getImages($includedeleted=0, $i
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn getServerProfiles($id)
+///
+/// \param $id - (optional) if specified, only return data for specified profile
+///
+/// \return an array where each key is a profile id whose value is an array with
+/// these values:\n
+/// \b name - profile name\n
+/// \b description - profile description\n
+/// \b imageid - id of image associated with profile\n
+/// \b image - pretty name of image associated with profile\n
+/// \b ownerid - user id of owner of profile\n
+/// \b owner - unityid of owner of profile\n
+/// \b fixedIP - IP address to be used with deployed profile\n
+/// \b fixedMAC - MAC address to be used with deployed profile\n
+/// \b admingroupid - id of admin user group associated with profile\n
+/// \b admingroup - name of admin user group associated with profile\n
+/// \b logingroupid - id of login user group associated with profile\n
+/// \b logingroup - name of login user group associated with profile\n
+/// \b monitored - whether or not deployed profile should be monitored\n
+/// \b resourceid - resource id of profile
+///
+/// \brief gets information about server profiles
+///
+////////////////////////////////////////////////////////////////////////////////
+function getServerProfiles($id=0) {
+ $key = getKey(array('getServerProfiles', $id));
+ if(array_key_exists($key, $_SESSION['usersessiondata']))
+ return $_SESSION['usersessiondata'][$key];
+
+ $fixeddata = array();
+ $query = "SELECT name, value FROM variable WHERE name LIKE 'fixedIPsp%'";
+ $qh = doQuery($query);
+ while($row = mysql_fetch_assoc($qh)) {
+ $spid = str_replace('fixedIPsp', '', $row['name']);
+ $fixeddata[$spid] = Spyc::YAMLLoad($row['value']);
+ }
+
+ $query = "SELECT s.id, "
+ . "s.name, "
+ . "s.description, "
+ . "s.imageid, "
+ . "i.prettyname AS image, "
+ . "s.ownerid, "
+ . "CONCAT(u.unityid, '@', a.name) AS owner, "
+ . "s.fixedIP, "
+ . "s.fixedMAC, "
+ . "s.admingroupid, "
+ . "CONCAT(ga.name, '@', aa.name) AS admingroup, "
+ . "s.logingroupid, "
+ . "CONCAT(gl.name, '@', al.name) AS logingroup, "
+ . "s.monitored, "
+ . "r.id AS resourceid "
+ . "FROM serverprofile s "
+ . "LEFT JOIN image i ON (i.id = s.imageid) "
+ . "LEFT JOIN user u ON (u.id = s.ownerid) "
+ . "LEFT JOIN affiliation a ON (a.id = u.affiliationid) "
+ . "LEFT JOIN usergroup ga ON (ga.id = s.admingroupid) "
+ . "LEFT JOIN affiliation aa ON (aa.id = ga.affiliationid) "
+ . "LEFT JOIN usergroup gl ON (gl.id = s.logingroupid) "
+ . "LEFT JOIN affiliation al ON (al.id = gl.affiliationid) "
+ . "LEFT JOIN resource r ON (r.subid = s.id) "
+ . "WHERE r.resourcetypeid = 17 ";
+ if($id != 0)
+ $query .= "AND s.id = $id";
+ else
+ $query .= "ORDER BY name";
+ $qh = doQuery($query, 101);
+ $profiles = array();
+ while($row = mysql_fetch_assoc($qh)) {
+ $profiles[$row['id']] = $row;
+ if(array_key_exists($row['id'], $fixeddata)) {
+ $profiles[$row['id']]['netmask'] = $fixeddata[$row['id']]['netmask'];
+ $profiles[$row['id']]['router'] = $fixeddata[$row['id']]['router'];
+ $profiles[$row['id']]['dns'] = implode(',', $fixeddata[$row['id']]['dns']);
+ }
+ else {
+ $profiles[$row['id']]['netmask'] = '';
+ $profiles[$row['id']]['router'] = '';
+ $profiles[$row['id']]['dns'] = '';
+ }
+ }
+ $_SESSION['usersessiondata'][$key] = $profiles;
+ return $profiles;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getServerProfileImages($userid)
+///
+/// \param $userid - id from user table
+///
+/// \return array where the key is the id of the image and the value is the
+/// prettyname of the image
+///
+/// \brief builds an array of images that user has access to via server profiles
+///
+////////////////////////////////////////////////////////////////////////////////
+function getServerProfileImages($userid) {
+ $key = getKey(array('getServerProfileImages', $userid));
+ if(array_key_exists($key, $_SESSION['usersessiondata']))
+ return $_SESSION['usersessiondata'][$key];
+ $resources = getUserResources(array('serverCheckOut', 'serverProfileAdmin'),
+ array('available', 'administer'));
+ $ids = array_keys($resources['serverprofile']);
+ $inids = implode(',', $ids);
+ if(empty($inids)) {
+ $_SESSION['usersessiondata'][$key] = array();
+ return array();
+ }
+ $query = "SELECT i.id, "
+ . "i.prettyname AS image "
+ . "FROM serverprofile s, "
+ . "image i "
+ . "WHERE s.imageid = i.id AND "
+ . "s.id IN ($inids)";
+ $qh = doQuery($query, 101);
+ $profiles = array();
+ while($row = mysql_fetch_assoc($qh))
+ $profiles[$row['id']] = $row['image'];
+ $_SESSION['usersessiondata'][$key] = $profiles;
+ return $profiles;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn getImageRevisions($imageid, $incdeleted)
///
/// \param $imageid - id of an image
@@ -1420,10 +1544,12 @@ function getImageNotes($imageid) {
////////////////////////////////////////////////////////////////////////////////
///
-/// \fn getImageConnectMethods($imageid, $revisionid)
+/// \fn getImageConnectMethods($imageid, $revisionid, $nostatic=0)
///
/// \param $imageid - id of an image
/// \param $revisionid - (optional, default=0) revision id of image
+/// \param $nostatic - (optional, default=0) pass 1 to keep from using the
+/// static variable defined in the function
///
/// \return an array of connect methods enabled for specified image where the
/// key is the id of the connect method and the value is the description
@@ -1431,18 +1557,20 @@ function getImageNotes($imageid) {
/// \brief builds an array of connect methods enabled for the image
///
////////////////////////////////////////////////////////////////////////////////
-function getImageConnectMethods($imageid, $revisionid=0) {
- $key = getKey(array('getImageConnectMethods', $imageid, $revisionid));
+function getImageConnectMethods($imageid, $revisionid=0, $nostatic=0) {
+ $key = getKey(array('getImageConnectMethods', (int)$imageid, (int)$revisionid));
if(array_key_exists($key, $_SESSION['usersessiondata']))
return $_SESSION['usersessiondata'][$key];
if($revisionid == 0)
- $revisionid = getProductionRevisionid($imageid);
+ $revisionid = getProductionRevisionid($imageid, $nostatic);
if($revisionid == '') {
$_SESSION['usersessiondata'][$key] = array();
return array();
}
static $allmethods = array();
+ if($nostatic)
+ $allmethods = array();
if(empty($allmethods)) {
$query = "SELECT DISTINCT c.id, "
. "c.description, "
@@ -1622,9 +1750,11 @@ function checkClearImageMeta($imagemetai
////////////////////////////////////////////////////////////////////////////////
///
-/// \fn getProductionRevisionid($imageid)
+/// \fn getProductionRevisionid($imageid, $nostatic=0)
///
/// \param $imageid
+/// \param $nostatic - (optional, default=0) pass 1 to keep from using the
+/// static variable defined in the function
///
/// \return the production revision id for $imageid
///
@@ -1632,8 +1762,10 @@ function checkClearImageMeta($imagemetai
/// table
///
////////////////////////////////////////////////////////////////////////////////
-function getProductionRevisionid($imageid) {
+function getProductionRevisionid($imageid, $nostatic=0) {
static $alldata = array();
+ if($nostatic)
+ $alldata = array();
if(! empty($alldata))
if(array_key_exists($imageid, $alldata))
return $alldata[$imageid];
@@ -1709,6 +1841,8 @@ function removeNoCheckout($images) {
function getUserResources($userprivs, $resourceprivs=array("available"),
$onlygroups=0, $includedeleted=0, $userid=0) {
global $user;
+ if(in_array('managementnodeAdmin', $userprivs))
+ $userprivs[] = 'mgmtnodeAdmin';
$key = getKey(array($userprivs, $resourceprivs, $onlygroups, $includedeleted, $userid));
if(array_key_exists($key, $_SESSION['userresources']))
return $_SESSION['userresources'][$key];
@@ -1840,6 +1974,9 @@ function getUserResources($userprivs, $r
getResourcesFromGroups($resourcegroups[$type], $type, $includedeleted);
}
addOwnedResources($resources, $includedeleted, $userid);
+ $noimageid = getImageId('noimage');
+ if(array_key_exists($noimageid, $resources['image']))
+ unset($resources['image'][$noimageid]);
$_SESSION['userresources'][$key] = $resources;
return $resources;
}
@@ -2082,23 +2219,25 @@ function addUserResources(&$nodeprivs, $
////////////////////////////////////////////////////////////////////////////////
function addOwnedResources(&$resources, $includedeleted, $userid) {
foreach(array_keys($resources) as $type) {
- if($type == "image")
- $field = "prettyname";
- elseif($type == "computer")
- $field = "hostname";
- elseif($type == "schedule")
- $field = "name";
- elseif($type == "managementnode")
- $field = "hostname";
- elseif($type == "serverprofile")
- $field = "name";
- else
- continue;
+ # TODO make this get name field from classes
+ switch($type) {
+ case "image":
+ $field = 'prettyname';
+ break;
+ case "computer":
+ case "managementnode":
+ $field = 'hostname';
+ break;
+ default:
+ $field = 'name';
+ break;
+ }
$query = "SELECT id, "
. "$field "
. "FROM $type "
. "WHERE ownerid = $userid";
- if(! $includedeleted && ($type == "image" || $type == "computer"))
+ if(! $includedeleted &&
+ ($type == "image" || $type == "computer" || $type == 'config'))
$query .= " AND deleted = 0";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
@@ -2157,18 +2296,18 @@ function addOwnedResourceGroups(&$resour
////////////////////////////////////////////////////////////////////////////////
function getResourcesFromGroups($groups, $type, $includedeleted) {
$return = array();
- if($type == "image")
- $field = "prettyname";
- elseif($type == "computer")
- $field = "hostname";
- elseif($type == "schedule")
- $field = "name";
- elseif($type == "managementnode")
- $field = "hostname";
- elseif($type == "serverprofile")
- $field = "name";
- else
- return array();
+ switch($type) {
+ case "image":
+ $field = 'prettyname';
+ break;
+ case "computer":
+ case "managementnode":
+ $field = 'hostname';
+ break;
+ default:
+ $field = 'name';
+ break;
+ }
$groups = implode("','", $groups);
$inlist = "'$groups'";
@@ -2186,7 +2325,8 @@ function getResourcesFromGroups($groups,
. "g.name IN ($inlist) AND "
. "g.resourcetypeid = rt.id AND "
. "rt.name = '$type'";
- if(! $includedeleted && ($type == "image" || $type == "computer")) {
+ if(! $includedeleted &&
+ ($type == "image" || $type == "computer" || $type == 'config')) {
$query .= "AND deleted = 0 ";
}
/*if($type == "image")
@@ -2354,17 +2494,18 @@ function decryptData($data) {
}
////////////////////////////////////////////////////////////////////////////////
-//
-// \fn encryptDataAsymmetric($data, $public_key)
-//
-// \param $data - a string
-//
-// \param $public_key - either a filename for a public key or the public key itself
-//
-// \return hex-encoded, encrypted form of $data
-//
-// \brief generate public key encrypted data
-//
+///
+/// \fn encryptDataAsymmetric($data, $public_key)
+///
+/// \param $data - a string
+///
+/// \param $public_key - either a filename for a public key or the public key
+/// itself
+///
+/// \return hex-encoded, encrypted form of $data
+///
+/// \brief generate public key encrypted data
+///
////////////////////////////////////////////////////////////////////////////////
function encryptDataAsymmetric($data, $public_key){
if(file_exists($public_key)){
@@ -3176,7 +3317,7 @@ function processInputVar($vartag, $type,
if(! is_string($return)) {
print "ERROR (code:3)<br>\n";
printHTMLFooter();
- semUnlock();
+ cleanSemaphore();
exit();
}
#print "before - $return<br>\n";
@@ -3198,7 +3339,7 @@ function processInputVar($vartag, $type,
if(! is_string($value)) {
print "ERROR (code:3)<br>\n";
printHTMLFooter();
- semUnlock();
+ cleanSemaphore();
exit();
}
}
@@ -3406,6 +3547,8 @@ function getUserInfo($id, $noupdate=0, $
. "u.mapserial AS mapserial, "
. "u.showallgroups, "
. "u.lastupdated AS lastupdated, "
+ . "u.usepublickeys, "
+ . "u.sshpublickeys, "
. "af.shibonly "
. "FROM user u, "
. "IMtype i, "
@@ -3419,6 +3562,7 @@ function getUserInfo($id, $noupdate=0, $
$qh = doQuery($query, "105");
if($user = mysql_fetch_assoc($qh)) {
+ $user['sshpublickeys'] = htmlspecialchars($user['sshpublickeys']);
if((datetimeToUnix($user["lastupdated"]) > time() - SECINDAY) ||
$user['unityid'] == 'vclreload' ||
$user['affiliation'] == 'Local' ||
@@ -3723,9 +3867,10 @@ function getOverallUserPrivs($userid) {
. "WHERE ownerid = $userid))";
$qh = doQuery($query, 107);
$privileges = array();
- while($row = mysql_fetch_row($qh)) {
- array_push($privileges, $row[0]);
- }
+ while($row = mysql_fetch_row($qh))
+ $privileges[] = $row[0];
+ if(in_array("mgmtNodeAdmin", $privileges))
+ $privileges[] = 'managementnodeAdmin';
return $privileges;
}
@@ -3765,14 +3910,17 @@ function getBlockAllocationIDs($user) {
////////////////////////////////////////////////////////////////////////////////
///
/// \fn isAvailable($images, $imageid, $imagerevisionid, $start, $end,
-/// $requestid, $userid, $ignoreprivileges, $forimaging, $ip,
-/// $mac, $skipconcurrentcheck)
+/// $holdcomps, $requestid, $userid, $ignoreprivileges,
+/// $forimaging, $ip, $mac, $skipconcurrentcheck)
///
/// \param $images - array as returned from getImages
/// \param $imageid - imageid from the image table
/// \param $imagerevisionid - id of revision of image from imagerevision table
/// \param $start - unix timestamp for start of reservation
/// \param $end - unix timestamp for end of reservation
+/// \param $holdcomps - bool - 1 to lock computers for later adding to
+/// reservation, 0 not to; use 0 when just checking for estimated availability,
+/// use 1 when finding computers to actually reserve
/// \param $requestid - (optional) a requestid; if checking for an available
/// timeslot to update a request, pass the request id that will be updated;
/// otherwise, don't pass this argument
@@ -3790,7 +3938,8 @@ function getBlockAllocationIDs($user) {
/// \param $skipconcurrentcheck (optional, default=0) - set to 1 to skip check
/// for concurrent use of image; useful for setting up reload reservations
///
-/// \return -3 if unavailable due to an ip/mac conflict
+/// \return -4 if unavailable due to an ip/mac conflict with another machine
+/// -3 if unavailable due to an ip/mac conflict with another reservation
/// -2 if specified time period is during a maintenance window
/// -1 if $imageid is limited in the number of concurrent reservations
/// available, and the limit has been reached
@@ -3801,16 +3950,25 @@ function getBlockAllocationIDs($user) {
///
////////////////////////////////////////////////////////////////////////////////
function isAvailable($images, $imageid, $imagerevisionid, $start, $end,
- $requestid=0, $userid=0, $ignoreprivileges=0,
+ $holdcomps, $requestid=0, $userid=0, $ignoreprivileges=0,
$forimaging=0, $ip='', $mac='', $skipconcurrentcheck=0) {
- global $requestInfo;
+ 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 -2;
+ 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;
@@ -3826,26 +3984,29 @@ function isAvailable($images, $imageid,
$requestInfo["computers"] = array();
$requestInfo["computers"][0] = 0;
$requestInfo["images"][0] = $imageid;
+ $requestInfo["imagerevisions"][0] = $imagerevisionid[$imageid][0];
- # loop to check for available computers for all needed images
+ # 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++;
}
}
- // get semaphore lock
- if(! semLock())
- abort(3);
-
$startstamp = unixToDatetime($start);
$endstamp = unixToDatetime($end + 900);
- # check for overlapping use of mac or ip
if(! empty($mac) || ! empty($ip)) {
+ # check for overlapping use of mac or ip
$query = "SELECT rq.id "
. "FROM reservation rs, "
. "request rq, "
@@ -3862,8 +4023,17 @@ function isAvailable($images, $imageid,
$query .= "LIMIT 1";
$qh = doQuery($query, 101);
if(mysql_num_rows($qh)) {
- semUnlock();
- return -3;
+ 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);
}
}
@@ -3874,10 +4044,19 @@ function isAvailable($images, $imageid,
$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');
@@ -3899,6 +4078,7 @@ function isAvailable($images, $imageid,
}
$usagecnt = count($compids);
$allids = implode("','", $compids);
+ $ignoregroups = implode("','", array_keys($usersgroups));
$query = "SELECT COUNT(bc.imageid) AS currentusage "
. "FROM blockComputers bc, "
. "blockRequest br, "
@@ -3907,34 +4087,55 @@ function isAvailable($images, $imageid,
. "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)) {
- semUnlock();
- return 0;
+ cleanSemaphore();
+ return debugIsAvailable(0, 3, $start, $end, $imagerevisionid);
}
if(($usagecnt + $row['currentusage'] - $decforedit) >= $images[$imageid]['maxconcurrent']) {
- semUnlock();
- return -1;
+ cleanSemaphore();
+ return debugIsAvailable(-1, 4, $start, $end, $imagerevisionid);
}
}
$platformid = getImagePlatform($imageid);
if(is_null($platformid)) {
- semUnlock();
- return 0;
+ cleanSemaphore();
+ return debugIsAvailable(0, 5, $start, $end, $imagerevisionid);
}
# get computers $imageid maps to
- $tmp = getMappedResources($imageid, "image", "computer");
- if(! count($tmp)) {
- semUnlock();
- return 0;
+ $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);
}
- $mappedcomputers = implode(',', $tmp);
#get computers for available schedules and platforms
$computerids = array();
@@ -3960,8 +4161,8 @@ function isAvailable($images, $imageid,
$qh = doQuery($query, 128);
$row = mysql_fetch_row($qh);
if(! in_array($row[0], $scheduleids)) {
- semUnlock();
- return 0;
+ 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;
@@ -3975,9 +4176,10 @@ function isAvailable($images, $imageid,
. "WHERE i.id = $imageid";
$qh = doQuery($query, 101);
if(! ($row = mysql_fetch_assoc($qh))) {
- semUnlock();
- return 0;
+ 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
@@ -4006,6 +4208,7 @@ function isAvailable($images, $imageid,
. "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 "
@@ -4020,16 +4223,17 @@ function isAvailable($images, $imageid,
if(! $ignoreprivileges)
$query .= "c.id IN ($usercomputers) AND ";
$query .= "c.id IN ($mappedcomputers) AND "
- . "c.id NOT IN ($alloccompids) "
- . "ORDER BY (c.procspeed * c.procnumber) DESC, "
- . "RAM DESC, "
- . "network DESC";
+ . "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'] == $imagerevisionid) {
+ $row['imagerevisionid'] == $requestInfo['imagerevisions'][$key]) {
array_push($currentids, $row['id']);
}
}
@@ -4039,6 +4243,10 @@ function isAvailable($images, $imageid,
$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 "
@@ -4060,15 +4268,19 @@ function isAvailable($images, $imageid,
// if modifying a reservation and $computerids is now empty, return 0
if($requestid && empty($computerids)) {
- semUnlock();
- return 0;
+ 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)) {
- semUnlock();
- return 0;
+ cleanSemaphore();
+ return debugIsAvailable(0, 10, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual);
}
}
elseif(! count($blockids)) { # && ! $altRemoveBlockCheck
@@ -4104,7 +4316,7 @@ function isAvailable($images, $imageid,
. "LEFT JOIN computer c2 ON (v.id = c2.vmhostid) "
. "LEFT JOIN image i ON (c2.currentimageid = i.id) "
. "WHERE c.stateid = 20 "
- . "GROUP BY c.id";
+ . "GROUP BY v.id";
doQuery($query, 101);
}
@@ -4116,9 +4328,9 @@ function isAvailable($images, $imageid,
. "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.procspeed * c.procnumber) DESC, "
- . "c.RAM DESC, "
- . "c.network DESC";
+ . "ORDER BY c.RAM, "
+ . "(c.procspeed * c.procnumber), "
+ . "c.network";
$qh = doQuery($query, 101);
$newcompids = array();
while($row = mysql_fetch_assoc($qh))
@@ -4126,6 +4338,48 @@ function isAvailable($images, $imageid,
$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);
@@ -4152,14 +4406,17 @@ function isAvailable($images, $imageid,
}
# allocate a computer
+ $_imgrevid = $requestInfo['imagerevisions'][$key];
$comparr = allocComputer($blockids, $currentids, $computerids,
- $startstamp, $nowfuture);
+ $startstamp, $endstamp, $nowfuture, $imageid, $_imgrevid,
+ $holdcomps, $requestid);
if(empty($comparr) && $shortened)
$comparr = allocComputer($origblockids, $origcurrentids,
- $origcomputerids, $startstamp, $nowfuture);
+ $origcomputerids, $startstamp, $endstamp, $nowfuture,
+ $imageid, $_imgrevid, $holdcomps, $requestid);
if(empty($comparr)) {
- semUnlock();
- return 0;
+ cleanSemaphore();
+ return debugIsAvailable(0, 11, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, $failedids, $virtual);
}
$requestInfo["computers"][$key] = $comparr['compid'];
@@ -4171,7 +4428,110 @@ function isAvailable($images, $imageid,
array_push($allocatedcompids, $comparr['compid']);
}
- return 1;
+ return debugIsAvailable(1, 12, $start, $end, $imagerevisionid, $computerids, $currentids, $blockids, array(), $virtual);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn debugIsAvailable($rc, $loc, $start, $end, $imagerevisionid,
+/// $compids=array(), $currentids=array(),
+/// $blockids=array(), $failedids=array(), $virtual='')
+///
+/// \param $rc - return code
+/// \param $loc - location from isAvailable function
+/// \param $start - as passed to isAvailable function
+/// \param $end - as passed to isAvailable function
+/// \param $imagerevisionid - as passed to isAvailable function
+/// \param $compids - $computerids from isAvailable
+/// \param $currentids - $currentids from isAvailable
+/// \param $blockids - $blockids from isAvailable
+/// \param $failedids - $failedids from isAvailable
+/// \param $virtual - $virtual from isAvailable
+///
+/// \return $rc as passed in
+///
+/// \brief prints debug line about why isAvailable returned specified return
+/// code in javascript console if user has 'View Debug Information' user group
+/// permission and has set the debug flag; most data passed in is currently
+/// unused, but allows for a single place to add code for debugging
+///
+////////////////////////////////////////////////////////////////////////////////
+function debugIsAvailable($rc, $loc, $start, $end, $imagerevisionid,
+ $compids=array(), $currentids=array(),
+ $blockids=array(), $failedids=array(), $virtual='') {
+ global $user, $mode;
+ $debug = getContinuationVar('debug', 0);
+ if(! $debug ||
+ $mode != 'AJupdateWaitTime' ||
+ ! checkUserHasPerm('View Debug Information'))
+ return $rc;
+ switch($loc) {
+ case "1":
+ $msg = "site maintenance is scheduled for the requested time";
+ break;
+ case "20":
+ $msg = "invalid image id submitted - not found in images available to the user";
+ break;
+ case "2":
+ $msg = "an overlapping server reservation has the same fixed IP or MAC address";
+ break;
+ case "16":
+ $msg = "the requested fixed IP address is currently in use by a management node";
+ break;
+ case "17":
+ $msg = "failed to look up information about the specified user";
+ break;
+ case "3":
+ $msg = "failed to get image usage count for block allocations";
+ break;
+ case "4":
+ $msg = "max concurrent usage of image exceeded (includes those set aside for block allocations)";
+ break;
+ case "5":
+ $msg = "failed to get platform of image";
+ break;
+ case "6":
+ $msg = "image is not mapped to any computers";
+ break;
+ case "18":
+ $msg = "no available computers under a management node that can handle the specified IP address";
+ break;
+ case "7":
+ $msg = "the schedule of the currently reserved computer does not allow for the requested time";
+ break;
+ case "8":
+ $msg = "failed to get OSinstalltype for image";
+ break;
+ case "21":
+ $msg = "no computers with a matching schedule and platform, and in an available state, and available to the user, and mapped to the image, and matching image resource requirements";
+ break;
+ case "9":
+ $msg = "not able to change existing reservation time for currently reserved computer";
+ break;
+ case "19":
+ $msg = "no computers available (after removing scheduled computers/before performing virtual host resource checks)";
+ break;
+ case "10":
+ $msg = "modification time overlaps with time computer is set aside for block allocation";
+ break;
+ case "13":
+ $msg = "no computers available (after virtual host resource checks/before performing overlapping IP address check)";
+ break;
+ case "18":
+ $msg = "requested IP address in use by another computer";
+ break;
+ case "19":
+ $msg = "at least 2 computers have the requested IP address assigned to them";
+ break;
+ case "11":
+ $msg = "unable to get either a management node or semaphore for available computer";
+ break;
+ case "12":
+ $msg = "successfully found a computer";
+ break;
+ }
+ print "console.log('$msg');";
+ return $rc;
}
////////////////////////////////////////////////////////////////////////////////
@@ -4274,14 +4634,20 @@ function schCheckMaintenance($start, $en
////////////////////////////////////////////////////////////////////////////////
///
-/// \fn allocComputer($blockids, $currentids, $computerids, $start,
-/// $nowfuture)
+/// \fn allocComputer($blockids, $currentids, $computerids, $start, $end,
+/// $nowfuture, $imageid, $imagerevisionid, $holdcomps,
+/// $requestid)
///
/// \param $blockids - array of computer ids
/// \param $currentids - array of computer ids
/// \param $computerids - array of computer ids
/// \param $start - start time in datetime format
+/// \param $start - end time in datetime format
/// \param $nowfuture - "now" or "future"
+/// \param $holdcomps - bool - 1 to lock computers for later adding to
+/// reservation, 0 not to; use 0 when just checking for estimated availability,
+/// use 1 when finding computers to actually reserve
+/// \param $requestid - id of request if called for editing an existing one
///
/// \return empty array if failed to allocate a computer; array with these keys
/// on success:\n
@@ -4294,8 +4660,10 @@ function schCheckMaintenance($start, $en
/// tries to allocate a management node for it
///
////////////////////////////////////////////////////////////////////////////////
-function allocComputer($blockids, $currentids, $computerids, $start,
- $nowfuture) {
+function allocComputer($blockids, $currentids, $computerids, $start, $end,
+ $nowfuture, $imageid, $imagerevisionid, $holdcomps,
+ $requestid) {
+ global $requestInfo;
$ret = array();
if(SCHEDULER_ALLOCATE_RANDOM_COMPUTER) {
shuffle($blockids);
@@ -4306,6 +4674,8 @@ function allocComputer($blockids, $curre
$mgmtnodeid = findManagementNode($compid, $start, $nowfuture);
if($mgmtnodeid == 0)
continue;
+ if($holdcomps && ! getSemaphore($imageid, $imagerevisionid, $mgmtnodeid, $compid, $start, $end, $requestid))
+ continue;
$ret['compid'] = $compid;
$ret['mgmtid'] = $mgmtnodeid;
$ret['loaded'] = 1;
@@ -4316,6 +4686,8 @@ function allocComputer($blockids, $curre
$mgmtnodeid = findManagementNode($compid, $start, $nowfuture);
if($mgmtnodeid == 0)
continue;
+ if($holdcomps && ! getSemaphore($imageid, $imagerevisionid, $mgmtnodeid, $compid, $start, $end, $requestid))
+ continue;
$ret['compid'] = $compid;
$ret['mgmtid'] = $mgmtnodeid;
$ret['loaded'] = 1;
@@ -4326,6 +4698,8 @@ function allocComputer($blockids, $curre
$mgmtnodeid = findManagementNode($compid, $start, $nowfuture);
if($mgmtnodeid == 0)
continue;
+ if($holdcomps && ! getSemaphore($imageid, $imagerevisionid, $mgmtnodeid, $compid, $start, $end, $requestid))
+ continue;
$ret['compid'] = $compid;
$ret['mgmtid'] = $mgmtnodeid;
$ret['loaded'] = 0;
@@ -4337,6 +4711,103 @@ function allocComputer($blockids, $curre
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn getSemaphore($imageid, $imagerevisionid, $mgmtnodeid, $compid, $start,
+/// $end, $requestid=0)
+///
+/// \param $imageid - id of image
+/// \param $imagerevisionid - id of image revision
+/// \param $mgmtnodeid - id of management node
+/// \param $compid - id of computer
+/// \param $start - start of reservation in datetime format
+/// \param $end - end of reservation in datetime format
+/// \param $requestid - (optional) if passed, ignores checking for conflict
+/// in request table for matching id
+///
+/// \return 0 on failure, 1 on success
+///
+/// \brief tries to get a semaphore for the requested computer
+///
+////////////////////////////////////////////////////////////////////////////////
+function getSemaphore($imageid, $imagerevisionid, $mgmtnodeid, $compid, $start,
+ $end, $requestid=0) {
+ global $mysql_link_vcl, $uniqid;
+ $query = "INSERT INTO semaphore "
+ . "SELECT c.id, "
+ . "$imageid, "
+ . "$imagerevisionid, "
+ . "$mgmtnodeid, "
+ . "NOW() + INTERVAL " . SEMTIMEOUT . " SECOND, "
+ . "'$uniqid' "
+ . "FROM computer c "
+ . "LEFT JOIN semaphore s ON (c.id = s.computerid) "
+ . "WHERE c.id = $compid AND "
+ . "(s.expires IS NULL OR s.expires < NOW()) "
+ . "LIMIT 1";
+ doQuery($query);
+ $rc = mysql_affected_rows($mysql_link_vcl);
+
+ # check to see if another process allocated this one
+ if($rc) {
+ $query = "SELECT rq.id "
+ . "FROM request rq, "
+ . "reservation rs "
+ . "WHERE rs.requestid = rq.id AND "
+ . "rs.computerid = $compid AND "
+ . "rq.start < '$end' AND "
+ . "rq.end > '$start' AND "
+ . "rq.stateid NOT IN (1, 5, 12)";
+ if($requestid)
+ $query .= " AND rq.id != $requestid";
+ $qh = doQuery($query);
+ $rc2 = mysql_num_rows($qh);
+ if($rc2) {
+ $query = "DELETE FROM semaphore "
+ . "WHERE computerid = $compid AND "
+ . "procid = '$uniqid'";
+ doQuery($query);
+ return 0;
+ }
+ }
+ return $rc;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn retryGetSemaphore($imageid, $imagerevisionid, $mgmtnodeid, $compid,
+/// $start, $end, $requestid=0, $tries=5, $delay=200000)
+///
+/// \param $imageid - id of image
+/// \param $imagerevisionid - id of image revision
+/// \param $mgmtnodeid - id of management node
+/// \param $compid - id of computer
+/// \param $start - start of reservation in datetime format
+/// \param $end - end of reservation in datetime format
+/// \param $requestid - (optional) if passed, ignores checking for conflict
+/// \param $tries - (optional, default=5) number of attempts to make for getting
+/// a semaphore
+/// \param $delay - (optional, default=200000) microseconds to wait between
+/// tries
+///
+/// \return 0 on failure, 1 on success
+///
+/// \brief makes multiple attempts to get a semaphore for a computer; useful
+/// when needing to do an operation on a specific computer
+///
+////////////////////////////////////////////////////////////////////////////////
+function retryGetSemaphore($imageid, $imagerevisionid, $mgmtnodeid, $compid,
+ $start, $end, $requestid=0, $tries=5, $delay=200000) {
+ for($i = 0; $i < $tries; $i++) {
+ if(getSemaphore($imageid, $imagerevisionid, $mgmtnodeid, $compid, $start, $end, $requestid)) {
+ return 1;
+ }
+ else
+ usleep($delay);
+ }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn getPossibleRecentFailures($userid, $imageid)
///
/// \param $userid - check log data for this user; if $userid = 0, check for
@@ -4373,8 +4844,7 @@ function getPossibleRecentFailures($user
////////////////////////////////////////////////////////////////////////////////
///
-/// \fn getMappedResources($resourcesubid, $resourcetype1,
-/// $resourcetype2)
+/// \fn getMappedResources($resourcesubid, $resourcetype1, $resourcetype2)
///
/// \param $resourcesubid - id of a resource from its table (ie an imageid)
/// \param $resourcetype1 - type of $resourcesubid (name or id)
@@ -4606,7 +5076,7 @@ function getMaxOverlap($userid) {
///
////////////////////////////////////////////////////////////////////////////////
function addRequest($forimaging=0, $revisionid=array()) {
- global $requestInfo, $user;
+ global $requestInfo, $user, $uniqid, $mysql_link_vcl;
$startstamp = unixToDatetime($requestInfo["start"]);
$endstamp = unixToDatetime($requestInfo["end"]);
$now = time();
@@ -4628,18 +5098,6 @@ function addRequest($forimaging=0, $revi
}
$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, "
@@ -4690,24 +5148,51 @@ function addRequest($forimaging=0, $revi
else
$blockdata = array();
- $query = "INSERT INTO reservation "
- . "(requestid, "
- . "computerid, "
- . "imageid, "
- . "imagerevisionid, "
- . "managementnodeid) "
- . "VALUES "
- . "($requestid, "
- . "$computerid, "
- . "$imageid, "
- . "$imagerevisionid, "
- . "$mgmtnodeid)";
- doQuery($query, 133);
addSublogEntry($logid, $imageid, $imagerevisionid, $computerid,
$mgmtnodeid, $fromblock, $blockdata);
}
+
+ $query = "INSERT INTO reservation "
+ . "(requestid, "
+ . "computerid, "
+ . "imageid, "
+ . "imagerevisionid, "
+ . "managementnodeid) "
+ . "SELECT $requestid, "
+ . "computerid, "
+ . "imageid, "
+ . "imagerevisionid, "
+ . "managementnodeid "
+ . "FROM semaphore "
+ . "WHERE expires > NOW() AND "
+ . "procid = '$uniqid'";
+ doQuery($query);
+ $cnt = mysql_affected_rows($mysql_link_vcl);
+ if($cnt == 0) {
+ # reached this point SEMTIMEOUT seconds after getting semaphore, clean up and abort
+ $query = "DELETE FROM request WHERE id = $requestid";
+ doQuery($query);
+ $query = "UPDATE log SET wasavailable = 0 WHERE id = $logid";
+ doQuery($query);
+ $query = "DELETE FROM sublog WHERE logid = $logid";
+ doQuery($query);
+ abort(400);
+ }
+ else {
+ $query = "INSERT INTO changelog "
+ . "(logid, "
+ . "start, "
+ . "end, "
+ . "timestamp) "
+ . "VALUES "
+ . "($logid, "
+ . "'$start', "
+ . "'$endstamp', "
+ . "NOW())";
+ doQuery($query, 136);
+ }
// release semaphore lock
- semUnlock();
+ cleanSemaphore();
return $requestid;
}
@@ -5033,7 +5518,11 @@ function updateRequest($requestid) {
. "managementnodeid = $mgmtnodeid "
. "WHERE requestid = $requestid AND "
. "imageid = $imgid AND "
- . "computerid = $oldCompid";
+ . "computerid = $oldCompid "
+ . "LIMIT 1"; # without this, it can update one row to have the
+ # same computer as another row; then, the later row
+ # could be updated, which would end up setting both
+ # rows to the same computer
doQuery($query, 147);
addChangeLogEntry($logid, NULL, $endstamp, $startstamp, $computerid, NULL,
1);
@@ -5120,12 +5609,17 @@ function deleteRequest($request) {
}
if($request['serverrequest']) {
- $query = "DELETE FROM serverrequest WHERE requestid = {$request['id']}";
- $qh = doQuery($query, 152);
+ $query = "SELECT id FROM serverrequest WHERE requestid = {$request['id']}";
+ $qh = doQuery($query);
+ if($row = mysql_fetch_assoc($qh)) {
+ $query = "DELETE FROM serverrequest WHERE requestid = {$request['id']}";
+ doQuery($query, 152);
+ deleteVariable("fixedIPsr{$row['id']}");
+ }
}
$query = "DELETE FROM request WHERE id = {$request['id']}";
- $qh = doQuery($query, 153);
+ doQuery($query, 153);
$query = "DELETE FROM reservation WHERE requestid = {$request['id']}";
doQuery($query, 154);
@@ -5145,7 +5639,8 @@ function deleteRequest($request) {
/// reservations were found on $compid
///
/// \brief attempts to move reservations off of a $compid - if $compid is not
-/// given, removes all reservations from the computer with the least number
+/// given, removes all reservations from the computer with the least number;
+/// NOTE - cleanSemaphore should be called after this by the calling function
///
////////////////////////////////////////////////////////////////////////////////
function moveReservationsOffComputer($compid=0, $count=0) {
@@ -5198,10 +5693,14 @@ function moveReservationsOffComputer($co
return -1;
$images = getImages();
$allmovable = 1;
+ # TODO eventually, for clusters, there will probably be restrictions on how the computers
+ # relate to each other; at that point, this will need to be updated to make sure the computer
+ # a reservation is reassigned to meets the same restrictions
foreach($resInfo as $res) {
+ // pass forimaging = 1 so that isAvailable only looks at one computer
$rc = isAvailable($images, $res["imageid"], $res['imagerevisionid'],
datetimeToUnix($res["start"]), datetimeToUnix($res["end"]), 0,
- $res["userid"]);
+ 0, $res["userid"], 0, 1);
if($rc < 1) {
$allmovable = 0;
break;
@@ -5211,8 +5710,8 @@ function moveReservationsOffComputer($co
return 0;
foreach($resInfo as $res) {
$rc = isAvailable($images, $res["imageid"], $res['imagerevisionid'],
- datetimeToUnix($res["start"]), datetimeToUnix($res["end"]), 0,
- $res["userid"]);
+ datetimeToUnix($res["start"]), datetimeToUnix($res["end"]), 1,
+ 0, $res["userid"], 0, 1);
if($rc > 0) {
$newcompid = array_shift($requestInfo["computers"]);
# get mgmt node for computer
@@ -5227,7 +5726,8 @@ function moveReservationsOffComputer($co
addChangeLogEntry($res['logid'], NULL, NULL, NULL, $newcompid);
# update sublog entry
$query = "UPDATE sublog "
- . "SET computerid = $newcompid "
+ . "SET computerid = $newcompid, "
+ . "managementnodeid = $mgmtnodeid "
. "WHERE logid = {$res['logid']} AND "
. "computerid = $compid";
doQuery($query, 101);
@@ -5240,23 +5740,71 @@ function moveReservationsOffComputer($co
////////////////////////////////////////////////////////////////////////////////
///
-/// \fn getCompFinalReservationTime($compid)
+/// \fn moveReservationsOffVMs($compid, $sem)
+///
+/// \param $compid - id of host computer from which to move
+/// reservations
+/// \param $sem - (optional) array of data to be used when getting a semaphore
+/// for a VM after reservations have been moved off of it; must include these
+/// keys: imageid, revid, mnid, start (datetime), end (datetime)
+///
+/// \return 0 if failed to move reservations, 1 if succeeded, -1 if no
+/// reservations were found on $compid
+///
+/// \brief attempts to move reservations off of any VMs assigned to a $compid
+/// NOTE - cleanSemaphore should be called after this by the calling function
+///
+////////////////////////////////////////////////////////////////////////////////
+function moveReservationsOffVMs($compid, $sem=0) {
+ if(! is_array($sem)) {
+ $sem = array();
+ $resources = getUserResources(array("imageAdmin", "imageCheckOut"));
+ $tmp = array_keys($resources['image']);
+ $sem['imageid'] = $tmp[0];
+ $sem['revid'] = getProductionRevisionid($sem['imageid']);
+ $tmp = array_keys($resources['managementnode']);
+ $sem['mnid'] = $tmp[0];
+ $sem['start'] = unixToDatetime(time());
+ $sem['end'] = '2038-01-01 00:00:00';
+ }
+ $query = "SELECT vm.id "
+ . "FROM computer vm, "
+ . "vmhost v "
+ . "WHERE v.computerid = $compid AND "
+ . "vm.vmhostid = v.id";
+ $qh = doQuery($query);
+ while($row = mysql_fetch_assoc($qh)) {
+ $rc = moveReservationsOffComputer($row['id']);
+ if($rc != 0)
+ # lock computer so that reservations on other VMs on this host do not get moved to it
+ getSemaphore($sem['imageid'], $sem['revid'], $sem['mnid'], $row['id'], $sem['start'], $sem['end']);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getCompFinalReservationTime($compid, $extraskipstate=0)
///
/// \param $compid - a computer id
+/// \param $extraskipstate - (default=0) id of an additional request state to
+/// ignore; if 0 passed, no additional states are ignored
///
/// \return unix timestamp of last end time of any reservations for $compid
///
/// \brief determines the final end time of all reservations on a computer
///
////////////////////////////////////////////////////////////////////////////////
-function getCompFinalReservationTime($compid) {
+function getCompFinalReservationTime($compid, $extraskipstate=0) {
$end = 0;
+ $skipstates = "1,5,12";
+ if($extraskipstate)
+ $skipstates .= ",$extraskipstate";
$query = "SELECT UNIX_TIMESTAMP(rq.end) as end "
. "FROM request rq, "
. "reservation rs "
. "WHERE rs.requestid = rq.id AND "
. "rs.computerid = $compid AND "
- . "rq.stateid NOT IN (1,5,12) "
+ . "rq.stateid NOT IN ($skipstates) "
. "ORDER BY rq.end DESC "
. "LIMIT 1";
$qh = doQuery($query, 101);
@@ -5279,6 +5827,153 @@ function getCompFinalReservationTime($co
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn getCompFinalVMReservationTime($hostid, $addsemaphores, $notomaintenance)
+///
+/// \param $hostid - computer id of a vm host
+/// \param $addsemaphores - (optional, default = 0) 1 to add semaphores for each
+/// of the VMs
+/// \param $notomaintenance - (optional, default = 0) 1 to ignore any
+/// tomaintenance reservations
+///
+/// \return unix timestamp of last end time of any reservations for VMs on
+/// $hostid; 0 if no reservations; -1 if $addsemaphores = 1 and failed to get
+/// semaphores
+///
+/// \brief determines the final end time of all reservations of all VMs on a
+/// VM host computer
+///
+////////////////////////////////////////////////////////////////////////////////
+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;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getExistingChangeStateStartTime($compid, $stateid)
+///
+/// \param $compid - computer id
+/// \param $stateid - id of state of reservation
+///
+/// \return unix timestamp
+///
+/// \brief gets the start time for the earliest existing reservation for $compid
+/// that has a state of $stateid
+///
+////////////////////////////////////////////////////////////////////////////////
+function getExistingChangeStateStartTime($compid, $stateid) {
+ $query = "SELECT rq.start "
+ . "FROM request rq, "
+ . "reservation rs "
+ . "WHERE rs.requestid = rq.id AND "
+ . "rs.computerid = $compid AND "
+ . "rq.stateid = $stateid AND "
+ . "rq.start > NOW() "
+ . "ORDER BY rq.start "
+ . "LIMIT 1";
+ $qh = doQuery($query);
+ if($row = mysql_fetch_assoc($qh))
+ return datetimeToUnix($row['start']);
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn updateExistingToState($compid, $start, $stateid)
+///
+/// \param $compid - computer id
+/// \param $start - new start time in datetime format
+/// \param $stateid - id of state for existing reservation
+///
+/// \brief updates the start time of an existing reservation for $compid with a
+/// state of $stateid
+///
+////////////////////////////////////////////////////////////////////////////////
+function updateExistingToState($compid, $start, $stateid) {
+ $query = "UPDATE request rq, "
+ . "reservation rs "
+ . "SET rq.start = '$start' "
+ . "WHERE rs.requestid = rq.id AND "
+ . "rq.stateid = $stateid AND "
+ . "rq.start > '$start' AND "
+ . "rs.computerid = $compid";
+ doQuery($query);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn getUserRequests($type, $id)
///
/// \param $type - "normal", "forimaging", or "all"
@@ -5850,6 +6545,50 @@ function getProvisioning() {
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn getProvisioningTypes()
+///
+/// \return array of provisioning types allowed for each computer type of this
+/// form:\n
+/// {[blade] => {[id] => type,\n
+/// [id] => type},\n
+/// [lab] => {[id] => type}\n
+/// [virtualmachine] => {[id] => type,\n
+/// [id] => type}\n
+///
+/// \brief generates an array of provisioning types allowed for each computer
+/// type
+///
+////////////////////////////////////////////////////////////////////////////////
+function getProvisioningTypes() {
+ $query = "SELECT id, prettyname FROM provisioning WHERE name = 'none'";
+ $qh = doQuery($query);
+ $none = mysql_fetch_assoc($qh);
+ $query = "SELECT p.id, "
+ . "p.prettyname, "
+ . "o.name AS `type` "
+ . "FROM provisioning p, "
+ . "OSinstalltype o, "
+ . "provisioningOSinstalltype po "
+ . "WHERE po.provisioningid = p.id AND "
+ . "po.OSinstalltypeid = o.id "
+ . "ORDER BY o.name";
+ $qh = doQuery($query);
+ $types = array('blade' => array($none['id'] => $none['prettyname']),
+ 'lab' => array(),
+ 'virtualmachine' => array());
+ while($row = mysql_fetch_assoc($qh)) {
+ if($row['type'] == 'kickstart' || $row['type'] == 'partimage')
+ $types['blade'][$row['id']] = $row['prettyname'];
+ if($row['type'] == 'none')
+ $types['lab'][$row['id']] = $row['prettyname'];
+ if($row['type'] == 'vbox' || $row['type'] == 'vmware')
+ $types['virtualmachine'][$row['id']] = $row['prettyname'];
+ }
+ return $types;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn getSchedules()
///
/// \return array of schedules where the index are the id from the schedule table,
@@ -5857,6 +6596,7 @@ function getProvisioning() {
/// \b name - name of schedule\n
/// \b ownerid - user id of owner\n
/// \b owner - unity id of owner\n
+/// \b resourceid - id from resource table\n
/// \b times - array of start and end times for the schedule
///
/// \brief gets information for schedules in schedule table
@@ -5943,11 +6683,15 @@ function formatMinOfWeek($min) {
////////////////////////////////////////////////////////////////////////////////
///
-/// \fn getManagementNodes($alive)
+/// \fn getManagementNodes($alive, $includedeleted, $id)
///
/// \param $alive - (optional) if given, only return "alive" nodes, can be
/// either "now" or "future" so we know how recently it must
/// have checked in
+/// \param $includedeleted - (optional, default=0) 1 to include management
+/// nodes with a state of deleted, 0 to leave them out
+/// \param $id - (optional, default is all nodes) specify an id of a management
+/// node to only have data for that node returned
///
/// \return an array of management nodes where eash index is the id from the
/// managementnode table and each element is an array of data about the node
@@ -5957,7 +6701,7 @@ function formatMinOfWeek($min) {
/// if $alive = future, must have checked in within 1 hour
///
////////////////////////////////////////////////////////////////////////////////
-function getManagementNodes($alive="neither") {
+function getManagementNodes($alive="neither", $includedeleted=0, $id=0) {
if($alive == "now")
$lastcheckin = unixToDatetime(time() - 300);
elseif($alive == "future")
@@ -5988,7 +6732,9 @@ function getManagementNodes($alive="neit
. "m.sharedMailBox AS sharedmailbox, "
. "r.id as resourceid, "
. "m.predictivemoduleid, "
- . "mo.prettyname AS predictivemodule "
+ . "mo.prettyname AS predictivemodule, "
+ . "m.availablenetworks, "
+ . "m.NOT_STANDALONE AS federatedauth "
. "FROM user u, "
. "state s, "
. "resource r, "
@@ -6004,6 +6750,10 @@ function getManagementNodes($alive="neit
. "rt.name = 'managementnode' AND "
. "u.affiliationid = a.id AND "
. "m.predictivemoduleid = mo.id";
+ if($id != 0)
+ $query .= " AND m.id = $id";
+ if($includedeleted == 0)
+ $query .= " AND s.name != 'deleted'";
if($alive == "now" || $alive == "future") {
$query .= " AND m.lastcheckin > '$lastcheckin'"
. " AND s.name != 'maintenance'";
@@ -6012,12 +6762,107 @@ function getManagementNodes($alive="neit
$return = array();
while($row = mysql_fetch_assoc($qh)) {
$return[$row["id"]] = $row;
+ $return[$row['id']]['availablenetworks'] = explode(',', $row['availablenetworks']);
+ if($row['state'] == 'deleted')
+ $return[$row['id']]['deleted'] = 1;
+ else
+ $return[$row['id']]['deleted'] = 0;
}
+
+ # Get items from variable table for specific management node id
+ foreach ($return as $mn_id => $value ) {
+ if(array_key_exists("hostname", $value)) {
+ $mn_hostname = $value['hostname'];
+ $timeservers = getVariable('timesource|'.$mn_hostname);
+ if($timeservers == NULL) {
+ $timeservers = getVariable('timesource|global');
+ }
+ $return[$mn_id]['timeservers'] = $timeservers;
+ }
+ }
+
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn getMnsFromImage($imageid)
+///
+/// \param $imageid - id of an image
+///
+/// \return array of management node ids
+///
+/// \brief determines which management nodes can handle an image based on
+/// image group to computer group, then computer group to management node group
+/// mapping
+///
+////////////////////////////////////////////////////////////////////////////////
+function getMnsFromImage($imageid) {
+ $comps = getMappedResources($imageid, 'image', 'computer');
+ if(empty($comps))
+ return array();
+ $inlist = implode(',', $comps);
+ $query = "SELECT DISTINCT rgm.resourcegroupid "
+ . "FROM resourcegroupmembers rgm, "
+ . "resource r, "
+ . "computer c "
+ . "WHERE c.id = r.subid AND "
+ . "r.resourcetypeid = 12 AND "
+ . "r.id = rgm.resourceid AND "
+ . "c.id in ($inlist)";
+ $qh = doQuery($query);
+ $compgroups = array();
+ while($row = mysql_fetch_assoc($qh))
+ $compgroups[] = $row['resourcegroupid'];
+ $mngrps = array();
+ foreach($compgroups as $grpid) {
+ $mngrpset = getResourceMapping('managementnode', 'computer', '', implode(',', $compgroups));
+ foreach($mngrpset as $mngrpid => $compgrpset)
+ $mngrps[$mngrpid] = 1;
+ }
+ $mngrpnames = array();
+ foreach(array_keys($mngrps) as $mnid) {
+ $mngrpnames[] = getResourceGroupName($mnid);
+ }
+ $mns = getResourcesFromGroups($mngrpnames, 'managementnode', 0);
+ $mnids = array();
+ foreach($mns as $mnid => $name)
+ $mnids[$mnid] = 1;
+ return array_keys($mnids);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn checkAvailableNetworks($ip)
+///
+/// \param $ip - public ip address for a reservation
+///
+/// \return array of management node ids that can handle $ip
+///
+/// \brief finds any management nodes that can manage networks containing $ip
+///
+////////////////////////////////////////////////////////////////////////////////
+function checkAvailableNetworks($ip) {
+ $ip = ip2long($ip);
+ $mnids = array();
+ $mns = getManagementNodes();
+ foreach($mns as $mn) {
+ foreach($mn['availablenetworks'] as $net) {
+ if($net == '')
+ continue;
+ list($net, $netmask) = explode('/', $net);
+ $net = ip2long($net);
+ $mask = pow(2, (32 - $netmask)) - 1;
+ $mask = ~ $mask;
+ if(($ip & $mask) == ($net & $mask))
+ $mnids[$mn['id']] = 1;
+ }
+ }
+ return array_keys($mnids);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn getPredictiveModules()
///
/// \return an array of predictive loading modules where the index is the module
@@ -6043,8 +6888,9 @@ function getPredictiveModules() {
////////////////////////////////////////////////////////////////////////////////
///
-/// \fn getTimeSlots($end, $start)
+/// \fn getTimeSlots($compids, $end, $start)
///
+/// \param $compids - array of computer ids
/// \param $end - (optional) end time as unix timestamp
/// \param $start - (optional) start time as unix timestamp
///
@@ -6755,12 +7601,19 @@ function findAvailableTimes($start, $end
$query = "SELECT c.id AS compid "
. "FROM computer c, "
. "image i, "
- . "state s "
+ . "state s, "
+ . "provisioningOSinstalltype poi, "
+ . "OSinstalltype oi, "
+ . "OS o "
. "WHERE c.stateid = s.id AND "
. "i.id = $imageid AND "
. "s.name NOT IN ($nowignorestates) AND "
. "c.platformid = $platformid AND "
. "c.scheduleid IN ($schedules) AND "
+ . "i.OSid = o.id AND "
+ . "o.installtype = oi.name AND "
+ . "oi.id = poi.OSinstalltypeid AND "
+ . "poi.provisioningid = c.provisioningid AND "
. "c.RAM >= i.minram AND "
. "c.procnumber >= i.minprocnumber AND "
. "c.procspeed >= i.minprocspeed AND "
@@ -6774,9 +7627,9 @@ function findAvailableTimes($start, $end
$query .= "DATE_ADD(rq.end, INTERVAL 15 MINUTE) >= '$startdt' AND "
. "rs.computerid IN ($incompids)) AND "
. "c.id IN ($incompids) "
- . "ORDER BY (c.procspeed * c.procnumber) DESC, "
- . "RAM DESC, "
- . "network DESC";
+ . "ORDER BY RAM, "
+ . "(c.procspeed * c.procnumber), "
+ . "network";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$row['duration'] = $reqduration;
@@ -6799,7 +7652,10 @@ function findAvailableTimes($start, $end
. "reservation rs2, "
. "image i, "
. "state s, "
- . "computer c "
+ . "computer c, "
+ . "provisioningOSinstalltype poi, "
+ . "OSinstalltype oi, "
+ . "OS o "
. "WHERE rq1.id = rs1.requestid AND "
. "rs2.requestid = rq2.id AND "
. "rq1.id != rq2.id AND "
@@ -6811,6 +7667,10 @@ function findAvailableTimes($start, $end
. "c.id = rs1.computerid AND "
. "c.platformid = $platformid AND "
. "c.scheduleid IN ($schedules) AND "
+ . "i.OSid = o.id AND "
+ . "o.installtype = oi.name AND "
+ . "oi.id = poi.OSinstalltypeid AND "
+ . "poi.provisioningid = c.provisioningid AND "
. "c.RAM >= i.minram AND "
. "c.procnumber >= i.minprocnumber AND "
. "c.procspeed >= i.minprocspeed AND "
@@ -6857,7 +7717,10 @@ function findAvailableTimes($start, $end
. "reservation rs, "
. "image i, "
. "state s, "
- . "computer c "
+ . "computer c, "
+ . "provisioningOSinstalltype poi, "
+ . "OSinstalltype oi, "
+ . "OS o "
. "WHERE rs.requestid = rq.id AND "
. "(rq.start > '$startdt' OR "
. "(DATE_ADD(rq.end, INTERVAL 15 MINUTE) > '$startdt' AND rq.start <= '$startdt')) AND "
@@ -6866,6 +7729,10 @@ function findAvailableTimes($start, $end
. "c.id = rs.computerid AND "
. "c.platformid = $platformid AND "
. "c.scheduleid IN ($schedules) AND "
+ . "i.OSid = o.id AND "
+ . "o.installtype = oi.name AND "
+ . "oi.id = poi.OSinstalltypeid AND "
+ . "poi.provisioningid = c.provisioningid AND "
. "c.RAM >= i.minram AND "
. "c.procnumber >= i.minprocnumber AND "
. "c.procspeed >= i.minprocspeed AND "
@@ -6904,7 +7771,10 @@ function findAvailableTimes($start, $end
. "reservation rs, "
. "image i, "
. "state s, "
- . "computer c "
+ . "computer c, "
+ . "provisioningOSinstalltype poi, "
+ . "OSinstalltype oi, "
+ . "OS o "
. "WHERE rs.requestid = rq.id AND "
. "(rq.start > '$startdt' OR "
. "(DATE_ADD(rq.end, INTERVAL 15 MINUTE) > '$startdt' AND rq.start <= '$startdt')) AND "
@@ -6913,10 +7783,15 @@ function findAvailableTimes($start, $end
. "c.id = rs.computerid AND "
. "c.platformid = $platformid AND "
. "c.scheduleid IN ($schedules) AND "
+ . "i.OSid = o.id AND "
+ . "o.installtype = oi.name AND "
+ . "oi.id = poi.OSinstalltypeid AND "
+ . "poi.provisioningid = c.provisioningid 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.stateid = s.id AND "
. "s.name NOT IN ($ignorestates) AND ";
if($reqid != '')
@@ -7249,7 +8124,7 @@ function getComputers($sort=0, $included
. "c.platformid AS platformid, "
. "sc.name AS schedule, "
. "c.scheduleid AS scheduleid, "
- . "cur.name AS currentimg, "
+ . "cur.prettyname AS currentimg, "
. "c.currentimageid AS currentimgid, "
. "c.imagerevisionid, "
. "next.name AS nextimg, "
@@ -7269,6 +8144,7 @@ function getComputers($sort=0, $included
. "c.notes, "
. "c.vmhostid, "
. "c2.hostname AS vmhost, "
+ . "c2.id AS vmhostcomputerid, "
. "c.location, "
. "c.provisioningid, "
. "pr.prettyname AS provisioning, "
@@ -7852,7 +8728,7 @@ function isImageBlockTimeActive($imageid
/// \param $selectedid - (optional) index of $dataArr to be initially selected;
/// use -1 for nothing to be selected
/// \param $skip - (optional) this is used if the array from getImages is passed
-/// as $dataArr so we know to skip index 4 since it is the noimage element
+/// as $dataArr so we know to skip the 'No Image" element
/// \param $multiple - (optional) use this to print select input with the
/// multiple tag set
/// \param $domid - (optional) use this to pass in the javascript id to be used
@@ -7867,6 +8743,66 @@ function isImageBlockTimeActive($imageid
////////////////////////////////////////////////////////////////////////////////
function printSelectInput($name, $dataArr, $selectedid=-1, $skip=0, $multiple=0,
$domid="", $extra="") {
+ print selectInputHTML($name, $dataArr, $domid, $extra, $selectedid, $skip,
+ $multiple);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn selectInputAutoDijitHTML($name, $dataArr, $domid='', $extra='',
+/// $selectedid=-1) {
+///
+/// \param $name - name of input element
+/// \param $dataArr - array containing options
+/// \param $domid - (optional) use this to pass in the javascript id to be used
+/// for the select object
+/// \param $extra - (optional) any extra attributes that need to be set
+/// \param $selectedid - (optional) index of $dataArr to be initially selected;
+/// use -1 for nothing to be selected
+///
+/// \return html
+///
+/// \brief wrapper for calling selectInputHTML with the resulting element
+/// being a dijit.form.Select if number of items is <= 10 and being a
+/// dijit.form.FilteringSelect if number of items is > 10
+///
+////////////////////////////////////////////////////////////////////////////////
+function selectInputAutoDijitHTML($name, $dataArr, $domid='', $extra='',
+ $selectedid=-1) {
+ if(count($dataArr) > 10 &&
+ USEFILTERINGSELECT && count($dataArr) < FILTERINGSELECTTHRESHOLD)
+ $type = 'dojoType="dijit.form.FilteringSelect" queryExpr="*${0}*"';
+ else
+ $type = 'dojoType="dijit.form.Select" maxHeight="250"';
+ return selectInputHTML($name, $dataArr, $domid, "$type $extra", $selectedid);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn selectInputHTML($name, $dataArr, $domid, $extra, $selectedid, $skip,
+/// $multiple)
+///
+/// \param $name - name of input element
+/// \param $dataArr - array containing options
+/// \param $domid - (optional) use this to pass in the javascript id to be used
+/// for the select object
+/// \param $extra - (optional) any extra attributes that need to be set
+/// \param $selectedid - (optional) index of $dataArr to be initially selected;
+/// use -1 for nothing to be selected
+/// \param $skip - (optional) this is used if the array from getImages is passed
+/// as $dataArr so we know to skip the 'No Image" element
+/// \param $multiple - (optional) use this to print select input with the
+/// multiple tag set
+///
+/// \brief generates HTML for select input
+/// it is assumed that if $selectedid is left off, we assume $dataArr has no
+/// index '-1'\n
+/// each OPTION's value is the index of that element of the array
+///
+////////////////////////////////////////////////////////////////////////////////
+function selectInputHTML($name, $dataArr, $domid="", $extra="", $selectedid=-1,
+ $skip=0, $multiple=0) {
+ $h = '';
if(! empty($domid))
$domid = "id=\"$domid\"";
if($multiple)
@@ -7874,52 +8810,218 @@ function printSelectInput($name, $dataAr
else
$multiple = "";
if($name != '')
- print " <select name=$name $multiple $domid $extra>\n";
+ $h .= " <select name=$name $multiple $domid $extra>\n";
else
- print " <select $multiple $domid $extra>\n";
+ $h .= " <select $multiple $domid $extra>\n";
foreach(array_keys($dataArr) as $id) {
- if(($skip && $id == 4) || ($dataArr[$id] != 0 && empty($dataArr[$id])))
+ if(($dataArr[$id] != 0 && empty($dataArr[$id])))
continue;
if($id == $selectedid)
- print " <option value=\"$id\" selected=\"selected\">";
[... 2112 lines stripped ...]