Add external lock to image cache sqlite driver db init

This commit adds an external lock to sqlite when launching multiple
worker processes (using uwsgi) the db init will fail for one since the 2
workers will race for initializing the DB. The method is idempotent so
we can safely run it twice in succession, but the lock is necessary to
provides us protection against running it at the same time.

Depends-On: I9a66a8636d12037ff9aa4fb73cc3f9b9343dd7e9
Change-Id: I654c3a5604a89402ba94d9cea44699a48583a7e0
This commit is contained in:
Matthew Treinish 2017-04-24 20:08:15 -04:00
parent f786c9270e
commit c09d157960
No known key found for this signature in database
GPG Key ID: FD12A0F214C9E177
4 changed files with 36 additions and 20 deletions

View File

@ -26,6 +26,7 @@ import time
from eventlet import sleep
from eventlet import timeout
from oslo_concurrency import lockutils
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import excutils
@ -119,26 +120,32 @@ class Driver(base.Driver):
def initialize_db(self):
db = CONF.image_cache_sqlite_db
self.db_path = os.path.join(self.base_dir, db)
try:
conn = sqlite3.connect(self.db_path, check_same_thread=False,
factory=SqliteConnection)
conn.executescript("""
CREATE TABLE IF NOT EXISTS cached_images (
image_id TEXT PRIMARY KEY,
last_accessed REAL DEFAULT 0.0,
last_modified REAL DEFAULT 0.0,
size INTEGER DEFAULT 0,
hits INTEGER DEFAULT 0,
checksum TEXT
);
""")
conn.close()
except sqlite3.DatabaseError as e:
msg = _("Failed to initialize the image cache database. "
"Got error: %s") % e
LOG.error(msg)
raise exception.BadDriverConfiguration(driver_name='sqlite',
reason=msg)
lockutils.set_defaults(self.base_dir)
@lockutils.synchronized('image_cache_db_init', external=True)
def create_db():
try:
conn = sqlite3.connect(self.db_path, check_same_thread=False,
factory=SqliteConnection)
conn.executescript("""
CREATE TABLE IF NOT EXISTS cached_images (
image_id TEXT PRIMARY KEY,
last_accessed REAL DEFAULT 0.0,
last_modified REAL DEFAULT 0.0,
size INTEGER DEFAULT 0,
hits INTEGER DEFAULT 0,
checksum TEXT
);
""")
conn.close()
except sqlite3.DatabaseError as e:
msg = _("Failed to initialize the image cache database. "
"Got error: %s") % e
LOG.error(msg)
raise exception.BadDriverConfiguration(driver_name='sqlite',
reason=msg)
create_db()
def get_cache_size(self):
"""

View File

@ -214,6 +214,7 @@ class TestBinGlanceCacheManage(functional.FunctionalTest):
'image_cache_dir': self.api_server.image_cache_dir,
'image_cache_driver': self.image_cache_driver,
'registry_port': self.registry_server.bind_port,
'lock_path': self.test_dir,
'log_file': os.path.join(self.test_dir, 'cache.log'),
'metadata_encryption_key': "012345678901234567890123456789ab",
'filesystem_store_datadir': self.test_dir
@ -221,6 +222,7 @@ class TestBinGlanceCacheManage(functional.FunctionalTest):
with open(cache_config_filepath, 'w') as cache_file:
cache_file.write("""[DEFAULT]
debug = True
lock_path = %(lock_path)s
image_cache_dir = %(image_cache_dir)s
image_cache_driver = %(image_cache_driver)s
registry_host = 127.0.0.1

View File

@ -932,12 +932,14 @@ class BaseCacheManageMiddlewareTest(object):
'image_cache_driver': self.image_cache_driver,
'registry_port': self.registry_server.bind_port,
'log_file': os.path.join(self.test_dir, 'cache.log'),
'lock_path': self.test_dir,
'metadata_encryption_key': "012345678901234567890123456789ab",
'filesystem_store_datadir': self.test_dir
}
with open(cache_config_filepath, 'w') as cache_file:
cache_file.write("""[DEFAULT]
debug = True
lock_path = %(lock_path)s
image_cache_dir = %(image_cache_dir)s
image_cache_driver = %(image_cache_driver)s
registry_host = 127.0.0.1

View File

@ -0,0 +1,5 @@
---
upgrade:
- The lock_path config option from oslo.concurrency is now required for using
the sql image_cache driver. If one is not specified it will default to
the image_cache_dir and emit a warning.