[Subnet pool] Add 'subnet pool set' command support
This patch supports setting a new name, pool prefix, default prefix length, minimum prefix length, and maximum prefix length for a subnet pool. Change-Id: I65bd71e0f54f2f65acefbc542df67a1b1ec26397 Partial-Bug: #1544591 Related-to: blueprint neutron-client
This commit is contained in:
		| @@ -35,6 +35,48 @@ List subnet pools | |||||||
|  |  | ||||||
|     List additional fields in output |     List additional fields in output | ||||||
|  |  | ||||||
|  | subnet pool set | ||||||
|  | --------------- | ||||||
|  |  | ||||||
|  | Set subnet pool properties | ||||||
|  |  | ||||||
|  | .. program:: subnet pool set | ||||||
|  |    .. code:: bash | ||||||
|  |  | ||||||
|  |     os subnet pool set | ||||||
|  |         [--name <name>] | ||||||
|  |         [--pool-prefix <pool-prefix> [...]] | ||||||
|  |         [--default-prefix-length <default-prefix-length>] | ||||||
|  |         [--min-prefix-length <min-prefix-length>] | ||||||
|  |         [--max-prefix-length <max-prefix-length>] | ||||||
|  |         <subnet-pool> | ||||||
|  |  | ||||||
|  | .. option:: --name <name> | ||||||
|  |  | ||||||
|  |     Set subnet pool name | ||||||
|  |  | ||||||
|  | .. option:: --pool-prefix <pool-prefix> | ||||||
|  |  | ||||||
|  |     Set subnet pool prefixes (in CIDR notation). | ||||||
|  |     Repeat this option to set multiple prefixes. | ||||||
|  |  | ||||||
|  | .. option:: --default-prefix-length <default-prefix-length> | ||||||
|  |  | ||||||
|  |     Set subnet pool default prefix length | ||||||
|  |  | ||||||
|  | .. option:: --min-prefix-length <min-prefix-length> | ||||||
|  |  | ||||||
|  |     Set subnet pool minimum prefix length | ||||||
|  |  | ||||||
|  | .. option:: --max-prefix-length <max-prefix-length> | ||||||
|  |  | ||||||
|  |     Set subnet pool maximum prefix length | ||||||
|  |  | ||||||
|  | .. _subnet_pool_set-subnet-pool: | ||||||
|  |    .. describe:: <subnet-pool> | ||||||
|  |  | ||||||
|  |     Subnet pool to modify (name or ID) | ||||||
|  |  | ||||||
| subnet pool show | subnet pool show | ||||||
| ---------------- | ---------------- | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,6 +14,8 @@ | |||||||
| """Subnet pool action implementations""" | """Subnet pool action implementations""" | ||||||
|  |  | ||||||
| from openstackclient.common import command | from openstackclient.common import command | ||||||
|  | from openstackclient.common import exceptions | ||||||
|  | from openstackclient.common import parseractions | ||||||
| from openstackclient.common import utils | from openstackclient.common import utils | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -30,6 +32,51 @@ _formatters = { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _get_attrs(parsed_args): | ||||||
|  |     attrs = {} | ||||||
|  |     if parsed_args.name is not None: | ||||||
|  |         attrs['name'] = str(parsed_args.name) | ||||||
|  |     if parsed_args.prefixes is not None: | ||||||
|  |         attrs['prefixes'] = parsed_args.prefixes | ||||||
|  |     if parsed_args.default_prefix_length is not None: | ||||||
|  |         attrs['default_prefix_length'] = parsed_args.default_prefix_length | ||||||
|  |     if parsed_args.min_prefix_length is not None: | ||||||
|  |         attrs['min_prefix_length'] = parsed_args.min_prefix_length | ||||||
|  |     if parsed_args.max_prefix_length is not None: | ||||||
|  |         attrs['max_prefix_length'] = parsed_args.max_prefix_length | ||||||
|  |  | ||||||
|  |     return attrs | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _add_prefix_options(parser): | ||||||
|  |     parser.add_argument( | ||||||
|  |         '--pool-prefix', | ||||||
|  |         metavar='<pool-prefix>', | ||||||
|  |         dest='prefixes', | ||||||
|  |         action='append', | ||||||
|  |         help='Set subnet pool prefixes (in CIDR notation). ' | ||||||
|  |              'Repeat this option to set multiple prefixes.', | ||||||
|  |     ) | ||||||
|  |     parser.add_argument( | ||||||
|  |         '--default-prefix-length', | ||||||
|  |         metavar='<default-prefix-length>', | ||||||
|  |         action=parseractions.NonNegativeAction, | ||||||
|  |         help='Set subnet pool default prefix length', | ||||||
|  |     ) | ||||||
|  |     parser.add_argument( | ||||||
|  |         '--min-prefix-length', | ||||||
|  |         metavar='<min-prefix-length>', | ||||||
|  |         action=parseractions.NonNegativeAction, | ||||||
|  |         help='Set subnet pool minimum prefix length', | ||||||
|  |     ) | ||||||
|  |     parser.add_argument( | ||||||
|  |         '--max-prefix-length', | ||||||
|  |         metavar='<max-prefix-length>', | ||||||
|  |         action=parseractions.NonNegativeAction, | ||||||
|  |         help='Set subnet pool maximum prefix length', | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class DeleteSubnetPool(command.Command): | class DeleteSubnetPool(command.Command): | ||||||
|     """Delete subnet pool""" |     """Delete subnet pool""" | ||||||
|  |  | ||||||
| @@ -37,8 +84,8 @@ class DeleteSubnetPool(command.Command): | |||||||
|         parser = super(DeleteSubnetPool, self).get_parser(prog_name) |         parser = super(DeleteSubnetPool, self).get_parser(prog_name) | ||||||
|         parser.add_argument( |         parser.add_argument( | ||||||
|             'subnet_pool', |             'subnet_pool', | ||||||
|             metavar="<subnet-pool>", |             metavar='<subnet-pool>', | ||||||
|             help=("Subnet pool to delete (name or ID)") |             help='Subnet pool to delete (name or ID)' | ||||||
|         ) |         ) | ||||||
|         return parser |         return parser | ||||||
|  |  | ||||||
| @@ -98,6 +145,42 @@ class ListSubnetPool(command.Lister): | |||||||
|                 ) for s in data)) |                 ) for s in data)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class SetSubnetPool(command.Command): | ||||||
|  |     """Set subnet pool properties""" | ||||||
|  |  | ||||||
|  |     def get_parser(self, prog_name): | ||||||
|  |         parser = super(SetSubnetPool, self).get_parser(prog_name) | ||||||
|  |         parser.add_argument( | ||||||
|  |             'subnet_pool', | ||||||
|  |             metavar='<subnet-pool>', | ||||||
|  |             help='Subnet pool to modify (name or ID)' | ||||||
|  |         ) | ||||||
|  |         parser.add_argument( | ||||||
|  |             '--name', | ||||||
|  |             metavar='<name>', | ||||||
|  |             help='Set subnet pool name', | ||||||
|  |         ) | ||||||
|  |         _add_prefix_options(parser) | ||||||
|  |  | ||||||
|  |         return parser | ||||||
|  |  | ||||||
|  |     def take_action(self, parsed_args): | ||||||
|  |         client = self.app.client_manager.network | ||||||
|  |         obj = client.find_subnet_pool(parsed_args.subnet_pool, | ||||||
|  |                                       ignore_missing=False) | ||||||
|  |  | ||||||
|  |         attrs = _get_attrs(parsed_args) | ||||||
|  |         if attrs == {}: | ||||||
|  |             msg = "Nothing specified to be set" | ||||||
|  |             raise exceptions.CommandError(msg) | ||||||
|  |  | ||||||
|  |         # Existing prefixes must be a subset of the new prefixes. | ||||||
|  |         if 'prefixes' in attrs: | ||||||
|  |             attrs['prefixes'].extend(obj.prefixes) | ||||||
|  |  | ||||||
|  |         client.update_subnet_pool(obj, **attrs) | ||||||
|  |  | ||||||
|  |  | ||||||
| class ShowSubnetPool(command.ShowOne): | class ShowSubnetPool(command.ShowOne): | ||||||
|     """Display subnet pool details""" |     """Display subnet pool details""" | ||||||
|  |  | ||||||
| @@ -105,8 +188,8 @@ class ShowSubnetPool(command.ShowOne): | |||||||
|         parser = super(ShowSubnetPool, self).get_parser(prog_name) |         parser = super(ShowSubnetPool, self).get_parser(prog_name) | ||||||
|         parser.add_argument( |         parser.add_argument( | ||||||
|             'subnet_pool', |             'subnet_pool', | ||||||
|             metavar="<subnet-pool>", |             metavar='<subnet-pool>', | ||||||
|             help=("Subnet pool to display (name or ID)") |             help='Subnet pool to display (name or ID)' | ||||||
|         ) |         ) | ||||||
|         return parser |         return parser | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,8 +11,10 @@ | |||||||
| #   under the License. | #   under the License. | ||||||
| # | # | ||||||
|  |  | ||||||
|  | import argparse | ||||||
| import mock | import mock | ||||||
|  |  | ||||||
|  | from openstackclient.common import exceptions | ||||||
| from openstackclient.common import utils | from openstackclient.common import utils | ||||||
| from openstackclient.network.v2 import subnet_pool | from openstackclient.network.v2 import subnet_pool | ||||||
| from openstackclient.tests.network.v2 import fakes as network_fakes | from openstackclient.tests.network.v2 import fakes as network_fakes | ||||||
| @@ -129,6 +131,96 @@ class TestListSubnetPool(TestSubnetPool): | |||||||
|         self.assertEqual(self.data_long, list(data)) |         self.assertEqual(self.data_long, list(data)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestSetSubnetPool(TestSubnetPool): | ||||||
|  |  | ||||||
|  |     # The subnet_pool to set. | ||||||
|  |     _subnet_pool = network_fakes.FakeSubnetPool.create_one_subnet_pool() | ||||||
|  |  | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestSetSubnetPool, self).setUp() | ||||||
|  |  | ||||||
|  |         self.network.update_subnet_pool = mock.Mock(return_value=None) | ||||||
|  |  | ||||||
|  |         self.network.find_subnet_pool = mock.Mock( | ||||||
|  |             return_value=self._subnet_pool) | ||||||
|  |  | ||||||
|  |         # Get the command object to test | ||||||
|  |         self.cmd = subnet_pool.SetSubnetPool(self.app, self.namespace) | ||||||
|  |  | ||||||
|  |     def test_set_this(self): | ||||||
|  |         arglist = [ | ||||||
|  |             self._subnet_pool.name, | ||||||
|  |             '--name', 'noob', | ||||||
|  |             '--default-prefix-length', '8', | ||||||
|  |             '--min-prefix-length', '8', | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('subnet_pool', self._subnet_pool.name), | ||||||
|  |             ('name', 'noob'), | ||||||
|  |             ('default_prefix_length', '8'), | ||||||
|  |             ('min_prefix_length', '8'), | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         result = self.cmd.take_action(parsed_args) | ||||||
|  |  | ||||||
|  |         attrs = { | ||||||
|  |             'name': 'noob', | ||||||
|  |             'default_prefix_length': '8', | ||||||
|  |             'min_prefix_length': '8', | ||||||
|  |         } | ||||||
|  |         self.network.update_subnet_pool.assert_called_with( | ||||||
|  |             self._subnet_pool, **attrs) | ||||||
|  |         self.assertIsNone(result) | ||||||
|  |  | ||||||
|  |     def test_set_that(self): | ||||||
|  |         arglist = [ | ||||||
|  |             self._subnet_pool.name, | ||||||
|  |             '--pool-prefix', '10.0.1.0/24', | ||||||
|  |             '--pool-prefix', '10.0.2.0/24', | ||||||
|  |             '--max-prefix-length', '16', | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('subnet_pool', self._subnet_pool.name), | ||||||
|  |             ('prefixes', ['10.0.1.0/24', '10.0.2.0/24']), | ||||||
|  |             ('max_prefix_length', '16'), | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         result = self.cmd.take_action(parsed_args) | ||||||
|  |  | ||||||
|  |         prefixes = ['10.0.1.0/24', '10.0.2.0/24'] | ||||||
|  |         prefixes.extend(self._subnet_pool.prefixes) | ||||||
|  |         attrs = { | ||||||
|  |             'prefixes': prefixes, | ||||||
|  |             'max_prefix_length': '16', | ||||||
|  |         } | ||||||
|  |         self.network.update_subnet_pool.assert_called_with( | ||||||
|  |             self._subnet_pool, **attrs) | ||||||
|  |         self.assertIsNone(result) | ||||||
|  |  | ||||||
|  |     def test_set_nothing(self): | ||||||
|  |         arglist = [self._subnet_pool.name, ] | ||||||
|  |         verifylist = [('subnet_pool', self._subnet_pool.name), ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         self.assertRaises(exceptions.CommandError, self.cmd.take_action, | ||||||
|  |                           parsed_args) | ||||||
|  |  | ||||||
|  |     def test_set_len_negative(self): | ||||||
|  |         arglist = [ | ||||||
|  |             self._subnet_pool.name, | ||||||
|  |             '--max-prefix-length', '-16', | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('subnet_pool', self._subnet_pool.name), | ||||||
|  |             ('max_prefix_length', '-16'), | ||||||
|  |         ] | ||||||
|  |  | ||||||
|  |         self.assertRaises(argparse.ArgumentTypeError, self.check_parser, | ||||||
|  |                           self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestShowSubnetPool(TestSubnetPool): | class TestShowSubnetPool(TestSubnetPool): | ||||||
|  |  | ||||||
|     # The subnet_pool to set. |     # The subnet_pool to set. | ||||||
| @@ -189,14 +281,13 @@ class TestShowSubnetPool(TestSubnetPool): | |||||||
|         verifylist = [ |         verifylist = [ | ||||||
|             ('subnet_pool', self._subnet_pool.name), |             ('subnet_pool', self._subnet_pool.name), | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|         columns, data = self.cmd.take_action(parsed_args) |         columns, data = self.cmd.take_action(parsed_args) | ||||||
|  |  | ||||||
|         self.network.find_subnet_pool.assert_called_with( |         self.network.find_subnet_pool.assert_called_with( | ||||||
|             self._subnet_pool.name, |             self._subnet_pool.name, | ||||||
|             ignore_missing=False |             ignore_missing=False | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.assertEqual(self.columns, columns) |         self.assertEqual(self.columns, columns) | ||||||
|         self.assertEqual(self.data, data) |         self.assertEqual(self.data, data) | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								releasenotes/notes/bug-1544591-267fd16cc5efffe6.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								releasenotes/notes/bug-1544591-267fd16cc5efffe6.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | --- | ||||||
|  | features: | ||||||
|  |   - Add ``subnet pool set`` command. | ||||||
|  |     [Bug `1544591 <https://bugs.launchpad.net/python-openstackclient/+bug/1544591>`_] | ||||||
| @@ -356,6 +356,7 @@ openstack.network.v2 = | |||||||
|  |  | ||||||
|     subnet_pool_delete = openstackclient.network.v2.subnet_pool:DeleteSubnetPool |     subnet_pool_delete = openstackclient.network.v2.subnet_pool:DeleteSubnetPool | ||||||
|     subnet_pool_list = openstackclient.network.v2.subnet_pool:ListSubnetPool |     subnet_pool_list = openstackclient.network.v2.subnet_pool:ListSubnetPool | ||||||
|  |     subnet_pool_set = openstackclient.network.v2.subnet_pool:SetSubnetPool | ||||||
|     subnet_pool_show = openstackclient.network.v2.subnet_pool:ShowSubnetPool |     subnet_pool_show = openstackclient.network.v2.subnet_pool:ShowSubnetPool | ||||||
|  |  | ||||||
| openstack.object_store.v1 = | openstack.object_store.v1 = | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Tang Chen
					Tang Chen