Skip to content

Commit

Permalink
Detect Amazon EC2 instances that use the newer hypervisor
Browse files Browse the repository at this point in the history
Check DMI identifiers to identifier whether we're a Nitro hypervisor instance,
and keep checking /sys/hypervisor/uuid for Xen instances.

Deprecates CPL_AWS_CHECK_HYPERVISOR_UUID and replaces with CPL_AWS_AUTODETECT_EC2
  • Loading branch information
rcoup committed Oct 1, 2018
1 parent 04296c6 commit 9df23a3
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 29 deletions.
8 changes: 4 additions & 4 deletions autotest/gcore/vsis3.py
Original file line number Diff line number Diff line change
Expand Up @@ -2124,7 +2124,7 @@ def vsis3_read_credentials_ec2():
gdal.SetConfigOption('CPL_AWS_EC2_CREDENTIALS_URL',
'http://localhost:%d/latest/meta-data/iam/security-credentials/' % gdaltest.webserver_port)
# Disable hypervisor related check to test if we are really on EC2
gdal.SetConfigOption('CPL_AWS_CHECK_HYPERVISOR_UUID', 'NO')
gdal.SetConfigOption('CPL_AWS_AUTODETECT_EC2', 'NO')

gdal.VSICurlClearCache()

Expand Down Expand Up @@ -2169,7 +2169,7 @@ def vsis3_read_credentials_ec2():
return 'fail'

gdal.SetConfigOption('CPL_AWS_EC2_CREDENTIALS_URL', '')
gdal.SetConfigOption('CPL_AWS_CHECK_HYPERVISOR_UUID', None)
gdal.SetConfigOption('CPL_AWS_AUTODETECT_EC2', None)

return 'success'

Expand All @@ -2194,7 +2194,7 @@ def vsis3_read_credentials_ec2_expiration():
gdal.SetConfigOption('CPL_AWS_EC2_CREDENTIALS_URL',
'http://localhost:%d/latest/meta-data/iam/security-credentials/expire_in_past/' % gdaltest.webserver_port)
# Disable hypervisor related check to test if we are really on EC2
gdal.SetConfigOption('CPL_AWS_CHECK_HYPERVISOR_UUID', 'NO')
gdal.SetConfigOption('CPL_AWS_AUTODETECT_EC2', 'NO')

gdal.VSICurlClearCache()

Expand Down Expand Up @@ -2230,7 +2230,7 @@ def vsis3_read_credentials_ec2_expiration():
return 'fail'

gdal.SetConfigOption('CPL_AWS_EC2_CREDENTIALS_URL', '')
gdal.SetConfigOption('CPL_AWS_CHECK_HYPERVISOR_UUID', None)
gdal.SetConfigOption('CPL_AWS_AUTODETECT_EC2', None)

return 'success'

Expand Down
71 changes: 49 additions & 22 deletions gdal/port/cpl_aws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,35 +600,62 @@ static bool Iso8601ToUnixTime(const char* pszDT, GIntBig* pnUnixTime)
static bool IsMachinePotentiallyEC2Instance()
{
#ifdef __linux
// Small optimization on Linux. If the kernel is recent
// enough, a /sys/hypervisor/uuid file should exist on EC2 instances
// and contain a string beginning with ec2.
// Optimization on Linux to avoid the network request
// See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html
// If /sys/hypervisor exists, but /sys/hypervisor/uuid does not
// exist or doesn't start with ec2, then do not attempt any network
// access
bool bAttemptNetworkAccess = true;
if( CPLTestBool(CPLGetConfigOption(
"CPL_AWS_CHECK_HYPERVISOR_UUID", "YES")) )
// Skip if either:
// - CPL_AWS_AUTODETECT_EC2=NO
// - CPL_AWS_CHECK_HYPERVISOR_UUID=NO (deprecated)

// On the newer Nitro Hypervisor (C5, M5, H1, T3), use
// /sys/devices/virtual/dmi/id/sys_vendor = 'Amazon EC2' instead.

// On older Xen hypervisor EC2 instances, a /sys/hypervisor/uuid file will
// exist with a string beginning with 'ec2'.

// If the files exist but don't contain the correct content, then we're not EC2 and
// do not attempt any network access

if( ! CPLTestBool(CPLGetConfigOption("CPL_AWS_AUTODETECT_EC2", "YES")) )
{
return true;
}
else
{
VSIStatBufL sStat;
if( VSIStatL("/sys/hypervisor", &sStat) == 0 )
CPLString opt = CPLGetConfigOption("CPL_AWS_CHECK_HYPERVISOR_UUID", "");
if ( ! opt.empty() )
{
char uuid[36+1] = { 0 };
VSILFILE* fp = VSIFOpenL("/sys/hypervisor/uuid", "rb");
if( fp != nullptr )
{
VSIFReadL( uuid, 1, sizeof(uuid)-1, fp );
bAttemptNetworkAccess = EQUALN( uuid, "ec2", 3 );
VSIFCloseL(fp);
}
else
CPLDebug("AWS", "CPL_AWS_CHECK_HYPERVISOR_UUID is deprecated. Use CPL_AWS_AUTODETECT_EC2 instead");
if ( ! CPLTestBool(opt) )
{
bAttemptNetworkAccess = false;
return true;
}
}
}
return bAttemptNetworkAccess;

// Nitro Hypervisor instances
VSILFILE* fp = VSIFOpenL("/sys/devices/virtual/dmi/id/sys_vendor", "rb");
if( fp != nullptr )
{
char buf[10+1] = { 0 };
VSIFReadL( buf, 1, sizeof(buf)-1, fp );
bool bMatch = EQUALN( buf, "Amazon EC2", 10 );
VSIFCloseL(fp);
return bMatch;
}

// Xen Hypervisor instances
fp = VSIFOpenL("/sys/hypervisor/uuid", "rb");
if( fp != nullptr )
{
char uuid[36+1] = { 0 };
VSIFReadL( uuid, 1, sizeof(uuid)-1, fp );
bool bMatch = EQUALN( uuid, "ec2", 3 );
VSIFCloseL(fp);
return bMatch;
}

// Fallback: Check via the network
return true;
#elif defined(WIN32)
// We might add later a way of detecting if we run on EC2 using WMI
// See http://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/identify_ec2_instances.html
Expand Down
6 changes: 3 additions & 3 deletions gdal/port/cpl_vsil_s3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1254,9 +1254,9 @@ const char* VSIS3FSHandler::GetOptions()
"description='Whether to disable signing of requests' default='NO'/>"
" <Option name='AWS_DEFAULT_REGION' type='string' "
"description='AWS S3 default region' default='us-east-1'/>"
" <Option name='CPL_AWS_CHECK_HYPERVISOR_UUID' type='boolean' "
"description='Whether to check /sys/hypervisor/uuid to determine "
"if current machine is a AWS EC2 instance' default='YES'/>"
" <Option name='CPL_AWS_AUTODETECT_EC2' type='boolean' "
"description='Whether to check Hypervisor & DMI identifiers to "
"determine if current host is an AWS EC2 instance' default='YES'/>"
" <Option name='AWS_DEFAULT_PROFILE' type='string' "
"description='Name of the profile to use for IAM credentials "
"retrieval on EC2 instances' default='default'/>"
Expand Down

0 comments on commit 9df23a3

Please sign in to comment.