Skip to content

Commit 47716d1

Browse files
author
songminglong
committed
Add extra filtering options to floating ip list
The patch adds filtering '--long', 'status', '--project', '--project-domain' and '--router' options to floating ip list command. Closes-Bug: #1614379 Partially-Implements: blueprint network-commands-options Change-Id: I2a02cf23845ff435927d8b481f77249915bd94dc
1 parent 83cf09d commit 47716d1

4 files changed

Lines changed: 207 additions & 0 deletions

File tree

doc/source/command-objects/floating-ip.rst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ List floating IP(s)
8989
[--network <network>]
9090
[--port <port>]
9191
[--fixed-ip-address <fixed-ip-address>]
92+
[--long]
93+
[--status <status>]
94+
[--project <project> [--project-domain <project-domain>]]
95+
[--router <router>]
9296
9397
.. option:: --network <network>
9498
@@ -108,6 +112,37 @@ List floating IP(s)
108112
109113
*Network version 2 only*
110114
115+
.. option:: --long
116+
117+
List additional fields in output
118+
119+
*Network version 2 only*
120+
121+
.. option:: --status <status>
122+
123+
List floating IP(s) according to given status ('ACTIVE', 'DOWN')
124+
125+
*Network version 2 only*
126+
127+
.. option:: --project <project>
128+
129+
List floating IP(s) according to given project (name or ID)
130+
131+
*Network version 2 only*
132+
133+
.. option:: --project-domain <project-domain>
134+
135+
Domain the project belongs to (name or ID). This can
136+
be used in case collisions between project names exist.
137+
138+
*Network version 2 only*
139+
140+
.. option:: --router <router>
141+
142+
List floating IP(s) according to given router (name or ID)
143+
144+
*Network version 2 only*
145+
111146
floating ip show
112147
----------------
113148

openstackclient/network/v2/floating_ip.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ def take_action_compute(self, client, parsed_args):
219219

220220

221221
class ListFloatingIP(common.NetworkAndComputeLister):
222+
# TODO(songminglong): Use SDK resource mapped attribute names once
223+
# the OSC minimum requirements include SDK 1.0
222224
_description = _("List floating IP(s)")
223225

224226
def update_parser_network(self, parser):
@@ -240,11 +242,38 @@ def update_parser_network(self, parser):
240242
help=_("List floating IP(s) according to "
241243
"given fixed IP address")
242244
)
245+
parser.add_argument(
246+
'--long',
247+
action='store_true',
248+
default=False,
249+
help=_("List additional fields in output")
250+
)
251+
parser.add_argument(
252+
'--status',
253+
metavar='<status>',
254+
choices=['ACTIVE', 'DOWN'],
255+
help=_("List floating IP(s) according to "
256+
"given status ('ACTIVE', 'DOWN')")
257+
)
258+
parser.add_argument(
259+
'--project',
260+
metavar='<project>',
261+
help=_("List floating IP(s) according to "
262+
"given project (name or ID)")
263+
)
264+
identity_common.add_project_domain_option_to_parser(parser)
265+
parser.add_argument(
266+
'--router',
267+
metavar='<router>',
268+
help=_("List floating IP(s) according to "
269+
"given router (name or ID)")
270+
)
243271

244272
return parser
245273

246274
def take_action_network(self, client, parsed_args):
247275
network_client = self.app.client_manager.network
276+
identity_client = self.app.client_manager.identity
248277

249278
columns = (
250279
'id',
@@ -262,6 +291,17 @@ def take_action_network(self, client, parsed_args):
262291
'Floating Network',
263292
'Project',
264293
)
294+
if parsed_args.long:
295+
columns = columns + (
296+
'router_id',
297+
'status',
298+
'description',
299+
)
300+
headers = headers + (
301+
'Router',
302+
'Status',
303+
'Description',
304+
)
265305

266306
query = {}
267307

@@ -275,6 +315,20 @@ def take_action_network(self, client, parsed_args):
275315
query['port_id'] = port.id
276316
if parsed_args.fixed_ip_address is not None:
277317
query['fixed_ip_address'] = parsed_args.fixed_ip_address
318+
if parsed_args.status:
319+
query['status'] = parsed_args.status
320+
if parsed_args.project is not None:
321+
project = identity_common.find_project(
322+
identity_client,
323+
parsed_args.project,
324+
parsed_args.project_domain,
325+
)
326+
query['tenant_id'] = project.id
327+
query['project_id'] = project.id
328+
if parsed_args.router is not None:
329+
router = network_client.find_router(parsed_args.router,
330+
ignore_missing=False)
331+
query['router_id'] = router.id
278332

279333
data = client.ips(**query)
280334

openstackclient/tests/unit/network/v2/test_floating_ip.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ def setUp(self):
3232

3333
# Get a shortcut to the network client
3434
self.network = self.app.client_manager.network
35+
# Get a shortcut to the ProjectManager Mock
3536
self.projects_mock = self.app.client_manager.identity.projects
37+
# Get a shortcut to the DomainManager Mock
38+
self.domains_mock = self.app.client_manager.identity.domains
3639

3740

3841
class TestCreateFloatingIPNetwork(TestFloatingIPNetwork):
@@ -287,6 +290,9 @@ class TestListFloatingIPNetwork(TestFloatingIPNetwork):
287290
fake_port = network_fakes.FakePort.create_one_port({
288291
'id': 'fake_port_id',
289292
})
293+
fake_router = network_fakes.FakeRouter.create_one_router({
294+
'id': 'fake_router_id',
295+
})
290296

291297
columns = (
292298
'ID',
@@ -296,8 +302,14 @@ class TestListFloatingIPNetwork(TestFloatingIPNetwork):
296302
'Floating Network',
297303
'Project',
298304
)
305+
columns_long = columns + (
306+
'Router',
307+
'Status',
308+
'Description',
309+
)
299310

300311
data = []
312+
data_long = []
301313
for ip in floating_ips:
302314
data.append((
303315
ip.id,
@@ -307,13 +319,25 @@ class TestListFloatingIPNetwork(TestFloatingIPNetwork):
307319
ip.floating_network_id,
308320
ip.tenant_id,
309321
))
322+
data_long.append((
323+
ip.id,
324+
ip.floating_ip_address,
325+
ip.fixed_ip_address,
326+
ip.port_id,
327+
ip.floating_network_id,
328+
ip.tenant_id,
329+
ip.router_id,
330+
ip.status,
331+
ip.description,
332+
))
310333

311334
def setUp(self):
312335
super(TestListFloatingIPNetwork, self).setUp()
313336

314337
self.network.ips = mock.Mock(return_value=self.floating_ips)
315338
self.network.find_network = mock.Mock(return_value=self.fake_network)
316339
self.network.find_port = mock.Mock(return_value=self.fake_port)
340+
self.network.find_router = mock.Mock(return_value=self.fake_router)
317341

318342
# Get the command object to test
319343
self.cmd = floating_ip.ListFloatingIP(self.app, self.namespace)
@@ -380,6 +404,94 @@ def test_floating_ip_list_fixed_ip_address(self):
380404
self.assertEqual(self.columns, columns)
381405
self.assertEqual(self.data, list(data))
382406

407+
def test_floating_ip_list_long(self):
408+
arglist = ['--long', ]
409+
verifylist = [('long', True), ]
410+
411+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
412+
413+
columns, data = self.cmd.take_action(parsed_args)
414+
415+
self.network.ips.assert_called_once_with()
416+
self.assertEqual(self.columns_long, columns)
417+
self.assertEqual(self.data_long, list(data))
418+
419+
def test_floating_ip_list_status(self):
420+
arglist = [
421+
'--status', 'ACTIVE',
422+
'--long',
423+
]
424+
verifylist = [
425+
('status', 'ACTIVE'),
426+
]
427+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
428+
429+
columns, data = self.cmd.take_action(parsed_args)
430+
431+
self.network.ips.assert_called_once_with(**{
432+
'status': 'ACTIVE',
433+
})
434+
self.assertEqual(self.columns_long, columns)
435+
self.assertEqual(self.data_long, list(data))
436+
437+
def test_floating_ip_list_project(self):
438+
project = identity_fakes_v3.FakeProject.create_one_project()
439+
self.projects_mock.get.return_value = project
440+
arglist = [
441+
'--project', project.id,
442+
]
443+
verifylist = [
444+
('project', project.id),
445+
]
446+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
447+
448+
columns, data = self.cmd.take_action(parsed_args)
449+
filters = {'tenant_id': project.id,
450+
'project_id': project.id, }
451+
452+
self.network.ips.assert_called_once_with(**filters)
453+
454+
self.assertEqual(self.columns, columns)
455+
self.assertEqual(self.data, list(data))
456+
457+
def test_floating_ip_list_project_domain(self):
458+
project = identity_fakes_v3.FakeProject.create_one_project()
459+
self.projects_mock.get.return_value = project
460+
arglist = [
461+
'--project', project.id,
462+
'--project-domain', project.domain_id,
463+
]
464+
verifylist = [
465+
('project', project.id),
466+
]
467+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
468+
469+
columns, data = self.cmd.take_action(parsed_args)
470+
filters = {'tenant_id': project.id,
471+
'project_id': project.id, }
472+
473+
self.network.ips.assert_called_once_with(**filters)
474+
self.assertEqual(self.columns, columns)
475+
self.assertEqual(self.data, list(data))
476+
477+
def test_floating_ip_list_router(self):
478+
arglist = [
479+
'--router', 'fake_router_id',
480+
'--long',
481+
]
482+
verifylist = [
483+
('router', 'fake_router_id'),
484+
]
485+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
486+
487+
columns, data = self.cmd.take_action(parsed_args)
488+
489+
self.network.ips.assert_called_once_with(**{
490+
'router_id': 'fake_router_id',
491+
})
492+
self.assertEqual(self.columns_long, columns)
493+
self.assertEqual(self.data_long, list(data))
494+
383495

384496
class TestShowFloatingIPNetwork(TestFloatingIPNetwork):
385497

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
features:
3+
- |
4+
Add ``--long``, ``--status``, ``--project``, ``--project-domain``,
5+
and ``--router`` options to ``floating ip list`` command.
6+
[Bug `1614379 <https://bugs.launchpad.net/bugs/1614379>`_]

0 commit comments

Comments
 (0)