separate Metadata logic away from the web service

The changes here are coming as a result of starting on blueprint
config-drive-v2 [1].  I wanted to separate out the "Metadata" from the
"Metadata Server".  Thus, the creation of nova/api/metadata/base.py.

The InstanceMetadata in base.py contains most of the logic for
presenting metadata.  As a result, the Metadata webservice in handler.py
greatly simplified.  This should make it easier to render duplicate
data to a config drive.

Additional changes here:
 * a few more tests
 * removal of the separate 'Versions' handler.  Its now replaced
   by the single handler.

Change-Id: I35fcfd8d7f247763954afc0a9f752f629b243e9b
This commit is contained in:
Scott Moser
2012-06-01 17:24:12 -04:00
parent 7626472ed8
commit 55128d1c5d
4 changed files with 425 additions and 292 deletions

View File

@@ -3,27 +3,11 @@
############
[composite:metadata]
use = egg:Paste#urlmap
/: metaversions
/latest: meta
/1.0: meta
/2007-01-19: meta
/2007-03-01: meta
/2007-08-29: meta
/2007-10-10: meta
/2007-12-15: meta
/2008-02-01: meta
/2008-09-01: meta
/2009-04-04: meta
[pipeline:metaversions]
pipeline = ec2faultwrap logrequest metaverapp
/: meta
[pipeline:meta]
pipeline = ec2faultwrap logrequest metaapp
[app:metaverapp]
paste.app_factory = nova.api.metadata.handler:Versions.factory
[app:metaapp]
paste.app_factory = nova.api.metadata.handler:MetadataRequestHandler.factory

255
nova/api/metadata/base.py Normal file
View File

@@ -0,0 +1,255 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Instance Metadata information."""
import base64
import os
from nova.api.ec2 import ec2utils
from nova import block_device
from nova import compute
from nova import context
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
from nova import network
from nova import volume
FLAGS = flags.FLAGS
flags.DECLARE('dhcp_domain', 'nova.network.manager')
_DEFAULT_MAPPINGS = {'ami': 'sda1',
'ephemeral0': 'sda2',
'root': block_device.DEFAULT_ROOT_DEV_NAME,
'swap': 'sda3'}
VERSIONS = [
'1.0',
'2007-01-19',
'2007-03-01',
'2007-08-29',
'2007-10-10',
'2007-12-15',
'2008-02-01',
'2008-09-01',
'2009-04-04',
]
class InvalidMetadataEc2Version(Exception):
pass
class InvalidMetadataPath(Exception):
pass
class InstanceMetadata():
"""Instance metadata."""
def __init__(self, instance, address=None):
self.instance = instance
ctxt = context.get_admin_context()
services = db.service_get_all_by_host(ctxt.elevated(),
instance['host'])
self.availability_zone = ec2utils.get_availability_zone_by_host(
services, instance['host'])
self.ip_info = ec2utils.get_ip_info_for_instance(ctxt, instance)
self.security_groups = db.security_group_get_by_instance(ctxt,
instance['id'])
self.mappings = _format_instance_mapping(ctxt, instance)
if instance.get('user_data', None) != None:
self.userdata_b64 = base64.b64decode(instance['user_data'])
else:
self.userdata_b64 = None
self.ec2_ids = {}
self.ec2_ids['instance-id'] = ec2utils.id_to_ec2_id(instance['id'])
self.ec2_ids['ami-id'] = ec2utils.glance_id_to_ec2_id(ctxt,
instance['image_ref'])
for image_type in ['kernel', 'ramdisk']:
if self.instance.get('%s_id' % image_type):
image_id = self.instance['%s_id' % image_type]
image_type = ec2utils.image_type(image_type)
ec2_id = ec2utils.glance_id_to_ec2_id(ctxt, image_id,
image_type)
self.ec2_ids['%s-id' % image_type] = ec2_id
self.address = address
def get_ec2_metadata(self, version):
if version == "latest":
version = VERSIONS[-1]
if version not in VERSIONS:
raise InvalidMetadataEc2Version(version)
hostname = "%s.%s" % (self.instance['hostname'], FLAGS.dhcp_domain)
floating_ips = self.ip_info['floating_ips']
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 != None:
data['user-data'] = self.userdata_b64
# public-keys should be in meta-data only if user specified one
if self.instance['key_name']:
data['meta-data']['public-keys'] = {
'0': {'_name': 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'] = []
return data
def lookup(self, path):
if path == "" or path[0] != "/":
path = os.path.normpath("/" + path)
else:
path = os.path.normpath(path)
if path == "/":
return VERSIONS + ["latest"]
items = path.split('/')[1:]
try:
md = self.get_ec2_metadata(items[0])
except InvalidMetadataEc2Version:
raise InvalidMetadataPath(path)
data = md
for i in range(1, len(items)):
if isinstance(data, dict) or isinstance(data, list):
if items[i] in data:
data = data[items[i]]
else:
raise InvalidMetadataPath(path)
else:
if i != len(items) - 1:
raise InvalidMetadataPath(path)
data = data[items[i]]
return data
def get_metadata_by_address(address):
ctxt = context.get_admin_context()
fixed_ip = network.API().get_fixed_ip_by_address(ctxt, address)
instance = db.instance_get(ctxt, fixed_ip['instance_id'])
return InstanceMetadata(instance, address)
def _format_instance_mapping(ctxt, instance):
root_device_name = instance['root_device_name']
if root_device_name is None:
return _DEFAULT_MAPPINGS
mappings = {}
mappings['ami'] = block_device.strip_dev(root_device_name)
mappings['root'] = root_device_name
default_ephemeral_device = instance.get('default_ephemeral_device')
if default_ephemeral_device:
mappings['ephemeral0'] = default_ephemeral_device
default_swap_device = instance.get('default_swap_device')
if default_swap_device:
mappings['swap'] = default_swap_device
ebs_devices = []
# 'ephemeralN', 'swap' and ebs
for bdm in db.block_device_mapping_get_all_by_instance(
ctxt, instance['uuid']):
if bdm['no_device']:
continue
# ebs volume case
if (bdm['volume_id'] or bdm['snapshot_id']):
ebs_devices.append(bdm['device_name'])
continue
virtual_name = bdm['virtual_name']
if not virtual_name:
continue
if block_device.is_swap_or_ephemeral(virtual_name):
mappings[virtual_name] = bdm['device_name']
# NOTE(yamahata): I'm not sure how ebs device should be numbered.
# Right now sort by device name for deterministic
# result.
if ebs_devices:
nebs = 0
ebs_devices.sort()
for ebs in ebs_devices:
mappings['ebs%d' % nebs] = ebs
nebs += 1
return mappings
def ec2_md_print(data):
if isinstance(data, dict):
output = ''
for key in sorted(data.keys()):
if key == '_name':
continue
output += key
if isinstance(data[key], dict):
if '_name' in data[key]:
output += '=' + str(data[key]['_name'])
else:
output += '/'
output += '\n'
return output[:-1]
elif isinstance(data, list):
return '\n'.join(data)
else:
return str(data)

View File

@@ -18,115 +18,31 @@
"""Metadata request handler."""
import base64
import webob.dec
import webob.exc
from nova.api.ec2 import ec2utils
from nova import block_device
from nova import compute
from nova import context
from nova import db
from nova.api.metadata import base
from nova import exception
from nova import flags
from nova import log as logging
from nova import network
from nova import volume
from nova import wsgi
LOG = logging.getLogger(__name__)
FLAGS = flags.FLAGS
flags.DECLARE('use_forwarded_for', 'nova.api.auth')
flags.DECLARE('dhcp_domain', 'nova.network.manager')
if FLAGS.memcached_servers:
import memcache
else:
from nova.common import memorycache as memcache
_DEFAULT_MAPPINGS = {'ami': 'sda1',
'ephemeral0': 'sda2',
'root': block_device.DEFAULT_ROOT_DEV_NAME,
'swap': 'sda3'}
class Versions(wsgi.Application):
@webob.dec.wsgify(RequestClass=wsgi.Request)
def __call__(self, req):
"""Respond to a request for all versions."""
# available api versions
versions = [
'1.0',
'2007-01-19',
'2007-03-01',
'2007-08-29',
'2007-10-10',
'2007-12-15',
'2008-02-01',
'2008-09-01',
'2009-04-04',
]
return ''.join('%s\n' % v for v in versions)
class MetadataRequestHandler(wsgi.Application):
"""Serve metadata."""
def __init__(self):
self.network_api = network.API()
self.compute_api = compute.API(
network_api=self.network_api,
volume_api=volume.API())
self._cache = memcache.Client(FLAGS.memcached_servers, debug=0)
def _format_instance_mapping(self, ctxt, instance_ref):
root_device_name = instance_ref['root_device_name']
if root_device_name is None:
return _DEFAULT_MAPPINGS
mappings = {}
mappings['ami'] = block_device.strip_dev(root_device_name)
mappings['root'] = root_device_name
default_ephemeral_device = instance_ref.get('default_ephemeral_device')
if default_ephemeral_device:
mappings['ephemeral0'] = default_ephemeral_device
default_swap_device = instance_ref.get('default_swap_device')
if default_swap_device:
mappings['swap'] = default_swap_device
ebs_devices = []
# 'ephemeralN', 'swap' and ebs
for bdm in db.block_device_mapping_get_all_by_instance(
ctxt, instance_ref['uuid']):
if bdm['no_device']:
continue
# ebs volume case
if (bdm['volume_id'] or bdm['snapshot_id']):
ebs_devices.append(bdm['device_name'])
continue
virtual_name = bdm['virtual_name']
if not virtual_name:
continue
if block_device.is_swap_or_ephemeral(virtual_name):
mappings[virtual_name] = bdm['device_name']
# NOTE(yamahata): I'm not sure how ebs device should be numbered.
# Right now sort by device name for deterministic
# result.
if ebs_devices:
nebs = 0
ebs_devices.sort()
for ebs in ebs_devices:
mappings['ebs%d' % nebs] = ebs
nebs += 1
return mappings
def get_metadata(self, address):
if not address:
raise exception.FixedIpNotFoundForAddress(address=address)
@@ -136,110 +52,21 @@ class MetadataRequestHandler(wsgi.Application):
if data:
return data
ctxt = context.get_admin_context()
try:
fixed_ip = self.network_api.get_fixed_ip_by_address(ctxt, address)
instance_ref = db.instance_get(ctxt, fixed_ip['instance_id'])
data = base.get_metadata_by_address(address)
except exception.NotFound:
return None
hostname = "%s.%s" % (instance_ref['hostname'], FLAGS.dhcp_domain)
host = instance_ref['host']
services = db.service_get_all_by_host(ctxt.elevated(), host)
availability_zone = ec2utils.get_availability_zone_by_host(services,
host)
ip_info = ec2utils.get_ip_info_for_instance(ctxt, instance_ref)
floating_ips = ip_info['floating_ips']
floating_ip = floating_ips and floating_ips[0] or ''
ec2_id = ec2utils.id_to_ec2_id(instance_ref['id'])
image_id = instance_ref['image_ref']
ctxt = context.get_admin_context()
image_ec2_id = ec2utils.glance_id_to_ec2_id(ctxt, image_id)
security_groups = db.security_group_get_by_instance(ctxt,
instance_ref['id'])
security_groups = [x['name'] for x in security_groups]
mappings = self._format_instance_mapping(ctxt, instance_ref)
data = {
'user-data': base64.b64decode(instance_ref['user_data']),
'meta-data': {
'ami-id': image_ec2_id,
'ami-launch-index': instance_ref['launch_index'],
'ami-manifest-path': 'FIXME',
'block-device-mapping': mappings,
'hostname': hostname,
'instance-action': 'none',
'instance-id': ec2_id,
'instance-type': instance_ref['instance_type']['name'],
'local-hostname': hostname,
'local-ipv4': address,
'placement': {'availability-zone': availability_zone},
'public-hostname': hostname,
'public-ipv4': floating_ip,
'reservation-id': instance_ref['reservation_id'],
'security-groups': security_groups}}
# public-keys should be in meta-data only if user specified one
if instance_ref['key_name']:
data['meta-data']['public-keys'] = {
'0': {'_name': instance_ref['key_name'],
'openssh-key': instance_ref['key_data']}}
for image_type in ['kernel', 'ramdisk']:
if instance_ref.get('%s_id' % image_type):
image_id = instance_ref['%s_id' % image_type]
image_type = ec2utils.image_type(image_type)
ec2_id = ec2utils.glance_id_to_ec2_id(ctxt,
image_id,
image_type)
data['meta-data']['%s-id' % image_type] = ec2_id
if False: # TODO(vish): store ancestor ids
data['ancestor-ami-ids'] = []
if False: # TODO(vish): store product codes
data['product-codes'] = []
self._cache.set(cache_key, data, 15)
return data
def print_data(self, data):
if isinstance(data, dict):
output = ''
for key in data:
if key == '_name':
continue
output += key
if isinstance(data[key], dict):
if '_name' in data[key]:
output += '=' + str(data[key]['_name'])
else:
output += '/'
output += '\n'
# Cut off last \n
return output[:-1]
elif isinstance(data, list):
return '\n'.join(data)
else:
return str(data)
def lookup(self, path, data):
items = path.split('/')
for item in items:
if item:
if not isinstance(data, dict):
return data
if not item in data:
return None
data = data[item]
return data
@webob.dec.wsgify(RequestClass=wsgi.Request)
def __call__(self, req):
remote_address = req.remote_addr
if FLAGS.use_forwarded_for:
remote_address = req.headers.get('X-Forwarded-For', remote_address)
try:
meta_data = self.get_metadata(remote_address)
except Exception:
@@ -252,7 +79,10 @@ class MetadataRequestHandler(wsgi.Application):
if meta_data is None:
LOG.error(_('Failed to get metadata for ip: %s'), remote_address)
raise webob.exc.HTTPNotFound()
data = self.lookup(req.path_info, meta_data)
if data is None:
try:
data = meta_data.lookup(req.path_info)
except base.InvalidMetadataPath:
raise webob.exc.HTTPNotFound()
return self.print_data(data)
return base.ec2_md_print(data)

View File

@@ -19,8 +19,12 @@
"""Tests for metadata service."""
import base64
from copy import copy
import stubout
import webob
from nova.api.metadata import base
from nova.api.metadata import handler
from nova import db
from nova.db.sqlalchemy import api
@@ -30,119 +34,110 @@ from nova import network
from nova import test
from nova.tests import fake_network
FLAGS = flags.FLAGS
USER_DATA_STRING = ("This is an encoded string")
ENCODE_USER_DATA_STRING = base64.b64encode(USER_DATA_STRING)
INSTANCES = (
{'id': 1,
'uuid': 'b65cee2f-8c69-4aeb-be2f-f79742548fc2',
'name': 'fake',
'project_id': 'test',
'key_name': "mykey",
'key_data': "ssh-rsa AAAAB3Nzai....N3NtHw== someuser@somehost",
'host': 'test',
'launch_index': 1,
'instance_type': {'name': 'm1.tiny'},
'reservation_id': 'r-xxxxxxxx',
'user_data': ENCODE_USER_DATA_STRING,
'image_ref': 7,
'vcpus': 1,
'fixed_ips': [],
'root_device_name': '/dev/sda1',
'info_cache': {'network_info': []},
'hostname': 'test'},
)
def return_non_existing_address(*args, **kwarg):
raise exception.NotFound()
class MetadataTestCase(test.TestCase):
"""Test that metadata is returning proper values."""
def fake_InstanceMetadata(stubs, inst_data, address=None, sgroups=None):
if sgroups == None:
sgroups = [{'name': 'default'}]
def sg_get(*args, **kwargs):
return sgroups
stubs.Set(api, 'security_group_get_by_instance', sg_get)
return base.InstanceMetadata(inst_data, address=address)
def fake_request(stubs, mdinst, relpath, address="127.0.0.1",
fake_get_metadata=None, headers=None):
def get_metadata(address):
return mdinst
app = handler.MetadataRequestHandler()
if fake_get_metadata == None:
fake_get_metadata = get_metadata
if stubs:
stubs.Set(app, 'get_metadata', fake_get_metadata)
request = webob.Request.blank(relpath)
request.remote_addr = address
if headers != None:
request.headers.update(headers)
response = request.get_response(app)
return response
class MetadataTestCase(test.TestCase):
def setUp(self):
super(MetadataTestCase, self).setUp()
self.instance = ({'id': 1,
'uuid': 'b65cee2f-8c69-4aeb-be2f-f79742548fc2',
'name': 'fake',
'project_id': 'test',
'key_name': None,
'host': 'test',
'launch_index': 1,
'instance_type': {'name': 'm1.tiny'},
'reservation_id': 'r-xxxxxxxx',
'user_data': '',
'image_ref': 7,
'vcpus': 1,
'fixed_ips': [],
'root_device_name': '/dev/sda1',
'info_cache': {'network_info': []},
'hostname': 'test'})
def fake_get_floating_ips_by_fixed_address(self, context, fixed_ip):
return ['1.2.3.4', '5.6.7.8']
def instance_get(*args, **kwargs):
return self.instance
def instance_get_list(*args, **kwargs):
return [self.instance]
def get_fixed_ip_by_address(*args, **kwargs):
return {'instance_id': self.instance['id']}
fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
spectacular=True)
self.stubs.Set(network.API, 'get_floating_ips_by_fixed_address',
fake_get_floating_ips_by_fixed_address)
self.stubs.Set(network.API, 'get_fixed_ip_by_address',
get_fixed_ip_by_address)
self.stubs.Set(api, 'instance_get', instance_get)
self.stubs.Set(api, 'instance_get_all_by_filters', instance_get_list)
self.app = handler.MetadataRequestHandler()
network_manager = fake_network.FakeNetworkManager()
self.stubs.Set(self.app.compute_api.network_api,
'get_instance_uuids_by_ip_filter',
network_manager.get_instance_uuids_by_ip_filter)
def request(self, relative_url):
request = webob.Request.blank(relative_url)
request.remote_addr = "127.0.0.1"
return request.get_response(self.app).body
def test_base(self):
self.assertEqual(self.request('/'), 'meta-data/\nuser-data')
self.instance = INSTANCES[0]
def test_user_data(self):
self.instance['user_data'] = base64.b64encode('happy')
self.assertEqual(self.request('/user-data'), 'happy')
inst = copy(self.instance)
inst['user_data'] = base64.b64encode("happy")
md = fake_InstanceMetadata(self.stubs, inst)
self.assertEqual(
md.get_ec2_metadata(version='2009-04-04')['user-data'], "happy")
def test_no_user_data(self):
inst = copy(self.instance)
del inst['user_data']
md = fake_InstanceMetadata(self.stubs, inst)
obj = object()
self.assertEqual(
md.get_ec2_metadata(version='2009-04-04').get('user-data', obj),
obj)
def test_security_groups(self):
def sg_get(*args, **kwargs):
return [{'name': 'default'}, {'name': 'other'}]
self.stubs.Set(api, 'security_group_get_by_instance', sg_get)
self.assertEqual(self.request('/meta-data/security-groups'),
'default\nother')
inst = copy(self.instance)
sgroups = [{'name': 'default'}, {'name': 'other'}]
expected = ['default', 'other']
def test_user_data_non_existing_fixed_address(self):
self.stubs.Set(network.API, 'get_fixed_ip_by_address',
return_non_existing_address)
request = webob.Request.blank('/user-data')
request.remote_addr = "127.1.1.1"
response = request.get_response(self.app)
self.assertEqual(response.status_int, 404)
def test_user_data_none_fixed_address(self):
request = webob.Request.blank('/user-data')
request.remote_addr = None
response = request.get_response(self.app)
self.assertEqual(response.status_int, 500)
def test_user_data_invalid_url(self):
request = webob.Request.blank('/user-data-invalid')
request.remote_addr = "127.0.0.1"
response = request.get_response(self.app)
self.assertEqual(response.status_int, 404)
def test_user_data_with_use_forwarded_header(self):
self.instance['user_data'] = ENCODE_USER_DATA_STRING
self.flags(use_forwarded_for=True)
request = webob.Request.blank('/user-data')
request.remote_addr = "127.0.0.1"
response = request.get_response(self.app)
self.assertEqual(response.status_int, 200)
self.assertEqual(response.body, USER_DATA_STRING)
md = fake_InstanceMetadata(self.stubs, inst, sgroups=sgroups)
data = md.get_ec2_metadata(version='2009-04-04')
self.assertEqual(data['meta-data']['security-groups'], expected)
def test_local_hostname_fqdn(self):
self.assertEqual(self.request('/meta-data/local-hostname'),
md = fake_InstanceMetadata(self.stubs, copy(self.instance))
data = md.get_ec2_metadata(version='2009-04-04')
self.assertEqual(data['meta-data']['local-hostname'],
"%s.%s" % (self.instance['hostname'], FLAGS.dhcp_domain))
def test_get_instance_mapping(self):
"""Make sure that _get_instance_mapping works"""
def test_format_instance_mapping(self):
"""Make sure that _format_instance_mappings works"""
ctxt = None
instance_ref0 = {'id': 0,
'uuid': 'e5fe5518-0288-4fa3-b0c4-c79764101b85',
@@ -180,9 +175,78 @@ class MetadataTestCase(test.TestCase):
'swap': '/dev/sdc',
'ebs0': '/dev/sdh'}
self.assertEqual(self.app._format_instance_mapping(ctxt,
instance_ref0),
handler._DEFAULT_MAPPINGS)
self.assertEqual(self.app._format_instance_mapping(ctxt,
instance_ref1),
self.assertEqual(base._format_instance_mapping(ctxt, instance_ref0),
base._DEFAULT_MAPPINGS)
self.assertEqual(base._format_instance_mapping(ctxt, instance_ref1),
expected)
class MetadataHandlerTestCase(test.TestCase):
"""Test that metadata is returning proper values."""
def setUp(self):
super(MetadataHandlerTestCase, self).setUp()
self.instance = INSTANCES[0]
self.mdinst = fake_InstanceMetadata(self.stubs, self.instance,
address=None, sgroups=None)
def test_root(self):
expected = "\n".join(base.VERSIONS) + "\nlatest"
response = fake_request(self.stubs, self.mdinst, "/")
self.assertEqual(response.body, expected)
response = fake_request(self.stubs, self.mdinst, "/foo/../")
self.assertEqual(response.body, expected)
def test_version_root(self):
response = fake_request(self.stubs, self.mdinst, "/2009-04-04")
self.assertEqual(response.body, 'meta-data/\nuser-data')
response = fake_request(self.stubs, self.mdinst, "/9999-99-99")
self.assertEqual(response.status_int, 404)
def test_user_data_non_existing_fixed_address(self):
self.stubs.Set(network.API, 'get_fixed_ip_by_address',
return_non_existing_address)
response = fake_request(None, self.mdinst, "/2009-04-04/user-data",
"127.1.1.1")
self.assertEqual(response.status_int, 404)
def test_fixed_address_none(self):
response = fake_request(None, self.mdinst,
relpath="/2009-04-04/user-data", address=None)
self.assertEqual(response.status_int, 500)
def test_invalid_path_is_404(self):
response = fake_request(self.stubs, self.mdinst,
relpath="/2009-04-04/user-data-invalid")
self.assertEqual(response.status_int, 404)
def test_user_data_with_use_forwarded_header(self):
expected_addr = "192.192.192.2"
def fake_get_metadata(address):
if address == expected_addr:
return self.mdinst
else:
raise Exception("Expected addr of %s, got %s" %
(expected_addr, address))
self.flags(use_forwarded_for=True)
response = fake_request(self.stubs, self.mdinst,
relpath="/2009-04-04/user-data",
address="168.168.168.1",
fake_get_metadata=fake_get_metadata,
headers={'X-Forwarded-For': expected_addr})
self.assertEqual(response.status_int, 200)
self.assertEqual(response.body,
base64.b64decode(self.instance['user_data']))
response = fake_request(self.stubs, self.mdinst,
relpath="/2009-04-04/user-data",
address="168.168.168.1",
fake_get_metadata=fake_get_metadata,
headers=None)
self.assertEqual(response.status_int, 500)