Update network wrapper to handle neutron plugins router handling

Some plugins (such as Cisco ASR) don't use router ID as the device ID
of the port. Also, some plugins don't allow user to update HA router
interface as it has internal logic to handle that.

This patchset is to catch some exception such that it will not stop
cleanup context to cleanup further resources

Change-Id: Idb1f2922e0310fdeb57cef752d27b7ef11e13865
This commit is contained in:
Kahou Lei 2017-09-01 09:37:09 -07:00 committed by Chris Plock
parent 21a252272f
commit 18be8cf167
2 changed files with 70 additions and 2 deletions

View File

@ -271,8 +271,17 @@ class NeutronWrapper(NetworkWrapper):
"network:router_interface_distributed",
"network:ha_router_replicated_interface",
"network:router_gateway"):
self.client.remove_interface_router(
port["device_id"], {"port_id": port["id"]})
try:
self.client.remove_interface_router(
port["device_id"], {"port_id": port["id"]})
except (neutron_exceptions.BadRequest,
neutron_exceptions.NotFound):
# Some neutron plugins don't use router as
# the device ID. Also, some plugin doesn't allow
# to update the ha rotuer interface as there is
# an internal logic to update the interface/data model
# instead.
pass
else:
try:
self.client.delete_port(port["id"])

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import ddt
import mock
from rally.common import utils
@ -29,6 +30,7 @@ class Owner(utils.RandomNameGeneratorMixin):
task = {"uuid": "task-uuid"}
@ddt.ddt
class NeutronWrapperTestCase(test.TestCase):
def setUp(self):
self.owner = Owner()
@ -287,6 +289,63 @@ class NeutronWrapperTestCase(test.TestCase):
mock_neutron_wrapper_supports_extension.assert_called_once_with(
"dhcp_agent_scheduler")
@ddt.data({"exception_type": neutron_exceptions.NotFound,
"should_raise": False},
{"exception_type": neutron_exceptions.BadRequest,
"should_raise": False},
{"exception_type": KeyError,
"should_raise": True})
@ddt.unpack
@mock.patch("rally.plugins.openstack.wrappers.network.NeutronWrapper"
".supports_extension", return_value=(True, ""))
def test_delete_network_with_router_throw_exception(
self, mock_neutron_wrapper_supports_extension, exception_type,
should_raise):
# Ensure cleanup context still move forward even
# remove_interface_router throw NotFound/BadRequest exception
service = self.get_wrapper()
service.client.remove_interface_router.side_effect = exception_type
agents = ["foo_agent", "bar_agent"]
subnets = ["foo_subnet", "bar_subnet"]
ports = [{"id": "foo_port", "device_owner": "network:router_interface",
"device_id": "rounttter"},
{"id": "bar_port", "device_owner": "network:dhcp"}]
service.client.list_dhcp_agent_hosting_networks.return_value = (
{"agents": [{"id": agent_id} for agent_id in agents]})
service.client.list_ports.return_value = ({"ports": ports})
service.client.delete_network.return_value = "foo_deleted"
if should_raise:
self.assertRaises(exception_type, service.delete_network,
{"id": "foo_id", "router_id": "foo_router",
"subnets": subnets, "lb_pools": []})
self.assertNotEqual(service.client.delete_subnet.mock_calls,
[mock.call(subnet_id) for subnet_id in
subnets])
self.assertFalse(service.client.delete_network.called)
else:
result = service.delete_network(
{"id": "foo_id", "router_id": "foo_router", "subnets": subnets,
"lb_pools": []})
self.assertEqual("foo_deleted", result)
service.client.delete_port.assert_called_once_with(ports[1]["id"])
service.client.remove_interface_router.assert_called_once_with(
ports[0]["device_id"], {"port_id": ports[0]["id"]})
self.assertEqual(service.client.delete_subnet.mock_calls,
[mock.call(subnet_id) for subnet_id in subnets])
service.client.delete_network.assert_called_once_with("foo_id")
self.assertEqual(
service.client.remove_network_from_dhcp_agent.mock_calls,
[mock.call(agent_id, "foo_id") for agent_id in agents])
self.assertEqual(service.client.remove_gateway_router.mock_calls,
[mock.call("foo_router")])
mock_neutron_wrapper_supports_extension.assert_called_once_with(
"dhcp_agent_scheduler")
def test_list_networks(self):
service = self.get_wrapper()
service.client.list_networks.return_value = {"networks": "foo_nets"}