Skip to content

Commit

Permalink
Fix mysql checkout handler AttributeError
Browse files Browse the repository at this point in the history
If the mysql_on_checkout handler encountered an error due to
disconnect, it would fail with an AttributeError,

 AttributeError: 'module' object has no attribute 'warn'

This is because it used the logging module where the LOG logger
should have been used.

Change-Id: Iae8a9bd4aeee6e35508059c20b92d70c36232963
Closes-Bug: #1234873
  • Loading branch information
Brant Knudson committed Oct 3, 2013
1 parent a513ea7 commit d973ea9
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
2 changes: 1 addition & 1 deletion keystone/common/sql/core.py
Expand Up @@ -204,7 +204,7 @@ def mysql_on_checkout(dbapi_conn, connection_rec, connection_proxy):
dbapi_conn.cursor().execute('select 1')
except dbapi_conn.OperationalError as e:
if e.args[0] in (2006, 2013, 2014, 2045, 2055):
logging.warn(_('Got mysql server has gone away: %s'), e)
LOG.warn(_('Got mysql server has gone away: %s'), e)
raise DisconnectionError("Database server went away")
else:
raise
Expand Down
58 changes: 58 additions & 0 deletions keystone/tests/test_sql_core.py
Expand Up @@ -13,6 +13,8 @@
# under the License.


from sqlalchemy.exc import DisconnectionError

from keystone.common import sql
from keystone import tests

Expand Down Expand Up @@ -180,3 +182,59 @@ def test_get_session_invalidated(self):
sql.set_global_engine(None)
session2 = base.get_session()
self.assertIsNot(session1.bind, session2.bind)


class FakeDbapiConn(object):
"""Simulates the dbapi_conn passed to mysql_on_checkout."""

class OperationalError(Exception):
pass

class Cursor(object):
def __init__(self, failwith=None):
self._failwith = failwith

def execute(self, sql):
if self._failwith:
raise self._failwith

def __init__(self, failwith=None):
self._cursor = self.Cursor(failwith=failwith)

def cursor(self):
return self._cursor


class TestCheckoutHandler(tests.TestCase):
def _do_on_checkout(self, failwith=None):
dbapi_conn = FakeDbapiConn(failwith=failwith)
connection_rec = None
connection_proxy = None
sql.mysql_on_checkout(dbapi_conn, connection_rec, connection_proxy)

def test_checkout_success(self):
# If call mysql_on_checkout and query doesn't raise anything, then no
# problems

# If this doesn't raise then the test is successful.
self._do_on_checkout()

def test_disconnected(self):
# If call mysql_on_checkout and query raises OperationalError with
# specific errors, then raises DisconnectionError.

# mysql_on_checkout should look for 2006 among others.
disconnected_exception = FakeDbapiConn.OperationalError(2006)
self.assertRaises(DisconnectionError,
self._do_on_checkout,
failwith=disconnected_exception)

def test_error(self):
# If call mysql_on_checkout and query raises an exception that doesn't
# indicate disconnected, then the original error is raised.

# mysql_on_checkout doesn't look for 2056
other_exception = FakeDbapiConn.OperationalError(2056)
self.assertRaises(FakeDbapiConn.OperationalError,
self._do_on_checkout,
failwith=other_exception)

0 comments on commit d973ea9

Please sign in to comment.