= to the minimum required. # The trust value can be either numeric or a string; if a string its # first converted to the numeric equiv. # function TBMinTrust($trust_value, $minimum) { global $TBDB_TRUST_NONE; global $TBDB_TRUST_ADMIN; if ($minimum < $TBDB_TRUST_NONE || $minimum > $TBDB_TRUST_ADMIN) { TBERROR("Invalid minimum trust $minimum!", 1); } # # Sleazy? # if (gettype($trust_value) == "string") { $trust_value = TBTrustConvert($trust_value); } return $trust_value >= $minimum; } # # Determine the trust level for a uid/pid/gid. That is, each uid will have # a different trust level depending on the project/group in question. # Return that trust level as one of the numeric values above. # function TBGrpTrust($uid, $pid, $gid) { global $TBDB_TRUST_NONE; # # No group, then use the default group. # if (! $gid) { $gid = $pid; } $query_result = DBQueryFatal("select trust from group_membership ". "where uid='$uid' and pid='$pid' and gid='$gid'"); # # No membership is the same as no trust. True? Maybe an error instead? # if (mysql_num_rows($query_result) == 0) { return $TBDB_TRUST_NONE; } $row = mysql_fetch_array($query_result); $trust_string = $row[trust]; return TBTrustConvert($trust_string); } # # Determine the project trust level for a uid/pid. This is the trust level # for the default group in the project. # function TBProjTrust($uid, $pid) { return TBGrpTrust($uid, $pid, $pid); } # # Project permission checks. The group id (gid) can be zero, in which case # the pid is used (ie: a default group check is made). # # Usage: TBProjAccessCheck($uid, $pid, $gid, $access_type) # returns 0 if not allowed. # returns 1 if allowed. # function TBProjAccessCheck($uid, $pid, $gid, $access_type) { global $TB_PROJECT_READINFO; global $TB_PROJECT_MAKEGROUP; global $TB_PROJECT_EDITGROUP; global $TB_PROJECT_GROUPGRABUSERS; global $TB_PROJECT_BESTOWGROUPROOT; global $TB_PROJECT_DELGROUP; global $TB_PROJECT_LEADGROUP; global $TB_PROJECT_ADDUSER; global $TB_PROJECT_DELUSER; global $TB_PROJECT_MAKEOSID; global $TB_PROJECT_DELOSID; global $TB_PROJECT_MAKEIMAGEID; global $TB_PROJECT_DELIMAGEID; global $TB_PROJECT_CREATEEXPT; global $TB_PROJECT_MIN; global $TB_PROJECT_MAX; global $TBDB_TRUST_USER; global $TBDB_TRUST_LOCALROOT; global $TBDB_TRUST_GROUPROOT; global $TBDB_TRUST_PROJROOT; $mintrust; if ($access_type < $TB_PROJECT_MIN || $access_type > $TB_PROJECT_MAX) { TBERROR("Invalid access type: $access_type!", 1); } # # Admins do whatever they want! # if (ISADMIN($uid)) { return 1; } # # No group, then use the default group. # if (! $gid) { $gid = $pid; } if ($access_type == $TB_PROJECT_READINFO) { $mintrust = $TBDB_TRUST_USER; } elseif ($access_type == $TB_PROJECT_MAKEGROUP || $access_type == $TB_PROJECT_DELGROUP) { $mintrust = $TBDB_TRUST_GROUPROOT; } elseif ($access_type == $TB_PROJECT_LEADGROUP) { # # Allow mere user (in default group) to lead a subgroup. # $mintrust = $TBDB_TRUST_USER; } elseif ($access_type == $TB_PROJECT_MAKEOSID || $access_type == $TB_PROJECT_MAKEIMAGEID || $access_type == $TB_PROJECT_CREATEEXPT) { $mintrust = $TBDB_TRUST_LOCALROOT; } elseif ($access_type == $TB_PROJECT_ADDUSER || $access_type == $TB_PROJECT_EDITGROUP) { # # If user is project_root or group_root in default group, # allow them to add/edit/remove users in any group. # if (TBMinTrust(TBGrpTrust($uid, $pid, $pid), $TBDB_TRUST_GROUPROOT)) { return 1; } # # Otherwise, editing a group requires group_root # in that group. # $mintrust = $TBDB_TRUST_GROUPROOT; } elseif ($access_type == $TB_PROJECT_BESTOWGROUPROOT) { # # If user is project_root, # allow them to bestow group_root in any group. # if (TBMinTrust(TBGrpTrust($uid, $pid, $pid), $TBDB_TRUST_PROJROOT)) { return 1; } if (strcmp($gid, $pid) == 0) { # # Only project_root can bestow group_root in default group, and # we already established that they are not project_root, so fail. # return 0; } else { # # Non-default group. # group_root in default group may bestow group_root. # if (TBMinTrust(TBGrpTrust($uid, $pid, $pid), $TBDB_TRUST_GROUPROOT)) { return 1; } # # group_root in the group in question may also bestow group_root. # $mintrust = $TBDB_TRUST_GROUPROOT; } } elseif ($access_type == $TB_PROJECT_GROUPGRABUSERS) { # # Only project_root or group_root in default group # may grab (involuntarily add) users into groups. # $gid = $pid; $mintrust = $TBDB_TRUST_GROUPROOT; } elseif ($access_type == $TB_PROJECT_DELUSER) { $mintrust = $TBDB_TRUST_PROJROOT; } else { TBERROR("Unexpected access type: $access_type!", 1); } return TBMinTrust(TBGrpTrust($uid, $pid, $gid), $mintrust); } # # Checks proposed Group trust change for consistency. # # Usage: TBCheckGroupTrustConsistency($user, $pid, $gid, $newtrust, $fail) # returns 1 if proposed change is valid # returns 0 if proposed change is invalid and $fail == 0 # does not return if proposed change is invalid and $fail == 1. # function TBCheckGroupTrustConsistency($user, $pid, $gid, $newtrust, $fail) { global $TBDB_TRUST_USER; # # set $newtrustisroot to 1 if attempting to set a rootful trust, # 0 otherwise. # $newtrustisroot = TBTrustConvert($newtrust) > $TBDB_TRUST_USER ? 1 : 0; # # If changing subgroup trust level, then compare levels. # A user may not have root privs in the project and user privs # in the subgroup; it makes no sense to do that and can violate trust. # if (strcmp($pid, $gid)) { # # Setting non-default "sub"group. # Verify that if user has root in project, # we are setting a rootful trust for him in # the subgroup as well. # $projtrustisroot = TBProjTrust($user, $pid) > $TBDB_TRUST_USER ? 1 : 0; if ($projtrustisroot > $newtrustisroot) { if (!$fail) { return 0; } TBERROR("User $user may not have a root trust level in ". "the default group of $pid, ". "yet be non-root in subgroup $gid!", 1); } } else { # # Setting default group. # Don't verify anything (yet.) # $projtrustisroot = $newtrustisroot; } # # Get all the subgroups not equal to the subgroup being changed. # $query_result = DBQueryFatal("select trust,gid from group_membership ". "where uid='$user' and pid='$pid' and trust!='none' ". " and gid!=pid and gid!='$gid'"); while ($row = mysql_fetch_array($query_result)) { $grptrust = $row[0]; $ogid = $row[1]; # # Get what the user's trust level is in the # current subgroup we're looking at. # $grptrustisroot = TBTrustConvert( $grptrust ) > $TBDB_TRUST_USER ? 1 : 0; # # If user's trust level is higher in the default group than in the # subgroup we are looking at, this is wrong. # if ($projtrustisroot > $grptrustisroot) { if (!$fail) { return 0; } TBERROR("User $user may not have a root trust level in ". "the default group of $pid, ". "yet be non-root in subgroup $ogid!", 1); } if (strcmp($pid, $gid)) { # # Iff we're modifying a subgroup, # Make sure that the trust we're setting is as # rootful as the trust we already have set in # every other subgroup. # if ($newtrustisroot != $grptrustisroot) { if (!$fail) { return 0; } TBERROR("User $user may not mix root and ". "non-root trust levels in ". "different subgroups of $pid!", 1); } } } return 1; } # Usage: TBExptGroup($pid, $eid, &$gid) # returns 0 if expt doesn't exist. # returns 1 if expt exists. function TBExptGroup($pid, $eid, &$gid) { $query_result = DBQueryFatal("SELECT gid FROM experiments WHERE ". "eid='$eid' and pid='$pid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $gid = $row[gid]; return 1; } # # Experiment permission checks. # # Usage: TBExptAccessCheck($uid, $pid, $eid, $access_type) # returns 0 if not allowed. # returns 1 if allowed. # function TBExptAccessCheck($uid, $pid, $eid, $access_type) { global $TB_EXPT_READINFO; global $TB_EXPT_MODIFY; global $TB_EXPT_DESTROY; global $TB_EXPT_UPDATEACCOUNTS; global $TB_EXPT_MIN; global $TB_EXPT_MAX; global $TBDB_TRUST_USER; global $TBDB_TRUST_LOCALROOT; global $TBDB_TRUST_GROUPROOT; global $TBDB_TRUST_PROJROOT; $mintrust; if ($access_type < $TB_EXPT_MIN || $access_type > $TB_EXPT_MAX) { TBERROR("Invalid access type: $access_type!", 1); } # # Admins do whatever they want! # if (ISADMIN($uid)) { return 1; } $query_result = DBQueryFatal("SELECT gid,expt_head_uid FROM experiments WHERE ". "eid='$eid' and pid='$pid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $gid = $row[gid]; $head = $row[expt_head_uid]; if ($access_type == $TB_EXPT_READINFO) { $mintrust = $TBDB_TRUST_USER; } else { $mintrust = $TBDB_TRUST_LOCALROOT; } # # Either proper permission in the group, or group_root in the project. # This lets group_roots muck with other peoples experiments, including # those in groups they do not belong to. # return TBMinTrust(TBGrpTrust($uid, $pid, $gid), $mintrust) || TBMinTrust(TBGrpTrust($uid, $pid, $pid), $TBDB_TRUST_GROUPROOT); } # # Determine if uid can access a node (read or modify). # # Usage: TBNodeAccessCheck($uid, $node_id, $access_type) # returns 0 if not allowed. # returns 1 if allowed. # function TBNodeAccessCheck($uid, $node_id, $access_type) { global $TB_NODEACCESS_READINFO; global $TB_NODEACCESS_MODIFYINFO; global $TB_NODEACCESS_LOADIMAGE; global $TB_NODEACCESS_REBOOT; global $TB_NODEACCESS_POWERCYCLE; global $TB_NODEACCESS_MIN; global $TB_NODEACCESS_MAX; global $TBDB_TRUST_USER; global $TBDB_TRUST_LOCALROOT; $mintrust; if ($access_type < $TB_NODEACCESS_MIN || $access_type > $TB_NODEACCESS_MAX) { TBERROR("Invalid access type: $access_type!", 1); } $query_result = DBQueryFatal("select e.pid,e.gid from reserved as r ". "left join experiments as e on ". " e.pid=r.pid and e.eid=r.eid ". "where r.node_id='$node_id'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $pid = $row[pid]; $gid = $row[gid]; if ($access_type == $TB_NODEACCESS_READINFO) { $mintrust = $TBDB_TRUST_USER; } else { $mintrust = $TBDB_TRUST_LOCALROOT; } return TBMinTrust(TBGrpTrust($uid, $pid, $gid), $mintrust) || TBMinTrust(TBGrpTrust($uid, $pid, $pid), $TBDB_TRUST_GROUPROOT); } # # Determine if uid can access a another user record (read or modify). # # Usage: TBUserInfoAccessCheck($uid, $target_uid, $access_type) # returns 0 if not allowed. # returns 1 if allowed. # function TBUserInfoAccessCheck($uid, $target_uid, $access_type) { global $TB_USERINFO_READINFO; global $TB_USERINFO_MODIFYINFO; global $TB_USERINFO_MIN; global $TB_USERINFO_MAX; if ($access_type < $TB_USERINFO_MIN || $access_type > $TB_USERINFO_MAX) { TBERROR("Invalid access type $access_type!", 1); } if (strcmp($uid, $target_uid) == 0) { return 1; } # # Admins do whatever they want! # if (ISADMIN($uid)) { return 1; } # # This join will allow the operation if the current user is in the same # group (any group) as the target user, but with root permissions. # $query_result = DBQueryFatal("select g.trust from group_membership as g ". "left join group_membership as authed on ". " g.pid=authed.pid and g.gid=authed.gid and ". " g.uid='$target_uid' ". "where authed.uid='$uid' and ". " (authed.trust='group_root' or ". " authed.trust='project_root')"); if (mysql_num_rows($query_result) == 0) { return 0; } return 1; } # # Access checks for an OSID. Tests for tbadmin. # # Usage: TBOSIDAccessCheck($uid, $osid, $access_type) # returns 0 if not allowed. # returns 1 if allowed. # function TBOSIDAccessCheck($uid, $osid, $access_type) { global $TB_OSID_READINFO; global $TB_OSID_MODIFYINFO; global $TB_OSID_DESTROY; global $TB_OSID_MIN; global $TB_OSID_MAX; global $TBDB_TRUST_USER; global $TBDB_TRUST_LOCALROOT; $mintrust; if ($access_type < $TB_OSID_MIN || $access_type > $TB_OSID_MAX) { TBERROR("Invalid access type $access_type!", 1); } # # Admins do whatever they want! # if (ISADMIN($uid)) { return 1; } # # No GIDs yet. # $query_result = DBQueryFatal("SELECT pid,shared FROM os_info WHERE osid='$osid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $pid = $row[pid]; $shared = $row[shared]; # # Global OSIDs can be read by anyone. # if ($shared) { if ($access_type == $TB_OSID_READINFO) { return 1; } return 0; } # # Otherwise must have proper trust in the project. # if ($access_type == $TB_OSID_READINFO) { $mintrust = $TBDB_TRUST_USER; } else { $mintrust = $TBDB_TRUST_LOCALROOT; } return TBMinTrust(TBProjTrust($uid, $pid), $mintrust); } # # Access checks for an ImageID # # Usage: TBImageIDAccessCheck($uid, $imageid, $access_type) # returns 0 if not allowed. # returns 1 if allowed. # function TBImageIDAccessCheck($uid, $imageid, $access_type) { global $TB_IMAGEID_READINFO; global $TB_IMAGEID_MODIFYINFO; global $TB_IMAGEID_DESTROY; global $TB_IMAGEID_ACCESS; global $TB_IMAGEID_MIN; global $TB_IMAGEID_MAX; global $TBDB_TRUST_USER; global $TBDB_TRUST_LOCALROOT; $mintrust; if ($access_type < $TB_IMAGEID_MIN || $access_type > $TB_IMAGEID_MAX) { TBERROR("Invalid access type $access_type!", 1); } # # Admins do whatever they want! # if (ISADMIN($uid)) { return 1; } $query_result = DBQueryFatal("SELECT pid,gid,shared,global FROM images ". "WHERE imageid='$imageid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $shared = $row[shared]; $global = $row["global"]; $pid = $row[pid]; $gid = $row[gid]; # # Global ImageIDs can be read by anyone but written by Admins only. # if ($global) { if ($access_type == $TB_IMAGEID_READINFO) { return 1; } return 0; } # # Otherwise must have proper trust in the project. # if ($access_type == $TB_IMAGEID_READINFO) { $mintrust = $TBDB_TRUST_USER; # # Shared imageids are readable by anyone in the project. # if ($shared) $gid = $pid; } else { $mintrust = $TBDB_TRUST_LOCALROOT; } return TBMinTrust(TBGrpTrust($uid, $pid, $gid), $mintrust) || TBMinTrust(TBGrpTrust($uid, $pid, $pid), $TBDB_TRUST_GROUPROOT); } # # Return the Unix GID Name and Number for a group. This is distinct from # the name we use within the Testbed system. # # usage: TBGroupUnixInfo($pid, $gid, &$unix_gid, &$unix_name) # function TBGroupUnixInfo($pid, $gid, &$unix_gid, &$unix_name) { $query_result = DBQueryFatal("select unix_name,unix_gid from groups ". "where pid='$pid' and gid='$gid'"); if (mysql_num_rows($query_result) == 0) { TBERROR("No such group $gid in project $pid!", 1); } $row = mysql_fetch_array($query_result); $unix_gid = $row[unix_gid]; $unix_name = $row[unix_name]; } # # Get name and email info for a uid. Args are pass by reference. # # usage: TBUserInfo($uid, $user_name, $user_email) # function TBUserInfo($uid, &$user_name, &$user_email) { $query_result = DBQueryFatal("select usr_name,usr_email from users where uid='$uid'"); if (mysql_num_rows($query_result) == 0) { TBERROR("No such user $uid!", 1); } $row = mysql_fetch_array($query_result); $user_name = $row[usr_name]; $user_email = $row[usr_email]; } # # Confirm a current user or not. # # usage TBCurrentUser($uid) # returns 1 if a valid user. # returns 0 if not a valid user. # function TBCurrentUser($uid) { $query_result = DBQueryFatal("SELECT usr_pswd FROM users WHERE uid='$uid'"); return mysql_num_rows($query_result); } # # Get user status, # # usage TBUserStatus($uid) # returns status if a valid user. # returns 0 if not a valid user. # function TBUserStatus($uid) { $query_result = DBQueryFatal("SELECT status FROM users WHERE uid='$uid'"); if (! mysql_num_rows($query_result)) { return 0; } $row = mysql_fetch_row($query_result); return $row[0]; } # # Confirm a valid pid/gid # # usage TBValidGroup($pid, $gid) # returns 1 if a valid group. # returns 0 if not a valid group # function TBValidGroup($pid, $gid) { $query_result = DBQueryFatal("select pid,gid from groups as g ". "where pid='$pid' and gid='$gid'"); if (mysql_num_rows($query_result) == 0) { return 0; } # # XXX String compare to ensure case match. # $row = mysql_fetch_row($query_result); if (strcmp($row[0], $pid) || strcmp($row[1], $gid)) { return 0; } return 1; } # # Confirm a valid project. # # usage TBValidProject($pid) # returns 1 if a valid project. # returns 0 if not a valid project. # function TBValidProject($pid) { return TBValidGroup($pid, $pid); } # # Confirm a group member. # # usage TBGroupMember($uid, $pid, $gid, &$approved) # returns 1 if a member. # returns 0 if not a member. # function TBGroupMember($uid, $pid, $gid, &$approved) { global $TBDB_TRUST_USER; $approved = 0; $query_result = DBQueryFatal("select trust from group_membership ". "where uid='$uid' and pid='$pid' and gid='$gid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_row($query_result); $trust = $row[0]; $approved = TBMinTrust($trust, $TBDB_TRUST_USER); return 1; } # # Confirm a valid OS Descriptor in the specified project. # # usage TBValidOS($pid, $imagename) # returns 1 if valid # returns 0 if not valid # function TBValidOS($pid, $osname) { $query_result = DBQueryFatal("select osid from os_info where ". "pid='$pid' and osname='$osname'"); if (mysql_num_rows($query_result) == 0) { return 0; } return 1; } # # Confirm a valid osid. # # usage TBValidOSID($osid) # returns 1 if valid # returns 0 if not valid # function TBValidOSID($osid) { $query_result = DBQueryFatal("select osid from os_info where osid='$osid'"); if (mysql_num_rows($query_result) == 0) { return 0; } return 1; } # # Confirm a valid image in the specified project. # # usage TBValidImage($pid, $imagename) # returns 1 if valid # returns 0 if not valid # function TBValidImage($pid, $imagename) { $query_result = DBQueryFatal("select imageid from images where ". "pid='$pid' and imagename='$imagename'"); if (mysql_num_rows($query_result) == 0) { return 0; } return 1; } # # Confirm a valid imageid (imageids are globally unique). # # usage TBValidImageID($imageid) # returns 1 if valid # returns 0 if not valid # function TBValidImageID($imageid) { $query_result = DBQueryFatal("select imageid from images where imageid='$imageid'"); if (mysql_num_rows($query_result) == 0) { return 0; } return 1; } # # Return info for an imageid. # # usage TBImageInfo($imageid, &$imagename, &$pid) # returns 1 if valid # returns 0 if not valid # function TBImageInfo($imageid, &$imagename, &$pid) { $query_result = DBQueryFatal("select * from images where imageid='$imageid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $imagename = $row[imagename]; $pid = $row[pid]; return 1; } # # Return info for an osid. # # usage TBOSInfo($osid, &$osname, &$pid) # returns 1 if valid # returns 0 if not valid # function TBOSInfo($osid, &$osname, &$pid) { $query_result = DBQueryFatal("select * from os_info where osid='$osid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $osname = $row[osname]; $pid = $row[pid]; return 1; } # # Confirm a valid experiment. # # usage TBValidExperiment($pid, $eid) # returns 1 if valid # returns 0 if not valid # function TBValidExperiment($pid, $eid) { $query_result = DBQueryFatal("select eid from experiments ". "where eid='$eid' and pid='$pid'"); if (mysql_num_rows($query_result) == 0) { return 0; } return 1; } # # Confirm a valid node name. # # usage TBValidNodeName($node) # returns 1 if valid # returns 0 if not valid # function TBValidNodeName($node) { $query_result = DBQueryFatal("select node_id from nodes where node_id='$node'"); if (mysql_num_rows($query_result) == 0) { return 0; } return 1; } # # Confirm a valid node type # # usage TBValidNodeType($type) # returns 1 if valid # returns 0 if not valid # function TBValidNodeType($type) { $query_result = DBQueryFatal("select type from node_types where type='$type'"); if (mysql_num_rows($query_result) == 0) { return 0; } return 1; } # # Return mail addresses for project_root and group_root people. # # usage TBLeaderMailList($pid, $gid) # Uses default group (pid=gid) if gid not given. # returns string like "Leader Name (uid) [, ...]" # returns 0 if not valid function TBLeaderMailList($pid, $gid) { # No group, then use the default group. if (! $gid) { $gid = $pid; } $query_result = DBQueryFatal("select distinct usr_name,u.uid,usr_email from users as u ". "left join group_membership as gm on gm.uid=u.uid ". "where (trust='". TBDB_TRUSTSTRING_PROJROOT . "' and pid='$pid') or (trust='". TBDB_TRUSTSTRING_GROUPROOT . "' and pid='$pid' and gid='$gid') ". "order by trust DESC, usr_name"); if (mysql_num_rows($query_result) == 0) { return 0; } $mailstr=""; while ($row = mysql_fetch_array($query_result)) { if ($mailstr != "") { $mailstr .=", "; } $mailstr .= '"'.$row[usr_name]." (".$row[uid].")\" <".$row[usr_email].">"; } return $mailstr; } # # Return Project Leader. # # usage TBProjLeader($pid, &$projleader) # returns 1 if valid # returns 0 if not valid # function TBProjLeader($pid, &$projleader) { $query_result = DBQueryFatal("select head_uid from projects where pid='$pid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $projleader = $row[head_uid]; return 1; } # # Return Group Leader. # # usage TBGroupLeader($pid, $gid, &$groupleader) # returns 1 if valid # returns 0 if not valid # function TBGroupLeader($pid, $gid, &$groupleader) { $query_result = DBQueryFatal("select leader from groups ". "where pid='$pid' and gid='$gid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $groupleader = $row[leader]; return 1; } # # Return Experiment Leader. # # usage TBExpLeader($pid, $eid, &$expleader) # returns 1 if valid # returns 0 if not valid # function TBExpLeader($pid, $eid, &$expleader) { $query_result = DBQueryFatal("select expt_head_uid from experiments ". "where pid='$pid' and eid='$eid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $expleader = $row[expt_head_uid]; return 1; } # # Return a list of projects for which the uid is allowed to perform the # requested operation. Only a couple of access options are supported since # to be totally general would require too many DB operations. Not worth # the effort or the expense. # # Returns an indexed array (by pid) of lists (of gids). # function TBProjList($uid, $access_type) { global $TB_PROJECT_CREATEEXPT; global $TB_PROJECT_MAKEOSID; global $TB_PROJECT_MAKEIMAGEID; global $TB_PROJECT_MAKEGROUP; global $TB_PROJECT_READINFO; $result = array(); $user_clause = "where uid='$uid' and"; if ($access_type == $TB_PROJECT_READINFO) { $trust_clause = "trust!='none'"; } elseif ($access_type == $TB_PROJECT_MAKEGROUP) { $trust_clause = "trust='project_root'"; } elseif ($access_type == $TB_PROJECT_CREATEEXPT) { $trust_clause = "(trust='project_root' or trust='group_root' or ". " trust='local_root')"; } elseif ($access_type == $TB_PROJECT_MAKEOSID || $access_type == $TB_PROJECT_MAKEIMAGEID) { if (ISADMIN($uid)) { $user_clause = ""; } else { $trust_clause = "(trust='project_root' or trust='group_root' or ". " trust='local_root')"; } } else { TBERROR("Invalid access type $access_type!", 1); } $query_result = DBQueryFatal("SELECT distinct pid,gid FROM group_membership ". "$user_clause $trust_clause order by pid"); if (mysql_num_rows($query_result) == 0) { return $result; } $i = 0; while ($row = mysql_fetch_array($query_result)) { $pid = $row['pid']; $gid = $row['gid']; $result[$pid][] = $gid; $i++; } return $result; } function TBExptState($pid, $eid) { $query_result = DBQueryFatal("select state from experiments ". "where eid='$eid' and pid='$pid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $state = $row[state]; return $state; } function TBExptBatchState($pid, $eid, &$bstate) { $query_result = DBQueryFatal("select batchmode,batchstate from experiments ". "where eid='$eid' and pid='$pid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); $mode = $row[batchmode]; $bstate = $row[batchstate]; if (!$mode) { return 0; } return 1; } function TBExptIndex($pid, $eid) { $query_result = DBQueryFatal("select idx from experiments ". "where eid='$eid' and pid='$pid'"); if (mysql_num_rows($query_result) == 0) { return -1; } $row = mysql_fetch_array($query_result); $idx = $row[idx]; return $idx; } function TBrsrcIndex($pid, $eid) { $query_result = DBQueryFatal("select s.rsrcidx from experiments as e ". "left join experiment_stats as s on s.exptidx=e.idx ". "where e.pid='$pid' and e.eid='$eid'"); if (mysql_num_rows($query_result) == 0) { return -1; } $row = mysql_fetch_array($query_result); $idx = $row[rsrcidx]; return $idx; } function TBUidNodeLastLogin($uid) { $query_result = DBQueryFatal("select * from uidnodelastlogin where uid='$uid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); return $row; } # # Return the last login for the node, but only after the experiment was # created (swapped in). # function TBNodeUidLastLogin($node_id) { $query_result = DBQueryFatal("select n.* from nodeuidlastlogin as n ". "left join reserved as r on n.node_id=r.node_id ". "left join experiments as e ". " on r.eid=e.eid and r.pid=e.pid ". "where r.node_id='$node_id' and ". " DATE_ADD(n.date, INTERVAL n.time HOUR_SECOND) >= ". " e.expt_swapped"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); return $row; } # # Return the last login for the users node. # function TBUsersLastLogin($uid) { $query_result = DBQueryFatal("select * from userslastlogin where uid='$uid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); return $row; } # # Return number of events in an experiment. # function TBEventCount($pid, $eid) { $query_result = DBQueryFatal("select count(*) from eventlist ". "where pid='$pid' and eid='$eid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_row($query_result); return $row[0]; } # # Return the last login for all of the nodes in an experiment, but only # after the experiment was created (swapped in). # function TBExpUidLastLogins($pid, $eid) { $query_result = DBQueryFatal("select n.*, date_format(n.date,'%c/%e') as shortdate, ". "to_days(now())-to_days(n.date) as daysidle ". "from nodeuidlastlogin as n ". "left join reserved as r on n.node_id=r.node_id ". "left join experiments as e ". " on r.eid=e.eid and r.pid=e.pid ". "where r.pid='$pid' and r.eid='$eid' and ". " DATE_ADD(n.date, INTERVAL n.time HOUR_SECOND) >= ". " e.expt_swapped ". " order by n.date DESC"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); return $row; } # # Number of globally free PCs. # function TBFreePCs() { $query_result = DBQueryFatal("select a.node_id from nodes as a ". "left join reserved as b on a.node_id=b.node_id ". "left join node_types as nt on a.type=nt.type ". "where b.node_id is null and a.role='testnode' ". " and a.type like 'pc%'"); return mysql_num_rows($query_result); } function TBUserPCs($uid) { $query_result = DBQueryFatal("select a.node_id from nodes as a ". "left join reserved as b on a.node_id=b.node_id ". "left join node_types as nt on a.type=nt.type ". "left join experiments as e on b.pid=e.pid and ". " b.eid=e.eid ". "where e.expt_head_uid='$uid' and e.pid!='emulab-ops' ". " and a.role='testnode' and a.type like 'pc%'"); return mysql_num_rows($query_result); } function TBExptLogFile($pid, $eid) { $query_result = DBQueryFatal("select logfile from experiments ". "where pid='$pid' and eid='$eid' and ". " logfile is not null"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_row($query_result); return $row[0]; } function TBWebdbAllowed($uid) { $query_result = DBQueryFatal("select dbedit from users ". "WHERE uid='$uid' and dbedit=1"); return mysql_num_rows($query_result); } function TBCvswebAllowed($uid) { $query_result = DBQueryFatal("select cvsweb from users ". "WHERE uid='$uid' and cvsweb=1"); return mysql_num_rows($query_result); } # # Returns > 0 if a node has a serial console, 0 if it does not # function TBHasSerialConsole($node_id) { $query_result = DBQueryFatal("select tipname from tiplines WHERE node_id='$node_id'"); return mysql_num_rows($query_result); } # # Generate a verification key, and stash it in the database # function TBGenVerificationKey($name) { $key = md5(uniqid(rand(),1)); DBQueryFatal("update users set verify_key='$key' where uid='$name'"); return $key; } # # Get a verification key from the database # function TBGetVerificationKey($name) { $query_result = DBQueryFatal("select verify_key from users where uid='$name'"); if (mysql_num_rows($query_result) == 0) { # Can we signal error somehow? return ""; } $row = mysql_fetch_array($query_result); return $row[verify_key]; } # # Map IP to nodeid. # function TBIPtoNodeID($ip) { $query_result = DBQueryFatal("select n.node_id from interfaces as i ". "left join nodes as n on n.node_id=i.node_id ". "left join node_types as t ". " on t.type=n.type and i.iface=t.control_iface ". "where i.IP='$ip'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); return $row[node_id]; } # # Functions related to idle times # $lastact_query = "greatest(last_tty_act,last_net_act,last_cpu_act,". "last_ext_act)"; # # Gets the time of last activity for a node # function TBGetNodeLastAct($pc) { global $lastact_query; $query_result = DBQueryWarn("select $lastact_query as last_act from node_activity ". "where node_id='$pc'"); if (mysql_num_rows($query_result) == 0) { return -1; } $row = mysql_fetch_array($query_result); return $row[last_act]; } # # Gets the time of idleness for a node, in hours by default (ie '2.75') # function TBGetNodeIdleTime($pc, $format = 0) { global $lastact_query; $query_result = DBQueryWarn("select (unix_timestamp(now()) - unix_timestamp( ". "$lastact_query)) as idle_time from node_activity ". "where node_id='$pc'"); if (mysql_num_rows($query_result) == 0) { return -1; } $row = mysql_fetch_array($query_result); $t = $row[idle_time]; # if it is less than 5 minutes, it is not idle at all... $t = ($t < 300 ? 0 : $t); if (!$format) { $t = round($t/3600,2); } else { $t = date($format,mktime(0,0,$t)); } return $t; } # # Find out if a node's idle reports are stale # function TBGetNodeIdleStale($pc) { global $lastact_query; # We currently have a 5 minute interval for slothd between reports # So give some slack in case a node reboots without reporting for a while $staletime = 10; # in minutes $stalesec = 60 * $staletime; $query_result = DBQueryWarn("select (unix_timestamp(now()) - ". "unix_timestamp(last_report )) as t ". "from node_activity where node_id='$pc'"); if (mysql_num_rows($query_result) == 0) { return -1; } $row = mysql_fetch_array($query_result); return ($row[t]>$stalesec); } # # Gets the time of last activity for an expt # function TBGetExptLastAct($pid, $eid) { global $lastact_query; $query_result = DBQueryWarn("select max($lastact_query) as last_act ". "from node_activity as na ". "left join reserved as r on na.node_id=r.node_id ". "where pid='$pid' and eid='$eid' ". "group by pid,eid"); if (mysql_num_rows($query_result) == 0) { return -1; } $row = mysql_fetch_array($query_result); return $row[last_act]; } # # Gets the time of idleness for an expt, in hours # function TBGetExptIdleTime($pid, $eid, $format = 0) { global $lastact_query; $query_result = DBQueryWarn("select (unix_timestamp(now()) - unix_timestamp( ". "max($lastact_query))) as idle_time ". "from node_activity as na ". "left join reserved as r on na.node_id=r.node_id ". "where pid='$pid' and eid='$eid' ". "group by pid,eid"); if (mysql_num_rows($query_result) == 0) { return -1; } $row = mysql_fetch_array($query_result); $t = $row[idle_time]; # if it is less than 5 minutes, it is not idle at all... $t = ($t < 300 ? 0 : $t); if (!$format) { $t = round($t/3600,2); } else { $t = date($format,mktime(0,0,$t,1,1)); } return $t; } # # Find out if an expt's idle report is stale # function TBGetExptIdleStale($pid, $eid) { global $lastact_query; # We currently have a 5 minute interval for slothd between reports # So give some slack in case a node reboots without reporting for a while $staletime = 10; # in minutes $stalesec = 60 * $staletime; $query_result = DBQueryWarn("select (unix_timestamp(now()) - ". "unix_timestamp(min(last_report) )) as t ". "from node_activity as na ". "left join reserved as r on na.node_id=r.node_id ". "where pid='$pid' and eid='$eid' ". "group by pid,eid"); if (mysql_num_rows($query_result) == 0) { return -1; } $row = mysql_fetch_array($query_result); return ($row[t]>$stalesec); } # # Find out if an expt's idleness should be ignored # function TBGetExptIdleIgnore($pid,$eid) { global $lastact_query; $query_result = DBQueryWarn("select idle_ignore from experiments ". "where pid='$pid' and eid='$eid'"); if (mysql_num_rows($query_result) == 0) { return 0; } $row = mysql_fetch_array($query_result); return $row[idle_ignore]; } # # Check if a site-specific variable exists. # # usage: TBSiteVarExists($name) # returns 1 if variable exists; # returns 0 otherwise. # function TBSiteVarExists($name) { global $lastact_query; $name = addslashes( $name ); $query_result = DBQueryFatal("select name from sitevariables ". "where name='$name'"); if (mysql_num_rows($query_result) > 0) { return 1; } else { return 0; } } # # Get site-specific variable. # Get the value of the variable, or the default value if # the value is undefined (NULL). # # usage: TBGetSiteVar($name) # returns value if variable is defined; # dies otherwise. # function TBGetSiteVar($name) { global $lastact_query; $name = addslashes( $name ); $query_result = DBQueryFatal("select value, defaultvalue from sitevariables ". "where name='$name'"); if (mysql_num_rows($query_result) > 0) { $row = mysql_fetch_array($query_result); $value = $row[value]; $defaultvalue = $row[defaultvalue]; if (isset($value)) { return $value; } if (isset($defaultvalue)) { return $defaultvalue; } } TBERROR("Attempted to fetch unknown site variable '$name'!"); } # # DB Interface. # $maxtries = 3; $DBlinkid = 0; while ($maxtries) { $DBlinkid = mysql_connect("localhost", basename($SCRIPT_NAME)); if ($DBlinkid) { break; } $maxtries--; sleep(1); } if (! $DBlinkid) { TBERROR("Could not connect to mysqld after several attempts!", 1); } if (!mysql_select_db($TBDBNAME)) { TBERROR("Could not select DB after connecting!", 1); } # # Record last DB error string. # $DBErrorString = ""; # # This mirrors the routine in the PERL code. The point is to avoid # writing the same thing repeatedly, get consistent error handling, # and make sure that mail is sent to the testbed list when things go # wrong! # # Argument is a string. Returns the actual query object, so it is up to # the caller to test it. I would not for one moment view this as # encapsulation of the DB interface. # # usage: DBQuery(char *str) # returns the query object result. # # Sets $DBErrorString is case of error; saving the original query string and # the error string from the DB module. Use DBFatal (below) to print/email # that string, and then exit. # function DBQuery($query) { global $TBDBNAME; global $DBErrorString; global $DBlinkid; $result = mysql_query($query, $DBlinkid); if (! $result) { $DBErrorString = " Query: $query\n". " Error: " . mysql_error(); } return $result; } # # Same as above, but die on error. # function DBQueryFatal($query) { $result = DBQuery($query); if (! $result) { DBFatal("DB Query failed"); } return $result; } # # Same as above, but just send email on error. This info is useful # to the TB system, but the caller has to retain control. # function DBQueryWarn($query) { $result = DBQuery($query); if (! $result) { DBWarn("DB Query failed"); } return $result; } # # Warn and send email after a failed DB query. First argument is the error # message to send. The contents of $DBErrorString is also sent. We do not # print this stuff back to the user since we might leak stuff out that we # should not. # # usage: DBWarn(char *message) # function DBWarn($message) { global $PHP_SELF, $DBErrorString; $text = "$message - In $PHP_SELF\n" . "$DBErrorString\n"; TBERROR($text, 0); } # # Same as above, but die after the warning. # # usage: DBFatal(char *message); # function DBFatal($message) { global $TBMAILADDR; DBWarn($message); PAGEERROR("

". "Unexpected Error. Could not continue. ". "Please contact $TBMAILADDR\n"); } ?>