Merge "Use database joins for fixed ips to other objects"

This commit is contained in:
Jenkins 2014-10-11 19:30:13 +00:00 committed by Gerrit Code Review
commit 1d8c249391
7 changed files with 81 additions and 24 deletions

View File

@ -1357,8 +1357,17 @@ def fixed_ip_get_by_instance(context, instance_uuid):
if not uuidutils.is_uuid_like(instance_uuid):
raise exception.InvalidUUID(uuid=instance_uuid)
vif_and = and_(models.VirtualInterface.id ==
models.FixedIp.virtual_interface_id,
models.VirtualInterface.deleted == 0)
result = model_query(context, models.FixedIp, read_deleted="no").\
filter_by(instance_uuid=instance_uuid).\
outerjoin(models.VirtualInterface, vif_and).\
options(contains_eager("virtual_interface")).\
options(joinedload('network')).\
options(joinedload('floating_ips')).\
order_by(asc(models.VirtualInterface.created_at),
asc(models.VirtualInterface.id)).\
all()
if not result:
@ -1398,6 +1407,8 @@ def fixed_ip_get_by_network_host(context, network_id, host):
def fixed_ips_by_virtual_interface(context, vif_id):
result = model_query(context, models.FixedIp, read_deleted="no").\
filter_by(virtual_interface_id=vif_id).\
options(joinedload('network')).\
options(joinedload('floating_ips')).\
all()
return result

View File

@ -878,6 +878,14 @@ class FixedIp(BASE, NovaBase):
'FixedIp.instance_uuid == Instance.uuid,'
'FixedIp.deleted == 0,'
'Instance.deleted == 0)')
virtual_interface = orm.relationship(VirtualInterface,
backref=orm.backref('fixed_ips'),
foreign_keys=virtual_interface_id,
primaryjoin='and_('
'FixedIp.virtual_interface_id == '
'VirtualInterface.id,'
'FixedIp.deleted == 0,'
'VirtualInterface.deleted == 0)')
class FloatingIp(BASE, NovaBase):

View File

@ -22,7 +22,8 @@ from nova.objects import fields
from nova import utils
FIXED_IP_OPTIONAL_ATTRS = ['instance', 'network']
FIXED_IP_OPTIONAL_ATTRS = ['instance', 'network', 'virtual_interface',
'floating_ips']
class FixedIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
@ -31,7 +32,8 @@ class FixedIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
# Version 1.2: Instance version 1.14
# Version 1.3: Instance 1.15
# Version 1.4: Added default_route field
VERSION = '1.4'
# Version 1.5: Added floating_ips field
VERSION = '1.5'
fields = {
'id': fields.IntegerField(),
@ -48,10 +50,16 @@ class FixedIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
'network': fields.ObjectField('Network', nullable=True),
'virtual_interface': fields.ObjectField('VirtualInterface',
nullable=True),
# NOTE(danms): This should not ever be made lazy-loadable
# because it would create a bit of a loop between FixedIP
# and FloatingIP
'floating_ips': fields.ObjectField('FloatingIPList'),
}
def obj_make_compatible(self, primitive, target_version):
target_version = utils.convert_version_to_tuple(target_version)
if target_version < (1, 5) and 'floating_ips' in primitive:
del primitive['floating_ips']
if target_version < (1, 4) and 'default_route' in primitive:
del primitive['default_route']
if target_version < (1, 3) and 'instance' in primitive:
@ -63,20 +71,15 @@ class FixedIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
primitive['instance']['nova_object.data'], '1.13')
primitive['instance']['nova_object.version'] = '1.13'
@property
def floating_ips(self):
return objects.FloatingIPList.get_by_fixed_ip_id(self._context,
self.id)
@staticmethod
def _from_db_object(context, fixedip, db_fixedip, expected_attrs=None):
if expected_attrs is None:
expected_attrs = []
for field in fixedip.fields:
if field in ('virtual_interface', 'default_route'):
# NOTE(danms): These fields are only set when doing a
if field == 'default_route':
# NOTE(danms): This field is only set when doing a
# FixedIPList.get_by_network() because it's a relatively
# special-case thing, so skip them here
# special-case thing, so skip it here
continue
if field not in FIXED_IP_OPTIONAL_ATTRS:
fixedip[field] = db_fixedip[field]
@ -88,7 +91,20 @@ class FixedIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
db_fixedip['instance']) if db_fixedip['instance'] else None
if 'network' in expected_attrs:
fixedip.network = objects.Network._from_db_object(
context, objects.Network(context), db_fixedip['network'])
context,
objects.Network(context),
db_fixedip['network']) if db_fixedip['network'] else None
if 'virtual_interface' in expected_attrs:
db_vif = db_fixedip['virtual_interface']
vif = objects.VirtualInterface._from_db_object(
context,
objects.VirtualInterface(context),
db_fixedip['virtual_interface']) if db_vif else None
fixedip.virtual_interface = vif
if 'floating_ips' in expected_attrs:
fixedip.floating_ips = obj_base.obj_make_list(
context, objects.FloatingIPList(context),
objects.FloatingIP, db_fixedip['floating_ips'])
fixedip._context = context
fixedip.obj_reset_changes()
return fixedip
@ -186,7 +202,8 @@ class FixedIPList(obj_base.ObjectListBase, obj_base.NovaObject):
# Version 1.2: FixedIP <= version 1.2
# Version 1.3: FixedIP <= version 1.3
# Version 1.4: FixedIP <= version 1.4
VERSION = '1.4'
# Version 1.5: FixedIP <= version 1.5, added expected attrs to gets
VERSION = '1.5'
fields = {
'objects': fields.ListOfObjectsField('FixedIP'),
@ -197,6 +214,7 @@ class FixedIPList(obj_base.ObjectListBase, obj_base.NovaObject):
'1.2': '1.2',
'1.3': '1.3',
'1.4': '1.4',
'1.5': '1.5',
}
@obj_base.remotable_classmethod
@ -207,9 +225,11 @@ class FixedIPList(obj_base.ObjectListBase, obj_base.NovaObject):
@obj_base.remotable_classmethod
def get_by_instance_uuid(cls, context, instance_uuid):
expected_attrs = ['network', 'virtual_interface', 'floating_ips']
db_fixedips = db.fixed_ip_get_by_instance(context, instance_uuid)
return obj_base.obj_make_list(context, cls(context),
objects.FixedIP, db_fixedips)
objects.FixedIP, db_fixedips,
expected_attrs=expected_attrs)
@obj_base.remotable_classmethod
def get_by_host(cls, context, host):
@ -219,9 +239,11 @@ class FixedIPList(obj_base.ObjectListBase, obj_base.NovaObject):
@obj_base.remotable_classmethod
def get_by_virtual_interface_id(cls, context, vif_id):
expected_attrs = ['network', 'floating_ips']
db_fixedips = db.fixed_ips_by_virtual_interface(context, vif_id)
return obj_base.obj_make_list(context, cls(context),
objects.FixedIP, db_fixedips)
objects.FixedIP, db_fixedips,
expected_attrs=expected_attrs)
@obj_base.remotable_classmethod
def get_by_network(cls, context, network, host=None):

View File

@ -28,7 +28,8 @@ class FloatingIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
# Version 1.2: FixedIP <= version 1.2
# Version 1.3: FixedIP <= version 1.3
# Version 1.4: FixedIP <= version 1.4
VERSION = '1.4'
# Version 1.5: FixedIP <= version 1.5
VERSION = '1.5'
fields = {
'id': fields.IntegerField(),
'address': fields.IPAddressField(),
@ -55,6 +56,10 @@ class FloatingIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
self.fixed_ip.obj_make_compatible(
primitive['fixed_ip']['nova_object.data'], '1.3')
primitive['fixed_ip']['nova_object.version'] = '1.3'
elif target_version < (1, 5) and self.obj_attr_is_set('fixed_ip'):
self.fixed_ip.obj_make_compatible(
primitive['fixed_ip']['nova_object.data'], '1.4')
primitive['fixed_ip']['nova_object.version'] = '1.4'
@staticmethod
def _from_db_object(context, floatingip, db_floatingip,
@ -173,6 +178,7 @@ class FloatingIPList(obj_base.ObjectListBase, obj_base.NovaObject):
# Version 1.3: FloatingIP 1.2
# Version 1.4: FloatingIP 1.3
# Version 1.5: FloatingIP 1.4
# Version 1.6: FloatingIP 1.5
fields = {
'objects': fields.ListOfObjectsField('FloatingIP'),
}
@ -183,8 +189,9 @@ class FloatingIPList(obj_base.ObjectListBase, obj_base.NovaObject):
'1.3': '1.2',
'1.4': '1.3',
'1.5': '1.4',
'1.6': '1.5',
}
VERSION = '1.5'
VERSION = '1.6'
@obj_base.remotable_classmethod
def get_all(cls, context):

View File

@ -3629,7 +3629,8 @@ class FixedIPTestCase(BaseInstanceTypeTestCase):
]
db.fixed_ip_bulk_create(self.ctxt, params)
ignored_keys = ['created_at', 'id', 'deleted_at', 'updated_at']
ignored_keys = ['created_at', 'id', 'deleted_at', 'updated_at',
'virtual_interface', 'network', 'floating_ips']
fixed_ip_data = db.fixed_ip_get_by_instance(self.ctxt, instance_uuid)
# we have no `id` in incoming data so we can not use

View File

@ -40,13 +40,16 @@ fake_fixed_ip = {
'leased': False,
'reserved': False,
'host': None,
'network': None,
'virtual_interface': None,
'floating_ips': [],
}
class _TestFixedIPObject(object):
def _compare(self, obj, db_obj):
for field in obj.fields:
if field in ('virtual_interface', 'default_route'):
if field in ('default_route', 'floating_ips'):
continue
if field in fixed_ip.FIXED_IP_OPTIONAL_ATTRS:
if obj.obj_attr_is_set(field) and db_obj[field] is not None:
@ -257,6 +260,10 @@ class _TestFixedIPObject(object):
get.assert_called_once_with(self.context, 123)
self._compare(fixedips[0], fake_fixed_ip)
def test_floating_ips_do_not_lazy_load(self):
fixedip = fixed_ip.FixedIP()
self.assertRaises(NotImplementedError, lambda: fixedip.floating_ips)
@mock.patch('nova.db.fixed_ip_bulk_create')
def test_bulk_create(self, bulk):
fixed_ips = [fixed_ip.FixedIP(address='192.168.1.1'),

View File

@ -944,12 +944,12 @@ object_data = {
'EC2InstanceMapping': '1.0-627baaf4b12c9067200979bdc4558a99',
'EC2SnapshotMapping': '1.0-26cf315be1f8abab4289d4147671c836',
'EC2VolumeMapping': '1.0-2f8c3bf077c65a425294ec2b361c9143',
'FixedIP': '1.4-c86389e85d762b7857db084b0dad0f24',
'FixedIPList': '1.4-663f3790a8783daede3d56748329361e',
'FixedIP': '1.5-2472964d39e50da67202109eb85cd173',
'FixedIPList': '1.5-b150167937c905b207769a17e7201d15',
'Flavor': '1.1-096cfd023c35d07542cf732fb29b45e4',
'FlavorList': '1.1-a3d5551267cb8f62ff38ded125900721',
'FloatingIP': '1.4-27eb68b7c9c620dd5f0561b5a3be0e82',
'FloatingIPList': '1.5-28f21c9c8a12afd51535b3f17900667d',
'FloatingIP': '1.5-27eb68b7c9c620dd5f0561b5a3be0e82',
'FloatingIPList': '1.6-6b50a8954fbd03b2bdd01df088210e86',
'Instance': '1.15-1154dc29398bc3c57f053b8e449bb03d',
'InstanceAction': '1.1-6b1d0a6dbd522b5a83c20757ec659663',
'InstanceActionEvent': '1.1-42dbdba74bd06e0619ca75cd3397cd1b',
@ -996,8 +996,9 @@ object_data = {
object_relationships = {
'BlockDeviceMapping': {'Instance': '1.15'},
'FixedIP': {'Instance': '1.15', 'Network': '1.2',
'VirtualInterface': '1.0'},
'FloatingIP': {'FixedIP': '1.4'},
'VirtualInterface': '1.0',
'FloatingIPList': '1.6'},
'FloatingIP': {'FixedIP': '1.5'},
'Instance': {'InstanceFault': '1.2',
'InstanceInfoCache': '1.5',
'InstanceNUMATopology': '1.0',