Skip to content

Commit

Permalink
Add virtual interface before add fixed IP on nova-network
Browse files Browse the repository at this point in the history
nova allow user to add fixed IP to an instance when the instance
is running. This action will fail due to no virtual interface
will be created before create fixed ip.
TypeError: 'NoneType' object is unsubscriptable will be reported.

Change-Id: I5885806d1965022816633d0105606e7aaf763b3a
Closes-Bug: #1294939
  • Loading branch information
jichenjc committed Nov 11, 2014
1 parent d9d0493 commit e08ce4d
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
16 changes: 16 additions & 0 deletions nova/network/manager.py
Expand Up @@ -893,6 +893,13 @@ def allocate_fixed_ip(self, context, instance_id, network, **kwargs):

vif = objects.VirtualInterface.get_by_instance_and_network(
context, instance_id, network['id'])
if vif is None:
LOG.debug('vif for network %(network)s is used up, '
'trying to create new vif',
{'network': network['id']}, instance=instance)
vif = self._add_virtual_interface(context,
instance_id, network['id'])

fip.allocated = True
fip.virtual_interface_id = vif.id
fip.save()
Expand Down Expand Up @@ -1924,6 +1931,15 @@ def allocate_fixed_ip(self, context, instance_id, network, **kwargs):

vif = objects.VirtualInterface.get_by_instance_and_network(
context, instance_id, network['id'])
if vif is None:
LOG.debug('vif for network %(network)s and instance '
'%(instance_id)s is used up, '
'trying to create new vif',
{'network': network['id'],
'instance_id': instance_id})
vif = self._add_virtual_interface(context,
instance_id, network['id'])

fip.allocated = True
fip.virtual_interface_id = vif.id
fip.save()
Expand Down
85 changes: 85 additions & 0 deletions nova/tests/unit/network/test_manager.py
Expand Up @@ -794,6 +794,52 @@ def test_allocate_fixed_ip_cleanup(self,

mock_fixedip_disassociate.assert_called_once_with(self.context)

@mock.patch('nova.objects.instance.Instance.get_by_uuid')
@mock.patch('nova.objects.virtual_interface.VirtualInterface'
'.get_by_instance_and_network')
@mock.patch('nova.objects.fixed_ip.FixedIP.disassociate')
@mock.patch('nova.objects.fixed_ip.FixedIP.associate_pool')
@mock.patch('nova.objects.fixed_ip.FixedIP.save')
@mock.patch('nova.network.manager.NetworkManager._add_virtual_interface')
def test_allocate_fixed_ip_create_new_vifs(self,
mock_add,
mock_fixedip_save,
mock_fixedip_associate,
mock_fixedip_disassociate,
mock_vif_get,
mock_instance_get):
address = netaddr.IPAddress('1.2.3.4')

fip = objects.FixedIP(instance_uuid='fake-uuid',
address=address,
virtual_interface_id=1)
net = {'cidr': '24', 'id': 1, 'uuid': 'nosuch'}
instance = objects.Instance(context=self.context)
instance.create()

vif = objects.VirtualInterface(context,
id=1000,
address='00:00:00:00:00:00',
instance_uuid=instance.uuid,
network_id=net['id'],
uuid='nosuch')
mock_fixedip_associate.return_value = fip
mock_add.return_value = vif
mock_instance_get.return_value = instance
mock_vif_get.return_value = None

with contextlib.nested(
mock.patch.object(self.network, '_setup_network_on_host'),
mock.patch.object(self.network, 'instance_dns_manager'),
mock.patch.object(self.network,
'_do_trigger_security_group_members_refresh_for_instance')
) as (mock_setup_network, mock_dns_manager, mock_ignored):
self.network.allocate_fixed_ip(self.context, instance['uuid'],
net)
mock_add.assert_called_once_with(self.context, instance['uuid'],
net['id'])
self.assertEqual(fip.virtual_interface_id, vif.id)


class FlatDHCPNetworkTestCase(test.TestCase):

Expand Down Expand Up @@ -944,6 +990,45 @@ def test_allocate_fixed_ip(self):
network.vpn_private_address = '192.168.0.2'
self.network.allocate_fixed_ip(self.context, FAKEUUID, network)

@mock.patch('nova.network.manager.VlanManager._setup_network_on_host')
@mock.patch('nova.network.manager.VlanManager.'
'_validate_instance_zone_for_dns_domain')
@mock.patch('nova.network.manager.VlanManager.'
'_do_trigger_security_group_members_refresh_for_instance')
@mock.patch('nova.network.manager.VlanManager._add_virtual_interface')
@mock.patch('nova.objects.instance.Instance.get_by_uuid')
@mock.patch('nova.objects.fixed_ip.FixedIP.associate')
@mock.patch('nova.objects.fixed_ip.FixedIP.save')
@mock.patch('nova.objects.VirtualInterface.get_by_instance_and_network')
def test_allocate_fixed_ip_return_none(self, mock_get, mock_save,
mock_associate, mock_get_uuid, mock_add, mock_trigger,
mock_validate, mock_setup):
net = {'cidr': '24', 'id': 1, 'uuid': 'nosuch'}
fip = objects.FixedIP(instance_uuid='fake-uuid',
address=netaddr.IPAddress('1.2.3.4'),
virtual_interface_id=1)

instance = objects.Instance(context=self.context)
instance.create()

vif = objects.VirtualInterface(self.context,
id=1000,
address='00:00:00:00:00:00',
instance_uuid=instance.uuid,
network_id=net['id'],
uuid='nosuch')
mock_associate.return_value = fip
mock_add.return_value = vif
mock_get.return_value = None
mock_get_uuid.return_value = instance
mock_validate.return_value = False

self.network.allocate_fixed_ip(self.context_admin, instance.uuid, net)

mock_add.assert_called_once_with(self.context_admin, instance.uuid,
net['id'])
mock_save.assert_called_once_with()

@mock.patch('nova.objects.instance.Instance.get_by_uuid')
@mock.patch('nova.objects.fixed_ip.FixedIP.associate')
def test_allocate_fixed_ip_passes_string_address(self, mock_associate,
Expand Down

0 comments on commit e08ce4d

Please sign in to comment.