Handle failures on update_dhcp_port

Ensure exceptions due to conflicting
state of network or subnet resources
are dealt with by the dhcp agent.

Closes-bug:  #1253344
Related-bug: #1243726

Change-Id: I4fd51442c034fabc91d5a3f065f4df98f5fad35b
This commit is contained in:
armando-migliaccio 2013-11-26 14:45:24 -08:00
parent bff120a477
commit b48ddb648b
5 changed files with 65 additions and 8 deletions

View File

@ -448,12 +448,14 @@ class DhcpPluginApi(proxy.RpcProxy):
def update_dhcp_port(self, port_id, port):
"""Make a remote process call to update the dhcp port."""
return dhcp.DictModel(self.call(self.context,
self.make_msg('update_dhcp_port',
port_id=port_id,
port=port,
host=self.host),
topic=self.topic))
port = self.call(self.context,
self.make_msg('update_dhcp_port',
port_id=port_id,
port=port,
host=self.host),
topic=self.topic)
if port:
return dhcp.DictModel(port)
def release_dhcp_port(self, network_id, device_id):
"""Make a remote process call to release the dhcp port."""

View File

@ -672,6 +672,8 @@ class DeviceManager(object):
[dict(subnet_id=s) for s in dhcp_enabled_subnet_ids])
dhcp_port = self.plugin.update_dhcp_port(
port.id, {'port': {'fixed_ips': port_fixed_ips}})
if not dhcp_port:
raise exceptions.Conflict()
else:
dhcp_port = port
# break since we found port that matches device_id

View File

@ -51,6 +51,8 @@ class DhcpRpcCallbackMixin(object):
try:
if action == 'create_port':
return plugin.create_port(context, port)
elif action == 'update_port':
return plugin.update_port(context, port['id'], port['port'])
else:
msg = _('Unrecognized action')
raise n_exc.Invalid(message=msg)
@ -278,4 +280,6 @@ class DhcpRpcCallbackMixin(object):
{'port': port,
'host': host})
plugin = manager.NeutronManager.get_plugin()
return plugin.update_port(context, port_id, port)
return self._port_action(plugin, context,
{'id': port_id, 'port': port},
'update_port')

View File

@ -63,6 +63,22 @@ class TestDhcpRpcCallackMixin(base.BaseTestCase):
{'port': port},
action))
def _test__port_action_good_action(self, action, port, expected_call):
self.callbacks._port_action(self.plugin, mock.Mock(),
port, action)
self.plugin.assert_has_calls(expected_call)
def test_port_action_create_port(self):
self._test__port_action_good_action(
'create_port', mock.Mock(),
mock.call.create_port(mock.ANY, mock.ANY))
def test_port_action_update_port(self):
fake_port = {'id': 'foo_port_id', 'port': mock.Mock()}
self._test__port_action_good_action(
'update_port', fake_port,
mock.call.update_port(mock.ANY, 'foo_port_id', mock.ANY))
def test__port_action_bad_action(self):
self.assertRaises(
n_exc.Invalid,
@ -149,6 +165,14 @@ class TestDhcpRpcCallackMixin(base.BaseTestCase):
self.plugin.assert_has_calls(expected)
return retval
def test_update_dhcp_port(self):
self.callbacks.update_dhcp_port(mock.Mock(),
host='foo_host',
port_id='foo_port_id',
port=mock.Mock())
self.plugin.assert_has_calls(
mock.call.update_port(mock.ANY, 'foo_port_id', mock.ANY))
def test_get_dhcp_port_existing(self):
port_retval = dict(id='port_id', fixed_ips=[dict(subnet_id='a')])
expectations = [

View File

@ -899,7 +899,13 @@ class TestDhcpPluginApiProxy(base.BaseTestCase):
'fixed_ips': [{'subnet_id': fake_fixed_ip1.subnet_id}],
'device_id': mock.ANY}})
self.assertIsNone(self.proxy.create_dhcp_port(port_body))
self.proxy.create_dhcp_port(port_body)
def test_update_dhcp_port_none(self):
self.call.return_value = None
port_body = {'port': {'fixed_ips':
[{'subnet_id': fake_fixed_ip1.subnet_id}]}}
self.assertIsNone(self.proxy.update_dhcp_port(fake_port1.id,
port_body))
def test_update_dhcp_port(self):
port_body = {'port': {'fixed_ips':
@ -1166,6 +1172,14 @@ class TestDeviceManager(base.BaseTestCase):
def test_setup_device_exists_reuse(self):
self._test_setup_helper(True, True)
def test_create_dhcp_port_raise_conflict(self):
plugin = mock.Mock()
dh = dhcp.DeviceManager(cfg.CONF, cfg.CONF.root_helper, plugin)
plugin.create_dhcp_port.return_value = None
self.assertRaises(exceptions.Conflict,
dh.setup_dhcp_port,
fake_network)
def test_create_dhcp_port_create_new(self):
plugin = mock.Mock()
dh = dhcp.DeviceManager(cfg.CONF, cfg.CONF.root_helper, plugin)
@ -1197,6 +1211,17 @@ class TestDeviceManager(base.BaseTestCase):
mock.call.update_dhcp_port(fake_network_copy.ports[0].id,
port_body)])
def test_update_dhcp_port_raises_conflict(self):
plugin = mock.Mock()
dh = dhcp.DeviceManager(cfg.CONF, cfg.CONF.root_helper, plugin)
fake_network_copy = copy.deepcopy(fake_network)
fake_network_copy.ports[0].device_id = dh.get_device_id(fake_network)
fake_network_copy.subnets[1].enable_dhcp = True
plugin.update_dhcp_port.return_value = None
self.assertRaises(exceptions.Conflict,
dh.setup_dhcp_port,
fake_network_copy)
def test_create_dhcp_port_no_update_or_create(self):
plugin = mock.Mock()
dh = dhcp.DeviceManager(cfg.CONF, cfg.CONF.root_helper, plugin)