Skip to content

Commit 82257e8

Browse files
committed
Add address scope CRUD
Add address scope CRUD which is new in Mitaka. This patch set includes the following: - AddressScope resource - Proxy interface updates for the resource - Related resource updates - Documentation updates - Unit tests - Functional tests Applicable references for this support: - https://review.openstack.org/#/c/180267/ - https://github.com/openstack/neutron/blob/master/doc/source/devref/address_scopes.rst - https://github.com/openstack/neutron/blob/master/neutron/extensions/address_scope.py Change-Id: I8d1864f5ef44841c948c5357496e01c83f7a6341
1 parent 4a30b15 commit 82257e8

File tree

11 files changed

+294
-0
lines changed

11 files changed

+294
-0
lines changed

doc/source/users/resources/network/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Network Resources
44
.. toctree::
55
:maxdepth: 1
66

7+
v2/address_scope
78
v2/availability_zone
89
v2/extension
910
v2/floating_ip
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
openstack.network.v2.address_scope
2+
==================================
3+
4+
.. automodule:: openstack.network.v2.address_scope
5+
6+
The AddressScope Class
7+
----------------------
8+
9+
The ``AddressScope`` class inherits from :class:`~openstack.resource.Resource`.
10+
11+
.. autoclass:: openstack.network.v2.address_scope.AddressScope
12+
:members:

openstack/network/v2/_proxy.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# License for the specific language governing permissions and limitations
1111
# under the License.
1212

13+
from openstack.network.v2 import address_scope as _address_scope
1314
from openstack.network.v2 import availability_zone
1415
from openstack.network.v2 import extension
1516
from openstack.network.v2 import floating_ip as _floating_ip
@@ -35,6 +36,91 @@
3536

3637
class Proxy(proxy.BaseProxy):
3738

39+
def create_address_scope(self, **attrs):
40+
"""Create a new address scope from attributes
41+
42+
:param dict attrs: Keyword arguments which will be used to create
43+
a :class:`~openstack.network.v2.address_scope.AddressScope`,
44+
comprised of the properties on the AddressScope class.
45+
46+
:returns: The results of address scope creation
47+
:rtype: :class:`~openstack.network.v2.address_scope.AddressScope`
48+
"""
49+
return self._create(_address_scope.AddressScope, **attrs)
50+
51+
def delete_address_scope(self, address_scope, ignore_missing=True):
52+
"""Delete an address scope
53+
54+
:param address_scope: The value can be either the ID of an
55+
address scope or
56+
a :class:`~openstack.network.v2.address_scope.AddressScope`
57+
instance.
58+
:param bool ignore_missing: When set to ``False``
59+
:class:`~openstack.exceptions.ResourceNotFound` will be
60+
raised when the address scope does not exist.
61+
When set to ``True``, no exception will be set when
62+
attempting to delete a nonexistent address scope.
63+
64+
:returns: ``None``
65+
"""
66+
self._delete(_address_scope.AddressScope, address_scope,
67+
ignore_missing=ignore_missing)
68+
69+
def find_address_scope(self, name_or_id, ignore_missing=True):
70+
"""Find a single address scope
71+
72+
:param name_or_id: The name or ID of an address scope.
73+
:param bool ignore_missing: When set to ``False``
74+
:class:`~openstack.exceptions.ResourceNotFound` will be
75+
raised when the resource does not exist.
76+
When set to ``True``, None will be returned when
77+
attempting to find a nonexistent resource.
78+
:returns: One :class:`~openstack.network.v2.address_scope.AddressScope`
79+
or None
80+
"""
81+
return self._find(_address_scope.AddressScope, name_or_id,
82+
ignore_missing=ignore_missing)
83+
84+
def get_address_scope(self, address_scope):
85+
"""Get a single address scope
86+
87+
:param address_scope: The value can be the ID of an address scope or a
88+
:class:`~openstack.network.v2.address_scope.AddressScope` instance.
89+
90+
:returns: One :class:`~openstack.network.v2.address_scope.AddressScope`
91+
:raises: :class:`~openstack.exceptions.ResourceNotFound`
92+
when no resource can be found.
93+
"""
94+
return self._get(_address_scope.AddressScope, address_scope)
95+
96+
def address_scopes(self, **query):
97+
"""Return a generator of address scopes
98+
99+
:param kwargs \*\*query: Optional query parameters to be sent to limit
100+
the resources being returned.
101+
102+
:returns: A generator of address scope objects
103+
:rtype: :class:`~openstack.network.v2.address_scope.AddressScope`
104+
"""
105+
return self._list(_address_scope.AddressScope,
106+
paginated=False,
107+
**query)
108+
109+
def update_address_scope(self, address_scope, **attrs):
110+
"""Update an address scope
111+
112+
:param address_scope: Either the ID of an address scope or a
113+
:class:`~openstack.network.v2.address_scope.AddressScope` instance.
114+
:attrs kwargs: The attributes to update on the address scope
115+
represented by ``value``.
116+
117+
:returns: The updated address scope
118+
:rtype: :class:`~openstack.network.v2.address_scope.AddressScope`
119+
"""
120+
return self._update(_address_scope.AddressScope,
121+
address_scope,
122+
**attrs)
123+
38124
def availability_zones(self):
39125
"""Return a generator of availability zones
40126
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
from openstack.network import network_service
14+
from openstack import resource
15+
16+
17+
class AddressScope(resource.Resource):
18+
resource_key = 'address_scope'
19+
resources_key = 'address_scopes'
20+
base_path = '/address-scopes'
21+
service = network_service.NetworkService()
22+
23+
# capabilities
24+
allow_create = True
25+
allow_retrieve = True
26+
allow_update = True
27+
allow_delete = True
28+
allow_list = True
29+
30+
# Properties
31+
#: The address scope name.
32+
name = resource.prop('name')
33+
#: The ID of the project that owns the address scope.
34+
project_id = resource.prop('tenant_id')
35+
#: The IP address family of the address scope.
36+
#: *Type: int*
37+
ip_version = resource.prop('ip_version', type=int)
38+
#: Indicates whether this address scope is shared across all projects.
39+
#: *Type: bool*
40+
is_shared = resource.prop('shared', type=bool)

openstack/network/v2/network.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ class Network(resource.Resource):
3434
#: Availability zones for the network.
3535
#: *Type: list of availability zone names*
3636
availability_zones = resource.prop('availability_zones')
37+
#: The ID of the IPv4 address scope for the network.
38+
ipv4_address_scope_id = resource.prop('ipv4_address_scope')
39+
#: The ID of the IPv6 address scope for the network.
40+
ipv6_address_scope_id = resource.prop('ipv6_address_scope')
3741
#: The administrative state of the network, which is up ``True`` or
3842
#: down ``False``. *Type: bool*
3943
is_admin_state_up = resource.prop('admin_state_up', type=bool)

openstack/network/v2/subnet_pool.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class SubnetPool(resource.Resource):
2828
allow_list = True
2929

3030
# Properties
31+
#: The ID of the address scope associated with the subnet pool.
32+
address_scope_id = resource.prop('address_scope_id')
3133
#: The length of the prefix to allocate when the cidr or prefixlen
3234
#: attributes are omitted when creating a subnet. *Type: int*
3335
default_prefix_length = resource.prop('default_prefixlen', type=int)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
import uuid
14+
15+
from openstack.network.v2 import address_scope as _address_scope
16+
from openstack.tests.functional import base
17+
18+
19+
class TestAddressScope(base.BaseFunctionalTest):
20+
21+
ADDRESS_SCOPE_ID = None
22+
ADDRESS_SCOPE_NAME = uuid.uuid4().hex
23+
ADDRESS_SCOPE_NAME_UPDATED = uuid.uuid4().hex
24+
IS_SHARED = False
25+
IP_VERSION = 4
26+
27+
@classmethod
28+
def setUpClass(cls):
29+
super(TestAddressScope, cls).setUpClass()
30+
address_scope = cls.conn.network.create_address_scope(
31+
ip_version=cls.IP_VERSION,
32+
name=cls.ADDRESS_SCOPE_NAME,
33+
shared=cls.IS_SHARED,
34+
)
35+
assert isinstance(address_scope, _address_scope.AddressScope)
36+
cls.assertIs(cls.ADDRESS_SCOPE_NAME, address_scope.name)
37+
cls.ADDRESS_SCOPE_ID = address_scope.id
38+
39+
@classmethod
40+
def tearDownClass(cls):
41+
sot = cls.conn.network.delete_address_scope(cls.ADDRESS_SCOPE_ID)
42+
cls.assertIs(None, sot)
43+
44+
def test_find(self):
45+
sot = self.conn.network.find_address_scope(self.ADDRESS_SCOPE_NAME)
46+
self.assertEqual(self.ADDRESS_SCOPE_ID, sot.id)
47+
48+
def test_get(self):
49+
sot = self.conn.network.get_address_scope(self.ADDRESS_SCOPE_ID)
50+
self.assertEqual(self.ADDRESS_SCOPE_NAME, sot.name)
51+
self.assertEqual(self.IS_SHARED, sot.is_shared)
52+
self.assertEqual(self.IP_VERSION, sot.ip_version)
53+
54+
def test_list(self):
55+
names = [o.name for o in self.conn.network.address_scopes()]
56+
self.assertIn(self.ADDRESS_SCOPE_NAME, names)
57+
58+
def test_update(self):
59+
sot = self.conn.network.update_address_scope(
60+
self.ADDRESS_SCOPE_ID,
61+
name=self.ADDRESS_SCOPE_NAME_UPDATED)
62+
self.assertEqual(self.ADDRESS_SCOPE_NAME_UPDATED, sot.name)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
import testtools
14+
15+
from openstack.network.v2 import address_scope
16+
17+
IDENTIFIER = 'IDENTIFIER'
18+
EXAMPLE = {
19+
'id': IDENTIFIER,
20+
'ip_version': 4,
21+
'name': '1',
22+
'shared': True,
23+
'tenant_id': '2',
24+
}
25+
26+
27+
class TestAddressScope(testtools.TestCase):
28+
29+
def test_basic(self):
30+
sot = address_scope.AddressScope()
31+
self.assertEqual('address_scope', sot.resource_key)
32+
self.assertEqual('address_scopes', sot.resources_key)
33+
self.assertEqual('/address-scopes', sot.base_path)
34+
self.assertEqual('network', sot.service.service_type)
35+
self.assertTrue(sot.allow_create)
36+
self.assertTrue(sot.allow_retrieve)
37+
self.assertTrue(sot.allow_update)
38+
self.assertTrue(sot.allow_delete)
39+
self.assertTrue(sot.allow_list)
40+
41+
def test_make_it(self):
42+
sot = address_scope.AddressScope(EXAMPLE)
43+
self.assertEqual(EXAMPLE['id'], sot.id)
44+
self.assertEqual(EXAMPLE['ip_version'], sot.ip_version)
45+
self.assertEqual(EXAMPLE['name'], sot.name)
46+
self.assertTrue(sot.is_shared)
47+
self.assertEqual(EXAMPLE['tenant_id'], sot.project_id)

openstack/tests/unit/network/v2/test_network.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
'port_security_enabled': True,
3333
'availability_zone_hints': ['15', '16'],
3434
'availability_zones': ['16'],
35+
'ipv4_address_scope': '17',
36+
'ipv6_address_scope': '18',
3537
}
3638

3739

@@ -72,3 +74,7 @@ def test_make_it(self):
7274
sot.availability_zone_hints)
7375
self.assertEqual(EXAMPLE['availability_zones'],
7476
sot.availability_zones)
77+
self.assertEqual(EXAMPLE['ipv4_address_scope'],
78+
sot.ipv4_address_scope_id)
79+
self.assertEqual(EXAMPLE['ipv6_address_scope'],
80+
sot.ipv6_address_scope_id)

openstack/tests/unit/network/v2/test_proxy.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import mock
1414

1515
from openstack.network.v2 import _proxy
16+
from openstack.network.v2 import address_scope
1617
from openstack.network.v2 import availability_zone
1718
from openstack.network.v2 import extension
1819
from openstack.network.v2 import floating_ip
@@ -40,6 +41,37 @@ def setUp(self):
4041
super(TestNetworkProxy, self).setUp()
4142
self.proxy = _proxy.Proxy(self.session)
4243

44+
def test_address_scope_create_attrs(self):
45+
self.verify_create(self.proxy.create_address_scope,
46+
address_scope.AddressScope)
47+
48+
def test_address_scope_delete(self):
49+
self.verify_delete(self.proxy.delete_address_scope,
50+
address_scope.AddressScope,
51+
False)
52+
53+
def test_address_scope_delete_ignore(self):
54+
self.verify_delete(self.proxy.delete_address_scope,
55+
address_scope.AddressScope,
56+
True)
57+
58+
def test_address_scope_find(self):
59+
self.verify_find(self.proxy.find_address_scope,
60+
address_scope.AddressScope)
61+
62+
def test_address_scope_get(self):
63+
self.verify_get(self.proxy.get_address_scope,
64+
address_scope.AddressScope)
65+
66+
def test_address_scopes(self):
67+
self.verify_list(self.proxy.address_scopes,
68+
address_scope.AddressScope,
69+
paginated=False)
70+
71+
def test_address_scope_update(self):
72+
self.verify_update(self.proxy.update_address_scope,
73+
address_scope.AddressScope)
74+
4375
def test_availability_zones(self):
4476
self.verify_list_no_kwargs(self.proxy.availability_zones,
4577
availability_zone.AvailabilityZone,

0 commit comments

Comments
 (0)