Summary
Summary here…
Description
Detailed Description…
Amazon EC2 Metadata
We use the following class to obtain Metadata from a running Amazon instance. This code also demonstrates a way set a timeout variable when using the WebClient object.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class AwsHelper | |
{ | |
private const string LOG_PREFIX = "AwsHelper/"; | |
/* A class to return Metadata from a running Amazon instance. | |
Requires: using System.Net; | |
We call these methods in the startup routine of our windows service. | |
Here is an example: | |
// If called from a non AWS instance, each request would take 5 seconds (the timeout), | |
// so we wrap them to only be called when an AvailabilityZone is returned. | |
string avZone = AwsHelper.AvailabilityZone; | |
if (!string.IsNullOrEmpty(avZone)) | |
{ | |
Logging.LogInfo(logMsg + " Amazon Availability Zone: " + avZone); | |
Logging.LogInfo(logMsg + " AmiId: " + AwsHelper.AmiId); | |
Logging.LogInfo(logMsg + " PublicIpv4: " + AwsHelper.PublicIpv4); | |
Logging.LogInfo(logMsg + " InstanceId: " + AwsHelper.InstanceId); | |
Logging.LogInfo(logMsg + " InstanceType: " + AwsHelper.InstanceType); | |
Logging.LogInfo(logMsg + " SecurityGroups: " + AwsHelper.SecurityGroups); | |
} | |
Here is a list of other meta data that could be returned. This list is | |
obtained by calling: http://169.254.169.254/latest/meta-data/ | |
ami-id | |
ami-launch-index | |
ami-manifest-path | |
block-device-mapping/ | |
hostname | |
instance-action | |
instance-id | |
instance-type | |
local-hostname | |
local-ipv4 | |
mac | |
metrics/ | |
network/ | |
placement/ | |
profile | |
public-hostname | |
public-ipv4 | |
public-keys/ | |
reservation-id | |
security-groups | |
services/ | |
*/ | |
public static string AvailabilityZone | |
{ | |
// Returns Region + AvailabilityZone, Example: eu-west-1c | |
get { return GetMetaData("placement/availability-zone"); } | |
} | |
public static string PublicIpv4 | |
{ | |
get { return GetMetaData("public-ipv4"); } | |
} | |
public static string AmiId | |
{ | |
get { return GetMetaData("ami-id"); } | |
} | |
public static string InstanceId | |
{ | |
get { return GetMetaData("instance-id"); } | |
} | |
public static string InstanceType | |
{ | |
get { return GetMetaData("instance-type"); } | |
} | |
public static string SecurityGroups | |
{ | |
get { return GetMetaData("security-groups"); } | |
} | |
public static string GetMetaData(string urlSuffix) | |
{ | |
string logMsg = LOG_PREFIX + "GetMetaData"; | |
string retVal = ""; | |
const string URL_PREFIX = "http://169.254.169.254/latest/meta-data/"; | |
const int WAIT_TIMEOUT_MILLISECONDS = 5000; | |
try | |
{ | |
Logging.LogTrace(logMsg + string.Format(", for urlSuffix: {0}", urlSuffix)); | |
// Create the Full Url we will need to find the data. | |
string fullUrl = URL_PREFIX; | |
if (!urlSuffix.StartsWith("/")) | |
{ fullUrl += "/"; } | |
fullUrl += urlSuffix; | |
WebClientWithTimeout webClient = new WebClientWithTimeout(WAIT_TIMEOUT_MILLISECONDS); | |
retVal = webClient.DownloadString(fullUrl); | |
} | |
catch (WebException ex) | |
{ | |
if (ex.Message.Contains("The operation has timed out")) | |
{ | |
// This "EXCEPTION" will normally be thrown when we try to use this | |
// method from a computer that is not running on an Amazon server. | |
Logging.LogTrace(logMsg + ", Property called from a non Amazon server."); | |
} | |
else | |
{ Logging.LogError(logMsg + ", WEBEXCEPTION: " + ex.Message, ex); } | |
} | |
catch (Exception ex) | |
{ Logging.LogError(logMsg + ", EXCEPTION: " + ex.Message, ex); } | |
return retVal; | |
} | |
private class WebClientWithTimeout : WebClient | |
{ | |
// The reason we are not using the default WebClient class is because we need to specify | |
// a timeout. The default Timeout for the WebClient is at least 20 seconds (Some people | |
// say 100 seconds). When we are running on an Amazon server, the request returns almost | |
// instantaneously, so the timeout doesn't matter. | |
// However, when we call this from a non Amazon computer, the code will just "hang" until | |
// the timeout has elapsed. | |
// http://stackoverflow.com/questions/1789627/how-to-change-the-timeout-on-a-net-webclient-object | |
private int _timeoutMilliSeconds = 5000; | |
public WebClientWithTimeout() { } | |
public WebClientWithTimeout(int timeoutMilliSeconds) | |
{ | |
_timeoutMilliSeconds = timeoutMilliSeconds; | |
} | |
protected override WebRequest GetWebRequest(Uri uri) | |
{ | |
WebRequest webRequest = base.GetWebRequest(uri); | |
webRequest.Timeout = _timeoutMilliSeconds; | |
return webRequest; | |
} | |
} | |
} |
Click the “view raw” link to view the entire code listing.
Technology
- C#
- WebClient (with timeout)