From 7f87b6dd9520ecfc9047696d16f1e8d7b0afe86d Mon Sep 17 00:00:00 2001 From: ashrod98 Date: Sun, 28 Mar 2021 19:45:58 +0000 Subject: [PATCH] Add share network subnet resource to shared file system Introduce Share Network Subnet Class with basic methods including list, get, create and delete to shared file system storage service. Co-Authored-By: Reynaldo Bontje Change-Id: I781eb8d19c6af8097c9de4293bb975361e524344 --- .../user/proxies/shared_file_system.rst | 13 +++ .../resources/shared_file_system/index.rst | 1 + .../v2/share_network_subnet.rst | 13 +++ openstack/shared_file_system/v2/_proxy.py | 91 +++++++++++++++++-- .../v2/share_network_subnet.py | 62 +++++++++++++ .../test_share_network_subnet.py | 75 +++++++++++++++ .../unit/shared_file_system/v2/test_proxy.py | 44 +++++++++ .../v2/test_share_network_subnet.py | 65 +++++++++++++ ...ubnet-to-shared-file-b5de3ce6ca723209.yaml | 5 + 9 files changed, 360 insertions(+), 9 deletions(-) create mode 100644 doc/source/user/resources/shared_file_system/v2/share_network_subnet.rst create mode 100644 openstack/shared_file_system/v2/share_network_subnet.py create mode 100644 openstack/tests/functional/shared_file_system/test_share_network_subnet.py create mode 100644 openstack/tests/unit/shared_file_system/v2/test_share_network_subnet.py create mode 100644 releasenotes/notes/add-share-network-subnet-to-shared-file-b5de3ce6ca723209.yaml diff --git a/doc/source/user/proxies/shared_file_system.rst b/doc/source/user/proxies/shared_file_system.rst index 53de3bdb2..96897c408 100644 --- a/doc/source/user/proxies/shared_file_system.rst +++ b/doc/source/user/proxies/shared_file_system.rst @@ -101,6 +101,7 @@ Create and manipulate Share Networks with the Shared File Systems service. :members: share_networks, get_share_network, delete_share_network, update_share_network, create_share_network + Shared File System Share Instances ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -113,3 +114,15 @@ Systems Service. :members: share_instances, get_share_instance, reset_share_instance_status, delete_share_instance + + +Shared File System Share Network Subnets +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Create and manipulate Share Network Subnets with the Shared File Systems +service. + +.. autoclass:: openstack.shared_file_system.v2._proxy.Proxy + :noindex: + :members: share_network_subnets, get_share_network_subnet, + create_share_network_subnet, delete_share_network_subnet diff --git a/doc/source/user/resources/shared_file_system/index.rst b/doc/source/user/resources/shared_file_system/index.rst index 56d40c533..8c60006f7 100644 --- a/doc/source/user/resources/shared_file_system/index.rst +++ b/doc/source/user/resources/shared_file_system/index.rst @@ -9,6 +9,7 @@ Shared File System service resources v2/limit v2/share v2/share_instance + v2/share_network_subnet v2/share_snapshot v2/share_snapshot_instance v2/share_network diff --git a/doc/source/user/resources/shared_file_system/v2/share_network_subnet.rst b/doc/source/user/resources/shared_file_system/v2/share_network_subnet.rst new file mode 100644 index 000000000..95638a60b --- /dev/null +++ b/doc/source/user/resources/shared_file_system/v2/share_network_subnet.rst @@ -0,0 +1,13 @@ +openstack.shared_file_system.v2.share_network_subnet +==================================================== + +.. automodule:: openstack.shared_file_system.v2.share_network_subnet + +The ShareNetworkSubnet Class +---------------------------- + +The ``ShareNetworkSubnet`` class inherits from +:class:`~openstack.resource.Resource`. + +.. autoclass:: openstack.shared_file_system.v2.share_network_subnet.ShareNetworkSubnet + :members: diff --git a/openstack/shared_file_system/v2/_proxy.py b/openstack/shared_file_system/v2/_proxy.py index a9a7d0609..e9c801914 100644 --- a/openstack/shared_file_system/v2/_proxy.py +++ b/openstack/shared_file_system/v2/_proxy.py @@ -20,6 +20,9 @@ from openstack.shared_file_system.v2 import ( from openstack.shared_file_system.v2 import ( share_network as _share_network ) +from openstack.shared_file_system.v2 import ( + share_network_subnet as _share_network_subnet +) from openstack.shared_file_system.v2 import ( share_snapshot as _share_snapshot ) @@ -46,6 +49,7 @@ class Proxy(proxy.Proxy): "limit": _limit.Limit, "share": _share.Share, "share_network": _share_network.ShareNetwork, + "share_network_subnet": _share_network_subnet.ShareNetworkSubnet, "share_snapshot_instance": _share_snapshot_instance.ShareSnapshotInstance, "share_instance": _share_instance.ShareInstance, @@ -316,8 +320,8 @@ class Proxy(proxy.Proxy): * project_id: The ID of the user or service making the API request. :returns: A generator of manila share snapshot resources - :rtype: :class:`~openstack.shared_file_system.v2. - share_snapshot.ShareSnapshot` + :rtype: + :class:`~openstack.shared_file_system.v2.share_snapshot.ShareSnapshot` """ base_path = '/snapshots/detail' if details else None return self._list( @@ -328,8 +332,8 @@ class Proxy(proxy.Proxy): :param snapshot_id: The ID of the snapshot to get :returns: Details of the identified share snapshot - :rtype: :class:`~openstack.shared_file_system.v2. - share_snapshot.ShareSnapshot` + :rtype: + :class:`~openstack.shared_file_system.v2.share_snapshot.ShareSnapshot` """ return self._get(_share_snapshot.ShareSnapshot, snapshot_id) @@ -337,8 +341,8 @@ class Proxy(proxy.Proxy): """Creates a share snapshot from attributes :returns: Details of the new share snapshot - :rtype: :class:`~openstack.shared_file_system.v2. - share_snapshot.ShareSnapshot` + :rtype: + :class:`~openstack.shared_file_system.v2.share_snapshot.ShareSnapshot` """ return self._create(_share_snapshot.ShareSnapshot, **attrs) @@ -348,8 +352,8 @@ class Proxy(proxy.Proxy): :param snapshot_id: The ID of the snapshot to update :pram dict attrs: The attributes to update on the snapshot :returns: the updated share snapshot - :rtype: :class:`~openstack.shared_file_system.v2. - share_snapshot.ShareSnapshot` + :rtype: + :class:`~openstack.shared_file_system.v2.share_snapshot.ShareSnapshot` """ return self._update(_share_snapshot.ShareSnapshot, snapshot_id, **attrs) @@ -364,8 +368,77 @@ class Proxy(proxy.Proxy): self._delete(_share_snapshot.ShareSnapshot, snapshot_id, ignore_missing=ignore_missing) + # ========= Network Subnets ========== + def share_network_subnets(self, share_network_id): + """Lists all share network subnets with details. + + :param share_network_id: The id of the share network for which + Share Network Subnets should be listed. + :returns: A generator of manila share network subnets + :rtype: + :class:`~openstack.shared_file_system.v2.share_network_subnet.ShareNetworkSubnet` + """ + return self._list( + _share_network_subnet.ShareNetworkSubnet, + share_network_id=share_network_id) + + def get_share_network_subnet( + self, share_network_id, share_network_subnet_id, + ): + """Lists details of a single share network subnet. + + :param share_network_id: The id of the share network associated + with the Share Network Subnet. + :param share_network_subnet_id: The id of the Share Network Subnet + to retrieve. + :returns: Details of the identified share network subnet + :rtype: + :class:`~openstack.shared_file_system.v2.share_network_subnet.ShareNetworkSubnet` + """ + + return self._get( + _share_network_subnet.ShareNetworkSubnet, + share_network_subnet_id, + share_network_id=share_network_id) + + def create_share_network_subnet(self, share_network_id, **attrs): + """Creates a share network subnet from attributes + + :param share_network_id: The id of the share network wthin which the + the Share Network Subnet should be created. + :param dict attrs: Attributes which will be used to create + a share network subnet. + :returns: Details of the new share network subnet. + :rtype: + :class:`~openstack.shared_file_system.v2.share_network_subnet.ShareNetworkSubnet` + """ + return self._create( + _share_network_subnet.ShareNetworkSubnet, + **attrs, + share_network_id=share_network_id) + + def delete_share_network_subnet( + self, share_network_id, share_network_subnet, ignore_missing=True + ): + """Deletes a share network subnet. + + :param share_network_id: The id of the Share Network associated with + the Share Network Subnet. + :param share_network_subnet: The id of the Share Network Subnet + which should be deleted. + :returns: Result of the ``delete`` + :rtype: None + """ + + self._delete( + _share_network_subnet.ShareNetworkSubnet, + share_network_subnet, + share_network_id=share_network_id, + ignore_missing=ignore_missing) + def wait_for_delete(self, res, interval=2, wait=120): """Wait for a resource to be deleted. + :param res: The resource to wait on to be deleted. :type resource: A :class:`~openstack.resource.Resource` object. :param interval: Number of seconds to wait before to consecutive @@ -374,7 +447,7 @@ class Proxy(proxy.Proxy): Default to 120. :returns: The resource is returned on success. :raises: :class:`~openstack.exceptions.ResourceTimeout` if transition - to delete failed to occur in the specified seconds. + to delete failed to occur in the specified seconds. """ return resource.wait_for_delete(self, res, interval, wait) diff --git a/openstack/shared_file_system/v2/share_network_subnet.py b/openstack/shared_file_system/v2/share_network_subnet.py new file mode 100644 index 000000000..7dc3cdacd --- /dev/null +++ b/openstack/shared_file_system/v2/share_network_subnet.py @@ -0,0 +1,62 @@ +# 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 openstack import resource + + +class ShareNetworkSubnet(resource.Resource): + resource_key = "share_network_subnet" + resources_key = "share_network_subnets" + base_path = "/share-networks/%(share_network_id)s/subnets" + + # capabilities + allow_create = True + allow_fetch = True + allow_commit = False + allow_delete = True + allow_list = True + + #: Properties + #: The share nerwork ID, part of the URI for share network subnets. + share_network_id = resource.URI("share_network_id", type=str) + + #: The name of the availability zone that the share network + #: subnet belongs to. + availability_zone = resource.Body("availability_zone", type=str) + #: The IP block from which to allocate the network, in CIDR notation. + cidr = resource.Body("cidr", type=str) + #: Date and time the share network subnet was created at. + created_at = resource.Body("created_at") + #: The gateway of a share network subnet. + gateway = resource.Body("gateway", type=str) + #: The IP version of the network. + ip_version = resource.Body("ip_version", type=int) + #: The MTU of a share network subnet. + mtu = resource.Body("mtu", type=str) + #: The network type. A valid value is VLAN, VXLAN, GRE, or flat + network_type = resource.Body("network_type", type=str) + #: The name of the neutron network. + neutron_net_id = resource.Body("neutron_net_id", type=str) + #: The ID of the neitron subnet. + neutron_subnet_id = resource.Body("neutron_subnet_id", type=str) + #: The segmentation ID. + segmentation_id = resource.Body('segmentation_id', type=int) + #: The name of the share network that the share network subnet belongs to. + share_network_name = resource.Body("share_network_name", type=str) + #: Date and time the share network subnet was last updated at. + updated_at = resource.Body("updated_at", type=str) + + def create(self, session, **kwargs): + return super().\ + create(session, + resource_request_key='share-network-subnet', + **kwargs) diff --git a/openstack/tests/functional/shared_file_system/test_share_network_subnet.py b/openstack/tests/functional/shared_file_system/test_share_network_subnet.py new file mode 100644 index 000000000..8f9c5b839 --- /dev/null +++ b/openstack/tests/functional/shared_file_system/test_share_network_subnet.py @@ -0,0 +1,75 @@ +# 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 openstack.shared_file_system.v2 import ( + share_network_subnet as _share_network_subnet +) +from openstack.tests.functional.shared_file_system import base + + +class ShareNetworkSubnetTest(base.BaseSharedFileSystemTest): + + def setUp(self): + super().setUp() + + zones = self.user_cloud.shared_file_system.\ + availability_zones() + first_zone = next(zones) + + self.SHARE_NETWORK_NAME = self.getUniqueString() + snt = self.user_cloud.shared_file_system.create_share_network( + name=self.SHARE_NETWORK_NAME) + self.assertIsNotNone(snt) + self.assertIsNotNone(snt.id) + self.SHARE_NETWORK_ID = snt.id + snsb = self.user_cloud.shared_file_system.\ + create_share_network_subnet(self.SHARE_NETWORK_ID, + availability_zone=first_zone.name) + self.assertIsNotNone(snsb) + self.assertIsNotNone(snsb.id) + self.SHARE_NETWORK_SUBNET_ID = snsb.id + + def tearDown(self): + subnet = self.user_cloud.shared_file_system.\ + get_share_network_subnet(self.SHARE_NETWORK_ID, + self.SHARE_NETWORK_SUBNET_ID) + fdel = self.user_cloud.shared_file_system.\ + delete_share_network_subnet(self.SHARE_NETWORK_ID, + self.SHARE_NETWORK_SUBNET_ID, + ignore_missing=True) + self.assertIsNone(fdel) + self.user_cloud.shared_file_system.\ + wait_for_delete(subnet) + sot = self.user_cloud.shared_file_system.\ + delete_share_network(self.SHARE_NETWORK_ID, + ignore_missing=True) + self.assertIsNone(sot) + super().tearDown() + + def test_get(self): + sub = self.user_cloud.shared_file_system.\ + get_share_network_subnet(self.SHARE_NETWORK_ID, + self.SHARE_NETWORK_SUBNET_ID) + assert isinstance(sub, _share_network_subnet.ShareNetworkSubnet) + + def test_list(self): + subs = self.user_cloud.shared_file_system.share_network_subnets( + self.SHARE_NETWORK_ID) + self.assertGreater(len(list(subs)), 0) + for sub in subs: + for attribute in ('id', 'name', 'created_at', 'updated_at', + 'share_network_id', 'availability_zone', + 'cidr', 'gateway', 'ip_version', 'mtu', + 'network_type', 'neutron_net_id', + 'neutron_subnet_id', 'segmentation_id', + 'share_network_name'): + self.assertTrue(hasattr(sub, attribute)) diff --git a/openstack/tests/unit/shared_file_system/v2/test_proxy.py b/openstack/tests/unit/shared_file_system/v2/test_proxy.py index 9c2a00be3..9748866ce 100644 --- a/openstack/tests/unit/shared_file_system/v2/test_proxy.py +++ b/openstack/tests/unit/shared_file_system/v2/test_proxy.py @@ -17,6 +17,7 @@ from openstack.shared_file_system.v2 import limit from openstack.shared_file_system.v2 import share from openstack.shared_file_system.v2 import share_instance from openstack.shared_file_system.v2 import share_network +from openstack.shared_file_system.v2 import share_network_subnet from openstack.shared_file_system.v2 import share_snapshot from openstack.shared_file_system.v2 import share_snapshot_instance from openstack.shared_file_system.v2 import storage_pool @@ -299,3 +300,46 @@ class TestShareNetworkResource(test_proxy_base.TestProxyBase): def test_share_network_update(self): self.verify_update( self.proxy.update_share_network, share_network.ShareNetwork) + + +class TestShareNetworkSubnetResource(test_proxy_base.TestProxyBase): + + def setUp(self): + super(TestShareNetworkSubnetResource, self).setUp() + self.proxy = _proxy.Proxy(self.session) + + def test_share_network_subnets(self): + self.verify_list( + self.proxy.share_network_subnets, + share_network_subnet.ShareNetworkSubnet, + method_args=["test_share"], + expected_args=[], + expected_kwargs={"share_network_id": "test_share"}) + + def test_share_network_subnet_get(self): + self.verify_get( + self.proxy.get_share_network_subnet, + share_network_subnet.ShareNetworkSubnet, + method_args=["fake_network_id", "fake_sub_network_id"], + expected_args=['fake_sub_network_id'], + expected_kwargs={'share_network_id': 'fake_network_id'}) + + def test_share_network_subnet_create(self): + self.verify_create( + self.proxy.create_share_network_subnet, + share_network_subnet.ShareNetworkSubnet, + method_args=["fake_network_id"], + method_kwargs={"p1": "v1"}, + expected_args=[], + expected_kwargs={ + "share_network_id": "fake_network_id", + "p1": "v1"}) + + def test_share_network_subnet_delete(self): + self.verify_delete( + self.proxy.delete_share_network_subnet, + share_network_subnet.ShareNetworkSubnet, + False, + method_args=["fake_network_id", "fake_sub_network_id"], + expected_args=["fake_sub_network_id"], + expected_kwargs={'share_network_id': 'fake_network_id'}) diff --git a/openstack/tests/unit/shared_file_system/v2/test_share_network_subnet.py b/openstack/tests/unit/shared_file_system/v2/test_share_network_subnet.py new file mode 100644 index 000000000..30eddaf48 --- /dev/null +++ b/openstack/tests/unit/shared_file_system/v2/test_share_network_subnet.py @@ -0,0 +1,65 @@ +# 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 openstack.shared_file_system.v2 import share_network_subnet as SNS +from openstack.tests.unit import base + +IDENTIFIER = '9cd5a59f-4d22-496f-8b1a-ea4860c24d39' +EXAMPLE = { + "id": IDENTIFIER, + "availability_zone": None, + "share_network_id": "652ef887-b805-4328-b65a-b88c64cb69ec", + "share_network_name": None, + "created_at": "2021-02-24T02:45:59.000000", + "segmentation_id": None, + "neutron_subnet_id": None, + "updated_at": None, + "neutron_net_id": None, + "ip_version": None, + "cidr": None, + "network_type": None, + "mtu": None, + "gateway": None +} + + +class TestShareNetworkSubnet(base.TestCase): + + def test_basic(self): + SNS_resource = SNS.ShareNetworkSubnet() + self.assertEqual('share_network_subnets', SNS_resource.resources_key) + self.assertEqual('/share-networks/%(share_network_id)s/subnets', + SNS_resource.base_path) + self.assertTrue(SNS_resource.allow_list) + + def test_make_share_network_subnet(self): + SNS_resource = SNS.ShareNetworkSubnet(**EXAMPLE) + self.assertEqual(EXAMPLE['id'], SNS_resource.id) + self.assertEqual(EXAMPLE['availability_zone'], + SNS_resource.availability_zone) + self.assertEqual(EXAMPLE['share_network_id'], + SNS_resource.share_network_id) + self.assertEqual(EXAMPLE['share_network_name'], + SNS_resource.share_network_name) + self.assertEqual(EXAMPLE['created_at'], SNS_resource.created_at) + self.assertEqual(EXAMPLE['segmentation_id'], + SNS_resource.segmentation_id) + self.assertEqual(EXAMPLE['neutron_subnet_id'], + SNS_resource.neutron_subnet_id) + self.assertEqual(EXAMPLE['updated_at'], SNS_resource.updated_at) + self.assertEqual(EXAMPLE['neutron_net_id'], + SNS_resource.neutron_net_id) + self.assertEqual(EXAMPLE['ip_version'], SNS_resource.ip_version) + self.assertEqual(EXAMPLE['cidr'], SNS_resource.cidr) + self.assertEqual(EXAMPLE['network_type'], SNS_resource.network_type) + self.assertEqual(EXAMPLE['mtu'], SNS_resource.mtu) + self.assertEqual(EXAMPLE['gateway'], SNS_resource.gateway) diff --git a/releasenotes/notes/add-share-network-subnet-to-shared-file-b5de3ce6ca723209.yaml b/releasenotes/notes/add-share-network-subnet-to-shared-file-b5de3ce6ca723209.yaml new file mode 100644 index 000000000..c61e18c6d --- /dev/null +++ b/releasenotes/notes/add-share-network-subnet-to-shared-file-b5de3ce6ca723209.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Added support to create, list, get, and delete share network + subnets on the shared file system service.