Skip to content

Commit

Permalink
Don't fail response if caching failed
Browse files Browse the repository at this point in the history
Fixes bug 929762

Change-Id: I90761b69cc556b14fd4bdb931541804244b653e8
  • Loading branch information
Mark Washenberger committed Feb 10, 2012
1 parent e4db87c commit 481929b
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 5 deletions.
1 change: 1 addition & 0 deletions Authors
Expand Up @@ -28,6 +28,7 @@ Kevin L. Mitchell <kevin.mitchell@rackspace.com>
Lorin Hochstein <lorin@isi.edu>
Major Hayden <major@mhtx.net>
Mark McLoughlin <markmc@redhat.com>
Mark Washenberger <mark.washenberger@rackspace.com>
Matt Dietz <matt.dietz@rackspace.com>
Mike Lundy <mike@pistoncloud.com>
Monty Taylor <mordred@inaugust.com>
Expand Down
21 changes: 16 additions & 5 deletions glance/image_cache/__init__.py
Expand Up @@ -220,11 +220,22 @@ def get_caching_iter(self, image_id, image_iter):
logger.debug(_("Tee'ing image '%s' into cache"), image_id)

def tee_iter(image_id):
with self.driver.open_for_write(image_id) as cache_file:
for chunk in image_iter:
cache_file.write(chunk)
yield chunk
cache_file.flush()
try:
with self.driver.open_for_write(image_id) as cache_file:
for chunk in image_iter:
try:
cache_file.write(chunk)
finally:
yield chunk
cache_file.flush()
except Exception:
logger.exception(_("Exception encountered while tee'ing "
"image '%s' into cache. Continuing "
"with response.") % image_id)

# NOTE(markwash): continue responding even if caching failed
for chunk in image_iter:
yield chunk

return tee_iter(image_id)

Expand Down
61 changes: 61 additions & 0 deletions glance/tests/unit/test_image_cache.py
Expand Up @@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.

from contextlib import contextmanager
import os
import random
import shutil
Expand All @@ -24,6 +25,7 @@
import stubout

from glance import image_cache
from glance.common import cfg
from glance.common import exception
from glance.common import utils
from glance.tests import utils as test_utils
Expand Down Expand Up @@ -308,3 +310,62 @@ def setUp(self):
def tearDown(self):
if os.path.exists(self.cache_dir):
shutil.rmtree(self.cache_dir)


class TestImageCacheNoDep(unittest.TestCase):

def setUp(self):
self.driver = None

def init_driver(self2):
self2.driver = self.driver

self.stubs = stubout.StubOutForTesting()
self.stubs.Set(image_cache.ImageCache, 'init_driver', init_driver)

def tearDown(self):
self.stubs.UnsetAll()

def test_get_caching_iter_when_write_fails(self):

class FailingFile(object):

def write(self, data):
if data == "Fail":
raise IOError

class FailingFileDriver(object):

def is_cacheable(self, *args, **kwargs):
return True

@contextmanager
def open_for_write(self, *args, **kwargs):
yield FailingFile()

self.driver = FailingFileDriver()
conf = cfg.ConfigOpts()
cache = image_cache.ImageCache(conf)
data = ['a', 'b', 'c', 'Fail', 'd', 'e', 'f']

caching_iter = cache.get_caching_iter('dummy_id', iter(data))
self.assertEqual(list(caching_iter), data)

def test_get_caching_iter_when_open_fails(self):

class OpenFailingDriver(object):

def is_cacheable(self, *args, **kwargs):
return True

@contextmanager
def open_for_write(self, *args, **kwargs):
raise IOError

self.driver = OpenFailingDriver()
conf = cfg.ConfigOpts()
cache = image_cache.ImageCache(conf)
data = ['a', 'b', 'c', 'd', 'e', 'f']

caching_iter = cache.get_caching_iter('dummy_id', iter(data))
self.assertEqual(list(caching_iter), data)

0 comments on commit 481929b

Please sign in to comment.