Merge "Network: enable instance deletion when dhcp release fails"

This commit is contained in:
Jenkins 2014-09-18 00:49:35 +00:00 committed by Gerrit Code Review
commit 5becdc168a
4 changed files with 63 additions and 3 deletions

View File

@ -586,6 +586,10 @@ class NetworkDuplicated(Invalid):
msg_fmt = _("Network %(network_id)s is duplicated.") msg_fmt = _("Network %(network_id)s is duplicated.")
class NetworkDhcpReleaseFailed(NovaException):
msg_fmt = _("Failed to release IP %(address)s with MAC %(mac_address)s")
class NetworkInUse(NovaException): class NetworkInUse(NovaException):
msg_fmt = _("Network %(network_id)s is still in use.") msg_fmt = _("Network %(network_id)s is still in use.")

View File

@ -992,7 +992,12 @@ def get_dhcp_opts(context, network_ref, fixedips):
def release_dhcp(dev, address, mac_address): def release_dhcp(dev, address, mac_address):
utils.execute('dhcp_release', dev, address, mac_address, run_as_root=True) try:
utils.execute('dhcp_release', dev, address, mac_address,
run_as_root=True)
except processutils.ProcessExecutionError:
raise exception.NetworkDhcpReleaseFailed(address=address,
mac_address=mac_address)
def update_dhcp(context, dev, network_ref): def update_dhcp(context, dev, network_ref):

View File

@ -39,7 +39,7 @@ from oslo import messaging
from nova import conductor from nova import conductor
from nova import context from nova import context
from nova import exception from nova import exception
from nova.i18n import _ from nova.i18n import _, _LE
from nova import ipv6 from nova import ipv6
from nova import manager from nova import manager
from nova.network import api as network_api from nova.network import api as network_api
@ -1026,7 +1026,14 @@ class NetworkManager(manager.Manager):
self._teardown_network_on_host(context, network) self._teardown_network_on_host(context, network)
# NOTE(vish): This forces a packet so that the release_fixed_ip # NOTE(vish): This forces a packet so that the release_fixed_ip
# callback will get called by nova-dhcpbridge. # callback will get called by nova-dhcpbridge.
try:
self.driver.release_dhcp(dev, address, vif.address) self.driver.release_dhcp(dev, address, vif.address)
except exception.NetworkDhcpReleaseFailed:
LOG.error(_LE("Error releasing DHCP for IP %(address)s "
"with MAC %(mac_address)s"),
{'address': address,
'mac_address': vif.address},
instance=instance)
# NOTE(yufang521247): This is probably a failed dhcp fixed ip. # NOTE(yufang521247): This is probably a failed dhcp fixed ip.
# DHCPRELEASE packet sent to dnsmasq would not trigger # DHCPRELEASE packet sent to dnsmasq would not trigger

View File

@ -1668,6 +1668,50 @@ class VlanNetworkTestCase(test.TestCase):
fixed_update.assert_called_once_with(context1, fix_addr.address, fixed_update.assert_called_once_with(context1, fix_addr.address,
{'allocated': False}) {'allocated': False})
@mock.patch('nova.db.fixed_ip_get_by_address')
@mock.patch('nova.db.network_get')
@mock.patch('nova.db.fixed_ip_update')
def test_deallocate_fixed_with_dhcp_exception(self, fixed_update, net_get,
fixed_get):
net_get.return_value = dict(test_network.fake_network,
**networks[1])
def vif_get(_context, _vif_id):
return vifs[0]
with contextlib.nested(
mock.patch.object(db, 'virtual_interface_get', vif_get),
mock.patch.object(
utils, 'execute',
side_effect=processutils.ProcessExecutionError()),
) as (_vif_get, _execute):
context1 = context.RequestContext('user', 'project1')
instance = db.instance_create(context1,
{'project_id': 'project1'})
elevated = context1.elevated()
fix_addr = db.fixed_ip_associate_pool(elevated, 1,
instance['uuid'])
fixed_get.return_value = dict(test_fixed_ip.fake_fixed_ip,
address=fix_addr.address,
instance_uuid=instance.uuid,
allocated=True,
virtual_interface_id=3,
network=dict(
test_network.fake_network,
**networks[1]))
self.flags(force_dhcp_release=True)
self.network.deallocate_fixed_ip(context1, fix_addr.address,
'fake')
fixed_update.assert_called_once_with(context1, fix_addr.address,
{'allocated': False})
_execute.assert_called_once_with('dhcp_release',
networks[1]['bridge'],
fix_addr.address,
'DE:AD:BE:EF:00:00',
run_as_root=True)
def test_deallocate_fixed_deleted(self): def test_deallocate_fixed_deleted(self):
# Verify doesn't deallocate deleted fixed_ip from deleted network. # Verify doesn't deallocate deleted fixed_ip from deleted network.