Merge "Fix HDS HNAS errors caused by incorrect IDs" into stable/mitaka
This commit is contained in:
commit
1a9502713a
|
@ -13,6 +13,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from oslo_utils import excutils
|
||||
|
@ -151,13 +153,14 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
Not used by this driver.
|
||||
"""
|
||||
|
||||
hnas_share_id = self._get_hnas_share_id(share['id'])
|
||||
|
||||
try:
|
||||
self._ensure_share(share['id'])
|
||||
self._ensure_share(hnas_share_id)
|
||||
except exception.HNASItemNotFoundException:
|
||||
raise exception.ShareResourceNotFound(share_id=share['id'])
|
||||
|
||||
host_list = []
|
||||
share_id = self._get_hnas_share_id(share['id'])
|
||||
|
||||
for rule in access_rules:
|
||||
if rule['access_type'].lower() != 'ip':
|
||||
|
@ -172,13 +175,13 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
host_list.append(rule['access_to'] + '(' +
|
||||
rule['access_level'] + ')')
|
||||
|
||||
self.hnas.update_access_rule(share_id, host_list)
|
||||
self.hnas.update_access_rule(hnas_share_id, host_list)
|
||||
|
||||
if host_list:
|
||||
LOG.debug("Share %(share)s has the rules: %(rules)s",
|
||||
{'share': share_id, 'rules': ', '.join(host_list)})
|
||||
{'share': share['id'], 'rules': ', '.join(host_list)})
|
||||
else:
|
||||
LOG.debug("Share %(share)s has no rules.", {'share': share_id})
|
||||
LOG.debug("Share %(share)s has no rules.", {'share': share['id']})
|
||||
|
||||
def create_share(self, context, share, share_server=None):
|
||||
"""Creates share.
|
||||
|
@ -212,12 +215,15 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
:param share_server: Data structure with share server information.
|
||||
Not used by this driver.
|
||||
"""
|
||||
share_id = self._get_hnas_share_id(share['id'])
|
||||
hnas_share_id = self._get_hnas_share_id(share['id'])
|
||||
|
||||
LOG.debug("Deleting share in HNAS: %(shr)s.",
|
||||
{'shr': share['id']})
|
||||
|
||||
self._delete_share(share_id)
|
||||
self._delete_share(hnas_share_id)
|
||||
|
||||
LOG.debug("Export and share successfully deleted: %(shr)s.",
|
||||
{'shr': share['id']})
|
||||
|
||||
def create_snapshot(self, context, snapshot, share_server=None):
|
||||
"""Creates snapshot.
|
||||
|
@ -227,13 +233,13 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
:param share_server: Data structure with share server information.
|
||||
Not used by this driver.
|
||||
"""
|
||||
share_id = self._get_hnas_share_id(snapshot['share_id'])
|
||||
hnas_share_id = self._get_hnas_share_id(snapshot['share_id'])
|
||||
|
||||
LOG.debug("The snapshot of share %(ss_sid)s will be created with "
|
||||
"id %(ss_id)s.", {'ss_sid': snapshot['share_id'],
|
||||
'ss_id': snapshot['id']})
|
||||
|
||||
self._create_snapshot(share_id, snapshot['id'])
|
||||
self._create_snapshot(hnas_share_id, snapshot['id'])
|
||||
LOG.info(_LI("Snapshot %(id)s successfully created."),
|
||||
{'id': snapshot['id']})
|
||||
|
||||
|
@ -245,13 +251,13 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
:param share_server:Data structure with share server information.
|
||||
Not used by this driver.
|
||||
"""
|
||||
share_id = self._get_hnas_share_id(snapshot['share_id'])
|
||||
hnas_share_id = self._get_hnas_share_id(snapshot['share_id'])
|
||||
|
||||
LOG.debug("The snapshot %(ss_sid)s will be deleted. The related "
|
||||
"share ID is %(ss_id)s.",
|
||||
{'ss_sid': snapshot['share_id'], 'ss_id': snapshot['id']})
|
||||
|
||||
self._delete_snapshot(share_id, snapshot['id'])
|
||||
self._delete_snapshot(hnas_share_id, snapshot['id'])
|
||||
LOG.info(_LI("Snapshot %(id)s successfully deleted."),
|
||||
{'id': snapshot['id']})
|
||||
|
||||
|
@ -271,11 +277,15 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
LOG.debug("Creating a new share from snapshot: %(ss_id)s.",
|
||||
{'ss_id': snapshot['id']})
|
||||
|
||||
path = self._create_share_from_snapshot(share, snapshot)
|
||||
hnas_src_share_id = self._get_hnas_share_id(snapshot['share_id'])
|
||||
|
||||
path = self._create_share_from_snapshot(share, hnas_src_share_id,
|
||||
snapshot)
|
||||
uri = self.hnas_evs_ip + ":" + path
|
||||
|
||||
LOG.debug("Share created successfully on path: %(uri)s.",
|
||||
{'uri': uri})
|
||||
LOG.debug("Share %(share)s created successfully on path: %(uri)s.",
|
||||
{'uri': uri,
|
||||
'share': share['id']})
|
||||
return uri
|
||||
|
||||
def ensure_share(self, context, share, share_server=None):
|
||||
|
@ -291,9 +301,9 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
LOG.debug("Ensuring share in HNAS: %(shr)s.",
|
||||
{'shr': share['id']})
|
||||
|
||||
share_id = self._get_hnas_share_id(share['id'])
|
||||
hnas_share_id = self._get_hnas_share_id(share['id'])
|
||||
|
||||
path = self._ensure_share(share_id)
|
||||
path = self._ensure_share(hnas_share_id)
|
||||
|
||||
export = self.hnas_evs_ip + ":" + path
|
||||
export_list = [export]
|
||||
|
@ -310,12 +320,12 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
:param share_server: Data structure with share server information.
|
||||
Not used by this driver.
|
||||
"""
|
||||
share_id = self._get_hnas_share_id(share['id'])
|
||||
hnas_share_id = self._get_hnas_share_id(share['id'])
|
||||
|
||||
LOG.debug("Expanding share in HNAS: %(shr_id)s.",
|
||||
{'shr_id': share['id']})
|
||||
|
||||
self._extend_share(share_id, share['size'], new_size)
|
||||
self._extend_share(hnas_share_id, share, new_size)
|
||||
LOG.info(_LI("Share %(shr_id)s successfully extended to "
|
||||
"%(shr_size)s."),
|
||||
{'shr_id': share['id'],
|
||||
|
@ -367,10 +377,12 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
:returns: Returns a dict with size of share managed
|
||||
and its location (your path in file-system).
|
||||
"""
|
||||
share_id = self._get_hnas_share_id(share['id'])
|
||||
hnas_share_id = self._get_hnas_share_id(share['id'])
|
||||
|
||||
if share_id != share['id']:
|
||||
msg = _("Share ID %s already exists, cannot manage.") % share_id
|
||||
# Make sure returned value is the same as provided,
|
||||
# confirming it does not exist.
|
||||
if hnas_share_id != share['id']:
|
||||
msg = _("Share ID %s already exists, cannot manage.") % share['id']
|
||||
raise exception.HNASBackendException(msg=msg)
|
||||
|
||||
LOG.info(_LI("Share %(shr_path)s will be managed with ID %(shr_id)s."),
|
||||
|
@ -382,7 +394,7 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
|
||||
if len(old_path) == 3:
|
||||
evs_ip = old_path_info[0]
|
||||
share_id = old_path[2]
|
||||
hnas_share_id = old_path[2]
|
||||
else:
|
||||
msg = _("Incorrect path. It should have the following format: "
|
||||
"IP:/shares/share_id.")
|
||||
|
@ -398,9 +410,18 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
"not configured.") % {'shr': share['host']}
|
||||
raise exception.ShareBackendException(msg=msg)
|
||||
|
||||
output = self._manage_existing(share_id)
|
||||
output = self._manage_existing(share['id'], hnas_share_id)
|
||||
self.private_storage.update(
|
||||
share['id'], {'hnas_id': share_id})
|
||||
share['id'], {'hnas_id': hnas_share_id})
|
||||
|
||||
LOG.debug("HNAS ID %(hnas_id)s has been saved to private storage for "
|
||||
"Share ID %(share_id)s", {'hnas_id': hnas_share_id,
|
||||
'share_id': share['id']})
|
||||
|
||||
LOG.info(_LI("Share %(shr_path)s was successfully managed with ID "
|
||||
"%(shr_id)s."),
|
||||
{'shr_path': share['export_locations'][0]['path'],
|
||||
'shr_id': share['id']})
|
||||
|
||||
return output
|
||||
|
||||
|
@ -428,12 +449,12 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
:param share_server: Data structure with share server information.
|
||||
Not used by this driver.
|
||||
"""
|
||||
share_id = self._get_hnas_share_id(share['id'])
|
||||
hnas_share_id = self._get_hnas_share_id(share['id'])
|
||||
|
||||
LOG.debug("Shrinking share in HNAS: %(shr_id)s.",
|
||||
{'shr_id': share['id']})
|
||||
|
||||
self._shrink_share(share_id, share['size'], new_size)
|
||||
self._shrink_share(hnas_share_id, share, new_size)
|
||||
LOG.info(_LI("Share %(shr_id)s successfully shrunk to "
|
||||
"%(shr_size)sG."),
|
||||
{'shr_id': share['id'],
|
||||
|
@ -444,18 +465,23 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
|
||||
if hnas_id is None:
|
||||
hnas_id = share_id
|
||||
|
||||
LOG.debug("Share ID is %(shr_id)s and respective HNAS ID "
|
||||
"is %(hnas_id)s.", {'shr_id': share_id,
|
||||
'hnas_id': hnas_id})
|
||||
|
||||
return hnas_id
|
||||
|
||||
def _create_share(self, share_id, share_size):
|
||||
"""Creates share.
|
||||
|
||||
Creates a virtual-volume, adds a quota limit and exports it.
|
||||
:param share_id: ID of share that will be created.
|
||||
:param share_id: manila's database ID of share that will be created.
|
||||
:param share_size: Size limit of share.
|
||||
:returns: Returns a path of /shares/share_id if the export was
|
||||
created successfully.
|
||||
"""
|
||||
path = '/shares/' + share_id
|
||||
path = os.path.join('/shares', share_id)
|
||||
|
||||
self._check_fs_mounted()
|
||||
|
||||
|
@ -484,113 +510,113 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
msg = _("Filesystem %s is not mounted.") % self.fs_name
|
||||
raise exception.HNASBackendException(msg=msg)
|
||||
|
||||
def _ensure_share(self, share_id):
|
||||
def _ensure_share(self, hnas_share_id):
|
||||
"""Ensure that share is exported.
|
||||
|
||||
:param share_id: ID of share that will be checked.
|
||||
:param hnas_share_id: HNAS ID of share that will be checked.
|
||||
:returns: Returns a path of /shares/share_id if the export is ok.
|
||||
"""
|
||||
path = '/shares/' + share_id
|
||||
path = os.path.join('/shares', hnas_share_id)
|
||||
|
||||
self._check_fs_mounted()
|
||||
|
||||
self.hnas.check_vvol(share_id)
|
||||
self.hnas.check_quota(share_id)
|
||||
self.hnas.check_export(share_id)
|
||||
self.hnas.check_vvol(hnas_share_id)
|
||||
self.hnas.check_quota(hnas_share_id)
|
||||
self.hnas.check_export(hnas_share_id)
|
||||
return path
|
||||
|
||||
def _shrink_share(self, share_id, old_size, new_size):
|
||||
def _shrink_share(self, hnas_share_id, share, new_size):
|
||||
"""Shrinks a share to new size.
|
||||
|
||||
:param share_id: ID of share that will be shrunk.
|
||||
:param old_size: Current size of share that will be shrunk.
|
||||
:param hnas_share_id: HNAS ID of share that will be shrunk.
|
||||
:param share: model of share that will be shrunk.
|
||||
:param new_size: New size of share after shrink operation.
|
||||
"""
|
||||
self._ensure_share(share_id)
|
||||
self._ensure_share(hnas_share_id)
|
||||
|
||||
usage = self.hnas.get_share_usage(share_id)
|
||||
usage = self.hnas.get_share_usage(hnas_share_id)
|
||||
|
||||
LOG.debug("Usage space in share %(share)s: %(usage)sG",
|
||||
{'share': share_id, 'usage': usage})
|
||||
{'share': share['id'], 'usage': usage})
|
||||
|
||||
if new_size > usage:
|
||||
self.hnas.modify_quota(share_id, new_size)
|
||||
self.hnas.modify_quota(hnas_share_id, new_size)
|
||||
else:
|
||||
raise exception.ShareShrinkingPossibleDataLoss(share_id=share_id)
|
||||
raise exception.ShareShrinkingPossibleDataLoss(
|
||||
share_id=share['id'])
|
||||
|
||||
def _extend_share(self, share_id, old_size, new_size):
|
||||
def _extend_share(self, hnas_share_id, share, new_size):
|
||||
"""Extends a share to new size.
|
||||
|
||||
:param share_id: ID of share that will be extended.
|
||||
:param old_size: Current size of share that will be extended.
|
||||
:param hnas_share_id: HNAS ID of share that will be extended.
|
||||
:param share: model of share that will be extended.
|
||||
:param new_size: New size of share after extend operation.
|
||||
"""
|
||||
self._ensure_share(share_id)
|
||||
self._ensure_share(hnas_share_id)
|
||||
|
||||
old_size = share['size']
|
||||
total, available_space = self.hnas.get_stats()
|
||||
|
||||
LOG.debug("Available space in filesystem: %(space)sG.",
|
||||
{'space': available_space})
|
||||
|
||||
if (new_size - old_size) < available_space:
|
||||
self.hnas.modify_quota(share_id, new_size)
|
||||
self.hnas.modify_quota(hnas_share_id, new_size)
|
||||
else:
|
||||
msg = (_("Share %s cannot be extended due to insufficient space.")
|
||||
% share_id)
|
||||
% share['id'])
|
||||
raise exception.HNASBackendException(msg=msg)
|
||||
|
||||
def _delete_share(self, share_id):
|
||||
def _delete_share(self, hnas_share_id):
|
||||
"""Deletes share.
|
||||
|
||||
It uses tree-delete-job-submit to format and delete virtual-volumes.
|
||||
Quota is deleted with virtual-volume.
|
||||
:param share_id: ID of share that will be deleted.
|
||||
:param hnas_share_id: HNAS ID of share that will be deleted.
|
||||
"""
|
||||
self._check_fs_mounted()
|
||||
|
||||
self.hnas.nfs_export_del(share_id)
|
||||
self.hnas.vvol_delete(share_id)
|
||||
self.hnas.nfs_export_del(hnas_share_id)
|
||||
self.hnas.vvol_delete(hnas_share_id)
|
||||
|
||||
LOG.debug("Export and share successfully deleted: %(shr)s on Manila.",
|
||||
{'shr': share_id})
|
||||
|
||||
def _manage_existing(self, share_id):
|
||||
def _manage_existing(self, share_id, hnas_share_id):
|
||||
"""Manages a share that exists on backend.
|
||||
|
||||
:param share_id: ID of share that will be managed.
|
||||
:param share_id: manila's database ID of share that will be managed.
|
||||
:param hnas_share_id: HNAS ID of share that will be managed.
|
||||
:returns: Returns a dict with size of share managed
|
||||
and its location (your path in file-system).
|
||||
"""
|
||||
self._ensure_share(share_id)
|
||||
self._ensure_share(hnas_share_id)
|
||||
|
||||
share_size = self.hnas.get_share_quota(share_id)
|
||||
share_size = self.hnas.get_share_quota(hnas_share_id)
|
||||
if share_size is None:
|
||||
msg = (_("The share %s trying to be managed does not have a "
|
||||
"quota limit, please set it before manage.") % share_id)
|
||||
raise exception.ManageInvalidShare(msg)
|
||||
|
||||
path = self.hnas_evs_ip + ':/shares/' + share_id
|
||||
path = self.hnas_evs_ip + os.path.join(':/shares', hnas_share_id)
|
||||
|
||||
return {'size': share_size, 'export_locations': [path]}
|
||||
|
||||
def _create_snapshot(self, share_id, snapshot_id):
|
||||
def _create_snapshot(self, hnas_share_id, snapshot_id):
|
||||
"""Creates a snapshot of share.
|
||||
|
||||
It copies the directory and all files to a new directory inside
|
||||
/snapshots/share_id/.
|
||||
:param share_id: ID of share for snapshot.
|
||||
:param hnas_share_id: HNAS ID of share for snapshot.
|
||||
:param snapshot_id: ID of new snapshot.
|
||||
"""
|
||||
self._ensure_share(share_id)
|
||||
self._ensure_share(hnas_share_id)
|
||||
|
||||
saved_list = self.hnas.get_host_list(share_id)
|
||||
saved_list = self.hnas.get_host_list(hnas_share_id)
|
||||
new_list = []
|
||||
for access in saved_list:
|
||||
new_list.append(access.replace('(rw)', '(ro)'))
|
||||
self.hnas.update_access_rule(share_id, new_list)
|
||||
self.hnas.update_access_rule(hnas_share_id, new_list)
|
||||
|
||||
src_path = '/shares/' + share_id
|
||||
dest_path = '/snapshots/' + share_id + '/' + snapshot_id
|
||||
src_path = os.path.join('/shares', hnas_share_id)
|
||||
dest_path = os.path.join('/snapshots', hnas_share_id, snapshot_id)
|
||||
try:
|
||||
self.hnas.tree_clone(src_path, dest_path)
|
||||
except exception.HNASNothingToCloneException:
|
||||
|
@ -598,35 +624,37 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||
"directory."))
|
||||
self.hnas.create_directory(dest_path)
|
||||
finally:
|
||||
self.hnas.update_access_rule(share_id, saved_list)
|
||||
self.hnas.update_access_rule(hnas_share_id, saved_list)
|
||||
|
||||
def _delete_snapshot(self, share_id, snapshot_id):
|
||||
def _delete_snapshot(self, hnas_share_id, snapshot_id):
|
||||
"""Deletes snapshot.
|
||||
|
||||
It receives the share_id only to mount the path for snapshot.
|
||||
:param share_id: ID of share that snapshot was created.
|
||||
It receives the hnas_share_id only to join the path for snapshot.
|
||||
:param hnas_share_id: HNAS ID of share from which snapshot was taken.
|
||||
:param snapshot_id: ID of snapshot.
|
||||
"""
|
||||
|
||||
self._check_fs_mounted()
|
||||
|
||||
path = '/snapshots/' + share_id + '/' + snapshot_id
|
||||
path = os.path.join('/snapshots', hnas_share_id, snapshot_id)
|
||||
self.hnas.tree_delete(path)
|
||||
path = '/snapshots/' + share_id
|
||||
path = os.path.join('/snapshots', hnas_share_id)
|
||||
self.hnas.delete_directory(path)
|
||||
|
||||
def _create_share_from_snapshot(self, share, snapshot):
|
||||
def _create_share_from_snapshot(self, share, src_hnas_share_id, snapshot):
|
||||
"""Creates a new share from snapshot.
|
||||
|
||||
It copies everything from snapshot directory to a new vvol,
|
||||
set a quota limit for it and export.
|
||||
:param share: a dict from new share.
|
||||
:param src_hnas_share_id: HNAS ID of share from which snapshot was
|
||||
taken.
|
||||
:param snapshot: a dict from snapshot that will be copied to
|
||||
new share.
|
||||
:returns: Returns the path for new share.
|
||||
"""
|
||||
dest_path = '/shares/' + share['id']
|
||||
src_path = '/snapshots/' + snapshot['share_id'] + '/' + snapshot['id']
|
||||
dest_path = os.path.join('/shares', share['id'])
|
||||
src_path = os.path.join('/snapshots', src_hnas_share_id,
|
||||
snapshot['id'])
|
||||
|
||||
# Before copying everything to new vvol, we need to create it,
|
||||
# because we only can transform an empty directory into a vvol.
|
||||
|
|
|
@ -153,16 +153,18 @@ class HDSHNASTestCase(test.TestCase):
|
|||
}
|
||||
access_list = [access1, access2]
|
||||
|
||||
self.mock_object(self._driver, '_get_hnas_share_id',
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(self._driver, '_ensure_share')
|
||||
self.mock_object(ssh.HNASSSHBackend, "update_access_rule",
|
||||
mock.Mock())
|
||||
self._driver.update_access('context', share, access_list, [], [])
|
||||
|
||||
ssh.HNASSSHBackend.update_access_rule.assert_called_once_with(
|
||||
share['id'], [access1['access_to'] + '('
|
||||
+ access1['access_level'] + ',norootsquash)',
|
||||
access2['access_to'] + '('
|
||||
+ access2['access_level'] + ')'])
|
||||
'hnas_id', [access1['access_to'] + '('
|
||||
+ access1['access_level'] + ',norootsquash)',
|
||||
access2['access_to'] + '('
|
||||
+ access2['access_level'] + ')'])
|
||||
self.assertTrue(self.mock_log.debug.called)
|
||||
|
||||
def test_update_access_ip_exception(self):
|
||||
|
@ -249,7 +251,7 @@ class HDSHNASTestCase(test.TestCase):
|
|||
|
||||
def test_delete_share(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value=share['id']))
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
|
||||
mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "nfs_export_del", mock.Mock())
|
||||
|
@ -258,13 +260,13 @@ class HDSHNASTestCase(test.TestCase):
|
|||
self._driver.delete_share('context', share)
|
||||
|
||||
self.assertTrue(self.mock_log.debug.called)
|
||||
ssh.HNASSSHBackend.nfs_export_del.assert_called_once_with(share['id'])
|
||||
ssh.HNASSSHBackend.vvol_delete.assert_called_once_with(share['id'])
|
||||
ssh.HNASSSHBackend.nfs_export_del.assert_called_once_with('hnas_id')
|
||||
ssh.HNASSSHBackend.vvol_delete.assert_called_once_with('hnas_id')
|
||||
|
||||
def test_create_snapshot(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share")
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value=share['id']))
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(ssh.HNASSSHBackend, "get_host_list", mock.Mock(
|
||||
return_value=['172.24.44.200(rw)']))
|
||||
self.mock_object(ssh.HNASSSHBackend, "update_access_rule", mock.Mock())
|
||||
|
@ -272,19 +274,19 @@ class HDSHNASTestCase(test.TestCase):
|
|||
|
||||
self._driver.create_snapshot('context', snapshot)
|
||||
|
||||
ssh.HNASSSHBackend.get_host_list.assert_called_once_with(share['id'])
|
||||
ssh.HNASSSHBackend.get_host_list.assert_called_once_with('hnas_id')
|
||||
ssh.HNASSSHBackend.update_access_rule.assert_any_call(
|
||||
share['id'], ['172.24.44.200(ro)'])
|
||||
'hnas_id', ['172.24.44.200(ro)'])
|
||||
ssh.HNASSSHBackend.update_access_rule.assert_any_call(
|
||||
share['id'], ['172.24.44.200(rw)'])
|
||||
'hnas_id', ['172.24.44.200(rw)'])
|
||||
ssh.HNASSSHBackend.tree_clone.assert_called_once_with(
|
||||
'/shares/' + share['id'], '/snapshots/' + share['id'] + '/' +
|
||||
snapshot['id'])
|
||||
'/shares/' + 'hnas_id', '/snapshots/' + 'hnas_id' + '/' +
|
||||
snapshot['id'])
|
||||
|
||||
def test_create_snapshot_first_snapshot(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share")
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value=share['id']))
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(ssh.HNASSSHBackend, "get_host_list", mock.Mock(
|
||||
return_value=['172.24.44.200(rw)']))
|
||||
self.mock_object(ssh.HNASSSHBackend, "update_access_rule", mock.Mock())
|
||||
|
@ -295,17 +297,17 @@ class HDSHNASTestCase(test.TestCase):
|
|||
self._driver.create_snapshot('context', snapshot)
|
||||
|
||||
self.assertTrue(self.mock_log.warning.called)
|
||||
ssh.HNASSSHBackend.get_host_list.assert_called_once_with(share['id'])
|
||||
ssh.HNASSSHBackend.get_host_list.assert_called_once_with('hnas_id')
|
||||
ssh.HNASSSHBackend.update_access_rule.assert_any_call(
|
||||
share['id'], ['172.24.44.200(ro)'])
|
||||
'hnas_id', ['172.24.44.200(ro)'])
|
||||
ssh.HNASSSHBackend.update_access_rule.assert_any_call(
|
||||
share['id'], ['172.24.44.200(rw)'])
|
||||
'hnas_id', ['172.24.44.200(rw)'])
|
||||
ssh.HNASSSHBackend.create_directory.assert_called_once_with(
|
||||
'/snapshots/' + share['id'] + '/' + snapshot['id'])
|
||||
'/snapshots/' + 'hnas_id' + '/' + snapshot['id'])
|
||||
|
||||
def test_delete_snapshot(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value=share['id']))
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted")
|
||||
self.mock_object(ssh.HNASSSHBackend, "tree_delete", mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "delete_directory", mock.Mock())
|
||||
|
@ -316,13 +318,13 @@ class HDSHNASTestCase(test.TestCase):
|
|||
self.assertTrue(self.mock_log.info.called)
|
||||
hds_hnas.HDSHNASDriver._check_fs_mounted.assert_called_once_with()
|
||||
ssh.HNASSSHBackend.tree_delete.assert_called_once_with(
|
||||
'/snapshots/' + share['id'] + '/' + snapshot['id'])
|
||||
'/snapshots/' + 'hnas_id' + '/' + snapshot['id'])
|
||||
ssh.HNASSSHBackend.delete_directory.assert_called_once_with(
|
||||
'/snapshots/' + share['id'])
|
||||
'/snapshots/' + 'hnas_id')
|
||||
|
||||
def test_ensure_share(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value=share['id']))
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
|
||||
mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "check_vvol", mock.Mock())
|
||||
|
@ -331,14 +333,14 @@ class HDSHNASTestCase(test.TestCase):
|
|||
|
||||
result = self._driver.ensure_share('context', share)
|
||||
|
||||
self.assertEqual(['172.24.44.10:/shares/' + share['id']], result)
|
||||
ssh.HNASSSHBackend.check_vvol.assert_called_once_with(share['id'])
|
||||
ssh.HNASSSHBackend.check_quota.assert_called_once_with(share['id'])
|
||||
ssh.HNASSSHBackend.check_export.assert_called_once_with(share['id'])
|
||||
self.assertEqual(['172.24.44.10:/shares/' + 'hnas_id'], result)
|
||||
ssh.HNASSSHBackend.check_vvol.assert_called_once_with('hnas_id')
|
||||
ssh.HNASSSHBackend.check_quota.assert_called_once_with('hnas_id')
|
||||
ssh.HNASSSHBackend.check_export.assert_called_once_with('hnas_id')
|
||||
|
||||
def test_shrink_share(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value=share['id']))
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "get_share_usage", mock.Mock(
|
||||
return_value=10))
|
||||
|
@ -346,24 +348,23 @@ class HDSHNASTestCase(test.TestCase):
|
|||
|
||||
self._driver.shrink_share(share, 11)
|
||||
|
||||
ssh.HNASSSHBackend.get_share_usage.assert_called_once_with(share['id'])
|
||||
ssh.HNASSSHBackend.modify_quota.assert_called_once_with(share['id'],
|
||||
11)
|
||||
ssh.HNASSSHBackend.get_share_usage.assert_called_once_with('hnas_id')
|
||||
ssh.HNASSSHBackend.modify_quota.assert_called_once_with('hnas_id', 11)
|
||||
|
||||
def test_shrink_share_new_size_lower_than_usage(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value=share['id']))
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "get_share_usage", mock.Mock(
|
||||
return_value=10))
|
||||
|
||||
self.assertRaises(exception.ShareShrinkingPossibleDataLoss,
|
||||
self._driver.shrink_share, share, 9)
|
||||
ssh.HNASSSHBackend.get_share_usage.assert_called_once_with(share['id'])
|
||||
ssh.HNASSSHBackend.get_share_usage.assert_called_once_with('hnas_id')
|
||||
|
||||
def test_extend_share(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value=share['id']))
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "get_stats", mock.Mock(
|
||||
return_value=(500, 200)))
|
||||
|
@ -372,12 +373,11 @@ class HDSHNASTestCase(test.TestCase):
|
|||
self._driver.extend_share(share, 150)
|
||||
|
||||
ssh.HNASSSHBackend.get_stats.assert_called_once_with()
|
||||
ssh.HNASSSHBackend.modify_quota.assert_called_once_with(share['id'],
|
||||
150)
|
||||
ssh.HNASSSHBackend.modify_quota.assert_called_once_with('hnas_id', 150)
|
||||
|
||||
def test_extend_share_with_no_available_space_in_fs(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value=share['id']))
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "get_stats", mock.Mock(
|
||||
return_value=(500, 200)))
|
||||
|
@ -450,6 +450,8 @@ class HDSHNASTestCase(test.TestCase):
|
|||
def test_create_share_from_snapshot(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
|
||||
mock.Mock())
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(ssh.HNASSSHBackend, "vvol_create", mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "quota_add", mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "tree_clone", mock.Mock())
|
||||
|
@ -463,13 +465,15 @@ class HDSHNASTestCase(test.TestCase):
|
|||
ssh.HNASSSHBackend.quota_add.assert_called_once_with(share['id'],
|
||||
share['size'])
|
||||
ssh.HNASSSHBackend.tree_clone.assert_called_once_with(
|
||||
'/snapshots/' + snapshot['share_id'] + '/' + snapshot['id'],
|
||||
'/snapshots/' + 'hnas_id' + '/' + snapshot['id'],
|
||||
'/shares/' + share['id'])
|
||||
ssh.HNASSSHBackend.nfs_export_add.assert_called_once_with(share['id'])
|
||||
|
||||
def test_create_share_from_snapshot_empty_snapshot(self):
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
|
||||
mock.Mock())
|
||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||
mock.Mock(return_value='hnas_id'))
|
||||
self.mock_object(ssh.HNASSSHBackend, "vvol_create", mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "quota_add", mock.Mock())
|
||||
self.mock_object(ssh.HNASSSHBackend, "tree_clone", mock.Mock(
|
||||
|
@ -485,7 +489,7 @@ class HDSHNASTestCase(test.TestCase):
|
|||
ssh.HNASSSHBackend.quota_add.assert_called_once_with(share['id'],
|
||||
share['size'])
|
||||
ssh.HNASSSHBackend.tree_clone.assert_called_once_with(
|
||||
'/snapshots/' + snapshot['share_id'] + '/' + snapshot['id'],
|
||||
'/snapshots/' + 'hnas_id' + '/' + snapshot['id'],
|
||||
'/shares/' + share['id'])
|
||||
ssh.HNASSSHBackend.nfs_export_add.assert_called_once_with(share['id'])
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
fixes:
|
||||
- Fixed error when allowing access to a managed share in
|
||||
HDS HNAS driver.
|
||||
- Fixed error when attempting to create a new share from
|
||||
a snapshot taken from a managed share in HDS HNAS
|
||||
driver.
|
||||
- Fixed ID inconsistencies in log when handling managed
|
||||
shares in HDS HNAS driver.
|
Loading…
Reference in New Issue