Merge "Hitachi HNAS driver share shrink"
This commit is contained in:
commit
e5f4e981f5
@ -47,7 +47,7 @@ Mapping of share drivers and share features support
|
|||||||
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
||||||
| HDFS | DHSS = False (K) | \- | M | \- | K | K |
|
| HDFS | DHSS = False (K) | \- | M | \- | K | K |
|
||||||
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
||||||
| Hitachi HNAS | DHSS = False (L) | L | L | \- | L | L |
|
| Hitachi HNAS | DHSS = False (L) | L | L | M | L | L |
|
||||||
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
||||||
| HPE 3PAR | DHSS = True (L) & False (K) | \- | \- | \- | K | K |
|
| HPE 3PAR | DHSS = True (L) & False (K) | \- | \- | \- | K | K |
|
||||||
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
+----------------------------------------+-----------------------------+-----------------------+--------------+--------------+------------------------+----------------------------+
|
||||||
|
@ -424,6 +424,25 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||||||
{'shr_path': share['export_locations'][0]['path'],
|
{'shr_path': share['export_locations'][0]['path'],
|
||||||
'shr_id': share['id']})
|
'shr_id': share['id']})
|
||||||
|
|
||||||
|
def shrink_share(self, share, new_size, share_server=None):
|
||||||
|
"""Shrinks a share to new size.
|
||||||
|
|
||||||
|
:param share: Share that will be shrunk.
|
||||||
|
:param new_size: New size of share.
|
||||||
|
:param share_server: Data structure with share server information.
|
||||||
|
Not used by this driver.
|
||||||
|
"""
|
||||||
|
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)
|
||||||
|
LOG.info(_LI("Share %(shr_id)s successfully shrunk to "
|
||||||
|
"%(shr_size)sG."),
|
||||||
|
{'shr_id': share['id'],
|
||||||
|
'shr_size': six.text_type(new_size)})
|
||||||
|
|
||||||
def _get_hnas_share_id(self, share_id):
|
def _get_hnas_share_id(self, share_id):
|
||||||
hnas_id = self.private_storage.get(share_id, 'hnas_id')
|
hnas_id = self.private_storage.get(share_id, 'hnas_id')
|
||||||
|
|
||||||
@ -549,6 +568,25 @@ class HDSHNASDriver(driver.ShareDriver):
|
|||||||
self.hnas.check_export(share_id)
|
self.hnas.check_export(share_id)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
def _shrink_share(self, share_id, old_size, 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 new_size: New size of share after shrink operation.
|
||||||
|
"""
|
||||||
|
self._ensure_share(share_id)
|
||||||
|
|
||||||
|
usage = self.hnas.get_share_usage(share_id)
|
||||||
|
|
||||||
|
LOG.debug("Usage space in share %(share)s: %(usage)sG",
|
||||||
|
{'share': share_id, 'usage': usage})
|
||||||
|
|
||||||
|
if new_size > usage:
|
||||||
|
self.hnas.modify_quota(share_id, new_size)
|
||||||
|
else:
|
||||||
|
raise exception.ShareShrinkingPossibleDataLoss(share_id=share_id)
|
||||||
|
|
||||||
def _extend_share(self, share_id, old_size, new_size):
|
def _extend_share(self, share_id, old_size, new_size):
|
||||||
"""Extends a share to new size.
|
"""Extends a share to new size.
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
from oslo_utils import strutils
|
||||||
from oslo_utils import units
|
from oslo_utils import units
|
||||||
import paramiko
|
import paramiko
|
||||||
import six
|
import six
|
||||||
@ -297,6 +298,20 @@ class HNASSSHBackend(object):
|
|||||||
"below 1G.") % share_id)
|
"below 1G.") % share_id)
|
||||||
raise exception.HNASBackendException(msg=msg)
|
raise exception.HNASBackendException(msg=msg)
|
||||||
|
|
||||||
|
def get_share_usage(self, share_id):
|
||||||
|
command = ['quota', 'list', self.fs_name, share_id]
|
||||||
|
output, err = self._execute(command)
|
||||||
|
|
||||||
|
quota = Quota(output)
|
||||||
|
|
||||||
|
if quota.usage is None:
|
||||||
|
msg = (_("Virtual volume %s does not have any quota.") % share_id)
|
||||||
|
raise exception.HNASItemNotFoundException(msg=msg)
|
||||||
|
else:
|
||||||
|
bytes_usage = strutils.string_to_bytes(six.text_type(quota.usage) +
|
||||||
|
quota.usage_unit)
|
||||||
|
return bytes_usage / units.Gi
|
||||||
|
|
||||||
def _get_share_export(self, share_id):
|
def _get_share_export(self, share_id):
|
||||||
share_id = '/shares/' + share_id
|
share_id = '/shares/' + share_id
|
||||||
command = ['nfs-export', 'list ', share_id]
|
command = ['nfs-export', 'list ', share_id]
|
||||||
|
@ -379,6 +379,31 @@ class HDSHNASTestCase(test.TestCase):
|
|||||||
ssh.HNASSSHBackend.check_quota.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'])
|
ssh.HNASSSHBackend.check_export.assert_called_once_with(share['id'])
|
||||||
|
|
||||||
|
def test_shrink_share(self):
|
||||||
|
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||||
|
mock.Mock(return_value=share['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.mock_object(ssh.HNASSSHBackend, "modify_quota", mock.Mock())
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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']))
|
||||||
|
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'])
|
||||||
|
|
||||||
def test_extend_share(self):
|
def test_extend_share(self):
|
||||||
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
|
||||||
mock.Mock(return_value=share['id']))
|
mock.Mock(return_value=share['id']))
|
||||||
|
@ -96,7 +96,7 @@ File system fake_fs successfully mounted."""
|
|||||||
|
|
||||||
HNAS_RESULT_quota = """Type : Explicit
|
HNAS_RESULT_quota = """Type : Explicit
|
||||||
Target : ViVol: vvol_test
|
Target : ViVol: vvol_test
|
||||||
Usage : 0 B
|
Usage : 1 GB
|
||||||
Limit : 5 GB (Hard)
|
Limit : 5 GB (Hard)
|
||||||
Warning : Unset
|
Warning : Unset
|
||||||
Critical : Unset
|
Critical : Unset
|
||||||
@ -112,7 +112,7 @@ Last modified : 2015-06-23 22:37:17.363660800+00:00 """
|
|||||||
|
|
||||||
HNAS_RESULT_quota_tb = """Type : Explicit
|
HNAS_RESULT_quota_tb = """Type : Explicit
|
||||||
Target : ViVol: vvol_test
|
Target : ViVol: vvol_test
|
||||||
Usage : 0 B
|
Usage : 1 TB
|
||||||
Limit : 1 TB (Hard)
|
Limit : 1 TB (Hard)
|
||||||
Warning : Unset
|
Warning : Unset
|
||||||
Critical : Unset
|
Critical : Unset
|
||||||
@ -128,7 +128,7 @@ Last modified : 2015-06-23 22:37:17.363660800+00:00 """
|
|||||||
|
|
||||||
HNAS_RESULT_quota_mb = """Type : Explicit
|
HNAS_RESULT_quota_mb = """Type : Explicit
|
||||||
Target : ViVol: vvol_test
|
Target : ViVol: vvol_test
|
||||||
Usage : 0 B
|
Usage : 20 MB
|
||||||
Limit : 500 MB (Hard)
|
Limit : 500 MB (Hard)
|
||||||
Warning : Unset
|
Warning : Unset
|
||||||
Critical : Unset
|
Critical : Unset
|
||||||
@ -797,6 +797,32 @@ class HNASSSHTestCase(test.TestCase):
|
|||||||
self.assertRaises(exception.HNASBackendException,
|
self.assertRaises(exception.HNASBackendException,
|
||||||
self._driver_ssh.get_share_quota, "vvol_test")
|
self._driver_ssh.get_share_quota, "vvol_test")
|
||||||
|
|
||||||
|
def test_get_share_usage(self):
|
||||||
|
self.mock_object(ssh.HNASSSHBackend, "_execute", mock.Mock(
|
||||||
|
return_value=(HNAS_RESULT_quota, '')))
|
||||||
|
|
||||||
|
self.assertEqual(1, self._driver_ssh.get_share_usage("vvol_test"))
|
||||||
|
|
||||||
|
def test_get_share_usage_error(self):
|
||||||
|
self.mock_object(ssh.HNASSSHBackend, "_execute", mock.Mock(
|
||||||
|
return_value=(HNAS_RESULT_quota_err, '')))
|
||||||
|
|
||||||
|
self.assertRaises(exception.HNASItemNotFoundException,
|
||||||
|
self._driver_ssh.get_share_usage, "vvol_test")
|
||||||
|
|
||||||
|
def test_get_share_usage_mb(self):
|
||||||
|
self.mock_object(ssh.HNASSSHBackend, "_execute", mock.Mock(
|
||||||
|
return_value=(HNAS_RESULT_quota_mb, '')))
|
||||||
|
|
||||||
|
self.assertEqual(0.01953125, self._driver_ssh.get_share_usage(
|
||||||
|
"vvol_test"))
|
||||||
|
|
||||||
|
def test_get_share_usage_tb(self):
|
||||||
|
self.mock_object(ssh.HNASSSHBackend, "_execute", mock.Mock(
|
||||||
|
return_value=(HNAS_RESULT_quota_tb, '')))
|
||||||
|
|
||||||
|
self.assertEqual(1024, self._driver_ssh.get_share_usage("vvol_test"))
|
||||||
|
|
||||||
def test__get_share_export(self):
|
def test__get_share_export(self):
|
||||||
self.mock_object(ssh.HNASSSHBackend, '_execute',
|
self.mock_object(ssh.HNASSSHBackend, '_execute',
|
||||||
mock.Mock(return_value=[HNAS_RESULT_export_ip, '']))
|
mock.Mock(return_value=[HNAS_RESULT_export_ip, '']))
|
||||||
|
Loading…
Reference in New Issue
Block a user