Skip to content

Commit b38be94

Browse files
author
reedip
committed
Introduce overwrite functionality in osc port set
The overwrite functionality allows user to overwrite either the binding-profile or the fixed-ips of a specific port. Change-Id: I8ec3d04eeaf28972ee545fcdda4d5f7bd9deb915 partially-implements: blueprint allow-overwrite-set-options
1 parent 320ed01 commit b38be94

4 files changed

Lines changed: 78 additions & 15 deletions

File tree

doc/source/command-objects/port.rst

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,13 @@ Set port properties
135135
.. code:: bash
136136
137137
os port set
138-
[--fixed-ip subnet=<subnet>,ip-address=<ip-address> | --no-fixed-ip]
138+
[--fixed-ip subnet=<subnet>,ip-address=<ip-address>]
139+
[--no-fixed-ip]
139140
[--device <device-id>]
140141
[--device-owner <device-owner>]
141142
[--vnic-type <vnic-type>]
142-
[--binding-profile <binding-profile> | --no-binding-profile]
143+
[--binding-profile <binding-profile>]
144+
[--no-binding-profile]
143145
[--host <host-id>]
144146
[--enable | --disable]
145147
[--name <name>]
@@ -153,7 +155,9 @@ Set port properties
153155
154156
.. option:: --no-fixed-ip
155157
156-
Clear existing information of fixed IP addresses
158+
Clear existing information of fixed IP addresses.
159+
Specify both --fixed-ip and --no-fixed-ip
160+
to overwrite the current fixed IP addresses.
157161
158162
.. option:: --device <device-id>
159163
@@ -177,7 +181,9 @@ Set port properties
177181
178182
.. option:: --no-binding-profile
179183
180-
Clear existing information of binding:profile
184+
Clear existing information of binding:profile.
185+
Specify both --binding-profile and --no-binding-profile
186+
to overwrite the current binding:profile information.
181187
182188
.. option:: --host <host-id>
183189

openstackclient/network/v2/port.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ def _get_attrs(client_manager, parsed_args):
109109
'The --host-id option is deprecated, '
110110
'please use --host instead.'
111111
))
112-
113112
if parsed_args.fixed_ip is not None:
114113
attrs['fixed_ips'] = parsed_args.fixed_ip
115114
if parsed_args.device:
@@ -409,8 +408,7 @@ def get_parser(self, prog_name):
409408
metavar="<name>",
410409
help=_("Set port name")
411410
)
412-
fixed_ip = parser.add_mutually_exclusive_group()
413-
fixed_ip.add_argument(
411+
parser.add_argument(
414412
'--fixed-ip',
415413
metavar='subnet=<subnet>,ip-address=<ip-address>',
416414
action=parseractions.MultiKeyValueAction,
@@ -419,24 +417,27 @@ def get_parser(self, prog_name):
419417
"subnet=<subnet>,ip-address=<ip-address> "
420418
"(repeat option to set multiple fixed IP addresses)")
421419
)
422-
fixed_ip.add_argument(
420+
parser.add_argument(
423421
'--no-fixed-ip',
424422
action='store_true',
425-
help=_("Clear existing information of fixed IP addresses")
423+
help=_("Clear existing information of fixed IP addresses."
424+
"Specify both --fixed-ip and --no-fixed-ip "
425+
"to overwrite the current fixed IP addresses.")
426426
)
427-
binding_profile = parser.add_mutually_exclusive_group()
428-
binding_profile.add_argument(
427+
parser.add_argument(
429428
'--binding-profile',
430429
metavar='<binding-profile>',
431430
action=JSONKeyValueAction,
432431
help=_("Custom data to be passed as binding:profile. Data may "
433432
"be passed as <key>=<value> or JSON. "
434433
"(repeat option to set multiple binding:profile data)")
435434
)
436-
binding_profile.add_argument(
435+
parser.add_argument(
437436
'--no-binding-profile',
438437
action='store_true',
439-
help=_("Clear existing information of binding:profile")
438+
help=_("Clear existing information of binding:profile."
439+
"Specify both --binding-profile and --no-binding-profile "
440+
"to overwrite the current binding:profile information.")
440441
)
441442
parser.add_argument(
442443
'port',
@@ -452,7 +453,11 @@ def take_action(self, parsed_args):
452453
attrs = _get_attrs(self.app.client_manager, parsed_args)
453454
obj = client.find_port(parsed_args.port, ignore_missing=False)
454455
if 'binding:profile' in attrs:
455-
attrs['binding:profile'].update(obj.binding_profile)
456+
# Do not modify attrs if both binding_profile/no_binding given
457+
if not parsed_args.no_binding_profile:
458+
tmp_binding_profile = copy.deepcopy(obj.binding_profile)
459+
tmp_binding_profile.update(attrs['binding:profile'])
460+
attrs['binding:profile'] = tmp_binding_profile
456461
elif parsed_args.no_binding_profile:
457462
attrs['binding:profile'] = {}
458463
if 'fixed_ips' in attrs:
@@ -461,7 +466,9 @@ def take_action(self, parsed_args):
461466
# would therefore add an empty dictionary, while we need
462467
# to append the attrs['fixed_ips'] iff there is some info
463468
# in the obj.fixed_ips. Therefore I have opted for this `for` loop
464-
attrs['fixed_ips'] += [ip for ip in obj.fixed_ips if ip]
469+
# Do not modify attrs if fixed_ip/no_fixed_ip given
470+
if not parsed_args.no_fixed_ip:
471+
attrs['fixed_ips'] += [ip for ip in obj.fixed_ips if ip]
465472
elif parsed_args.no_fixed_ip:
466473
attrs['fixed_ips'] = []
467474

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,50 @@ def test_append_fixed_ip(self):
465465
self.network.update_port.assert_called_once_with(_testport, **attrs)
466466
self.assertIsNone(result)
467467

468+
def test_overwrite_binding_profile(self):
469+
_testport = network_fakes.FakePort.create_one_port(
470+
{'binding_profile': {'lok_i': 'visi_on'}})
471+
self.network.find_port = mock.Mock(return_value=_testport)
472+
arglist = [
473+
'--binding-profile', 'lok_i=than_os',
474+
'--no-binding-profile',
475+
_testport.name,
476+
]
477+
verifylist = [
478+
('binding_profile', {'lok_i': 'than_os'}),
479+
('no_binding_profile', True)
480+
]
481+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
482+
result = self.cmd.take_action(parsed_args)
483+
attrs = {
484+
'binding:profile':
485+
{'lok_i': 'than_os'},
486+
}
487+
self.network.update_port.assert_called_once_with(_testport, **attrs)
488+
self.assertIsNone(result)
489+
490+
def test_overwrite_fixed_ip(self):
491+
_testport = network_fakes.FakePort.create_one_port(
492+
{'fixed_ips': [{'ip_address': '0.0.0.1'}]})
493+
self.network.find_port = mock.Mock(return_value=_testport)
494+
arglist = [
495+
'--fixed-ip', 'ip-address=10.0.0.12',
496+
'--no-fixed-ip',
497+
_testport.name,
498+
]
499+
verifylist = [
500+
('fixed_ip', [{'ip-address': '10.0.0.12'}]),
501+
('no_fixed_ip', True)
502+
]
503+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
504+
result = self.cmd.take_action(parsed_args)
505+
attrs = {
506+
'fixed_ips': [
507+
{'ip_address': '10.0.0.12'}],
508+
}
509+
self.network.update_port.assert_called_once_with(_testport, **attrs)
510+
self.assertIsNone(result)
511+
468512
def test_set_this(self):
469513
arglist = [
470514
'--disable',
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
features:
3+
- |
4+
``port set`` command now allows the user to overwrite fixed-ips or binding-profile
5+
of a port.
6+
[ Blueprint `allow-overwrite-set-options <https://blueprints.launchpad.net/python-openstackclient/+spec/allow-overwrite-set-options>` _]

0 commit comments

Comments
 (0)