Reputation: 23216
I wrote the following code to launch the AWS Instance
. It works fine. I am able to launch AWS
instance. But I need to wait, until the instance's status check is 2/2
or the instance is ready to be invoked.
public function launch_instance() {
$isInstanceLaunched = array('status' => false);
try {
if(!empty($this->ec2Client)) {
/**
* 1) EbsOptimized : Indicates whether the instance is optimized for EBS I/O.
* This optimization provides dedicated throughput to Amazon EBS and an optimized
* configuration stack to provide optimal EBS I/O performance. This optimization isn't
* available with all instance types. Additional usage charges apply when using an
* EBS-optimized instance.
*/
$result = $this->ec2Client->runInstances([
'AdditionalInfo' => 'Launched from API',
'DisableApiTermination' => false,
'ImageId' => 'ami-8xaxxxe8', // REQUIRED
'InstanceInitiatedShutdownBehavior' => 'stop',
'InstanceType' => 't2.micro',
'MaxCount' => 1, // REQUIRED
'MinCount' => 1, // REQUIRED,
'EbsOptimized' => false, // SEE COMMENT 1
'KeyName' => 'TestCloudKey',
'Monitoring' => [
'Enabled' => true // REQUIRED
],
'SecurityGroups' => ['TestGroup']
]);
if($result) {
$metadata = $result->get('@metadata');
$statusCode = $metadata['statusCode'];
//Verify if the code is 200
if($statusCode == 200) {
$instanceData = $result->get('Instances');
$instanceID = $instanceData[0]['InstanceId'];
// Give a name to the launched instance
$tagCreated = $this->ec2Client->createTags([
'Resources' => [$instanceID],
'Tags' => [
[
'Key' => 'Name',
'Value' => 'Created from API'
]
]
]);
$instance = $this->ec2Client->describeInstances([
'InstanceIds' => [$instanceID]
]);
$instanceInfo = $instance->get('Reservations')[0]['Instances'];
// Get the Public IP of the instance
$instancePublicIP = $instanceInfo[0]['PublicIpAddress'];
// Get the Public DNS of the instance
$instancePublicDNS = $instanceInfo[0]['PublicDnsName'];
// Get the instance state
$instanceState = $instanceInfo[0]['State']['Name'];
$instanceS = $this->ec2Client->describeInstanceStatus([
'InstanceIds' => [$instanceID]
]);
try {
$waiterName = 'InstanceRunning';
$waiterOptions = ['InstanceId' => $instanceID];
$waiter = $this->ec2Client->getWaiter($waiterName,$waiterOptions);
// Initiate the waiter and retrieve a promise.
$promise = $waiter->promise();
// Call methods when the promise is resolved.
$promise
->then(function () {
// Waiter Completed
})
->otherwise(function (\Exception $e) {
echo "Waiter failed: " . $e . "\n";
});
// Block until the waiter completes or fails. Note that this might throw
// a RuntimeException if the waiter fails.
$promise->wait();
}catch(RuntimeException $runTimeException) {
$isInstanceLaunched['side-information'] = $runTimeException->getMessage();
}
$isInstanceLaunched['aws-response'] = $result;
$isInstanceLaunched['instance-public-ip'] = $instancePublicIP;
$isInstanceLaunched['status'] = true;
}
}
}else {
$isInstanceLaunched['message'] = 'EC2 client not initialized. Call init_ec2 to initialize the client';
}
}catch(Ec2Exception $ec2Exception){
$isInstanceLaunched['message'] = $ec2Exception->getMessage().'-- FILE --'.$ec2Exception->getFile().'-- LINE --'.$ec2Exception->getLine();
}catch(Exception $exc) {
$isInstanceLaunched['message'] = $exc->getMessage().'-- FILE -- '.$exc->getFile().'-- LINE -- '.$exc->getLine();
}
return $isInstanceLaunched;
}
I have used the waiter
named InstanceRunning
but that doesn't help. How do I know that the instance is ready to be invoked or the status check is 2/2
?
Upvotes: 3
Views: 597
Reputation: 13
You need to use two waiters: first "InstanceRunning" and then "InstanceStatusOk"
Upvotes: 1
Reputation: 23216
I wrote the following code to check if the instance is ready to be invoked. I do a polling
to check if the statusCheck
is ok
.
/**
* The following block checks if the instance is ready to be invoked
* or StatusCheck of the instance equals 2/2
* Loop will return:
* - If the status check received is 'ok'
* - If it exceeds _amazon_client::MAX_ATTEMPTS_TO_EC2_SCHECK
*/
$statusCheckAttempt = 0;
do {
// Sleep for _amazon_client::POLLING_SECONDS
sleep(_amazon_client::POLLING_SECONDS);
// Query the instance status
$instanceS = $this->ec2Client->describeInstanceStatus([
'InstanceIds' => [$instanceID]
]);
$statusCheck = $instanceS->get('InstanceStatuses')[0]['InstanceStatus']['Status'];
$statusCheckAttempt++;
}while($statusCheck != 'ok' ||
$statusCheckAttempt >= _amazon_client::MAX_ATTEMPTS_TO_EC2_SCHECK);
Note: When the instance has just been launched, $instanceS->get('InstanceStatuses')[0]
returns an empty array. So I wait some seconds, before I could actually get the status.
Please suggest if there are better methods to achieve this.
Upvotes: 0
Reputation: 53713
have you try to replace
$waiter = $this->ec2Client->getWaiter($waiterName,$waiterOptions);
with
$this->ec2Client->waitUntil($waiterName, $waiterOptions);
$result = $ec2->describeInstances(array(
'InstanceIds' => array($instanceId),
));
I did not test for some time but it used to work for me
Upvotes: 1