Skip to content

Commit 747044f

Browse files
authored
Add vpc.v1.subnet resource (#256)
Add `vpc.v1.subnet` resource Add subnet methods to vpc.v1.proxy Add acceptance tests for vpc.v1.subnet Add vpc.v1.vpc and vpc.v1.subnet documentation Reviewed-by: Rodion Gyrbu <fpsoff@outlook.com> Reviewed-by: Anton Sidelnikov <None> Reviewed-by: Anton Kachurin <katchuring@gmail.com> Reviewed-by: None <None>
1 parent 1382ee7 commit 747044f

11 files changed

Lines changed: 526 additions & 17 deletions

File tree

doc/source/sdk/proxies/vpc.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,19 @@ VPC Route Operations
2525
.. autoclass:: otcextensions.sdk.vpc.v1._proxy.Proxy
2626
:noindex:
2727
:members: routes, get_route, add_route, delete_route
28+
29+
VPC Operations
30+
^^^^^^^^^^^^^^
31+
32+
.. autoclass:: otcextensions.sdk.vpc.v1._proxy.Proxy
33+
:noindex:
34+
:members: vpcs, create_vpc, delete_vpc, get_vpc,
35+
find_vpc, update_vpc
36+
37+
VPC Subnet Operations
38+
^^^^^^^^^^^^^^^^^^^^^
39+
40+
.. autoclass:: otcextensions.sdk.vpc.v1._proxy.Proxy
41+
:noindex:
42+
:members: subnets, create_subnet, delete_subnet, get_subnet,
43+
find_subnet, update_subnet

doc/source/sdk/resources/vpc/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@ VPC Resources
44
.. toctree::
55
:maxdepth: 1
66

7+
v1/vpc
8+
v1/subnet
79
v2/peering
810
v2/route
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
otcextensions.sdk.vpc.v1.subnet
2+
================================
3+
4+
.. automodule:: otcextensions.sdk.vpc.v1.subnet
5+
6+
The VPC Subnet Class
7+
--------------------
8+
9+
The ``Subnet`` class inherits from
10+
:class:`~otcextensions.sdk.sdk_resource.Resource`.
11+
12+
.. autoclass:: otcextensions.sdk.vpc.v1.subnet.Subnet
13+
:members:
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
otcextensions.sdk.vpc.v1.vpc
2+
================================
3+
4+
.. automodule:: otcextensions.sdk.vpc.v1.vpc
5+
6+
The VPC Class
7+
-------------------
8+
9+
The ``Vpc`` class inherits from
10+
:class:`~otcextensions.sdk.sdk_resource.Resource`.
11+
12+
.. autoclass:: otcextensions.sdk.vpc.v1.vpc.Vpc
13+
:members:

otcextensions/sdk/vpc/v1/_proxy.py

Lines changed: 131 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1010
# License for the specific language governing permissions and limitations
1111
# under the License.
12+
from openstack import exceptions
1213
from openstack import proxy
1314

1415
from otcextensions.sdk.vpc.v1 import peering as _peering
1516
from otcextensions.sdk.vpc.v1 import route as _route
17+
from otcextensions.sdk.vpc.v1 import subnet as _subnet
1618
from otcextensions.sdk.vpc.v1 import vpc as _vpc
1719

1820

@@ -187,15 +189,17 @@ def vpcs(self, **query):
187189
return self._list(_vpc.Vpc, **query)
188190

189191
def create_vpc(self, **attrs):
190-
""" Create a new vpc from attributes
191-
:param dict attrs: Keyword arguments which will be used to create
192-
a :class:`~otcextensions.sdk.vpc.v1.vpc.Vpc`
192+
"""Create a new vpc from attributes
193+
194+
:param dict attrs: Keyword arguments which will be used to create a
195+
:class:`~otcextensions.sdk.vpc.v1.vpc.Vpc`
193196
"""
194197
return self._create(_vpc.Vpc, **attrs,
195198
project_id=self.get_project_id())
196199

197200
def delete_vpc(self, vpc, ignore_missing=True):
198-
""" Delete a vpc
201+
"""Delete a vpc
202+
199203
:param vpc: vpc id or an instance of
200204
:class:`~otcextensions.sdk.vpc.v1.vpc.Vpc`
201205
@@ -212,9 +216,10 @@ def delete_vpc(self, vpc, ignore_missing=True):
212216
ignore_missing=ignore_missing)
213217

214218
def get_vpc(self, vpc):
215-
""" Get a vpc by id
219+
"""Get a vpc by id
220+
216221
:param vpc: vpc id or an instance of
217-
:class:`~otcextensions.sdk.vpc.v1.vpc.Vpc`
222+
:class:`~otcextensions.sdk.vpc.v1.vpc.Vpc`
218223
219224
:returns: One :class:`~otcextensions.sdk.vpc.v1.vpc.Vpc`
220225
"""
@@ -224,6 +229,7 @@ def find_vpc(self, name_or_id, ignore_missing=False):
224229
"""Find a single vpc
225230
226231
:param name_or_id: The name or ID of a vpc
232+
227233
:param bool ignore_missing: When set to ``False``
228234
:class:`~openstack.exceptions.ResourceNotFound` will be raised
229235
when the vpc does not exist.
@@ -238,7 +244,7 @@ def find_vpc(self, name_or_id, ignore_missing=False):
238244
project_id=self.get_project_id())
239245

240246
def update_vpc(self, vpc, **attrs):
241-
""" Update vpc
247+
"""Update vpc
242248
243249
:param vpc: vpc id or an instance of
244250
:class:`~otcextensions.sdk.vpc.v1.vpc.Vpc`
@@ -249,6 +255,124 @@ def update_vpc(self, vpc, **attrs):
249255
attrs['project_id'] = self.get_project_id()
250256
return self._update(_vpc.Vpc, vpc, **attrs)
251257

258+
# ========== Subnet ==========
259+
def subnets(self, **query):
260+
"""Return a generator of subnets
261+
262+
:param dict query: Optional query parameters to be sent to limit
263+
the resources being returned.
264+
265+
:returns: A generator of subnet objects
266+
267+
:rtype: :class:`~otcextensions.sdk.vpc.v1.subnet.Subnet`
268+
"""
269+
query['project_id'] = self.get_project_id()
270+
return self._list(_subnet.Subnet, **query)
271+
272+
def create_subnet(self, **attrs):
273+
"""Create a new subnet from attributes
274+
275+
:param dict attrs: Keyword arguments which will be used to create
276+
a :class:`~otcextensions.sdk.vpc.v1.subnet.Subnet`
277+
"""
278+
attrs['project_id'] = self.get_project_id()
279+
return self._create(_subnet.Subnet, **attrs)
280+
281+
def get_subnet(self, subnet):
282+
"""Get a subnet by id
283+
284+
:param subnet: subnet id or an instance of
285+
:class:`~otcextensions.sdk.vpc.v1.subnet.Subnet`
286+
287+
:returns: One :class:`~otcextensions.sdk.vpc.v1.subnet.Subnet`
288+
"""
289+
return self._get(_subnet.Subnet, subnet,
290+
project_id=self.get_project_id())
291+
292+
def find_subnet(self, name_or_id, ignore_missing=False):
293+
"""Find a single subnet
294+
295+
:param name_or_id: The name or ID of a subnet
296+
297+
:param bool ignore_missing: When set to ``False``
298+
:class:`~openstack.exceptions.ResourceNotFound` will be raised
299+
when the subnet does not exist.
300+
When set to ``True``, no exception will be set when attempting
301+
to delete a nonexistent peering.
302+
303+
:returns: One :class:`~otcextensions.sdk.vpc.v1.subnet.Subnet`
304+
"""
305+
return self._find(
306+
_subnet.Subnet, name_or_id,
307+
ignore_missing=ignore_missing,
308+
project_id=self.get_project_id())
309+
310+
def update_subnet(self, subnet, **attrs):
311+
"""Update subnet
312+
313+
:param subnet: subnet id or an instance of
314+
:class:`~otcextensions.sdk.vpc.v1.subnet.Subnet`
315+
316+
:param dict attrs: The attributes to update on the subnet
317+
represented by ``subnet``.
318+
"""
319+
attrs['project_id'] = self.get_project_id()
320+
321+
rs = self._get_resource(_subnet.Subnet, subnet)
322+
if rs.vpc_id is None and 'vpc_id' not in attrs:
323+
raise AttributeError('Updating subnet requires VPC ID')
324+
vpc_id = attrs.pop('vpc_id', rs.vpc_id) # vpc_id can't be changed
325+
326+
attrs.pop('base_path', None)
327+
base_path = _subnet.vpc_subnet_base_path(vpc_id)
328+
329+
return self._update(_subnet.Subnet,
330+
subnet,
331+
base_path=base_path,
332+
**attrs)
333+
334+
def _delete(self, resource_type, value, ignore_missing=True, **attrs):
335+
"""Override of ``_delete`` with support of ``base_path``"""
336+
base_path = attrs.pop('base_path', None)
337+
338+
res = self._get_resource(resource_type, value, **attrs)
339+
340+
try:
341+
rv = res.delete(self, base_path=base_path)
342+
except exceptions.ResourceNotFound:
343+
if ignore_missing:
344+
return None
345+
raise
346+
347+
return rv
348+
349+
def delete_subnet(self, subnet, vpc_id=None, ignore_missing=True):
350+
"""Delete a subnet
351+
352+
:param subnet: subnet id or an instance of
353+
:class:`~otcextensions.sdk.vpc.v1.subnet.Subnet`
354+
355+
:param vpc_id: VPC id. By default, taken from ``subnet``, if provided.
356+
357+
:param bool ignore_missing: When set to ``False``
358+
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
359+
the subnet route does not exist.
360+
When set to ``True``, no exception will be set when attempting to
361+
delete a nonexistent route.
362+
363+
:returns: none
364+
"""
365+
sn_res = self._get_resource(_subnet.Subnet, subnet)
366+
sn_res.vpc_id = vpc_id or sn_res.vpc_id
367+
if sn_res.vpc_id is None:
368+
raise AttributeError('Deleting subnet requires VPC ID')
369+
370+
base_path = _subnet.vpc_subnet_base_path(sn_res.vpc_id)
371+
372+
return self._delete(_subnet.Subnet, subnet,
373+
ignore_missing=ignore_missing,
374+
base_path=base_path)
375+
252376
# ========== Project cleanup ==========
253377
def _get_cleanup_dependencies(self):
254378
return {

otcextensions/sdk/vpc/v1/subnet.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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+
from openstack import resource
13+
14+
15+
class ExtraDHCPOpt(resource.Resource):
16+
#: Specifies the NTP server address configured for the subnet.
17+
opt_value = resource.Body('opt_value')
18+
#: Specifies the NTP server address name configured for the subnet.
19+
#: Currently, the value can only be set to ntp.
20+
opt_name = resource.Body('opt_name', default='ntp')
21+
22+
23+
class Subnet(resource.Resource):
24+
resource_key = 'subnet'
25+
resources_key = 'subnets'
26+
base_path = '/v1/%(project_id)s/subnets'
27+
28+
# capabilities
29+
allow_create = True
30+
allow_fetch = True
31+
allow_commit = True
32+
allow_delete = True
33+
allow_list = True
34+
35+
# Properties
36+
project_id = resource.URI('project_id')
37+
description = resource.Body('description')
38+
#: Specifies the subnet CIDR block.
39+
cidr = resource.Body('cidr')
40+
#: Specifies the gateway of the subnet.
41+
gateway_ip = resource.Body('gateway_ip')
42+
#: Specifies whether DHCP is enabled for the subnet.
43+
dhcp_enable = resource.Body('dhcp_enable')
44+
#: Specifies the IP address of DNS server 1 on the subnet.
45+
primary_dns = resource.Body('primary_dns')
46+
#: Specifies the IP address of DNS server 2 on the subnet.
47+
secondary_dns = resource.Body('secondary_dns')
48+
#: Specifies the DNS server address list of a subnet.
49+
#: This field is required if use more than two DNS servers.
50+
dns_list = resource.Body('dnsList', type=list, list_type=str)
51+
#: Specifies the AZ to which the subnet belongs
52+
availability_zone = resource.Body('availability_zone')
53+
#: Specifies the ID of the VPC to which the subnet belongs.
54+
vpc_id = resource.Body('vpc_id')
55+
#: Specifies the NTP server address configured for the subnet.
56+
extra_dhcp_opts = resource.Body('extra_dhcp_opts', type=list,
57+
list_type=ExtraDHCPOpt)
58+
59+
status = resource.Body('status')
60+
neutron_network_id = resource.Body('neutron_network_id')
61+
neutron_subnet_id = resource.Body('neutron_subnet_id')
62+
63+
64+
def vpc_subnet_base_path(vpc_id):
65+
"""Special case of subnet resource path"""
66+
return f'/v1/%(project_id)s/vpcs/{vpc_id}/subnets'

otcextensions/tests/functional/sdk/vpc/v1/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)