summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Baker <steve@stevebaker.org>2012-07-01 19:14:05 +1200
committerSteve Baker <steve@stevebaker.org>2012-07-02 09:19:43 +1200
commit29b1b4c79360e550cc89a9736dee56576aa5b972 (patch)
tree21125602d96fbfdefb50fef4b7863e1ac5bc6c97
parent019d953ef5b4bed7c53401375bfd7aa890fc0c1d (diff)
Make metadata content match the requested version of the metadata API.
Currently the same metadata is returned no matter what metadata version is requested. Metadata is currently implemented to version 2009-04-04 (apart from existing TODOs) as defined here: http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html This change adds version checking conditionals throughout get_ec2_metadata and only includes the metadata if the requested version should contain it. When there is a difference between Amazon API implementation and documentation I've gone with replicating the implementation. So far differences include: - undocumented hostname introduced in 1.0, deprecated in favour of local-hostname - kernel-id and ramdisk-id seem have to been implemented in 2007-12-15, not 2008-02-01 as documented get_ec2_metadata has also been reordered so that data is added oldest to newest by API version. In a future change I may attempt to add unimplemented API versions (2011-01-01, 2012-06-01). Change-Id: Ibf6e6e3b9807f29dccd31006515df550bf9bf57b
-rw-r--r--nova/api/metadata/base.py71
-rw-r--r--nova/tests/test_metadata.py12
2 files changed, 58 insertions, 25 deletions
diff --git a/nova/api/metadata/base.py b/nova/api/metadata/base.py
index 582bdec82..faa53f93e 100644
--- a/nova/api/metadata/base.py
+++ b/nova/api/metadata/base.py
@@ -115,27 +115,16 @@ class InstanceMetadata():
floating_ip = floating_ips and floating_ips[0] or ''
fmt_sgroups = [x['name'] for x in self.security_groups]
- data = {
- 'meta-data': {
- 'ami-launch-index': self.instance['launch_index'],
- 'ami-manifest-path': 'FIXME',
- 'block-device-mapping': self.mappings,
- 'hostname': hostname,
- 'instance-action': 'none',
- 'instance-type': self.instance['instance_type']['name'],
- 'local-hostname': hostname,
- 'local-ipv4': self.address,
- 'placement': {'availability-zone': self.availability_zone},
- 'public-hostname': hostname,
- 'public-ipv4': floating_ip,
- 'reservation-id': self.instance['reservation_id'],
- 'security-groups': fmt_sgroups}}
-
- for key in self.ec2_ids:
- data['meta-data'][key] = self.ec2_ids[key]
- if self.userdata_b64 is not None:
- data['user-data'] = self.userdata_b64
+ meta_data = {
+ 'ami-id': self.ec2_ids['ami-id'],
+ 'ami-launch-index': self.instance['launch_index'],
+ 'ami-manifest-path': 'FIXME',
+ 'instance-id': self.ec2_ids['instance-id'],
+ 'hostname': hostname,
+ 'local-ipv4': self.address,
+ 'reservation-id': self.instance['reservation_id'],
+ 'security-groups': fmt_sgroups}
# public keys are strangely rendered in ec2 metadata service
# meta-data/public-keys/ returns '0=keyname' (with no trailing /)
@@ -147,17 +136,49 @@ class InstanceMetadata():
# meta-data/public-keys/0/ : 'openssh-key'
# meta-data/public-keys/0/openssh-key : '%s' % publickey
if self.instance['key_name']:
- data['meta-data']['public-keys'] = {
+ meta_data['public-keys'] = {
'0': {'_name': "0=" + self.instance['key_name'],
'openssh-key': self.instance['key_data']}}
- if False: # TODO(vish): store ancestor ids
- data['ancestor-ami-ids'] = []
- if False: # TODO(vish): store product codes
- data['product-codes'] = []
+ if self._check_version('2007-01-19', version):
+ meta_data['local-hostname'] = hostname
+ meta_data['public-hostname'] = hostname
+ meta_data['public-ipv4'] = floating_ip
+
+ if False and self._check_version('2007-03-01', version):
+ # TODO(vish): store product codes
+ meta_data['product-codes'] = []
+
+ if self._check_version('2007-08-29', version):
+ meta_data['instance-type'] = self.instance['instance_type']['name']
+
+ if False and self._check_version('2007-10-10', version):
+ # TODO(vish): store ancestor ids
+ meta_data['ancestor-ami-ids'] = []
+
+ if self._check_version('2007-12-15', version):
+ meta_data['block-device-mapping'] = self.mappings
+ if 'kernel-id' in self.ec2_ids:
+ meta_data['kernel-id'] = self.ec2_ids['kernel-id']
+ if 'ramdisk-id' in self.ec2_ids:
+ meta_data['ramdisk-id'] = self.ec2_ids['ramdisk-id']
+
+ if self._check_version('2008-02-01', version):
+ meta_data['placement'] = {'availability-zone':
+ self.availability_zone}
+
+ if self._check_version('2008-09-01', version):
+ meta_data['instance-action'] = 'none'
+
+ data = {'meta-data': meta_data}
+ if self.userdata_b64 is not None:
+ data['user-data'] = self.userdata_b64
return data
+ def _check_version(self, required, requested):
+ return VERSIONS.index(requested) >= VERSIONS.index(required)
+
def lookup(self, path):
if path == "" or path[0] != "/":
path = os.path.normpath("/" + path)
diff --git a/nova/tests/test_metadata.py b/nova/tests/test_metadata.py
index cf48512f0..62822f721 100644
--- a/nova/tests/test_metadata.py
+++ b/nova/tests/test_metadata.py
@@ -211,6 +211,18 @@ class MetadataTestCase(test.TestCase):
self.assertTrue(re.match('aki-[0-9a-f]{8}',
data['meta-data']['kernel-id']))
+ def test_check_version(self):
+ inst = copy(self.instance)
+ md = fake_InstanceMetadata(self.stubs, inst)
+
+ self.assertTrue(md._check_version('1.0', '2009-04-04'))
+ self.assertFalse(md._check_version('2009-04-04', '1.0'))
+
+ self.assertFalse(md._check_version('2009-04-04', '2008-09-01'))
+ self.assertTrue(md._check_version('2008-09-01', '2009-04-04'))
+
+ self.assertTrue(md._check_version('2009-04-04', '2009-04-04'))
+
class MetadataHandlerTestCase(test.TestCase):
"""Test that metadata is returning proper values."""