Merge "Make the metadata paths use conductor"
This commit is contained in:
commit
9994a9161d
@ -115,10 +115,10 @@ def get_ip_info_for_instance(context, instance):
|
||||
return get_ip_info_for_instance_from_nw_info(nw_info)
|
||||
|
||||
|
||||
def get_availability_zone_by_host(services, host):
|
||||
def get_availability_zone_by_host(services, host, conductor_api=None):
|
||||
if len(services) > 0:
|
||||
return availability_zones.get_host_availability_zone(
|
||||
context.get_admin_context(), host)
|
||||
context.get_admin_context(), host, conductor_api)
|
||||
return 'unknown zone'
|
||||
|
||||
|
||||
|
@ -26,8 +26,8 @@ import posixpath
|
||||
from nova.api.ec2 import ec2utils
|
||||
from nova.api.metadata import password
|
||||
from nova import block_device
|
||||
from nova import conductor
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova import network
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import timeutils
|
||||
@ -83,7 +83,8 @@ class InvalidMetadataPath(Exception):
|
||||
class InstanceMetadata():
|
||||
"""Instance metadata."""
|
||||
|
||||
def __init__(self, instance, address=None, content=[], extra_md=None):
|
||||
def __init__(self, instance, address=None, content=[], extra_md=None,
|
||||
conductor_api=None):
|
||||
"""Creation of this object should basically cover all time consuming
|
||||
collection. Methods after that should not cause time delays due to
|
||||
network operations or lengthy cpu operations.
|
||||
@ -95,39 +96,32 @@ class InstanceMetadata():
|
||||
self.instance = instance
|
||||
self.extra_md = extra_md
|
||||
|
||||
if conductor_api:
|
||||
self.conductor_api = conductor_api
|
||||
else:
|
||||
self.conductor_api = conductor.API()
|
||||
|
||||
ctxt = context.get_admin_context()
|
||||
|
||||
services = db.service_get_all_by_host(ctxt.elevated(),
|
||||
instance['host'])
|
||||
capi = self.conductor_api
|
||||
services = capi.service_get_all_by_host(ctxt.elevated(),
|
||||
instance['host'])
|
||||
self.availability_zone = ec2utils.get_availability_zone_by_host(
|
||||
services, instance['host'])
|
||||
services, instance['host'], capi)
|
||||
|
||||
self.ip_info = ec2utils.get_ip_info_for_instance(ctxt, instance)
|
||||
|
||||
self.security_groups = db.security_group_get_by_instance(ctxt,
|
||||
instance['id'])
|
||||
self.security_groups = capi.security_group_get_by_instance(ctxt,
|
||||
instance)
|
||||
|
||||
self.mappings = _format_instance_mapping(ctxt, instance)
|
||||
self.mappings = _format_instance_mapping(capi, ctxt, instance)
|
||||
|
||||
if instance.get('user_data', None) is not None:
|
||||
self.userdata_raw = base64.b64decode(instance['user_data'])
|
||||
else:
|
||||
self.userdata_raw = None
|
||||
|
||||
self.ec2_ids = {}
|
||||
|
||||
self.ec2_ids['instance-id'] = ec2utils.id_to_ec2_inst_id(
|
||||
instance['uuid'])
|
||||
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]
|
||||
ec2_image_type = ec2utils.image_type(image_type)
|
||||
ec2_id = ec2utils.glance_id_to_ec2_id(ctxt, image_id,
|
||||
ec2_image_type)
|
||||
self.ec2_ids['%s-id' % image_type] = ec2_id
|
||||
self.ec2_ids = capi.get_ec2_ids(ctxt, instance)
|
||||
|
||||
self.address = address
|
||||
|
||||
@ -404,23 +398,26 @@ class InstanceMetadata():
|
||||
yield ('%s/%s/%s' % ("openstack", CONTENT_DIR, cid), content)
|
||||
|
||||
|
||||
def get_metadata_by_address(address):
|
||||
def get_metadata_by_address(conductor_api, address):
|
||||
ctxt = context.get_admin_context()
|
||||
fixed_ip = network.API().get_fixed_ip_by_address(ctxt, address)
|
||||
|
||||
return get_metadata_by_instance_id(fixed_ip['instance_uuid'],
|
||||
return get_metadata_by_instance_id(conductor_api,
|
||||
fixed_ip['instance_uuid'],
|
||||
address,
|
||||
ctxt)
|
||||
|
||||
|
||||
def get_metadata_by_instance_id(instance_id, address, ctxt=None):
|
||||
def get_metadata_by_instance_id(conductor_api, instance_id, address,
|
||||
ctxt=None):
|
||||
ctxt = ctxt or context.get_admin_context()
|
||||
instance = db.instance_get_by_uuid(ctxt, instance_id)
|
||||
instance = conductor_api.instance_get_by_uuid(ctxt, instance_id)
|
||||
return InstanceMetadata(instance, address)
|
||||
|
||||
|
||||
def _format_instance_mapping(ctxt, instance):
|
||||
bdms = db.block_device_mapping_get_all_by_instance(ctxt, instance['uuid'])
|
||||
def _format_instance_mapping(conductor_api, ctxt, instance):
|
||||
bdms = conductor_api.block_device_mapping_get_all_by_instance(
|
||||
ctxt, instance)
|
||||
return block_device.instance_block_mapping(instance, bdms)
|
||||
|
||||
|
||||
|
@ -26,6 +26,7 @@ import webob.exc
|
||||
|
||||
from nova.api.metadata import base
|
||||
from nova.common import memorycache
|
||||
from nova import conductor
|
||||
from nova import exception
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import log as logging
|
||||
@ -58,6 +59,7 @@ class MetadataRequestHandler(wsgi.Application):
|
||||
|
||||
def __init__(self):
|
||||
self._cache = memorycache.get_client()
|
||||
self.conductor_api = conductor.API()
|
||||
|
||||
def get_metadata_by_remote_address(self, address):
|
||||
if not address:
|
||||
@ -69,7 +71,7 @@ class MetadataRequestHandler(wsgi.Application):
|
||||
return data
|
||||
|
||||
try:
|
||||
data = base.get_metadata_by_address(address)
|
||||
data = base.get_metadata_by_address(self.conductor_api, address)
|
||||
except exception.NotFound:
|
||||
return None
|
||||
|
||||
@ -84,7 +86,8 @@ class MetadataRequestHandler(wsgi.Application):
|
||||
return data
|
||||
|
||||
try:
|
||||
data = base.get_metadata_by_instance_id(instance_id, address)
|
||||
data = base.get_metadata_by_instance_id(self.conductor_api,
|
||||
instance_id, address)
|
||||
except exception.NotFound:
|
||||
return None
|
||||
|
||||
|
@ -52,9 +52,13 @@ def set_availability_zones(context, services):
|
||||
return services
|
||||
|
||||
|
||||
def get_host_availability_zone(context, host):
|
||||
metadata = db.aggregate_metadata_get_by_host(
|
||||
context, host, key='availability_zone')
|
||||
def get_host_availability_zone(context, host, conductor_api=None):
|
||||
if conductor_api:
|
||||
metadata = conductor_api.aggregate_metadata_get_by_host(
|
||||
context, host, key='availability_zone')
|
||||
else:
|
||||
metadata = db.aggregate_metadata_get_by_host(
|
||||
context, host, key='availability_zone')
|
||||
if 'availability_zone' in metadata:
|
||||
return list(metadata['availability_zone'])[0]
|
||||
else:
|
||||
|
@ -154,6 +154,12 @@ class LocalAPI(object):
|
||||
aggregate,
|
||||
key)
|
||||
|
||||
def aggregate_metadata_get_by_host(self, context, host,
|
||||
key='availability_zone'):
|
||||
return self._manager.aggregate_metadata_get_by_host(context,
|
||||
host,
|
||||
key)
|
||||
|
||||
def bw_usage_get(self, context, uuid, start_period, mac):
|
||||
return self._manager.bw_usage_update(context, uuid, mac, start_period)
|
||||
|
||||
@ -319,6 +325,9 @@ class LocalAPI(object):
|
||||
def quota_rollback(self, context, reservations):
|
||||
return self._manager.quota_rollback(context, reservations)
|
||||
|
||||
def get_ec2_ids(self, context, instance):
|
||||
return self._manager.get_ec2_ids(context, instance)
|
||||
|
||||
|
||||
class API(object):
|
||||
"""Conductor API that does updates via RPC to the ConductorManager."""
|
||||
@ -463,6 +472,12 @@ class API(object):
|
||||
aggregate,
|
||||
key)
|
||||
|
||||
def aggregate_metadata_get_by_host(self, context, host,
|
||||
key='availability_zone'):
|
||||
return self.conductor_rpcapi.aggregate_metadata_get_by_host(context,
|
||||
host,
|
||||
key)
|
||||
|
||||
def bw_usage_get(self, context, uuid, start_period, mac):
|
||||
return self.conductor_rpcapi.bw_usage_update(context, uuid, mac,
|
||||
start_period)
|
||||
@ -636,3 +651,6 @@ class API(object):
|
||||
|
||||
def quota_rollback(self, context, reservations):
|
||||
return self.conductor_rpcapi.quota_rollback(context, reservations)
|
||||
|
||||
def get_ec2_ids(self, context, instance):
|
||||
return self.conductor_rpcapi.get_ec2_ids(context, instance)
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
"""Handles database requests from other nova services."""
|
||||
|
||||
from nova.api.ec2 import ec2utils
|
||||
from nova.compute import api as compute_api
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova import exception
|
||||
@ -47,7 +48,7 @@ datetime_fields = ['launched_at', 'terminated_at']
|
||||
class ConductorManager(manager.SchedulerDependentManager):
|
||||
"""Mission: TBD."""
|
||||
|
||||
RPC_API_VERSION = '1.41'
|
||||
RPC_API_VERSION = '1.42'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ConductorManager, self).__init__(service_name='conductor',
|
||||
@ -175,6 +176,11 @@ class ConductorManager(manager.SchedulerDependentManager):
|
||||
self.db.aggregate_metadata_delete(context.elevated(),
|
||||
aggregate['id'], key)
|
||||
|
||||
def aggregate_metadata_get_by_host(self, context, host,
|
||||
key='availability_zone'):
|
||||
result = self.db.aggregate_metadata_get_by_host(context, host, key)
|
||||
return jsonutils.to_primitive(result)
|
||||
|
||||
def bw_usage_update(self, context, uuid, mac, start_period,
|
||||
bw_in=None, bw_out=None,
|
||||
last_ctr_in=None, last_ctr_out=None,
|
||||
@ -384,3 +390,19 @@ class ConductorManager(manager.SchedulerDependentManager):
|
||||
|
||||
def quota_rollback(self, context, reservations):
|
||||
quota.QUOTAS.rollback(context, reservations)
|
||||
|
||||
def get_ec2_ids(self, context, instance):
|
||||
ec2_ids = {}
|
||||
|
||||
ec2_ids['instance-id'] = ec2utils.id_to_ec2_inst_id(instance['uuid'])
|
||||
ec2_ids['ami-id'] = ec2utils.glance_id_to_ec2_id(context,
|
||||
instance['image_ref'])
|
||||
for image_type in ['kernel', 'ramdisk']:
|
||||
if '%s_id' % image_type in instance:
|
||||
image_id = instance['%s_id' % image_type]
|
||||
ec2_image_type = ec2utils.image_type(image_type)
|
||||
ec2_id = ec2utils.glance_id_to_ec2_id(context, image_id,
|
||||
ec2_image_type)
|
||||
ec2_ids['%s-id' % image_type] = ec2_id
|
||||
|
||||
return ec2_ids
|
||||
|
@ -78,6 +78,7 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy):
|
||||
1.41 - Added fixed_ip_get_by_instance, network_get,
|
||||
instance_floating_address_get_all, quota_commit,
|
||||
quota_rollback
|
||||
1.42 - Added get_ec2_ids, aggregate_metadata_get_by_host
|
||||
"""
|
||||
|
||||
BASE_RPC_API_VERSION = '1.0'
|
||||
@ -176,6 +177,11 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy):
|
||||
key=key)
|
||||
return self.call(context, msg, version='1.7')
|
||||
|
||||
def aggregate_metadata_get_by_host(self, context, host, key):
|
||||
msg = self.make_msg('aggregate_metadata_get_by_host', host=host,
|
||||
key=key)
|
||||
return self.call(context, msg, version='1.42')
|
||||
|
||||
def bw_usage_update(self, context, uuid, mac, start_period,
|
||||
bw_in=None, bw_out=None,
|
||||
last_ctr_in=None, last_ctr_out=None,
|
||||
@ -409,3 +415,8 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy):
|
||||
reservations_p = jsonutils.to_primitive(reservations)
|
||||
msg = self.make_msg('quota_rollback', reservations=reservations_p)
|
||||
return self.call(context, msg, version='1.41')
|
||||
|
||||
def get_ec2_ids(self, context, instance):
|
||||
instance_p = jsonutils.to_primitive(instance)
|
||||
msg = self.make_msg('get_ec2_ids', instance=instance_p)
|
||||
return self.call(context, msg, version='1.42')
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import mox
|
||||
|
||||
from nova.api.ec2 import ec2utils
|
||||
from nova.compute import instance_types
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova.compute import vm_states
|
||||
@ -241,6 +242,15 @@ class _BaseTestCase(object):
|
||||
aggregate,
|
||||
'fake')
|
||||
|
||||
def test_aggregate_metadata_get_by_host(self):
|
||||
self.mox.StubOutWithMock(db, 'aggregate_metadata_get_by_host')
|
||||
db.aggregate_metadata_get_by_host(self.context, 'host',
|
||||
'key').AndReturn('result')
|
||||
self.mox.ReplayAll()
|
||||
result = self.conductor.aggregate_metadata_get_by_host(self.context,
|
||||
'host', 'key')
|
||||
self.assertEqual(result, 'result')
|
||||
|
||||
def test_bw_usage_update(self):
|
||||
self.mox.StubOutWithMock(db, 'bw_usage_update')
|
||||
self.mox.StubOutWithMock(db, 'bw_usage_get')
|
||||
@ -537,6 +547,39 @@ class _BaseTestCase(object):
|
||||
self.mox.ReplayAll()
|
||||
self.conductor.quota_rollback(self.context, 'reservations')
|
||||
|
||||
def test_get_ec2_ids(self):
|
||||
expected = {
|
||||
'instance-id': 'ec2-inst-id',
|
||||
'ami-id': 'ec2-ami-id',
|
||||
'kernel-id': 'ami-kernel-ec2-kernelid',
|
||||
'ramdisk-id': 'ami-ramdisk-ec2-ramdiskid',
|
||||
}
|
||||
inst = {
|
||||
'uuid': 'fake-uuid',
|
||||
'kernel_id': 'ec2-kernelid',
|
||||
'ramdisk_id': 'ec2-ramdiskid',
|
||||
'image_ref': 'fake-image',
|
||||
}
|
||||
self.mox.StubOutWithMock(ec2utils, 'id_to_ec2_inst_id')
|
||||
self.mox.StubOutWithMock(ec2utils, 'glance_id_to_ec2_id')
|
||||
self.mox.StubOutWithMock(ec2utils, 'image_type')
|
||||
|
||||
ec2utils.id_to_ec2_inst_id(inst['uuid']).AndReturn(
|
||||
expected['instance-id'])
|
||||
ec2utils.glance_id_to_ec2_id(self.context,
|
||||
inst['image_ref']).AndReturn(
|
||||
expected['ami-id'])
|
||||
for image_type in ['kernel', 'ramdisk']:
|
||||
image_id = inst['%s_id' % image_type]
|
||||
ec2utils.image_type(image_type).AndReturn('ami-' + image_type)
|
||||
ec2utils.glance_id_to_ec2_id(self.context, image_id,
|
||||
'ami-' + image_type).AndReturn(
|
||||
'ami-%s-ec2-%sid' % (image_type, image_type))
|
||||
|
||||
self.mox.ReplayAll()
|
||||
result = self.conductor.get_ec2_ids(self.context, inst)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
|
||||
class ConductorTestCase(_BaseTestCase, test.TestCase):
|
||||
"""Conductor Manager Tests."""
|
||||
|
@ -31,6 +31,7 @@ from nova.api.metadata import base
|
||||
from nova.api.metadata import handler
|
||||
from nova.api.metadata import password
|
||||
from nova import block_device
|
||||
from nova.conductor import api as conductor_api
|
||||
from nova import db
|
||||
from nova.db.sqlalchemy import api
|
||||
from nova import exception
|
||||
@ -118,6 +119,7 @@ class MetadataTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(MetadataTestCase, self).setUp()
|
||||
self.instance = INSTANCES[0]
|
||||
self.flags(use_local=True, group='conductor')
|
||||
fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
|
||||
spectacular=True)
|
||||
|
||||
@ -191,10 +193,11 @@ class MetadataTestCase(test.TestCase):
|
||||
'swap': '/dev/sdc',
|
||||
'ebs0': '/dev/sdh'}
|
||||
|
||||
self.assertEqual(base._format_instance_mapping(ctxt, instance_ref0),
|
||||
block_device._DEFAULT_MAPPINGS)
|
||||
self.assertEqual(base._format_instance_mapping(ctxt, instance_ref1),
|
||||
expected)
|
||||
capi = conductor_api.LocalAPI()
|
||||
self.assertEqual(base._format_instance_mapping(capi, ctxt,
|
||||
instance_ref0), block_device._DEFAULT_MAPPINGS)
|
||||
self.assertEqual(base._format_instance_mapping(capi, ctxt,
|
||||
instance_ref1), expected)
|
||||
|
||||
def test_pubkey(self):
|
||||
md = fake_InstanceMetadata(self.stubs, copy.copy(self.instance))
|
||||
@ -247,6 +250,7 @@ class OpenStackMetadataTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(OpenStackMetadataTestCase, self).setUp()
|
||||
self.instance = INSTANCES[0]
|
||||
self.flags(use_local=True, group='conductor')
|
||||
fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
|
||||
spectacular=True)
|
||||
|
||||
@ -382,6 +386,7 @@ class MetadataHandlerTestCase(test.TestCase):
|
||||
fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
|
||||
spectacular=True)
|
||||
self.instance = INSTANCES[0]
|
||||
self.flags(use_local=True, group='conductor')
|
||||
self.mdinst = fake_InstanceMetadata(self.stubs, self.instance,
|
||||
address=None, sgroups=None)
|
||||
|
||||
@ -547,6 +552,7 @@ class MetadataPasswordTestCase(test.TestCase):
|
||||
fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
|
||||
spectacular=True)
|
||||
self.instance = copy.copy(INSTANCES[0])
|
||||
self.flags(use_local=True, group='conductor')
|
||||
self.mdinst = fake_InstanceMetadata(self.stubs, self.instance,
|
||||
address=None, sgroups=None)
|
||||
self.flags(use_local=True, group='conductor')
|
||||
|
Loading…
Reference in New Issue
Block a user