From 1ddc618d2d75f7f773063a77cb8925ad02a151b7 Mon Sep 17 00:00:00 2001 From: Ryan Brady Date: Fri, 6 Jul 2018 09:42:46 -0400 Subject: [PATCH] Add support for static routes The networking API v2 specification, which is implemented by OpenStack Neutron, features an optional routes parameter - when updating a router PUT requests). Static routes are crucial for routers to handle traffic from subnets not directly connected to a router. This patch adds the routes parameter to the OpenStackCloud.update_router method as a list of dictionaries with destination and nexthop parameters. Example: [ { "destination": "179.24.1.0/24", "nexthop": "172.24.3.99" } ] Change-Id: I14205b6bb071d0b46967f29b6287f74d8796add8 --- ...etting-static-routes-b3ce6cac2c5e9e51.yaml | 9 +++++++ shade/openstackcloud.py | 18 ++++++++++++- shade/tests/functional/test_router.py | 25 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/add-support-for-setting-static-routes-b3ce6cac2c5e9e51.yaml diff --git a/releasenotes/notes/add-support-for-setting-static-routes-b3ce6cac2c5e9e51.yaml b/releasenotes/notes/add-support-for-setting-static-routes-b3ce6cac2c5e9e51.yaml new file mode 100644 index 000000000..0b7c577dd --- /dev/null +++ b/releasenotes/notes/add-support-for-setting-static-routes-b3ce6cac2c5e9e51.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + The networking API v2 specification, which is implemented by OpenStack + Neutron, features an optional routes parameter - when updating a router + (PUT requests). Static routes are crucial for routers to handle traffic + from subnets not directly connected to a router. The routes parameter has + now been added to the OpenStackCloud.update_router method as a list of + dictionaries with destination and nexthop parameters. diff --git a/shade/openstackcloud.py b/shade/openstackcloud.py index 59fcd50cf..8faa29965 100644 --- a/shade/openstackcloud.py +++ b/shade/openstackcloud.py @@ -4393,7 +4393,7 @@ class OpenStackCloud( def update_router(self, name_or_id, name=None, admin_state_up=None, ext_gateway_net_id=None, enable_snat=None, - ext_fixed_ips=None): + ext_fixed_ips=None, routes=None): """Update an existing logical router. :param string name_or_id: The name or UUID of the router to update. @@ -4412,7 +4412,16 @@ class OpenStackCloud( "ip_address": "192.168.10.2" } ] + :param list routes: + A list of dictionaries with destination and nexthop parameters. + Example:: + [ + { + "destination": "179.24.1.0/24", + "nexthop": "172.24.3.99" + } + ] :returns: The router object. :raises: OpenStackCloudException on operation error. """ @@ -4427,6 +4436,13 @@ class OpenStackCloud( if ext_gw_info: router['external_gateway_info'] = ext_gw_info + if routes: + if self._has_neutron_extension('extraroute'): + router['routes'] = routes + else: + self.log.warn( + 'extra routes extension is not available on target cloud') + if not router: self.log.debug("No router data to update") return diff --git a/shade/tests/functional/test_router.py b/shade/tests/functional/test_router.py index 5c4ccde46..b46710604 100644 --- a/shade/tests/functional/test_router.py +++ b/shade/tests/functional/test_router.py @@ -276,6 +276,31 @@ class TestRouter(base.BaseFunctionalTestCase): self.assertEqual(router['external_gateway_info'], updated['external_gateway_info']) + def test_update_router_routes(self): + router = self._create_and_verify_advanced_router( + external_cidr=u'10.7.7.0/24') + + routes = [{ + "destination": "10.7.7.0/24", + "nexthop": "10.7.7.99" + }] + + updated = self.operator_cloud.update_router( + router['id'], routes=routes) + self.assertIsNotNone(updated) + + for field in EXPECTED_TOPLEVEL_FIELDS: + self.assertIn(field, updated) + + # Name is the only change we expect + self.assertEqual(routes, updated['routes']) + + # Validate nothing else changed + self.assertEqual(router['status'], updated['status']) + self.assertEqual(router['admin_state_up'], updated['admin_state_up']) + self.assertEqual(router['external_gateway_info'], + updated['external_gateway_info']) + def test_update_router_admin_state(self): router = self._create_and_verify_advanced_router( external_cidr=u'10.8.8.0/24')