Merge "Hitachi HNAS driver share shrink"

This commit is contained in:
Jenkins 2016-02-08 23:25:24 +00:00 committed by Gerrit Code Review
commit e5f4e981f5
5 changed files with 108 additions and 4 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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, '']))