Skip to content

Commit f571341

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Fix inaccurate usage reporting when delayed_delete is enabled"
2 parents 6c33a66 + 13b3c72 commit f571341

File tree

2 files changed

+65
-4
lines changed

2 files changed

+65
-4
lines changed

glance/db/sqlalchemy/api.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,8 @@ def _image_get_disk_usage_by_owner(context, session, owner, image_id=None):
777777
if image_id is not None:
778778
query = query.filter(models.Image.id != image_id)
779779
query = query.filter(models.Image.size > 0)
780-
query = query.filter(~models.Image.status.in_(['killed', 'deleted']))
780+
query = query.filter(~models.Image.status.in_([
781+
'killed', 'deleted', 'pending_delete']))
781782
images = query.all()
782783

783784
total = 0
@@ -815,7 +816,8 @@ def _image_get_staging_usage_by_owner(context, session, owner):
815816
query = query.filter(~models.Image.status.in_(('uploading',
816817
'importing',
817818
'killed',
818-
'deleted')))
819+
'deleted',
820+
'pending_delete')))
819821
copying_images = query.all()
820822

821823
return sum(i.size for i in itertools.chain(importing_images,
@@ -825,7 +827,8 @@ def _image_get_staging_usage_by_owner(context, session, owner):
825827
def _image_get_count_by_owner(context, session, owner):
826828
query = session.query(models.Image)
827829
query = query.filter(models.Image.owner == owner)
828-
query = query.filter(~models.Image.status.in_(['killed', 'deleted']))
830+
query = query.filter(~models.Image.status.in_([
831+
'killed', 'pending_delete', 'deleted']))
829832
return query.count()
830833

831834

@@ -850,7 +853,8 @@ def _image_get_uploading_count_by_owner(context, session, owner):
850853
query = query.join(props, props.c.image_id == models.Image.id)
851854
query = query.filter(models.Image.owner == owner)
852855
query = query.filter(~models.Image.status.in_(importing_statuses +
853-
('killed', 'deleted')))
856+
('killed', 'deleted',
857+
'pending_delete')))
854858
copying = query.count()
855859

856860
return uploading + copying

glance/tests/functional/v2/test_images.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
from glance.api import policy
3737
from glance.common import wsgi
38+
from glance import context
39+
import glance.db as db_api
3840
from glance.quota import keystone as ks_quota
3941
from glance.tests import functional
4042
from glance.tests.functional import ft_utils as func_utils
@@ -4549,6 +4551,61 @@ def test_uploading_methods(self):
45494551
# Make sure we can still import.
45504552
self._create_and_import(stores=['store1'])
45514553

4554+
def test_image_count_total_with_delayed_delete(self):
4555+
self.config(delayed_delete=True)
4556+
self.set_limit({'image_size_total': 100,
4557+
'image_stage_total': 10,
4558+
'image_count_total': 1,
4559+
'image_count_uploading': 10})
4560+
self.start_server()
4561+
# Create an image
4562+
image_id = self._create_and_upload()
4563+
# Make sure we can not create any more images.
4564+
resp = self._create()
4565+
self.assertEqual(413, resp.status_code)
4566+
4567+
# Delete one image, which should put us under quota
4568+
self.api_delete('/v2/images/%s' % image_id)
4569+
4570+
# Verify image is in pending_delete state
4571+
image = self._get_pending_delete_image(image_id)
4572+
self.assertEqual('pending_delete', image['status'])
4573+
4574+
# Now we can create that image
4575+
self._create()
4576+
4577+
def test_image_size_total_with_delayed_delete(self):
4578+
self.config(delayed_delete=True)
4579+
self.set_limit({'image_size_total': 6,
4580+
'image_stage_total': 10,
4581+
'image_count_total': 10,
4582+
'image_count_uploading': 1})
4583+
self.start_server()
4584+
# Create an image
4585+
image_id = self._create_and_upload(
4586+
data_iter=test_utils.FakeData(8 * units.Mi))
4587+
# Make sure we can not upload any more images.
4588+
self._create_and_upload(expected_code=413)
4589+
4590+
# Delete one image, which should put us under quota
4591+
self.api_delete('/v2/images/%s' % image_id)
4592+
4593+
# Verify image is in pending_delete state
4594+
image = self._get_pending_delete_image(image_id)
4595+
self.assertEqual('pending_delete', image['status'])
4596+
4597+
# Now we can create that image
4598+
self._create_and_upload()
4599+
4600+
def _get_pending_delete_image(self, image_id):
4601+
# In Glance V2, there is no way to get the 'pending_delete' image from
4602+
# API. So we get the image from db here for testing.
4603+
# Clean the session cache first to avoid connecting to the old db data.
4604+
admin_context = context.get_admin_context(show_deleted=True)
4605+
db_api.get_api()._FACADE = None
4606+
image = db_api.get_api().image_get(admin_context, image_id)
4607+
return image
4608+
45524609

45534610
class TestStoreWeight(functional.SynchronousAPIBase):
45544611
def setUp(self):

0 commit comments

Comments
 (0)