Add command to unset information from Subnets

This patch introduces the ``subnet unset`` command to
clear the host-routes, allocation-pools and dns-nameservers
from subnets.
Implements: blueprint network-property-unset

Change-Id: I31324a2423f6d2315eed27445dfdcfe863e0b550
This commit is contained in:
reedip 2016-04-15 13:21:08 +09:00 committed by Reedip
parent 21ac9230e8
commit 45b026d7c8
5 changed files with 234 additions and 0 deletions

View File

@ -235,3 +235,41 @@ Display subnet details
.. describe:: <subnet>
Subnet to display (name or ID)
subnet unset
------------
Unset subnet properties
.. program:: subnet unset
.. code:: bash
os subnet unset
[--allocation-pool start=<ip-address>,end=<ip-address> [...]]
[--dns-nameserver <dns-nameserver> [...]]
[--host-route destination=<subnet>,gateway=<ip-address> [...]]
<subnet>
.. option:: --dns-nameserver <dns-nameserver>
DNS server to be removed from this subnet
(repeat option to unset multiple DNS servers)
.. option:: --allocation-pool start=<ip-address>,end=<ip-address>
Allocation pool to be removed from this subnet e.g.:
``start=192.168.199.2,end=192.168.199.254``
(repeat option to unset multiple Allocation pools)
.. option:: --host-route destination=<subnet>,gateway=<ip-address>
Route to be removed from this subnet e.g.:
``destination=10.10.0.0/16,gateway=192.168.71.254``
destination: destination subnet (in CIDR notation)
gateway: nexthop IP address
(repeat option to unset multiple host routes)
.. _subnet_unset-subnet:
.. describe:: <subnet>
subnet to modify (name or ID)

View File

@ -28,6 +28,11 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
def _update_arguments(obj_list, parsed_args_list):
for item in parsed_args_list:
obj_list.remove(item)
def _format_allocation_pools(data):
pool_formatted = ['%s-%s' % (pool.get('start', ''), pool.get('end', ''))
for pool in data]
@ -433,3 +438,81 @@ class ShowSubnet(command.ShowOne):
columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
return (columns, data)
class UnsetSubnet(command.Command):
"""Unset subnet properties"""
def get_parser(self, prog_name):
parser = super(UnsetSubnet, self).get_parser(prog_name)
parser.add_argument(
'--allocation-pool',
metavar='start=<ip-address>,end=<ip-address>',
dest='allocation_pools',
action=parseractions.MultiKeyValueAction,
required_keys=['start', 'end'],
help=_('Allocation pool to be removed from this subnet '
'e.g.: start=192.168.199.2,end=192.168.199.254 '
'(repeat option to unset multiple Allocation pools)')
)
parser.add_argument(
'--dns-nameserver',
metavar='<dns-nameserver>',
action='append',
dest='dns_nameservers',
help=_('DNS server to be removed from this subnet '
'(repeat option to set multiple DNS servers)')
)
parser.add_argument(
'--host-route',
metavar='destination=<subnet>,gateway=<ip-address>',
dest='host_routes',
action=parseractions.MultiKeyValueAction,
required_keys=['destination', 'gateway'],
help=_('Route to be removed from this subnet '
'e.g.: destination=10.10.0.0/16,gateway=192.168.71.254 '
'destination: destination subnet (in CIDR notation) '
'gateway: nexthop IP address '
'(repeat option to unset multiple host routes)')
)
parser.add_argument(
'subnet',
metavar="<subnet>",
help=_("Subnet to modify (name or ID)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.network
obj = client.find_subnet(parsed_args.subnet, ignore_missing=False)
tmp_obj = copy.deepcopy(obj)
attrs = {}
if parsed_args.dns_nameservers:
try:
_update_arguments(tmp_obj.dns_nameservers,
parsed_args.dns_nameservers)
except ValueError as error:
msg = (_("%s not in dns-nameservers") % str(error))
raise exceptions.CommandError(msg)
attrs['dns_nameservers'] = tmp_obj.dns_nameservers
if parsed_args.host_routes:
try:
_update_arguments(
tmp_obj.host_routes,
convert_entries_to_nexthop(parsed_args.host_routes))
except ValueError as error:
msg = (_("Subnet does not have %s in host-routes") %
str(error))
raise exceptions.CommandError(msg)
attrs['host_routes'] = tmp_obj.host_routes
if parsed_args.allocation_pools:
try:
_update_arguments(tmp_obj.allocation_pools,
parsed_args.allocation_pools)
except ValueError as error:
msg = (_("Subnet does not have %s in allocation-pools") %
str(error))
raise exceptions.CommandError(msg)
attrs['allocation_pools'] = tmp_obj.allocation_pools
if attrs:
client.update_subnet(obj, **attrs)

View File

@ -767,3 +767,109 @@ class TestShowSubnet(TestSubnet):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
class TestUnsetSubnet(TestSubnet):
def setUp(self):
super(TestUnsetSubnet, self).setUp()
self._testsubnet = network_fakes.FakeSubnet.create_one_subnet(
{'dns_nameservers': ['8.8.8.8',
'8.8.8.4'],
'host_routes': [{'destination': '10.20.20.0/24',
'nexthop': '10.20.20.1'},
{'destination': '10.30.30.30/24',
'nexthop': '10.30.30.1'}],
'allocation_pools': [{'start': '8.8.8.100',
'end': '8.8.8.150'},
{'start': '8.8.8.160',
'end': '8.8.8.170'}], })
self.network.find_subnet = mock.Mock(return_value=self._testsubnet)
self.network.update_subnet = mock.Mock(return_value=None)
# Get the command object to test
self.cmd = subnet_v2.UnsetSubnet(self.app, self.namespace)
def test_unset_subnet_params(self):
arglist = [
'--dns-nameserver', '8.8.8.8',
'--host-route', 'destination=10.30.30.30/24,gateway=10.30.30.1',
'--allocation-pool', 'start=8.8.8.100,end=8.8.8.150',
self._testsubnet.name,
]
verifylist = [
('dns_nameservers', ['8.8.8.8']),
('host_routes', [{
"destination": "10.30.30.30/24", "gateway": "10.30.30.1"}]),
('allocation_pools', [{
'start': '8.8.8.100', 'end': '8.8.8.150'}]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
attrs = {
'dns_nameservers': ['8.8.8.4'],
'host_routes': [{
"destination": "10.20.20.0/24", "nexthop": "10.20.20.1"}],
'allocation_pools': [{'start': '8.8.8.160', 'end': '8.8.8.170'}],
}
self.network.update_subnet.assert_called_once_with(
self._testsubnet, **attrs)
self.assertIsNone(result)
def test_unset_subnet_wrong_host_routes(self):
arglist = [
'--dns-nameserver', '8.8.8.8',
'--host-route', 'destination=10.30.30.30/24,gateway=10.30.30.2',
'--allocation-pool', 'start=8.8.8.100,end=8.8.8.150',
self._testsubnet.name,
]
verifylist = [
('dns_nameservers', ['8.8.8.8']),
('host_routes', [{
"destination": "10.30.30.30/24", "gateway": "10.30.30.2"}]),
('allocation_pools', [{
'start': '8.8.8.100', 'end': '8.8.8.150'}]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError,
self.cmd.take_action, parsed_args)
def test_unset_subnet_wrong_allocation_pool(self):
arglist = [
'--dns-nameserver', '8.8.8.8',
'--host-route', 'destination=10.30.30.30/24,gateway=10.30.30.1',
'--allocation-pool', 'start=8.8.8.100,end=8.8.8.156',
self._testsubnet.name,
]
verifylist = [
('dns_nameservers', ['8.8.8.8']),
('host_routes', [{
"destination": "10.30.30.30/24", "gateway": "10.30.30.1"}]),
('allocation_pools', [{
'start': '8.8.8.100', 'end': '8.8.8.156'}]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError,
self.cmd.take_action, parsed_args)
def test_unset_subnet_wrong_dns_nameservers(self):
arglist = [
'--dns-nameserver', '8.8.8.1',
'--host-route', 'destination=10.30.30.30/24,gateway=10.30.30.1',
'--allocation-pool', 'start=8.8.8.100,end=8.8.8.150',
self._testsubnet.name,
]
verifylist = [
('dns_nameservers', ['8.8.8.1']),
('host_routes', [{
"destination": "10.30.30.30/24", "gateway": "10.30.30.1"}]),
('allocation_pools', [{
'start': '8.8.8.100', 'end': '8.8.8.150'}]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError,
self.cmd.take_action, parsed_args)

View File

@ -0,0 +1,6 @@
---
features:
- |
Add a new command ``subnet unset`` to clear the information
of allocation-pools, host-routes or DNS servers from the subnet.
[ Blueprint `network-property-unset <https://blueprints.launchpad.net/python-openstackclient/+spec/network-property-unset>`_]

View File

@ -382,6 +382,7 @@ openstack.network.v2 =
subnet_list = openstackclient.network.v2.subnet:ListSubnet
subnet_set = openstackclient.network.v2.subnet:SetSubnet
subnet_show = openstackclient.network.v2.subnet:ShowSubnet
subnet_unset = openstackclient.network.v2.subnet:UnsetSubnet
subnet_pool_create = openstackclient.network.v2.subnet_pool:CreateSubnetPool
subnet_pool_delete = openstackclient.network.v2.subnet_pool:DeleteSubnetPool