Add 'allowed address pairs' option to 'port create/set/unset'
This patch adds '--allowed-addres-pair' and '--no-allowed-address-pair' options to 'port create', 'port set' and 'port unset' commands. Partial-Bug: #1612136 Closes-Bug: #1638265 Partially-Implements: blueprint network-commands-options Co-Authored-By: Ha Van Tu <tuhv@vn.fujitsu.com> Change-Id: I08d2269950467a8972a0d0110ed61f5cc7f5ca45
This commit is contained in:
parent
3ab94614c2
commit
8bcfb824c8
@ -29,6 +29,7 @@ Create new port
|
||||
[--mac-address <mac-address>]
|
||||
[--security-group <security-group> | --no-security-group]
|
||||
[--dns-name <dns-name>]
|
||||
[--allowed-address ip-address=<ip-address>[,mac-address=<mac-address>]]
|
||||
[--project <project> [--project-domain <project-domain>]]
|
||||
[--enable-port-security | --disable-port-security]
|
||||
<name>
|
||||
@ -97,6 +98,12 @@ Create new port
|
||||
Set DNS name to this port
|
||||
(requires DNS integration extension)
|
||||
|
||||
.. option:: --allowed-address ip-address=<ip-address>[,mac-address=<mac-address>]
|
||||
|
||||
Add allowed-address pair associated with this port:
|
||||
ip-address=<ip-address>[,mac-address=<mac-address>]
|
||||
(repeat option to set multiple allowed-address pairs)
|
||||
|
||||
.. option:: --project <project>
|
||||
|
||||
Owner's project (name or ID)
|
||||
@ -199,6 +206,8 @@ Set port properties
|
||||
[--no-security-group]
|
||||
[--enable-port-security | --disable-port-security]
|
||||
[--dns-name <dns-name>]
|
||||
[--allowed-address ip-address=<ip-address>[,mac-address=<mac-address>]]
|
||||
[--no-allowed-address]
|
||||
<port>
|
||||
|
||||
.. option:: --description <description>
|
||||
@ -281,6 +290,19 @@ Set port properties
|
||||
Set DNS name to this port
|
||||
(requires DNS integration extension)
|
||||
|
||||
.. option:: --allowed-address ip-address=<ip-address>[,mac-address=<mac-address>]
|
||||
|
||||
Add allowed-address pair associated with this port:
|
||||
ip-address=<ip-address>[,mac-address=<mac-address>]
|
||||
(repeat option to set multiple allowed-address pairs)
|
||||
|
||||
.. option:: --no-allowed-address
|
||||
|
||||
Clear existing allowed-address pairs associated
|
||||
with this port.
|
||||
(Specify both --allowed-address and --no-allowed-address
|
||||
to overwrite the current allowed-address pairs)
|
||||
|
||||
.. _port_set-port:
|
||||
.. describe:: <port>
|
||||
|
||||
@ -314,6 +336,7 @@ Unset port properties
|
||||
[--fixed-ip subnet=<subnet>,ip-address=<ip-address> [...]]
|
||||
[--binding-profile <binding-profile-key> [...]]
|
||||
[--security-group <security-group> [...]]
|
||||
[--allowed-address ip-address=<ip-address>[,mac-address=<mac-address>] [...]]
|
||||
<port>
|
||||
|
||||
.. option:: --fixed-ip subnet=<subnet>,ip-address=<ip-address>
|
||||
@ -332,6 +355,12 @@ Unset port properties
|
||||
Security group which should be removed from this port (name or ID)
|
||||
(repeat option to unset multiple security groups)
|
||||
|
||||
.. option:: --allowed-address ip-address=<ip-address>[,mac-address=<mac-address>]
|
||||
|
||||
Desired allowed-address pair which should be removed from this port:
|
||||
ip-address=<ip-address>[,mac-address=<mac-address>]
|
||||
(repeat option to unset multiple allowed-address pairs)
|
||||
|
||||
.. _port_unset-port:
|
||||
.. describe:: <port>
|
||||
|
||||
|
@ -246,6 +246,17 @@ def _add_updatable_args(parser):
|
||||
|
||||
# TODO(abhiraut): Use the SDK resource mapped attribute names once the
|
||||
# OSC minimum requirements include SDK 1.0.
|
||||
def _convert_address_pairs(parsed_args):
|
||||
ops = []
|
||||
for opt in parsed_args.allowed_address_pairs:
|
||||
addr = {}
|
||||
addr['ip_address'] = opt['ip-address']
|
||||
if 'mac-address' in opt:
|
||||
addr['mac_address'] = opt['mac-address']
|
||||
ops.append(addr)
|
||||
return ops
|
||||
|
||||
|
||||
class CreatePort(command.ShowOne):
|
||||
_description = _("Create a new port")
|
||||
|
||||
@ -305,7 +316,7 @@ class CreatePort(command.ShowOne):
|
||||
help=_("Name of this port")
|
||||
)
|
||||
# TODO(singhj): Add support for extended options:
|
||||
# qos,dhcp, address pairs
|
||||
# qos,dhcp
|
||||
secgroups = parser.add_mutually_exclusive_group()
|
||||
secgroups.add_argument(
|
||||
'--security-group',
|
||||
@ -332,7 +343,17 @@ class CreatePort(command.ShowOne):
|
||||
action='store_true',
|
||||
help=_("Disable port security for this port")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--allowed-address',
|
||||
metavar='ip-address=<ip-address>[,mac-address=<mac-address>]',
|
||||
action=parseractions.MultiKeyValueAction,
|
||||
dest='allowed_address_pairs',
|
||||
required_keys=['ip-address'],
|
||||
optional_keys=['mac-address'],
|
||||
help=_("Add allowed-address pair associated with this port: "
|
||||
"ip-address=<ip-address>[,mac-address=<mac-address>] "
|
||||
"(repeat option to set multiple allowed-address pairs)")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
@ -349,6 +370,9 @@ class CreatePort(command.ShowOne):
|
||||
for sg in parsed_args.security_groups]
|
||||
if parsed_args.no_security_group:
|
||||
attrs['security_groups'] = []
|
||||
if parsed_args.allowed_address_pairs:
|
||||
attrs['allowed_address_pairs'] = (
|
||||
_convert_address_pairs(parsed_args))
|
||||
|
||||
obj = client.create_port(**attrs)
|
||||
display_columns, columns = _get_columns(obj)
|
||||
@ -569,7 +593,26 @@ class SetPort(command.Command):
|
||||
action='store_true',
|
||||
help=_("Disable port security for this port")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--allowed-address',
|
||||
metavar='ip-address=<ip-address>[,mac-address=<mac-address>]',
|
||||
action=parseractions.MultiKeyValueAction,
|
||||
dest='allowed_address_pairs',
|
||||
required_keys=['ip-address'],
|
||||
optional_keys=['mac-address'],
|
||||
help=_("Add allowed-address pair associated with this port: "
|
||||
"ip-address=<ip-address>[,mac-address=<mac-address>] "
|
||||
"(repeat option to set multiple allowed-address pairs)")
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-allowed-address',
|
||||
dest='no_allowed_address_pair',
|
||||
action='store_true',
|
||||
help=_("Clear existing allowed-address pairs associated"
|
||||
"with this port."
|
||||
"(Specify both --allowed-address and --no-allowed-address"
|
||||
"to overwrite the current allowed-address pairs)")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
@ -609,6 +652,19 @@ class SetPort(command.Command):
|
||||
elif parsed_args.no_security_group:
|
||||
attrs['security_groups'] = []
|
||||
|
||||
if (parsed_args.allowed_address_pairs and
|
||||
parsed_args.no_allowed_address_pair):
|
||||
attrs['allowed_address_pairs'] = (
|
||||
_convert_address_pairs(parsed_args))
|
||||
|
||||
elif parsed_args.allowed_address_pairs:
|
||||
attrs['allowed_address_pairs'] = (
|
||||
[addr for addr in obj.allowed_address_pairs if addr] +
|
||||
_convert_address_pairs(parsed_args))
|
||||
|
||||
elif parsed_args.no_allowed_address_pair:
|
||||
attrs['allowed_address_pairs'] = []
|
||||
|
||||
client.update_port(obj, **attrs)
|
||||
|
||||
|
||||
@ -669,6 +725,19 @@ class UnsetPort(command.Command):
|
||||
metavar="<port>",
|
||||
help=_("Port to modify (name or ID)")
|
||||
)
|
||||
parser.add_argument(
|
||||
'--allowed-address',
|
||||
metavar='ip-address=<ip-address>[,mac-address=<mac-address>]',
|
||||
action=parseractions.MultiKeyValueAction,
|
||||
dest='allowed_address_pairs',
|
||||
required_keys=['ip-address'],
|
||||
optional_keys=['mac-address'],
|
||||
help=_("Desired allowed-address pair which should be removed "
|
||||
"from this port: ip-address=<ip-address> "
|
||||
"[,mac-address=<mac-address>] (repeat option to set "
|
||||
"multiple allowed-address pairs)")
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
@ -680,6 +749,7 @@ class UnsetPort(command.Command):
|
||||
tmp_fixed_ips = copy.deepcopy(obj.fixed_ips)
|
||||
tmp_binding_profile = copy.deepcopy(obj.binding_profile)
|
||||
tmp_secgroups = copy.deepcopy(obj.security_groups)
|
||||
tmp_addr_pairs = copy.deepcopy(obj.allowed_address_pairs)
|
||||
_prepare_fixed_ips(self.app.client_manager, parsed_args)
|
||||
attrs = {}
|
||||
if parsed_args.fixed_ip:
|
||||
@ -708,6 +778,14 @@ class UnsetPort(command.Command):
|
||||
msg = _("Port does not contain security group %s") % sg
|
||||
raise exceptions.CommandError(msg)
|
||||
attrs['security_groups'] = tmp_secgroups
|
||||
if parsed_args.allowed_address_pairs:
|
||||
try:
|
||||
for addr in _convert_address_pairs(parsed_args):
|
||||
tmp_addr_pairs.remove(addr)
|
||||
except ValueError:
|
||||
msg = _("Port does not contain allowed-address-pair %s") % addr
|
||||
raise exceptions.CommandError(msg)
|
||||
attrs['allowed_address_pairs'] = tmp_addr_pairs
|
||||
|
||||
if attrs:
|
||||
client.update_port(obj, **attrs)
|
||||
|
@ -216,7 +216,7 @@ class TestCreatePort(TestPort):
|
||||
'test-port',
|
||||
]
|
||||
verifylist = [
|
||||
('network', self._port.network_id,),
|
||||
('network', self._port.network_id),
|
||||
('enable', True),
|
||||
('binding_profile', {'parent_name': 'fake_parent', 'tag': 42}),
|
||||
('name', 'test-port'),
|
||||
@ -351,6 +351,74 @@ class TestCreatePort(TestPort):
|
||||
self.assertEqual(ref_columns, columns)
|
||||
self.assertEqual(ref_data, data)
|
||||
|
||||
def test_create_port_with_allowed_address_pair_ipaddr(self):
|
||||
pairs = [{'ip_address': '192.168.1.123'},
|
||||
{'ip_address': '192.168.1.45'}]
|
||||
arglist = [
|
||||
'--network', self._port.network_id,
|
||||
'--allowed-address', 'ip-address=192.168.1.123',
|
||||
'--allowed-address', 'ip-address=192.168.1.45',
|
||||
'test-port',
|
||||
]
|
||||
verifylist = [
|
||||
('network', self._port.network_id),
|
||||
('enable', True),
|
||||
('allowed_address_pairs', [{'ip-address': '192.168.1.123'},
|
||||
{'ip-address': '192.168.1.45'}]),
|
||||
('name', 'test-port'),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = (self.cmd.take_action(parsed_args))
|
||||
|
||||
self.network.create_port.assert_called_once_with(**{
|
||||
'admin_state_up': True,
|
||||
'network_id': self._port.network_id,
|
||||
'allowed_address_pairs': pairs,
|
||||
'name': 'test-port',
|
||||
})
|
||||
|
||||
ref_columns, ref_data = self._get_common_cols_data(self._port)
|
||||
self.assertEqual(ref_columns, columns)
|
||||
self.assertEqual(ref_data, data)
|
||||
|
||||
def test_create_port_with_allowed_address_pair(self):
|
||||
pairs = [{'ip_address': '192.168.1.123',
|
||||
'mac_address': 'aa:aa:aa:aa:aa:aa'},
|
||||
{'ip_address': '192.168.1.45',
|
||||
'mac_address': 'aa:aa:aa:aa:aa:b1'}]
|
||||
arglist = [
|
||||
'--network', self._port.network_id,
|
||||
'--allowed-address',
|
||||
'ip-address=192.168.1.123,mac-address=aa:aa:aa:aa:aa:aa',
|
||||
'--allowed-address',
|
||||
'ip-address=192.168.1.45,mac-address=aa:aa:aa:aa:aa:b1',
|
||||
'test-port',
|
||||
]
|
||||
verifylist = [
|
||||
('network', self._port.network_id),
|
||||
('enable', True),
|
||||
('allowed_address_pairs', [{'ip-address': '192.168.1.123',
|
||||
'mac-address': 'aa:aa:aa:aa:aa:aa'},
|
||||
{'ip-address': '192.168.1.45',
|
||||
'mac-address': 'aa:aa:aa:aa:aa:b1'}]),
|
||||
('name', 'test-port'),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = (self.cmd.take_action(parsed_args))
|
||||
|
||||
self.network.create_port.assert_called_once_with(**{
|
||||
'admin_state_up': True,
|
||||
'network_id': self._port.network_id,
|
||||
'allowed_address_pairs': pairs,
|
||||
'name': 'test-port',
|
||||
})
|
||||
|
||||
ref_columns, ref_data = self._get_common_cols_data(self._port)
|
||||
self.assertEqual(ref_columns, columns)
|
||||
self.assertEqual(ref_data, data)
|
||||
|
||||
def test_create_port_security_enabled(self):
|
||||
arglist = [
|
||||
'--network', self._port.network_id,
|
||||
@ -996,6 +1064,91 @@ class TestSetPort(TestPort):
|
||||
self.network.update_port.assert_called_once_with(_testport, **attrs)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_set_allowed_address_pair(self):
|
||||
arglist = [
|
||||
'--allowed-address', 'ip-address=192.168.1.123',
|
||||
self._port.name,
|
||||
]
|
||||
verifylist = [
|
||||
('allowed_address_pairs', [{'ip-address': '192.168.1.123'}]),
|
||||
('port', self._port.name),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
attrs = {
|
||||
'allowed_address_pairs': [{'ip_address': '192.168.1.123'}],
|
||||
}
|
||||
self.network.update_port.assert_called_once_with(self._port, **attrs)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_append_allowed_address_pair(self):
|
||||
_testport = network_fakes.FakePort.create_one_port(
|
||||
{'allowed_address_pairs': [{'ip_address': '192.168.1.123'}]})
|
||||
self.network.find_port = mock.Mock(return_value=_testport)
|
||||
arglist = [
|
||||
'--allowed-address', 'ip-address=192.168.1.45',
|
||||
_testport.name,
|
||||
]
|
||||
verifylist = [
|
||||
('allowed_address_pairs', [{'ip-address': '192.168.1.45'}]),
|
||||
('port', _testport.name),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
attrs = {
|
||||
'allowed_address_pairs': [{'ip_address': '192.168.1.123'},
|
||||
{'ip_address': '192.168.1.45'}],
|
||||
}
|
||||
self.network.update_port.assert_called_once_with(_testport, **attrs)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_overwrite_allowed_address_pair(self):
|
||||
_testport = network_fakes.FakePort.create_one_port(
|
||||
{'allowed_address_pairs': [{'ip_address': '192.168.1.123'}]})
|
||||
self.network.find_port = mock.Mock(return_value=_testport)
|
||||
arglist = [
|
||||
'--allowed-address', 'ip-address=192.168.1.45',
|
||||
'--no-allowed-address',
|
||||
_testport.name,
|
||||
]
|
||||
verifylist = [
|
||||
('allowed_address_pairs', [{'ip-address': '192.168.1.45'}]),
|
||||
('no_allowed_address_pair', True),
|
||||
('port', _testport.name),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
attrs = {
|
||||
'allowed_address_pairs': [{'ip_address': '192.168.1.45'}],
|
||||
}
|
||||
self.network.update_port.assert_called_once_with(_testport, **attrs)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_set_no_allowed_address_pairs(self):
|
||||
arglist = [
|
||||
'--no-allowed-address',
|
||||
self._port.name,
|
||||
]
|
||||
verifylist = [
|
||||
('no_allowed_address_pair', True),
|
||||
('port', self._port.name),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
attrs = {
|
||||
'allowed_address_pairs': [],
|
||||
}
|
||||
self.network.update_port.assert_called_once_with(self._port, **attrs)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_port_security_enabled(self):
|
||||
arglist = [
|
||||
'--enable-port-security',
|
||||
@ -1192,3 +1345,42 @@ class TestUnsetPort(TestPort):
|
||||
self.assertRaises(exceptions.CommandError,
|
||||
self.cmd.take_action,
|
||||
parsed_args)
|
||||
|
||||
def test_unset_port_allowed_address_pair(self):
|
||||
_fake_port = network_fakes.FakePort.create_one_port(
|
||||
{'allowed_address_pairs': [{'ip_address': '192.168.1.123'}]})
|
||||
self.network.find_port = mock.Mock(return_value=_fake_port)
|
||||
arglist = [
|
||||
'--allowed-address', 'ip-address=192.168.1.123',
|
||||
_fake_port.name,
|
||||
]
|
||||
verifylist = [
|
||||
('allowed_address_pairs', [{'ip-address': '192.168.1.123'}]),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
attrs = {
|
||||
'allowed_address_pairs': [],
|
||||
}
|
||||
|
||||
self.network.update_port.assert_called_once_with(_fake_port, **attrs)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_unset_port_allowed_address_pair_not_existent(self):
|
||||
_fake_port = network_fakes.FakePort.create_one_port(
|
||||
{'allowed_address_pairs': [{'ip_address': '192.168.1.123'}]})
|
||||
self.network.find_port = mock.Mock(return_value=_fake_port)
|
||||
arglist = [
|
||||
'--allowed-address', 'ip-address=192.168.1.45',
|
||||
_fake_port.name,
|
||||
]
|
||||
verifylist = [
|
||||
('allowed_address_pairs', [{'ip-address': '192.168.1.45'}]),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
self.assertRaises(exceptions.CommandError,
|
||||
self.cmd.take_action,
|
||||
parsed_args)
|
||||
|
7
releasenotes/notes/bug-1612136-6111b944569b9351.yaml
Normal file
7
releasenotes/notes/bug-1612136-6111b944569b9351.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add ``--allowed-address`` option to ``port create``, ``port set`` and
|
||||
``port unset`` commands. Also add ``--no-allowed-address`` option to
|
||||
``port create`` and ``port set`` commands.
|
||||
[Bug `1612136 <https://bugs.launchpad.net/python-openstackclient/+bug/1612136>`_]
|
Loading…
Reference in New Issue
Block a user