\n";
if($item['allowreservations']) {
print _("You will be able to access your reserved machines during ");
print _("this maintenance. However, you will not be able to access ");
print _("information on how to connect to them. \n");
}
else {
print _("You will not be able to access any of your reservations ");
print _("during this maintenance. \n");
}
print "
\n";
$tmp = array_values($user['groups']);
if(count($tmp) == 1 && $tmp[0] == 'nodemo') {
print "Your account is a demo account that has expired. ";
print "You cannot make any more reservations. Please contact " . HELPEMAIL . " if you need ";
print "further access to VCL. \n";
return;
}
$requests = getUserRequests("all", $user["id"]);
if($num = count($requests)) {
if($num == 1) {
print _("You currently have ") . "$num" . _(" reservation. \n");
}
else {
print _("You currently have ") . "$num" . _(" reservations. \n");
}
}
else {
print _("You do not have any current reservations. \n");
}
print _("Please make a selection from the menu to continue. \n");
}
else {
print "Click the Log in to VCL button at the top right part of ";
print "the page to start using the VCL system \n";
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn abort($errcode, $query)
///
/// \param $errcode - error code
/// \param $query - a myql query
///
/// \brief prints out error message(s), closes db connection, prints footer
/// and exits
///
////////////////////////////////////////////////////////////////////////////////
function abort($errcode, $query="") {
global $mysql_link_vcl, $mysql_link_acct, $ERRORS, $user, $mode;
global $ENABLE_ITECSAUTH, $requestInfo;
if($mode == 'xmlrpccall')
xmlRPCabort($errcode, $query);
if(ONLINEDEBUG && checkUserHasPerm('View Debug Information')) {
if($errcode >= 100 && $errcode < 400) {
print "" . mysql_error($mysql_link_vcl) . " \n";
if($ENABLE_ITECSAUTH)
print "" . mysql_error($mysql_link_acct) . " \n";
print "$query \n";
}
print "ERROR($errcode): " . $ERRORS["$errcode"] . " \n";
print "
\n";
print getBacktraceString(FALSE);
print "
\n";
}
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";
if(is_array($user) && array_key_exists('unityid', $user))
$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";
}
if($errcode == 40) {
$message .= "One of the following computers didn't get a mgmt node:\n";
foreach($requestInfo["images"] as $key => $imageid) {
$message .= "imageid: $imageid\n";
$message .= "compid: {$requestInfo['computers'][$key]}\n";
}
}
$message .= getBacktraceString(FALSE);
$mailParams = "-f" . ENVELOPESENDER;
mail(ERROREMAIL, "Error with VCL pages ($errcode)", $message, '', $mailParams);
print _("An error has occurred. If this problem persists, please email ");
print "";
print HELPEMAIL . " " . _("for further assistance. Please include the ");
print _("steps you took that led up to this problem in your email message.");
}
dbDisconnect();
printHTMLFooter();
// release semaphore lock
semUnlock();
exit;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn errorrpt()
///
/// \brief takes input from ajax call and emails error to ERROREMAIL
///
////////////////////////////////////////////////////////////////////////////////
function errorrpt() {
$mailParams = "-f" . ENVELOPESENDER;
mail(ERROREMAIL, "Error with VCL pages (ajax sent html wrappers)", $_POST['data'], '', $mailParams);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn validateUserid($loginid)
///
/// \param $loginid - a submitted loginid
///
/// \return 0 if the loginid is not found in one of the authentications
/// systems, 1 if it is
///
/// \brief checks to see if $loginid is found in one of the authentication
/// systems
///
////////////////////////////////////////////////////////////////////////////////
function validateUserid($loginid) {
global $affilValFuncArgs, $affilValFunc;
if(empty($loginid))
return 0;
$rc = getAffilidAndLogin($loginid, $affilid);
if($rc == -1)
return 0;
if(empty($affilid))
return 0;
$escloginid = mysql_real_escape_string($loginid);
$query = "SELECT id "
. "FROM user "
. "WHERE unityid = '$escloginid' AND "
. "affiliationid = $affilid";
$qh = doQuery($query, 101);
if(mysql_num_rows($qh))
return 1;
$valfunc = $affilValFunc[$affilid];
if(array_key_exists($affilid, $affilValFuncArgs))
return $valfunc($affilValFuncArgs[$affilid], $loginid);
else
return $valfunc($loginid);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn AJvalidateUserid()
///
/// \brief checks to see if submitted userid is valid
///
////////////////////////////////////////////////////////////////////////////////
function AJvalidateUserid() {
$user = processInputVar('user', ARG_STRING);
if(validateUserid($user))
sendJSON(array('status' => 'valid'));
else
sendJSON(array('status' => 'invalid'));
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getAffilidAndLogin(&$login, &$affilid)
///
/// \param $login - login for user, may include \@affiliation
/// \param $affilid - variable in which to stick the affiliation id
///
/// \return 1 if $affilid set by a registered function, 0 if set to default,
/// -1 if @affiliation was part of $login but did not contain a known
/// affiliation
///
/// \brief tries registered affiliation lookup functions to determine the
/// affiliation id of the user; if it finds it, sticks the affiliationid in
/// $affilid and sets $login to not include \@affiliation if it did
///
////////////////////////////////////////////////////////////////////////////////
function getAffilidAndLogin(&$login, &$affilid) {
global $findAffilFuncs;
foreach($findAffilFuncs as $func) {
$rc = $func($login, $affilid);
if($rc)
return $rc;
}
$affilid = DEFAULT_AFFILID;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn mysql_connect_plus($host, $user, $pwd)
///
/// \param $host - mysql host
/// \param $user - userid to use for connection
/// \param $pwd - password to use for connection
///
/// \return mysql resource identifier, 0 if failure to connect
///
/// \brief opens a socket connection to $host, if it is not established in 5
/// seconds, returns an error, otherwise, opens a connection to the database
/// and returns the identifier
///
////////////////////////////////////////////////////////////////////////////////
function mysql_connect_plus($host, $user, $pwd) {
$timeout = 5; /* timeout in seconds */
if($fp = @fsockopen($host, 3306, $errno, $errstr, $timeout)) {
fclose($fp);
return $link = mysql_connect($host, $user, $pwd);
} else {
#print "ERROR: socket timeout \n";
return 0;
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn dbConnect()
///
/// \brief opens connections to database, the resource identifiers are\n
/// \b $mysql_link_vcl - for vcl database\n
/// \b $mysql_link_acct - for accounts database\n
///
////////////////////////////////////////////////////////////////////////////////
function dbConnect() {
global $vclhost, $vcldb, $vclusername, $vclpassword, $mysql_link_vcl;
global $accthost, $acctusername, $acctpassword, $mysql_link_acct;
global $ENABLE_ITECSAUTH;
if($ENABLE_ITECSAUTH) {
// open a connection to mysql server for accounts
if($mysql_link_acct = mysql_connect_plus($accthost, $acctusername, $acctpassword))
mysql_select_db("accounts", $mysql_link_acct);
else
$ENABLE_ITECSAUTH = 0;
}
// open a connection to mysql server for vcl
if(! $mysql_link_vcl = mysql_connect_plus($vclhost, $vclusername, $vclpassword)) {
die("Error connecting to $vclhost. \n");
}
// select the vcl database
mysql_select_db($vcldb, $mysql_link_vcl) or abort(104);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn dbDisconnect()
///
/// \brief closes connections to the database
///
////////////////////////////////////////////////////////////////////////////////
function dbDisconnect() {
global $mysql_link_vcl, $mysql_link_acct, $ENABLE_ITECSAUTH;
mysql_close($mysql_link_vcl);
if($ENABLE_ITECSAUTH)
mysql_close($mysql_link_acct);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn doQuery($query, $errcode, $db, $nolog)
///
/// \param $query - SQL statement
/// \param $errcode - error code
/// \param $db - (optional, defaul=vcl), database to query against
/// \param $nolog - (optional, defaul=0), don't log to queryLog table
///
/// \return $qh - query handle
///
/// \brief performs the query and returns $qh or aborts on error
///
////////////////////////////////////////////////////////////////////////////////
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)) {
$logquery = str_replace("'", "\'", $query);
$logquery = str_replace('"', '\"', $logquery);
if(isset($user['id']))
$id = $user['id'];
else
$id = 0;
$q = "INSERT INTO querylog "
. "(userid, "
. "timestamp, "
. "mode, "
. "query) "
. "VALUES "
. "($id, "
. "NOW(), "
. "'$mode', "
. "'$logquery')";
mysql_query($q, $mysql_link_vcl);
}
$qh = mysql_query($query, $mysql_link_vcl) or abort($errcode, $query);
}
elseif($db == "accounts") {
if($ENABLE_ITECSAUTH)
$qh = mysql_query($query, $mysql_link_acct) or abort($errcode, $query);
else
$qh = NULL;
}
return $qh;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn dbLastInsertID()
///
/// \return last insert id for $mysql_link_vcl
///
/// \brief calls mysql_insert_id for $mysql_link_vcl
///
////////////////////////////////////////////////////////////////////////////////
function dbLastInsertID() {
global $mysql_link_vcl;
return mysql_insert_id($mysql_link_vcl);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getOSList()
///
/// \return $oslist - array of OSs
///
/// \brief builds an array of OSs
///
////////////////////////////////////////////////////////////////////////////////
function getOSList() {
$qh = doQuery("SELECT id, name, prettyname, type FROM OS", "115");
$oslist = array();
while($row = mysql_fetch_assoc($qh))
$oslist[$row['id']] = $row;
return $oslist;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getImages($includedeleted=0, $imageid=0)
///
/// \param $includedeleted = (optional) 1 to show deleted images, 0 not to
/// \param $imageid = (optional) only get data for this image, defaults
/// to getting data for all images
///
/// \return $imagelist - array of images with the following elements:\n
/// \b name - name of image\n
/// \b prettyname - pretty name of image\n
/// \b ownerid - userid of owner\n
/// \b owner - unity id of owner\n
/// \b platformid - platformid for the platform the image if for\n
/// \b platform - platform the image is for\n
/// \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 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
/// \b minnetwork - minimum speed of network needed for image\n
/// \b maxconcurrent - maximum concurrent usage of this iamge\n
/// \b reloadtime - time in minutes for image to be loaded\n
/// \b deleted - 'yes' or 'no'; whether or not this image has been deleted\n
/// \b test - 0 or 1; whether or not there is a test version of this image\n
/// \b resourceid - image's resource id from the resource table\n
/// \b lastupdate - datetime image was last updated\n
/// \b forcheckout - 0 or 1; whether or not the image is allowed to be directly
/// checked out\n
/// \b maxinitialtime - maximum time (in minutes) to be shown when requesting
/// a reservation that the image can reserved for\n
/// \b imagemetaid - NULL or corresponding id from imagemeta table and the
/// following additional information:\n
/// \b checkuser - whether or not vcld should check for a logged in user\n
/// \b sysprep - whether or not to use sysprep on creation of the image\n
/// \b connectmethods - array of enabled connect methods\n
/// \b subimages - an array of subimages to be loaded along with selected
/// image\n
/// \b imagerevision - an array of revision info about the image, it has these
/// keys: id, revision, userid, user, datecreated, prettydate, production,
/// imagename
///
/// \brief generates an array of images
///
////////////////////////////////////////////////////////////////////////////////
function getImages($includedeleted=0, $imageid=0) {
# key in $imagelist is for $includedeleted
static $imagelist = array(0 => array(), 1 => array());
if(! empty($imagelist[$includedeleted])) {
if($imageid == 0)
return $imagelist[$includedeleted];
else
return array($imageid => $imagelist[$includedeleted][$imageid]);
}
# get all image meta data
$allmetadata = array();
$query = "SELECT checkuser, "
. "rootaccess, "
. "subimages, "
. "sysprep, "
. "id "
. "FROM imagemeta";
$qh = doQuery($query);
while($row = mysql_fetch_assoc($qh))
$allmetadata[$row['id']] = $row;
# get all image revision data
$allrevisiondata = array();
$query = "SELECT i.id, "
. "i.imageid, "
. "i.revision, "
. "i.userid, "
. "CONCAT(u.unityid, '@', a.name) AS user, "
. "i.datecreated, "
. "DATE_FORMAT(i.datecreated, '%c/%d/%y %l:%i %p') AS prettydate, "
. "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";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$id = $row['imageid'];
unset($row['imageid']);
if(! array_key_exists($id, $allrevisiondata))
$allrevisiondata[$id] = array();
$allrevisiondata[$id][$row['id']] = $row;
}
$query = "SELECT i.id AS id,"
. "i.name AS name, "
. "i.prettyname AS prettyname, "
. "i.ownerid AS ownerid, "
. "CONCAT(u.unityid, '@', a.name) AS owner, "
. "i.platformid AS platformid, "
. "p.name AS platform, "
. "i.OSid AS osid, "
. "o.name AS os, "
. "o.installtype, "
. "i.minram AS minram, "
. "i.minprocnumber AS minprocnumber, "
. "i.minprocspeed AS minprocspeed, "
. "i.minnetwork AS minnetwork, "
. "i.maxconcurrent AS maxconcurrent, "
. "i.reloadtime AS reloadtime, "
. "i.deleted AS deleted, "
. "i.test AS test, "
. "r.id AS resourceid, "
. "i.lastupdate, "
. "i.forcheckout, "
. "i.maxinitialtime, "
. "i.imagemetaid "
. "FROM image i, "
. "platform p, "
. "OS o, "
. "resource r, "
. "resourcetype t, "
. "user u, "
. "affiliation a "
. "WHERE i.platformid = p.id AND "
. "r.resourcetypeid = t.id AND "
. "t.name = 'image' AND "
. "r.subid = i.id AND "
. "i.OSid = o.id AND "
. "i.ownerid = u.id AND "
. "u.affiliationid = a.id ";
if(! $includedeleted)
$query .= "AND i.deleted = 0 ";
$query .= "ORDER BY i.prettyname";
$qh = doQuery($query, 120);
while($row = mysql_fetch_assoc($qh)) {
$imagelist[$includedeleted][$row["id"]] = $row;
if($row["imagemetaid"] != NULL) {
if(array_key_exists($row['imagemetaid'], $allmetadata)) {
$metaid = $row['imagemetaid'];
$imagelist[$includedeleted][$row['id']]['checkuser'] = $allmetadata[$metaid]['checkuser'];
$imagelist[$includedeleted][$row['id']]['rootaccess'] = $allmetadata[$metaid]['rootaccess'];
$imagelist[$includedeleted][$row['id']]['sysprep'] = $allmetadata[$metaid]['sysprep'];
$imagelist[$includedeleted][$row["id"]]["subimages"] = array();
if($allmetadata[$metaid]["subimages"]) {
$query2 = "SELECT imageid "
. "FROM subimages "
. "WHERE imagemetaid = $metaid";
$qh2 = doQuery($query2, 101);
while($row2 = mysql_fetch_assoc($qh2))
$imagelist[$includedeleted][$row["id"]]["subimages"][] = $row2["imageid"];
}
}
else
$row["imagemetaid"] = NULL;
}
if(array_key_exists($row['id'], $allrevisiondata))
$imagelist[$includedeleted][$row['id']]['imagerevision'] = $allrevisiondata[$row['id']];
$imagelist[$includedeleted][$row['id']]['connectmethods'] = getImageConnectMethods($row['id']);
}
if($imageid != 0)
return array($imageid => $imagelist[$includedeleted][$imageid]);
return $imagelist[$includedeleted];
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getImageRevisions($imageid, $incdeleted)
///
/// \param $imageid - id of an image
/// \param $incdeleted - (optional, defaults to 0) 1 to include deleted images
///
/// \return an array where each key is the id of the image revision and each
/// element has these values:\n
/// \b id - id of revision\n
/// \b revision - revision number\n
/// \b creatorid - user id of person that created the revision\n
/// \b creator - user@affiliation\n
/// \b datecreated - datetime of when revision was created\n
/// \b deleted - 1 if deleted, 0 if not\n
/// \b production - 1 if production revision, 0 if not\n
/// \b comments - comments about the revision\n
/// \b imagename - name for files related to revision
///
/// \brief gets image revision data related to $imageid
///
////////////////////////////////////////////////////////////////////////////////
function getImageRevisions($imageid, $incdeleted=0) {
$query = "SELECT i.id, "
. "i.revision, "
. "i.userid AS creatorid, "
. "CONCAT(u.unityid, '@', a.name) AS creator, "
. "i.datecreated, "
. "i.deleted, "
. "i.production, "
. "i.comments, "
. "i.imagename "
. "FROM imagerevision i, "
. "user u, "
. "affiliation a "
. "WHERE i.userid = u.id "
. "AND u.affiliationid = a.id "
. "AND i.imageid = $imageid";
if(! $incdeleted)
$query .= " AND i.deleted = 0";
$query .= " ORDER BY revision";
$qh = doQuery($query, 101);
$return = array();
while($row = mysql_fetch_assoc($qh))
$return[$row['id']] = $row;
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getImageNotes($imageid)
///
/// \param $imageid - id of an image
/// \param $revisionid - image revision id
///
/// \return an array with these keys:\n
/// \b description - description of image\n
/// \b usage - notes on using the image
///
/// \brief gets data from the imageinfo table for $imageid and $revisionid
///
////////////////////////////////////////////////////////////////////////////////
function getImageNotes($imageid) {
if(empty($imageid))
$imageid = 0;
$query = "SELECT description, "
. "`usage` "
. "FROM image "
. "WHERE id = $imageid";
$qh = doQuery($query, 101);
if($row = mysql_fetch_assoc($qh))
return $row;
else
return array('description' => '', 'usage' => '');
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getImageConnectMethods($imageid, $revisionid)
///
/// \param $imageid - id of an image
/// \param $revisionid - (optional, default=0) revision id of image
///
/// \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
///
/// \brief builds an array of connect methods enabled for the image
///
////////////////////////////////////////////////////////////////////////////////
function getImageConnectMethods($imageid, $revisionid=0) {
$key = getKey(array('getImageConnectMethods', $imageid, $revisionid));
if(array_key_exists($key, $_SESSION['usersessiondata']))
return $_SESSION['usersessiondata'][$key];
if($revisionid == 0)
$revisionid = getProductionRevisionid($imageid);
if($revisionid == '') {
$_SESSION['usersessiondata'][$key] = array();
return array();
}
static $allmethods = array();
if(empty($allmethods)) {
$query = "SELECT DISTINCT c.id, "
. "c.description, "
. "cm.disabled, "
. "i.id AS imageid, "
. "cm.imagerevisionid AS cmimagerevisionid, "
. "ir.id AS imagerevisionid, "
. "ir.imagename "
. "FROM image i "
. "LEFT JOIN OS o ON (o.id = i.OSid) "
. "LEFT JOIN OStype ot ON (ot.name = o.type) "
. "LEFT JOIN imagerevision ir ON (ir.imageid = i.id) "
. "LEFT JOIN connectmethodmap cm ON (cm.OStypeid = ot.id OR "
. "cm.OSid = o.id OR "
. "cm.imagerevisionid = ir.id) "
. "LEFT JOIN connectmethod c ON (cm.connectmethodid = c.id) "
. "WHERE cm.autoprovisioned IS NULL "
. "ORDER BY i.id, "
. "cm.disabled, "
. "c.description";
$qh = doQuery($query);
while($row = mysql_fetch_assoc($qh)) {
$_imageid = $row['imageid'];
$_revid = $row['imagerevisionid'];
unset($row['imageid']);
unset($row['imagerevisionid']);
if(! array_key_exists($_imageid, $allmethods))
$allmethods[$_imageid] = array();
if(! array_key_exists($_revid, $allmethods[$_imageid]))
$allmethods[$_imageid][$_revid] = array();
$allmethods[$_imageid][$_revid][] = $row;
}
}
if(! array_key_exists($imageid, $allmethods) ||
! array_key_exists($revisionid, $allmethods[$imageid])) {
$_SESSION['usersessiondata'][$key] = array();
return array();
}
$methods = array();
foreach($allmethods[$imageid][$revisionid] as $data) {
if($data['disabled']) {
if(array_key_exists($data['id'], $methods))
unset($methods[$data['id']]);
}
else
$methods[$data['id']] = $data['description'];
}
$_SESSION['usersessiondata'][$key] = $methods;
return $methods;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getImageConnectMethodTexts($imageid, $revisionid)
///
/// \param $imageid - id of an image
/// \param $revisionid - (optional, default=0) revision id of image
///
/// \return an array of connect method texts enabled for specified image where
/// the key is the id of the connect method and the value is the connecttext
///
/// \brief builds an array of connect methods enabled for the image
///
////////////////////////////////////////////////////////////////////////////////
function getImageConnectMethodTexts($imageid, $revisionid=0) {
global $locale;
$descfield = 'description';
$textfield = 'connecttext';
if(! preg_match('/^en/', $locale)) {
$query = "DESC connectmethod";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
if($row['Field'] == "description_$locale")
$descfield = "description_$locale";
if($row['Field'] == "connecttext_$locale")
$textfield = "connecttext_$locale";
}
}
if($revisionid == 0)
$revisionid = getProductionRevisionid($imageid);
$query = "SELECT c.id, "
. "c.`$descfield` AS description, "
. "c.`$textfield` AS connecttext, "
. "cm.disabled "
. "FROM connectmethod c, "
. "connectmethodmap cm, "
. "image i "
. "LEFT JOIN OS o ON (o.id = i.OSid) "
. "LEFT JOIN OStype ot ON (ot.name = o.type) "
. "WHERE i.id = $imageid AND "
. "cm.connectmethodid = c.id AND "
. "cm.autoprovisioned IS NULL AND "
. "(cm.OStypeid = ot.id OR "
. "cm.OSid = o.id OR "
. "cm.imagerevisionid = $revisionid) "
. "ORDER BY cm.disabled, "
. "c.`$descfield`";
$methods = array();
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
if($row['disabled']) {
if(array_key_exists($row['id'], $methods))
unset($methods[$row['id']]);
}
else
$methods[$row['id']] = array('description' => $row['description'],
'connecttext' => $row['connecttext']);
}
return $methods;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getImageTypes()
///
/// \return array of image types where each key is the id and each value is the
/// name
///
/// \brief builds an array of image types from the imagetype table
///
////////////////////////////////////////////////////////////////////////////////
function getImageTypes() {
$query = "SELECT id, name FROM imagetype ORDER BY name";
$qh = doQuery($query);
$data = array();
while($row = mysql_fetch_assoc($qh))
$data[$row['id']] = $row['name'];
return $data;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn checkClearImageMeta($imagemetaid, $imageid, $ignorefield)
///
/// \param $imagemetaid - id from imagemeta table
/// \param $imageid - id from image table
/// \param $ignorefield - (optional, default='') field to ignore being different
/// from default
///
/// \return 0 if imagemeta entry was not deleted, 1 if it was
///
/// \brief checks to see if all values of the imagemeta table are defaults, and
/// if so, deletes the entry and sets imagemetaid to NULL in image table
///
////////////////////////////////////////////////////////////////////////////////
function checkClearImageMeta($imagemetaid, $imageid, $ignorefield='') {
# get defaults for imagemeta table
$query = "DESC imagemeta";
$qh = doQuery($query, 101);
$defaults = array();
while($row = mysql_fetch_assoc($qh))
$defaults[$row['Field']] = $row['Default'];
# get imagemeta data
$query = "SELECT * FROM imagemeta WHERE id = $imagemetaid";
$qh = doQuery($query, 101);
$row = mysql_fetch_assoc($qh);
$alldefaults = 1;
foreach($row as $field => $val) {
if($field == 'id' || $field == $ignorefield)
continue;
if($defaults[$field] != $val) {
$alldefaults = 0;
break;
}
}
// if all default values, delete imagemeta entry
if($alldefaults) {
$query = "DELETE FROM imagemeta WHERE id = $imagemetaid";
doQuery($query, 101);
$query = "UPDATE image SET imagemetaid = NULL WHERE id = $imageid";
doQuery($query, 101);
return 1;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getProductionRevisionid($imageid)
///
/// \param $imageid
///
/// \return the production revision id for $imageid
///
/// \brief gets the production revision id for $imageid from the imagerevision
/// table
///
////////////////////////////////////////////////////////////////////////////////
function getProductionRevisionid($imageid) {
static $alldata = array();
if(! empty($alldata))
if(array_key_exists($imageid, $alldata))
return $alldata[$imageid];
else
return '';
$query = "SELECT id, "
. "imageid "
. "FROM imagerevision "
. "WHERE production = 1";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh))
$alldata[$row['imageid']] = $row['id'];
return $alldata[$imageid];
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn removeNoCheckout($images)
///
/// \param $images - an array of images
///
/// \return an array of images with the images that have forcheckout == 0
/// removed
///
/// \brief removes any images in $images that have forcheckout == 0
///
////////////////////////////////////////////////////////////////////////////////
function removeNoCheckout($images) {
$allimages = getImages();
foreach(array_keys($images) as $id) {
if(array_key_exists($id, $allimages) && ! $allimages[$id]["forcheckout"])
unset($images[$id]);
}
return $images;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserResources($userprivs, $resourceprivs, $onlygroups,
/// $includedeleted, $userid)
///
/// \param $userprivs - array of privileges to look for (such as
/// imageAdmin, imageCheckOut, etc) - this is an OR list; don't include 'block' or 'cascade'
/// \param $resourceprivs - array of privileges to look for (such as
/// available, administer, manageGroup) - this is an OR list; don't include 'block' or 'cascade'
/// \param $onlygroups - (optional) if 1, return the resource groups instead
/// of the resources
/// \param $includedeleted - (optional) included deleted resources if 1,
/// don't if 0
/// \param $userid - (optional) id from the user table, if not given, use the
/// id of the currently logged in user
///
/// \return an array of 2 arrays where the first indexes are resource types
/// and each one's arrays are a list of resources available to the user where
/// the index of each item is the id and the value is the name of the
/// resource\n
/// if $onlygroups == 1:\n
/// {[computer] => {[groupid] => "groupname",\n
/// [groupid] => "groupname"},\n
/// [image] => {[groupid] => "groupname",\n
/// [groupid] => "groupname"},\n
/// ...}\n
/// if $onlygroups == 0:\n
/// {[computer] => {[compid] => "hostname",\n
/// [compid] => "hosename"},\n
/// [image] => {[imageid] => "prettyname",\n
/// [imageid] => "prettyname"},\n
/// ...}
///
/// \brief builds a list of resources a user has access to and returns it
///
////////////////////////////////////////////////////////////////////////////////
function getUserResources($userprivs, $resourceprivs=array("available"),
$onlygroups=0, $includedeleted=0, $userid=0) {
global $user;
$key = getKey(array($userprivs, $resourceprivs, $onlygroups, $includedeleted, $userid));
if(array_key_exists($key, $_SESSION['userresources']))
return $_SESSION['userresources'][$key];
#FIXME this whole function could be much more efficient
if(! $userid)
$userid = $user["id"];
$return = array();
$nodeprivs = array();
$startnodes = array();
# build a list of nodes where user is granted $userprivs
$inlist = "'" . implode("','", $userprivs) . "'";
$query = "SELECT u.privnodeid "
. "FROM userpriv u, "
. "userprivtype t "
. "WHERE u.userprivtypeid = t.id AND "
. "t.name IN ($inlist) AND "
. "(u.userid = $userid OR "
. "u.usergroupid IN (SELECT usergroupid "
. "FROM usergroupmembers "
. "WHERE userid = $userid))";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
array_push($startnodes, $row["privnodeid"]);
}
# build data array from userprivtype and userpriv tables to reduce queries
# in addNodeUserResourcePrivs
$privdataset = array('user' => array(), 'usergroup' => array());
$query = "SELECT t.name, "
. "u.privnodeid "
. "FROM userprivtype t, "
. "userpriv u "
. "WHERE u.userprivtypeid = t.id AND "
. "u.userid IS NOT NULL AND "
. "u.userid = $userid AND "
. "t.name IN ('block','cascade',$inlist)";
$qh = doQuery($query);
while($row = mysql_fetch_assoc($qh)) {
if(! array_key_exists($row['privnodeid'], $privdataset['user']))
$privdataset['user'][$row['privnodeid']] = array();
$privdataset['user'][$row['privnodeid']][] = $row['name'];
}
$query = "SELECT t.name, "
. "u.usergroupid, "
. "u.privnodeid "
. "FROM userprivtype t, "
. "userpriv u "
. "WHERE u.userprivtypeid = t.id AND "
. "u.usergroupid IS NOT NULL AND "
. "u.usergroupid IN (SELECT usergroupid "
. "FROM usergroupmembers "
. "WHERE userid = $userid) AND "
. "t.name IN ('block','cascade',$inlist) "
. "ORDER BY u.privnodeid, "
. "u.usergroupid";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
if(! array_key_exists($row['privnodeid'], $privdataset['usergroup']))
$privdataset['usergroup'][$row['privnodeid']] = array();
$privdataset['usergroup'][$row['privnodeid']][] = array('name' => $row['name'], 'groupid' => $row['usergroupid']);
}
# travel up tree looking at privileges granted at parent nodes
foreach($startnodes as $nodeid) {
getUserResourcesUp($nodeprivs, $nodeid, $userid, $userprivs, $privdataset);
}
# travel down tree looking at privileges granted at child nodes if cascade privs at this node
foreach($startnodes as $nodeid) {
getUserResourcesDown($nodeprivs, $nodeid, $userid, $userprivs, $privdataset);
}
$nodeprivs = simplifyNodePrivs($nodeprivs, $userprivs); // call this before calling addUserResources
addUserResources($nodeprivs, $userid);
# build a list of resource groups user has access to
$resourcegroups = array();
$types = getTypes("resources");
foreach($types["resources"] as $type) {
$resourcegroups[$type] = array();
}
foreach(array_keys($nodeprivs) as $nodeid) {
// if user doesn't have privs at this node, no need to look
// at any resource groups here
$haspriv = 0;
foreach($userprivs as $priv) {
if($nodeprivs[$nodeid][$priv])
$haspriv = 1;
}
if(! $haspriv)
continue;
# check to see if resource groups has any of $resourceprivs at this node
foreach(array_keys($nodeprivs[$nodeid]["resources"]) as $resourceid) {
foreach($resourceprivs as $priv) {
if(in_array($priv, $nodeprivs[$nodeid]["resources"][$resourceid])) {
list($type, $name, $id) = explode('/', $resourceid);
if(! array_key_exists($type, $resourcegroups))
$resourcegroups[$type] = array();
if(! in_array($name, $resourcegroups[$type]))
$resourcegroups[$type][$id] = $name;
}
}
}
# check to see if resource groups has any of $resourceprivs cascaded to this node
foreach(array_keys($nodeprivs[$nodeid]["cascaderesources"]) as $resourceid) {
foreach($resourceprivs as $priv) {
if(in_array($priv, $nodeprivs[$nodeid]["cascaderesources"][$resourceid]) &&
! (array_key_exists($resourceid, $nodeprivs[$nodeid]["resources"]) &&
in_array("block", $nodeprivs[$nodeid]["resources"][$resourceid]))) {
list($type, $name, $id) = explode('/', $resourceid);
if(! array_key_exists($type, $resourcegroups))
$resourcegroups[$type] = array();
if(! in_array($name, $resourcegroups[$type]))
$resourcegroups[$type][$id] = $name;
}
}
}
}
addOwnedResourceGroups($resourcegroups, $userid);
if($onlygroups) {
foreach(array_keys($resourcegroups) as $type)
uasort($resourcegroups[$type], "sortKeepIndex");
$_SESSION['userresources'][$key] = $resourcegroups;
return $resourcegroups;
}
$resources = array();
foreach(array_keys($resourcegroups) as $type) {
$resources[$type] =
getResourcesFromGroups($resourcegroups[$type], $type, $includedeleted);
}
addOwnedResources($resources, $includedeleted, $userid);
$_SESSION['userresources'][$key] = $resources;
return $resources;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserResourcesUp(&$nodeprivs, $nodeid, $userid,
/// $resourceprivs)
///
/// \param $nodeprivs - node privilege array used in getUserResources
/// \param $nodeid - an id from the nodepriv table
/// \param $userid - an id from the user table
/// \param $resourceprivs - array of privileges to look for (such as
/// imageAdmin, imageCheckOut, etc); don't include 'block' or 'cascade'
///
/// \return modifies $nodeprivs, but doesn't return anything
///
/// \brief adds resource privileges to $nodeprivs for the parents of $nodeid
///
////////////////////////////////////////////////////////////////////////////////
function getUserResourcesUp(&$nodeprivs, $nodeid, $userid,
$resourceprivs, $privdataset) {
# build list of parent nodes
# starting at top, get images available at that node and user privs there and
# walk down to $nodeid
$nodelist = getParentNodes($nodeid);
array_unshift($nodelist, $nodeid);
$lastid = 0;
while(count($nodelist)) {
$id = array_pop($nodelist);
if(array_key_exists($id, $nodeprivs))
continue;
addNodeUserResourcePrivs($nodeprivs, $id, $lastid, $userid, $resourceprivs, $privdataset);
$lastid = $id;
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserResourcesDown(&$nodeprivs, $nodeid, $userid,
/// $resourceprivs)
///
/// \param $nodeprivs - node privilege array used in getUserResources
/// \param $nodeid - an id from the nodepriv table
/// \param $userid - an id from the user table
/// \param $resourceprivs - array of privileges to look for (such as
/// imageAdmin, imageCheckOut, etc); don't include 'block' or 'cascade'
///
/// \return modifies $nodeprivs, but doesn't return anything
///
/// \brief recursively adds resource privileges to $nodeprivs for any children
/// of $nodeid
///
////////////////////////////////////////////////////////////////////////////////
function getUserResourcesDown(&$nodeprivs, $nodeid, $userid,
$resourceprivs, $privdataset) {
# FIXME can we check for cascading and if not there, don't descend?
$children = getChildNodes($nodeid);
foreach(array_keys($children) as $id) {
addNodeUserResourcePrivs($nodeprivs, $id, $nodeid, $userid, $resourceprivs, $privdataset);
getUserResourcesDown($nodeprivs, $id, $userid, $resourceprivs, $privdataset);
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn addNodeUserResourcePrivs(&$nodeprivs, $id, $lastid, $userid,
/// $resourceprivs)
///
/// \param $nodeprivs - node privilege array used in getUserResources
/// \param $id - an id from the nodepriv table
/// \param $lastid - $id's parent, 0 if at the root
/// \param $userid - an id from the user table
/// \param $resourceprivs - array of privileges to look for (such as
/// imageAdmin, imageCheckOut, etc); don't include 'block' or 'cascade'
///
/// \return modifies $nodeprivs, but doesn't return anything
///
/// \brief for $id, gets privileges and cascaded privileges the user and any
/// groups the user is and adds them to $nodeprivs
///
////////////////////////////////////////////////////////////////////////////////
function addNodeUserResourcePrivs(&$nodeprivs, $id, $lastid, $userid,
$resourceprivs, $privdataset) {
$nodeprivs[$id]["user"] = array("cascade" => 0);
foreach($resourceprivs as $priv) {
$nodeprivs[$id]["user"][$priv] = 0;
}
# add permissions for user
$block = 0;
if(array_key_exists($id, $privdataset['user'])) {
foreach($privdataset['user'][$id] as $name) {
if($name != 'block')
$nodeprivs[$id]['user'][$name] = 1;
else
$block = 1;
}
}
// if don't have anything in $resourceprivs, set cascade = 0
if($nodeprivs[$id]["user"]["cascade"]) {
$noprivs = 1;
foreach($resourceprivs as $priv) {
if($nodeprivs[$id]["user"][$priv])
$noprivs = 0;
}
if($noprivs)
$nodeprivs[$id]["user"]["cascade"] = 0;
}
// if not blocking at this node, and previous node had cascade
if($lastid && ! $block && $nodeprivs[$lastid]["user"]["cascade"]) {
# set cascade = 1
$nodeprivs[$id]["user"]["cascade"] = 1;
# set each priv in $resourceprivs = 1
foreach($resourceprivs as $priv) {
if($nodeprivs[$lastid]["user"][$priv])
$nodeprivs[$id]["user"][$priv] = 1;
}
}
# add permissions for user's groups
$basearray = array("cascade" => 0,
"block" => 0);
foreach($resourceprivs as $priv)
$basearray[$priv] = 0;
if(array_key_exists($id, $privdataset['usergroup'])) {
foreach($privdataset['usergroup'][$id] as $data) {
if(! array_key_exists($data["groupid"], $nodeprivs[$id]))
$nodeprivs[$id][$data["groupid"]] = $basearray;
$nodeprivs[$id][$data["groupid"]][$data["name"]] = 1;
}
}
# add groups from $lastid if it is not 0
$groupkeys = array_keys($nodeprivs[$id]);
if($lastid) {
foreach(array_keys($nodeprivs[$lastid]) as $groupid) {
if(in_array($groupid, $groupkeys))
continue;
$nodeprivs[$id][$groupid] = $basearray;
}
}
foreach(array_keys($nodeprivs[$id]) as $groupid) {
if(! is_numeric($groupid))
continue;
// if don't have anything in $resourceprivs, set cascade = 0
if($nodeprivs[$id][$groupid]["cascade"]) {
$noprivs = 1;
foreach($resourceprivs as $priv) {
if($nodeprivs[$id][$groupid][$priv])
$noprivs = 0;
}
if($noprivs)
$nodeprivs[$id][$groupid]["cascade"] = 0;
}
// if group not blocking at this node, and group had cascade at previous
# node
if($lastid && ! $nodeprivs[$id][$groupid]["block"] &&
array_key_exists($groupid, $nodeprivs[$lastid]) &&
$nodeprivs[$lastid][$groupid]["cascade"]) {
# set cascade = 1
$nodeprivs[$id][$groupid]["cascade"] = 1;
# set each priv in $resourceprivs = 1
foreach($resourceprivs as $priv) {
if($nodeprivs[$lastid][$groupid][$priv])
$nodeprivs[$id][$groupid][$priv] = 1;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn simplifyNodePrivs($nodeprivs, $resourceprivs)
///
/// \param $nodeprivs - node privilege array used in getUserResources
/// \param $resourceprivs - array of privileges to look for (such as
/// imageAdmin, imageCheckOut, etc); don't include 'block' or 'cascade'
///
/// \return a simplified version of $nodeprivs
///
/// \brief checks the user and group privileges for each node in $nodeprivs and
/// creates a new privilege array that just shows if the user has that
/// permission (either directly or from a group)
///
////////////////////////////////////////////////////////////////////////////////
function simplifyNodePrivs($nodeprivs, $resourceprivs) {
$return = array();
$basearray = array();
foreach($resourceprivs as $priv) {
$basearray[$priv] = 0;
}
foreach(array_keys($nodeprivs) as $nodeid) {
$return[$nodeid] = $basearray;
foreach(array_keys($nodeprivs[$nodeid]) as $key) {
foreach($resourceprivs as $priv) {
if($nodeprivs[$nodeid][$key][$priv])
$return[$nodeid][$priv] = 1;
}
}
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn addUserResources(&$nodeprivs, $userid)
///
/// \param $nodeprivs - node privilege array used in getUserResources
/// \param $userid - an id from the user table
///
/// \return modifies $nodeprivs, but doesn't return anything
///
/// \brief for each node in $nodeprivs, adds any resources that are available
/// to $nodeprivs
///
////////////////////////////////////////////////////////////////////////////////
function addUserResources(&$nodeprivs, $userid) {
require_once(".ht-inc/privileges.php");
foreach(array_keys($nodeprivs) as $nodeid) {
$privs = getNodePrivileges($nodeid, "resources");
$nodeprivs[$nodeid]["resources"] = $privs["resources"];
$privs = getNodeCascadePrivileges($nodeid, "resources");
$nodeprivs[$nodeid]["cascaderesources"] = $privs["resources"];
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn addOwnedResources(&$resources, $includedeleted, $userid)
///
/// \param $resources - array of resources from getUserResources
/// \param $includedeleted - 1 to include deleted resources, 0 not to
/// \param $userid - id from user table
///
/// \return modifies $resources, but doesn't return anything
///
/// \brief adds resources that the user owns
///
////////////////////////////////////////////////////////////////////////////////
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;
$query = "SELECT id, "
. "$field "
. "FROM $type "
. "WHERE ownerid = $userid";
if(! $includedeleted && ($type == "image" || $type == "computer"))
$query .= " AND deleted = 0";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
if(! array_key_exists($row["id"], $resources[$type]))
$resources[$type][$row["id"]] = $row[$field];
}
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn addOwnedResourceGroups(&$resourcegroups, $userid)
///
/// \param $resourcegroups - array of resources from getUserResources
/// \param $userid - id from user table
///
/// \return modifies $resources, but doesn't return anything
///
/// \brief adds resources that the user owns
///
////////////////////////////////////////////////////////////////////////////////
function addOwnedResourceGroups(&$resourcegroups, $userid) {
if(! $user = getUserInfo($userid, 1, 1))
return;
$userid = $user["id"];
$groupids = implode(',', array_keys($user["groups"]));
if(empty($groupids))
$groupids = "''";
$query = "SELECT g.id AS id, "
. "g.name AS name, "
. "t.name AS type "
. "FROM resourcegroup g, "
. "resourcetype t "
. "WHERE g.resourcetypeid = t.id AND "
. "g.ownerusergroupid IN ($groupids)";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
if(! array_key_exists($row["id"], $resourcegroups[$row["type"]]))
$resourcegroups[$row["type"]][$row["id"]] = $row["name"];
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getResourcesFromGroups($groups, $type, $includedeleted)
///
/// \param $groups - an array of group names
/// \param $type - the type of the groups (from resourcetype table)
/// \param $includedeleted - 1 to include deleted resources, 0 not to
///
/// \return an array of resources where the index is the id of the resource and
/// the value is the name of the resource
///
/// \brief builds an array of resources from $groups
///
////////////////////////////////////////////////////////////////////////////////
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();
$groups = implode("','", $groups);
$inlist = "'$groups'";
$query = "SELECT DISTINCT(r.subid) AS id, "
. "t.$field AS name "
. "FROM $type t, "
. "resource r, "
. "resourcegroupmembers m, "
. "resourcegroup g, "
. "resourcetype rt "
. "WHERE r.subid = t.id AND "
. "r.id = m.resourceid AND "
. "m.resourcegroupid = g.id AND "
. "g.name IN ($inlist) AND "
. "g.resourcetypeid = rt.id AND "
. "rt.name = '$type'";
if(! $includedeleted && ($type == "image" || $type == "computer")) {
$query .= "AND deleted = 0 ";
}
/*if($type == "image")
$query .= "AND test = 0 ";*/
$query .= "ORDER BY t.$field";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$return[$row["id"]] = $row["name"];
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn updateUserOrGroupPrivs($name, $node, $adds, $removes, $mode)
///
/// \param $name - loginid, user id, or user group id
/// \param $node - id of the node
/// \param $adds - array of privs (the name, not the id) to add
/// \param $removes - array of privs (the name, not the id) to remove
/// \param $mode - "user" or "group"
///
/// \brief adds/removes $adds/$removes privs for $unityid to/from $node
///
////////////////////////////////////////////////////////////////////////////////
function updateUserOrGroupPrivs($name, $node, $adds, $removes, $mode) {
if(! (count($adds) || count($removes))) {
return;
}
if($mode == "user") {
$field = "userid";
if(is_numeric($name))
$id = $name;
else {
$id = getUserlistID($name);
if(! $id)
$id = addUser($name);
}
}
else {
$field = "usergroupid";
$id = $name;
}
foreach($adds as $type) {
$typeid = getUserPrivTypeID($type);
$query = "INSERT IGNORE INTO userpriv ("
. "$field, "
. "privnodeid, "
. "userprivtypeid) "
. "VALUES ("
. "$id, "
. "$node, "
. "$typeid)";
doQuery($query, 375);
}
foreach($removes as $type) {
$typeid = getUserPrivTypeID($type);
$query = "DELETE FROM userpriv "
. "WHERE $field = $id AND "
. "privnodeid = $node AND "
. "userprivtypeid = $typeid";
doQuery($query, 376);
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn updateResourcePrivs($group, $node, $adds, $removes)
///
/// \param $group - id from resourcegroup table, or group name of the form
/// type/name
/// \param $node - id of the node
/// \param $adds - array of privs (the name, not the id) to add
/// \param $removes - array of privs (the name, not the id) to remove
///
/// \brief adds/removes $adds/$removes privs for $name to/from $node
///
////////////////////////////////////////////////////////////////////////////////
function updateResourcePrivs($group, $node, $adds, $removes) {
if(! (count($adds) || count($removes))) {
return;
}
if(is_numeric($group))
$groupid = $group;
else
$groupid = getResourceGroupID($group);
foreach($adds as $type) {
$query = "INSERT IGNORE INTO resourcepriv ("
. "resourcegroupid, "
. "privnodeid, "
. "type) "
. "VALUES ("
. "$groupid, "
. "$node, "
. "'$type')";
doQuery($query, 377);
}
foreach($removes as $type) {
$query = "DELETE FROM resourcepriv "
. "WHERE resourcegroupid = $groupid AND "
. "privnodeid = $node AND "
. "type = '$type'";
doQuery($query, 378);
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getKey($data)
///
/// \param $data - an array
///
/// \return an md5 string that is unique for $data
///
/// \brief generates an md5sum for $data
///
////////////////////////////////////////////////////////////////////////////////
function getKey($data) {
$newdata = array();
foreach($data as $arr)
if(is_array($arr))
$newdata = array_merge_recursive($newdata, $arr);
else
array_push($newdata, $arr);
$rc = '';
foreach($newdata as $key => $val)
$rc = md5("$rc$key$val");
return $rc;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn encryptData($data)
///
/// \param $data - a string
///
/// \return an encrypted form of the string that has been base64 encoded
///
/// \brief encrypts $data with blowfish and base64 encodes it
///
////////////////////////////////////////////////////////////////////////////////
function encryptData($data) {
global $cryptkey;
if(! $data)
return false;
$aes = new Crypt_AES();
$aes->setKey($cryptkey);
$cryptdata = $aes->encrypt($data);
return trim(base64_encode($cryptdata));
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn decryptData($data)
///
/// \param $data - a string
///
/// \return decrypted form of $data
///
/// \brief base64 decodes $data and decrypts it
///
////////////////////////////////////////////////////////////////////////////////
function decryptData($data) {
global $cryptkey;
if(! $data)
return false;
$aes = new Crypt_AES();
$aes->setKey($cryptkey);
$cryptdata = base64_decode($data);
$decryptdata = $aes->decrypt($cryptdata);
return trim($decryptdata);
}
////////////////////////////////////////////////////////////////////////////////
//
// \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)){
$key = openssl_pkey_get_public(file_get_contents($public_key));
} else {
$key = openssl_pkey_get_public($public_key);
}
openssl_public_encrypt($data, $encrypted, $key, OPENSSL_PKCS1_OAEP_PADDING);
openssl_free_key($key);
$hexformatted = unpack("H*hex", $encrypted);
return $hexformatted['hex'];
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getParentNodes($node)
///
/// \param $node - a privnode id
///
/// \return an array of parents of $node
///
/// \brief build array of node's parents with 0th index being immediate parent
///
////////////////////////////////////////////////////////////////////////////////
function getParentNodes($node) {
global $nodeparents;
if(array_key_exists($node, $nodeparents))
return $nodeparents[$node];
$nodelist = array();
while($node != 1) {
$nodeinfo = getNodeInfo($node);
$node = $nodeinfo["parent"];
if($node == NULL)
break;
array_push($nodelist, $node);
}
$nodeparents[$node] = $nodelist;
return $nodelist;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getChildNodes($parent)
///
/// \param parent - (optional) the parent of all the children; defaults to 2
/// (the root node)
///
/// \return an array of nodes
///
/// \brief gets all children for $parent
///
////////////////////////////////////////////////////////////////////////////////
function getChildNodes($parent=DEFAULT_PRIVNODE) {
global $cache;
if(! array_key_exists('nodes', $cache))
# call getNodeInfo to populate $cache['nodes']
getNodeInfo($parent);
static $allnodes = array();
if(empty($allnodes)) {
foreach($cache['nodes'] as $id => $node) {
unset($node['id']);
if(! array_key_exists($node['parent'], $allnodes))
$allnodes[$node['parent']] = array();
$allnodes[$node['parent']][$id] = $node;
}
}
if(array_key_exists($parent, $allnodes))
return $allnodes[$parent];
else
return array();
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserGroups($groupType, $affiliationid)
///
/// \param $groupType - (optional, default = 0) 0 for all groups, 1 for custom
/// groups, 2 for courseroll groups
/// \param $affiliationid - (optional, default = 0) 0 for groups of any
/// affiliation, or the id of an affiliation for only groups with that
/// affiliation
///
/// \return an array where each index is an id from usergroup and the values
/// are arrays with the indexes:\n
/// name\n
/// groupaffiliation\n
/// groupaffiliationid\n
/// ownerid\n
/// owner\n
/// affiliation\n
/// editgroupid\n
/// editgroup\n
/// editgroupaffiliationid\n
/// editgroupaffiliation\n
/// custom\n
/// courseroll\n
/// initialmaxtime\n
/// totalmaxtime\n
/// maxextendtime\n
/// overlapResCount
///
/// \brief builds list of user groups\n
///
////////////////////////////////////////////////////////////////////////////////
function getUserGroups($groupType=0, $affiliationid=0) {
global $user;
$key = getKey(array($groupType, $affiliationid, $user['showallgroups']));
if(array_key_exists($key, $_SESSION['usersessiondata']))
return $_SESSION['usersessiondata'][$key];
$return = array();
$query = "SELECT ug.id, "
. "ug.name, "
. "ga.name AS groupaffiliation, "
. "ug.affiliationid AS groupaffiliationid, "
. "ug.ownerid, "
. "u.unityid AS owner, "
. "a.name AS affiliation, "
. "ug.editusergroupid AS editgroupid, "
. "eug.name AS editgroup, "
. "eug.affiliationid AS editgroupaffiliationid, "
. "euga.name AS editgroupaffiliation, "
. "ug.custom, "
. "ug.courseroll, "
. "ug.initialmaxtime, "
. "ug.totalmaxtime, "
. "ug.maxextendtime, "
. "ug.overlapResCount "
. "FROM usergroup ug "
. "LEFT JOIN user u ON (ug.ownerid = u.id) "
. "LEFT JOIN usergroup eug ON (ug.editusergroupid = eug.id) "
. "LEFT JOIN affiliation a ON (u.affiliationid = a.id) "
. "LEFT JOIN affiliation ga ON (ug.affiliationid = ga.id) "
. "LEFT JOIN affiliation euga ON (eug.affiliationid = euga.id) "
. "WHERE 1 ";
if($groupType == 1)
$query .= "AND ug.custom = 1 ";
elseif($groupType == 2)
$query .= "AND ug.courseroll = 1 ";
if(! $user['showallgroups'] && $affiliationid)
$query .= "AND ug.affiliationid = $affiliationid ";
$query .= "ORDER BY name";
$qh = doQuery($query, 280);
while($row = mysql_fetch_assoc($qh)) {
if(! empty($row["owner"]) && ! empty($row['affiliation']))
$row['owner'] = "{$row['owner']}@{$row['affiliation']}";
if($user['showallgroups'] || $affiliationid == 0)
$row['name'] = "{$row['name']}@{$row['groupaffiliation']}";
$return[$row["id"]] = $row;
}
$_SESSION['usersessiondata'][$key] = $return;
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserEditGroups($id)
///
/// \param $id - user id (string or numeric)
///
/// \return an array of groups where each key is the group id
///
/// \brief builds an array of groups for which $id can edit the membership
///
////////////////////////////////////////////////////////////////////////////////
function getUserEditGroups($id) {
global $user;
if(! is_numeric($id))
$id = getUserlistID($id);
if($user['showallgroups']) {
$query = "SELECT DISTINCT(u.id), "
. "CONCAT(u.name, '@', a.name) AS name "
. "FROM `usergroup` u, "
. "`usergroupmembers` m, "
. "affiliation a "
. "WHERE u.editusergroupid = m.usergroupid AND "
. "u.affiliationid = a.id AND "
. "(u.ownerid = $id OR m.userid = $id) "
. "ORDER BY name";
}
else {
$query = "SELECT DISTINCT(u.id), "
. "u.name "
. "FROM `usergroup` u, "
. "`usergroupmembers` m "
. "WHERE u.editusergroupid = m.usergroupid AND "
. "(u.ownerid = $id OR m.userid = $id) AND "
. "u.affiliationid = {$user['affiliationid']} "
. "ORDER BY name";
}
$qh = doQuery($query, 101);
$groups = array();
while($row = mysql_fetch_assoc($qh)) {
$groups[$row['id']] = $row['name'];
}
return $groups;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserGroupPrivs($groupid='')
///
/// \param $groupid (optional, default='') - if specified, only get permissions
/// granted to this user group; if not specified, get information about
/// all groups
///
/// \return array of data about user group permissions where each element is an
/// array with these keys:\n
/// \b usergroup - name of user group\n
/// \b usergroupid - id of user group\n
/// \b permission - permission granted to user group\n
/// \b permid - id of permission granted to user group
///
/// \brief builds an array of data about permissions granted to user groups
///
////////////////////////////////////////////////////////////////////////////////
function getUserGroupPrivs($groupid='') {
$data = array();
$query = "SELECT ug.name AS usergroup, "
. "ugp.usergroupid, "
. "ugpt.name AS permission, "
. "ugp.userprivtypeid AS permid "
. "FROM usergroup ug, "
. "usergrouppriv ugp, "
. "usergroupprivtype ugpt "
. "WHERE ugp.usergroupid = ug.id AND "
. "ugp.userprivtypeid = ugpt.id ";
if(! empty($groupid))
$query .= "AND ugp.usergroupid = $groupid ";
$query .= "ORDER BY ug.name, "
. "ugpt.name";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh))
$data[] = $row;
return $data;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserGroupPrivTypes()
///
/// \return array of information about user group permissions where each index
/// is the id of the permission and each element has these keys:\n
/// \b id - id of permission\n
/// \b name - name of permission\n
/// \b help - additional information about permission
///
/// \brief builds an array of information about the user group permissions
///
////////////////////////////////////////////////////////////////////////////////
function getUserGroupPrivTypes() {
$data = array();
$query = "SELECT id, name, help FROM usergroupprivtype ORDER BY name";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh))
$data[$row['id']] = $row;
return $data;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getResourceGroups($type)
///
/// \param $type - (optional) a name from the resourcetype table, defaults to
/// be empty
///
/// \return an array of resource group names whose index values are the ids;
/// the names are the resource type and group name combined as 'type/name'
///
/// \brief builds list of resource groups
///
////////////////////////////////////////////////////////////////////////////////
function getResourceGroups($type="") {
$return = array();
$query = "SELECT g.id AS id, "
. "g.name AS name, "
. "t.name AS type, "
. "g.ownerusergroupid AS ownerid, "
. "CONCAT(u.name, '@', a.name) AS owner "
. "FROM resourcegroup g, "
. "resourcetype t, "
. "usergroup u, "
. "affiliation a "
. "WHERE g.resourcetypeid = t.id AND "
. "g.ownerusergroupid = u.id AND "
. "u.affiliationid = a.id ";
if(! empty($type))
$query .= "AND t.name = '$type' ";
$query .= "ORDER BY t.name, g.name";
$qh = doQuery($query, 281);
while($row = mysql_fetch_assoc($qh)) {
if(empty($type))
$return[$row["id"]]["name"] = $row["type"] . "/" . $row["name"];
else
$return[$row["id"]]["name"] = $row["name"];
$return[$row["id"]]["ownerid"] = $row["ownerid"];
$return[$row["id"]]["owner"] = $row["owner"];
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getResourceGroupMemberships($type)
///
/// \param $type - (optional) a name from the resourcetype table, defaults to
/// "all"
///
/// \return an array where each index is a resource type and the values are
/// arrays where each index is a resource id and its values are an array of
/// resource group ids that it is a member of
///
/// \brief builds an array of group memberships for resources
///
////////////////////////////////////////////////////////////////////////////////
function getResourceGroupMemberships($type="all") {
$return = array();
if($type == "all")
$types = getTypes("resources");
else
$types = array("resources" => array($type));
foreach($types["resources"] as $type) {
$return[$type] = array();
$query = "SELECT r.subid AS id, "
. "gm.resourcegroupid AS groupid "
. "FROM resource r, "
. "resourcegroupmembers gm, "
. "resourcetype t "
. "where t.name = '$type' AND "
. "gm.resourceid = r.id AND "
. "r.resourcetypeid = t.id";
$qh = doQuery($query, 282);
while($row = mysql_fetch_assoc($qh)) {
if(array_key_exists($row["id"], $return[$type])) {
array_push($return[$type][$row["id"]], $row["groupid"]);
}
else {
$return[$type][$row["id"]] = array($row["groupid"]);
}
}
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getResourceGroupMembers($type)
///
/// \param $type - (optional) a name from the resourcetype table, defaults to
/// "all"
///
/// \return an array where each index is a resource type and the values are
/// arrays where each index is a resourcegroup id and its values are an array of
/// resource ids that are each an array, resulting in this:\n
/// Array {\n
/// [resourcetype] => Array {\n
/// [resourcegroupid] => Array {\n
/// [resourceid] => Array {\n
/// [subid] => resource sub id\n
/// [name] => name of resource\n
/// }\n
/// }\n
/// }\n
/// }
///
/// \brief builds an array of resource group members that don't have the deleted
/// flag set
///
////////////////////////////////////////////////////////////////////////////////
function getResourceGroupMembers($type="all") {
$key = getKey(array('getResourceGroupMembers', $type));
if(array_key_exists($key, $_SESSION['userresources']))
return $_SESSION['userresources'][$key];
$return = array();
if($type == "computer") {
$names = "c.hostname AS computer, c.deleted ";
$joins = "LEFT JOIN computer c ON (r.subid = c.id AND r.resourcetypeid = 12) ";
$orders = "c.hostname";
$types = "'computer'";
}
elseif($type == "image") {
$names = "i.prettyname AS image, i.deleted ";
$joins = "LEFT JOIN image i ON (r.subid = i.id AND r.resourcetypeid = 13) ";
$orders = "i.prettyname";
$types = "'image'";
}
elseif($type == "schedule") {
$names = "s.name AS schedule ";
$joins = "LEFT JOIN schedule s ON (r.subid = s.id AND r.resourcetypeid = 15) ";
$orders = "s.name";
$types = "'schedule'";
}
elseif($type == "managementnode") {
$names = "m.hostname AS managementnode ";
$joins = "LEFT JOIN managementnode m ON (r.subid = m.id AND r.resourcetypeid = 16) ";
$orders = "m.hostname";
$types = "'managementnode'";
}
else {
$names = "c.hostname AS computer, "
. "c.deleted, "
. "i.prettyname AS image, "
. "i.deleted AS deleted2, "
. "s.name AS schedule, "
. "m.hostname AS managementnode ";
$joins = "LEFT JOIN computer c ON (r.subid = c.id AND r.resourcetypeid = 12) "
. "LEFT JOIN image i ON (r.subid = i.id AND r.resourcetypeid = 13) "
. "LEFT JOIN schedule s ON (r.subid = s.id AND r.resourcetypeid = 15) "
. "LEFT JOIN managementnode m ON (r.subid = m.id AND r.resourcetypeid = 16) ";
$orders = "c.hostname, "
. "i.prettyname, "
. "s.name, "
. "m.hostname";
$types = "'computer','image','schedule','managementnode'";
}
$query = "SELECT rgm.resourcegroupid, "
. "rgm.resourceid, "
. "rt.name AS resourcetype, "
. "r.subid, "
. $names
. "FROM resourcegroupmembers rgm, "
. "resourcetype rt, "
. "resource r "
. $joins
. "WHERE rgm.resourceid = r.id AND "
. "r.resourcetypeid = rt.id AND "
. "rt.name in ($types) "
. "ORDER BY rt.name, "
. "rgm.resourcegroupid, "
. $orders;
$qh = doQuery($query, 282);
while($row = mysql_fetch_assoc($qh)) {
if(array_key_exists('deleted', $row) && $row['deleted'] == 1)
continue;
if(array_key_exists('deleted2', $row) && $row['deleted2'] == 1)
continue;
if(! array_key_exists($row['resourcetype'], $return))
$return[$row['resourcetype']] = array();
if(! array_key_exists($row['resourcegroupid'], $return[$row['resourcetype']]))
$return[$row['resourcetype']][$row['resourcegroupid']] = array();
$return[$row['resourcetype']][$row['resourcegroupid']][$row['resourceid']] =
array('subid' => $row['subid'],
'name' => $row[$row['resourcetype']]);
}
$_SESSION['userresources'][$key] = $return;
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserGroupMembers($groupid)
///
/// \param $groupid - a usergroup id
///
/// \return an array of unityids where the index is the userid
///
/// \brief builds an array of user group memberships
///
////////////////////////////////////////////////////////////////////////////////
function getUserGroupMembers($groupid) {
$return = array();
$query = "SELECT m.userid AS id, "
. "CONCAT(u.unityid, '@', a.name) AS user "
. "FROM usergroupmembers m, "
. "affiliation a, "
. "user u "
. "WHERE m.usergroupid = $groupid AND "
. "m.userid = u.id AND "
. "u.affiliationid = a.id "
. "ORDER BY u.unityid";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$return[$row["id"]] = $row['user'];
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn addUserGroupMember($loginid, $groupid)
///
/// \param $loginid - a user's loginid
/// \param $groupid - a usergroup id
///
/// \brief adds an entry to usergroupmembers for $unityid and $groupid
///
////////////////////////////////////////////////////////////////////////////////
function addUserGroupMember($loginid, $groupid) {
$userid = getUserlistID($loginid);
$groups = getUsersGroups($userid);
if(in_array($groupid, array_keys($groups)))
return;
$query = "INSERT INTO usergroupmembers "
. "(userid, "
. "usergroupid) "
. "VALUES "
. "($userid, "
. "$groupid)";
doQuery($query, 101);
checkUpdateServerRequestGroups($groupid);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn deleteUserGroupMember($userid, $groupid)
///
/// \param $userid - a userid
/// \param $groupid - a usergroup id
///
/// \brief deletes an entry from usergroupmembers for $userid and $groupid
///
////////////////////////////////////////////////////////////////////////////////
function deleteUserGroupMember($userid, $groupid) {
$query = "DELETE FROM usergroupmembers "
. "WHERE userid = $userid AND "
. "usergroupid = $groupid";
doQuery($query, 101);
checkUpdateServerRequestGroups($groupid);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserlistID($loginid, $noadd)
///
/// \param $loginid - login ID
/// \param $noadd - (optional, default=0) 0 to try to add user to database if
/// not there, 1 to only return the id if it already exists in the database
///
/// \return id from userlist table for the user
///
/// \brief gets id field from userlist table for $loginid; if it does not exist,
/// calls addUser to add it to the table
///
////////////////////////////////////////////////////////////////////////////////
function getUserlistID($loginid, $noadd=0) {
$_loginid = $loginid;
getAffilidAndLogin($loginid, $affilid);
if(empty($affilid))
abort(12);
$query = "SELECT id "
. "FROM user "
. "WHERE unityid = '$loginid' AND "
. "affiliationid = $affilid";
$qh = doQuery($query, 140);
if(mysql_num_rows($qh)) {
$row = mysql_fetch_row($qh);
return $row[0];
}
if($noadd)
return NULL;
return addUser($_loginid);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUsersLastImage($userid)
///
/// \param $userid - a numeric user id
///
/// \return id of user's last used image or NULL if user has no entries in the
/// log table
///
/// \brief gets the user's last used image from the log table
///
////////////////////////////////////////////////////////////////////////////////
function getUsersLastImage($userid) {
$query = "SELECT imageid "
. "FROM log "
. "WHERE userid = $userid "
. "ORDER BY id DESC "
. "LIMIT 1";
$qh = doQuery($query, 101);
if($row = mysql_fetch_assoc($qh))
return $row['imageid'];
return NULL;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getAffiliations()
///
/// \return an array of affiliations where each index is the id of the
/// affiliation
///
/// \brief gets a list of all affiliations
///
////////////////////////////////////////////////////////////////////////////////
function getAffiliations() {
$query = "SELECT id, name FROM affiliation ORDER BY name";
$qh = doQuery($query, 101);
$return = array();
while($row = mysql_fetch_assoc($qh))
$return[$row['id']] = $row['name'];
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserUnityID($userid)
///
/// \param $userid - an id from the user table
///
/// \return unityid for $userid or NULL if $userid not found
///
/// \brief gets the unityid for $userid
///
////////////////////////////////////////////////////////////////////////////////
function getUserUnityID($userid) {
global $cache;
if(! array_key_exists('unityids', $cache))
$cache['unityids'] = array();
if(array_key_exists($userid, $cache['unityids']))
return $cache['unityids'][$userid];
$query = "SELECT unityid FROM user WHERE id = $userid";
$qh = doQuery($query, 101);
if(mysql_num_rows($qh)) {
$row = mysql_fetch_row($qh);
$cache['unityids'][$userid] = $row[0];
return $row[0];
}
return NULL;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getAffiliationID($affil)
///
/// \param $affil - name of an affiliation
///
/// \return id from affiliation table
///
/// \brief gets id field from affiliation table for $affil
///
////////////////////////////////////////////////////////////////////////////////
function getAffiliationID($affil) {
$affil = mysql_real_escape_string($affil);
$query = "SELECT id FROM affiliation WHERE name = '$affil'";
$qh = doQuery($query, 101);
if(mysql_num_rows($qh)) {
$row = mysql_fetch_row($qh);
return $row[0];
}
return NULL;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getAffiliationName($affilid)
///
/// \param $affilid - id of an affiliation
///
/// \return name from affiliation table
///
/// \brief gets name field from affiliation table for $affilid
///
////////////////////////////////////////////////////////////////////////////////
function getAffiliationName($affilid) {
$query = "SELECT name FROM affiliation WHERE id = $affilid";
$qh = doQuery($query, 101);
if(mysql_num_rows($qh)) {
$row = mysql_fetch_row($qh);
return $row[0];
}
return NULL;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getAffiliationDataUpdateText($affilid)
///
/// \param $affilid - (optional) specify an affiliation id to get only the text
/// for that id
///
/// \return an array of the html text to display for updating user information
/// that is displayed on the User Preferences page
///
/// \brief gets dataUpdateText from affiliation table
///
////////////////////////////////////////////////////////////////////////////////
function getAffiliationDataUpdateText($affilid=0) {
$query = "SELECT id, dataUpdateText FROM affiliation";
if($affilid)
$query .= " WHERE id = $affilid";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh))
$return[$row['id']] = $row['dataUpdateText'];
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getAffiliationTheme($affilid)
///
/// \param $affilid - id of an affiliation
///
/// \return name of the affiliations's theme
///
/// \brief gets affiliation.theme for the specified affiliation
///
////////////////////////////////////////////////////////////////////////////////
function getAffiliationTheme($affilid) {
$query = "SELECT theme FROM affiliation WHERE id = $affilid";
$qh = doQuery($query);
if(($row = mysql_fetch_assoc($qh)) && ! empty($row['theme']))
return $row['theme'];
else
return 'default';
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn processInputVar($vartag, $type, $defaultvalue, $stripwhitespace)
///
/// \param $vartag - name of GET or POST variable
/// \param $type - tag type:\n
/// \b ARG_NUMERIC - numeric\n
/// \b ARG_STRING - string\n
/// \b ARG_MULTINUMERIC - an array of numbers
/// \param $defaultvalue - default value for the variable (NULL if not passed in)
/// \param $stripwhitespace - (optional, default=0) - set to 1 to strip
/// whitespace from the beginning and end of the value
///
/// \return safe value for the GET or POST variable
///
/// \brief checks for $vartag in the $_POST array, then the $_GET array; then
/// sanitizes the variable to make sure it doesn't contain anything malicious
///
////////////////////////////////////////////////////////////////////////////////
function processInputVar($vartag, $type, $defaultvalue=NULL, $stripwhitespace=0) {
if((array_key_exists($vartag, $_POST) &&
strncmp("$_POST[$vartag]", "0", 1) == 0 &&
$type == ARG_NUMERIC &&
strncmp("$_POST[$vartag]", "0x0", 3) != 0) ||
(array_key_exists($vartag, $_GET) &&
strncmp("$_GET[$vartag]", "0", 1) == 0 &&
$type == ARG_NUMERIC &&
strncmp("$_GET[$vartag]", "0x0", 3) != 0)) {
$_POST[$vartag] = "zero";
}
if(!empty($_POST[$vartag])) {
$return = $_POST[$vartag];
}
elseif(!empty($_GET[$vartag])) {
$return = $_GET[$vartag];
}
else {
if($type == ARG_MULTINUMERIC || $type == ARG_MULTISTRING) {
$return = array();
}
else {
$return = $defaultvalue;
}
}
if($return == "zero") {
$return = "0";
}
if($type == ARG_MULTINUMERIC) {
foreach($return as $index => $value) {
$return[$index] = strip_tags($value);
if($stripwhitespace)
$return[$index] = trim($return[$index]);
if($return[$index] == 'zero')
$return[$index] = '0';
}
}
elseif($type == ARG_MULTISTRING) {
foreach($return as $index => $value) {
$return[$index] = strip_tags($value);
if($stripwhitespace)
$return[$index] = trim($return[$index]);
}
}
else {
$return = strip_tags($return);
if($stripwhitespace)
$return = trim($return);
}
if(! empty($return) && $type == ARG_NUMERIC) {
if(! is_numeric($return)) {
return preg_replace('([^\d])', '', $return);
}
}
elseif(! empty($return) && $type == ARG_STRING) {
if(! is_string($return)) {
print "ERROR (code:3) \n";
printHTMLFooter();
semUnlock();
exit();
}
#print "before - $return \n";
#$return = addslashes($return);
#$return = str_replace("\'", "", $return);
#$return = str_replace("\"", "", $return);
#print "after - $return \n";
}
elseif(! empty($return) && $type == ARG_MULTINUMERIC) {
foreach($return as $index => $value) {
if(! is_numeric($value)) {
$return[$index] = preg_replace('([^\d])', '', $value);
}
}
return $return;
}
elseif(! empty($return) && $type == ARG_MULTISTRING) {
foreach($return as $index => $value) {
if(! is_string($value)) {
print "ERROR (code:3) \n";
printHTMLFooter();
semUnlock();
exit();
}
}
return $return;
}
if(is_string($return)) {
if(strlen($return) == 0) {
$return = $defaultvalue;
}
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getContinuationVar($name, $defaultval)
///
/// \param $name (optional, default=NULL)- key of value to return from
/// $contdata or omit to get all of $contdata
/// \param $defaultval (optional, default=NULL) - default value in case $name
/// does not exist in $contdata
///
/// \return if $name is passed, $contdata[$name] or $defaultval; if $name is
/// omitted, $contdata
///
/// \brief returns the requested value from $contdata or a default value if
/// $name does not exist in $contdata; if both args are omitted, just return all
/// of $contdata
///
////////////////////////////////////////////////////////////////////////////////
function getContinuationVar($name=NULL, $defaultval=NULL) {
global $contdata, $inContinuation;
if($name === NULL) {
return $contdata;
}
if(! $inContinuation)
return $defaultval;
if(array_key_exists($name, $contdata)) {
if($contdata[$name] == 'zero')
return 0;
return $contdata[$name];
}
return $defaultval;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn processInputData($data, $type, $addslashes, $defaultvalue)
///
/// \param $data - data to sanitize
/// \param $type - tag type:\n
/// \b ARG_NUMERIC - numeric\n
/// \b ARG_STRING - string\n
/// \b ARG_MULTINUMERIC - an array of numbers
/// \param $addslashes - (optional, defaults to 0) set to 1 if values should
/// have addslashes called to escape things
/// \param $defaultvalue - (optional, defaults to NULL) default value for the
/// variable
///
/// \return a sanitized version of $data
///
/// \brief sanitizes $data to keep bad stuff from being passed in
///
////////////////////////////////////////////////////////////////////////////////
function processInputData($data, $type, $addslashes=0, $defaultvalue=NULL) {
if(strncmp("$data", "0", 1) == 0 &&
$type == ARG_NUMERIC &&
strncmp("$data", "0x0", 3) != 0) {
$data = "zero";
}
if(!empty($data))
$return = $data;
else {
if($type == ARG_MULTINUMERIC || $type == ARG_MULTISTRING)
$return = array();
else
$return = $defaultvalue;
}
if($return == "zero")
$return = "0";
if($type == ARG_MULTINUMERIC) {
foreach($return as $index => $value) {
$return[$index] = strip_tags($value);
if($return[$index] == 'zero')
$return[$index] = '0';
}
}
elseif($type == ARG_MULTISTRING) {
foreach($return as $index => $value) {
$return[$index] = strip_tags($value);
}
}
else
$return = strip_tags($return);
if(! empty($return) && $type == ARG_NUMERIC) {
if(! is_numeric($return)) {
return preg_replace('([^\d])', '', $return);
}
}
elseif(! empty($return) && $type == ARG_STRING) {
if(! is_string($return))
$return = $defaultvalue;
}
elseif(! empty($return) && $type == ARG_MULTINUMERIC) {
foreach($return as $index => $value) {
if(! is_numeric($value)) {
$return[$index] = preg_replace('([^\d])', '', $value);
}
}
return $return;
}
elseif(! empty($return) && $type == ARG_MULTISTRING) {
foreach($return as $index => $value) {
if(! is_string($value))
$return[$index] = $defaultvalue;
elseif($addslashes)
$return[$index] = addslashes($value);
}
return $return;
}
if(is_string($return)) {
if(strlen($return) == 0)
$return = $defaultvalue;
elseif($addslashes)
$return = addslashes($return);
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserInfo($id, $noupdate, $numeric)
///
/// \param $id - unity ID for the user or user's id from database
/// \param $noupdate - (optional, default=0) specify 1 to skip updating user's
/// data if lastupdated timestamp is expired
/// \param $numeric - (optional, default=0) 1 specifies $id corresponds to the
/// id field from the user table; 0 otherwise
///
/// \return 0 if fail to fetch data or $user - an array with these elements:\n
/// \b unityid - unity ID for the user\n
/// \b affiliationid - affiliation id of user\n
/// \b affiliation - affiliation of user\n
/// \b login - login ID for the user (unity ID or part before \@sign)\n
/// \b firstname - user's first name\n
/// \b lastname - user's last name\n
/// \b preferredname - user's preferred name\n
/// \b email - user's preferred email address\n
/// \b emailnotices - bool for sending email notices to user\n
/// \b IMtype - user's preferred IM protocol\n
/// \b IMid - user's IM id\n
/// \b id - user's id from database\n
/// \b width - pixel width for rdp files\n
/// \b height - pixel height for rdp files\n
/// \b bpp - color depth for rdp files\n
/// \b audiomode - 'none' or 'local' - audio mode for rdp files\n
/// \b mapdrives - 0 or 1 - map drives for rdp files; 1 means to map\n
/// \b mapprinters - 0 or 1 - map printers for rdp files; 1 means to map\n
/// \b mapserial - 0 or 1 - map serial ports for rdp files; 1 means to map\n
/// \b showallgroups - 0 or 1 - show only user groups matching user's
/// affiliation or show all user groups\n
/// \b lastupdated - datetime the information was last updated\n
/// \b groups - array of groups user is a member of where the index is the id
/// of the group and the value is the name of the group\n
/// \b privileges - array of privileges that the user has
///
/// \brief gets the user's information from the db and puts it into an array;
/// if the user is not in the db, query ldap and add them; if the user changed
/// their name and unity id; fix information in db based on numeric unity id;
/// returns NULL if could not get information about the user
///
////////////////////////////////////////////////////////////////////////////////
function getUserInfo($id, $noupdate=0, $numeric=0) {
$affilid = DEFAULT_AFFILID;
if(! $numeric) {
$rc = getAffilidAndLogin($id, $affilid);
if($rc == -1)
return NULL;
}
$user = array();
$query = "SELECT u.unityid AS unityid, "
. "u.affiliationid, "
. "af.name AS affiliation, "
. "u.firstname AS firstname, "
. "u.lastname AS lastname, "
. "u.preferredname AS preferredname, "
. "u.email AS email, "
. "u.emailnotices, "
. "i.name AS IMtype, "
. "u.IMid AS IMid, "
. "u.id AS id, "
. "u.width AS width, "
. "u.height AS height, "
. "u.bpp AS bpp, "
. "u.audiomode AS audiomode, "
. "u.mapdrives AS mapdrives, "
. "u.mapprinters AS mapprinters, "
. "u.mapserial AS mapserial, "
. "u.showallgroups, "
. "u.lastupdated AS lastupdated, "
. "af.shibonly "
. "FROM user u, "
. "IMtype i, "
. "affiliation af "
. "WHERE u.IMtypeid = i.id AND "
. "u.affiliationid = af.id AND ";
if($numeric)
$query .= "u.id = $id";
else
$query .= "u.unityid = '$id' AND af.id = $affilid";
$qh = doQuery($query, "105");
if($user = mysql_fetch_assoc($qh)) {
if((datetimeToUnix($user["lastupdated"]) > time() - SECINDAY) ||
$user['unityid'] == 'vclreload' ||
$user['affiliation'] == 'Local' ||
$user['shibonly'] ||
$noupdate) {
# get user's groups
$user["groups"] = getUsersGroups($user["id"], 1);
$user["groupperms"] = getUsersGroupPerms(array_keys($user['groups']));
checkExpiredDemoUser($user['id'], $user['groups']);
# get user's privileges
$user["privileges"] = getOverallUserPrivs($user["id"]);
if(preg_match('/@/', $user['unityid'])) {
$tmparr = explode('@', $user['unityid']);
$user['login'] = $tmparr[0];
}
else
$user['login'] = $user['unityid'];
$blockids = getBlockAllocationIDs($user);
$user['memberCurrentBlock'] = count($blockids);
return $user;
}
}
if($numeric)
$user = updateUserData($id, "numeric");
else
$user = updateUserData($id, "loginid", $affilid);
if(! is_null($user)) {
$blockids = getBlockAllocationIDs($user);
$user['memberCurrentBlock'] = count($blockids);
}
return $user;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUsersGroups($userid, $includeowned, $includeaffil)
///
/// \param $userid - an id from the user table
/// \param $includeowned - (optional, default=0) include groups the user owns
/// but is not in
/// \param $includeaffil - (optional, default=0) include @affiliation in name
/// of group
///
/// \return an array of the user's groups where the index is the id of the
/// group
///
/// \brief builds a array of the groups the user is member of
///
////////////////////////////////////////////////////////////////////////////////
function getUsersGroups($userid, $includeowned=0, $includeaffil=0) {
if($includeaffil) {
$query = "SELECT m.usergroupid, "
. "CONCAT(g.name, '@', a.name) AS name "
. "FROM usergroupmembers m, "
. "usergroup g, "
. "affiliation a "
. "WHERE m.userid = $userid AND "
. "m.usergroupid = g.id AND "
. "g.affiliationid = a.id";
}
else {
$query = "SELECT m.usergroupid, "
. "g.name "
. "FROM usergroupmembers m, "
. "usergroup g "
. "WHERE m.userid = $userid AND "
. "m.usergroupid = g.id";
}
$qh = doQuery($query, "101");
$groups = array();
while($row = mysql_fetch_assoc($qh)) {
$groups[$row["usergroupid"]] = $row["name"];
}
if($includeowned) {
if($includeaffil) {
$query = "SELECT g.id AS usergroupid, "
. "CONCAT(g.name, '@', a.name) AS name "
. "FROM usergroup g, "
. "affiliation a "
. "WHERE g.ownerid = $userid AND "
. "g.affiliationid = a.id";
}
else {
$query = "SELECT id AS usergroupid, "
. "name "
. "FROM usergroup "
. "WHERE ownerid = $userid";
}
$qh = doQuery($query, "101");
while($row = mysql_fetch_assoc($qh)) {
$groups[$row["usergroupid"]] = $row["name"];
}
}
uasort($groups, "sortKeepIndex");
return $groups;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUsersGroupPerms($usergroupids)
///
/// \param $usergroupids - array of user group ids
///
/// \return array of permissions where each index is the permission id and each
/// element is the name of the permission
///
/// \brief builds an array of all permissions granted to a user via that user's
/// user groups
///
////////////////////////////////////////////////////////////////////////////////
function getUsersGroupPerms($usergroupids) {
if(empty($usergroupids))
return array();
$inlist = implode(',', $usergroupids);
if($inlist == '')
return array();
$query = "SELECT DISTINCT t.id, "
. "t.name "
. "FROM usergroupprivtype t, "
. "usergrouppriv u "
. "WHERE u.usergroupid IN ($inlist) AND "
. "u.userprivtypeid = t.id "
. "ORDER BY t.name";
$perms = array();
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh))
$perms[$row['id']] = $row['name'];
return $perms;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn checkUserHasPerm($perm, $userid=0)
///
/// \param $perm - name of a user group permission
/// \param $userid (optional, default=0) - if specified, check for $userid
/// having $perm; otherwise, check logged in user
///
/// \return 1 if user has $perm, 0 otherwise
///
/// \brief checks to see if a user has been granted a permission through that
/// user's group memberships
///
////////////////////////////////////////////////////////////////////////////////
function checkUserHasPerm($perm, $userid=0) {
global $user;
if($userid == 0) {
if(is_array($user) && array_key_exists('groupperms', $user))
$perms = $user['groupperms'];
else
return 0;
}
else {
$usersgroups = getUsersGroups($userid, 1);
$perms = getUsersGroupPerms(array_keys($usersgroups));
}
if(is_array($perms) && in_array($perm, $perms))
return 1;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn updateUserData($id, $type, $affilid)
///
/// \param $id - user's unity id or id from user table
/// \param $type - (optional, default=loginid) - numericid or loginid
/// numericid is the user's numeric id; loginid is the other form (ie a unity
/// id)
/// \param $affilid - (optional, default=DEFAULT_AFFILID) - affiliation id
///
/// \return 0 if fail to update data or an array with these elements:\n
/// \b id - user's numeric unity id\n
/// \b unityid - unity ID for the user\n
/// \b affiliation - user's affiliation\n
/// \b affiliationid - user's affiliation id\n
/// \b firstname - user's first name\n
/// \b lastname - user's last name\n
/// \b email - user's preferred email address\n
/// \b IMtype - user's preferred IM protocol\n
/// \b IMid - user's IM id\n
/// \b lastupdated - datetime the information was last updated
///
/// \brief looks up the logged in user's info in ldap and updates it in the db
/// or adds it to the db
///
////////////////////////////////////////////////////////////////////////////////
function updateUserData($id, $type="loginid", $affilid=DEFAULT_AFFILID) {
global $updateUserFunc, $updateUserFuncArgs;
if($type == 'numeric') {
$query = "SELECT unityid, "
. "affiliationid "
. "FROM user "
. "WHERE id = $id";
$qh = doQuery($query, 101);
if($row = mysql_fetch_assoc($qh)) {
$id = $row['unityid'];
$type = 'loginid';
$affilid = $row['affiliationid'];
}
else
abort(1);
}
$updateFunc = $updateUserFunc[$affilid];
if(array_key_exists($affilid, $updateUserFuncArgs))
return $updateFunc($updateUserFuncArgs[$affilid], $id);
else
return $updateFunc($id);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn addUser($loginid)
///
/// \param $loginid - a login id
///
/// \return id from user table for the user, NULL if userid not in table
///
/// \brief looks up the user via LDAP and adds to DB
///
////////////////////////////////////////////////////////////////////////////////
function addUser($loginid) {
global $addUserFuncArgs, $addUserFunc;
getAffilidAndLogin($loginid, $affilid);
if(empty($affilid))
abort(11);
$addfunc = $addUserFunc[$affilid];
if(array_key_exists($affilid, $addUserFuncArgs))
return $addfunc($addUserFuncArgs[$affilid], $loginid);
else
return $addfunc($loginid);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn updateUserPrefs($userid, $preferredname, $width, $height, $bpp, $audio,
/// $mapdrives, $mapprinters, $mapserial)
///
/// \param $userid - id from user table
/// \param $preferredname - user's preferred name
/// \param $width - pixel width for rdp files
/// \param $height - pixel height for rdp files
/// \param $bpp - color depth for rdp files
/// \param $audio - 'none' or 'local' - audio preference for rdp files
/// \param $mapdrives - 0 or 1 - 1 to map local drives in rdp files
/// \param $mapprinters - 0 or 1 - 1 to map printers in rdp files
/// \param $mapserial - 0 or 1 - 1 to map serial ports in rdp files
///
/// \return number of rows affected by update (\b NOTE: this may be 0 if none
/// of the values were actually changes
///
/// \brief updates the preferences for the user
///
////////////////////////////////////////////////////////////////////////////////
function updateUserPrefs($userid, $preferredname, $width, $height, $bpp, $audio,
$mapdrives, $mapprinters, $mapserial) {
global $mysql_link_vcl;
$preferredname = mysql_real_escape_string($preferredname);
$audio = mysql_real_escape_string($audio);
$query = "UPDATE user SET "
. "preferredname = '$preferredname', "
. "width = '$width', "
. "height = '$height', "
. "bpp = $bpp, "
. "audiomode = '$audio', "
. "mapdrives = $mapdrives, "
. "mapprinters = $mapprinters, "
. "mapserial = $mapserial "
. "WHERE id = $userid";
doQuery($query, 270);
return mysql_affected_rows($mysql_link_vcl);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getOverallUserPrivs($userid)
///
/// \param $userid - an id from the user table
///
/// \return an array of privileges types that the user has somewhere in the
/// privilege tree
///
/// \brief get the privilege types that the user has somewhere in the
/// privilege tree
///
////////////////////////////////////////////////////////////////////////////////
function getOverallUserPrivs($userid) {
$query = "SELECT DISTINCT t.name "
. "FROM userprivtype t, "
. "userpriv u "
. "WHERE u.userprivtypeid = t.id AND "
. "(u.userid = $userid OR "
. "u.usergroupid IN (SELECT usergroupid "
. "FROM usergroupmembers "
. "WHERE userid = $userid) OR "
. "u.usergroupid IN (SELECT id "
. "FROM usergroup "
. "WHERE ownerid = $userid))";
$qh = doQuery($query, 107);
$privileges = array();
while($row = mysql_fetch_row($qh)) {
array_push($privileges, $row[0]);
}
return $privileges;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getBlockAllocationIDs($user)
///
/// \param $user - array of user data
///
/// \return array of block allocation ids that are currently active for $user
///
/// \brief checks to see if $user is a member of an active block allocation
/// (active also includes allocations starting within 15 minutes)
///
////////////////////////////////////////////////////////////////////////////////
function getBlockAllocationIDs($user) {
$groupids = array_keys($user['groups']);
if(empty($groupids))
return array();
$inids = implode(',', $groupids);
$query = "SELECT r.id "
. "FROM blockRequest r, "
. "blockTimes t "
. "WHERE t.blockRequestid = r.id AND "
. "r.status = 'accepted' AND "
. "t.start <= DATE_ADD(NOW(), INTERVAL 15 MINUTE) AND "
. "t.end > NOW() AND "
. "t.skip = 0 AND "
. "r.groupid IN ($inids)";
$ids = array();
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh))
$ids[] = $row['id'];
return $ids;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn isAvailable($images, $imageid, $imagerevisionid, $start, $end,
/// $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 $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
/// \param $userid - (optional) id from user table
/// \param $ignoreprivileges (optional, default=0) - 0 (false) or 1 (true) - set
/// to 1 to look for computers from any that are mapped to be able to run the
/// image; set to 0 to only look for computers from ones that are both mapped
/// and that $userid has been granted access to through the privilege tree
/// \param $forimaging - (optional, default=0) - 0 if normal reservation, 1 if
/// an imaging reservation
/// \param $ip - (optional, default='') ip address to be assigned; assumed to
/// be a server profile reservation if defined
/// \param $mac - (optional, default='') mac address to be assigned; assumed to
/// be a server profile reservation if defined
/// \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
/// -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
/// 0 if combination is not available\n
/// an integer >0 if it is available
///
/// \brief checks that the passed in arguments constitute an available request
///
////////////////////////////////////////////////////////////////////////////////
function isAvailable($images, $imageid, $imagerevisionid, $start, $end,
$requestid=0, $userid=0, $ignoreprivileges=0,
$forimaging=0, $ip='', $mac='', $skipconcurrentcheck=0) {
global $requestInfo;
$requestInfo["start"] = $start;
$requestInfo["end"] = $end;
$requestInfo["imageid"] = $imageid;
$allocatedcompids = array(0);
if(schCheckMaintenance($start, $end))
return -2;
if($requestInfo["start"] <= time()) {
$now = 1;
$nowfuture = 'now';
}
else {
$now = 0;
$nowfuture = 'future';
}
$scheduleids = getAvailableSchedules($start, $end);
$requestInfo["computers"] = array();
$requestInfo["computers"][0] = 0;
$requestInfo["images"][0] = $imageid;
# loop to check for available computers for all needed images
if(! $forimaging && $images[$imageid]["imagemetaid"] != NULL) {
$count = 1;
foreach($images[$imageid]["subimages"] as $imgid) {
$requestInfo['computers'][$count] = 0;
$requestInfo['images'][$count] = $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)) {
$query = "SELECT rq.id "
. "FROM reservation rs, "
. "request rq, "
. "serverrequest sr "
. "WHERE '$startstamp' < (rq.end + INTERVAL 900 SECOND) AND "
. "'$endstamp' > rq.start AND "
. "sr.requestid = rq.id AND "
. "rs.requestid = rq.id AND "
. "(sr.fixedIP = '$ip' OR "
. "sr.fixedMAC = '$mac') AND "
. "rq.stateid NOT IN (1,5,11,12) ";
if($requestid)
$query .= "AND rq.id != $requestid ";
$query .= "LIMIT 1";
$qh = doQuery($query, 101);
if(mysql_num_rows($qh)) {
semUnlock();
return -3;
}
}
if($requestid)
$requestData = getRequestInfo($requestid);
$vmhostcheckdone = 0;
$ignorestates = "'maintenance','vmhostinuse','hpc','failed'";
if($now)
$ignorestates .= ",'reloading','reload','timeout','inuse'";
foreach($requestInfo["images"] as $key => $imageid) {
# check for max concurrent usage of image
if(! $skipconcurrentcheck &&
$images[$imageid]['maxconcurrent'] != NULL) {
$decforedit = 0;
$compids = array();
$reloadid = getUserlistID('vclreload@Local');
$query = "SELECT rs.computerid, "
. "rq.id AS reqid "
. "FROM reservation rs, "
. "request rq "
. "WHERE '$startstamp' < (rq.end + INTERVAL 900 SECOND) AND "
. "'$endstamp' > rq.start AND "
. "rs.requestid = rq.id AND "
. "rs.imageid = $imageid AND "
. "rq.stateid NOT IN (1,5,11,12,16,17) AND "
. "rq.userid != $reloadid";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$compids[] = $row['computerid'];
if($row['reqid'] == $requestid)
$decforedit = 1;
}
$usagecnt = count($compids);
$allids = implode("','", $compids);
$query = "SELECT COUNT(bc.imageid) AS currentusage "
. "FROM blockComputers bc, "
. "blockRequest br, "
. "blockTimes bt "
. "WHERE bc.blockTimeid = bt.id AND "
. "bt.blockRequestid = br.id AND "
. "bc.imageid = $imageid AND "
. "bc.computerid NOT IN ('$allids') AND "
. "'$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;
}
if(($usagecnt + $row['currentusage'] - $decforedit) >= $images[$imageid]['maxconcurrent']) {
semUnlock();
return -1;
}
}
$platformid = getImagePlatform($imageid);
if(is_null($platformid)) {
semUnlock();
return 0;
}
# get computers $imageid maps to
$tmp = getMappedResources($imageid, "image", "computer");
if(! count($tmp)) {
semUnlock();
return 0;
}
$mappedcomputers = implode(',', $tmp);
#get computers for available schedules and platforms
$computerids = array();
$currentids = array();
$blockids = array();
$altRemoveBlockCheck = 0;
// if we are modifying a request and it is after the start time, only allow
// the scheduled computer(s) to be modified
if($requestid && datetimeToUnix($requestData["start"]) <= time()) {
$altRemoveBlockCheck = 1;
foreach($requestData["reservations"] as $key2 => $res) {
if($res["imageid"] == $imageid) {
$compid = $res["computerid"];
unset($requestData['reservations'][$key2]);
break;
}
}
array_push($computerids, $compid);
array_push($currentids, $compid);
$query = "SELECT scheduleid "
. "FROM computer "
. "WHERE id = $compid";
$qh = doQuery($query, 128);
$row = mysql_fetch_row($qh);
if(! in_array($row[0], $scheduleids)) {
semUnlock();
return 0;
}
// set $virtual to 0 so that it is defined later but skips the additional code
$virtual = 0;
}
// otherwise, build a list of computers
else {
# determine if image is bare metal or virtual
$query = "SELECT OS.installtype "
. "FROM image i "
. "LEFT JOIN OS ON (i.OSid = OS.id) "
. "WHERE i.id = $imageid";
$qh = doQuery($query, 101);
if(! ($row = mysql_fetch_assoc($qh))) {
semUnlock();
return 0;
}
if(preg_match('/(vmware)/', $row['installtype']))
$virtual = 1;
else
$virtual = 0;
# get list of available computers
if(! $ignoreprivileges) {
$resources = getUserResources(array("imageAdmin", "imageCheckOut"),
array("available"), 0, 0, $userid);
$usercomputers = implode("','", array_keys($resources["computer"]));
$usercomputers = "'$usercomputers'";
}
$alloccompids = implode(",", $allocatedcompids);
# get list of computers we can provision image to
$schedules = implode(',', $scheduleids);
#image.OSid->OS.installtype->OSinstalltype.id->provisioningOSinstalltype.provisioningid->computer.provisioningid
$query = "SELECT DISTINCT c.id, "
. "c.currentimageid, "
. "c.imagerevisionid "
. "FROM state s, "
. "image i "
. "LEFT JOIN OS o ON (o.id = i.OSid) "
. "LEFT JOIN OSinstalltype oi ON (oi.name = o.installtype) "
. "LEFT JOIN provisioningOSinstalltype poi ON (poi.OSinstalltypeid = oi.id) "
. "LEFT JOIN computer c ON (poi.provisioningid = c.provisioningid) "
. "WHERE i.id = $imageid AND "
. "c.scheduleid IN ($schedules) AND "
. "c.platformid = $platformid AND "
. "c.stateid = s.id AND "
. "s.name NOT IN ($ignorestates) AND "
. "c.RAM >= i.minram AND "
. "c.procnumber >= i.minprocnumber AND "
. "c.procspeed >= i.minprocspeed AND "
. "c.network >= i.minnetwork AND "
. "c.deleted = 0 AND "
. "(c.type != 'virtualmachine' OR c.vmhostid IS NOT NULL) AND ";
if(! $ignoreprivileges)
$query .= "c.id IN ($usercomputers) AND ";
$query .= "c.id IN ($mappedcomputers) AND "
. "c.id NOT IN ($alloccompids) "
. "ORDER BY (c.procspeed * c.procnumber) DESC, "
. "RAM DESC, "
. "network DESC";
$qh = doQuery($query, 129);
while($row = mysql_fetch_assoc($qh)) {
array_push($computerids, $row['id']);
if($row['currentimageid'] == $imageid &&
$row['imagerevisionid'] == $imagerevisionid) {
array_push($currentids, $row['id']);
}
}
# get computer ids available from block allocations
$blockdata = getAvailableBlockComputerids($imageid, $start, $end,
$allocatedcompids);
$blockids = $blockdata['compids'];
}
#remove computers from list that are already scheduled
$usedComputerids = array();
$query = "SELECT DISTINCT rs.computerid "
. "FROM reservation rs, "
. "request rq "
. "WHERE '$startstamp' < (rq.end + INTERVAL 900 SECOND) AND "
. "'$endstamp' > rq.start AND "
. "rq.id != $requestid AND "
. "rs.requestid = rq.id AND "
. "rq.stateid NOT IN (1, 5, 12)"; # deleted, failed, complete
$qh = doQuery($query, 130);
while($row = mysql_fetch_row($qh)) {
array_push($usedComputerids, $row[0]);
}
$computerids = array_diff($computerids, $usedComputerids);
$currentids = array_diff($currentids, $usedComputerids);
$blockids = array_diff($blockids, $usedComputerids);
// if modifying a reservation and $computerids is now empty, return 0
if($requestid && empty($computerids)) {
semUnlock();
return 0;
}
# remove computers from list that are allocated to block allocations
if($altRemoveBlockCheck) {
if(editRequestBlockCheck($computerids[0], $imageid, $start, $end)) {
semUnlock();
return 0;
}
}
elseif(! count($blockids)) { # && ! $altRemoveBlockCheck
$usedBlockCompids = getUsedBlockComputerids($start, $end);
$computerids = array_diff($computerids, $usedBlockCompids);
$currentids = array_diff($currentids, $usedBlockCompids);
}
if($virtual && empty($currentids) && ! empty($computerids)) {
# find computers whose hosts can handle the required RAM - we don't
# need to do this if there are VMs with the requested image already
# available because they would already fit within the host's available
# RAM
if(! $vmhostcheckdone) {
$vmhostcheckdone = 1;
$query = "DROP TEMPORARY TABLE IF EXISTS VMhostCheck";
doQuery($query, 101);
$query = "CREATE TEMPORARY TABLE VMhostCheck ( "
. "RAM mediumint unsigned NOT NULL, "
. "allocRAM mediumint unsigned NOT NULL, "
. "vmhostid smallint unsigned NOT NULL "
. ") ENGINE=MEMORY";
doQuery($query, 101);
$query = "INSERT INTO VMhostCheck "
. "SELECT c.RAM, "
. "SUM(i.minram), "
. "v.id "
. "FROM vmhost v "
. "LEFT JOIN computer c ON (v.computerid = c.id) "
. "LEFT JOIN computer c2 ON (v.id = c2.vmhostid) "
. "LEFT JOIN image i ON (c2.currentimageid = i.id) "
. "WHERE c.stateid = 20 "
. "GROUP BY c.id";
doQuery($query, 101);
}
$inids = implode(',', $computerids);
// if want overbooking, modify the last part of the WHERE clause
$query = "SELECT c.id "
. "FROM VMhostCheck v "
. "LEFT JOIN computer c ON (v.vmhostid = c.vmhostid) "
. "LEFT JOIN image i ON (c.currentimageid = i.id) "
. "WHERE c.id IN ($inids) AND "
. "(v.allocRAM - i.minram + {$images[$imageid]['minram']}) < v.RAM "
. "ORDER BY (c.procspeed * c.procnumber) DESC, "
. "c.RAM DESC, "
. "c.network DESC";
$qh = doQuery($query, 101);
$newcompids = array();
while($row = mysql_fetch_assoc($qh))
$newcompids[] = $row['id'];
$computerids = $newcompids;
}
# remove any recently reserved computers that could have been an
# undetected failure
$failedids = getPossibleRecentFailures($userid, $imageid);
$shortened = 0;
if(! empty($failedids)) {
$origcomputerids = $computerids;
$origcurrentids = $currentids;
$origblockids = $blockids;
if(! empty($computerids)) {
$testids = array_diff($computerids, $failedids);
if(! empty($testids)) {
$shortened = 1;
$computerids = $testids;
$currentids = array_diff($currentids, $failedids);
}
}
if(! empty($blockids)) {
$testids = array_diff($blockids, $failedids);
if(! empty($testids)) {
$shortened = 1;
$blockids = $testids;
}
}
}
# allocate a computer
$comparr = allocComputer($blockids, $currentids, $computerids,
$startstamp, $nowfuture);
if(empty($comparr) && $shortened)
$comparr = allocComputer($origblockids, $origcurrentids,
$origcomputerids, $startstamp, $nowfuture);
if(empty($comparr)) {
semUnlock();
return 0;
}
$requestInfo["computers"][$key] = $comparr['compid'];
$requestInfo["mgmtnodes"][$key] = $comparr['mgmtid'];
$requestInfo["loaded"][$key] = $comparr['loaded'];
$requestInfo['fromblock'][$key] = $comparr['fromblock'];
if($comparr['fromblock'])
$requestInfo['blockdata'][$key] = $blockdata[$comparr['compid']];
array_push($allocatedcompids, $comparr['compid']);
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getAvailableSchedules($start, $end)
///
/// \param $start - start time in unix timestamp form
/// \param $end - end time in unix timestamp form
///
/// \return array of schedule ids
///
/// \brief gets schedules available for given start and end time
///
////////////////////////////////////////////////////////////////////////////////
function getAvailableSchedules($start, $end) {
# get list of schedules
$starttime = minuteOfWeek($start);
$endtime = minuteOfWeek($end);
# request is within a single week
if(weekOfYear($start) == weekOfYear($end)) {
$query = "SELECT scheduleid "
. "FROM scheduletimes "
. "WHERE start <= $starttime AND "
. "end >= $endtime";
}
# request covers at least a week's worth of time
elseif($end - $start >= SECINDAY * 7) {
$query = "SELECT scheduleid "
. "FROM scheduletimes "
. "WHERE start = 0 AND "
. "end = 10080";
}
# request starts in one week and ends in the following week
else {
$query = "SELECT s1.scheduleid "
. "FROM scheduletimes s1, "
. "scheduletimes s2 "
. "WHERE s1.scheduleid = s2.scheduleid AND "
. "s1.start <= $starttime AND "
. "s1.end = 10080 AND "
. "s2.start = 0 AND "
. "s2.end >= $endtime";
}
$scheduleids = array();
$qh = doQuery($query, 127);
while($row = mysql_fetch_row($qh)) {
array_push($scheduleids, $row[0]);
}
return $scheduleids;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getImagePlatform($imageid)
///
/// \param $imageid - id of an image
///
/// \return id of image's platform
///
/// \brief gets the platformid for $imageid
///
////////////////////////////////////////////////////////////////////////////////
function getImagePlatform($imageid) {
$query = "SELECT platformid FROM image WHERE id = $imageid";
$qh = doQuery($query, 125);
if(! $row = mysql_fetch_assoc($qh))
return NULL;
return $row['platformid'];
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn schCheckMaintenance($start, $end)
///
/// \param $start - unix timestamp for start of reservation
/// \param $end - unix timestamp for end of reservation
///
/// \return true if time window conflicts with maintenance window; false if not
///
/// \brief checks to see if the specified window conflicts with a maintenance
/// window
///
////////////////////////////////////////////////////////////////////////////////
function schCheckMaintenance($start, $end) {
$startdt = unixToDatetime($start);
$enddt = unixToDatetime($end);
$query = "SELECT id "
. "FROM sitemaintenance "
. "WHERE ((allowreservations = 0 AND "
. "(('$enddt' > start) AND ('$startdt' < end))) OR "
. "(('$startdt' > (start - INTERVAL 30 MINUTE)) AND ('$startdt' < end))) AND "
. "end > NOW()";
$qh = doQuery($query, 101);
if($row = mysql_fetch_row($qh))
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn allocComputer($blockids, $currentids, $computerids, $start,
/// $nowfuture)
///
/// \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 $nowfuture - "now" or "future"
///
/// \return empty array if failed to allocate a computer; array with these keys
/// on success:\n
/// \b compid - id of computer\n
/// \b mgmtid - id of management node for computer\n
/// \b loaded - 0 or 1 - whether or not computer is loaded with desired image
///
/// \brief determines a computer to use from $blockids, $currentids,
/// and $computerids, looking at the arrays in that order and
/// tries to allocate a management node for it
///
////////////////////////////////////////////////////////////////////////////////
function allocComputer($blockids, $currentids, $computerids, $start,
$nowfuture) {
$ret = array();
if(SCHEDULER_ALLOCATE_RANDOM_COMPUTER) {
shuffle($blockids);
shuffle($currentids);
shuffle($computerids);
}
foreach($blockids as $compid) {
$mgmtnodeid = findManagementNode($compid, $start, $nowfuture);
if($mgmtnodeid == 0)
continue;
$ret['compid'] = $compid;
$ret['mgmtid'] = $mgmtnodeid;
$ret['loaded'] = 1;
$ret['fromblock'] = 1;
return $ret;
}
foreach($currentids as $compid) {
$mgmtnodeid = findManagementNode($compid, $start, $nowfuture);
if($mgmtnodeid == 0)
continue;
$ret['compid'] = $compid;
$ret['mgmtid'] = $mgmtnodeid;
$ret['loaded'] = 1;
$ret['fromblock'] = 0;
return $ret;
}
foreach($computerids as $compid) {
$mgmtnodeid = findManagementNode($compid, $start, $nowfuture);
if($mgmtnodeid == 0)
continue;
$ret['compid'] = $compid;
$ret['mgmtid'] = $mgmtnodeid;
$ret['loaded'] = 0;
$ret['fromblock'] = 0;
return $ret;
}
return $ret;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getPossibleRecentFailures($userid, $imageid)
///
/// \param $userid - check log data for this user; if $userid = 0, check for
/// currently logged in user
/// \param $imageid - check log data for this image
///
/// \return array of computerids that may have recently given the user a problem
///
/// \brief checks for recent reservations by the user that were very short and
/// within a recent time frame in case there was a computer that gave a problem
/// that the backend did not pick up
///
////////////////////////////////////////////////////////////////////////////////
function getPossibleRecentFailures($userid, $imageid) {
if($userid == 0) {
global $user;
$userid = $user['id'];
}
$comps = array();
$query = "SELECT s.computerid "
. "FROM log l "
. "LEFT JOIN sublog s ON (s.logid = l.id) "
. "WHERE l.start > (NOW() - INTERVAL 90 MINUTE) AND "
. "l.finalend < NOW() AND "
. "l.userid = $userid AND "
. "l.imageid = $imageid AND "
. "l.wasavailable = 1 AND "
. "l.ending != 'failed'";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh))
$comps[] = $row['computerid'];
return $comps;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \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)
/// \param $resourcetype2 - type of resource $resourcesubid maps to
///
/// \return an array of resource ids of type $resourcetype2
///
/// \brief gets a list of resources of type $resourcetype2 that $resourcesubid
/// of type $resourcetype1 maps to based on the resourcemap table
///
////////////////////////////////////////////////////////////////////////////////
function getMappedResources($resourcesubid, $resourcetype1, $resourcetype2) {
if(! is_numeric($resourcetype1))
$resourcetype1 = getResourceTypeID($resourcetype1);
if(! is_numeric($resourcetype2))
$resourcetype2 = getResourceTypeID($resourcetype2);
# get $resourcesubid's resource id
$query = "SELECT id "
. "FROM resource "
. "WHERE subid = $resourcesubid AND "
. "resourcetypeid = $resourcetype1";
$qh = doQuery($query, 101);
$row = mysql_fetch_row($qh);
$resourceid = $row[0];
# get groups $resourceid is in
$resourcegroupids = array();
$query = "SELECT resourcegroupid "
. "FROM resourcegroupmembers "
. "WHERE resourceid = $resourceid";
$qh = doQuery($query, 101);
while($row = mysql_fetch_row($qh)) {
array_push($resourcegroupids, $row[0]);
}
# get $resourcetype2 groups that $resourcegroupids map to
if(! count($resourcegroupids))
return array();
$inlist = implode(',', $resourcegroupids);
$type2groupids = array();
# get all mappings from resourcemap table where $resourcetype1 ==
# resourcemap.resourcetypeid1
$query = "SELECT resourcegroupid2 "
. "FROM resourcemap "
. "WHERE resourcegroupid1 IN ($inlist) AND "
. "resourcetypeid1 = $resourcetype1 AND "
. "resourcetypeid2 = $resourcetype2";
$qh = doQuery($query, 101);
while($row = mysql_fetch_row($qh)) {
array_push($type2groupids, $row[0]);
}
# get all mappings from resourcemap table where $resourcetype1 ==
# resourcemap.resourcetypeid2
$query = "SELECT resourcegroupid1 "
. "FROM resourcemap "
. "WHERE resourcegroupid2 IN ($inlist) AND "
. "resourcetypeid2 = $resourcetype1 AND "
. "resourcetypeid1 = $resourcetype2";
$qh = doQuery($query, 101);
while($row = mysql_fetch_row($qh)) {
array_push($type2groupids, $row[0]);
}
# get $resourcetype2 items in $type2groupids groups
if(! count($type2groupids))
return array();
$inlist = implode(',', $type2groupids);
$mappedresources = array();
$query = "SELECT r.subid "
. "FROM resource r, "
. "resourcegroupmembers m "
. "WHERE m.resourcegroupid IN ($inlist) AND "
. "m.resourceid = r.id";
$qh = doQuery($query, 101);
while($row = mysql_fetch_row($qh)) {
array_push($mappedresources, $row[0]);
}
return $mappedresources;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn checkOverlap($start, $end, $max, $requestid)
///
/// \param $start - unix timestamp for start of reservation
/// \param $end - unix timestamp for end of reservation
/// \param $max - max allowed overlapping reservations
/// \param $requestid - (optional) a requestid to ignore when checking for an
/// overlap; use this when changing an existing request
///
/// \return 0 if user doesn't have a reservation overlapping the time period
/// between $start and $end; 1 if the user does
///
/// \brief checks for a user having an overlapping reservation with the
/// specified time period
///
////////////////////////////////////////////////////////////////////////////////
function checkOverlap($start, $end, $max, $requestid=0) {
global $user;
$requests = getUserRequests("all");
$count = 0;
if($max > 0)
$max--;
foreach(array_keys($requests) as $id) {
if(! (($requests[$id]["currstateid"] == 12 ||
$requests[$id]["currstateid"] == 14) &&
$requests[$id]["laststateid"] == 11) &&
$requests[$id]["currstateid"] != 5 &&
$requests[$id]["id"] != $requestid &&
($start < datetimeToUnix($requests[$id]["end"]) &&
$end > datetimeToUnix($requests[$id]["start"])) &&
$requests[$id]['serverowner'] == 1) {
$count++;
if($count > $max)
return 1;
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn editRequestBlockCheck($compid, $imageid, $start, $end)
///
/// \param $compid - id of computer to check
/// \param $imageid - id of image being checked
/// \param $start - start of time period in unix timestamp format
/// \param $end - end of time period in unix timestamp format
///
/// \return 1 if time period overlaps with a block allocation unavailable to the
/// logged in user; 0 if not
///
/// \brief checks to see if $compid is part of a block allocation that the
/// current user is not part of or is set for a different image than what the
/// user is currently using on the computer
///
////////////////////////////////////////////////////////////////////////////////
function editRequestBlockCheck($compid, $imageid, $start, $end) {
global $user;
$groupids = implode(',', array_keys($user['groups']));
if(! count($user['groups']))
$groupids = "''";
$startdt = unixToDatetime($start);
$enddt = unixToDatetime($end);
$query = "SELECT bc.computerid "
. "FROM blockComputers bc, "
. "blockTimes bt, "
. "blockRequest r "
. "WHERE bc.blockTimeid = bt.id AND "
. "bt.blockRequestid = r.id AND "
. "bc.computerid = $compid AND "
. "(bt.start - INTERVAL 15 MINUTE) < '$enddt' AND "
. "bt.end > '$startdt' AND "
. "(r.groupid NOT IN ($groupids) OR "
. "r.imageid != $imageid) AND "
. "r.status = 'accepted'";
$qh = doQuery($query, 101);
return(mysql_num_rows($qh));
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getReloadStartTime()
///
/// \return unix timestamp
///
/// \brief determines the nearest 15 minute increment of an hour that is less
/// than the current time
///
////////////////////////////////////////////////////////////////////////////////
function getReloadStartTime() {
$nowArr = getdate();
if($nowArr["minutes"] == 0)
$subtract = 0;
elseif($nowArr["minutes"] < 15)
$subtract = $nowArr["minutes"] * 60;
elseif($nowArr["minutes"] < 30)
$subtract = ($nowArr["minutes"] - 15) * 60;
elseif($nowArr["minutes"] < 45)
$subtract = ($nowArr["minutes"] - 30) * 60;
elseif($nowArr["minutes"] < 60)
$subtract = ($nowArr["minutes"] - 45) * 60;
$start = time() - $subtract;
$start -= $start % 60;
return $start;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getMaxOverlap($userid)
///
/// \param $userid - id from user table
///
/// \return max number of allowed overlapping reservations for user
///
/// \brief determines how many overlapping reservations $user can have based on
/// the groups $user is a member of
///
////////////////////////////////////////////////////////////////////////////////
function getMaxOverlap($userid) {
$query = "SELECT u.overlapResCount "
. "FROM usergroup u, "
. "usergroupmembers m "
. "WHERE m.usergroupid = u.id AND "
. "m.userid = $userid "
. "ORDER BY u.overlapResCount DESC "
. "LIMIT 1";
$qh = doQuery($query, 101);
if($row = mysql_fetch_assoc($qh))
return $row['overlapResCount'];
else
return 1;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn addRequest($forimaging, $revisionid)
///
/// \param $forimaging - (optional) 0 if a normal request, 1 if a request for
/// creating a new image
/// \param $revisionid - (optional) desired revision id of the image
///
/// \return id from request table that corresponds to the added entry
///
/// \brief adds an entry to the request and reservation tables
///
////////////////////////////////////////////////////////////////////////////////
function addRequest($forimaging=0, $revisionid=array()) {
global $requestInfo, $user;
$startstamp = unixToDatetime($requestInfo["start"]);
$endstamp = unixToDatetime($requestInfo["end"]);
$now = time();
if($requestInfo["start"] <= $now) {
$start = unixToDatetime($now);
$nowfuture = "now";
}
else {
$start = $startstamp;
$nowfuture = "future";
}
addLogEntry($nowfuture, $start, $endstamp, 1, $requestInfo["imageid"]);
$qh = doQuery("SELECT LAST_INSERT_ID() FROM log", 131);
if(! $row = mysql_fetch_row($qh)) {
abort(132);
}
$logid = $row[0];
$query = "INSERT INTO changelog "
. "(logid, "
. "start, "
. "end, "
. "timestamp) "
. "VALUES "
. "($logid, "
. "'$start', "
. "'$endstamp', "
. "NOW())";
doQuery($query, 136);
# add single entry to request table
$query = "INSERT INTO request "
. "(stateid, "
. "userid, "
. "laststateid, "
. "logid, "
. "forimaging, "
. "start, "
. "end, "
. "daterequested) "
. "VALUES "
. "(13, "
. "{$user['id']}, "
. "13, "
. "$logid, "
. "$forimaging, "
. "'$startstamp', "
. "'$endstamp', "
. "NOW())";
$qh = doQuery($query, 136);
$qh = doQuery("SELECT LAST_INSERT_ID() FROM request", 134);
if(! $row = mysql_fetch_row($qh)) {
abort(135);
}
$requestid = $row[0];
# add requestid to log entry
$query = "UPDATE log "
. "SET requestid = $requestid "
. "WHERE id = $logid";
doQuery($query, 101);
# add an entry to the reservation table for each image
# NOTE: make sure parent image is the first entry we add
# so that it has the lowest reservationid
foreach($requestInfo["images"] as $key => $imageid) {
if(array_key_exists($imageid, $revisionid) &&
! empty($revisionid[$imageid]))
$imagerevisionid = array_shift($revisionid[$imageid]);
else
$imagerevisionid = getProductionRevisionid($imageid);
$computerid = $requestInfo["computers"][$key];
$mgmtnodeid = $requestInfo['mgmtnodes'][$key];
$fromblock = $requestInfo['fromblock'][$key];
if($fromblock)
$blockdata = $requestInfo['blockdata'][$key];
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);
}
// release semaphore lock
semUnlock();
return $requestid;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn simpleAddRequest($compid, $imageid, $revisionid, $start, $end,
/// $stateid, $userid) {
///
/// \param $compid - a computer id
/// \param $imageid - an iamge id
/// \param $revisionid - revisionid for $imageid
/// \param $start - starting time in datetime format
/// \param $end - ending time in datetime format
/// \param $stateid - state for request
/// \param $userid - userid for request
///
/// \return id for the request or 0 on failure
///
/// \brief adds an entry to the request and reservation tables
///
////////////////////////////////////////////////////////////////////////////////
function simpleAddRequest($compid, $imageid, $revisionid, $start, $end,
$stateid, $userid) {
$mgmtnodeid = findManagementNode($compid, $start, 'now');
if($mgmtnodeid == 0)
return 0;
$query = "INSERT INTO request "
. "(stateid, "
. "userid, "
. "laststateid, "
. "start, "
. "end, "
. "daterequested) "
. "VALUES "
. "($stateid, "
. "$userid, "
. "$stateid, "
. "'$start', "
. "'$end', "
. "NOW())";
doQuery($query, 101);
$requestid = dbLastInsertID();
if($requestid == 0)
abort(135);
# add an entry to the reservation table for each image
$query = "INSERT INTO reservation "
. "(requestid, "
. "computerid, "
. "imageid, "
. "imagerevisionid, "
. "managementnodeid) "
. "VALUES "
. "($requestid, "
. "$compid, "
. "$imageid, "
. "$revisionid, "
. "$mgmtnodeid)";
doQuery($query, 101);
$testid = dbLastInsertID();
if($testid == 0)
abort(135);
return $requestid;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn findManagementNode($compid, $start, $nowfuture)
///
/// \param $compid - a computer id
/// \param $start - start time for the reservation (datetime format)
/// \param $nowfuture - type of reservation - "now" or "future"
///
/// \return a management node id
///
/// \brief finds a management node that can handle $compid, if none found,
/// returns 0
///
////////////////////////////////////////////////////////////////////////////////
function findManagementNode($compid, $start, $nowfuture) {
global $HTMLheader;
$allmgmtnodes = array_keys(getManagementNodes($nowfuture));
$mapped = getMappedResources($compid, "computer", "managementnode");
$usablemgmtnodes = array_intersect($allmgmtnodes, $mapped);
$mgmtnodecnt = array();
foreach($usablemgmtnodes as $id) {
$mgmtnodecnt[$id] = 0;
}
if(! count($usablemgmtnodes))
return 0;
$inlist = implode(',', $usablemgmtnodes);
$mystart = datetimeToUnix($start);
$start = unixToDatetime($mystart - 1800);
$end = unixToDatetime($mystart + 1800);
$query = "SELECT DISTINCT COUNT(rs.managementnodeid) AS count, "
. "rs.managementnodeid AS mnid "
. "FROM reservation rs, "
. "request rq "
. "WHERE rs.managementnodeid IN ($inlist) AND "
. "rs.requestid = rq.id AND "
. "rq.start > '$start' AND "
. "rq.start < '$end' "
. "GROUP BY rs.managementnodeid "
. "ORDER BY count";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$mgmtnodecnt[$row["mnid"]] = $row["count"];
}
uasort($mgmtnodecnt, "sortKeepIndex");
$keys = array_keys($mgmtnodecnt);
return array_shift($keys);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getRequestInfo($id, $returnNULL)
///
/// \param $id - id of request
/// \param $returnNULL - (optional, default=0) return NULL if reservation no
/// longer exists
///
/// \return an array containing the following elements:\n
/// \b stateid - stateid of the request\n
/// \b laststateid - laststateid of the request\n
/// \b userid - id from the db of the user\n
/// \b start - start of request\n
/// \b end - end of request\n
/// \b daterequested - date request was made\n
/// \b datemodified - date request was last modified\n
/// \b id - id of this request\n
/// \b logid - id from log table\n
/// \b test - test flag\n
/// \b forimaging - 0 if request is normal, 1 if it is for imaging\n
/// \b serverrequest - 0 if request is normal, 1 if it is a server request\n
/// \b servername - name of server if server request\n
/// \b admingroupid - id of admin user group if server request\n
/// \b logingroupid - id of login user group if server request\n
/// \b fixedIP - possible fixed IP address if server request\n
/// \b fixedMAC - possible fixed MAC address if server request\n\n
/// an array of reservations associated with the request whose key is
/// 'reservations', each with the following items:\n
/// \b imageid - id of the image\n
/// \b imagerevisionid - id of the image revision\n
/// \b production - image revision production flag (0 or 1)\n
/// \b image - name of the image\n
/// \b prettyimage - pretty name of the image\n
/// \b OS - name of the os\n
/// \b OStype - type of the os\n
/// \b computerid - id of the computer\n
/// \b reservationid - id of the corresponding reservation\n
/// \b reservedIP - ip address of reserved computer\n
/// \b hostname - hostname of reserved computer\n
/// \b forcheckout - whether or not the image is intended for checkout\n
/// \b password - password for this computer\n
/// \b connectIP - IP to which user will connect\n
/// \b connectport - port to which user will connect\n
/// \b remoteIP - IP of remote user\n\n
/// an array of arrays of passwords whose key is 'passwds', with the next key
/// being the reservationid and the elements being the userid as a key and that
/// user's password as the value
///
/// \brief creates an array with info about request $id
///
////////////////////////////////////////////////////////////////////////////////
function getRequestInfo($id, $returnNULL=0) {
global $printedHTMLheader, $HTMLheader;
if(empty($id))
abort(9);
$query = "SELECT stateid, "
. "laststateid, "
. "userid, "
. "start, "
. "end, "
. "daterequested, "
. "datemodified, "
. "logid, "
. "test, "
. "forimaging "
. "FROM request "
. "WHERE id = $id";
$qh = doQuery($query, 165);
if(! ($data = mysql_fetch_assoc($qh))) {
if($returnNULL)
return NULL;
# FIXME handle XMLRPC cases
if(! $printedHTMLheader)
print $HTMLheader;
print _("
OOPS! - Reservation Has Expired
\n");
print _("The selected reservation is no longer available. Go to ");
print "";
print _("New Reservations to request a new reservation or to ");
print "";
print _("Current Reservations to select another one that is available.");
printHTMLFooter();
dbDisconnect();
exit;
}
$data["id"] = $id;
$query = "SELECT rs.imageid, "
. "rs.imagerevisionid, "
. "rs.managementnodeid, "
. "ir.production, "
. "i.name AS image, "
. "i.prettyname AS prettyimage, "
. "o.prettyname AS OS, "
. "o.type AS OStype, "
. "rs.computerid, "
. "rs.id AS reservationid, "
. "c.IPaddress AS reservedIP, "
. "c.hostname, "
. "i.forcheckout, "
. "rs.pw AS password, "
. "rs.connectIP, "
. "rs.connectport, "
. "rs.remoteIP "
. "FROM reservation rs, "
. "image i, "
. "imagerevision ir, "
. "OS o, "
. "computer c "
. "WHERE rs.requestid = $id AND "
. "rs.imageid = i.id AND "
. "rs.imagerevisionid = ir.id AND "
. "i.OSid = o.id AND "
. "rs.computerid = c.id "
. "ORDER BY rs.id";
$qh = doQuery($query, 101);
$data["reservations"] = array();
$data['passwds'] = array();
$resids = array();
while($row = mysql_fetch_assoc($qh)) {
array_push($data["reservations"], $row);
$resids[] = $row['reservationid'];
$data['passwds'][$row['reservationid']][$data['userid']] = $row['password'];
}
$query = "SELECT id, "
. "name, "
. "admingroupid, "
. "logingroupid, "
. "fixedIP, "
. "fixedMAC "
. "FROM serverrequest "
. "WHERE requestid = $id";
$qh = doQuery($query, 101);
if($row = mysql_fetch_assoc($qh)) {
$data['serverrequest'] = 1;
$data['servername'] = $row['name'];
$data['admingroupid'] = $row['admingroupid'];
$data['logingroupid'] = $row['logingroupid'];
$data['fixedIP'] = $row['fixedIP'];
$data['fixedMAC'] = $row['fixedMAC'];
$inids = implode(',', $resids);
$query = "SELECT reservationid, "
. "userid, "
. "password "
. "FROM reservationaccounts "
. "WHERE reservationid IN ($inids)";
$qh = doQuery($query);
while($row = mysql_fetch_assoc($qh))
$data['passwds'][$row['reservationid']][$row['userid']] = $row['password'];
}
else
$data['serverrequest'] = 0;
return $data;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn updateRequest($requestid)
///
/// \param $requestid - the id of the request to be updated
///
/// \brief updates an entry to the request and reservation tables
///
////////////////////////////////////////////////////////////////////////////////
function updateRequest($requestid) {
global $requestInfo;
$startstamp = unixToDatetime($requestInfo["start"]);
$endstamp = unixToDatetime($requestInfo["end"]);
if($requestInfo["start"] <= time())
$nowfuture = "now";
else
$nowfuture = "future";
$query = "SELECT logid FROM request WHERE id = $requestid";
$qh = doQuery($query, 146);
if(! $row = mysql_fetch_row($qh)) {
abort(148);
}
$logid = $row[0];
$query = "UPDATE request "
. "SET start = '$startstamp', "
. "end = '$endstamp', "
. "datemodified = NOW() "
. "WHERE id = $requestid";
doQuery($query, 101);
if($nowfuture == 'now') {
addChangeLogEntry($logid, NULL, $endstamp, $startstamp, NULL, NULL, 1);
return;
}
$requestData = getRequestInfo($requestid);
foreach($requestInfo["images"] as $key => $imgid) {
foreach($requestData["reservations"] as $key2 => $res) {
if($res["imageid"] == $imgid) {
$oldCompid = $res["computerid"];
unset($requestData['reservations'][$key2]);
break;
}
}
$computerid = $requestInfo["computers"][$key];
$mgmtnodeid = $requestInfo['mgmtnodes'][$key];
$query = "UPDATE reservation "
. "SET computerid = $computerid, "
. "managementnodeid = $mgmtnodeid "
. "WHERE requestid = $requestid AND "
. "imageid = $imgid AND "
. "computerid = $oldCompid";
doQuery($query, 147);
addChangeLogEntry($logid, NULL, $endstamp, $startstamp, $computerid, NULL,
1);
$query = "UPDATE sublog "
. "SET computerid = $computerid "
. "WHERE logid = $logid AND "
. "imageid = $imgid AND "
. "computerid = $oldCompid";
doQuery($query, 101);
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn deleteRequest($request)
///
/// \param $request - an array from getRequestInfo
///
/// \brief removes a request from the request and reservation tables
///
////////////////////////////////////////////////////////////////////////////////
function deleteRequest($request) {
# new - 13
# deleted - 1
# complete - 12
# reserved - 3
# inuse - 8
# pending - 14
# timeout - 11
$now = time();
if(datetimeToUnix($request["start"]) < $now) {
# current: new, last: none OR
# current: pending, last: new
if($request["stateid"] == 13 ||
($request["stateid"] == 14 && $request["laststateid"] == 13)) {
$query = "UPDATE request "
. "SET stateid = 1, "
. "laststateid = 3 "
. "WHERE id = {$request['id']}";
}
# current: reserved, last: new OR
# current: pending, last: reserved
elseif(($request["stateid"] == 3 && $request["laststateid"] == 13) ||
($request["stateid"] == 14 && $request["laststateid"] == 3)) {
$query = "UPDATE request "
. "SET stateid = 1, "
. "laststateid = 3 "
. "WHERE id = {$request['id']}";
}
# current: inuse, last: reserved OR
# current: pending, last: inuse
elseif(($request["stateid"] == 8 && $request["laststateid"] == 3) ||
($request["stateid"] == 14 && $request["laststateid"] == 8)) {
$query = "UPDATE request "
. "SET stateid = 1, "
. "laststateid = 8 "
. "WHERE id = {$request['id']}";
}
# shouldn't happen, but if current: pending, set to deleted or
// if not current: pending, set laststate to current state and
# current state to deleted
else {
if($request["stateid"] == 14) {
$query = "UPDATE request "
. "SET stateid = 1 "
. "WHERE id = {$request['id']}";
}
else {
# somehow a user submitted a deleteRequest where the current
# stateid was empty
if(! is_numeric($request["stateid"]) || $request["stateid"] < 0)
$request["stateid"] = 1;
$query = "UPDATE request "
. "SET stateid = 1, "
. "laststateid = {$request['stateid']} "
. "WHERE id = {$request['id']}";
}
}
$qh = doQuery($query, 150);
addChangeLogEntry($request["logid"], NULL, unixToDatetime($now), NULL,
NULL, "released");
return;
}
if($request['serverrequest']) {
$query = "DELETE FROM serverrequest WHERE requestid = {$request['id']}";
$qh = doQuery($query, 152);
}
$query = "DELETE FROM request WHERE id = {$request['id']}";
$qh = doQuery($query, 153);
$query = "DELETE FROM reservation WHERE requestid = {$request['id']}";
doQuery($query, 154);
addChangeLogEntry($request["logid"], NULL, NULL, NULL, NULL, "deleted");
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn moveReservationsOffComputer($compid, $count)
///
/// \param $compid - (optional) id of computer from which to move reservations
/// \param $count - (optional) number of reservations to move, defaults to
/// all of them
///
/// \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 a $compid - if $compid is not
/// given, removes all reservations from the computer with the least number
///
////////////////////////////////////////////////////////////////////////////////
function moveReservationsOffComputer($compid=0, $count=0) {
global $requestInfo, $user;
$resInfo = array();
$checkstart = unixToDatetime(time() + 180);
if($compid == 0) {
$resources = getUserResources(array("imageAdmin", "imageCheckOut"),
array("available"), 0, 0);
$computers = implode("','", array_keys($resources["computer"]));
$computers = "'$computers'";
$query = "SELECT DISTINCT COUNT(rs.id) AS reservations, "
. "rs.computerid "
. "FROM reservation rs, "
. "request rq "
. "WHERE rq.start > '$checkstart' AND "
. "rs.computerid IN ($computers) "
. "GROUP BY computerid "
. "ORDER BY reservations "
. "LIMIT 1";
$qh = doQuery($query, 101);
if($row = mysql_fetch_assoc($qh))
$compid = $row["computerid"];
else
return -1;
}
# get all reservation info for $compid
$query = "SELECT rs.id, "
. "rs.requestid, "
. "rs.imageid, "
. "rs.imagerevisionid, "
. "rq.logid, "
. "rq.userid, "
. "rq.start, "
. "rq.end "
. "FROM reservation rs, "
. "request rq "
. "WHERE rs.computerid = $compid AND "
. "rs.requestid = rq.id AND "
. "rq.start > '$checkstart' AND "
. "rq.stateid NOT IN (1, 5, 11, 12) "
. "ORDER BY rq.start";
if($count)
$query .= " LIMIT $count";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$resInfo[$row["id"]] = $row;
}
if(! count($resInfo))
return -1;
$images = getImages();
$allmovable = 1;
foreach($resInfo as $res) {
$rc = isAvailable($images, $res["imageid"], $res['imagerevisionid'],
datetimeToUnix($res["start"]), datetimeToUnix($res["end"]), 0,
$res["userid"]);
if($rc < 1) {
$allmovable = 0;
break;
}
}
if(! $allmovable)
return 0;
foreach($resInfo as $res) {
$rc = isAvailable($images, $res["imageid"], $res['imagerevisionid'],
datetimeToUnix($res["start"]), datetimeToUnix($res["end"]), 0,
$res["userid"]);
if($rc > 0) {
$newcompid = array_shift($requestInfo["computers"]);
# get mgmt node for computer
$mgmtnodeid = findManagementNode($newcompid, $res['start'], 'future');
# update mgmt node and computer in reservation table
$query = "UPDATE reservation "
. "SET computerid = $newcompid, "
. "managementnodeid = $mgmtnodeid "
. "WHERE id = {$res['id']}";
doQuery($query, 101);
# add changelog entry
addChangeLogEntry($res['logid'], NULL, NULL, NULL, $newcompid);
# update sublog entry
$query = "UPDATE sublog "
. "SET computerid = $newcompid "
. "WHERE logid = {$res['logid']} AND "
. "computerid = $compid";
doQuery($query, 101);
}
else
return 0;
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getCompFinalReservationTime($compid)
///
/// \param $compid - a computer id
///
/// \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) {
$end = 0;
$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) "
. "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.computerid = $compid AND "
. "c.blockTimeid = t.id AND "
. "t.end > NOW() "
. "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 getUserRequests($type, $id)
///
/// \param $type - "normal", "forimaging", or "all"
/// \param $id - (optional) user's id from userlist table
///
/// \return an array of user's requests; the array has the following elements
/// for each entry where forcheckout == 1 for the image:\n
/// \b id - id of the request\n
/// \b userid - id of user owning request\n
/// \b imageid - id of requested image\n
/// \b imagerevisionid - revision id of requested image\n
/// \b image - name of requested image\n
/// \b prettyimage - pretty name of requested image\n
/// \b OS - name of the requested os\n
/// \b OSinstalltype - installtype for OS\n
/// \b start - start time of request\n
/// \b end - end time of request\n
/// \b daterequested - date request was made\n
/// \b currstateid - current stateid of request\n
/// \b laststateid - last stateid of request\n
/// \b forimaging - 0 if an normal request, 1 if imaging request\n
/// \b forcheckout - 1 if image is available for reservations, 0 if not\n
/// \b test - test flag - 0 or 1\n
/// \b longterm - 1 if request length is > 24 hours\n
/// \b server - 1 if corresponding entry in serverprofiles\n
/// \b serverowner - 1 user owns the reservation, 0 if not\n
/// \b resid - id of primary reservation\n
/// \b compimageid - currentimageid for primary computer\n
/// \b computerstateid - current stateid of primary computer\n
/// \b computerid - id of primary computer\n
/// \b IPaddress - IP address of primary computer\n
/// \b comptype - type of primary computer\n
/// \b vmhostid - if VM, id of host's entry in vmhost table, NULL otherwise\n
/// the following additional items if a server request (values will be NULL
/// if not a server request), some values can be NULL:\n
/// \b servername - name of server request\n
/// \b serverrequestid - from server request table\n
/// \b fixedIP - if specified for request\n
/// \b fixedMAC - if specified for request\n
/// \b serveradmingroupid - id of admin user group\n
/// \b serveradmingroup - name of admin user group\n
/// \b serverlogingroupid - id of login user group\n
/// \b serverlogingroup - name of login user group\n
/// \b monitored - whether or not request is to be monitored (0 or 1)\n
/// \b useraccountready - whether or not all accounts for this user have been
/// created on the reserved machine(s)\n
/// and an array of subimages named reservations with the following elements
/// for each subimage:\n
/// \b resid - id of reservation\n
/// \b imageid - id of requested image\n
/// \b imagerevisionid - revision id of requested image\n
/// \b image - name of requested image\n
/// \b prettyname - pretty name of requested image\n
/// \b OS - name of the requested os\n
/// \b compimageid - currentimageid for computer\n
/// \b computerstateid - current stateid of computer\n
/// \b computerid - id of reserved computer\n
/// \b IPaddress - IP address of reserved computer\n
/// \b type - type of computer\n
/// \b resacctuserid - empty if user account has not been created on this machine
/// yet, the user's numeric id if it has\n
/// \b password - password for this user on the machine; if it is empty but
/// resacctuserid is not empty, the user should use a federated password
///
/// \brief builds an array of current requests made by the user
///
////////////////////////////////////////////////////////////////////////////////
function getUserRequests($type, $id=0) {
global $user;
if($id == 0)
$id = $user["id"];
if(empty($user['groups']))
$ingroupids = "''";
else
$ingroupids = implode(',', array_keys($user['groups']));
$query = "SELECT i.name AS image, "
. "i.prettyname AS prettyimage, "
. "i.id AS imageid, "
. "rq.userid, "
. "rq.start, "
. "rq.end, "
. "rq.daterequested, "
. "rq.id, "
. "o.prettyname AS OS, "
. "o.installtype AS OSinstalltype, "
. "rq.stateid AS currstateid, "
. "rq.laststateid, "
. "rs.computerid, "
. "rs.id AS resid, "
. "c.currentimageid AS compimageid, "
. "c.stateid AS computerstateid, "
. "c.IPaddress, "
. "c.type AS comptype, "
. "c.vmhostid, "
. "rq.forimaging, "
. "i.forcheckout, "
. "rs.managementnodeid, "
. "rs.imagerevisionid, "
. "rq.test,"
. "sp.name AS servername, "
. "sp.requestid AS serverrequestid, "
. "sp.fixedIP, "
. "sp.fixedMAC, "
. "sp.admingroupid AS serveradmingroupid, "
. "uga.name AS serveradmingroup, "
. "sp.logingroupid AS serverlogingroupid, "
. "ugl.name AS serverlogingroup, "
. "sp.monitored, "
. "ra.password, "
. "ra.userid AS resacctuserid, "
. "rs.pw "
. "FROM image i, "
. "OS o, "
. "computer c, "
. "request rq "
. "LEFT JOIN serverrequest sp ON (sp.requestid = rq.id) "
. "LEFT JOIN usergroup uga ON (uga.id = sp.admingroupid) "
. "LEFT JOIN usergroup ugl ON (ugl.id = sp.logingroupid) "
. "LEFT JOIN reservation rs ON (rs.requestid = rq.id) "
. "LEFT JOIN reservationaccounts ra ON (ra.reservationid = rs.id AND ra.userid = $id) "
. "WHERE (rq.userid = $id OR "
. "sp.admingroupid IN ($ingroupids) OR "
. "sp.logingroupid IN ($ingroupids)) AND "
. "rs.imageid = i.id AND "
. "rq.end > NOW() AND "
. "i.OSid = o.id AND "
. "c.id = rs.computerid AND "
. "rq.stateid NOT IN (1, 10, 16, 17) AND " # deleted, maintenance, complete, image, makeproduction
. "rq.laststateid NOT IN (1, 10, 16, 17) "; # deleted, maintenance, complete, image, makeproduction
if($type == "normal")
$query .= "AND rq.forimaging = 0 "
. "AND i.forcheckout = 1 "
. "AND sp.requestid IS NULL ";
if($type == "forimaging")
$query .= "AND rq.forimaging = 1 "
. "AND sp.requestid IS NULL ";
if($type == "server")
$query .= "AND sp.requestid IS NOT NULL ";
$query .= "ORDER BY rq.start, "
. "rs.id";
$qh = doQuery($query, 160);
$count = -1;
$data = array();
$foundids = array();
$lastreqid = 0;
while($row = mysql_fetch_assoc($qh)) {
if($row['id'] != $lastreqid) {
$lastreqid = $row['id'];
$count++;
$data[$count] = $row;
$data[$count]['useraccountready'] = 1;
$data[$count]['reservations'] = array();
}
if(array_key_exists($row['id'], $foundids)) {
$data[$count]['reservations'][] = array(
'resid' => $row['resid'],
'image' => $row['image'],
'prettyname' => $row['prettyimage'],
'imageid' => $row['imageid'],
'imagerevisionid' => $row['imagerevisionid'],
'OS' => $row['OS'],
'computerid' => $row['computerid'],
'compimageid' => $row['compimageid'],
'computerstateid' => $row['computerstateid'],
'IPaddress' => $row['IPaddress'],
'comptype' => $row['comptype'],
'password' => $row['password'],
'resacctuserid' => $row['resacctuserid']
);
if($row['userid'] != $id && empty($row['resacctuserid']))
$data[$count]['useraccountready'] = 0;
continue;
}
$foundids[$row['id']] = 1;
if(! is_null($row['serverrequestid'])) {
$data[$count]['server'] = 1;
$data[$count]['longterm'] = 0;
if($row['userid'] == $user['id']) {
$data[$count]['serverowner'] = 1;
$data[$count]['serveradmin'] = 1;
}
else {
$data[$count]['serverowner'] = 0;
if(! empty($row['serveradmingroupid']) &&
array_key_exists($row['serveradmingroupid'], $user['groups']))
$data[$count]['serveradmin'] = 1;
else
$data[$count]['serveradmin'] = 0;
}
}
elseif((datetimeToUnix($row['end']) - datetimeToUnix($row['start'])) > SECINDAY) {
$data[$count]['server'] = 0;
$data[$count]['longterm'] = 1;
$data[$count]['serverowner'] = 1;
$data[$count]['serveradmin'] = 1;
}
else {
$data[$count]['server'] = 0;
$data[$count]['longterm'] = 0;
$data[$count]['serverowner'] = 1;
$data[$count]['serveradmin'] = 1;
}
if($row['userid'] != $id && empty($row['resacctuserid']))
$data[$count]['useraccountready'] = 0;
}
return $data;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn isComputerLoading($request, $computers)
///
/// \param $request - an element from the array returned from getUserRequests
/// \param $computers - array from getComputers
///
/// \return 1 if a computer is loading, 0 if not
///
/// \brief checks all computers associated with the request to see if they
/// are loading
///
////////////////////////////////////////////////////////////////////////////////
function isComputerLoading($request, $computers) {
if($computers[$request["computerid"]]["stateid"] == 6 ||
($computers[$request["computerid"]]["stateid"] == 2 &&
$computers[$request["computerid"]]["imagerevisionid"] != $request["imagerevisionid"]))
return 1;
foreach($request["reservations"] as $res) {
if($computers[$res["computerid"]]["stateid"] == 6 ||
($computers[$res["computerid"]]["stateid"] == 2 &&
$computers[$res["computerid"]]["imagerevisionid"] != $res["imagerevisionid"]))
return 1;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getMaxReloadTime($request, $images)
///
/// \param $request - an element from the array returned from getUserRequests
/// \param $images - array returned from getImages
///
/// \return the max reload time for all images associated with $request
///
/// \brief looks at all the reload times for images associated with $request
/// and returns the longest one
///
////////////////////////////////////////////////////////////////////////////////
function getMaxReloadTime($request, $images) {
$reloadtime = $images[$request["imageid"]]["reloadtime"];
foreach($request["reservations"] as $res) {
if($images[$res["imageid"]]["reloadtime"] > $reloadtime)
$reloadtime = $images[$res["imageid"]]["reloadtime"];
}
return $reloadtime;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn datetimeToUnix($datetime)
///
/// \param $datetime - a mysql datetime
///
/// \return timestamp - a unix timestamp
///
/// \brief converts a mysql datetime to a unix timestamp
///
////////////////////////////////////////////////////////////////////////////////
function datetimeToUnix($datetime) {
$tmp = explode(' ', $datetime);
list($year, $month, $day) = explode('-', $tmp[0]);
list($hour, $min, $sec) = explode(':', $tmp[1]);
return mktime($hour, $min, $sec, $month, $day, $year, -1);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn unixToDatetime($timestamp)
///
/// \param $timestamp - a unix timestamp
///
/// \return datetime - a mysql datetime
///
/// \brief converts a unix timestamp to a mysql datetime
///
////////////////////////////////////////////////////////////////////////////////
function unixToDatetime($timestamp) {
return date("Y-m-d H:i:s", $timestamp);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn numdatetimeToDatetime($numtime)
///
/// \param $numtime - date and time in YYYYMMDDHHMMSS format
///
/// \return a mysql datetime formatted string (YYYY-MM-DD HH:MM:SS)
///
/// \brief converts numeric date and time into datetime format
///
////////////////////////////////////////////////////////////////////////////////
function numdatetimeToDatetime($numtime) {
$year = substr($numtime, 0, 4);
$month = substr($numtime, 4, 2);
$day = substr($numtime, 6, 2);
$hour = substr($numtime, 8, 2);
$min = substr($numtime, 10, 2);
$sec = substr($numtime, 12, 2);
return "$year-$month-$day $hour:$min:$sec";
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn minuteOfDay($hour, $min)
///
/// \param $hour - hour of the day (0 - 23)
/// \param $min - minute into the hour (0 - 59)
///
/// \return minutes into the day (0 - 1439)
///
/// \brief converts hour:min to minutes since midnight
///
////////////////////////////////////////////////////////////////////////////////
function minuteOfDay($hour, $min) {
return ($hour * 60) + $min;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn minuteOfDay2($time)
///
/// \param $time - in format 'HH:MM (am|pm)'
///
/// \return minutes into the day (0 - 1439)
///
/// \brief converts 'HH:MM (am|pm)' to minutes since midnight
///
////////////////////////////////////////////////////////////////////////////////
function minuteOfDay2($time) {
$timeArr = explode(':', $time);
$hour = $timeArr[0];
$timeArr = explode(' ', $timeArr[1]);
$min = $timeArr[0];
$meridian = $timeArr[1];
if($meridian == "am" && $hour == 12) {
return $min;
}
elseif($meridian == "pm" && $hour < 12) {
$hour += 12;
}
return ($hour * 60) + $min;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn minuteOfWeek($ts)
///
/// \param $ts - a unix timestamp
///
/// \return minute of the week
///
/// \brief takes a unix timestamp and returns how many minutes into the week it
/// is with the week starting on Sunday at midnight
///
////////////////////////////////////////////////////////////////////////////////
function minuteOfWeek($ts) {
# ((day of week (0-6)) * 1440) + ((hour in day) * 60) + (min in hour)
return (date('w', $ts) * 1440) + (date('G', $ts) * 60) + date('i', $ts);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn minuteToTime($minutes)
///
/// \param $minutes - minutes since midnight
///
/// \return time string in the form (H)H:MM (am/pm)
///
/// \brief converts "minutes since midnight" to time of day
///
////////////////////////////////////////////////////////////////////////////////
function minuteToTime($minutes) {
$hour = sprintf("%d", $minutes / 60);
$min = sprintf("%02d", $minutes % 60);
$meridian = "am";
if($hour == 0) {
$hour = 12;
}
elseif($hour == 12) {
$meridian = "pm";
}
elseif($hour > 12) {
$hour -= 12;
$meridian = "pm";
}
return "$hour:$min $meridian";
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn hour12to24($hour, $meridian)
///
/// \param $hour - 1 to 12
/// \param $meridian - am or pm
///
/// \return 24 hour equivilent of $hour $meridian
///
/// \brief converts 12 hour format to 24 hour format
///
////////////////////////////////////////////////////////////////////////////////
function hour12to24($hour, $meridian) {
if($meridian == 'pm' && $hour < 12)
return $hour + 12;
elseif($meridian == 'am' && $hour == 12)
return 0;
return $hour;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn hour24to12($hour) {
///
/// \param $hour - hour of day in 24 hour format
///
/// \return array with two elements where the first item is the hour and the
// second item is either 'am' or 'pm'
///
/// \brief converts 24 hour to 12 hour + am/pm
///
////////////////////////////////////////////////////////////////////////////////
function hour24to12($hour) {
$m = 'am';
if($hour == 0)
$hour = 12;
elseif($hour == 12)
$m = 'pm';
elseif($hour > 12) {
$m = 'pm';
$hour -= 12;
}
return array($hour, $m);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getDepartmentName($id)
///
/// \param $id - id for a department in the department table
///
/// \return if found, department name; if not, 0
///
/// \brief looks up the name field corresponding to $id in the department table
/// and returns it
///
////////////////////////////////////////////////////////////////////////////////
function getDepartmentName($id) {
$query = "SELECT name FROM department WHERE id = '$id'";
$qh = doQuery($query, 101);
if($row = mysql_fetch_row($qh)) {
return $row[0];
}
else {
return 0;
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getImageId($image)
///
/// \param $image - name of an image (must match name (not prettyname) in the
/// image table)
///
/// \return the id of matching $image in the image table or 0 if lookup fails
///
/// \brief looks up the id for $image and returns it
///
////////////////////////////////////////////////////////////////////////////////
function getImageId($image) {
$qh = doQuery("SELECT id FROM image WHERE name = '$image'", 170);
if($row = mysql_fetch_row($qh)) {
return $row[0];
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getOSId($os)
///
/// \param $os - name of an os (must match name in the os table
///
/// \return the id of matching $os in the os table or 0 if lookup fails
///
/// \brief looks up the id for $os and returns it
///
////////////////////////////////////////////////////////////////////////////////
function getOSId($os) {
$qh = doQuery("SELECT id FROM OS WHERE name = '$os'", 175);
if($row = mysql_fetch_row($qh)) {
return $row[0];
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getStates()
///
/// \return array of states where the index are the id from the state table
///
/// \brief gets names for states in state table
///
////////////////////////////////////////////////////////////////////////////////
function getStates() {
$qh = doQuery("SELECT id, name FROM state", 176);
$states = array();
while($row = mysql_fetch_row($qh)) {
$states[$row[0]] = $row[1];
}
return $states;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getPlatforms()
///
/// \return array of platforms where the index are the id from the platform table
///
/// \brief gets names for platforms in platform table
///
////////////////////////////////////////////////////////////////////////////////
function getPlatforms() {
$qh = doQuery("SELECT id, name FROM platform", 178);
$platforms = array();
while($row = mysql_fetch_row($qh)) {
$platforms[$row[0]] = $row[1];
}
return $platforms;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getProvisioning()
///
/// \return array of provisioning engines where each index is the id and the
/// value is an array with these keys: name, prettyname, moduleid, modulename
///
/// \brief gets data from provisioning table
///
////////////////////////////////////////////////////////////////////////////////
function getProvisioning() {
$query = "SELECT p.id, "
. "p.name, "
. "p.prettyname, "
. "p.moduleid, "
. "m.prettyname AS modulename "
. "FROM provisioning p, "
. "module m "
. "WHERE p.moduleid = m.id "
. "ORDER BY p.prettyname";
$qh = doQuery($query, 101);
$provisioning = array();
while($row = mysql_fetch_assoc($qh))
$provisioning[$row['id']] = $row;
return $provisioning;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getSchedules()
///
/// \return array of schedules where the index are the id from the schedule table,
/// each index has the following elements:\n
/// \b name - name of schedule\n
/// \b ownerid - user id of owner\n
/// \b owner - unity id of owner\n
/// \b times - array of start and end times for the schedule
///
/// \brief gets information for schedules in schedule table
///
////////////////////////////////////////////////////////////////////////////////
function getSchedules() {
$query = "SELECT s.id, "
. "s.name, "
. "s.ownerid, "
. "CONCAT(u.unityid, '@', a.name) AS owner, "
. "r.id AS resourceid "
. "FROM schedule s, "
. "resource r, "
. "resourcetype t, "
. "user u, "
. "affiliation a "
. "WHERE r.subid = s.id AND "
. "r.resourcetypeid = t.id AND "
. "t.name = 'schedule' AND "
. "s.ownerid = u.id AND "
. "u.affiliationid = a.id "
. "ORDER BY s.name";
$qh = doQuery($query, 179);
$schedules = array();
while($row = mysql_fetch_assoc($qh)) {
$schedules[$row["id"]] = $row;
$schedules[$row["id"]]["times"] = array();
}
$query = "SELECT scheduleid, "
. "start, "
. "end "
. "FROM scheduletimes "
. "ORDER BY scheduleid, "
. "start";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
array_push($schedules[$row["scheduleid"]]["times"],
array("start" => $row["start"], "end" => $row["end"]));
}
return $schedules;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn formatMinOfWeek($min)
///
/// \param $min - minute of the week
///
/// \return a string with the day of week and time
///
/// \brief formats $min into something useful for printing
///
////////////////////////////////////////////////////////////////////////////////
function formatMinOfWeek($min) {
$time = minuteToTime($min % 1440);
if($min / 1440 == 0) {
return "Sunday, $time";
}
elseif((int)($min / 1440) == 1) {
return "Monday, $time";
}
elseif((int)($min / 1440) == 2) {
return "Tuesday, $time";
}
elseif((int)($min / 1440) == 3) {
return "Wednesday, $time";
}
elseif((int)($min / 1440) == 4) {
return "Thursday, $time";
}
elseif((int)($min / 1440) == 5) {
return "Friday, $time";
}
elseif((int)($min / 1440) == 6) {
return "Saturday, $time";
}
elseif((int)($min / 1440) > 6) {
return "Sunday, $time";
}
else {
return "$time";
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getManagementNodes($alive)
///
/// \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
///
/// \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
///
/// \brief builds an array of data about the management nodes\n
/// if $alive = now, must have checked in within 5 minutes\n
/// if $alive = future, must have checked in within 1 hour
///
////////////////////////////////////////////////////////////////////////////////
function getManagementNodes($alive="neither") {
if($alive == "now")
$lastcheckin = unixToDatetime(time() - 300);
elseif($alive == "future")
$lastcheckin = unixToDatetime(time() - 3600);
$query = "SELECT m.id, "
. "m.IPaddress, "
. "m.hostname, "
. "m.ownerid, "
. "CONCAT(u.unityid, '@', a.name) as owner, "
. "m.stateid, "
. "s.name as state, "
. "m.lastcheckin, "
. "m.checkininterval, "
. "m.installpath, "
. "m.imagelibenable, "
. "m.imagelibgroupid, "
. "rg.name AS imagelibgroup, "
. "m.imagelibuser, "
. "m.imagelibkey, "
. "m.keys, "
. "m.sshport, "
. "m.publicIPconfiguration AS publicIPconfig, "
. "m.publicSubnetMask AS publicnetmask, "
. "m.publicDefaultGateway AS publicgateway, "
. "m.publicDNSserver AS publicdnsserver, "
. "m.sysadminEmailAddress AS sysadminemail, "
. "m.sharedMailBox AS sharedmailbox, "
. "r.id as resourceid, "
. "m.predictivemoduleid, "
. "mo.prettyname AS predictivemodule "
. "FROM user u, "
. "state s, "
. "resource r, "
. "resourcetype rt, "
. "affiliation a, "
. "module mo, "
. "managementnode m "
. "LEFT JOIN resourcegroup rg ON (m.imagelibgroupid = rg.id) "
. "WHERE m.ownerid = u.id AND "
. "m.stateid = s.id AND "
. "m.id = r.subid AND "
. "r.resourcetypeid = rt.id AND "
. "rt.name = 'managementnode' AND "
. "u.affiliationid = a.id AND "
. "m.predictivemoduleid = mo.id";
if($alive == "now" || $alive == "future") {
$query .= " AND m.lastcheckin > '$lastcheckin'"
. " AND s.name != 'maintenance'";
}
$qh = doQuery($query, 101);
$return = array();
while($row = mysql_fetch_assoc($qh)) {
$return[$row["id"]] = $row;
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getPredictiveModules()
///
/// \return an array of predictive loading modules where the index is the module
/// id and the value is a row of data from the module table
///
/// \brief gets all the predictive loading modules from the module table
///
////////////////////////////////////////////////////////////////////////////////
function getPredictiveModules() {
$query = "SELECT id, "
. "name, "
. "prettyname, "
. "description, "
. "perlpackage "
. "FROM module "
. "WHERE perlpackage LIKE 'VCL::Module::Predictive::%'";
$qh = doQuery($query, 101);
$modules = array();
while($row = mysql_fetch_assoc($qh))
$modules[$row['id']] = $row;
return $modules;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getTimeSlots($end, $start)
///
/// \param $end - (optional) end time as unix timestamp
/// \param $start - (optional) start time as unix timestamp
///
/// \return array of free/used timeslotes
///
/// \brief generates an array of availability for computers where index is a
/// computerid with a value that is an array whose indexes are unix timestamps
/// that increment by 15 minutes with a value that is an array with 2 indexes:
/// 'scheduleclosed' and 'available' that tell if the computer's schedule is
/// closed at that moment and if the computer is available at that moment\n
/// Array {\n
/// [computerid0] => Array {\n
/// [timeslot0] => Array {\n
/// [scheduleclosed] => (0/1)\n
/// [available] => (0/1)\n
/// }\n
/// ...\n
/// [timeslotN] => Array {...}\n
/// }\n
/// ...\n
/// [computeridN] => Array {...}\n
/// }
///
////////////////////////////////////////////////////////////////////////////////
function getTimeSlots($compids, $end=0, $start=0) {
if(empty($compids))
return array();
$requestid = processInputVar("requestid", ARG_NUMERIC, 0);
$platsel = getContinuationVar("platforms");
if(empty($platsel))
$platsel = processInputVar("platforms", ARG_MULTINUMERIC);
$schsel = getContinuationVar("schedules");
if(empty($schsel))
$schsel = processInputVar("schedules", ARG_MULTINUMERIC);
# all computations done with unix timestamps
if($end != 0) {
$enddate = unixToDatetime($end);
}
if($start != 0) {
$startdate = unixToDatetime($start);
}
$computerids = array();
$reservedComputerids = array();
$schedules = getSchedules();
$times = array();
$scheduleids = array();
$compinlist = implode(",", $compids);
$query = "SELECT id, scheduleid "
. "FROM computer "
. "WHERE scheduleid IS NOT NULL AND "
. "scheduleid != 0 AND "
. "id IN ($compinlist) ";
if(! empty($schsel) && ! empty($platsel)) {
$schinlist = implode(',', $schsel);
$platinlist = implode(',', $platsel);
$query .= "AND scheduleid IN ($schinlist) "
. "AND platformid IN ($platinlist)";
}
$qh = doQuery($query, 155);
while($row = mysql_fetch_row($qh)) {
array_push($computerids, $row[0]);
$times[$row[0]] = array();
$scheduleids[$row[0]] = $row[1];
}
if($start != 0 && $end != 0) {
$query = "SELECT rs.computerid, "
. "rq.start, "
. "rq.end + INTERVAL 900 SECOND AS end, "
. "rq.id, "
. "u.unityid, "
. "i.prettyname "
. "FROM reservation rs, "
. "request rq, "
. "user u, "
. "image i "
. "WHERE (rq.start < '$enddate' AND "
. "rq.end > '$startdate') AND "
. "rq.id = rs.requestid AND "
. "u.id = rq.userid AND "
. "i.id = rs.imageid AND "
. "rq.stateid NOT IN (1,5,12) "
. "ORDER BY rs.computerid, "
. "rq.start";
}
else {
$query = "SELECT rs.computerid, "
. "rq.start, "
. "rq.end + INTERVAL 900 SECOND AS end, "
. "rq.id, "
. "u.unityid, "
. "i.prettyname "
. "FROM reservation rs, "
. "request rq, "
. "user u, "
. "image i "
. "WHERE rq.end > NOW() AND "
. "rq.id = rs.requestid AND "
. "u.id = rq.userid AND "
. "i.id = rs.imageid AND "
. "rq.stateid NOT IN (1,5,12) "
. "ORDER BY rs.computerid, "
. "rq.start";
}
$qh = doQuery($query, 156);
$id = "";
while($row = mysql_fetch_row($qh)) {
if($row[3] == $requestid) {
continue;
}
if($id != $row[0]) {
$count = 0;
$id = $row[0];
array_push($reservedComputerids, $id);
}
$times[$id][$count] = array();
$times[$id][$count]["start"] = datetimeToUnix($row[1]);
$times[$id][$count]["end"] = datetimeToUnix($row[2]);
$times[$id][$count]["requestid"] = $row[3];
$times[$id][$count]["unityid"] = $row[4];
$times[$id][$count++]["prettyimage"] = $row[5];
}
# use floor function to get to a 15 min increment for start
if($start != 0) {
$start = unixFloor15($start);
}
else {
$start = unixFloor15() + 900;
}
# last time to look at
if($end != 0) {
$endtime = $end;
}
else {
$endtime = $start + (DAYSAHEAD * SECINDAY);
}
$blockData = getBlockTimeData($start, $endtime);
$maintItems = getMaintItemsForTimeTable($start, $endtime);
$reserveInfo = array(); // 0 = reserved, 1 = available
foreach($computerids as $id) {
$reserveInfo[$id] = array();
$first = 1;
# loop from $start to $endtime by 15 minute increments
for($current = $start, $count = 0, $max = count($times[$id]);
$current < $endtime;
$current += 900) {
/*print "compid - $id \n";
print "count - $count \n";
print "current - " . unixToDatetime($current) . " \n";
if(array_key_exists($count, $times[$id])) {
print "start - " . unixToDatetime($times[$id][$count]["start"]) . " \n";
print "end - " . unixToDatetime($times[$id][$count]["end"]) . " \n";
}
print "----------------------------------------------------- \n";*/
$reserveInfo[$id][$current]['blockAllocation'] = 0;
$reserveInfo[$id][$current]["inmaintenance"] = 0;
if(scheduleClosed($id, $current, $schedules[$scheduleids[$id]])) {
$reserveInfo[$id][$current]["available"] = 0;
$reserveInfo[$id][$current]["scheduleclosed"] = 1;
continue;
}
if(checkInMaintenanceForTimeTable($current, $current + 900, $maintItems)) {
$reserveInfo[$id][$current]["available"] = 0;
$reserveInfo[$id][$current]["inmaintenance"] = 1;
continue;
}
if($blockid = isBlockAllocationTime($id, $current, $blockData)) {
$reserveInfo[$id][$current]['blockAllocation'] = 1;
$reserveInfo[$id][$current]['blockInfo']['groupid'] = $blockData[$blockid]['groupid'];
$reserveInfo[$id][$current]['blockInfo']['imageid'] = $blockData[$blockid]['imageid'];
$reserveInfo[$id][$current]['blockInfo']['name'] = $blockData[$blockid]['name'];
$reserveInfo[$id][$current]['blockInfo']['image'] = $blockData[$blockid]['image'];
}
$reserveInfo[$id][$current]["scheduleclosed"] = 0;
//if computer not in $reservedComputerids, it is free
if(! in_array($id, $reservedComputerids)) {
$reserveInfo[$id][$current]["available"] = 1;
continue;
}
//if past an end
if($count != $max && $current >= $times[$id][$count]["end"]) {
$count++;
}
# past the end of all reservations
if($count == $max) {
$reserveInfo[$id][$current]["available"] = 1;
continue;
}
//if before any start times
if($count == 0 && $current < $times[$id][0]["start"]) {
$reserveInfo[$id][$current]["available"] = 1;
continue;
}
//if between a start and end time
if($current >= $times[$id][$count]["start"] &&
$current < $times[$id][$count]["end"]) {
if($first) {
# set the previous 15 minute block to show as busy to allow for load time
$first = 0;
$reserveInfo[$id][$current - 900]['blockAllocation'] = 0;
$reserveInfo[$id][$current - 900]["scheduleclosed"] = 0;
$reserveInfo[$id][$current - 900]["available"] = 0;
$reserveInfo[$id][$current - 900]["requestid"] = $times[$id][$count]["requestid"];
$reserveInfo[$id][$current - 900]["unityid"] = $times[$id][$count]["unityid"];
$reserveInfo[$id][$current - 900]["prettyimage"] = $times[$id][$count]["prettyimage"];
}
$reserveInfo[$id][$current]["available"] = 0;
$reserveInfo[$id][$current]["requestid"] = $times[$id][$count]["requestid"];
$reserveInfo[$id][$current]["unityid"] = $times[$id][$count]["unityid"];
$reserveInfo[$id][$current]["prettyimage"] = $times[$id][$count]["prettyimage"];
continue;
}
//if after previous end but before this start
if($current >= $times[$id][$count - 1]["end"] &&
$current < $times[$id][$count]["start"]) {
$reserveInfo[$id][$current]["available"] = 1;
continue;
}
# shouldn't get here; print debug info if we do
if(checkUserHasPerm('View Debug Information')) {
print "****************************************************** \n";
print "current - " . unixToDatetime($current) . " \n";
print "endtime - " . unixToDatetime($endtime) . " \n";
print "count - $count \n";
print "max - $max \n";
print "start - " . unixToDatetime($times[$id][$count]["start"]) . " \n";
print "end - " . unixToDatetime($times[$id][$count]["end"]) . " \n";
print "------------------------------------------------------ \n";
}
}
}
return $reserveInfo;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn unixFloor15($timestamp)
///
/// \param $timestamp - (optional) unix timestamp, defaults to now
///
/// \return floored timestamp
///
/// \brief takes $timestamp and floors it to a 15 minute increment with 0 seconds
///
////////////////////////////////////////////////////////////////////////////////
function unixFloor15($timestamp=0) {
if($timestamp == 0) {
$timestamp = time();
}
$timeval = getdate($timestamp);
if($timeval["minutes"] < 15) {
$timeval["minutes"] = 0;
}
elseif($timeval["minutes"] < 30) {
$timeval["minutes"] = 15;
}
elseif($timeval["minutes"] < 45) {
$timeval["minutes"] = 30;
}
elseif($timeval["minutes"] < 60) {
$timeval["minutes"] = 45;
}
return mktime($timeval["hours"],
$timeval["minutes"],
0,
$timeval["mon"],
$timeval["mday"],
$timeval["year"],
-1);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn pickTimeTable()
///
/// \brief prints a form for selecting what elements to show in the timetable
///
////////////////////////////////////////////////////////////////////////////////
function pickTimeTable() {
$data = getUserComputerMetaData();
print "
Time Table
\n";
print "Select the criteria for the computers you want to have in the timetable:\n";
print "\n";
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn showTimeTable($links)
///
/// \param $links - 1 to make free times links; 0 for no links
///
/// \brief prints out a timetable of free/used timeslots
///
////////////////////////////////////////////////////////////////////////////////
function showTimeTable($links) {
global $mode, $user;
$imaging = getContinuationVar('imaging', 0);
if($links == 1) {
$imageid = getContinuationVar('imageid');
$length = getContinuationVar('length');
$requestid = getContinuationVar('requestid', 0);
$showmessage = getContinuationVar('showmessage', 0);
$platforms = array();
$schedules = array();
}
else {
$imageid = 0;
$length = 0;
$requestid = 0;
$showmessage = 0;
$platforms = getContinuationVar("platforms");
if(empty($platforms))
$platforms = processInputVar("platforms", ARG_MULTINUMERIC);
$schedules = getContinuationVar("schedules");
if(empty($schedules))
$schedules = processInputVar("schedules", ARG_MULTINUMERIC);
}
$argstart = getContinuationVar("start");
$argend = getContinuationVar("end");
$resources = getUserResources(array("computerAdmin"));
$userCompIDs = array_keys($resources["computer"]);
$computerData = getComputers();
$imageData = getImages();
$now = time();
if($links) {
$resources = getUserResources(array("imageAdmin", "imageCheckOut"));
$usercomputerids = array_keys($resources["computer"]);
# get list of computers' platformids
$qh = doQuery("SELECT platformid FROM image WHERE id = $imageid", 110);
$row = mysql_fetch_row($qh);
$platformid = $row[0];
$computer_platformids = array();
$qh = doQuery("SELECT id, platformid FROM computer", 111);
while($row = mysql_fetch_row($qh)) {
$computer_platformids[$row[0]] = $row[1];
}
$mappedcomputers = getMappedResources($imageid, "image", "computer");
$compidlist = array_intersect($mappedcomputers, $usercomputerids);
}
else
$compidlist = $userCompIDs;
if(! empty($argstart) && ! empty($argend)) {
$timeslots = getTimeSlots($compidlist, $argend, $argstart);
$start = $argstart;
$end = $argend;
}
else {
$start = $now;
$end = $start + (SECINDAY / 2);
$timeslots = getTimeSlots($compidlist, $end);
}
print "
\n";
print _("
Time Table
\n");
print "
\n";
$computeridrow = "";
$displayedids = array();
$computers = array_keys($timeslots);
if($links) {
$computers = array_intersect($computers, $usercomputerids);
}
foreach($computers as $id) {
if($links) {
# don't show computers that don't meet hardware criteria, are not
# in the available state, are the wrong platform, or wrong group,
# or aren't mapped in resourcemap
if($computer_platformids[$id] != $platformid ||
($computerData[$id]["stateid"] != 2 &&
$computerData[$id]["stateid"] != 3 &&
$computerData[$id]["stateid"] != 6 &&
$computerData[$id]["stateid"] != 8) ||
$computerData[$id]["ram"] < $imageData[$imageid]["minram"] ||
$computerData[$id]["procnumber"] < $imageData[$imageid]["minprocnumber"] ||
$computerData[$id]["procspeed"] < $imageData[$imageid]["minprocspeed"] ||
$computerData[$id]["network"] < $imageData[$imageid]["minnetwork"] ||
! in_array($id, $mappedcomputers)) {
continue;
}
}
elseif(! array_key_exists($id, $computerData) ||
! in_array($computerData[$id]["platformid"], $platforms) ||
! in_array($computerData[$id]["scheduleid"], $schedules) ||
! in_array($id, $userCompIDs)) {
continue;
}
$computeridrow .= "
$id
\n";
array_push($displayedids, $id);
}
if(empty($displayedids)) {
if($links) {
print _("There are currently no computers available that can run the application you selected.\n");
}
else {
print _("There are no computers that meet the specified criteria\n");
}
return;
}
if($showmessage) {
print _("The time you have requested to use the environment is not ");
print _("available. You may select from the green blocks of time to ");
print _("select an available time slot to make a reservation. \n");
}
print "
\n";
}
# computer's schedule is currently closed
elseif($timeslots[$id][$stamp]["scheduleclosed"] == 1) {
print "
\n";
}
# computer is in maintenance state
elseif($computerData[$id]["stateid"] == 10) {
print "
\n";
}
# computer is reserved for a block allocation that doesn't match this
elseif($timeslots[$id][$stamp]['blockAllocation'] &&
($timeslots[$id][$stamp]['blockInfo']['imageid'] != $imageid || # this line threw an error at one point, but we couldn't recreate it later
(! in_array($timeslots[$id][$stamp]['blockInfo']['groupid'], array_keys($user['groups'])))) &&
$timeslots[$id][$stamp]['available']) {
if($links) {
print "
\n";
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn findAvailableTimes($start, $end, $imageid, $userid, $usedaysahead,
// $reqid='', $extendonly=0, $ip='', $mac='')
///
/// \param $start - desired start time (epoch time)
/// \param $end - desired end time (epoch time)
/// \param $imageid - desired image
/// \param $userid - id of user to check for
/// \param $usedaysahead - 1 to limit suggested start time based on DAYSAHEAD,
/// 0 not to
/// \param $reqid - (optional, default='') id of a request to ignore - use this
/// when editing an existing reservation
/// \param $extendonly - (optional, default=0) if set to 1, only check for how
/// long this reservation can be extended; $reqid also be given a value and
/// function will only search for extensions to existing reservation on same
/// computer
/// \param $ip - (optional, default='') desired IP address
/// \param $mac - (optional, default='') desired MAC address
///
/// \return an array where each key is a unix timestamp for the start time of
/// the available slot and each element is an array with these items:\n
/// \b start - start of slot in datetime format\n
/// \b startts - start of slot in unix timestamp format\n
/// \b duration - length of slot in minutes\n
/// \b compid - id of computer for slot
///
/// \brief builds an array of available time slots close to the submitted
/// parameters
///
////////////////////////////////////////////////////////////////////////////////
function findAvailableTimes($start, $end, $imageid, $userid, $usedaysahead,
$reqid='', $extendonly=0, $ip='', $mac='') {
global $user;
if($userid == $user['id'])
$ingroups = implode(',', array_keys($user['groups']));
else {
$userdata = getUserInfo($userid, 0, 1);
$ingroups = implode(',', array_keys($userdata['groups']));
}
# TODO make this work for cluster images
if(! $extendonly) {
$mappedcomputers = getMappedResources($imageid, 'image', 'computer');
$resources = getUserResources(array('imageAdmin', 'imageCheckOut'),
array('available'), 0, 0, $userid);
$compids = array_intersect($mappedcomputers, array_keys($resources['computer']));
if(! count($compids)) {
return array();
}
$incompids = implode(',', $compids);
}
else {
$request = getRequestInfo($reqid);
$incompids = $request['reservations'][0]['computerid'];
}
$scheduleids = getAvailableSchedules($start, $end);
if(empty($scheduleids))
return array();
$schedules = implode(',', $scheduleids);
$platformid = getImagePlatform($imageid);
if(is_null($platformid))
return array();
$reqduration = $end - $start;
$startdt = unixToDatetime($start);
$end += 900;
$enddt = unixToDatetime($end);
$ignorestates = "'maintenance','vmhostinuse','hpc','failed'";
$nowignorestates = "$ignorestates,'timeout'";
if(! $extendonly)
$nowignorestates .= ",'reloading','reload','inuse'";
$slots = array();
$removes = array();
$minstart = $start;
$maxend = $start;
$newcompids = array();
$daysahead = time() + (DAYSAHEAD * SECINDAY);
# add computers that are available now with no future reservations
# restricting duration; we do this so that they'll be in our arrays to check
# for concurrent image use, block allocations, ip/mac overlap, and
# maintenance window overlap
$query = "SELECT c.id AS compid "
. "FROM computer c, "
. "image i, "
. "state s "
. "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 "
. "c.RAM >= i.minram AND "
. "c.procnumber >= i.minprocnumber AND "
. "c.procspeed >= i.minprocspeed AND "
. "c.network >= i.minnetwork AND "
. "c.id NOT IN (SELECT rs.computerid "
. "FROM reservation rs, "
. "request rq "
. "WHERE rs.requestid = rq.id AND ";
if($reqid != '')
$query .= "rq.id != $reqid AND ";
$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";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$row['duration'] = $reqduration;
$row['startts'] = $start;
$row['start'] = $startdt;
$row['endts'] = $start + $reqduration;
$slots[$row['compid']] = array();
$slots[$row['compid']][] = $row;
$newcompids[] = $row['compid'];
}
if(! $extendonly) {
# find available timeslots based on spacing between existing reservations
$query = "SELECT rs1.computerid AS compid, "
. "DATE_ADD(rq1.end, INTERVAL 15 MINUTE) AS start, "
. "MIN(UNIX_TIMESTAMP(rq2.start) - UNIX_TIMESTAMP(rq1.end) - 1800) AS duration " # 1800 is adding 15 min to end of rq1.end and end of requested reservation
. "FROM request rq1, "
. "request rq2, "
. "reservation rs1, "
. "reservation rs2, "
. "image i, "
. "state s, "
. "computer c "
. "WHERE rq1.id = rs1.requestid AND "
. "rs2.requestid = rq2.id AND "
. "rq1.id != rq2.id AND "
. "rq1.start < rq2.start AND "
. "DATE_ADD(rq1.end, INTERVAL 15 MINUTE) >= '$startdt' AND "
. "rs1.computerid = rs2.computerid AND "
. "rs1.computerid IN ($incompids) AND "
. "i.id = $imageid AND "
. "c.id = rs1.computerid AND "
. "c.platformid = $platformid AND "
. "c.scheduleid IN ($schedules) AND "
. "c.RAM >= i.minram AND "
. "c.procnumber >= i.minprocnumber AND "
. "c.procspeed >= i.minprocspeed AND "
. "c.network >= i.minnetwork AND "
. "c.stateid = s.id AND "
. "s.name NOT IN ($ignorestates) AND ";
if($reqid != '')
$query .= "rq1.id != $reqid AND "
. "rq2.id != $reqid AND ";
$query .= "(c.type != 'virtualmachine' OR c.vmhostid IS NOT NULL) "
. "GROUP BY rq1.id ";
$query .= "ORDER BY rs1.computerid, rq1.start, rq1.end";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$row['startts'] = datetimeToUnix($row['start']);
if($row['startts'] % 900) {
$row['startts'] = $row['startts'] - ($row['startts'] % 900) + 900;
$row['start'] = unixToDatetime($row['startts']);
$row['duration'] -= 900;
}
if($row['duration'] >= 1800) {
if($usedaysahead && $row['startts'] > $daysahead)
continue;
if($row['duration'] > $reqduration)
$row['duration'] = $reqduration;
$row['endts'] = $row['startts'] + $row['duration'];
if(! array_key_exists($row['compid'], $slots))
$slots[$row['compid']] = array();
$slots[$row['compid']][] = $row;
if($row['startts'] < $minstart)
$minstart = $row['startts'];
if($row['endts'] > $maxend)
$maxend = $row['endts'];
$newcompids[] = $row['compid'];
}
}
}
# find slots that are available now
$query = "SELECT UNIX_TIMESTAMP(MIN(rq.start)) - UNIX_TIMESTAMP('$startdt') - 900 AS duration, "
. "UNIX_TIMESTAMP(MIN(rq.start)) AS endts, "
. "rs.computerid AS compid "
. "FROM request rq, "
. "reservation rs, "
. "image i, "
. "state s, "
. "computer c "
. "WHERE rs.requestid = rq.id AND "
. "(rq.start > '$startdt' OR "
. "(DATE_ADD(rq.end, INTERVAL 15 MINUTE) > '$startdt' AND rq.start <= '$startdt')) AND "
. "rs.computerid IN ($incompids) AND "
. "i.id = $imageid AND "
. "c.id = rs.computerid AND "
. "c.platformid = $platformid AND "
. "c.scheduleid IN ($schedules) AND "
. "c.RAM >= i.minram AND "
. "c.procnumber >= i.minprocnumber AND "
. "c.procspeed >= i.minprocspeed AND "
. "c.network >= i.minnetwork AND "
. "c.stateid = s.id AND "
. "s.name NOT IN ($nowignorestates) AND ";
if($reqid != '')
$query .= "rq.id != $reqid AND ";
$query .= "(c.type != 'virtualmachine' OR c.vmhostid IS NOT NULL) "
. "GROUP BY rs.computerid";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
if($row['endts'] % 900) {
$row['endts'] = $row['endts'] - ($row['endts'] % 900);
$row['duration'] -= 900;
}
if($row['duration'] >= 1800) {
if($row['duration'] > $reqduration)
$row['duration'] = $reqduration;
$row['start'] = $startdt;
$row['startts'] = $start;
if(! array_key_exists($row['compid'], $slots))
$slots[$row['compid']] = array();
$slots[$row['compid']][] = $row;
if($row['endts'] > $maxend)
$maxend = $row['endts'];
$newcompids[] = $row['compid'];
}
}
# find slots that are available after all reservations are over
$query = "SELECT UNIX_TIMESTAMP(MAX(rq.end)) + 900 AS startts, "
. "DATE_ADD(MAX(rq.end), INTERVAL 15 MINUTE) AS start, "
. "rs.computerid AS compid "
. "FROM request rq, "
. "reservation rs, "
. "image i, "
. "state s, "
. "computer c "
. "WHERE rs.requestid = rq.id AND "
. "(rq.start > '$startdt' OR "
. "(DATE_ADD(rq.end, INTERVAL 15 MINUTE) > '$startdt' AND rq.start <= '$startdt')) AND "
. "rs.computerid IN ($incompids) AND "
. "i.id = $imageid AND "
. "c.id = rs.computerid AND "
. "c.platformid = $platformid AND "
. "c.scheduleid IN ($schedules) AND "
. "c.RAM >= i.minram AND "
. "c.procnumber >= i.minprocnumber AND "
. "c.procspeed >= i.minprocspeed AND "
. "c.network >= i.minnetwork AND "
. "c.stateid = s.id AND "
. "s.name NOT IN ($ignorestates) AND ";
if($reqid != '')
$query .= "rq.id != $reqid AND ";
$query .= "(c.type != 'virtualmachine' OR c.vmhostid IS NOT NULL) "
. "GROUP BY rs.computerid";
if($extendonly)
$query .= " HAVING start = '$startdt'";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
if($usedaysahead && $row['startts'] > $daysahead)
continue;
if($row['startts'] % 900) {
$row['startts'] = $row['startts'] - ($row['startts'] % 900) + 900;
$row['start'] = unixToDatetime($row['startts']);
}
$row['endts'] = $row['startts'] + $reqduration;
$row['duration'] = $reqduration;
if(! array_key_exists($row['compid'], $slots))
$slots[$row['compid']] = array();
$slots[$row['compid']][] = $row;
if($row['endts'] > $maxend)
$maxend = $row['endts'];
$newcompids[] = $row['compid'];
}
if(empty($newcompids))
return array();
# remove block computers
$minstartdt = unixToDatetime($minstart);
$maxenddt = unixToDatetime($maxend);
$newincompids = implode(',', $newcompids);
$query = "SELECT bc.computerid AS compid, "
. "UNIX_TIMESTAMP(bt.start) AS start, "
. "UNIX_TIMESTAMP(bt.end) AS end "
. "FROM blockComputers bc, "
. "blockTimes bt, "
. "blockRequest br "
. "WHERE bt.id = bc.blockTimeid AND "
. "br.id = bt.blockRequestid AND "
. "bt.skip = 0 AND "
. "bt.start < '$maxenddt' AND "
. "bt.end > '$minstartdt' AND ";
if($ingroups != '')
$query .= "(br.groupid NOT IN ($ingroups) OR "
. "br.imageid != $imageid) AND ";
$query .= "bc.computerid IN ($newincompids)";
$qh = doQuery($query);
while($row = mysql_fetch_assoc($qh)) {
if(array_key_exists($row['compid'], $slots))
fATremoveOverlaps($slots, $row['compid'], $row['start'], $row['end'], 0);
}
# remove mac/ip overlaps
$newcompids = array_keys($slots);
$newincompids = implode(',', $newcompids);
if(! empty($ip) || ! empty($mac)) {
$query = "SELECT rs.computerid AS compid, "
. "UNIX_TIMESTAMP(rq.start) AS start, "
. "UNIX_TIMESTAMP(rq.end) AS end "
. "FROM serverrequest s, "
. "request rq, "
. "reservation rs "
. "WHERE s.requestid = rq.id AND "
. "rs.requestid = rq.id AND "
. "rq.start < '$maxenddt' AND "
. "rq.end > '$minstartdt' AND "
. "rs.computerid IN ($newincompids) AND ";
if($reqid != '')
$query .= "rq.id != $reqid AND ";
if(! empty($ip) && ! empty($mac))
$query .= "(s.fixedIP = '$ip' OR s.fixedMAC = '$mac')";
elseif(! empty($ip))
$query .= "s.fixedIP = '$ip'";
elseif(! empty($mac))
$query .= "s.fixedIP = '$mac'";
$qh = doQuery($query);
while($row = mysql_fetch_assoc($qh)) {
if(array_key_exists($row['compid'], $slots))
fATremoveOverlaps($slots, $row['compid'], $row['start'], $row['end'], 0);
}
}
# remove slots overlapping with scheduled maintenance
$query = "SELECT UNIX_TIMESTAMP(start) AS start, "
. "UNIX_TIMESTAMP(end) AS end, "
. "allowreservations "
. "FROM sitemaintenance "
. "WHERE start < '$maxenddt' AND "
. "end > '$minstartdt'";
$qh = doQuery($query);
while($row = mysql_fetch_assoc($qh)) {
foreach(array_keys($slots) AS $compid)
fATremoveOverlaps($slots, $compid, $row['start'], $row['end'],
$row['allowreservations']);
}
$imgdata = getImages(0, $imageid);
$options = array();
foreach($slots AS $comp) {
foreach($comp AS $data) {
$data['duration'] = $data['duration'] - ($data['duration'] % 900);
if(! $extendonly) {
if($data['duration'] > 3600 && $data['duration'] < 7200)
$data['duration'] = 3600;
elseif($data['duration'] > 7200 && $data['duration'] < (SECINDAY * 2))
$data['duration'] = $data['duration'] - ($data['duration'] % 7200);
elseif($data['duration'] > (SECINDAY * 2))
$data['duration'] = $data['duration'] - ($data['duration'] % SECINDAY);
}
# skip computers that have no controlling management node
if(! findManagementNode($data['compid'], $data['start'], 'future'))
continue;
# skip slots that would cause a concurrent use violation
if($imgdata[$imageid]['maxconcurrent'] != NULL &&
fATconcurrentOverlap($data['startts'], $data['duration'], $imageid,
$imgdata[$imageid]['maxconcurrent'], $ignorestates,
$extendonly, $reqid))
continue;
if(array_key_exists($data['startts'], $options)) {
if($data['duration'] > $options[$data['startts']]['duration']) {
$options[$data['startts']]['duration'] = $data['duration'];
if(checkUserHasPerm('View Debug Information'))
$options[$data['startts']]['compid'] = $data['compid'];
}
}
else {
$options[$data['startts']] = array('start' => $data['start'],
'startts' => $data['startts'],
'duration' => $data['duration']);
if(checkUserHasPerm('View Debug Information'))
$options[$data['startts']]['compid'] = $data['compid'];
}
}
}
uasort($options, "sortAvailableTimesByStart");
return $options;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn fATremoveOverlaps($array, $compid, $start, $end, $allowstart)
///
/// \param $array - array of time slots - pass by reference
/// \param $compid - id of computer to check
/// \param $start - start of time period
/// \param $end - end of time period
/// \param $allowstart - whether or not $start can be within $array time slot
///
/// \brief removes timeslots from $array that overlap with $start and $end
///
////////////////////////////////////////////////////////////////////////////////
function fATremoveOverlaps(&$array, $compid, $start, $end, $allowstart) {
foreach($array[$compid] AS $key => $data) {
if($data['startts'] < $end && $data['endts'] > $start) {
# reservation within slot
if($data['startts'] <= $start && $data['endts'] >= $end) {
if($allowstart)
continue;
$test1 = $data['duration'] - ($data['endts'] - $start) - 900;
$test2 = $data['duration'] - ($end - $data['startts']) - 900;
if($test1 < 1800 && $test2 < 1800)
unset($array[$compid][$key]);
elseif($test1 >= 1800 && $test2 < 1800)
$array[$compid][$key]['duration'] = $test1;
elseif($test1 < 1800 && $test2 >= 1800) {
$array[$compid][$key]['duration'] = $test2;
$array[$compid][$key]['startts'] = $end + 900;
$array[$compid][$key]['start'] = unixToDatetime($end + 900);
}
else {
$array[$compid][$key]['duration'] = $test1;
$new = array('duration' => $test2,
'endts' => $end + 900 + $test2,
'compid' => $compid,
'start' => unixToDatetime($end + 900),
'startts' => $end + 900);
$array[$compid][] = $new;
}
}
# start of reservation overlaps slot
elseif($data['startts'] < $start && $data['endts'] > $start) {
if($allowstart)
continue;
$test = $data['duration'] - ($data['endts'] - $start) - 900;
if($test >= 1800)
$array[$compid][$key]['duration'] = $test;
else
unset($array[$compid][$key]);
}
# end of reservation overlaps slot
elseif($data['startts'] < $end && $data['endts'] > $end) {
$test = $data['duration'] - ($end - $data['startts']) - 900;
if($test >= 1800) {
$array[$compid][$key]['duration'] = $test;
$array[$compid][$key]['startts'] = $end + 900;
$array[$compid][$key]['start'] = unixToDatetime($end + 900);
}
else
unset($array[$compid][$key]);
}
# slot within reservation
#if($data['startts'] >= $start && $data['endts'] <= $end)
else
unset($array[$compid][$key]);
}
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn fATconcurrentOverlap($start, $length, $imageid, $maxoverlap,
// $ignorestates, $extendonly, $reqid)
///
/// \param $start - start time (epoch time)
/// \param $length - desired duration in seconds
/// \param $imageid - id of image
/// \param $maxoverlap - max allowed overlapping reservations for image
/// \param $ignorestates - computers with these states should be ignored
/// \param $extendonly - 1 if this is an extension, 0 otherwise
/// \param $reqid - id of request if $extendonly is 1
///
/// \return 1 if this would violate max concurrent use of the image, 0 if not
///
/// \brief determines if a reservation during the specified time slot would
/// violate the max concurrent reservations for $imageid
///
////////////////////////////////////////////////////////////////////////////////
function fATconcurrentOverlap($start, $length, $imageid, $maxoverlap,
$ignorestates, $extendonly, $reqid) {
$end = $start + $length;
$query = "SELECT rq.start, "
. "rq.end "
. "FROM request rq, "
. "reservation rs, "
. "state s, "
. "computer c "
. "WHERE rs.requestid = rq.id AND "
. "rs.computerid = c.id AND "
. "rs.imageid = $imageid AND "
. "UNIX_TIMESTAMP(rq.start) < $end AND "
. "UNIX_TIMESTAMP(rq.end) > $start AND "
. "c.stateid = s.id AND "
. "s.name NOT IN ($ignorestates)";
if($extendonly)
$query .= " AND rq.id != $reqid";
$qh = doQuery($query);
if(mysql_num_rows($qh) >= $maxoverlap)
return 1;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn sortAvailableTimesByStart($a, $b)
///
/// \param $a - first item
/// \param $b - second item
///
/// \return -1 if $a < $b, 0 if $a == $b, 1 if $a > $b
///
/// \brief used to sort suggested times in findAvailableTimes
///
////////////////////////////////////////////////////////////////////////////////
function sortAvailableTimesByStart($a, $b) {
$ats = datetimeToUnix($a['start']);
$bts = datetimeToUnix($b['start']);
if($ats < $bts)
return -1;
if($ats > $bts)
return 1;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getComputers($sort, $includedeleted, $compid)
///
/// \param $sort - (optional) 1 to sort; 0 not to
/// \param $includedeleted = (optional) 1 to show deleted images, 0 not to
/// \param $compid - (optional) only get info for this computer id
///
/// \return an array with info about the computers in the comptuer table; each
/// element's index is the id from the table; each element has the following
/// items\n
/// \b state - current state of the computer\n
/// \b stateid - id of current state\n
/// \b owner - unity id of owner\n
/// \b ownerid - user id of owner\n
/// \b platform - computer's platform\n
/// \b platformid - id of computer's platform\n
/// \b schedule - computer's schedule\n
/// \b scheduleid - id of computer's schedule\n
/// \b currentimg - computer's current image\n
/// \b currentimgid - id of computer's current image\n
/// \b imagerevisionid - revision id of computer's current image\n
/// \b nextimg - computer's next image\n
/// \b nextimgid - id of computer's next image\n
/// \b nextimg - computer's next image\n
/// \b nextimgid - id of computer's next image\n
/// \b ram - amount of RAM in computer in MB\n
/// \b procnumber - number of processors in computer\n
/// \b procspeed - speed of processor(s) in MHz\n
/// \b network - speed of computer's NIC\n
/// \b hostname - computer's hostname\n
/// \b IPaddress - computer's IP address\n
/// \b privateIPaddress - computer's private IP address\n
/// \b eth0macaddress - computer's eth0 mac address\n
/// \b eth1macaddress - computer's eth1 mac address\n
/// \b type - either 'blade' or 'lab' - used to determine what backend utilities\n
/// \b deleted - 0 or 1; whether or not this computer has been deleted\n
/// \b resourceid - computer's resource id from the resource table\n
/// \b location - computer's location\n
/// \b provisioningid - id of provisioning engine\n
/// \b provisioning - pretty name of provisioning engine\n
/// \b vmprofileid - if vmhost, id of vmprofile
/// need to be used to manage computer
///
/// \brief builds an array of computers
///
////////////////////////////////////////////////////////////////////////////////
function getComputers($sort=0, $includedeleted=0, $compid="") {
$return = array();
$query = "SELECT c.id AS id, "
. "st.name AS state, "
. "c.stateid AS stateid, "
. "CONCAT(u.unityid, '@', a.name) AS owner, "
. "u.id AS ownerid, "
. "p.name AS platform, "
. "c.platformid AS platformid, "
. "sc.name AS schedule, "
. "c.scheduleid AS scheduleid, "
. "cur.name AS currentimg, "
. "c.currentimageid AS currentimgid, "
. "c.imagerevisionid, "
. "next.name AS nextimg, "
. "c.nextimageid AS nextimgid, "
. "c.RAM AS ram, "
. "c.procnumber AS procnumber, "
. "c.procspeed AS procspeed, "
. "c.network AS network, "
. "c.hostname AS hostname, "
. "c.IPaddress AS IPaddress, "
. "c.privateIPaddress, "
. "c.eth0macaddress, "
. "c.eth1macaddress, "
. "c.type AS type, "
. "c.deleted AS deleted, "
. "r.id AS resourceid, "
. "c.notes, "
. "c.vmhostid, "
. "c2.hostname AS vmhost, "
. "c.location, "
. "c.provisioningid, "
. "pr.prettyname AS provisioning, "
. "vh2.vmprofileid "
. "FROM state st, "
. "platform p, "
. "schedule sc, "
. "image cur, "
. "resource r, "
. "resourcetype t, "
. "user u, "
. "affiliation a, "
. "computer c "
. "LEFT JOIN vmhost vh ON (c.vmhostid = vh.id) "
. "LEFT JOIN vmhost vh2 ON (c.id = vh2.computerid) "
. "LEFT JOIN computer c2 ON (c2.id = vh.computerid) "
. "LEFT JOIN image next ON (c.nextimageid = next.id) "
. "LEFT JOIN provisioning pr ON (c.provisioningid = pr.id) "
. "WHERE c.stateid = st.id AND "
. "c.platformid = p.id AND "
. "c.scheduleid = sc.id AND "
. "c.currentimageid = cur.id AND "
. "r.resourcetypeid = t.id AND "
. "t.name = 'computer' AND "
. "r.subid = c.id AND "
. "c.ownerid = u.id AND "
. "u.affiliationid = a.id ";
if(! $includedeleted)
$query .= "AND c.deleted = 0 ";
if(! empty($compid))
$query .= "AND c.id = $compid ";
$query .= "ORDER BY c.hostname";
$qh = doQuery($query, 180);
while($row = mysql_fetch_assoc($qh)) {
$return[$row['id']] = $row;
}
if($sort) {
uasort($return, "sortComputers");
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUserComputerMetaData()
///
/// \return an array of 2 indices - platforms, schedules - where each
/// index's value is an array of user's computer's data
///
/// \brief builds an array of platforms and schedules for user's computers
///
////////////////////////////////////////////////////////////////////////////////
function getUserComputerMetaData() {
$key = getKey(array('getUserComputerMetaData'));
if(array_key_exists($key, $_SESSION['usersessiondata']))
return $_SESSION['usersessiondata'][$key];
$computers = getComputers();
$resources = getUserResources(array("computerAdmin"),
array("administer", "manageGroup"), 0, 1);
$return = array("platforms" => array(),
"schedules" => array());
foreach(array_keys($resources["computer"]) as $compid) {
if(! array_key_exists($compid, $computers))
continue;
if(! in_array($computers[$compid]["platform"], $return["platforms"]))
$return["platforms"][$computers[$compid]["platformid"]] =
$computers[$compid]["platform"];
if(! in_array($computers[$compid]["schedule"], $return["schedules"]))
$return["schedules"][$computers[$compid]["scheduleid"]] =
$computers[$compid]["schedule"];
}
uasort($return["platforms"], "sortKeepIndex");
uasort($return["schedules"], "sortKeepIndex");
$_SESSION['usersessiondata'][$key] = $return;
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getCompStateFlow($compid)
///
/// \param $compid - a computer id
///
/// \return an array of data about the flow of states for $compid; the following
/// keys and elements are returned:\n
/// \b repeatid - id from computerloadstate for the repeat state\n
/// \b stateids - array of computerloadstate ids for this flow in the order
/// they occur\n
/// \b nextstates - array where each key is a computerloadstate id and its value
/// is that state's following state; the last state has a NULL value\n
/// \b totaltime - estimated time (in seconds) it takes for all states to
/// complete\n
/// \b data - array where each key is is a computerloadstate id and each value
/// is an array with these elements:\n
/// \b stateid - same as key\n
/// \b state - name of this state\n
/// \b nextstateid - id of next state\n
/// \b nextstate - name of next state\n
/// \b statetime - estimated time it takes for this state to complete
///
/// \brief gathers information about the flow of states for $compid
///
////////////////////////////////////////////////////////////////////////////////
function getCompStateFlow($compid) {
$key = getKey(array($compid));
if(array_key_exists($key, $_SESSION['compstateflow']))
return $_SESSION['compstateflow'][$key];
# get id for repeat state, useful because several of the calling functions
# need this information
$query = "SELECT id FROM computerloadstate WHERE loadstatename = 'repeat'";
$qh = doQuery($query, 101);
if(! $row = mysql_fetch_assoc($qh))
return array();
$loadstates['repeatid'] = $row['id'];
$query = "SELECT `type` FROM computer WHERE id = $compid";
$qh = doQuery($query, 101);
if(! $row = mysql_fetch_assoc($qh))
return array();
$type = $row['type'];
$query = "SELECT cf.computerloadstateid AS stateid, "
. "cs1.prettyname AS state, "
. "cs1.loadstatename AS statename, "
. "cf.nextstateid, "
. "cs2.prettyname AS nextstate, "
. "cs1.est AS statetime "
. "FROM computerloadstate cs1, "
. "computerloadflow cf "
. "LEFT JOIN computerloadstate cs2 ON (cf.nextstateid = cs2.id) "
. "WHERE cf.computerloadstateid = cs1.id AND "
. "cf.type = '$type' ";
$query2 = $query . "AND cf.computerloadstateid NOT IN "
. "(SELECT nextstateid FROM computerloadflow WHERE `type` = '$type' "
. "AND nextstateid IS NOT NULL)";
$qh = doQuery($query2, 101);
if(! $row = mysql_fetch_assoc($qh))
return array();
$loadstates['data'][$row['stateid']] = $row;
$loadstates['stateids'] = array($row['stateid']);
$loadstates['nextstates'] = array($row['stateid'] => $row['nextstateid']);
$loadstates['totaltime'] = 0;
for($i = 0; $i < 100; $i++) { # don't want an endless loop
$query2 = $query . "AND cf.computerloadstateid = {$row['nextstateid']} "
. "AND `type` = '$type'";
$qh = doQuery($query2, 101);
if(! $row = mysql_fetch_assoc($qh)) {
$_SESSION['compstateflow'][$key] = $loadstates;
return $loadstates;
}
else {
array_push($loadstates['stateids'], $row['stateid']);
$loadstates['nextstates'][$row['stateid']] = $row['nextstateid'];
$loadstates['totaltime'] += $row['statetime'];
$loadstates['data'][$row['stateid']] = $row;
}
if(empty($row['nextstateid'])) {
$_SESSION['compstateflow'][$key] = $loadstates;
return $loadstates;
}
}
$_SESSION['compstateflow'][$key] = $loadstates;
return $loadstates;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getCompLoadLog($resid)
///
/// \param $resid - reservation id
///
/// \return an array where each key is an id from the computerloadlog table and
/// each element is an array with these items:\n
/// \b computerid - id of computer\n
/// \b loadstateid - load id of this state\n
/// \b ts - unix timestamp when item entered in log\n
/// \b time - actual time (in seconds) this state took
///
/// \brief gets information from the computerloadlog table for $resid
///
////////////////////////////////////////////////////////////////////////////////
function getCompLoadLog($resid) {
$query = "SELECT UNIX_TIMESTAMP(rq.start) AS start, "
. "UNIX_TIMESTAMP(rq.daterequested) AS reqtime, "
. "rs.computerid "
. "FROM request rq, "
. "reservation rs "
. "WHERE rs.id = $resid AND "
. "rs.requestid = rq.id "
. "LIMIT 1";
$qh = doQuery($query, 101);
if(! $row = mysql_fetch_assoc($qh))
abort(113);
if($row['start'] < $row['reqtime']) {
# now
$reqtime = $row['reqtime'];
$future = 0;
}
else
$future = 1;
$flow = getCompStateFlow($row['computerid']);
$instates = implode(',', $flow['stateids']);
$query = "SELECT id, "
. "computerid, "
. "loadstateid, "
. "UNIX_TIMESTAMP(timestamp) AS ts "
. "FROM computerloadlog "
. "WHERE reservationid = $resid AND "
. "(loadstateid IN ($instates) OR "
. "loadstateid = {$flow['repeatid']}) "
. "ORDER BY id";
$qh = doQuery($query, 101);
$last = array();
$data = array();
while($row = mysql_fetch_assoc($qh)) {
$data[$row['id']] = $row;
if(empty($last)) {
if($future)
# just set to 10 sec for first state since we don't know when a preload started
$data[$row['id']]['time'] = 10;
else
$data[$row['id']]['time'] = $row['ts'] - $reqtime;
}
else
$data[$row['id']]['time'] = $row['ts'] - $last['ts'];
$last = $row;
}
return $data;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getImageLoadEstimate($imageid)
///
/// \param $imageid - id of an image
///
/// \return estimated time in seconds that it takes to load $imageid
///
/// \brief determines an estimated load time (in seconds) that it takes $imageid
/// to load based on the last 12 months of log data
///
////////////////////////////////////////////////////////////////////////////////
function getImageLoadEstimate($imageid) {
$query = "SELECT AVG(UNIX_TIMESTAMP(loaded) - UNIX_TIMESTAMP(start)) AS avgloadtime "
. "FROM log "
. "WHERE imageid = $imageid AND "
. "wasavailable = 1 AND "
. "UNIX_TIMESTAMP(loaded) - UNIX_TIMESTAMP(start) > 120 AND "
. "loaded > start AND "
. "ending != 'failed' AND "
. "nowfuture = 'now' AND "
. "start > (NOW() - INTERVAL 12 MONTH) AND "
. "UNIX_TIMESTAMP(loaded) - UNIX_TIMESTAMP(start) < 1800";
$qh = doQuery($query, 101);
if($row = mysql_fetch_assoc($qh)) {
if(! empty($row['avgloadtime']))
return (int)$row['avgloadtime'];
else
return 0;
}
else
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getComputerCounts(&$computers)
///
/// \param $computers - array returned from getComputers
///
/// \brief adds a "counts" field for each computer in $computers that is the
/// total number of reservations that computer has had
///
////////////////////////////////////////////////////////////////////////////////
function getComputerCounts(&$computers) {
foreach(array_keys($computers) as $compid) {
$query = "SELECT COUNT(logid) "
. "FROM sublog "
. "WHERE computerid = $compid";
$qh = doQuery($query, 101);
if($row = mysql_fetch_row($qh))
$computers[$compid]["counts"] = $row[0];
else
$computers[$compid]["counts"] = 0;
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn sortComputers($a, $b)
///
/// \param $a - first input passed in by uasort
/// \param $b - second input passed in by uasort
///
/// \return -1, 0, or 1 if $a < $b, $a == $b, $a > $b, respectively
///
/// \brief determines if $a should go before or after $b
///
////////////////////////////////////////////////////////////////////////////////
function sortComputers($a, $b) {
//if somehow there are empty strings passed in, push them to the end
if(empty($a)) {
return 1;
}
if(empty($b)) {
return -1;
}
# get hostname and first part of domain name
$tmp = explode('.', $a["hostname"]);
$h1 = array_shift($tmp);
$domain1 = array_shift($tmp);
$letters1 = preg_replace('([^a-zA-Z])', '', $h1);
$tmp = explode('.', $b["hostname"]);
$h2 = array_shift($tmp);
$domain2 = array_shift($tmp);
$letters2 = preg_replace('([^a-zA-Z])', '', $h2);
// if different domain names, return based on that
$cmp = strcasecmp($domain1, $domain2);
if($cmp) {
return $cmp;
}
// if non-numeric part is different, return based on that
$cmp = strcasecmp($letters1, $letters2);
if($cmp) {
return $cmp;
}
// at this point, the only difference is in the numbers
$digits1 = preg_replace('([^\d-])', '', $h1);
$digits1Arr = explode('-', $digits1);
$digits2 = preg_replace('([^\d-])', '', $h2);
$digits2Arr = explode('-', $digits2);
$len1 = count($digits1Arr);
$len2 = count($digits2Arr);
for($i = 0; $i < $len1 && $i < $len2; $i++) {
if($digits1Arr[$i] < $digits2Arr[$i]) {
return -1;
}
elseif($digits1Arr[$i] > $digits2Arr[$i]) {
return 1;
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getAvailableBlockComputerids($imageid, $start, $end, $allocatedcompids)
///
/// \param $imageid - id of an image
/// \param $start - starting time in unix timestamp form
/// \param $end - ending time in unix timestamp form
/// \param $allocatedcompids - array of computer ids that have already been
/// allocated while processing this reservation
///
/// \return an array with the key 'compids' that is an array of available
/// computerids; additional keys exist for each computerid that are arrays
/// of block data for that computer with these keys:\n
/// \b start - start of block time\n
/// \b end - end of block time\n
/// \b blockid - id of block request
///
/// \brief gets all computer ids that are part of a block allocation the logged
/// in user is a part of that are available between $start and $end
///
////////////////////////////////////////////////////////////////////////////////
function getAvailableBlockComputerids($imageid, $start, $end, $allocatedcompids) {
global $user;
$data = array('compids' => array());
$groupids = implode(',', array_keys($user['groups']));
if(! count($user['groups']))
$groupids = "''";
$startdt = unixToDatetime($start);
$enddt = unixToDatetime($end);
$alloccompids = implode(",", $allocatedcompids);
$query = "SELECT c.computerid, "
. "t.start, "
. "t.end, "
. "r.id AS blockid "
. "FROM blockComputers c, "
. "blockRequest r, "
. "blockTimes t, "
. "state s, "
. "computer c2 "
. "WHERE r.groupid IN ($groupids) AND "
. "r.status = 'accepted' AND "
. "c.computerid = c2.id AND "
. "c2.currentimageid = $imageid AND "
. "r.expireTime > NOW() AND "
. "t.blockRequestid = r.id AND "
. "c.blockTimeid = t.id AND "
. "t.start < '$enddt' AND "
. "t.end > '$startdt' AND "
. "c2.stateid = s.id AND "
. "s.name != 'failed' AND "
. "c2.id NOT IN ($alloccompids) "
. "ORDER BY s.name";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$data['compids'][] = $row['computerid'];
$data[$row['computerid']] = $row;
}
return $data;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getUsedBlockComputerids($start, $end)
///
/// \param $start - starting time in unix timestamp form
/// \param $end - ending time in unix timestamp form
///
/// \return array of computer ids
///
/// \brief gets a list of all computerids that are allocated to block
/// allocations during the given times
///
////////////////////////////////////////////////////////////////////////////////
function getUsedBlockComputerids($start, $end) {
$compids = array();
$startdt = unixToDatetime($start);
$enddt = unixToDatetime($end);
$query = "SELECT c.computerid "
. "FROM blockComputers c, "
. "blockTimes t "
. "WHERE t.end > '$startdt' AND "
. "t.start < '$enddt' AND "
. "c.blockTimeid = t.id";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
array_push($compids, $row['computerid']);
}
return $compids;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn getBlockTimeData($start, $end)
///
/// \param $start - (optional) start time of blockTimes to get in unix timestamp
/// form
/// \param $end - (optional) end time of blockTimes to get in unix timestamp
/// form
///
/// \return an array of block allocation data where each index in a blockTime id
/// and the value is an array with these elements:\n
/// \b blockid - id of block allocation\n
/// \b name - name of block allocation\n
/// \b imageid - id of selected image\n
/// \b image - name of selected image\n
/// \b numMachines - number of machines allocated\n
/// \b groupid - user group associated with allocation\n
/// \b repeating - weekly, monthly, or list\n
/// \b ownerid - id from user table of the owner\n
/// \b admingroupid - admin user group associated with allocation\n
/// \b managementnodeid - id of management node handling allocation\n
/// \b expireTime - time at which the allocation will be completely finished\n
/// \b timeid - id of blockTimes entry\n
/// \b start - dattime for starting time of block time\n
/// \b end - dattime for ending time of block time\n
/// \b unixstart - unix timestamp for starting time of block time\n
/// \b unixend - unix timestamp for ending time of block time\n
/// \b computerids - array of computer ids allocated for the block time
///
/// \brief builds an array of block allocation data
///
////////////////////////////////////////////////////////////////////////////////
function getBlockTimeData($start="", $end="") {
$return = array();
$query = "SELECT r.id AS blockid, "
. "r.name, "
. "r.imageid, "
. "i.prettyname AS image, "
. "r.numMachines, "
. "r.groupid, "
. "r.repeating, "
. "r.ownerid, "
. "r.admingroupid, "
. "r.managementnodeid, "
. "r.expireTime, "
. "t.id AS timeid, "
. "t.start, "
. "t.end "
. "FROM blockRequest r, "
. "blockTimes t, "
. "image i "
. "WHERE r.id = t.blockRequestid AND "
. "r.status = 'accepted' AND "
. "r.imageid = i.id";
if(! empty($start))
$query .= " AND t.start < '" . unixToDatetime($end) . "'";
if(! empty($end))
$query .= " AND t.end > '" . unixToDatetime($start) . "'";
$query .= " ORDER BY t.start, t.end";
$qh = doQuery($query, 101);
while($row = mysql_fetch_assoc($qh)) {
$return[$row['timeid']] = $row;
$return[$row['timeid']]['unixstart'] = datetimeToUnix($row['start']);
$return[$row['timeid']]['unixend'] = datetimeToUnix($row['end']);
$return[$row['timeid']]['computerids'] = array();
$query2 = "SELECT computerid "
. "FROM blockComputers "
. "WHERE blockTimeid = {$row['timeid']}";
$qh2 = doQuery($query2, 101);
while($row2 = mysql_fetch_assoc($qh2))
array_push($return[$row['timeid']]['computerids'], $row2['computerid']);
}
return $return;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn isBlockAllocationTime($compid, $ts, $blockData)
///
/// \param $compid - a computer id
/// \param $ts - a timestamp
/// \param $blockData - an array as returned from getBlockTimeData
///
/// \return the blockTimeid $ts falls in to if it does; 0 if it doesn't fall
/// into any block times
///
/// \brief determines if $ts falls into a block time $compid is part of
///
////////////////////////////////////////////////////////////////////////////////
function isBlockAllocationTime($compid, $ts, $blockData) {
foreach(array_keys($blockData) as $timeid) {
if(in_array($compid, $blockData[$timeid]['computerids']) &&
$ts >= $blockData[$timeid]['unixstart'] &&
$ts < $blockData[$timeid]['unixend'])
return $timeid;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn isImageBlockTimeActive($imageid)
///
/// \param $imageid - id of an image
///
/// \return 1 if a block time for a block allocation for $imageid has had the
/// processed flag set and the end time has not been reached; 0 otherwise
///
/// \brief checks to see if a block time for $imageid has been processed but not
/// yet ended
///
////////////////////////////////////////////////////////////////////////////////
function isImageBlockTimeActive($imageid) {
$now = time();
$nowdt = unixToDatetime($now);
$query = "SELECT bt.id "
. "FROM blockTimes bt, "
. "blockRequest br "
. "WHERE bt.blockRequestid = br.id AND "
. "bt.processed = 1 AND "
. "bt.end > '$nowdt' AND "
. "br.imageid = $imageid";
$qh = doQuery($query, 101);
if($row = mysql_fetch_assoc($qh))
return 1;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn printSelectInput($name, $dataArr, $selectedid, $skip, $multiple, $domid,
/// $extra)
///
/// \param $name - name of input element
/// \param $dataArr - array containing options
/// \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
/// \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
/// for the select object
/// \param $extra - (optional) any extra attributes that need to be set
///
/// \brief prints out a select input part of a form\n
/// 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 printSelectInput($name, $dataArr, $selectedid=-1, $skip=0, $multiple=0,
$domid="", $extra="") {
if(! empty($domid))
$domid = "id=\"$domid\"";
if($multiple)
$multiple = "multiple";
else
$multiple = "";
if($name != '')
print "