From: Abhiram Moturi Date: Mon, 10 Aug 2015 14:23:09 +0000 (+0000) Subject: ZFSSA driver to return project 'available' space X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=075ff30d7d8bbeca1af634718f3cb19099bc44b3;p=openstack-build%2Fcinder-build.git 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 --- diff --git a/cinder/tests/unit/test_zfssa.py b/cinder/tests/unit/test_zfssa.py index 719bb8025..a6ec506dc 100644 --- a/cinder/tests/unit/test_zfssa.py +++ b/cinder/tests/unit/test_zfssa.py @@ -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): diff --git a/cinder/volume/drivers/zfssa/zfssaiscsi.py b/cinder/volume/drivers/zfssa/zfssaiscsi.py index 642b85fe5..f446f924c 100644 --- a/cinder/volume/drivers/zfssa/zfssaiscsi.py +++ b/cinder/volume/drivers/zfssa/zfssaiscsi.py @@ -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 diff --git a/cinder/volume/drivers/zfssa/zfssarest.py b/cinder/volume/drivers/zfssa/zfssarest.py index de1c5d9ff..2d07f166d 100644 --- a/cinder/volume/drivers/zfssa/zfssarest.py +++ b/cinder/volume/drivers/zfssa/zfssarest.py @@ -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