Esempio n. 1
0
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, " . "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"], datetimeToUnix($res["start"]), datetimeToUnix($res["end"]), "dummy", 0, $res["userid"]);
        if ($rc < 1) {
            $allmovable = 0;
            break;
        }
    }
    if (!$allmovable) {
        return 0;
    }
    foreach ($resInfo as $res) {
        $rc = isAvailable($images, $res["imageid"], datetimeToUnix($res["start"]), datetimeToUnix($res["end"]), "dummy", 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;
}
Esempio n. 2
0
 function AJsubmitReloadComputers()
 {
     $data = getContinuationVar();
     # imageid, compids, imagename
     $start = getReloadStartTime();
     $end = $start + 1200;
     // + 20 minutes
     $startstamp = unixToDatetime($start);
     $endstamp = unixToDatetime($end);
     $imagerevisionid = getProductionRevisionid($data['imageid']);
     $computers = $this->getData($this->defaultGetDataArgs);
     $reloadnow = array();
     $reloadasap = array();
     $fails = array();
     $passes = array();
     foreach ($data['compids'] as $compid) {
         if ($computers[$compid]['state'] == 'available' || $computers[$compid]['state'] == 'failed') {
             $mn = findManagementNode($compid, unixToDatetime($start), 1);
             if ($mn == 0) {
                 $fails[] = $compid;
                 continue;
             }
             if (getSemaphore($data['imageid'], $imagerevisionid, $mn, $compid, $startstamp, $endstamp)) {
                 $query = "SELECT rq.id " . "FROM request rq, " . "reservation rs, " . "state s " . "WHERE rs.requestid = rq.id AND " . "rq.stateid = s.id AND " . "rs.computerid = {$compid} AND " . "rq.start < '{$endstamp}' AND " . "rq.end > '{$startstamp}' AND " . "s.name NOT IN ('complete', 'deleted', 'failed', 'timeout')";
                 $qh = doQuery($query);
                 if (!mysql_num_rows($qh)) {
                     $reloadnow[] = $compid;
                 } else {
                     $reloadasap[] = $compid;
                 }
             } else {
                 $reloadasap[] = $compid;
             }
         }
     }
     $vclreloadid = getUserlistID('vclreload@Local');
     foreach ($reloadnow as $compid) {
         if (simpleAddRequest($compid, $data['imageid'], $imagerevisionid, $startstamp, $endstamp, 19, $vclreloadid)) {
             $passes[] = $compid;
         } else {
             $fails[] = $compid;
         }
     }
     // release semaphore lock on nodes
     cleanSemaphore();
     if (count($reloadasap)) {
         $compids = implode(',', $reloadasap);
         $query = "UPDATE computer " . "SET nextimageid = {$data['imageid']} " . "WHERE id IN ({$compids})";
         doQuery($query, 101);
     }
     $msg = '';
     if (count($passes)) {
         $msg .= "The following computers are being immediately reloaded with ";
         $msg .= "<strong>{$data['imagename']}</strong>:<br>\n";
         foreach ($passes as $compid) {
             $msg .= "<span class=\"ready\">{$computers[$compid]['hostname']}</span><br>\n";
         }
     }
     if (count($reloadasap)) {
         if (count($passes)) {
             $msg .= "<br>";
         }
         $msg .= "The following computers have <strong>{$data['imagename']}</strong> ";
         $msg .= "set as a priority for reloading at the end of their existing ";
         $msg .= "reservations:<br>\n";
         foreach ($reloadasap as $compid) {
             $msg .= "<span class=\"wait\">{$computers[$compid]['hostname']}</span><br>\n";
         }
     }
     if (count($fails)) {
         if (count($passes) || count($reloadasap)) {
             $msg .= "<br>";
         }
         $msg .= "No functional management node was found for the following ";
         $msg .= "computers. They could not be reloaded at this time:<br>\n";
         foreach ($fails as $compid) {
             $msg .= "<span class=\"rederrormsg\">{$computers[$compid]['hostname']}</span><br>\n";
         }
     }
     $ret = array('status' => 'success', 'title' => "Reload Computers", 'refreshcount' => 4, 'msg' => $msg);
     sendJSON($ret);
 }
Esempio n. 3
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;
}