Refactor metadata code out of ec2/cloud.py

part 2 of blueprint separate-nova-metadata

Change-Id: Id41e48434ff3a38e524a1c64757a21bd461c06b8
This commit is contained in:
Vishvananda Ishaya 2011-11-05 15:51:43 -07:00
parent de635fc882
commit 1a209e6f83
7 changed files with 295 additions and 260 deletions

View File

@ -32,13 +32,11 @@ import urllib
from nova import block_device
from nova import compute
from nova import context
from nova import crypto
from nova import db
from nova import exception
from nova import flags
from nova import ipv6
from nova import log as logging
from nova import network
from nova import rpc
@ -54,7 +52,7 @@ FLAGS = flags.FLAGS
flags.DECLARE('dhcp_domain', 'nova.network.manager')
flags.DECLARE('service_down_time', 'nova.scheduler.driver')
LOG = logging.getLogger("nova.api.cloud")
LOG = logging.getLogger("nova.api.ec2.cloud")
def _gen_key(context, user_id, key_name):
@ -104,14 +102,6 @@ def state_description_from_vm_state(vm_state):
return _STATE_DESCRIPTION_MAP.get(vm_state, vm_state)
# TODO(yamahata): hypervisor dependent default device name
_DEFAULT_ROOT_DEVICE_NAME = '/dev/sda1'
_DEFAULT_MAPPINGS = {'ami': 'sda1',
'ephemeral0': 'sda2',
'root': _DEFAULT_ROOT_DEVICE_NAME,
'swap': 'sda3'}
def _parse_block_device_mapping(bdm):
"""Parse BlockDeviceMappingItemType into flat hash
BlockDevicedMapping.<N>.DeviceName
@ -237,58 +227,6 @@ class CloudController(object):
utils.runthis(_("Generating root CA: %s"), "sh", genrootca_sh_path)
os.chdir(start)
def _get_ip_info_for_instance(self, context, instance):
"""Return a list of all fixed IPs for an instance"""
ip_info = dict(fixed_ips=[], fixed_ip6s=[], floating_ips=[])
fixed_ips = instance['fixed_ips']
for fixed_ip in fixed_ips:
fixed_addr = fixed_ip['address']
network = fixed_ip.get('network')
vif = fixed_ip.get('virtual_interface')
if not network or not vif:
name = instance['name']
ip = fixed_ip['address']
LOG.warn(_("Instance %(name)s has stale IP "
"address: %(ip)s (no network or vif)") % locals())
continue
cidr_v6 = network.get('cidr_v6')
if FLAGS.use_ipv6 and cidr_v6:
ipv6_addr = ipv6.to_global(cidr_v6, vif['address'],
network['project_id'])
if ipv6_addr not in ip_info['fixed_ip6s']:
ip_info['fixed_ip6s'].append(ipv6_addr)
for floating_ip in fixed_ip.get('floating_ips', []):
float_addr = floating_ip['address']
ip_info['floating_ips'].append(float_addr)
ip_info['fixed_ips'].append(fixed_addr)
return ip_info
def _get_mpi_data(self, context, project_id):
result = {}
search_opts = {'project_id': project_id, 'deleted': False}
for instance in self.compute_api.get_all(context,
search_opts=search_opts):
ip_info = self._get_ip_info_for_instance(context, instance)
# only look at ipv4 addresses
fixed_ips = ip_info['fixed_ips']
if fixed_ips:
line = '%s slots=%d' % (fixed_ips[0], instance['vcpus'])
key = str(instance['key_name'])
if key in result:
result[key].append(line)
else:
result[key] = [line]
return result
def _get_availability_zone_by_host(self, context, host):
services = db.service_get_all_by_host(context.elevated(), host)
if len(services) > 0:
return services[0]['availability_zone']
return 'unknown zone'
def _get_image_state(self, image):
# NOTE(vish): fallback status if image_state isn't set
state = image.get('status')
@ -296,120 +234,6 @@ class CloudController(object):
state = 'available'
return image['properties'].get('image_state', state)
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_local_device = instance_ref.get('default_local_device')
if default_local_device:
mappings['ephemeral0'] = default_local_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['id']):
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):
ctxt = context.get_admin_context()
search_opts = {'fixed_ip': address, 'deleted': False}
try:
instance_ref = self.compute_api.get_all(ctxt,
search_opts=search_opts)
except exception.NotFound:
instance_ref = None
if not instance_ref:
return None
# This ensures that all attributes of the instance
# are populated.
instance_ref = db.instance_get(ctxt, instance_ref[0]['id'])
mpi = self._get_mpi_data(ctxt, instance_ref['project_id'])
hostname = "%s.%s" % (instance_ref['hostname'], FLAGS.dhcp_domain)
host = instance_ref['host']
availability_zone = self._get_availability_zone_by_host(ctxt, host)
ip_info = self._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_ec2_id = self.image_ec2_id(instance_ref['image_ref'])
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': self._format_user_data(instance_ref),
'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,
'mpi': mpi}}
# 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):
ec2_id = self.image_ec2_id(instance_ref['%s_id' % image_type],
self._image_type(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'] = []
return data
def describe_availability_zones(self, context, **kwargs):
if ('zone_name' in kwargs and
'verbose' in kwargs['zone_name'] and
@ -1124,18 +948,14 @@ class CloudController(object):
if kernel_uuid is None or kernel_uuid == '':
return
kernel_id = self._get_image_id(context, kernel_uuid)
result[key] = self.image_ec2_id(kernel_id, 'aki')
result[key] = ec2utils.image_ec2_id(kernel_id, 'aki')
def _format_ramdisk_id(self, context, instance_ref, result, key):
ramdisk_uuid = instance_ref['ramdisk_id']
if ramdisk_uuid is None or ramdisk_uuid == '':
return
ramdisk_id = self._get_image_id(context, ramdisk_uuid)
result[key] = self.image_ec2_id(ramdisk_id, 'ari')
@staticmethod
def _format_user_data(instance_ref):
return base64.b64decode(instance_ref['user_data'])
result[key] = ec2utils.image_ec2_id(ramdisk_id, 'ari')
def describe_instance_attribute(self, context, instance_id, attribute,
**kwargs):
@ -1182,7 +1002,7 @@ class CloudController(object):
_unsupported_attribute(instance, result)
def _format_attr_user_data(instance, result):
result['userData'] = self._format_user_data(instance)
result['userData'] = base64.b64decode(instance['user_data'])
attribute_formatter = {
'blockDeviceMapping': _format_attr_block_device_mapping,
@ -1264,7 +1084,7 @@ class CloudController(object):
@staticmethod
def _format_instance_root_device_name(instance, result):
result['rootDeviceName'] = (instance.get('root_device_name') or
_DEFAULT_ROOT_DEVICE_NAME)
block_device.DEFAULT_ROOT_DEV_NAME)
@staticmethod
def _format_instance_type(instance, result):
@ -1317,7 +1137,7 @@ class CloudController(object):
i['instanceId'] = ec2_id
image_uuid = instance['image_ref']
image_id = self._get_image_id(context, image_uuid)
i['imageId'] = self.image_ec2_id(image_id)
i['imageId'] = ec2utils.image_ec2_id(image_id)
self._format_kernel_id(context, instance, i, 'kernelId')
self._format_ramdisk_id(context, instance, i, 'ramdiskId')
i['instanceState'] = {
@ -1326,7 +1146,7 @@ class CloudController(object):
fixed_ip = None
floating_ip = None
ip_info = self._get_ip_info_for_instance(context, instance)
ip_info = ec2utils.get_ip_info_for_instance(context, instance)
if ip_info['fixed_ips']:
fixed_ip = ip_info['fixed_ips'][0]
if ip_info['floating_ips']:
@ -1355,7 +1175,8 @@ class CloudController(object):
self._format_instance_bdm(context, instance_id,
i['rootDeviceName'], i)
host = instance['host']
zone = self._get_availability_zone_by_host(context, host)
services = db.service_get_all_by_host(context.elevated(), host)
zone = ec2utils.get_availability_zone_by_host(services, host)
i['placement'] = {'availabilityZone': zone}
if instance['reservation_id'] not in reservations:
r = {}
@ -1537,34 +1358,6 @@ class CloudController(object):
**changes)
return True
@staticmethod
def _image_type(image_type):
"""Converts to a three letter image type.
aki, kernel => aki
ari, ramdisk => ari
anything else => ami
"""
if image_type == 'kernel':
return 'aki'
if image_type == 'ramdisk':
return 'ari'
if image_type not in ['aki', 'ari']:
return 'ami'
return image_type
@staticmethod
def image_ec2_id(image_id, image_type='ami'):
"""Returns image ec2_id using id and three letter type."""
template = image_type + '-%08x'
try:
return ec2utils.id_to_ec2_id(image_id, template=template)
except ValueError:
#TODO(wwolf): once we have ec2_id -> glance_id mapping
# in place, this wont be necessary
return "ami-00000000"
def _get_image(self, context, ec2_id):
try:
internal_id = ec2utils.ec2_id_to_id(ec2_id)
@ -1575,7 +1368,7 @@ class CloudController(object):
except exception.NotFound:
raise exception.ImageNotFound(image_id=ec2_id)
image_type = ec2_id.split('-')[0]
if self._image_type(image.get('container_format')) != image_type:
if ec2utils.image_type(image.get('container_format')) != image_type:
raise exception.ImageNotFound(image_id=ec2_id)
return image
@ -1591,16 +1384,16 @@ class CloudController(object):
def _format_image(self, image):
"""Convert from format defined by GlanceImageService to S3 format."""
i = {}
image_type = self._image_type(image.get('container_format'))
ec2_id = self.image_ec2_id(image.get('id'), image_type)
image_type = ec2utils.image_type(image.get('container_format'))
ec2_id = ec2utils.image_ec2_id(image.get('id'), image_type)
name = image.get('name')
i['imageId'] = ec2_id
kernel_id = image['properties'].get('kernel_id')
if kernel_id:
i['kernelId'] = self.image_ec2_id(kernel_id, 'aki')
i['kernelId'] = ec2utils.image_ec2_id(kernel_id, 'aki')
ramdisk_id = image['properties'].get('ramdisk_id')
if ramdisk_id:
i['ramdiskId'] = self.image_ec2_id(ramdisk_id, 'ari')
i['ramdiskId'] = ec2utils.image_ec2_id(ramdisk_id, 'ari')
i['imageOwnerId'] = image['properties'].get('owner_id')
if name:
i['imageLocation'] = "%s (%s)" % (image['properties'].
@ -1626,7 +1419,8 @@ class CloudController(object):
('snapshot_id' in bdm or 'volume_id' in bdm) and
not bdm.get('no_device')):
root_device_type = 'ebs'
i['rootDeviceName'] = (root_device_name or _DEFAULT_ROOT_DEVICE_NAME)
i['rootDeviceName'] = (root_device_name or
block_device.DEFAULT_ROOT_DEV_NAME)
i['rootDeviceType'] = root_device_type
_format_mappings(properties, i)
@ -1657,8 +1451,8 @@ class CloudController(object):
def _register_image(self, context, metadata):
image = self.image_service.create(context, metadata)
image_type = self._image_type(image.get('container_format'))
image_id = self.image_ec2_id(image['id'], image_type)
image_type = ec2utils.image_type(image.get('container_format'))
image_id = ec2utils.image_ec2_id(image['id'], image_type)
return image_id
def register_image(self, context, image_location=None, **kwargs):
@ -1694,7 +1488,7 @@ class CloudController(object):
result['rootDeviceName'] = \
block_device.properties_root_device_name(image['properties'])
if result['rootDeviceName'] is None:
result['rootDeviceName'] = _DEFAULT_ROOT_DEVICE_NAME
result['rootDeviceName'] = block_device.DEFAULT_ROOT_DEV_NAME
supported_attributes = {
'blockDeviceMapping': _block_device_mapping_attribute,

View File

@ -19,6 +19,30 @@
import re
from nova import exception
from nova import flags
from nova import log as logging
from nova import ipv6
FLAGS = flags.FLAGS
LOG = logging.getLogger("nova.api.ec2.ec2utils")
def image_type(image_type):
"""Converts to a three letter image type.
aki, kernel => aki
ari, ramdisk => ari
anything else => ami
"""
if image_type == 'kernel':
return 'aki'
if image_type == 'ramdisk':
return 'ari'
if image_type not in ['aki', 'ari']:
return 'ami'
return image_type
def ec2_id_to_id(ec2_id):
@ -29,6 +53,53 @@ def ec2_id_to_id(ec2_id):
raise exception.InvalidEc2Id(ec2_id=ec2_id)
def image_ec2_id(image_id, image_type='ami'):
"""Returns image ec2_id using id and three letter type."""
template = image_type + '-%08x'
try:
return id_to_ec2_id(image_id, template=template)
except ValueError:
#TODO(wwolf): once we have ec2_id -> glance_id mapping
# in place, this wont be necessary
return "ami-00000000"
def get_ip_info_for_instance(context, instance):
"""Return a list of all fixed IPs for an instance"""
ip_info = dict(fixed_ips=[], fixed_ip6s=[], floating_ips=[])
fixed_ips = instance['fixed_ips']
for fixed_ip in fixed_ips:
fixed_addr = fixed_ip['address']
network = fixed_ip.get('network')
vif = fixed_ip.get('virtual_interface')
if not network or not vif:
name = instance['name']
ip = fixed_ip['address']
LOG.warn(_("Instance %(name)s has stale IP "
"address: %(ip)s (no network or vif)") % locals())
continue
cidr_v6 = network.get('cidr_v6')
if FLAGS.use_ipv6 and cidr_v6:
ipv6_addr = ipv6.to_global(cidr_v6, vif['address'],
network['project_id'])
if ipv6_addr not in ip_info['fixed_ip6s']:
ip_info['fixed_ip6s'].append(ipv6_addr)
for floating_ip in fixed_ip.get('floating_ips', []):
float_addr = floating_ip['address']
ip_info['floating_ips'].append(float_addr)
ip_info['fixed_ips'].append(fixed_addr)
return ip_info
def get_availability_zone_by_host(services, host):
if len(services) > 0:
return services[0]['availability_zone']
return 'unknown zone'
def id_to_ec2_id(instance_id, template='i-%08x'):
"""Convert an instance ID (int) to an ec2 ID (i-[base 16 number])"""
return template % int(instance_id)

View File

@ -18,19 +18,33 @@
"""Metadata request handler."""
import base64
import webob.dec
import webob.exc
from nova import log as logging
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
from nova import wsgi
from nova.api.ec2 import cloud
from nova.api.ec2 import ec2utils
LOG = logging.getLogger('nova.api.metadata')
FLAGS = flags.FLAGS
flags.DECLARE('use_forwarded_for', 'nova.api.auth')
_DEFAULT_MAPPINGS = {'ami': 'sda1',
'ephemeral0': 'sda2',
'root': block_device.DEFAULT_ROOT_DEV_NAME,
'swap': 'sda3'}
class Versions(wsgi.Application):
@ -56,7 +70,143 @@ class MetadataRequestHandler(wsgi.Application):
"""Serve metadata."""
def __init__(self):
self.cc = cloud.CloudController()
self.compute_api = compute.API(
network_api=network.API(),
volume_api=volume.API())
def _get_mpi_data(self, context, project_id):
result = {}
search_opts = {'project_id': project_id, 'deleted': False}
for instance in self.compute_api.get_all(context,
search_opts=search_opts):
ip_info = ec2utils.get_ip_info_for_instance(context, instance)
# only look at ipv4 addresses
fixed_ips = ip_info['fixed_ips']
if fixed_ips:
line = '%s slots=%d' % (fixed_ips[0], instance['vcpus'])
key = str(instance['key_name'])
if key in result:
result[key].append(line)
else:
result[key] = [line]
return result
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_local_device = instance_ref.get('default_local_device')
if default_local_device:
mappings['ephemeral0'] = default_local_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['id']):
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):
ctxt = context.get_admin_context()
search_opts = {'fixed_ip': address, 'deleted': False}
try:
instance_ref = self.compute_api.get_all(ctxt,
search_opts=search_opts)
except exception.NotFound:
instance_ref = None
if not instance_ref:
return None
# This ensures that all attributes of the instance
# are populated.
instance_ref = db.instance_get(ctxt, instance_ref[0]['id'])
mpi = self._get_mpi_data(ctxt, instance_ref['project_id'])
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_ec2_id = ec2utils.image_ec2_id(instance_ref['image_ref'])
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,
'mpi': mpi}}
# 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):
ec2_id = ec2utils.image_ec2_id(
instance_ref['%s_id' % image_type],
ec2utils.image_type(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'] = []
return data
def print_data(self, data):
if isinstance(data, dict):
@ -95,7 +245,7 @@ class MetadataRequestHandler(wsgi.Application):
if FLAGS.use_forwarded_for:
remote_address = req.headers.get('X-Forwarded-For', remote_address)
try:
meta_data = self.cc.get_metadata(remote_address)
meta_data = self.get_metadata(remote_address)
except Exception:
LOG.exception(_('Failed to get metadata for ip: %s'),
remote_address)

View File

@ -18,6 +18,9 @@
import re
DEFAULT_ROOT_DEV_NAME = '/dev/sda1'
def properties_root_device_name(properties):
"""get root device name from image meta data.
If it isn't specified, return None.

View File

@ -36,6 +36,7 @@ from nova import log as logging
from nova import utils
# TODO(eday): Eventually changes these to something not ec2-specific
from nova.api.ec2 import cloud
from nova.api.ec2 import ec2utils
FLAGS = flags.FLAGS
@ -98,7 +99,7 @@ class CloudPipe(object):
key_name = self.setup_key_pair(ctxt)
group_name = self.setup_security_group(ctxt)
ec2_id = self.controller.image_ec2_id(FLAGS.vpn_image_id)
ec2_id = ec2utils.image_ec2_id(FLAGS.vpn_image_id)
reservation = self.controller.run_instances(ctxt,
user_data=self.get_encoded_zip(project_id),
max_count=1,

View File

@ -24,7 +24,6 @@ import os
from eventlet import greenthread
from M2Crypto import BIO
from M2Crypto import RSA
import mox
from nova.api.ec2 import cloud
from nova.api.ec2 import ec2utils
@ -37,7 +36,6 @@ from nova import flags
from nova.image import fake
from nova import log as logging
from nova import manager
from nova import network
from nova import rpc
from nova import test
from nova import utils
@ -1750,33 +1748,6 @@ class CloudTestCase(test.TestCase):
'device_name': '/dev/sd3'},
]
def test_get_instance_mapping(self):
"""Make sure that _get_instance_mapping works"""
ctxt = None
instance_ref0 = {'id': 0,
'root_device_name': None}
instance_ref1 = {'id': 0,
'root_device_name': '/dev/sda1'}
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',
self._fake_bdm_get)
expected = {'ami': 'sda1',
'root': '/dev/sda1',
'ephemeral0': '/dev/sdb',
'swap': '/dev/sdc',
'ephemeral1': '/dev/sdd',
'ephemeral2': '/dev/sd3',
'ebs0': '/dev/sdh',
'ebs1': '/dev/sdi'}
self.assertEqual(self.cloud._format_instance_mapping(ctxt,
instance_ref0),
cloud._DEFAULT_MAPPINGS)
self.assertEqual(self.cloud._format_instance_mapping(ctxt,
instance_ref1),
expected)
def test_describe_instance_attribute(self):
"""Make sure that describe_instance_attribute works"""
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',

View File

@ -23,6 +23,7 @@ import webob
from nova.api.metadata import handler
from nova.db.sqlalchemy import api
from nova import db
from nova import exception
from nova import flags
from nova import network
@ -88,7 +89,7 @@ class MetadataTestCase(test.TestCase):
self.stubs.Set(api, 'instance_get_floating_address', floating_get)
self.app = handler.MetadataRequestHandler()
network_manager = fake_network.FakeNetworkManager()
self.stubs.Set(self.app.cc.network_api,
self.stubs.Set(self.app.compute_api.network_api,
'get_instance_uuids_by_ip_filter',
network_manager.get_instance_uuids_by_ip_filter)
@ -145,3 +146,47 @@ class MetadataTestCase(test.TestCase):
def test_local_hostname_fqdn(self):
self.assertEqual(self.request('/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"""
ctxt = None
instance_ref0 = {'id': 0,
'root_device_name': None}
instance_ref1 = {'id': 0,
'root_device_name': '/dev/sda1'}
def fake_bdm_get(ctxt, id):
return [{'volume_id': 87654321,
'snapshot_id': None,
'no_device': None,
'virtual_name': None,
'delete_on_termination': True,
'device_name': '/dev/sdh'},
{'volume_id': None,
'snapshot_id': None,
'no_device': None,
'virtual_name': 'swap',
'delete_on_termination': None,
'device_name': '/dev/sdc'},
{'volume_id': None,
'snapshot_id': None,
'no_device': None,
'virtual_name': 'ephemeral0',
'delete_on_termination': None,
'device_name': '/dev/sdb'}]
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',
fake_bdm_get)
expected = {'ami': 'sda1',
'root': '/dev/sda1',
'ephemeral0': '/dev/sdb',
'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),
expected)