ZFSSA driver to return project 'available' space

This fix allows the iSCSI driver to return the 'available' space
property at project level instead of the pool level which is more
accurate in cases when storage is not thin provisioned.

Change-Id: I52dec5e527eab393fd464fbc7f4f910fafb67268
Closes-Bug: #1479342
This commit is contained in:
Abhiram Moturi 2015-08-10 14:23:09 +00:00
parent 0773a4130d
commit 075ff30d7d
3 changed files with 39 additions and 19 deletions

View File

@ -460,10 +460,13 @@ class TestZFSSAISCSIDriver(test.TestCase):
'')
def test_get_volume_stats(self):
self.drv.zfssa.get_pool_stats.return_value = 2 * units.Gi, 3 * units.Gi
self.drv.zfssa.get_project_stats.return_value = 2 * units.Gi,\
3 * units.Gi
lcfg = self.configuration
stats = self.drv.get_volume_stats(refresh=True)
self.drv.zfssa.get_pool_stats.assert_called_once_with(lcfg.zfssa_pool)
self.drv.zfssa.get_project_stats.assert_called_once_with(
lcfg.zfssa_pool,
lcfg.zfssa_project)
self.assertEqual('Oracle', stats['vendor_name'])
self.assertEqual(self.configuration.volume_backend_name,
stats['volume_backend_name'])
@ -1174,6 +1177,27 @@ class TestZFSSAApi(test.TestCase):
'nodestroy': True}
self.zfssa.rclient.put.assert_called_with(expected_svc, expected_arg)
def test_get_project_stats(self):
ret_val = json.dumps({"project": {"name": self.project,
"space_available": 15754895360,
"space_total": 25754895360,
"dedup": False,
"logbias": "latency",
"encryption": "off"}})
self.zfssa.rclient.get.return_value = self._create_response(
client.Status.OK, ret_val)
self.zfssa.get_project_stats(self.pool, self.project)
expected_svc = '/api/storage/v1/pools/' + self.pool + '/projects/' + \
self.project
self.zfssa.rclient.get.assert_called_with(expected_svc)
self.zfssa.rclient.get.return_value = self._create_response(
client.Status.NOT_FOUND)
self.assertRaises(exception.VolumeBackendAPIException,
self.zfssa.get_project_stats,
self.pool,
self.project)
class TestZFSSANfsApi(test.TestCase):

View File

@ -393,7 +393,8 @@ class ZFSSAISCSIDriver(driver.ISCSIDriver):
data["storage_protocol"] = self.protocol
lcfg = self.configuration
(avail, total) = self.zfssa.get_pool_stats(lcfg.zfssa_pool)
(avail, total) = self.zfssa.get_project_stats(lcfg.zfssa_pool,
lcfg.zfssa_project)
if avail is None or total is None:
return

View File

@ -352,35 +352,30 @@ class ZFSSAApi(object):
LOG.error(exception_msg)
raise exception.VolumeBackendAPIException(data=exception_msg)
def get_pool_stats(self, pool):
"""Get pool stats.
def get_project_stats(self, pool, project):
"""Get project stats.
Get space available and total properties of a pool
returns (avail, total).
Get available space and total space of a project
returns (avail, total).
"""
svc = '/api/storage/v1/pools/' + pool
svc = '/api/storage/v1/pools/%s/projects/%s' % (pool, project)
ret = self.rclient.get(svc)
if ret.status != restclient.Status.OK:
exception_msg = (_('Error Getting Pool Stats: '
exception_msg = (_('Error Getting Project Stats: '
'Pool: %(pool)s '
'Project: %(project)s '
'Return code: %(ret.status)d '
'Message: %(ret.data)s.')
% {'pool': pool,
'project': project,
'ret.status': ret.status,
'ret.data': ret.data})
LOG.error(exception_msg)
raise exception.InvalidVolume(reason=exception_msg)
raise exception.VolumeBackendAPIException(data=exception_msg)
val = json.loads(ret.data)
if not self._is_pool_owned(val):
LOG.error(_LE('Error Pool ownership: Pool %(pool)s is not owned '
'by %(host)s.'),
{'pool': pool, 'host': self.host})
raise exception.InvalidInput(reason=pool)
avail = val['pool']['usage']['available']
total = val['pool']['usage']['total']
avail = val['project']['space_available']
total = avail + val['project']['space_total']
return avail, total