Merge "Improve docstrings for share and snapshot API methods"
This commit is contained in:
commit
8f48dd0511
|
@ -15,6 +15,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
|
||||
from manilaclient import extension
|
||||
from manilaclient.tests.unit import utils
|
||||
from manilaclient.tests.unit.v1 import fakes
|
||||
|
@ -27,12 +29,40 @@ extensions = [
|
|||
cs = fakes.FakeClient(extensions=extensions)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareSnapshotsTest(utils.TestCase):
|
||||
|
||||
def test_create_share_snapshot(self):
|
||||
cs.share_snapshots.create(1234)
|
||||
cs.assert_called('POST', '/snapshots')
|
||||
|
||||
@ddt.data(
|
||||
type('SnapshotUUID', (object, ), {'uuid': '1234'}),
|
||||
type('SnapshotID', (object, ), {'id': '1234'}),
|
||||
'1234')
|
||||
def test_get_share_snapshot(self, snapshot):
|
||||
snapshot = cs.share_snapshots.get(snapshot)
|
||||
cs.assert_called('GET', '/snapshots/1234')
|
||||
|
||||
@ddt.data(
|
||||
type('SnapshotUUID', (object, ), {'uuid': '1234'}),
|
||||
type('SnapshotID', (object, ), {'id': '1234'}),
|
||||
'1234')
|
||||
def test_update_share_snapshot(self, snapshot):
|
||||
data = dict(foo='bar', quuz='foobar')
|
||||
snapshot = cs.share_snapshots.update(snapshot, **data)
|
||||
cs.assert_called('PUT', '/snapshots/1234', {'snapshot': data})
|
||||
|
||||
@ddt.data(
|
||||
type('SnapshotUUID', (object, ), {'uuid': '1234'}),
|
||||
type('SnapshotID', (object, ), {'id': '1234'}),
|
||||
'1234')
|
||||
def test_reset_snapshot_state(self, snapshot):
|
||||
state = 'available'
|
||||
expected_body = {'os-reset_status': {'status': 'available'}}
|
||||
cs.share_snapshots.reset_state(snapshot, state)
|
||||
cs.assert_called('POST', '/snapshots/1234/action', expected_body)
|
||||
|
||||
def test_delete_share_snapshot(self):
|
||||
snapshot = cs.share_snapshots.get(1234)
|
||||
cs.share_snapshots.delete(snapshot)
|
||||
|
|
|
@ -97,16 +97,63 @@ class SharesTest(utils.TestCase):
|
|||
self.assertFalse(self.share.manager.allow.called)
|
||||
|
||||
# Testcases for class ShareManager
|
||||
def test_create_nfs_share(self):
|
||||
cs.shares.create('nfs', 1)
|
||||
cs.assert_called('POST', '/shares')
|
||||
|
||||
def test_create_cifs_share(self):
|
||||
cs.shares.create('cifs', 2)
|
||||
cs.assert_called('POST', '/shares')
|
||||
@ddt.data('nfs', 'cifs', 'glusterfs', 'hdfs')
|
||||
def test_create_share_with_protocol(self, protocol):
|
||||
expected = {
|
||||
'size': 1,
|
||||
'snapshot_id': None,
|
||||
'name': None,
|
||||
'description': None,
|
||||
'metadata': dict(),
|
||||
'share_proto': protocol,
|
||||
'share_network_id': None,
|
||||
'share_type': None,
|
||||
'is_public': False,
|
||||
}
|
||||
cs.shares.create(protocol, 1)
|
||||
cs.assert_called('POST', '/shares', {'share': expected})
|
||||
|
||||
@ddt.data(
|
||||
type('ShareNetworkUUID', (object, ), {'uuid': 'fake_nw'}),
|
||||
type('ShareNetworkID', (object, ), {'id': 'fake_nw'}),
|
||||
'fake_nw')
|
||||
def test_create_share_with_share_network(self, share_network):
|
||||
expected = {
|
||||
'size': 1,
|
||||
'snapshot_id': None,
|
||||
'name': None,
|
||||
'description': None,
|
||||
'metadata': dict(),
|
||||
'share_proto': 'nfs',
|
||||
'share_network_id': 'fake_nw',
|
||||
'share_type': None,
|
||||
'is_public': False,
|
||||
}
|
||||
cs.shares.create('nfs', 1, share_network=share_network)
|
||||
cs.assert_called('POST', '/shares', {'share': expected})
|
||||
|
||||
@ddt.data(
|
||||
type('ShareTypeUUID', (object, ), {'uuid': 'fake_st'}),
|
||||
type('ShareTypeID', (object, ), {'id': 'fake_st'}),
|
||||
'fake_st')
|
||||
def test_create_share_with_share_type(self, share_type):
|
||||
expected = {
|
||||
'size': 1,
|
||||
'snapshot_id': None,
|
||||
'name': None,
|
||||
'description': None,
|
||||
'metadata': dict(),
|
||||
'share_proto': 'nfs',
|
||||
'share_network_id': None,
|
||||
'share_type': 'fake_st',
|
||||
'is_public': False,
|
||||
}
|
||||
cs.shares.create('nfs', 1, share_type=share_type)
|
||||
cs.assert_called('POST', '/shares', {'share': expected})
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_create_share_with_public_attr_defined(self, is_public):
|
||||
def test_create_share_with_all_params_defined(self, is_public):
|
||||
body = {
|
||||
'share': {
|
||||
'is_public': is_public,
|
||||
|
@ -123,6 +170,23 @@ class SharesTest(utils.TestCase):
|
|||
cs.shares.create('nfs', 1, is_public=is_public)
|
||||
cs.assert_called('POST', '/shares', body)
|
||||
|
||||
@ddt.data(
|
||||
type('ShareUUID', (object, ), {'uuid': '1234'}),
|
||||
type('ShareID', (object, ), {'id': '1234'}),
|
||||
'1234')
|
||||
def test_get_share(self, share):
|
||||
share = cs.shares.get(share)
|
||||
cs.assert_called('GET', '/shares/1234')
|
||||
|
||||
@ddt.data(
|
||||
type('ShareUUID', (object, ), {'uuid': '1234'}),
|
||||
type('ShareID', (object, ), {'id': '1234'}),
|
||||
'1234')
|
||||
def test_get_update(self, share):
|
||||
data = dict(foo='bar', quuz='foobar')
|
||||
share = cs.shares.update(share, **data)
|
||||
cs.assert_called('PUT', '/shares/1234', {'share': data})
|
||||
|
||||
def test_delete_share(self):
|
||||
share = cs.shares.get('1234')
|
||||
cs.shares.delete(share)
|
||||
|
@ -222,12 +286,30 @@ class SharesTest(utils.TestCase):
|
|||
cs.assert_called('POST', '/shares/1234/metadata',
|
||||
{'metadata': {'k1': 'v2'}})
|
||||
|
||||
def test_delete_metadata(self):
|
||||
@ddt.data(
|
||||
type('ShareUUID', (object, ), {'uuid': '1234'}),
|
||||
type('ShareID', (object, ), {'id': '1234'}),
|
||||
'1234')
|
||||
def test_delete_metadata(self, share):
|
||||
keys = ['key1']
|
||||
cs.shares.delete_metadata(1234, keys)
|
||||
cs.shares.delete_metadata(share, keys)
|
||||
cs.assert_called('DELETE', '/shares/1234/metadata/key1')
|
||||
|
||||
def test_metadata_update_all(self):
|
||||
cs.shares.update_all_metadata(1234, {'k1': 'v1'})
|
||||
@ddt.data(
|
||||
type('ShareUUID', (object, ), {'uuid': '1234'}),
|
||||
type('ShareID', (object, ), {'id': '1234'}),
|
||||
'1234')
|
||||
def test_metadata_update_all(self, share):
|
||||
cs.shares.update_all_metadata(share, {'k1': 'v1'})
|
||||
cs.assert_called('PUT', '/shares/1234/metadata',
|
||||
{'metadata': {'k1': 'v1'}})
|
||||
|
||||
@ddt.data(
|
||||
type('ShareUUID', (object, ), {'uuid': '1234'}),
|
||||
type('ShareID', (object, ), {'id': '1234'}),
|
||||
'1234')
|
||||
def test_reset_share_state(self, share):
|
||||
state = 'available'
|
||||
expected_body = {'os-reset_status': {'status': 'available'}}
|
||||
cs.shares.reset_state(share, state)
|
||||
cs.assert_called('POST', '/shares/1234/action', expected_body)
|
||||
|
|
|
@ -67,12 +67,14 @@ class ShareSnapshotManager(base.ManagerWithFind):
|
|||
'description': description}}
|
||||
return self._create('/snapshots', body, 'snapshot')
|
||||
|
||||
def get(self, snapshot_id):
|
||||
def get(self, snapshot):
|
||||
"""Get a snapshot.
|
||||
|
||||
:param snapshot_id: The ID of the snapshot to get.
|
||||
:param snapshot: The :class:`ShareSnapshot` instance or string with ID
|
||||
of snapshot to delete.
|
||||
:rtype: :class:`ShareSnapshot`
|
||||
"""
|
||||
snapshot_id = common_base.getid(snapshot)
|
||||
return self._get('/snapshots/%s' % snapshot_id, 'snapshot')
|
||||
|
||||
def list(self, detailed=True, search_opts=None, sort_key=None,
|
||||
|
@ -131,14 +133,16 @@ class ShareSnapshotManager(base.ManagerWithFind):
|
|||
def update(self, snapshot, **kwargs):
|
||||
"""Update a snapshot.
|
||||
|
||||
:param snapshot: Snapshot to update.
|
||||
:param snapshot: The :class:`ShareSnapshot` instance or string with ID
|
||||
of snapshot to delete.
|
||||
:rtype: :class:`ShareSnapshot`
|
||||
"""
|
||||
if not kwargs:
|
||||
return
|
||||
|
||||
body = {'snapshot': kwargs, }
|
||||
return self._update("/snapshots/%s" % snapshot.id, body)
|
||||
snapshot_id = common_base.getid(snapshot)
|
||||
return self._update("/snapshots/%s" % snapshot_id, body)
|
||||
|
||||
def reset_state(self, snapshot, state):
|
||||
"""Update the specified share snapshot with the provided state."""
|
||||
|
|
|
@ -135,89 +135,114 @@ class ShareManager(base.ManagerWithFind):
|
|||
def create(self, share_proto, size, snapshot_id=None, name=None,
|
||||
description=None, metadata=None, share_network=None,
|
||||
share_type=None, is_public=False):
|
||||
"""Create NAS.
|
||||
"""Create a share.
|
||||
|
||||
:param size: Size of NAS in GB
|
||||
:param snapshot_id: ID of the snapshot
|
||||
:param name: Name of the NAS
|
||||
:param description: Short description of a share
|
||||
:param share_proto: Type of NAS (NFS, CIFS, GlusterFS or HDFS)
|
||||
:param metadata: Optional metadata to set on share creation
|
||||
:param share_proto: text - share protocol for new share
|
||||
available values are NFS, CIFS, GlusterFS and HDFS.
|
||||
:param size: int - size in GB
|
||||
:param snapshot_id: text - ID of the snapshot
|
||||
:param name: text - name of new share
|
||||
:param description: text - description of a share
|
||||
:param metadata: dict - optional metadata to set on share creation
|
||||
:param share_network: either instance of ShareNetwork or text with ID
|
||||
:param share_type: either instance of ShareType or text with ID
|
||||
:param is_public: bool, whether to set share as public or not.
|
||||
:rtype: :class:`Share`
|
||||
"""
|
||||
|
||||
if metadata is None:
|
||||
share_metadata = {}
|
||||
else:
|
||||
share_metadata = metadata
|
||||
|
||||
share_metadata = metadata if metadata is not None else dict()
|
||||
body = {
|
||||
'share': {
|
||||
'size': size,
|
||||
'snapshot_id': snapshot_id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'metadata': share_metadata,
|
||||
'share_proto': share_proto,
|
||||
'share_network_id': common_base.getid(share_network),
|
||||
'share_type': share_type,
|
||||
'is_public': is_public
|
||||
}
|
||||
'size': size,
|
||||
'snapshot_id': snapshot_id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'metadata': share_metadata,
|
||||
'share_proto': share_proto,
|
||||
'share_network_id': common_base.getid(share_network),
|
||||
'share_type': common_base.getid(share_type),
|
||||
'is_public': is_public
|
||||
}
|
||||
return self._create('/shares', body, 'share')
|
||||
return self._create('/shares', {'share': body}, 'share')
|
||||
|
||||
def manage(self, service_host, protocol, export_path,
|
||||
driver_options=None, share_type=None,
|
||||
name=None, description=None):
|
||||
"""Manage some existing share.
|
||||
|
||||
if not driver_options:
|
||||
driver_options = {}
|
||||
|
||||
:param service_host: text - host of share service where share is runing
|
||||
:param protocol: text - share protocol that is used
|
||||
:param export_path: text - export path of share
|
||||
:param driver_options: dict - custom set of key-values.
|
||||
:param share_type: text - share type that should be used for share
|
||||
:param name: text - name of new share
|
||||
:param description: - description for new share
|
||||
"""
|
||||
driver_options = driver_options if driver_options else dict()
|
||||
body = {
|
||||
'share': {
|
||||
'service_host': service_host,
|
||||
'share_type': share_type,
|
||||
'protocol': protocol,
|
||||
'export_path': export_path,
|
||||
'driver_options': driver_options,
|
||||
'name': name,
|
||||
'description': description
|
||||
}
|
||||
'service_host': service_host,
|
||||
'share_type': share_type,
|
||||
'protocol': protocol,
|
||||
'export_path': export_path,
|
||||
'driver_options': driver_options,
|
||||
'name': name,
|
||||
'description': description
|
||||
}
|
||||
|
||||
return self._create('/os-share-manage', body, 'share')
|
||||
return self._create('/os-share-manage', {'share': body}, 'share')
|
||||
|
||||
def unmanage(self, share):
|
||||
"""Unmanage a share.
|
||||
|
||||
:param share: either share object or text with its ID.
|
||||
"""
|
||||
return self.api.client.post(
|
||||
"/os-share-unmanage/%s/unmanage" % common_base.getid(share))
|
||||
|
||||
def get(self, share_id):
|
||||
def get(self, share):
|
||||
"""Get a share.
|
||||
|
||||
:param share_id: The ID of the share to get.
|
||||
:param share: either share object or text with its ID.
|
||||
:rtype: :class:`Share`
|
||||
"""
|
||||
share_id = common_base.getid(share)
|
||||
return self._get("/shares/%s" % share_id, "share")
|
||||
|
||||
def update(self, share, **kwargs):
|
||||
"""Updates a share.
|
||||
|
||||
:param share: Share to update.
|
||||
:param share: either share object or text with its ID.
|
||||
:rtype: :class:`Share`
|
||||
"""
|
||||
if not kwargs:
|
||||
return
|
||||
|
||||
body = {'share': kwargs, }
|
||||
return self._update("/shares/%s" % share.id, body)
|
||||
share_id = common_base.getid(share)
|
||||
return self._update("/shares/%s" % share_id, body)
|
||||
|
||||
def list(self, detailed=True, search_opts=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
"""Get a list of all shares.
|
||||
|
||||
:param detailed: Whether to return detailed share info.
|
||||
:param search_opts: Search options to filter out shares.
|
||||
:param sort_key: Key to be sorted.
|
||||
:param detailed: Whether to return detailed share info or not.
|
||||
:param search_opts: dict with search options to filter out shares.
|
||||
available keys are below (('name1', 'name2', ...), 'type'):
|
||||
- ('all_tenants', int)
|
||||
- ('is_public', bool)
|
||||
- ('metadata', dict)
|
||||
- ('extra_specs', dict)
|
||||
- ('limit', int)
|
||||
- ('offset', int)
|
||||
- ('name', text)
|
||||
- ('status', text)
|
||||
- ('host', text)
|
||||
- ('share_server_id', text)
|
||||
- (('share_network_id', 'share_network'), text)
|
||||
- (('share_type_id', 'share_type'), text)
|
||||
- (('snapshot_id', 'snapshot'), text)
|
||||
Note, that member context will have restricted set of
|
||||
available search opts. For admin context filtering also available
|
||||
by each share attr from its Model. So, this list is not full for
|
||||
admin context.
|
||||
:param sort_key: Key to be sorted (i.e. 'created_at' or 'status').
|
||||
:param sort_dir: Sort direction, should be 'desc' or 'asc'.
|
||||
:rtype: list of :class:`Share`
|
||||
"""
|
||||
|
@ -266,17 +291,21 @@ class ShareManager(base.ManagerWithFind):
|
|||
def delete(self, share):
|
||||
"""Delete a share.
|
||||
|
||||
:param share: The :class:`Share` to delete.
|
||||
:param share: either share object or text with its ID.
|
||||
"""
|
||||
self._delete("/shares/%s" % common_base.getid(share))
|
||||
|
||||
def force_delete(self, share):
|
||||
"""Delete a share forcibly - share status will be avoided.
|
||||
|
||||
:param share: either share object or text with its ID.
|
||||
"""
|
||||
return self._action('os-force_delete', common_base.getid(share))
|
||||
|
||||
def allow(self, share, access_type, access, access_level):
|
||||
"""Allow access from IP to a shares.
|
||||
"""Allow access to a share.
|
||||
|
||||
:param share: The :class:`Share` to delete.
|
||||
:param share: either share object or text with its ID.
|
||||
:param access_type: string that represents access type ('ip','domain')
|
||||
:param access: string that represents access ('127.0.0.1')
|
||||
:param access_level: string that represents access level ('rw', 'ro')
|
||||
|
@ -292,16 +321,19 @@ class ShareManager(base.ManagerWithFind):
|
|||
|
||||
return access
|
||||
|
||||
def deny(self, share, id):
|
||||
"""Deny access from IP to a shares.
|
||||
def deny(self, share, access_id):
|
||||
"""Deny access to a share.
|
||||
|
||||
:param share: The :class:`Share` to delete.
|
||||
:param ip: string that represents ip address
|
||||
:param share: either share object or text with its ID.
|
||||
:param access_id: ID of share access rule
|
||||
"""
|
||||
return self._action('os-deny_access', share, {'access_id': id})
|
||||
return self._action('os-deny_access', share, {'access_id': access_id})
|
||||
|
||||
def access_list(self, share):
|
||||
"""Get access list to the share."""
|
||||
"""Get access list to a share.
|
||||
|
||||
:param share: either share object or text with its ID.
|
||||
"""
|
||||
access_list = self._action("os-access_list", share)[1]["access_list"]
|
||||
if access_list:
|
||||
t = collections.namedtuple('Access', list(access_list[0]))
|
||||
|
@ -310,17 +342,17 @@ class ShareManager(base.ManagerWithFind):
|
|||
return []
|
||||
|
||||
def get_metadata(self, share):
|
||||
"""Get a shares metadata.
|
||||
"""Get metadata of a share.
|
||||
|
||||
:param share: The :class:`Share`.
|
||||
:param share: either share object or text with its ID.
|
||||
"""
|
||||
return self._get("/shares/%s/metadata" % common_base.getid(share),
|
||||
"metadata")
|
||||
|
||||
def set_metadata(self, share, metadata):
|
||||
"""Update/Set a shares metadata.
|
||||
"""Set or update metadata for share.
|
||||
|
||||
:param share: The :class:`Share`.
|
||||
:param share: either share object or text with its ID.
|
||||
:param metadata: A list of keys to be set.
|
||||
"""
|
||||
body = {'metadata': metadata}
|
||||
|
@ -330,17 +362,18 @@ class ShareManager(base.ManagerWithFind):
|
|||
def delete_metadata(self, share, keys):
|
||||
"""Delete specified keys from shares metadata.
|
||||
|
||||
:param share: The :class:`Share`.
|
||||
:param share: either share object or text with its ID.
|
||||
:param keys: A list of keys to be removed.
|
||||
"""
|
||||
for k in keys:
|
||||
self._delete("/shares/%s/metadata/%s" % (common_base.getid(share),
|
||||
k))
|
||||
share_id = common_base.getid(share)
|
||||
for key in keys:
|
||||
self._delete("/shares/%(share_id)s/metadata/%(key)s" % {
|
||||
'share_id': share_id, 'key': key})
|
||||
|
||||
def update_all_metadata(self, share, metadata):
|
||||
"""Update all metadata of a share.
|
||||
|
||||
:param share: The :class:`Share`.
|
||||
:param share: either share object or text with its ID.
|
||||
:param metadata: A list of keys to be updated.
|
||||
"""
|
||||
body = {'metadata': metadata}
|
||||
|
@ -348,12 +381,22 @@ class ShareManager(base.ManagerWithFind):
|
|||
body)
|
||||
|
||||
def _action(self, action, share, info=None, **kwargs):
|
||||
"""Perform a share 'action'."""
|
||||
"""Perform a share 'action'.
|
||||
|
||||
:param action: text with action name.
|
||||
:param share: either share object or text with its ID.
|
||||
:param info: dict with data for specified 'action'.
|
||||
:param kwargs: dict with data to be provided for action hooks.
|
||||
"""
|
||||
body = {action: info}
|
||||
self.run_hooks('modify_body_for_action', body, **kwargs)
|
||||
url = '/shares/%s/action' % common_base.getid(share)
|
||||
return self.api.client.post(url, body=body)
|
||||
|
||||
def reset_state(self, share, state):
|
||||
"""Update the provided share with the provided state."""
|
||||
"""Update the provided share with the provided state.
|
||||
|
||||
:param share: either share object or text with its ID.
|
||||
:param state: text with new state to set for share.
|
||||
"""
|
||||
return self._action('os-reset_status', share, {'status': state})
|
||||
|
|
Loading…
Reference in New Issue