Support manage/unmanage shares with manila

Change-Id: I95b72434a8a44f737f5ee9a44b6ecbf8f4162a7a
This commit is contained in:
Anvi Joshi 2023-07-12 21:38:51 +00:00
parent 8742c06490
commit 7b5356f32d
8 changed files with 239 additions and 1 deletions

View File

@ -180,3 +180,21 @@ specify multiple keys to be deleted.
.. literalinclude:: ../examples/shared_file_system/share_metadata.py
:pyobject: delete_share_metadata
Manage Share
------------
Manage a share with Manila.
.. literalinclude:: ../examples/shared_file_system/shares.py
:pyobject: manage_share
Unmanage Share
--------------
Unmanage a share from Manila.
.. literalinclude:: ../examples/shared_file_system/shares.py
:pyobject: unmanage_share

View File

@ -33,7 +33,8 @@ service.
.. autoclass:: openstack.shared_file_system.v2._proxy.Proxy
:noindex:
:members: shares, get_share, delete_share, update_share, create_share,
revert_share_to_snapshot, resize_share, find_share
revert_share_to_snapshot, resize_share, find_share, manage_share,
unmanage_share
Shared File System Storage Pools

View File

@ -31,3 +31,26 @@ def resize_shares_without_shrink(conn, min_size):
# Extend shares smaller than min_size to min_size,
# but don't shrink shares larger than min_size.
conn.share.resize_share(share.id, min_size, no_shrink=True)
def manage_share(conn, protocol, export_path, service_host, **params):
# Manage a share with the given protocol, export path, service host, and
# optional additional parameters
managed_share = conn.share.manage_share(
protocol, export_path, service_host, **params
)
# Can get the ID of the share, which is now being managed with Manila
managed_share_id = managed_share.id
print("The ID of the share which was managed: %s", managed_share_id)
def unmanage_share(conn, share_id):
# Unmanage the share with the given share ID
conn.share.unmanage_share(share_id)
try:
# Getting the share will raise an exception as it has been unmanaged
conn.share.get_share(share_id)
except Exception:
pass

View File

@ -187,6 +187,42 @@ class Proxy(proxy.Proxy):
res = self._get(_share.Share, share_id)
res.revert_to_snapshot(self, snapshot_id)
def manage_share(self, protocol, export_path, service_host, **params):
"""Manage a share.
:param str protocol: The shared file systems protocol of this share.
:param str export_path: The export path formatted according to the
protocol.
:param str service_host: The manage-share service host.
:param kwargs params: Optional parameters to be sent. Available
parameters include:
* name: The user defined name of the resource.
* share_type: The name or ID of the share type to be used to create
the resource.
* driver_options: A set of one or more key and value pairs, as a
dictionary of strings, that describe driver options.
* is_public: The level of visibility for the share.
* description: The user defiend description of the resource.
* share_server_id: The UUID of the share server.
:returns: The share that was managed.
"""
share = _share.Share()
return share.manage(
self, protocol, export_path, service_host, **params
)
def unmanage_share(self, share_id):
"""Unmanage the share with the given share ID.
:param share_id: The ID of the share to unmanage.
:returns: ``None``
"""
share_to_unmanage = self._get(_share.Share, share_id)
share_to_unmanage.unmanage(self)
def resize_share(
self, share_id, new_size, no_shrink=False, no_extend=False, force=False
):

View File

@ -160,3 +160,54 @@ class Share(resource.Resource, metadata.MetadataMixin):
"""
body = {"revert": {"snapshot_id": snapshot_id}}
self._action(session, body)
def manage(self, session, protocol, export_path, service_host, **params):
"""Manage a share.
:param session: A session object used for sending request.
:param str protocol: The shared file systems protocol of this share.
:param str export_path: The export path formatted according to the
protocol.
:param str service_host: The manage-share service host.
:param kwargs params: Optional parameters to be sent. Available
parameters include:
* name: The user defined name of the resource.
* share_type: The name or ID of the share type to be used to create
the resource.
* driver_options: A set of one or more key and value pairs, as a
dictionary of strings, that describe driver options.
* is_public: The level of visibility for the share.
* description: The user defiend description of the resource.
* share_server_id: The UUID of the share server.
:returns: The share that was managed.
"""
path = 'manage'
attrs = {
'share': {
'protocol': protocol,
'export_path': export_path,
'service_host': service_host,
}
}
attrs['share'].update(params)
url = utils.urljoin(self.base_path, path)
resp = session.post(url, json=attrs)
self._translate_response(resp)
return self
def unmanage(self, session):
"""Unmanage a share.
:param session: A session object used for sending request.
:returns: ``None``
"""
body = {'unmanage': None}
self._action(session, body)

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from openstack import exceptions
from openstack.shared_file_system.v2 import share as _share
from openstack.tests.functional.shared_file_system import base
@ -158,3 +159,59 @@ class ShareTest(base.BaseSharedFileSystemTest):
wait=self._wait_for_timeout,
)
self.assertEqual(larger_size, get_resized_share.size)
class ManageUnmanageShareTest(base.BaseSharedFileSystemTest):
def setUp(self):
super(ManageUnmanageShareTest, self).setUp()
self.NEW_SHARE = self.create_share(
share_proto="NFS",
name="accounting_p8787",
size=2,
)
self.SHARE_ID = self.NEW_SHARE.id
self.export_locations = self.operator_cloud.share.export_locations(
self.SHARE_ID
)
export_paths = [export['path'] for export in self.export_locations]
self.export_path = export_paths[0]
self.share_host = self.operator_cloud.share.get_share(self.SHARE_ID)[
'host'
]
def test_manage_and_unmanage_share(self):
self.operator_cloud.share.unmanage_share(self.SHARE_ID)
self.operator_cloud.shared_file_system.wait_for_delete(
self.NEW_SHARE, interval=2, wait=self._wait_for_timeout
)
try:
self.operator_cloud.share.get_share(self.SHARE_ID)
except exceptions.ResourceNotFound:
pass
managed_share = self.operator_cloud.share.manage_share(
self.NEW_SHARE.share_protocol, self.export_path, self.share_host
)
self.operator_cloud.share.wait_for_status(
managed_share,
status='available',
failures=['error'],
interval=5,
wait=self._wait_for_timeout,
)
self.assertEqual(
self.NEW_SHARE.share_protocol, managed_share.share_protocol
)
managed_host = self.operator_cloud.share.get_share(managed_share.id)[
'host'
]
self.assertEqual(self.share_host, managed_host)

View File

@ -183,3 +183,50 @@ class TestShareActions(TestShares):
self.sess.post.assert_called_with(
url, json=body, headers=headers, microversion=microversion
)
def test_manage_share(self):
sot = share.Share()
self.resp.headers = {}
self.resp.json = mock.Mock(
return_value={"share": {"name": "test_share", "size": 1}}
)
export_path = (
"10.254.0 .5:/shares/share-42033c24-0261-424f-abda-4fef2f6dbfd5."
)
params = {"name": "test_share"}
res = sot.manage(
self.sess,
sot["share_protocol"],
export_path,
sot["host"],
**params,
)
self.assertEqual(res.name, "test_share")
self.assertEqual(res.size, 1)
jsonDict = {
"share": {
"protocol": sot["share_protocol"],
"export_path": export_path,
"service_host": sot["host"],
"name": "test_share",
}
}
self.sess.post.assert_called_once_with("shares/manage", json=jsonDict)
def test_unmanage_share(self):
sot = share.Share(**EXAMPLE)
microversion = sot._get_microversion(self.sess, action='patch')
self.assertIsNone(sot.unmanage(self.sess))
url = 'shares/%s/action' % IDENTIFIER
body = {'unmanage': None}
self.sess.post.assert_called_with(
url, json=body, headers={'Accept': ''}, microversion=microversion
)

View File

@ -0,0 +1,5 @@
---
features:
- |
Added support to manage and unmanage shares
from the shared file system service.