From 2941b0c74a7e2a69e9cf88cea97d6e402476e6a9 Mon Sep 17 00:00:00 2001 From: Richard Theis Date: Mon, 16 Nov 2015 15:35:17 -0600 Subject: [PATCH] Add route options to neutron router-update Add the --route and --no-routes options to neutron router-update. This will make it easier for CLI users to add or remove routes associated with a router. Change-Id: If0e3125420afe3609633cd6c133edaa5a172357d Closes-Bug: #1452229 --- neutronclient/neutron/v2_0/router.py | 14 +++++ neutronclient/tests/unit/test_cli20_router.py | 62 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/neutronclient/neutron/v2_0/router.py b/neutronclient/neutron/v2_0/router.py index 31a2bf7ba..4c9a83c26 100644 --- a/neutronclient/neutron/v2_0/router.py +++ b/neutronclient/neutron/v2_0/router.py @@ -107,6 +107,16 @@ class UpdateRouter(neutronV20.UpdateCommand): parser, '--distributed', dest='distributed', help=_('True means this router should operate in' ' distributed mode.')) + routes_group = parser.add_mutually_exclusive_group() + routes_group.add_argument( + '--route', metavar='destination=CIDR,nexthop=IP_ADDR', + action='append', dest='routes', type=utils.str2dict, + help=_('Route to associate with the router.' + ' You can repeat this option.')) + routes_group.add_argument( + '--no-routes', + action='store_true', + help=_('Remove routes associated with the router.')) def args2body(self, parsed_args): body = {} @@ -114,6 +124,10 @@ class UpdateRouter(neutronV20.UpdateCommand): body['admin_state_up'] = parsed_args.admin_state neutronV20.update_dict(parsed_args, body, ['name', 'distributed']) + if parsed_args.no_routes: + body['routes'] = None + elif parsed_args.routes: + body['routes'] = parsed_args.routes return {self.resource: body} diff --git a/neutronclient/tests/unit/test_cli20_router.py b/neutronclient/tests/unit/test_cli20_router.py index d83cb6906..60ee733bd 100644 --- a/neutronclient/tests/unit/test_cli20_router.py +++ b/neutronclient/tests/unit/test_cli20_router.py @@ -196,6 +196,68 @@ class CLITestV20RouterJSON(test_cli20.CLITestV20Base): {'distributed': 'false'} ) + def test_update_router_no_routes(self): + """Update router: myid --no-routes""" + resource = 'router' + cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) + self._test_update_resource(resource, cmd, 'myid', + ['myid', '--no-routes'], + {'routes': None}) + + def test_update_router_add_route(self): + """Update router: myid + --route destination=10.0.3.0/24,nexthop=10.0.0.10 + """ + resource = 'router' + cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) + myid = 'myid' + args = [myid, + '--route', + 'destination=10.0.3.0/24,nexthop=10.0.0.10'] + routes = [{'destination': '10.0.3.0/24', + 'nexthop': '10.0.0.10'}] + updatefields = {'routes': routes} + self._test_update_resource(resource, cmd, myid, args, updatefields) + + def test_update_router_add_routes(self): + """Update router: myid + --route destination=10.0.3.0/24,nexthop=10.0.0.10 + --route destination=fd7a:1d63:2063::/64, + nexthop=fd7a:1d63:2063:0:f816:3eff:fe0e:a697 + """ + resource = 'router' + cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) + myid = 'myid' + args = [myid, + '--route', + 'destination=10.0.3.0/24,nexthop=10.0.0.10', + '--route', + 'destination=fd7a:1d63:2063::/64,' + 'nexthop=fd7a:1d63:2063:0:f816:3eff:fe0e:a697'] + routes = [{'destination': '10.0.3.0/24', + 'nexthop': '10.0.0.10'}, + {'destination': 'fd7a:1d63:2063::/64', + 'nexthop': 'fd7a:1d63:2063:0:f816:3eff:fe0e:a697'}] + updatefields = {'routes': routes} + self._test_update_resource(resource, cmd, myid, args, updatefields) + + def test_update_router_no_routes_with_add_route(self): + """Update router: --no-routes with --route""" + resource = 'router' + cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) + myid = 'myid' + args = [myid, + '--no-routes', + '--route', + 'destination=10.0.3.0/24,nexthop=10.0.0.10'] + actual_error_code = 0 + try: + self._test_update_resource(resource, cmd, myid, args, None) + except SystemExit: + exc_type, exc_value, exc_traceback = sys.exc_info() + actual_error_code = exc_value.code + self.assertEqual(2, actual_error_code) + def test_delete_router(self): """Delete router: myid.""" resource = 'router'