NSX|V: Fix error handling for distributed router interface

1. No need to rollback the interface creation in teh distributed router
driver. It is rolled back on the plugin level. the Double rollback causes
a new error to be raised.
2. In the plugin level - do not alert on the rollback faliure.
It may be legit
2. In the plugin level raise a proper error to neutron, instead of the
internal one.

Change-Id: I129f595d6cd17cd0af62fc9e2855451b97e73ff0
This commit is contained in:
asarfaty 2019-11-13 11:21:49 +02:00 committed by Adit Sarfaty
parent 85a475a8dc
commit 5e7f8dad6d
2 changed files with 34 additions and 39 deletions

View File

@ -14,7 +14,6 @@
import netaddr import netaddr
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import excutils
from neutron.db import l3_db from neutron.db import l3_db
@ -265,41 +264,32 @@ class RouterDistributedDriver(router_driver.RouterBaseDriver):
address_groups = self.plugin._get_address_groups( address_groups = self.plugin._get_address_groups(
context, router_id, network_id) context, router_id, network_id)
edge_id = self._get_edge_id(context, router_id) edge_id = self._get_edge_id(context, router_id)
interface_created = False with locking.LockManager.get_lock(str(edge_id)):
try: edge_utils.add_vdr_internal_interface(self.nsx_v, context,
with locking.LockManager.get_lock(str(edge_id)): router_id, network_id,
edge_utils.add_vdr_internal_interface(self.nsx_v, context, address_groups,
router_id, network_id, router_db.admin_state_up)
address_groups, # Update edge's firewall rules to accept subnets flows.
router_db.admin_state_up) self.plugin._update_subnets_and_dnat_firewall(context,
interface_created = True router_db)
# Update edge's firewall rules to accept subnets flows.
self.plugin._update_subnets_and_dnat_firewall(context,
router_db)
if router_db.gw_port: if router_db.gw_port:
plr_id = self.edge_manager.get_plr_by_tlr_id(context, plr_id = self.edge_manager.get_plr_by_tlr_id(context,
router_id) router_id)
if router_db.enable_snat: if router_db.enable_snat:
self.plugin._update_nat_rules(context, self.plugin._update_nat_rules(context,
router_db, plr_id) router_db, plr_id)
# Open firewall flows on plr # Open firewall flows on plr
self.plugin._update_subnets_and_dnat_firewall( self.plugin._update_subnets_and_dnat_firewall(
context, router_db, router_id=plr_id) context, router_db, router_id=plr_id)
# Update static routes of plr # Update static routes of plr
nexthop = self.plugin._get_external_attachment_info( nexthop = self.plugin._get_external_attachment_info(
context, router_db)[2] context, router_db)[2]
self._update_routes(context, router_id, self._update_routes(context, router_id,
nexthop) nexthop)
# In case of failure, rollbak will be done in teh plugin level
except Exception:
with excutils.save_and_reraise_exception():
if not interface_created:
super(nsx_v.NsxVPluginV2,
self.plugin).remove_router_interface(
context, router_id, interface_info)
return info return info
def remove_router_interface(self, context, router_id, interface_info): def remove_router_interface(self, context, router_id, interface_info):

View File

@ -4098,14 +4098,19 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
try: try:
return router_driver.add_router_interface( return router_driver.add_router_interface(
context, router_id, interface_info) context, router_id, interface_info)
except vsh_exc.VcnsApiException: except vsh_exc.VcnsApiException as e:
with excutils.save_and_reraise_exception(): LOG.error("Failed to add interface_info %(info)s on "
LOG.error("Failed to add interface_info %(info)s on " "router %(router_id)s: %(e)s",
"router %(router_id)s", {'info': str(interface_info),
{'info': str(interface_info), 'router_id': router_id,
'router_id': router_id}) 'e': e.message})
try:
router_driver.remove_router_interface( router_driver.remove_router_interface(
context, router_id, interface_info) context, router_id, interface_info)
except Exception:
# Rollback may fail if creation failed too early
pass
raise nsx_exc.NsxPluginException(err_msg=e.message)
def remove_router_interface(self, context, router_id, interface_info): def remove_router_interface(self, context, router_id, interface_info):
# Get the router interface port id # Get the router interface port id