summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorHuanxuan Ao <huanxuan.ao@easystack.cn>2016-06-16 13:09:27 +0800
committerSteve Martinelli <s.martinelli@gmail.com>2016-06-16 12:46:32 +0000
commit041ea4978b94149d5037b5afc7743db939b75331 (patch)
tree4565fc45b7ded8a2033dcad7a160de3802424562 /openstackclient
parent114eeeb0236d29a325abbf13b41a9a385746b367 (diff)
downloadpython-openstackclient-041ea4978b94149d5037b5afc7743db939b75331.tar.gz
Support bulk deletion for delete commands in networkv2
This patch support bulk deletion for delete commands below: 1.subnet delete 2.subnet pool delete Up to now, all the delete commands in networkv2 support bulk deletion. Change-Id: I63f6d1d02bad1fcc26e72b7028b53958a68ce2dc Partially-Implements: blueprint multi-argument-network Partial-Bug: #1592906
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/network/v2/subnet.py28
-rw-r--r--openstackclient/network/v2/subnet_pool.py30
-rw-r--r--openstackclient/tests/network/v2/fakes.py38
-rw-r--r--openstackclient/tests/network/v2/test_subnet.py66
-rw-r--r--openstackclient/tests/network/v2/test_subnet_pool.py67
5 files changed, 206 insertions, 23 deletions
diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py
index ceb1cb14..a2e32622 100644
--- a/openstackclient/network/v2/subnet.py
+++ b/openstackclient/network/v2/subnet.py
@@ -14,6 +14,7 @@
"""Subnet action implementations"""
import copy
+import logging
from osc_lib.cli import parseractions
from osc_lib.command import command
@@ -24,6 +25,9 @@ from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
+LOG = logging.getLogger(__name__)
+
+
def _format_allocation_pools(data):
pool_formatted = ['%s-%s' % (pool.get('start', ''), pool.get('end', ''))
for pool in data]
@@ -270,21 +274,37 @@ class CreateSubnet(command.ShowOne):
class DeleteSubnet(command.Command):
- """Delete subnet"""
+ """Delete subnet(s)"""
def get_parser(self, prog_name):
parser = super(DeleteSubnet, self).get_parser(prog_name)
parser.add_argument(
'subnet',
metavar="<subnet>",
- help=_("Subnet to delete (name or ID)")
+ nargs='+',
+ help=_("Subnet(s) to delete (name or ID)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.network
- client.delete_subnet(
- client.find_subnet(parsed_args.subnet))
+ result = 0
+
+ for subnet in parsed_args.subnet:
+ try:
+ obj = client.find_subnet(subnet, ignore_missing=False)
+ client.delete_subnet(obj)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete subnet with "
+ "name or ID '%(subnet)s': %(e)s")
+ % {'subnet': subnet, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.subnet)
+ msg = (_("%(result)s of %(total)s subnets failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
class ListSubnet(command.Lister):
diff --git a/openstackclient/network/v2/subnet_pool.py b/openstackclient/network/v2/subnet_pool.py
index 79f98fd9..55dfed83 100644
--- a/openstackclient/network/v2/subnet_pool.py
+++ b/openstackclient/network/v2/subnet_pool.py
@@ -13,14 +13,20 @@
"""Subnet pool action implementations"""
+import logging
+
from osc_lib.cli import parseractions
from osc_lib.command import command
+from osc_lib import exceptions
from osc_lib import utils
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
+LOG = logging.getLogger(__name__)
+
+
def _get_columns(item):
columns = list(item.keys())
if 'tenant_id' in columns:
@@ -176,21 +182,37 @@ class CreateSubnetPool(command.ShowOne):
class DeleteSubnetPool(command.Command):
- """Delete subnet pool"""
+ """Delete subnet pool(s)"""
def get_parser(self, prog_name):
parser = super(DeleteSubnetPool, self).get_parser(prog_name)
parser.add_argument(
'subnet_pool',
metavar='<subnet-pool>',
- help=_("Subnet pool to delete (name or ID)")
+ nargs='+',
+ help=_("Subnet pool(s) to delete (name or ID)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.network
- obj = client.find_subnet_pool(parsed_args.subnet_pool)
- client.delete_subnet_pool(obj)
+ result = 0
+
+ for pool in parsed_args.subnet_pool:
+ try:
+ obj = client.find_subnet_pool(pool, ignore_missing=False)
+ client.delete_subnet_pool(obj)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete subnet pool with "
+ "name or ID '%(pool)s': %(e)s")
+ % {'pool': pool, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.subnet_pool)
+ msg = (_("%(result)s of %(total)s subnet pools failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
class ListSubnetPool(command.Lister):
diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py
index 6b09e297..a23efc2d 100644
--- a/openstackclient/tests/network/v2/fakes.py
+++ b/openstackclient/tests/network/v2/fakes.py
@@ -771,6 +771,25 @@ class FakeSubnet(object):
return subnets
+ @staticmethod
+ def get_subnets(subnets=None, count=2):
+ """Get an iterable MagicMock object with a list of faked subnets.
+
+ If subnets list is provided, then initialize the Mock object
+ with the list. Otherwise create one.
+
+ :param List subnets:
+ A list of FakeResource objects faking subnets
+ :param int count:
+ The number of subnets to fake
+ :return:
+ An iterable Mock object with side_effect set to a list of faked
+ subnets
+ """
+ if subnets is None:
+ subnets = FakeSubnet.create_subnets(count)
+ return mock.MagicMock(side_effect=subnets)
+
class FakeFloatingIP(object):
"""Fake one or more floating ip."""
@@ -910,3 +929,22 @@ class FakeSubnetPool(object):
)
return subnet_pools
+
+ @staticmethod
+ def get_subnet_pools(subnet_pools=None, count=2):
+ """Get an iterable MagicMock object with a list of faked subnet pools.
+
+ If subnet_pools list is provided, then initialize the Mock object
+ with the list. Otherwise create one.
+
+ :param List subnet pools:
+ A list of FakeResource objects faking subnet pools
+ :param int count:
+ The number of subnet pools to fake
+ :return:
+ An iterable Mock object with side_effect set to a list of faked
+ subnet pools
+ """
+ if subnet_pools is None:
+ subnet_pools = FakeSubnetPool.create_subnet_pools(count)
+ return mock.MagicMock(side_effect=subnet_pools)
diff --git a/openstackclient/tests/network/v2/test_subnet.py b/openstackclient/tests/network/v2/test_subnet.py
index de7e1821..a57a0308 100644
--- a/openstackclient/tests/network/v2/test_subnet.py
+++ b/openstackclient/tests/network/v2/test_subnet.py
@@ -13,7 +13,9 @@
import copy
import mock
+from mock import call
+from osc_lib import exceptions
from osc_lib import utils
from openstackclient.network.v2 import subnet as subnet_v2
@@ -361,32 +363,82 @@ class TestCreateSubnet(TestSubnet):
class TestDeleteSubnet(TestSubnet):
- # The subnet to delete.
- _subnet = network_fakes.FakeSubnet.create_one_subnet()
+ # The subnets to delete.
+ _subnets = network_fakes.FakeSubnet.create_subnets(count=2)
def setUp(self):
super(TestDeleteSubnet, self).setUp()
self.network.delete_subnet = mock.Mock(return_value=None)
- self.network.find_subnet = mock.Mock(return_value=self._subnet)
+ self.network.find_subnet = (
+ network_fakes.FakeSubnet.get_subnets(self._subnets))
# Get the command object to test
self.cmd = subnet_v2.DeleteSubnet(self.app, self.namespace)
- def test_delete(self):
+ def test_subnet_delete(self):
arglist = [
- self._subnet.name,
+ self._subnets[0].name,
]
verifylist = [
- ('subnet', self._subnet.name),
+ ('subnet', [self._subnets[0].name]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.network.delete_subnet.assert_called_once_with(self._subnet)
+ self.network.delete_subnet.assert_called_once_with(self._subnets[0])
self.assertIsNone(result)
+ def test_multi_subnets_delete(self):
+ arglist = []
+ verifylist = []
+
+ for s in self._subnets:
+ arglist.append(s.name)
+ verifylist = [
+ ('subnet', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for s in self._subnets:
+ calls.append(call(s))
+ self.network.delete_subnet.assert_has_calls(calls)
+ self.assertIsNone(result)
+
+ def test_multi_subnets_delete_with_exception(self):
+ arglist = [
+ self._subnets[0].name,
+ 'unexist_subnet',
+ ]
+ verifylist = [
+ ('subnet',
+ [self._subnets[0].name, 'unexist_subnet']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self._subnets[0], exceptions.CommandError]
+ self.network.find_subnet = (
+ mock.MagicMock(side_effect=find_mock_result)
+ )
+
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 subnets failed to delete.', str(e))
+
+ self.network.find_subnet.assert_any_call(
+ self._subnets[0].name, ignore_missing=False)
+ self.network.find_subnet.assert_any_call(
+ 'unexist_subnet', ignore_missing=False)
+ self.network.delete_subnet.assert_called_once_with(
+ self._subnets[0]
+ )
+
class TestListSubnet(TestSubnet):
# The subnets going to be listed up.
diff --git a/openstackclient/tests/network/v2/test_subnet_pool.py b/openstackclient/tests/network/v2/test_subnet_pool.py
index 10ef76d8..7a96b30f 100644
--- a/openstackclient/tests/network/v2/test_subnet_pool.py
+++ b/openstackclient/tests/network/v2/test_subnet_pool.py
@@ -14,7 +14,9 @@
import argparse
import copy
import mock
+from mock import call
+from osc_lib import exceptions
from osc_lib import utils
from openstackclient.network.v2 import subnet_pool
@@ -263,36 +265,85 @@ class TestCreateSubnetPool(TestSubnetPool):
class TestDeleteSubnetPool(TestSubnetPool):
- # The subnet pool to delete.
- _subnet_pool = network_fakes.FakeSubnetPool.create_one_subnet_pool()
+ # The subnet pools to delete.
+ _subnet_pools = network_fakes.FakeSubnetPool.create_subnet_pools(count=2)
def setUp(self):
super(TestDeleteSubnetPool, self).setUp()
self.network.delete_subnet_pool = mock.Mock(return_value=None)
- self.network.find_subnet_pool = mock.Mock(
- return_value=self._subnet_pool
+ self.network.find_subnet_pool = (
+ network_fakes.FakeSubnetPool.get_subnet_pools(self._subnet_pools)
)
# Get the command object to test
self.cmd = subnet_pool.DeleteSubnetPool(self.app, self.namespace)
- def test_delete(self):
+ def test_subnet_pool_delete(self):
arglist = [
- self._subnet_pool.name,
+ self._subnet_pools[0].name,
]
verifylist = [
- ('subnet_pool', self._subnet_pool.name),
+ ('subnet_pool', [self._subnet_pools[0].name]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.network.delete_subnet_pool.assert_called_once_with(
- self._subnet_pool)
+ self._subnet_pools[0])
+ self.assertIsNone(result)
+
+ def test_multi_subnet_pools_delete(self):
+ arglist = []
+ verifylist = []
+
+ for s in self._subnet_pools:
+ arglist.append(s.name)
+ verifylist = [
+ ('subnet_pool', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ calls = []
+ for s in self._subnet_pools:
+ calls.append(call(s))
+ self.network.delete_subnet_pool.assert_has_calls(calls)
self.assertIsNone(result)
+ def test_multi_subnet_pools_delete_with_exception(self):
+ arglist = [
+ self._subnet_pools[0].name,
+ 'unexist_subnet_pool',
+ ]
+ verifylist = [
+ ('subnet_pool',
+ [self._subnet_pools[0].name, 'unexist_subnet_pool']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ find_mock_result = [self._subnet_pools[0], exceptions.CommandError]
+ self.network.find_subnet_pool = (
+ mock.MagicMock(side_effect=find_mock_result)
+ )
+
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('1 of 2 subnet pools failed to delete.', str(e))
+
+ self.network.find_subnet_pool.assert_any_call(
+ self._subnet_pools[0].name, ignore_missing=False)
+ self.network.find_subnet_pool.assert_any_call(
+ 'unexist_subnet_pool', ignore_missing=False)
+ self.network.delete_subnet_pool.assert_called_once_with(
+ self._subnet_pools[0]
+ )
+
class TestListSubnetPool(TestSubnetPool):
# The subnet pools going to be listed up.