Add share snapshot to shared file system.
Introduce Share Snapshot class with basic methods including list, create, delete, get and update to shared file systems service. Change-Id: Ie3fb8c7b14276d505a415aae857e2c6e5fefa888
This commit is contained in:
parent
7364a6254a
commit
72c223b52c
@ -66,3 +66,15 @@ service.
|
|||||||
.. autoclass:: openstack.shared_file_system.v2._proxy.Proxy
|
.. autoclass:: openstack.shared_file_system.v2._proxy.Proxy
|
||||||
:noindex:
|
:noindex:
|
||||||
:members: limits
|
:members: limits
|
||||||
|
|
||||||
|
|
||||||
|
Shared File System Snapshots
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Interact with Share Snapshots supported by the Shared File Systems
|
||||||
|
service.
|
||||||
|
|
||||||
|
.. autoclass:: openstack.shared_file_system.v2._proxy.Proxy
|
||||||
|
:noindex:
|
||||||
|
:members: share_snapshots, get_share_snapshot, delete_share_snapshot,
|
||||||
|
update_share_snapshot, create_share_snapshot
|
||||||
|
@ -9,3 +9,4 @@ Shared File System service resources
|
|||||||
v2/limit
|
v2/limit
|
||||||
v2/share
|
v2/share
|
||||||
v2/user_message
|
v2/user_message
|
||||||
|
v2/share_snapshot
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
openstack.shared_file_system.v2.share_snapshot
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
.. automodule:: openstack.shared_file_system.v2.share_snapshot
|
||||||
|
|
||||||
|
The ShareSnapshot Class
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The ``ShareSnapshot`` class inherits from
|
||||||
|
:class:`~openstack.resource.Resource`.
|
||||||
|
|
||||||
|
.. autoclass:: openstack.shared_file_system.v2.share_snapshot.ShareSnapshot
|
||||||
|
:members:
|
@ -14,6 +14,9 @@ from openstack import proxy
|
|||||||
from openstack import resource
|
from openstack import resource
|
||||||
from openstack.shared_file_system.v2 import (
|
from openstack.shared_file_system.v2 import (
|
||||||
availability_zone as _availability_zone)
|
availability_zone as _availability_zone)
|
||||||
|
from openstack.shared_file_system.v2 import (
|
||||||
|
share_snapshot as _share_snapshot
|
||||||
|
)
|
||||||
from openstack.shared_file_system.v2 import (
|
from openstack.shared_file_system.v2 import (
|
||||||
storage_pool as _storage_pool
|
storage_pool as _storage_pool
|
||||||
)
|
)
|
||||||
@ -238,3 +241,74 @@ class Proxy(proxy.Proxy):
|
|||||||
"""
|
"""
|
||||||
return self._list(
|
return self._list(
|
||||||
_limit.Limit, **query)
|
_limit.Limit, **query)
|
||||||
|
|
||||||
|
def share_snapshots(self, details=True, **query):
|
||||||
|
"""Lists all share snapshots with details.
|
||||||
|
|
||||||
|
:param kwargs query: Optional query parameters to be sent to limit
|
||||||
|
the snapshots being returned. Available parameters include:
|
||||||
|
|
||||||
|
* 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`
|
||||||
|
"""
|
||||||
|
base_path = '/snapshots/detail' if details else None
|
||||||
|
return self._list(
|
||||||
|
_share_snapshot.ShareSnapshot, base_path=base_path, **query)
|
||||||
|
|
||||||
|
def get_share_snapshot(self, snapshot_id):
|
||||||
|
"""Lists details of a single share snapshot
|
||||||
|
|
||||||
|
: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`
|
||||||
|
"""
|
||||||
|
return self._get(_share_snapshot.ShareSnapshot, snapshot_id)
|
||||||
|
|
||||||
|
def create_share_snapshot(self, **attrs):
|
||||||
|
"""Creates a share snapshot from attributes
|
||||||
|
|
||||||
|
:returns: Details of the new share snapshot
|
||||||
|
:rtype: :class:`~openstack.shared_file_system.v2.
|
||||||
|
share_snapshot.ShareSnapshot`
|
||||||
|
"""
|
||||||
|
return self._create(_share_snapshot.ShareSnapshot, **attrs)
|
||||||
|
|
||||||
|
def update_share_snapshot(self, snapshot_id, **attrs):
|
||||||
|
"""Updates details of a single share.
|
||||||
|
|
||||||
|
: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`
|
||||||
|
"""
|
||||||
|
return self._update(_share_snapshot.ShareSnapshot, snapshot_id,
|
||||||
|
**attrs)
|
||||||
|
|
||||||
|
def delete_share_snapshot(self, snapshot_id, ignore_missing=True):
|
||||||
|
"""Deletes a single share snapshot
|
||||||
|
|
||||||
|
:param snapshot_id: The ID of the snapshot to delete
|
||||||
|
:returns: Result of the ``delete``
|
||||||
|
:rtype: ``None``
|
||||||
|
"""
|
||||||
|
self._delete(_share_snapshot.ShareSnapshot, snapshot_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
|
||||||
|
checks. Default to 2.
|
||||||
|
:param wait: Maximum number of seconds to wait before the change.
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
return resource.wait_for_delete(self, res, interval, wait)
|
||||||
|
58
openstack/shared_file_system/v2/share_snapshot.py
Normal file
58
openstack/shared_file_system/v2/share_snapshot.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# 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 ShareSnapshot(resource.Resource):
|
||||||
|
resource_key = "snapshot"
|
||||||
|
resources_key = "snapshots"
|
||||||
|
base_path = "/snapshots"
|
||||||
|
|
||||||
|
# capabilities
|
||||||
|
allow_create = True
|
||||||
|
allow_fetch = True
|
||||||
|
allow_commit = True
|
||||||
|
allow_delete = True
|
||||||
|
allow_list = True
|
||||||
|
allow_head = False
|
||||||
|
|
||||||
|
_query_mapping = resource.QueryParameters(
|
||||||
|
"snapshot_id"
|
||||||
|
)
|
||||||
|
|
||||||
|
#: Properties
|
||||||
|
#: The date and time stamp when the resource was
|
||||||
|
#: created within the service’s database.
|
||||||
|
created_at = resource.Body("created_at")
|
||||||
|
#: The user defined description of the resource.
|
||||||
|
description = resource.Body("description", type=str)
|
||||||
|
#: The user defined name of the resource.
|
||||||
|
display_name = resource.Body("display_name", type=str)
|
||||||
|
#: The user defined description of the resource
|
||||||
|
display_description = resource.Body(
|
||||||
|
"display_description", type=str)
|
||||||
|
#: ID of the project that the snapshot belongs to.
|
||||||
|
project_id = resource.Body("project_id", type=str)
|
||||||
|
#: The UUID of the source share that was used to
|
||||||
|
#: create the snapshot.
|
||||||
|
share_id = resource.Body("share_id", type=str)
|
||||||
|
#: The file system protocol of a share snapshot
|
||||||
|
share_proto = resource.Body("share_proto", type=str)
|
||||||
|
#: The snapshot's source share's size, in GiBs.
|
||||||
|
share_size = resource.Body("share_size", type=int)
|
||||||
|
#: The snapshot size, in GiBs.
|
||||||
|
size = resource.Body("size", type=int)
|
||||||
|
#: The snapshot status
|
||||||
|
status = resource.Body("status", type=str)
|
||||||
|
#: ID of the user that the snapshot was created by.
|
||||||
|
user_id = resource.Body("user_id", type=str)
|
@ -0,0 +1,84 @@
|
|||||||
|
# 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.tests.functional.shared_file_system import base
|
||||||
|
|
||||||
|
|
||||||
|
class ShareSnapshotTest(base.BaseSharedFileSystemTest):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(ShareSnapshotTest, self).setUp()
|
||||||
|
|
||||||
|
self.SHARE_NAME = self.getUniqueString()
|
||||||
|
self.SNAPSHOT_NAME = self.getUniqueString()
|
||||||
|
my_share = self.operator_cloud.shared_file_system.create_share(
|
||||||
|
name=self.SHARE_NAME, size=2, share_type="dhss_false",
|
||||||
|
share_protocol='NFS', description=None)
|
||||||
|
self.operator_cloud.shared_file_system.wait_for_status(
|
||||||
|
my_share,
|
||||||
|
status='available',
|
||||||
|
failures=['error'],
|
||||||
|
interval=5,
|
||||||
|
wait=self._wait_for_timeout)
|
||||||
|
self.assertIsNotNone(my_share)
|
||||||
|
self.assertIsNotNone(my_share.id)
|
||||||
|
self.SHARE_ID = my_share.id
|
||||||
|
|
||||||
|
msp = self.operator_cloud.shared_file_system.create_share_snapshot(
|
||||||
|
share_id=self.SHARE_ID, name=self.SNAPSHOT_NAME, force=True)
|
||||||
|
self.operator_cloud.shared_file_system.wait_for_status(
|
||||||
|
msp,
|
||||||
|
status='available',
|
||||||
|
failures=['error'],
|
||||||
|
interval=5,
|
||||||
|
wait=self._wait_for_timeout)
|
||||||
|
self.assertIsNotNone(msp.id)
|
||||||
|
self.SNAPSHOT_ID = msp.id
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
snpt = self.operator_cloud.shared_file_system.get_share_snapshot(
|
||||||
|
self.SNAPSHOT_ID)
|
||||||
|
sot = self.operator_cloud.shared_file_system.delete_share_snapshot(
|
||||||
|
snpt, ignore_missing=False
|
||||||
|
)
|
||||||
|
self.operator_cloud.shared_file_system.wait_for_delete(
|
||||||
|
snpt, interval=2, wait=self._wait_for_timeout)
|
||||||
|
self.assertIsNone(sot)
|
||||||
|
sot = self.operator_cloud.shared_file_system.delete_share(
|
||||||
|
self.SHARE_ID,
|
||||||
|
ignore_missing=False)
|
||||||
|
self.assertIsNone(sot)
|
||||||
|
super(ShareSnapshotTest, self).tearDown()
|
||||||
|
|
||||||
|
def test_get(self):
|
||||||
|
sot = self.operator_cloud.shared_file_system.get_share_snapshot(
|
||||||
|
self.SNAPSHOT_ID
|
||||||
|
)
|
||||||
|
self.assertEqual(self.SNAPSHOT_NAME, sot.name)
|
||||||
|
|
||||||
|
def test_list(self):
|
||||||
|
snaps = self.operator_cloud.shared_file_system.share_snapshots(
|
||||||
|
details=True
|
||||||
|
)
|
||||||
|
self.assertGreater(len(list(snaps)), 0)
|
||||||
|
for snap in snaps:
|
||||||
|
for attribute in ('id', 'name', 'created_at', 'updated_at',
|
||||||
|
'description', 'share_id', 'share_proto',
|
||||||
|
'share_size', 'size', 'status', 'user_id'):
|
||||||
|
self.assertTrue(hasattr(snap, attribute))
|
||||||
|
|
||||||
|
def test_update(self):
|
||||||
|
u_snap = self.operator_cloud.shared_file_system.update_share_snapshot(
|
||||||
|
self.SNAPSHOT_ID, display_description='updated share snapshot')
|
||||||
|
get_u_snap = self.operator_cloud.shared_file_system.get_share_snapshot(
|
||||||
|
u_snap.id)
|
||||||
|
self.assertEqual('updated share snapshot', get_u_snap.description)
|
@ -15,6 +15,7 @@ from unittest import mock
|
|||||||
from openstack.shared_file_system.v2 import _proxy
|
from openstack.shared_file_system.v2 import _proxy
|
||||||
from openstack.shared_file_system.v2 import limit
|
from openstack.shared_file_system.v2 import limit
|
||||||
from openstack.shared_file_system.v2 import share
|
from openstack.shared_file_system.v2 import share
|
||||||
|
from openstack.shared_file_system.v2 import share_snapshot
|
||||||
from openstack.shared_file_system.v2 import storage_pool
|
from openstack.shared_file_system.v2 import storage_pool
|
||||||
from openstack.shared_file_system.v2 import user_message
|
from openstack.shared_file_system.v2 import user_message
|
||||||
from openstack.tests.unit import test_proxy_base
|
from openstack.tests.unit import test_proxy_base
|
||||||
@ -111,3 +112,59 @@ class TestUserMessageProxy(test_proxy_base.TestProxyBase):
|
|||||||
|
|
||||||
def test_limit(self):
|
def test_limit(self):
|
||||||
self.verify_list(self.proxy.limits, limit.Limit)
|
self.verify_list(self.proxy.limits, limit.Limit)
|
||||||
|
|
||||||
|
|
||||||
|
class TestShareSnapshotResource(test_proxy_base.TestProxyBase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestShareSnapshotResource, self).setUp()
|
||||||
|
self.proxy = _proxy.Proxy(self.session)
|
||||||
|
|
||||||
|
def test_share_snapshots(self):
|
||||||
|
self.verify_list(
|
||||||
|
self.proxy.share_snapshots, share_snapshot.ShareSnapshot)
|
||||||
|
|
||||||
|
def test_share_snapshots_detailed(self):
|
||||||
|
self.verify_list(
|
||||||
|
self.proxy.share_snapshots,
|
||||||
|
share_snapshot.ShareSnapshot,
|
||||||
|
method_kwargs={"details": True, "name": "my_snapshot"},
|
||||||
|
expected_kwargs={"name": "my_snapshot"})
|
||||||
|
|
||||||
|
def test_share_snapshots_not_detailed(self):
|
||||||
|
self.verify_list(
|
||||||
|
self.proxy.share_snapshots,
|
||||||
|
share_snapshot.ShareSnapshot,
|
||||||
|
method_kwargs={"details": False, "name": "my_snapshot"},
|
||||||
|
expected_kwargs={"name": "my_snapshot"})
|
||||||
|
|
||||||
|
def test_share_snapshot_get(self):
|
||||||
|
self.verify_get(
|
||||||
|
self.proxy.get_share_snapshot, share_snapshot.ShareSnapshot)
|
||||||
|
|
||||||
|
def test_share_snapshot_delete(self):
|
||||||
|
self.verify_delete(
|
||||||
|
self.proxy.delete_share_snapshot,
|
||||||
|
share_snapshot.ShareSnapshot, False)
|
||||||
|
|
||||||
|
def test_share_snapshot_delete_ignore(self):
|
||||||
|
self.verify_delete(
|
||||||
|
self.proxy.delete_share_snapshot,
|
||||||
|
share_snapshot.ShareSnapshot, True)
|
||||||
|
|
||||||
|
def test_share_snapshot_create(self):
|
||||||
|
self.verify_create(
|
||||||
|
self.proxy.create_share_snapshot, share_snapshot.ShareSnapshot)
|
||||||
|
|
||||||
|
def test_share_snapshot_update(self):
|
||||||
|
self.verify_update(
|
||||||
|
self.proxy.update_share_snapshot, share_snapshot.ShareSnapshot)
|
||||||
|
|
||||||
|
@mock.patch("openstack.resource.wait_for_delete")
|
||||||
|
def test_wait_for_delete(self, mock_wait):
|
||||||
|
mock_resource = mock.Mock()
|
||||||
|
mock_wait.return_value = mock_resource
|
||||||
|
|
||||||
|
self.proxy.wait_for_delete(mock_resource)
|
||||||
|
|
||||||
|
mock_wait.assert_called_once_with(self.proxy, mock_resource, 2, 120)
|
||||||
|
@ -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_snapshot
|
||||||
|
from openstack.tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLE = {
|
||||||
|
"status": "creating",
|
||||||
|
"share_id": "406ea93b-32e9-4907-a117-148b3945749f",
|
||||||
|
"user_id": "5c7bdb6eb0504d54a619acf8375c08ce",
|
||||||
|
"name": "snapshot_share1",
|
||||||
|
"created_at": "2021-06-07T11:50:39.756808",
|
||||||
|
"description": "Here is a snapshot of share Share1",
|
||||||
|
"share_proto": "NFS",
|
||||||
|
"share_size": 1,
|
||||||
|
"id": "6d221c1d-0200-461e-8d20-24b4776b9ddb",
|
||||||
|
"project_id": "cadd7139bc3148b8973df097c0911016",
|
||||||
|
"size": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestShareSnapshot(base.TestCase):
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
snapshot_resource = share_snapshot.ShareSnapshot()
|
||||||
|
self.assertEqual(
|
||||||
|
'snapshots', snapshot_resource.resources_key)
|
||||||
|
self.assertEqual('/snapshots', snapshot_resource.base_path)
|
||||||
|
self.assertTrue(snapshot_resource.allow_list)
|
||||||
|
|
||||||
|
self.assertDictEqual({
|
||||||
|
"limit": "limit",
|
||||||
|
"marker": "marker",
|
||||||
|
"snapshot_id": "snapshot_id"
|
||||||
|
},
|
||||||
|
snapshot_resource._query_mapping._mapping)
|
||||||
|
|
||||||
|
def test_make_share_snapshot(self):
|
||||||
|
snapshot_resource = share_snapshot.ShareSnapshot(**EXAMPLE)
|
||||||
|
self.assertEqual(EXAMPLE['id'], snapshot_resource.id)
|
||||||
|
self.assertEqual(EXAMPLE['share_id'], snapshot_resource.share_id)
|
||||||
|
self.assertEqual(EXAMPLE['user_id'],
|
||||||
|
snapshot_resource.user_id)
|
||||||
|
self.assertEqual(EXAMPLE['created_at'], snapshot_resource.created_at)
|
||||||
|
self.assertEqual(EXAMPLE['status'], snapshot_resource.status)
|
||||||
|
self.assertEqual(EXAMPLE['name'], snapshot_resource.name)
|
||||||
|
self.assertEqual(
|
||||||
|
EXAMPLE['description'], snapshot_resource.description)
|
||||||
|
self.assertEqual(
|
||||||
|
EXAMPLE['share_proto'], snapshot_resource.share_proto)
|
||||||
|
self.assertEqual(
|
||||||
|
EXAMPLE['share_size'], snapshot_resource.share_size)
|
||||||
|
self.assertEqual(
|
||||||
|
EXAMPLE['project_id'], snapshot_resource.project_id)
|
||||||
|
self.assertEqual(EXAMPLE['size'], snapshot_resource.size)
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds support to create, update, list, get, and delete share
|
||||||
|
snapshots to shared file system service.
|
Loading…
Reference in New Issue
Block a user