Add Neutron subnetpool API
Add Neutron subnetpool listing, creating, updating, showing and deleting Client API. neutron subnetpool-list neutron subnetpool-create neutron subnetpool-update neutron subnetpool-show neutron subnetpool-delete Change-Id: I19a6782d33609609f43353df8293864e60ead817 Partially-Implements: blueprint subnet-allocation
This commit is contained in:
parent
d6cfd34e13
commit
b978f90901
@ -36,6 +36,7 @@ TYPE_DICT = "dict"
|
|||||||
PLURALS = {'networks': 'network',
|
PLURALS = {'networks': 'network',
|
||||||
'ports': 'port',
|
'ports': 'port',
|
||||||
'subnets': 'subnet',
|
'subnets': 'subnet',
|
||||||
|
'subnetpools': 'subnetpool',
|
||||||
'dns_nameservers': 'dns_nameserver',
|
'dns_nameservers': 'dns_nameserver',
|
||||||
'host_routes': 'host_route',
|
'host_routes': 'host_route',
|
||||||
'allocation_pools': 'allocation_pool',
|
'allocation_pools': 'allocation_pool',
|
||||||
|
101
neutronclient/neutron/v2_0/subnetpool.py
Normal file
101
neutronclient/neutron/v2_0/subnetpool.py
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# Copyright 2015 OpenStack Foundation.
|
||||||
|
# All Rights Reserved
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
from neutronclient.i18n import _
|
||||||
|
from neutronclient.neutron import v2_0 as neutronV20
|
||||||
|
|
||||||
|
|
||||||
|
def add_updatable_arguments(parser):
|
||||||
|
parser.add_argument(
|
||||||
|
'--min-prefixlen', type=int,
|
||||||
|
help=_('Subnetpool minimum prefix length.'))
|
||||||
|
parser.add_argument(
|
||||||
|
'--max-prefixlen', type=int,
|
||||||
|
help=_('Subnetpool maximum prefix length.'))
|
||||||
|
parser.add_argument(
|
||||||
|
'--default-prefixlen', type=int,
|
||||||
|
help=_('Subnetpool default prefix length.'))
|
||||||
|
parser.add_argument(
|
||||||
|
'--pool-prefix',
|
||||||
|
action='append', dest='prefixes',
|
||||||
|
help=_('Subnetpool prefixes (This option can be repeated).'))
|
||||||
|
|
||||||
|
|
||||||
|
def updatable_args2body(parsed_args, body, for_create=True):
|
||||||
|
neutronV20.update_dict(parsed_args, body['subnetpool'],
|
||||||
|
['name', 'prefixes', 'default_prefixlen',
|
||||||
|
'min_prefixlen', 'max_prefixlen'])
|
||||||
|
|
||||||
|
|
||||||
|
class ListSubnetPool(neutronV20.ListCommand):
|
||||||
|
"""List subnetpools that belong to a given tenant."""
|
||||||
|
|
||||||
|
resource = 'subnetpool'
|
||||||
|
list_columns = ['id', 'name', 'prefixes',
|
||||||
|
'default_prefixlen']
|
||||||
|
pagination_support = True
|
||||||
|
sorting_support = True
|
||||||
|
|
||||||
|
|
||||||
|
class ShowSubnetPool(neutronV20.ShowCommand):
|
||||||
|
"""Show information of a given subnetpool."""
|
||||||
|
|
||||||
|
resource = 'subnetpool'
|
||||||
|
|
||||||
|
|
||||||
|
class CreateSubnetPool(neutronV20.CreateCommand):
|
||||||
|
"""Create a subnetpool for a given tenant."""
|
||||||
|
|
||||||
|
resource = 'subnetpool'
|
||||||
|
|
||||||
|
def add_known_arguments(self, parser):
|
||||||
|
add_updatable_arguments(parser)
|
||||||
|
parser.add_argument(
|
||||||
|
'--shared',
|
||||||
|
action='store_true',
|
||||||
|
help=_('Set the subnetpool as shared.'))
|
||||||
|
parser.add_argument(
|
||||||
|
'name',
|
||||||
|
help=_('Name of subnetpool to create.'))
|
||||||
|
|
||||||
|
def args2body(self, parsed_args):
|
||||||
|
body = {'subnetpool': {'prefixes': parsed_args.prefixes}}
|
||||||
|
updatable_args2body(parsed_args, body)
|
||||||
|
if parsed_args.shared:
|
||||||
|
body['subnetpool']['shared'] = True
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteSubnetPool(neutronV20.DeleteCommand):
|
||||||
|
"""Delete a given subnetpool."""
|
||||||
|
|
||||||
|
resource = 'subnetpool'
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateSubnetPool(neutronV20.UpdateCommand):
|
||||||
|
"""Update subnetpool's information."""
|
||||||
|
|
||||||
|
resource = 'subnetpool'
|
||||||
|
|
||||||
|
def add_known_arguments(self, parser):
|
||||||
|
add_updatable_arguments(parser)
|
||||||
|
parser.add_argument('--name',
|
||||||
|
help=_('Name of subnetpool to update.'))
|
||||||
|
|
||||||
|
def args2body(self, parsed_args):
|
||||||
|
body = {'subnetpool': {}}
|
||||||
|
updatable_args2body(parsed_args, body, for_create=False)
|
||||||
|
return body
|
@ -76,6 +76,7 @@ from neutronclient.neutron.v2_0 import router
|
|||||||
from neutronclient.neutron.v2_0 import securitygroup
|
from neutronclient.neutron.v2_0 import securitygroup
|
||||||
from neutronclient.neutron.v2_0 import servicetype
|
from neutronclient.neutron.v2_0 import servicetype
|
||||||
from neutronclient.neutron.v2_0 import subnet
|
from neutronclient.neutron.v2_0 import subnet
|
||||||
|
from neutronclient.neutron.v2_0 import subnetpool
|
||||||
from neutronclient.neutron.v2_0.vpn import ikepolicy
|
from neutronclient.neutron.v2_0.vpn import ikepolicy
|
||||||
from neutronclient.neutron.v2_0.vpn import ipsec_site_connection
|
from neutronclient.neutron.v2_0.vpn import ipsec_site_connection
|
||||||
from neutronclient.neutron.v2_0.vpn import ipsecpolicy
|
from neutronclient.neutron.v2_0.vpn import ipsecpolicy
|
||||||
@ -142,6 +143,11 @@ COMMAND_V2 = {
|
|||||||
'subnet-create': subnet.CreateSubnet,
|
'subnet-create': subnet.CreateSubnet,
|
||||||
'subnet-delete': subnet.DeleteSubnet,
|
'subnet-delete': subnet.DeleteSubnet,
|
||||||
'subnet-update': subnet.UpdateSubnet,
|
'subnet-update': subnet.UpdateSubnet,
|
||||||
|
'subnetpool-list': subnetpool.ListSubnetPool,
|
||||||
|
'subnetpool-show': subnetpool.ShowSubnetPool,
|
||||||
|
'subnetpool-create': subnetpool.CreateSubnetPool,
|
||||||
|
'subnetpool-delete': subnetpool.DeleteSubnetPool,
|
||||||
|
'subnetpool-update': subnetpool.UpdateSubnetPool,
|
||||||
'port-list': port.ListPort,
|
'port-list': port.ListPort,
|
||||||
'port-show': port.ShowPort,
|
'port-show': port.ShowPort,
|
||||||
'port-create': port.CreatePort,
|
'port-create': port.CreatePort,
|
||||||
|
@ -222,7 +222,7 @@ class CLITestV20Base(base.BaseTestCase):
|
|||||||
'policy_profile', 'ikepolicy',
|
'policy_profile', 'ikepolicy',
|
||||||
'ipsecpolicy', 'metering_label',
|
'ipsecpolicy', 'metering_label',
|
||||||
'metering_label_rule', 'net_partition',
|
'metering_label_rule', 'net_partition',
|
||||||
'fox_socket']
|
'fox_socket', 'subnetpool']
|
||||||
if not cmd_resource:
|
if not cmd_resource:
|
||||||
cmd_resource = resource
|
cmd_resource = resource
|
||||||
if (resource in non_admin_status_resources):
|
if (resource in non_admin_status_resources):
|
||||||
|
132
neutronclient/tests/unit/test_cli20_subnetpool.py
Normal file
132
neutronclient/tests/unit/test_cli20_subnetpool.py
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
# Copyright 2015 OpenStack Foundation.
|
||||||
|
# All Rights Reserved
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from mox3 import mox
|
||||||
|
|
||||||
|
from neutronclient.common import exceptions
|
||||||
|
from neutronclient.neutron.v2_0 import subnetpool
|
||||||
|
from neutronclient.tests.unit import test_cli20
|
||||||
|
|
||||||
|
|
||||||
|
class CLITestV20SubnetPoolJSON(test_cli20.CLITestV20Base):
|
||||||
|
def setUp(self):
|
||||||
|
super(CLITestV20SubnetPoolJSON, self).setUp(plurals={'tags': 'tag'})
|
||||||
|
|
||||||
|
def test_create_subnetpool_shared(self):
|
||||||
|
"""Create subnetpool: myname."""
|
||||||
|
resource = 'subnetpool'
|
||||||
|
cmd = subnetpool.CreateSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
name = 'myname'
|
||||||
|
myid = 'myid'
|
||||||
|
min_prefixlen = 30
|
||||||
|
prefix1 = '10.11.12.0/24'
|
||||||
|
prefix2 = '12.11.13.0/24'
|
||||||
|
args = [name, '--min-prefixlen', str(min_prefixlen),
|
||||||
|
'--pool-prefix', prefix1, '--pool-prefix', prefix2,
|
||||||
|
'--shared']
|
||||||
|
position_names = ['name', 'min_prefixlen', 'prefixes', 'shared']
|
||||||
|
position_values = [name, min_prefixlen, [prefix1, prefix2], True]
|
||||||
|
self._test_create_resource(resource, cmd, name, myid, args,
|
||||||
|
position_names, position_values)
|
||||||
|
|
||||||
|
def test_create_subnetpool_not_shared(self):
|
||||||
|
"""Create subnetpool: myname."""
|
||||||
|
resource = 'subnetpool'
|
||||||
|
cmd = subnetpool.CreateSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
name = 'myname'
|
||||||
|
myid = 'myid'
|
||||||
|
min_prefixlen = 30
|
||||||
|
prefix1 = '10.11.12.0/24'
|
||||||
|
prefix2 = '12.11.13.0/24'
|
||||||
|
args = [name, '--min-prefixlen', str(min_prefixlen),
|
||||||
|
'--pool-prefix', prefix1, '--pool-prefix', prefix2]
|
||||||
|
position_names = ['name', 'min_prefixlen', 'prefixes']
|
||||||
|
position_values = [name, min_prefixlen, [prefix1, prefix2]]
|
||||||
|
self._test_create_resource(resource, cmd, name, myid, args,
|
||||||
|
position_names, position_values)
|
||||||
|
|
||||||
|
def test_create_subnetpool_with_unicode(self):
|
||||||
|
"""Create subnetpool: u'\u7f51\u7edc'."""
|
||||||
|
resource = 'subnetpool'
|
||||||
|
cmd = subnetpool.CreateSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
name = u'\u7f51\u7edc'
|
||||||
|
myid = 'myid'
|
||||||
|
min_prefixlen = 30
|
||||||
|
prefixes = '10.11.12.0/24'
|
||||||
|
args = [name, '--min-prefixlen', str(min_prefixlen),
|
||||||
|
'--pool-prefix', prefixes]
|
||||||
|
position_names = ['name', 'min_prefixlen', 'prefixes']
|
||||||
|
position_values = [name, min_prefixlen, [prefixes]]
|
||||||
|
self._test_create_resource(resource, cmd, name, myid, args,
|
||||||
|
position_names, position_values)
|
||||||
|
|
||||||
|
def test_list_subnetpool_pagination(self):
|
||||||
|
cmd = subnetpool.ListSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
self.mox.StubOutWithMock(subnetpool.ListSubnetPool, "extend_list")
|
||||||
|
subnetpool.ListSubnetPool.extend_list(mox.IsA(list), mox.IgnoreArg())
|
||||||
|
self._test_list_resources_with_pagination("subnetpools", cmd)
|
||||||
|
self.mox.VerifyAll()
|
||||||
|
self.mox.UnsetStubs()
|
||||||
|
|
||||||
|
def test_list_subnetpools_sort(self):
|
||||||
|
"""List subnetpools: --sort-key name --sort-key id --sort-key asc
|
||||||
|
--sort-key desc
|
||||||
|
"""
|
||||||
|
resources = "subnetpools"
|
||||||
|
cmd = subnetpool.ListSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
self._test_list_resources(resources, cmd,
|
||||||
|
sort_key=["name", "id"],
|
||||||
|
sort_dir=["asc", "desc"])
|
||||||
|
|
||||||
|
def test_list_subnetpools_limit(self):
|
||||||
|
"""List subnetpools: -P."""
|
||||||
|
resources = "subnetpools"
|
||||||
|
cmd = subnetpool.ListSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
self._test_list_resources(resources, cmd, page_size=1000)
|
||||||
|
|
||||||
|
def test_update_subnetpool_exception(self):
|
||||||
|
"""Update subnetpool: myid."""
|
||||||
|
resource = 'subnetpool'
|
||||||
|
cmd = subnetpool.UpdateSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
self.assertRaises(exceptions.CommandError, self._test_update_resource,
|
||||||
|
resource, cmd, 'myid', ['myid'], {})
|
||||||
|
|
||||||
|
def test_update_subnetpool(self):
|
||||||
|
"""Update subnetpool: myid --name myname."""
|
||||||
|
resource = 'subnetpool'
|
||||||
|
cmd = subnetpool.UpdateSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
self._test_update_resource(resource, cmd, 'myid',
|
||||||
|
['myid', '--name', 'myname'],
|
||||||
|
{'name': 'myname'}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_show_subnetpool(self):
|
||||||
|
"""Show subnetpool: --fields id --fields name myid."""
|
||||||
|
resource = 'subnetpool'
|
||||||
|
cmd = subnetpool.ShowSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
args = ['--fields', 'id', '--fields', 'name', self.test_id]
|
||||||
|
self._test_show_resource(resource, cmd, self.test_id, args,
|
||||||
|
['id', 'name'])
|
||||||
|
|
||||||
|
def test_delete_subnetpool(self):
|
||||||
|
"""Delete subnetpool: subnetpoolid."""
|
||||||
|
resource = 'subnetpool'
|
||||||
|
cmd = subnetpool.DeleteSubnetPool(test_cli20.MyApp(sys.stdout), None)
|
||||||
|
myid = 'myid'
|
||||||
|
args = [myid]
|
||||||
|
self._test_delete_resource(resource, cmd, myid, args)
|
@ -339,6 +339,8 @@ class Client(ClientBase):
|
|||||||
port_path = "/ports/%s"
|
port_path = "/ports/%s"
|
||||||
subnets_path = "/subnets"
|
subnets_path = "/subnets"
|
||||||
subnet_path = "/subnets/%s"
|
subnet_path = "/subnets/%s"
|
||||||
|
subnetpools_path = "/subnetpools"
|
||||||
|
subnetpool_path = "/subnetpools/%s"
|
||||||
quotas_path = "/quotas"
|
quotas_path = "/quotas"
|
||||||
quota_path = "/quotas/%s"
|
quota_path = "/quotas/%s"
|
||||||
extensions_path = "/extensions"
|
extensions_path = "/extensions"
|
||||||
@ -604,6 +606,32 @@ class Client(ClientBase):
|
|||||||
"""Deletes the specified subnet."""
|
"""Deletes the specified subnet."""
|
||||||
return self.delete(self.subnet_path % (subnet))
|
return self.delete(self.subnet_path % (subnet))
|
||||||
|
|
||||||
|
@APIParamsCall
|
||||||
|
def list_subnetpools(self, retrieve_all=True, **_params):
|
||||||
|
"""Fetches a list of all subnetpools for a tenant."""
|
||||||
|
return self.list('subnetpools', self.subnetpools_path, retrieve_all,
|
||||||
|
**_params)
|
||||||
|
|
||||||
|
@APIParamsCall
|
||||||
|
def show_subnetpool(self, subnetpool, **_params):
|
||||||
|
"""Fetches information of a certain subnetpool."""
|
||||||
|
return self.get(self.subnetpool_path % (subnetpool), params=_params)
|
||||||
|
|
||||||
|
@APIParamsCall
|
||||||
|
def create_subnetpool(self, body=None):
|
||||||
|
"""Creates a new subnetpool."""
|
||||||
|
return self.post(self.subnetpools_path, body=body)
|
||||||
|
|
||||||
|
@APIParamsCall
|
||||||
|
def update_subnetpool(self, subnetpool, body=None):
|
||||||
|
"""Updates a subnetpool."""
|
||||||
|
return self.put(self.subnetpool_path % (subnetpool), body=body)
|
||||||
|
|
||||||
|
@APIParamsCall
|
||||||
|
def delete_subnetpool(self, subnetpool):
|
||||||
|
"""Deletes the specified subnetpool."""
|
||||||
|
return self.delete(self.subnetpool_path % (subnetpool))
|
||||||
|
|
||||||
@APIParamsCall
|
@APIParamsCall
|
||||||
def list_routers(self, retrieve_all=True, **_params):
|
def list_routers(self, retrieve_all=True, **_params):
|
||||||
"""Fetches a list of all routers for a tenant."""
|
"""Fetches a list of all routers for a tenant."""
|
||||||
|
Loading…
Reference in New Issue
Block a user