diff options
| author | Steve Baker <steve@stevebaker.org> | 2012-07-01 19:14:05 +1200 |
|---|---|---|
| committer | Steve Baker <steve@stevebaker.org> | 2012-07-02 09:19:43 +1200 |
| commit | 29b1b4c79360e550cc89a9736dee56576aa5b972 (patch) | |
| tree | 21125602d96fbfdefb50fef4b7863e1ac5bc6c97 | |
| parent | 019d953ef5b4bed7c53401375bfd7aa890fc0c1d (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.py | 71 | ||||
| -rw-r--r-- | nova/tests/test_metadata.py | 12 |
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.""" |
