From a2ceec28647d835aaa5228578537230ff571cee3 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Wed, 13 Apr 2016 05:20:00 -0700 Subject: [PATCH] Don't update DHCP ports in a transaction Updating ports is incompatible with the transaction semantics that happen inside of ML2. See partial-bug for more details. This transaction served no purpose wrapped around the port update because there should only be one port per agent per network and if that port fails to update, the code to delete the binding won't be hit anyway. Change-Id: Ica2c5a19e10ae1773e49537b5ff4ae0eacaeb388 Partial-Bug: #1540844 --- neutron/db/agentschedulers_db.py | 43 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/neutron/db/agentschedulers_db.py b/neutron/db/agentschedulers_db.py index 1f357702475..3cb4294dfdf 100644 --- a/neutron/db/agentschedulers_db.py +++ b/neutron/db/agentschedulers_db.py @@ -374,29 +374,28 @@ class DhcpAgentSchedulerDbMixin(dhcpagentscheduler def remove_network_from_dhcp_agent(self, context, id, network_id, notify=True): agent = self._get_agent(context, id) - with context.session.begin(subtransactions=True): - try: - query = context.session.query(NetworkDhcpAgentBinding) - query = query.filter( - NetworkDhcpAgentBinding.network_id == network_id, - NetworkDhcpAgentBinding.dhcp_agent_id == id) - # just ensure the binding exists - query.one() - except exc.NoResultFound: - raise dhcpagentscheduler.NetworkNotHostedByDhcpAgent( - network_id=network_id, agent_id=id) + try: + query = context.session.query(NetworkDhcpAgentBinding) + binding = query.filter( + NetworkDhcpAgentBinding.network_id == network_id, + NetworkDhcpAgentBinding.dhcp_agent_id == id).one() + except exc.NoResultFound: + raise dhcpagentscheduler.NetworkNotHostedByDhcpAgent( + network_id=network_id, agent_id=id) - # reserve the port, so the ip is reused on a subsequent add - device_id = utils.get_dhcp_agent_device_id(network_id, - agent['host']) - filters = dict(device_id=[device_id]) - ports = self.get_ports(context, filters=filters) - for port in ports: - port['device_id'] = constants.DEVICE_ID_RESERVED_DHCP_PORT - self.update_port(context, port['id'], dict(port=port)) - # avoid issues with query.one() object that was - # loaded into the session - query.delete(synchronize_session=False) + # reserve the port, so the ip is reused on a subsequent add + device_id = utils.get_dhcp_agent_device_id(network_id, + agent['host']) + filters = dict(device_id=[device_id]) + ports = self.get_ports(context, filters=filters) + # NOTE(kevinbenton): there should only ever be one port per + # DHCP agent per network so we don't have to worry about one + # update_port passing and another failing + for port in ports: + port['device_id'] = constants.DEVICE_ID_RESERVED_DHCP_PORT + self.update_port(context, port['id'], dict(port=port)) + with context.session.begin(): + context.session.delete(binding) if not notify: return