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
This commit is contained in:
Kevin Benton 2016-04-13 05:20:00 -07:00
parent 16346b906e
commit a2ceec2864

View File

@ -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