From ffc3923e93dc1d4eea789ce5163d176efb7d685b Mon Sep 17 00:00:00 2001 From: Abhishek Kekane Date: Tue, 28 Nov 2017 09:51:02 +0000 Subject: [PATCH] Fix unreachable 'ImageSizeLimitExceeded' exception in image-upload ImageSizeLimitExceeded exception block [1] is unreachable in upload because it is caught at [2] and raised StorageQuotaFull exception from there. The problem here is that we have nested usage of the limiting reader. To make it correct changed the limiting reader to accept exception class as parameter so that we can pass the StorageQuotaFull in case LimitingReader is used for quota check and ImageSizeExceeded exception if it is used for image size cap check. [1] https://github.com/openstack/glance/blob/fd16fa4f258fd3f77c14900a019e97bb90bc5ac0/glance/api/v2/image_data.py#L230 [2] https://github.com/openstack/glance/blob/fd16fa4f258fd3f77c14900a019e97bb90bc5ac0/glance/quota/__init__.py#L305 Closes-Bug: #1734832 Change-Id: I5a419b763bee7f983c2a94c6f3a2245281e86743 --- glance/common/utils.py | 9 ++++++--- glance/quota/__init__.py | 10 ++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/glance/common/utils.py b/glance/common/utils.py index 3dbc2160b0..05ff3df513 100644 --- a/glance/common/utils.py +++ b/glance/common/utils.py @@ -271,20 +271,23 @@ class LimitingReader(object): Reader designed to fail when reading image data past the configured allowable amount. """ - def __init__(self, data, limit): + def __init__(self, data, limit, + exception_class=exception.ImageSizeLimitExceeded): """ :param data: Underlying image data object :param limit: maximum number of bytes the reader should allow + :param exception_class: Type of exception to be raised """ self.data = data self.limit = limit self.bytes_read = 0 + self.exception_class = exception_class def __iter__(self): for chunk in self.data: self.bytes_read += len(chunk) if self.bytes_read > self.limit: - raise exception.ImageSizeLimitExceeded() + raise self.exception_class() else: yield chunk @@ -292,7 +295,7 @@ class LimitingReader(object): result = self.data.read(i) self.bytes_read += len(result) if self.bytes_read > self.limit: - raise exception.ImageSizeLimitExceeded() + raise self.exception_class() return result diff --git a/glance/quota/__init__.py b/glance/quota/__init__.py index ee16a0c136..0e2ce4fa7e 100644 --- a/glance/quota/__init__.py +++ b/glance/quota/__init__.py @@ -299,12 +299,10 @@ class ImageProxy(glance.domain.proxy.Image): if remaining is not None: # NOTE(jbresnah) we are trying to enforce a quota, put a limit # reader on the data - data = utils.LimitingReader(data, remaining) - try: - self.image.set_data(data, size=size) - except exception.ImageSizeLimitExceeded: - raise exception.StorageQuotaFull(image_size=size, - remaining=remaining) + data = utils.LimitingReader( + data, remaining, exception_class=exception.StorageQuotaFull) + + self.image.set_data(data, size=size) # NOTE(jbresnah) If two uploads happen at the same time and neither # properly sets the size attribute[1] then there is a race condition