Merge "Improve docstrings for share and snapshot API methods"

This commit is contained in:
Jenkins 2015-04-08 15:46:37 +00:00 committed by Gerrit Code Review
commit 8f48dd0511
4 changed files with 240 additions and 81 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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."""

View File

@ -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})