diff options
| author | Dan Wendlandt <dan@nicira.com> | 2012-08-21 01:54:17 -0700 |
|---|---|---|
| committer | Gary Kotton <gkotton@redhat.com> | 2012-08-22 06:14:51 -0400 |
| commit | 38abece8a6a82c722b00d8ea46997aacecb463a5 (patch) | |
| tree | 8e8a8ecda33fa32346dac9ccd4f55e0b74a16ae2 | |
| parent | f574f77731ed3ee2123c2b8f8572c50e30810c43 (diff) | |
| download | python-neutronclient-38abece8a6a82c722b00d8ea46997aacecb463a5.tar.gz | |
initial client + CLI support for routers + floating ips
bp quantum-client-l3-floating-ip
The task also does the following:
1. Fixes alignment of the --help output
2. Ensures that a show command prints a dictionary correctly
Change-Id: Ib61b3e8748a7bd476ec008ab6ce20ab852e92f58
| -rw-r--r-- | quantumclient/quantum/v2_0/__init__.py | 3 | ||||
| -rw-r--r-- | quantumclient/quantum/v2_0/floatingip.py | 133 | ||||
| -rw-r--r-- | quantumclient/quantum/v2_0/router.py | 186 | ||||
| -rw-r--r-- | quantumclient/shell.py | 32 | ||||
| -rw-r--r-- | quantumclient/tests/unit/test_cli20.py | 24 | ||||
| -rw-r--r-- | quantumclient/tests/unit/test_cli20_floatingips.py | 96 | ||||
| -rw-r--r-- | quantumclient/tests/unit/test_cli20_router.py | 151 | ||||
| -rw-r--r-- | quantumclient/v2_0/client.py | 108 |
8 files changed, 731 insertions, 2 deletions
diff --git a/quantumclient/quantum/v2_0/__init__.py b/quantumclient/quantum/v2_0/__init__.py index 78c5339..f2a458c 100644 --- a/quantumclient/quantum/v2_0/__init__.py +++ b/quantumclient/quantum/v2_0/__init__.py @@ -412,6 +412,9 @@ class ShowCommand(QuantumCommand, show.ShowOne): else: value += str(_item) data[self.resource][k] = value + elif isinstance(v, dict): + value = utils.dumps(v) + data[self.resource][k] = value elif v is None: data[self.resource][k] = '' return zip(*sorted(data[self.resource].iteritems())) diff --git a/quantumclient/quantum/v2_0/floatingip.py b/quantumclient/quantum/v2_0/floatingip.py new file mode 100644 index 0000000..cd1437e --- /dev/null +++ b/quantumclient/quantum/v2_0/floatingip.py @@ -0,0 +1,133 @@ +# Copyright 2012 OpenStack LLC. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import logging + +from quantumclient.quantum.v2_0 import CreateCommand +from quantumclient.quantum.v2_0 import DeleteCommand +from quantumclient.quantum.v2_0 import ListCommand +from quantumclient.quantum.v2_0 import QuantumCommand +from quantumclient.quantum.v2_0 import ShowCommand + + +class ListFloatingIP(ListCommand): + """List floating ips that belong to a given tenant.""" + + resource = 'floatingip' + log = logging.getLogger(__name__ + '.ListFloatingIP') + _formatters = {} + + +class ShowFloatingIP(ShowCommand): + """Show information of a given floating ip.""" + + resource = 'floatingip' + log = logging.getLogger(__name__ + '.ShowFloatingIP') + + +class CreateFloatingIP(CreateCommand): + """Create a floating ip for a given tenant.""" + + resource = 'floatingip' + log = logging.getLogger(__name__ + '.CreateFloatingIP') + + def add_known_arguments(self, parser): + parser.add_argument( + 'floating_network_id', + help='Network to allocate floating IP from') + parser.add_argument( + '--port_id', + help='ID of the port to be associated with the floatingip') + parser.add_argument( + '--fixed_ip_address', + help=('IP address on the port (only required if port has multiple' + 'IPs)')) + + def args2body(self, parsed_args): + body = {'floatingip': { + 'floating_network_id': parsed_args.floating_network_id}} + if parsed_args.tenant_id: + body['floatingip'].update({'tenant_id': parsed_args.tenant_id}) + return body + + +class DeleteFloatingIP(DeleteCommand): + """Delete a given floating ip.""" + + log = logging.getLogger(__name__ + '.DeleteFloatingIP') + resource = 'floatingip' + + +class AssociateFloatingIP(QuantumCommand): + """Create a mapping between a floating ip and a fixed ip.""" + + api = 'network' + log = logging.getLogger(__name__ + '.AssociateFloatingIP') + resource = 'floatingip' + + def get_parser(self, prog_name): + parser = super(AssociateFloatingIP, self).get_parser(prog_name) + parser.add_argument( + 'floatingip_id', metavar='floatingip_id', + help='IP address of the floating IP to associate') + parser.add_argument( + 'port_id', + help='ID of the port to be associated with the floatingip') + parser.add_argument( + '--fixed_ip_address', + help=('IP address on the port (only required if port has multiple' + 'IPs)')) + return parser + + def run(self, parsed_args): + self.log.debug('run(%s)' % parsed_args) + quantum_client = self.get_client() + quantum_client.format = parsed_args.request_format + update_dict = {} + if parsed_args.port_id: + update_dict['port_id'] = parsed_args.port_id + if parsed_args.fixed_ip_address: + update_dict['fixed_ip_address'] = parsed_args.fixed_ip_address + quantum_client.update_floatingip(parsed_args.floatingip_id, + {'floatingip': update_dict}) + print >>self.app.stdout, ( + _('Associated floatingip %s') % parsed_args.floatingip_id) + + +class DisassociateFloatingIP(QuantumCommand): + """Remove a mapping from a floating ip to a fixed ip. + """ + + api = 'network' + log = logging.getLogger(__name__ + '.DisassociateFloatingIP') + resource = 'floatingip' + + def get_parser(self, prog_name): + parser = super(DisassociateFloatingIP, self).get_parser(prog_name) + parser.add_argument( + 'floatingip_id', metavar='floatingip_id', + help='IP address of the floating IP to associate') + return parser + + def run(self, parsed_args): + self.log.debug('run(%s)' % parsed_args) + quantum_client = self.get_client() + quantum_client.format = parsed_args.request_format + quantum_client.update_floatingip(parsed_args.floatingip_id, + {'floatingip': {'port_id': None}}) + print >>self.app.stdout, ( + _('Disassociated floatingip %s') % parsed_args.floatingip_id) diff --git a/quantumclient/quantum/v2_0/router.py b/quantumclient/quantum/v2_0/router.py new file mode 100644 index 0000000..06afa34 --- /dev/null +++ b/quantumclient/quantum/v2_0/router.py @@ -0,0 +1,186 @@ +# Copyright 2012 OpenStack LLC. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import logging + +from quantumclient.common import utils +from quantumclient.quantum.v2_0 import CreateCommand +from quantumclient.quantum.v2_0 import DeleteCommand +from quantumclient.quantum.v2_0 import ListCommand +from quantumclient.quantum.v2_0 import QuantumCommand +from quantumclient.quantum.v2_0 import ShowCommand +from quantumclient.quantum.v2_0 import UpdateCommand + + +def _format_external_gateway_info(router): + try: + return utils.dumps(router['external_gateway_info']) + except Exception: + return '' + + +class ListRouter(ListCommand): + """List routers that belong to a given tenant.""" + + resource = 'router' + log = logging.getLogger(__name__ + '.ListRouter') + _formatters = {'external_gateway_info': _format_external_gateway_info, } + + +class ShowRouter(ShowCommand): + """Show information of a given router.""" + + resource = 'router' + log = logging.getLogger(__name__ + '.ShowRouter') + + +class CreateRouter(CreateCommand): + """Create a router for a given tenant.""" + + resource = 'router' + log = logging.getLogger(__name__ + '.CreateRouter') + + def add_known_arguments(self, parser): + parser.add_argument( + '--admin_state_down', + default=True, action='store_false', + help='Set Admin State Up to false') + parser.add_argument( + 'name', metavar='name', + help='Name of router to create') + + def args2body(self, parsed_args): + body = {'router': { + 'name': parsed_args.name, + 'admin_state_up': parsed_args.admin_state_down, }, } + if parsed_args.tenant_id: + body['router'].update({'tenant_id': parsed_args.tenant_id}) + return body + + +class DeleteRouter(DeleteCommand): + """Delete a given router.""" + + log = logging.getLogger(__name__ + '.DeleteRouter') + resource = 'router' + + +class UpdateRouter(UpdateCommand): + """Update router's information.""" + + log = logging.getLogger(__name__ + '.UpdateRouter') + resource = 'router' + + +class RouterInterfaceCommand(QuantumCommand): + """Based class to Add/Remove router interface.""" + + api = 'network' + log = logging.getLogger(__name__ + '.AddInterfaceRouter') + resource = 'router' + + def get_parser(self, prog_name): + parser = super(RouterInterfaceCommand, self).get_parser(prog_name) + parser.add_argument( + 'router_id', metavar='router_id', + help='ID of the router') + parser.add_argument( + 'subnet_id', metavar='subnet_id', + help='ID of the internal subnet for the interface') + return parser + + +class AddInterfaceRouter(RouterInterfaceCommand): + """Add an internal network interface to a router.""" + + def run(self, parsed_args): + self.log.debug('run(%s)' % parsed_args) + quantum_client = self.get_client() + quantum_client.format = parsed_args.request_format + #TODO(danwent): handle passing in port-id + quantum_client.add_interface_router(parsed_args.router_id, + {'subnet_id': + parsed_args.subnet_id}) + #TODO(danwent): print port ID that is added + print >>self.app.stdout, ( + _('Added interface to router %s') % parsed_args.router_id) + + +class RemoveInterfaceRouter(RouterInterfaceCommand): + """Remove an internal network interface from a router.""" + + def run(self, parsed_args): + self.log.debug('run(%s)' % parsed_args) + quantum_client = self.get_client() + quantum_client.format = parsed_args.request_format + #TODO(danwent): handle passing in port-id + quantum_client.remove_interface_router(parsed_args.router_id, + {'subnet_id': + parsed_args.subnet_id}) + print >>self.app.stdout, ( + _('Removed interface from router %s') % parsed_args.router_id) + + +class SetGatewayRouter(QuantumCommand): + """Set the external network gateway for a router.""" + + log = logging.getLogger(__name__ + '.SetGatewayRouter') + api = 'network' + resource = 'router' + + def get_parser(self, prog_name): + parser = super(SetGatewayRouter, self).get_parser(prog_name) + parser.add_argument( + 'router_id', metavar='router_id', + help='ID of the router') + parser.add_argument( + 'external_network_id', metavar='external_network_id', + help='ID of the external network for the gateway') + return parser + + def run(self, parsed_args): + self.log.debug('run(%s)' % parsed_args) + quantum_client = self.get_client() + quantum_client.format = parsed_args.request_format + quantum_client.add_gateway_router(parsed_args.router_id, + {'network_id': + parsed_args.external_network_id}) + print >>self.app.stdout, ( + _('Set gateway for router %s') % parsed_args.router_id) + + +class RemoveGatewayRouter(QuantumCommand): + """Remove an external network gateway from a router.""" + + log = logging.getLogger(__name__ + '.RemoveGatewayRouter') + api = 'network' + resource = 'router' + + def get_parser(self, prog_name): + parser = super(RemoveGatewayRouter, self).get_parser(prog_name) + parser.add_argument( + 'router_id', metavar='router_id', + help='ID of the router') + return parser + + def run(self, parsed_args): + self.log.debug('run(%s)' % parsed_args) + quantum_client = self.get_client() + quantum_client.format = parsed_args.request_format + quantum_client.remove_gateway_router(parsed_args.router_id) + print >>self.app.stdout, ( + _('Removed gateway from router %s') % parsed_args.router_id) diff --git a/quantumclient/shell.py b/quantumclient/shell.py index 952f56f..5ccc1c7 100644 --- a/quantumclient/shell.py +++ b/quantumclient/shell.py @@ -95,6 +95,36 @@ COMMAND_V2 = { 'quantumclient.quantum.v2_0.extension.ListExt'), 'ext-show': utils.import_class( 'quantumclient.quantum.v2_0.extension.ShowExt'), + 'router-list': utils.import_class( + 'quantumclient.quantum.v2_0.router.ListRouter'), + 'router-show': utils.import_class( + 'quantumclient.quantum.v2_0.router.ShowRouter'), + 'router-create': utils.import_class( + 'quantumclient.quantum.v2_0.router.CreateRouter'), + 'router-delete': utils.import_class( + 'quantumclient.quantum.v2_0.router.DeleteRouter'), + 'router-update': utils.import_class( + 'quantumclient.quantum.v2_0.router.UpdateRouter'), + 'router-interface-add': utils.import_class( + 'quantumclient.quantum.v2_0.router.AddInterfaceRouter'), + 'router-interface-delete': utils.import_class( + 'quantumclient.quantum.v2_0.router.RemoveInterfaceRouter'), + 'router-gateway-set': utils.import_class( + 'quantumclient.quantum.v2_0.router.SetGatewayRouter'), + 'router-gateway-clear': utils.import_class( + 'quantumclient.quantum.v2_0.router.RemoveGatewayRouter'), + 'floatingip-list': utils.import_class( + 'quantumclient.quantum.v2_0.floatingip.ListFloatingIP'), + 'floatingip-show': utils.import_class( + 'quantumclient.quantum.v2_0.floatingip.ShowFloatingIP'), + 'floatingip-create': utils.import_class( + 'quantumclient.quantum.v2_0.floatingip.CreateFloatingIP'), + 'floatingip-delete': utils.import_class( + 'quantumclient.quantum.v2_0.floatingip.DeleteFloatingIP'), + 'floatingip-associate': utils.import_class( + 'quantumclient.quantum.v2_0.floatingip.AssociateFloatingIP'), + 'floatingip-disassociate': utils.import_class( + 'quantumclient.quantum.v2_0.floatingip.DisassociateFloatingIP'), } COMMANDS = {'2.0': COMMAND_V2} @@ -116,7 +146,7 @@ class HelpAction(argparse.Action): factory = ep.load() cmd = factory(self, None) one_liner = cmd.get_description().split('\n')[0] - app.stdout.write(' %-13s %s\n' % (name, one_liner)) + app.stdout.write(' %-25s %s\n' % (name, one_liner)) sys.exit(0) diff --git a/quantumclient/tests/unit/test_cli20.py b/quantumclient/tests/unit/test_cli20.py index 3737061..6ed0afc 100644 --- a/quantumclient/tests/unit/test_cli20.py +++ b/quantumclient/tests/unit/test_cli20.py @@ -140,7 +140,7 @@ class CLITestV20Base(unittest.TestCase): self.mox.StubOutWithMock(cmd, "get_client") self.mox.StubOutWithMock(self.client.httpclient, "request") cmd.get_client().MultipleTimes().AndReturn(self.client) - if resource == 'subnet': + if (resource == 'subnet' or resource == 'floatingip'): body = {resource: {}, } else: body = {resource: {'admin_state_up': admin_state_up, }, } @@ -293,3 +293,25 @@ class CLITestV20Base(unittest.TestCase): self.mox.UnsetStubs() _str = self.fake_stdout.make_string() self.assertTrue(myid in _str) + + def _test_update_resource_action(self, resource, cmd, myid, action, args, + body): + self.mox.StubOutWithMock(cmd, "get_client") + self.mox.StubOutWithMock(self.client.httpclient, "request") + cmd.get_client().MultipleTimes().AndReturn(self.client) + path = getattr(self.client, resource + "_path") + path_action = '%s/%s' % (myid, action) + self.client.httpclient.request( + end_url(path % path_action), 'PUT', + body=MyComparator(body, self.client), + headers=ContainsKeyValue('X-Auth-Token', + TOKEN)).AndReturn((MyResp(204), None)) + self.mox.ReplayAll() + cmd_parser = cmd.get_parser("update_" + resource) + + parsed_args = cmd_parser.parse_args(args) + cmd.run(parsed_args) + self.mox.VerifyAll() + self.mox.UnsetStubs() + _str = self.fake_stdout.make_string() + self.assertTrue(myid in _str) diff --git a/quantumclient/tests/unit/test_cli20_floatingips.py b/quantumclient/tests/unit/test_cli20_floatingips.py new file mode 100644 index 0000000..f9b63df --- /dev/null +++ b/quantumclient/tests/unit/test_cli20_floatingips.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 Red Hat +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import sys + +from quantumclient.common import exceptions +from quantumclient.quantum.v2_0.floatingip import AssociateFloatingIP +from quantumclient.quantum.v2_0.floatingip import CreateFloatingIP +from quantumclient.quantum.v2_0.floatingip import DeleteFloatingIP +from quantumclient.quantum.v2_0.floatingip import DisassociateFloatingIP +from quantumclient.quantum.v2_0.floatingip import ListFloatingIP +from quantumclient.quantum.v2_0.floatingip import ShowFloatingIP +from quantumclient.tests.unit.test_cli20 import CLITestV20Base +from quantumclient.tests.unit.test_cli20 import MyApp + + +class CLITestV20FloatingIps(CLITestV20Base): + def test_create_floatingip(self): + """Create floatingip: fip1.""" + resource = 'floatingip' + cmd = CreateFloatingIP(MyApp(sys.stdout), None) + name = 'fip1' + myid = 'myid' + args = [name] + position_names = ['floating_network_id'] + position_values = [name] + _str = self._test_create_resource(resource, cmd, name, myid, args, + position_names, position_values) + + def test_create_floatingip_and_port(self): + """Create floatingip: fip1.""" + resource = 'floatingip' + cmd = CreateFloatingIP(MyApp(sys.stdout), None) + name = 'fip1' + myid = 'myid' + pid = 'mypid' + args = [name, '--port_id', pid] + position_names = ['floating_network_id', 'port_id'] + position_values = [name, pid] + _str = self._test_create_resource(resource, cmd, name, myid, args, + position_names, position_values) + + def test_list_floatingips(self): + """list floatingips: -D.""" + resources = 'floatingips' + cmd = ListFloatingIP(MyApp(sys.stdout), None) + self._test_list_resources(resources, cmd, True) + + def test_delete_floatingip(self): + """Delete floatingip: fip1""" + resource = 'floatingip' + cmd = DeleteFloatingIP(MyApp(sys.stdout), None) + myid = 'myid' + args = [myid] + self._test_delete_resource(resource, cmd, myid, args) + + def test_show_floatingip(self): + """Show floatingip: --fields id.""" + resource = 'floatingip' + cmd = ShowFloatingIP(MyApp(sys.stdout), None) + args = ['--fields', 'id', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, + args, ['id']) + + def test_disassociate_ip(self): + """Disassociate floating IP: myid""" + resource = 'floatingip' + cmd = DisassociateFloatingIP(MyApp(sys.stdout), None) + args = ['myid'] + self._test_update_resource(resource, cmd, 'myid', + args, {"port_id": None} + ) + + def test_associate_ip(self): + """Associate floating IP: myid portid""" + resource = 'floatingip' + cmd = AssociateFloatingIP(MyApp(sys.stdout), None) + args = ['myid', 'portid'] + self._test_update_resource(resource, cmd, 'myid', + args, {"port_id": "portid"} + ) diff --git a/quantumclient/tests/unit/test_cli20_router.py b/quantumclient/tests/unit/test_cli20_router.py new file mode 100644 index 0000000..502365d --- /dev/null +++ b/quantumclient/tests/unit/test_cli20_router.py @@ -0,0 +1,151 @@ +# Copyright 2012 Nicira, Inc +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +import sys + +from quantumclient.common import exceptions +from quantumclient.quantum.v2_0.router import AddInterfaceRouter +from quantumclient.quantum.v2_0.router import CreateRouter +from quantumclient.quantum.v2_0.router import DeleteRouter +from quantumclient.quantum.v2_0.router import ListRouter +from quantumclient.quantum.v2_0.router import RemoveGatewayRouter +from quantumclient.quantum.v2_0.router import RemoveInterfaceRouter +from quantumclient.quantum.v2_0.router import SetGatewayRouter +from quantumclient.quantum.v2_0.router import ShowRouter +from quantumclient.quantum.v2_0.router import UpdateRouter +from quantumclient.tests.unit.test_cli20 import CLITestV20Base +from quantumclient.tests.unit.test_cli20 import MyApp + + +class CLITestV20Router(CLITestV20Base): + def test_create_router(self): + """Create router: router1.""" + resource = 'router' + cmd = CreateRouter(MyApp(sys.stdout), None) + name = 'router1' + myid = 'myid' + args = [name, ] + position_names = ['name', ] + position_values = [name, ] + _str = self._test_create_resource(resource, cmd, name, myid, args, + position_names, position_values) + + def test_create_router_tenant(self): + """Create router: --tenant_id tenantid myname.""" + resource = 'router' + cmd = CreateRouter(MyApp(sys.stdout), None) + name = 'myname' + myid = 'myid' + args = ['--tenant_id', 'tenantid', name] + position_names = ['name', ] + position_values = [name, ] + _str = self._test_create_resource(resource, cmd, name, myid, args, + position_names, position_values, + tenant_id='tenantid') + + def test_create_router_admin_state(self): + """Create router: --admin_state_down myname.""" + resource = 'router' + cmd = CreateRouter(MyApp(sys.stdout), None) + name = 'myname' + myid = 'myid' + args = ['--admin_state_down', name, ] + position_names = ['name', ] + position_values = [name, ] + _str = self._test_create_resource(resource, cmd, name, myid, args, + position_names, position_values, + admin_state_up=False) + + def test_list_routers_detail(self): + """list routers: -D.""" + resources = "routers" + cmd = ListRouter(MyApp(sys.stdout), None) + self._test_list_resources(resources, cmd, True) + + def test_update_router_exception(self): + """Update router: myid.""" + resource = 'router' + cmd = UpdateRouter(MyApp(sys.stdout), None) + self.assertRaises(exceptions.CommandError, self._test_update_resource, + resource, cmd, 'myid', ['myid'], {}) + + def test_update_router(self): + """Update router: myid --name myname --tags a b.""" + resource = 'router' + cmd = UpdateRouter(MyApp(sys.stdout), None) + self._test_update_resource(resource, cmd, 'myid', + ['myid', '--name', 'myname'], + {'name': 'myname'} + ) + + def test_delete_router(self): + """Delete router: myid.""" + resource = 'router' + cmd = DeleteRouter(MyApp(sys.stdout), None) + myid = 'myid' + args = [myid] + self._test_delete_resource(resource, cmd, myid, args) + + def test_show_router(self): + """Show router: myid.""" + resource = 'router' + cmd = ShowRouter(MyApp(sys.stdout), None) + args = ['--fields', 'id', '--fields', 'name', self.test_id] + self._test_show_resource(resource, cmd, self.test_id, args, + ['id', 'name']) + + def test_add_interface(self): + """Add interface to router: myid subnetid""" + resource = 'router' + cmd = AddInterfaceRouter(MyApp(sys.stdout), None) + args = ['myid', 'subnetid'] + self._test_update_resource_action(resource, cmd, 'myid', + 'add_router_interface', + args, + {'subnet_id': 'subnetid'} + ) + + def test_del_interface(self): + """Delete interface from router: myid subnetid""" + resource = 'router' + cmd = RemoveInterfaceRouter(MyApp(sys.stdout), None) + args = ['myid', 'subnetid'] + self._test_update_resource_action(resource, cmd, 'myid', + 'remove_router_interface', + args, + {'subnet_id': 'subnetid'} + ) + + def test_set_gateway(self): + """Set external gateway for router: myid externalid""" + resource = 'router' + cmd = SetGatewayRouter(MyApp(sys.stdout), None) + args = ['myid', 'externalid'] + self._test_update_resource(resource, cmd, 'myid', + args, + {"external_gateway_info": + {"network_id": "externalid"}} + ) + + def test_remove_gateway(self): + """Remove external gateway from router: externalid""" + resource = 'router' + cmd = RemoveGatewayRouter(MyApp(sys.stdout), None) + args = ['externalid'] + self._test_update_resource(resource, cmd, 'externalid', + args, {"external_gateway_info": {}} + ) diff --git a/quantumclient/v2_0/client.py b/quantumclient/v2_0/client.py index 23766da..09712c9 100644 --- a/quantumclient/v2_0/client.py +++ b/quantumclient/v2_0/client.py @@ -158,6 +158,10 @@ class Client(object): quota_path = "/quotas/%s" exts_path = "/extensions" ext_path = "/extensions/%s" + routers_path = "/routers" + router_path = "/routers/%s" + floatingips_path = "/floatingips" + floatingip_path = "/floatingips/%s" @APIParamsCall def get_quotas_tenant(self, **_params): @@ -302,6 +306,110 @@ class Client(object): """ return self.delete(self.subnet_path % (subnet)) + @APIParamsCall + def list_routers(self, **_params): + """ + Fetches a list of all routers for a tenant + """ + # Pass filters in "params" argument to do_request + return self.get(self.routers_path, params=_params) + + @APIParamsCall + def show_router(self, router, **_params): + """ + Fetches information of a certain router + """ + return self.get(self.router_path % (router), params=_params) + + @APIParamsCall + def create_router(self, body=None): + """ + Creates a new router + """ + return self.post(self.routers_path, body=body) + + @APIParamsCall + def update_router(self, router, body=None): + """ + Updates a router + """ + return self.put(self.router_path % (router), body=body) + + @APIParamsCall + def delete_router(self, router): + """ + Deletes the specified router + """ + return self.delete(self.router_path % (router)) + + @APIParamsCall + def add_interface_router(self, router, body=None): + """ + Adds an internal network interface to the specified router + """ + return self.put((self.router_path % router) + "/add_router_interface", + body=body) + + @APIParamsCall + def remove_interface_router(self, router, body=None): + """ + Removes an internal network interface from the specified router + """ + return self.put((self.router_path % router) + + "/remove_router_interface", body=body) + + @APIParamsCall + def add_gateway_router(self, router, body=None): + """ + Adds an external network gateway to the specified router + """ + return self.put((self.router_path % router), + body={'router': {'external_gateway_info': body}}) + + @APIParamsCall + def remove_gateway_router(self, router): + """ + Removes an external network gateway from the specified router + """ + return self.put((self.router_path % router), + body={'router': {'external_gateway_info': {}}}) + + @APIParamsCall + def list_floatingips(self, **_params): + """ + Fetches a list of all floatingips for a tenant + """ + # Pass filters in "params" argument to do_request + return self.get(self.floatingips_path, params=_params) + + @APIParamsCall + def show_floatingip(self, floatingip, **_params): + """ + Fetches information of a certain floatingip + """ + return self.get(self.floatingip_path % (floatingip), params=_params) + + @APIParamsCall + def create_floatingip(self, body=None): + """ + Creates a new floatingip + """ + return self.post(self.floatingips_path, body=body) + + @APIParamsCall + def update_floatingip(self, floatingip, body=None): + """ + Updates a floatingip + """ + return self.put(self.floatingip_path % (floatingip), body=body) + + @APIParamsCall + def delete_floatingip(self, floatingip): + """ + Deletes the specified floatingip + """ + return self.delete(self.floatingip_path % (floatingip)) + def __init__(self, **kwargs): """ Initialize a new client for the Quantum v2.0 API. """ super(Client, self).__init__() |
