Don't fail response if caching failed

Fixes bug 929762

Change-Id: I90761b69cc556b14fd4bdb931541804244b653e8
This commit is contained in:
Mark Washenberger 2012-02-09 12:59:49 -05:00
parent e4db87ce4c
commit 481929b5c5
3 changed files with 78 additions and 5 deletions

View File

@ -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>

View File

@ -220,11 +220,22 @@ class ImageCache(object):
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)

View File

@ -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
@ -24,6 +25,7 @@ import unittest
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
@ -308,3 +310,62 @@ class TestImageCacheSqlite(unittest.TestCase,
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)