Add get_by_network() to FixedIPList

This adds support for get_by_network() to FixedIPList, which is needed
by the linux_net module to go full-objects. Since it depends on
information in the VirtualInterface object, this also adds a nested
FixedIP.virtual_interface object, which currently is only reachable
when queried in this way.

Related to blueprint nova-network-objects

Change-Id: I6b53e6eed1dee049a51d95f385132fc28c7cce05
Related-bug: 1290568
This commit is contained in:
Dan Smith 2014-03-11 10:44:15 -07:00
parent 5137045db2
commit 250e72ed1a
2 changed files with 81 additions and 2 deletions

View File

@ -18,6 +18,7 @@ from nova.objects import base as obj_base
from nova.objects import fields
from nova.objects import instance as instance_obj
from nova.objects import network as network_obj
from nova.objects import virtual_interface as vif_obj
from nova.openstack.common import timeutils
@ -26,7 +27,8 @@ FIXED_IP_OPTIONAL_ATTRS = ['instance', 'network']
class FixedIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
# Version 1.0: Initial version
VERSION = '1.0'
# Version 1.1: Added virtual_interface field
VERSION = '1.1'
fields = {
'id': fields.IntegerField(),
@ -40,6 +42,8 @@ class FixedIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
'host': fields.StringField(nullable=True),
'instance': fields.ObjectField('Instance', nullable=True),
'network': fields.ObjectField('Network', nullable=True),
'virtual_interface': fields.ObjectField('VirtualInterface',
nullable=True),
}
@property
@ -54,6 +58,11 @@ class FixedIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
if expected_attrs is None:
expected_attrs = []
for field in fixedip.fields:
if field == 'virtual_interface':
# NOTE(danms): This field is only set when doing a
# FixedIPList.get_by_network() because it's a relatively
# special-case thing, so skip it here
continue
if field not in FIXED_IP_OPTIONAL_ATTRS:
fixedip[field] = db_fixedip[field]
# NOTE(danms): Instance could be deleted, and thus None
@ -155,13 +164,15 @@ class FixedIP(obj_base.NovaPersistentObject, obj_base.NovaObject):
class FixedIPList(obj_base.ObjectListBase, obj_base.NovaObject):
# Version 1.0: Initial version
VERSION = '1.0'
# Version 1.1: Added get_by_network()
VERSION = '1.1'
fields = {
'objects': fields.ListOfObjectsField('FixedIP'),
}
child_versions = {
'1.0': '1.0',
'1.1': '1.1',
}
@obj_base.remotable_classmethod
@ -184,6 +195,38 @@ class FixedIPList(obj_base.ObjectListBase, obj_base.NovaObject):
db_fixedips = db.fixed_ips_by_virtual_interface(context, vif_id)
return obj_base.obj_make_list(context, cls(), FixedIP, db_fixedips)
@obj_base.remotable_classmethod
def get_by_network(cls, context, network, host=None):
ipinfo = db.network_get_associated_fixed_ips(context,
network['id'],
host=host)
if not ipinfo:
return []
fips = cls(context=context, objects=[])
for info in ipinfo:
inst = instance_obj.Instance(context=context,
uuid=info['instance_uuid'],
hostname=info['instance_hostname'],
created_at=info['instance_created'],
updated_at=info['instance_updated'])
vif = vif_obj.VirtualInterface(context=context,
id=info['vif_id'],
address=info['vif_address'])
fip = FixedIP(context=context,
address=info['address'],
instance_uuid=info['instance_uuid'],
network_id=info['network_id'],
virtual_interface_id=info['vif_id'],
allocated=info['allocated'],
leased=info['leased'],
instance=inst,
virtual_interface=vif)
fips.objects.append(fip)
fips.obj_reset_changes()
return fips
@obj_base.remotable_classmethod
def bulk_create(self, context, fixed_ips):
ips = []

View File

@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import iso8601
import mock
import netaddr
@ -44,6 +46,8 @@ fake_fixed_ip = {
class _TestFixedIPObject(object):
def _compare(self, obj, db_obj):
for field in obj.fields:
if field is 'virtual_interface':
continue
if field in fixed_ip.FIXED_IP_OPTIONAL_ATTRS:
if obj.obj_attr_is_set(field) and db_obj[field] is not None:
obj_val = obj[field].uuid
@ -254,6 +258,38 @@ class _TestFixedIPObject(object):
[{'address': '192.168.1.1'},
{'address': '192.168.1.2'}])
@mock.patch('nova.db.network_get_associated_fixed_ips')
def test_get_by_network(self, get):
info = {'address': '1.2.3.4',
'instance_uuid': 'fake-uuid',
'network_id': 0,
'vif_id': 1,
'vif_address': 'de:ad:be:ee:f0:00',
'instance_hostname': 'fake-host',
'instance_updated': datetime.datetime(1955, 11, 5),
'instance_created': datetime.datetime(1955, 11, 5),
'allocated': True,
'leased': True,
}
get.return_value = [info]
fixed_ips = fixed_ip.FixedIPList.get_by_network(
self.context, {'id': 0}, host='fake-host')
get.assert_called_once_with(self.context, 0, host='fake-host')
self.assertEqual(1, len(fixed_ips))
fip = fixed_ips[0]
self.assertEqual('1.2.3.4', str(fip.address))
self.assertEqual('fake-uuid', fip.instance_uuid)
self.assertEqual(0, fip.network_id)
self.assertEqual(1, fip.virtual_interface_id)
self.assertTrue(fip.allocated)
self.assertTrue(fip.leased)
self.assertEqual('fake-uuid', fip.instance.uuid)
self.assertEqual('fake-host', fip.instance.hostname)
self.assertIsInstance(fip.instance.created_at, datetime.datetime)
self.assertIsInstance(fip.instance.updated_at, datetime.datetime)
self.assertEqual(1, fip.virtual_interface.id)
self.assertEqual(info['vif_address'], fip.virtual_interface.address)
class TestFixedIPObject(test_objects._LocalTest,
_TestFixedIPObject):