Exemplo n.º 1
0
function showTimeTable($links)
{
    global $mode, $viewmode, $user;
    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 "<DIV align=center>\n";
    print "<H2>Time Table</H2>\n";
    print "</DIV>\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 .= "          <TH>{$id}</TH>\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.<br>\n";
    }
    print "<table summary=\"\">\n";
    print "  <TR>\n";
    print "    <TD>";
    # print Previous/Next links
    if (!empty($argstart) && $argstart - SECINDAY / 2 > $now - 600) {
        $prevstart = $start - SECINDAY / 2;
        $prevend = $end - SECINDAY / 2;
        print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
        $cdata = array('start' => $prevstart, 'end' => $prevend, 'imageid' => $imageid, 'requestid' => $requestid, 'length' => $length, 'platforms' => $platforms, 'schedules' => $schedules);
        $cont = addContinuationsEntry($mode, $cdata, SECINDAY);
        print "<INPUT type=hidden name=continuation value=\"{$cont}\">\n";
        print "<INPUT type=submit value=Previous>\n";
        print "</FORM>\n";
    }
    print "</TD>\n";
    print "    <TD>";
    if ($end + SECINDAY / 2 < $now + DAYSAHEAD * SECINDAY) {
        $nextstart = $start + SECINDAY / 2;
        $nextend = $end + SECINDAY / 2;
        print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
        $cdata = array('start' => $nextstart, 'end' => $nextend, 'imageid' => $imageid, 'requestid' => $requestid, 'length' => $length, 'platforms' => $platforms, 'schedules' => $schedules);
        $cont = addContinuationsEntry($mode, $cdata, SECINDAY);
        print "<INPUT type=hidden name=continuation value=\"{$cont}\">\n";
        print "<INPUT type=submit value=Next>\n";
        print "</FORM>\n";
    }
    print "</TD>\n";
    print "  </TR>\n";
    print "  <TR>\n";
    print "    <TD>\n";
    $tmpArr = array_keys($computers);
    $first = $computers[$tmpArr[0]];
    print "      <table id=ttlayout summary=\"\">\n";
    if (!$links || $viewmode >= ADMIN_DEVELOPER) {
        print "        <TR>\n";
        print "          <TH align=right>Computer&nbsp;ID:</TH>\n";
        print $computeridrow;
        print "        </TR>\n";
    }
    $yesterday = "";
    foreach (array_keys($timeslots[$first]) as $stamp) {
        if ($stamp < $now) {
            continue;
        }
        print "        <TR>\n";
        $stampArr = getdate($stamp);
        $label = "";
        if ($stampArr["mday"] != $yesterday) {
            $label = date('n/d/Y+g:i+a', $stamp);
            $label = str_replace('+', '&nbsp;', $label);
            $yesterday = $stampArr["mday"];
        } elseif ($stampArr["minutes"] == 0) {
            $label = date('g:i a', $stamp);
        }
        print "          <TH align=right>{$label}</TH>\n";
        $free = 0;
        # print the cells
        foreach ($computers as $id) {
            if (!in_array($id, $displayedids)) {
                continue;
            }
            if ($links && ($computer_platformids[$id] != $platformid || $computerData[$id]["stateid"] == 10 || $computerData[$id]["stateid"] == 5)) {
                continue;
            }
            # computer's schedule is currently closed
            if ($timeslots[$id][$stamp]["scheduleclosed"] == 1) {
                print "          <TD bgcolor=\"#a0a0a0\"><img src=images/gray.jpg ";
                print "alt=scheduleclosed border=0></TD>\n";
            } elseif ($computerData[$id]["stateid"] == 10) {
                print "          <TD bgcolor=\"#a0a0a0\"><img src=images/gray.jpg ";
                print "alt=maintenance border=0></TD>\n";
            } elseif ($timeslots[$id][$stamp]['blockRequest'] && ($timeslots[$id][$stamp]['blockRequestInfo']['imageid'] != $imageid || !in_array($timeslots[$id][$stamp]['blockRequestInfo']['groupid'], array_keys($user['groups']))) && $timeslots[$id][$stamp]['available']) {
                if ($links) {
                    print "          <TD bgcolor=\"#ff0000\"><img src=images/red.jpg ";
                    print "alt=blockrequest border=0></TD>\n";
                } else {
                    print "          <TD bgcolor=\"#e58304\"><img src=images/orange.jpg ";
                    $title = "Block Request: {$timeslots[$id][$stamp]['blockRequestInfo']['name']}\n" . "Image: {$timeslots[$id][$stamp]['blockRequestInfo']['image']}";
                    print "alt=blockrequest border=0 title=\"{$title}\"></TD>\n";
                }
            } elseif ($timeslots[$id][$stamp]["available"]) {
                if ($links) {
                    print "          <TD bgcolor=\"#00ff00\"><a href=\"" . BASEURL . SCRIPT;
                    print "?mode=newRequest&stamp={$stamp}&imageid={$imageid}&length={$length}\"><img ";
                    print "src=images/green.jpg alt=free border=0></a></TD>\n";
                } else {
                    print "          <TD bgcolor=\"#00ff00\"><img src=images/green.jpg alt=free border=0></TD>\n";
                }
            } else {
                if ($links) {
                    print "          <TD bgcolor=\"#ff0000\"><font color=\"#ff0000\">used</font></TD>\n";
                } else {
                    $title = "User: "******"unityid"] . " Image: " . $timeslots[$id][$stamp]["prettyimage"];
                    $cdata = array('requestid' => $timeslots[$id][$stamp]["requestid"]);
                    $cont = addContinuationsEntry('viewRequestInfo', $cdata);
                    print "          <TD bgcolor=\"#ff0000\"><a href=\"" . BASEURL;
                    print SCRIPT . "?continuation={$cont}\"><img src=images/red.jpg ";
                    print "alt=used border=0 title=\"{$title}\"></a></TD>\n";
                }
            }
        }
        print "        </TR>\n";
    }
    print "      </table>\n";
    print "    </TD>\n";
    print "  </TR>\n";
    print "  <TR>\n";
    print "    <TD>";
    # print Previous/Next links
    if (!empty($argstart) && $argstart - SECINDAY / 2 > $now - 600) {
        $prevstart = $start - SECINDAY / 2;
        $prevend = $end - SECINDAY / 2;
        print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
        $cdata = array('start' => $prevstart, 'end' => $prevend, 'imageid' => $imageid, 'requestid' => $requestid, 'length' => $length, 'platforms' => $platforms, 'schedules' => $schedules);
        $cont = addContinuationsEntry($mode, $cdata, SECINDAY);
        print "<INPUT type=hidden name=continuation value=\"{$cont}\">\n";
        print "<INPUT type=submit value=Previous>\n";
        print "</FORM>\n";
    }
    print "</TD>\n";
    print "    <TD>";
    if ($end + SECINDAY / 2 < $now + DAYSAHEAD * SECINDAY) {
        $nextstart = $start + SECINDAY / 2;
        $nextend = $end + SECINDAY / 2;
        print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
        $cdata = array('start' => $nextstart, 'end' => $nextend, 'imageid' => $imageid, 'requestid' => $requestid, 'length' => $length, 'platforms' => $platforms, 'schedules' => $schedules);
        $cont = addContinuationsEntry($mode, $cdata, SECINDAY);
        print "<INPUT type=hidden name=continuation value=\"{$cont}\">\n";
        print "<INPUT type=submit value=Next>\n";
        print "</FORM>\n";
    }
    print "</TD>\n";
    print "  </TR>\n";
    print "</table>\n";
}
Exemplo n.º 2
0
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, " . "provisioningOSinstalltype poi, " . "OSinstalltype oi, " . "OS o " . "WHERE c.stateid = s.id AND " . "i.id = {$imageid} AND " . "s.name NOT IN ({$nowignorestates}) AND " . "c.platformid = {$platformid} AND " . "c.scheduleid IN ({$schedules}) AND " . "i.OSid = o.id AND " . "o.installtype = oi.name AND " . "oi.id = poi.OSinstalltypeid AND " . "poi.provisioningid = c.provisioningid AND " . "c.RAM >= i.minram AND " . "c.procnumber >= i.minprocnumber AND " . "c.procspeed >= i.minprocspeed AND " . "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 RAM, " . "(c.procspeed * c.procnumber), " . "network";
    $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 " . "FROM request rq1, " . "request rq2, " . "reservation rs1, " . "reservation rs2, " . "image i, " . "state s, " . "computer c, " . "provisioningOSinstalltype poi, " . "OSinstalltype oi, " . "OS o " . "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 " . "i.OSid = o.id AND " . "o.installtype = oi.name AND " . "oi.id = poi.OSinstalltypeid AND " . "poi.provisioningid = c.provisioningid AND " . "c.RAM >= i.minram AND " . "c.procnumber >= i.minprocnumber AND " . "c.procspeed >= i.minprocspeed AND " . "c.network >= i.minnetwork AND " . "c.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, " . "provisioningOSinstalltype poi, " . "OSinstalltype oi, " . "OS o " . "WHERE rs.requestid = rq.id AND " . "(rq.start > '{$startdt}' OR " . "(DATE_ADD(rq.end, INTERVAL 15 MINUTE) > '{$startdt}' AND rq.start <= '{$startdt}')) AND " . "rs.computerid IN ({$incompids}) AND " . "i.id = {$imageid} AND " . "c.id = rs.computerid AND " . "c.platformid = {$platformid} AND " . "c.scheduleid IN ({$schedules}) AND " . "i.OSid = o.id AND " . "o.installtype = oi.name AND " . "oi.id = poi.OSinstalltypeid AND " . "poi.provisioningid = c.provisioningid AND " . "c.RAM >= i.minram AND " . "c.procnumber >= i.minprocnumber AND " . "c.procspeed >= i.minprocspeed AND " . "c.network >= i.minnetwork AND " . "c.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, " . "provisioningOSinstalltype poi, " . "OSinstalltype oi, " . "OS o " . "WHERE rs.requestid = rq.id AND " . "(rq.start > '{$startdt}' OR " . "(DATE_ADD(rq.end, INTERVAL 15 MINUTE) > '{$startdt}' AND rq.start <= '{$startdt}')) AND " . "rs.computerid IN ({$incompids}) AND " . "i.id = {$imageid} AND " . "c.id = rs.computerid AND " . "c.platformid = {$platformid} AND " . "c.scheduleid IN ({$schedules}) AND " . "i.OSid = o.id AND " . "o.installtype = oi.name AND " . "oi.id = poi.OSinstalltypeid AND " . "poi.provisioningid = c.provisioningid AND " . "c.RAM >= i.minram AND " . "c.procnumber >= i.minprocnumber AND " . "c.procspeed >= i.minprocspeed AND " . "c.network >= i.minnetwork AND " . "c.deleted = 0 AND " . "c.stateid = s.id AND " . "s.name NOT IN ({$ignorestates}) AND ";
    if ($reqid != '') {
        $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;
}