From: wanghao Date: Mon, 9 Mar 2015 10:49:31 +0000 (+0800) Subject: Fix response when querying host detail by host name X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=af853d479b70c22d60ae09e798ef4c3b62632fb2;p=openstack-build%2Fcinder-build.git Fix response when querying host detail by host name When querying host detail by host name like 'wanghao-devstack-snapshot@lvmdriver-1' returned by host list command, cinder returns incorrect result in 'total' block. "resource": { "volume_count": "0", "total_volume_gb": "0", "total_snapshot_gb": "0", "project": "(total)", "host": "wanghao-devstack-snapshot@lvmdriver-1", "snapshot_count": "0" } This issue is caused by 'volume_data_get_for_host' in sqlalchemy. This has nothing to do with multibackend, this is due to the introduction of pool support for single backend. Fix this by querying volume filter by host or host name like 'host#%' in volume_data_get_for_host. Change-Id: I751a474677d50e552d87fe06fadfed45e3c1ddab Closes-Bug: #1429787 --- diff --git a/cinder/db/sqlalchemy/api.py b/cinder/db/sqlalchemy/api.py index 17199ad99..bbf0cb072 100644 --- a/cinder/db/sqlalchemy/api.py +++ b/cinder/db/sqlalchemy/api.py @@ -1075,20 +1075,20 @@ def volume_create(context, values): @require_admin_context def volume_data_get_for_host(context, host, count_only=False): + host_attr = models.Volume.host + conditions = [host_attr == host, host_attr.op('LIKE')(host + '#%')] if count_only: result = model_query(context, func.count(models.Volume.id), - read_deleted="no").\ - filter_by(host=host).\ - first() + read_deleted="no").filter( + or_(*conditions)).first() return result[0] or 0 else: result = model_query(context, func.count(models.Volume.id), func.sum(models.Volume.size), - read_deleted="no").\ - filter_by(host=host).\ - first() + read_deleted="no").filter( + or_(*conditions)).first() # NOTE(vish): convert None to 0 return (result[0] or 0, result[1] or 0) diff --git a/cinder/tests/unit/test_db_api.py b/cinder/tests/unit/test_db_api.py index 85147ae9e..082572cfc 100644 --- a/cinder/tests/unit/test_db_api.py +++ b/cinder/tests/unit/test_db_api.py @@ -29,6 +29,10 @@ from cinder import test CONF = cfg.CONF +THREE = 3 +THREE_HUNDREDS = 300 +ONE_HUNDREDS = 100 + def _quota_reserve(context, project_id): """Create sample Quota, QuotaUsage and Reservation objects. @@ -264,23 +268,35 @@ class DBAPIVolumeTestCase(BaseTest): self.assertEqual(attachment['attached_host'], host_name) def test_volume_data_get_for_host(self): - for i in xrange(3): - for j in xrange(3): - db.volume_create(self.ctxt, {'host': 'h%d' % i, 'size': 100}) - for i in xrange(3): - self.assertEqual((3, 300), + for i in xrange(THREE): + for j in xrange(THREE): + db.volume_create(self.ctxt, {'host': 'h%d' % i, + 'size': ONE_HUNDREDS}) + for i in xrange(THREE): + self.assertEqual((THREE, THREE_HUNDREDS), db.volume_data_get_for_host( self.ctxt, 'h%d' % i)) + def test_volume_data_get_for_host_for_multi_backend(self): + for i in xrange(THREE): + for j in xrange(THREE): + db.volume_create(self.ctxt, {'host': + 'h%d@lvmdriver-1#lvmdriver-1' % i, + 'size': ONE_HUNDREDS}) + for i in xrange(THREE): + self.assertEqual((THREE, THREE_HUNDREDS), + db.volume_data_get_for_host( + self.ctxt, 'h%d@lvmdriver-1' % i)) + def test_volume_data_get_for_project(self): - for i in xrange(3): - for j in xrange(3): + for i in xrange(THREE): + for j in xrange(THREE): db.volume_create(self.ctxt, {'project_id': 'p%d' % i, - 'size': 100, + 'size': ONE_HUNDREDS, 'host': 'h-%d-%d' % (i, j), }) - for i in xrange(3): - self.assertEqual((3, 300), + for i in xrange(THREE): + self.assertEqual((THREE, THREE_HUNDREDS), db.volume_data_get_for_project( self.ctxt, 'p%d' % i))