Skip to content
This repository was archived by the owner on Nov 29, 2023. It is now read-only.

Commit eb7a744

Browse files
author
ivan-zhu
committed
Convenience cmds for l3
Bug #1049551 Add two CLI and unit tests: quantum net-external-list (runs net-list with router:external=True filter) quantum router-port-list <router-id/name> (runs port-list, filtering with device_id equal to specified router) Change-Id: I9a9668836ac24d4cbc6a3867ec031611b64ded14
1 parent 3e19fc0 commit eb7a744

5 files changed

Lines changed: 302 additions & 33 deletions

File tree

quantumclient/quantum/v2_0/network.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,21 @@ class ListNetwork(ListCommand):
4141
list_columns = ['id', 'name', 'subnets']
4242

4343

44+
class ListExternalNetwork(ListCommand):
45+
"""List external networks that belong to a given tenant"""
46+
47+
resource = 'network'
48+
log = logging.getLogger(__name__ + '.ListExternalNetwork')
49+
_formatters = {'subnets': _format_subnets, }
50+
list_colums = ['id', 'name', 'subnets']
51+
52+
def get_data(self, parsed_args):
53+
if '--' not in parsed_args.filter_specs:
54+
parsed_args.filter_specs.append('--')
55+
parsed_args.filter_specs.append('--router:external=True')
56+
return super(ListExternalNetwork, self).get_data(parsed_args)
57+
58+
4459
class ShowNetwork(ShowCommand):
4560
"""Show information of a given network."""
4661

quantumclient/quantum/v2_0/port.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,41 @@ def _format_fixed_ips(port):
3535

3636

3737
class ListPort(ListCommand):
38-
"""List networks that belong to a given tenant."""
38+
"""List ports that belong to a given tenant."""
3939

4040
resource = 'port'
4141
log = logging.getLogger(__name__ + '.ListPort')
4242
_formatters = {'fixed_ips': _format_fixed_ips, }
4343
list_columns = ['id', 'name', 'mac_address', 'fixed_ips']
4444

4545

46+
class ListRouterPort(ListCommand):
47+
"""List ports that belong to a given tenant, with specified router"""
48+
49+
resource = 'port'
50+
log = logging.getLogger(__name__ + '.ListRouterPort')
51+
_formatters = {'fixed_ips': _format_fixed_ips, }
52+
list_columns = ['id', 'name', 'mac_address', 'fixed_ips']
53+
54+
def get_parser(self, prog_name):
55+
parser = super(ListCommand, self).get_parser(prog_name)
56+
quantumv20.add_show_list_common_argument(parser)
57+
parser.add_argument(
58+
'id', metavar='router',
59+
help='ID or name of router to look up')
60+
quantumv20.add_extra_argument(parser, 'filter_specs',
61+
'filters options')
62+
return parser
63+
64+
def get_data(self, parsed_args):
65+
quantum_client = self.get_client()
66+
quantum_client.format = parsed_args.request_format
67+
_id = quantumv20.find_resourceid_by_name_or_id(
68+
quantum_client, 'router', parsed_args.id)
69+
parsed_args.filter_specs.append('--device_id=%s' % _id)
70+
return super(ListRouterPort, self).get_data(parsed_args)
71+
72+
4673
class ShowPort(ShowCommand):
4774
"""Show information of a given port."""
4875

quantumclient/shell.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ def env(*_vars, **kwargs):
5454
COMMAND_V2 = {
5555
'net-list': utils.import_class(
5656
'quantumclient.quantum.v2_0.network.ListNetwork'),
57+
'net-external-list': utils.import_class(
58+
'quantumclient.quantum.v2_0.network.ListExternalNetwork'),
5759
'net-show': utils.import_class(
5860
'quantumclient.quantum.v2_0.network.ShowNetwork'),
5961
'net-create': utils.import_class(
@@ -96,6 +98,8 @@ def env(*_vars, **kwargs):
9698
'quantumclient.quantum.v2_0.extension.ShowExt'),
9799
'router-list': utils.import_class(
98100
'quantumclient.quantum.v2_0.router.ListRouter'),
101+
'router-port-list': utils.import_class(
102+
'quantumclient.quantum.v2_0.port.ListRouterPort'),
99103
'router-show': utils.import_class(
100104
'quantumclient.quantum.v2_0.router.ShowRouter'),
101105
'router-create': utils.import_class(

quantumclient/tests/unit/test_cli20_network.py

Lines changed: 143 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# vim: tabstop=4 shiftwidth=4 softtabstop=4
1717

1818
import sys
19+
from mox import ContainsKeyValue
1920

2021
from quantumclient.common import exceptions
2122
from quantumclient.common import utils
@@ -27,6 +28,7 @@
2728
from quantumclient.quantum.v2_0.network import UpdateNetwork
2829
from quantumclient.quantum.v2_0.network import ShowNetwork
2930
from quantumclient.quantum.v2_0.network import DeleteNetwork
31+
from quantumclient.quantum.v2_0.network import ListExternalNetwork
3032

3133

3234
class CLITestV20Network(CLITestV20Base):
@@ -39,8 +41,8 @@ def test_create_network(self):
3941
args = [name, ]
4042
position_names = ['name', ]
4143
position_values = [name, ]
42-
_str = self._test_create_resource(resource, cmd, name, myid, args,
43-
position_names, position_values)
44+
self._test_create_resource(resource, cmd, name, myid, args,
45+
position_names, position_values)
4446

4547
def test_create_network_tenant(self):
4648
"""Create net: --tenant_id tenantid myname."""
@@ -51,15 +53,15 @@ def test_create_network_tenant(self):
5153
args = ['--tenant_id', 'tenantid', name]
5254
position_names = ['name', ]
5355
position_values = [name, ]
54-
_str = self._test_create_resource(resource, cmd, name, myid, args,
55-
position_names, position_values,
56-
tenant_id='tenantid')
56+
self._test_create_resource(resource, cmd, name, myid, args,
57+
position_names, position_values,
58+
tenant_id='tenantid')
5759

5860
# Test dashed options
5961
args = ['--tenant-id', 'tenantid', name]
60-
_str = self._test_create_resource(resource, cmd, name, myid, args,
61-
position_names, position_values,
62-
tenant_id='tenantid')
62+
self._test_create_resource(resource, cmd, name, myid, args,
63+
position_names, position_values,
64+
tenant_id='tenantid')
6365

6466
def test_create_network_tags(self):
6567
"""Create net: myname --tags a b."""
@@ -70,9 +72,9 @@ def test_create_network_tags(self):
7072
args = [name, '--tags', 'a', 'b']
7173
position_names = ['name', ]
7274
position_values = [name, ]
73-
_str = self._test_create_resource(resource, cmd, name, myid, args,
74-
position_names, position_values,
75-
tags=['a', 'b'])
75+
self._test_create_resource(resource, cmd, name, myid, args,
76+
position_names, position_values,
77+
tags=['a', 'b'])
7678

7779
def test_create_network_state(self):
7880
"""Create net: --admin_state_down myname."""
@@ -83,15 +85,15 @@ def test_create_network_state(self):
8385
args = ['--admin_state_down', name, ]
8486
position_names = ['name', ]
8587
position_values = [name, ]
86-
_str = self._test_create_resource(resource, cmd, name, myid, args,
87-
position_names, position_values,
88-
admin_state_up=False)
88+
self._test_create_resource(resource, cmd, name, myid, args,
89+
position_names, position_values,
90+
admin_state_up=False)
8991

9092
# Test dashed options
9193
args = ['--admin-state-down', name, ]
92-
_str = self._test_create_resource(resource, cmd, name, myid, args,
93-
position_names, position_values,
94-
admin_state_up=False)
94+
self._test_create_resource(resource, cmd, name, myid, args,
95+
position_names, position_values,
96+
admin_state_up=False)
9597

9698
def test_list_nets_empty_with_column(self):
9799
resources = "networks"
@@ -179,6 +181,130 @@ def test_list_nets_with_default_column(self):
179181
self.assertEquals(0, len(set(network) ^
180182
set(cmd.list_columns)))
181183

184+
def test_list_external_nets_empty_with_column(self):
185+
resources = "networks"
186+
cmd = ListExternalNetwork(MyApp(sys.stdout), None)
187+
self.mox.StubOutWithMock(cmd, "get_client")
188+
self.mox.StubOutWithMock(self.client.httpclient, "request")
189+
cmd.get_client().MultipleTimes().AndReturn(self.client)
190+
reses = {resources: []}
191+
resstr = self.client.serialize(reses)
192+
# url method body
193+
query = "router%3Aexternal=True&id=myfakeid"
194+
args = ['-c', 'id', '--', '--id', 'myfakeid']
195+
path = getattr(self.client, resources + "_path")
196+
self.client.httpclient.request(
197+
test_cli20.end_url(path, query), 'GET',
198+
body=None,
199+
headers=test_cli20.ContainsKeyValue(
200+
'X-Auth-Token',
201+
test_cli20.TOKEN)).AndReturn(
202+
(test_cli20.MyResp(200), resstr))
203+
self.mox.ReplayAll()
204+
cmd_parser = cmd.get_parser("list_" + resources)
205+
206+
parsed_args = cmd_parser.parse_args(args)
207+
208+
cmd.run(parsed_args)
209+
self.mox.VerifyAll()
210+
self.mox.UnsetStubs()
211+
_str = self.fake_stdout.make_string()
212+
self.assertEquals('\n', _str)
213+
214+
def _test_list_external_nets(self, resources, cmd,
215+
detail=False, tags=[],
216+
fields_1=[], fields_2=[]):
217+
self.mox.StubOutWithMock(cmd, "get_client")
218+
self.mox.StubOutWithMock(self.client.httpclient, "request")
219+
cmd.get_client().MultipleTimes().AndReturn(self.client)
220+
reses = {resources: [{'id': 'myid1', },
221+
{'id': 'myid2', }, ], }
222+
223+
resstr = self.client.serialize(reses)
224+
225+
# url method body
226+
query = ""
227+
args = detail and ['-D', ] or []
228+
if fields_1:
229+
for field in fields_1:
230+
args.append('--fields')
231+
args.append(field)
232+
if tags:
233+
args.append('--')
234+
args.append("--tag")
235+
for tag in tags:
236+
args.append(tag)
237+
if (not tags) and fields_2:
238+
args.append('--')
239+
if fields_2:
240+
args.append("--fields")
241+
for field in fields_2:
242+
args.append(field)
243+
fields_1.extend(fields_2)
244+
for field in fields_1:
245+
if query:
246+
query += "&fields=" + field
247+
else:
248+
query = "fields=" + field
249+
if query:
250+
query += '&router%3Aexternal=True'
251+
else:
252+
query += 'router%3Aexternal=True'
253+
for tag in tags:
254+
if query:
255+
query += "&tag=" + tag
256+
else:
257+
query = "tag=" + tag
258+
if detail:
259+
query = query and query + '&verbose=True' or 'verbose=True'
260+
path = getattr(self.client, resources + "_path")
261+
262+
self.client.httpclient.request(
263+
test_cli20.end_url(path, query), 'GET',
264+
body=None,
265+
headers=ContainsKeyValue('X-Auth-Token',
266+
test_cli20.TOKEN)).AndReturn(
267+
(test_cli20.MyResp(200), resstr))
268+
self.mox.ReplayAll()
269+
cmd_parser = cmd.get_parser("list_" + resources)
270+
271+
parsed_args = cmd_parser.parse_args(args)
272+
cmd.run(parsed_args)
273+
274+
self.mox.VerifyAll()
275+
self.mox.UnsetStubs()
276+
_str = self.fake_stdout.make_string()
277+
278+
self.assertTrue('myid1' in _str)
279+
280+
def test_list_external_nets_detail(self):
281+
"""list external nets: -D."""
282+
resources = "networks"
283+
cmd = ListExternalNetwork(MyApp(sys.stdout), None)
284+
self._test_list_external_nets(resources, cmd, True)
285+
286+
def test_list_external_nets_tags(self):
287+
"""List external nets: -- --tags a b."""
288+
resources = "networks"
289+
cmd = ListExternalNetwork(MyApp(sys.stdout), None)
290+
self._test_list_external_nets(resources,
291+
cmd, tags=['a', 'b'])
292+
293+
def test_list_external_nets_detail_tags(self):
294+
"""List external nets: -D -- --tags a b."""
295+
resources = "networks"
296+
cmd = ListExternalNetwork(MyApp(sys.stdout), None)
297+
self._test_list_external_nets(resources, cmd,
298+
detail=True, tags=['a', 'b'])
299+
300+
def test_list_externel_nets_fields(self):
301+
"""List external nets: --fields a --fields b -- --fields c d."""
302+
resources = "networks"
303+
cmd = ListExternalNetwork(MyApp(sys.stdout), None)
304+
self._test_list_external_nets(resources, cmd,
305+
fields_1=['a', 'b'],
306+
fields_2=['c', 'd'])
307+
182308
def test_update_network_exception(self):
183309
"""Update net: myid."""
184310
resource = 'network'

0 commit comments

Comments
 (0)