Skip to content

Instantly share code, notes, and snippets.

@vanjos
Created August 28, 2013 19:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vanjos/6370080 to your computer and use it in GitHub Desktop.
Save vanjos/6370080 to your computer and use it in GitHub Desktop.
Set up ec2metata_constants.php
<?php
/**
* This script gets EC2 metadata and saves it to an ini file. It should be run
* on boot before starting application stuff, such as php-fpm or video
* processing.
*/
// path to put file
$path = '/usr/local/viafoura';
$file_path = $path.'/ec2metadata_constants.php';
// make sure the path exists and the file is writable
if (!file_exists($path))
{
echo "Directory $path does not exist. Attempting to create it.\n";
$parent = dirname($path);
if (!is_writable($parent))
{
echo "Unable to write in $parent.\n";
exit(1);
}
if (!mkdir('/usr/local/viafoura'))
{
echo "Unable to create path $path.\n";
exit(1);
}
}
if (!is_writable($path))
{
echo "Unable to write in $path.\n";
exit(1);
}
if (file_exists($file_path) && !is_writable($file_path))
{
echo "Unable to write to $file_path.\n";
exit(1);
}
require_once "../../Viafoura-Core/third_party/r53.php";
$Route53 = new Route53('AKIAJYE5YGIZ2YNGF44Q', 'KBDqD67Tgh9XUPWQVyEwiAPwUIxlfkrpNamgiPdM');
$data = array();
$roles = false; // no known machine role
echo "Getting user-data...";
$data = array();
$user_data_url = 'http://169.254.169.254/2011-05-01/user-data';
$dummy_file = $path.'/dummy_ec2_metadata';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $user_data_url);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
try
{
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($http_code !== 200)
throw new Exception ("no user data.");
$header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $header_size);
$body = substr($response, $header_size);
// we use mime file in user data so we can do multiple things with it.
// first step is to locate any php bits.
$mime_header = 'Content-Type: multipart/mixed; boundary="';
$mime_header_len = strlen($mime_header);
if (strpos($body, $mime_header) !== 0)
throw new Exception ("user data not in compatible (mime) format");
$boundary_len = strpos($body, '"', $mime_header_len) - $mime_header_len;
$boundary = '--' . substr($body, $mime_header_len, $boundary_len);
$mime_bits = explode($body, $boundary);
foreach ($mime_bits as $bit)
{
// a hack to test for
// Content-Disposition: attachment; filename="php_user_data"
if (strpos('php_user_data') === false)
continue;
// find the first double newline -- after which is the data we want
// and then split the good stuff into lines we can import.
$candy = explode("\n", substr($bit, strpos($bit, "\n\n")));
foreach ($candy as $cavity)
{
// find the first separator
$separator = strpos($cavity, '=');
// if no separator, continue
if ($separator === false)
continue;
// switch on the before separator part, and do something with the
// after separator, e.g. availability-zone= us-east-1a
$key = trim(substr($cavity, 0, $separator));
$value = trim(substr($cavity, $separator + 1));
if (isset($data[$key]))
echo " over-writing";
echo " $key...";
$data[$key] = $value;
}
}
echo " done.\n";
}
catch (Exception $e)
{
echo " ".$e->getMessage()."\n";
}
curl_close($curl);
echo "Getting EC2 metadata...";
$metadata_url = 'http://169.254.169.254/2011-05-01/meta-data/';
$curl_pieces = array(
'ami-id' => 'ami-id',
'availability-zone' => 'placement/availability-zone',
'instance-id' => 'instance-id',
'instance-type' => 'instance-type',
'local-hostname' => 'local-hostname',
'local-ipv4' => 'local-ipv4',
'public-hostname' => 'public-hostname',
'public-ipv4' => 'public-ipv4',
'security-groups' => 'security-groups'
);
$curl = curl_multi_init();
$curl_handles = array();
foreach ($curl_pieces as $item => $url_piece)
{
$curl_handles[$item] = curl_init($metadata_url . $url_piece);
curl_setopt($curl_handles[$item], CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($curl, $curl_handles[$item]);
}
// execute all curl queries simultaneously and continue when complete
$active = null;
do
{
$mrc = curl_multi_exec($curl, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK)
{
if (curl_multi_select($curl) != -1)
{
do
{
$mrc = curl_multi_exec($curl, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
// store the results of the curls
foreach ($curl_pieces as $item => $url_piece)
{
$http_code = curl_getinfo($curl_handles[$item], CURLINFO_HTTP_CODE);
if ($http_code !== 200)
continue;
if (isset($data[$item]))
echo " over-writing";
echo " $item...";
$data[$item] = curl_multi_getcontent($curl_handles[$item]);
curl_multi_remove_handle($curl, $curl_handles[$item]);
}
curl_multi_close($curl);
echo " done.\n";
if (file_exists($dummy_file) && is_readable($dummy_file))
{
echo "Parsing EC2 metadata dummy file $dummy_file...";
$candy = explode("\n", file_get_contents($dummy_file));
foreach ($candy as $cavity)
{
// find the first separator
$separator = strpos($cavity, '=');
// if no separator, continue
if ($separator === false)
continue;
// switch on the before separator part, and do something with the
// after separator, e.g. availability-zone= us-east-1a
$key = trim(substr($cavity, 0, $separator));
$value = trim(substr($cavity, $separator + 1));
if (isset($data[$key]))
echo " over-writing";
echo " $key...";
$data[$key] = $value;
}
echo " done.\n";
}
// set some default values for variables used later
$av_zone = 'unknown-avzone';
$instance_id = 'unknown-instance';
$local_hostname = 'unknown-internal-hostname';
$public_hostname = 'unknown-public-hostname';
$security_groups = 'unknown-security-groups';
// start building string for file...
$file_data = "<?php\n";
// loop through each retrieved value
foreach ($data as $key => $value)
{
switch ($key)
{
case 'roles':
$file_data .= "define ('MACHINE_ROLES', '$value');\n";
$roles = $value;
break;
case 'ami-id':
$file_data .= "define ('EC2_AMI_ID', '$value');\n";
break;
case 'availability-zone':
$file_data .= "define ('EC2_AVAILABILITY_ZONE', '$value');\n";
$av_zone = $value;
break;
case 'instance-id':
$file_data .= "define ('EC2_INSTANCE_ID', '$value');\n";
$instance_id = $value;
break;
case 'instance-type':
$file_data .= "define ('EC2_INSTANCE_TYPE', '$value');\n";
break;
case 'local-hostname':
$file_data .= "define ('EC2_LOCAL_HOSTNAME', '$value');\n";
$local_hostname = $value;
break;
case 'local-ipv4':
$file_data .= "define ('EC2_LOCAL_IPV4', '$value');\n";
break;
case 'public-hostname':
$file_data .= "define ('EC2_PUBLIC_HOSTNAME', '$value');\n";
$public_hostname = $value;
break;
case 'public-ipv4':
$file_data .= "define ('EC2_PUBLIC_IPV4', '$value');\n";
break;
case 'security-groups':
$file_data .= "define ('EC2_SECURITY_GROUPS', '$value');\n";
$security_groups = $value;
break;
default:
// do nothing... we ought to ignore unknown values...
}
}
// live, staging, or dev?
switch ($security_groups)
{
case 'FFmpeg+Live':
case 'Galera+Live':
case 'Task+Live':
case 'Web+Live':
$environment = 'live';
break;
case 'FFmpeg+Staging':
case 'Galera+Staging':
case 'Task+Staging':
case 'Web+Staging':
$environment = 'staging';
break;
case 'FFmpeg+Dev':
case 'Galera+Dev':
case 'Task+Dev':
case 'Web+Dev':
$environment = 'dev';
break;
default:
$environment = 'unknown-lsd';
}
$file_data .= "define ('ENVIRONMENT', '$environment');\n";
// Determine master database hosts based on region. By using the region we'll,
// automatically support being launched in new availability zones not defined
// in the script. Of course, new regions will require defining master hosts
// here.
// us-east-1a => us-east
$region = substr($av_zone, 0, strpos($av_zone, '-', strpos($av_zone, '-') + 1));
switch ($region)
{
case 'us-east':
$db_master_avs = 'us-east-1a;us-east-1d;us-east-1e';
default:
}
$file_data .= "define ('DB_MASTER_AV_ZONES', '$db_master_avs');\n";
// Let's do the same as above, but for Cassandra now
switch ($region)
{
case 'us-east':
$cassandra_avs = ($environment === 'dev') ? 'us-east-1a;us-east-1e' : 'us-east-1a;us-east-1d;us-east-1e';
default:
}
$file_data .= "define ('CASSANDRA_AV_ZONES', '$cassandra_avs');\n";
file_put_contents($file_path, $file_data);
echo "Created metadata file at $file_path\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment