Example #1
0
function EC2_GetRunningInstances()
{
    $now = time();
    $instances = array();
    $key = GetSetting('ec2_key');
    $secret = GetSetting('ec2_secret');
    if ($key && $secret) {
        $locations = EC2_GetAMILocations();
        try {
            $ec2 = \Aws\Ec2\Ec2Client::factory(array('key' => $key, 'secret' => $secret, 'region' => 'us-east-1'));
            $regions = array();
            $response = $ec2->describeRegions();
            if (isset($response['Regions'])) {
                foreach ($response['Regions'] as $region) {
                    $regions[] = $region['RegionName'];
                }
            }
        } catch (\Aws\Ec2\Exception\Ec2Exception $e) {
            $error = $e->getMessage();
            EC2LogError("Listing running EC2 instances: {$error}");
        }
        if (isset($regions) && is_array($regions) && count($regions)) {
            foreach ($regions as $region) {
                try {
                    $ec2 = \Aws\Ec2\Ec2Client::factory(array('key' => $key, 'secret' => $secret, 'region' => $region));
                    $response = $ec2->describeInstances();
                    if (isset($response['Reservations'])) {
                        foreach ($response['Reservations'] as $reservation) {
                            foreach ($reservation['Instances'] as $instance) {
                                $wptLocations = null;
                                // See what locations are associated with the AMI
                                if (isset($instance['ImageId']) && isset($locations[$instance['ImageId']]['locations'])) {
                                    $wptLocations = $locations[$instance['ImageId']]['locations'];
                                } elseif (isset($instance['Tags'])) {
                                    // fall back to using tags to identify locations if they were set
                                    foreach ($instance['Tags'] as $tag) {
                                        if ($tag['Key'] == 'WPTLocations') {
                                            $wptLocations = explode(',', $tag['Value']);
                                            break;
                                        }
                                    }
                                }
                                if (isset($wptLocations)) {
                                    $launchTime = strtotime($instance['LaunchTime']);
                                    $elapsed = $now - $launchTime;
                                    $state = $instance['State']['Code'];
                                    $running = false;
                                    if (is_numeric($state) && $state <= 16) {
                                        $running = true;
                                    }
                                    $instances[] = array('region' => $region, 'id' => $instance['InstanceId'], 'ami' => $instance['ImageId'], 'state' => $state, 'launchTime' => $instance['LaunchTime'], 'launched' => $launchTime, 'runningTime' => $elapsed, 'locations' => $wptLocations, 'running' => $running);
                                }
                            }
                        }
                    }
                } catch (\Aws\Ec2\Exception\Ec2Exception $e) {
                    $error = $e->getMessage();
                    EC2LogError("Listing running EC2 instances: {$error}");
                }
            }
        }
    }
    // update the AMI counts we are tracking locally
    if (count($instances)) {
        $lock = Lock('ec2-instances', true, 120);
        if ($lock) {
            $amis = array();
            foreach ($instances as $instance) {
                if (isset($instance['ami']) && strlen($instance['ami']) && $instance['running']) {
                    if (!isset($amis[$instance['ami']])) {
                        $amis[$instance['ami']] = array('count' => 0);
                    }
                    $amis[$instance['ami']]['count']++;
                }
            }
            file_put_contents('./tmp/ec2-instances.dat', json_encode($amis));
            Unlock($lock);
        }
    }
    return $instances;
}
/**
* Start any instances that may be needed to handle large batches or
* to keep the minimum instance count for a given location
* 
*/
function EC2_StartNeededInstances()
{
    $lock = Lock('ec2-instances', true, 120);
    if ($lock) {
        $instances = json_decode(file_get_contents('./tmp/ec2-instances.dat'), true);
        if (!$instances || !is_array($instances)) {
            $instances = array();
        }
        $locations = EC2_GetAMILocations();
        $scaleFactor = GetSetting('EC2.ScaleFactor');
        if (!$scaleFactor) {
            $scaleFactor = 100;
        }
        // see how long the work queues are for each location in each AMI
        foreach ($locations as $ami => $info) {
            $tests = 0;
            $min = 0;
            $max = 1;
            foreach ($info['locations'] as $location) {
                $queues = GetQueueLengths($location);
                if (isset($queues) && is_array($queues)) {
                    foreach ($queues as $priority => $count) {
                        $tests += $count;
                    }
                }
                $locMin = GetSetting("EC2.min");
                if ($locMin !== false) {
                    $min = max(0, intval($locMin));
                }
                $locMin = GetSetting("EC2.{$location}.min");
                if ($locMin !== false) {
                    $min = max(0, intval($locMin));
                }
                $locMax = GetSetting("EC2.max");
                if ($locMax !== false) {
                    $max = max(1, intval($locMax));
                }
                $locMax = GetSetting("EC2.{$location}.max");
                if ($locMax !== false) {
                    $max = max(1, intval($locMax));
                }
            }
            $locations[$ami]['tests'] = $tests;
            $locations[$ami]['min'] = $min;
            $locations[$ami]['max'] = $max;
        }
        foreach ($locations as $ami => $info) {
            $count = isset($instances[$ami]['count']) ? $instances[$ami]['count'] : 0;
            $target = $locations[$ami]['tests'] / $scaleFactor;
            $target = min($target, $locations[$ami]['max']);
            $target = max($target, $locations[$ami]['min']);
            $needed = 0;
            if ($count < $target) {
                $needed = $target - $count;
                for ($i = 0; $i < $needed; $i++) {
                    if (EC2_StartInstance($ami)) {
                        if (!isset($instances[$ami])) {
                            $instances[$ami] = array('count' => 0);
                        }
                        if (!isset($instances[$ami]['count'])) {
                            $instances[$ami]['count'] = 0;
                        }
                        $instances[$ami]['count']++;
                    } else {
                        break;
                    }
                }
            }
        }
        file_put_contents('./tmp/ec2-instances.dat', json_encode($instances));
        Unlock($lock);
    }
}