Merge "Use database joins for fixed ips to other objects"
This commit is contained in:
commit
1d8c249391
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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'),
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user