Merge ~blake-rouse/maas:fix-bad-postgres-connection into maas:master

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: b843207535c85c8ca2fdfd9bc61976da4186108b
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~blake-rouse/maas:fix-bad-postgres-connection
Merge into: maas:master
Diff against target: 57 lines (+27/-0)
2 files modified
src/maasserver/utils/orm.py (+11/-0)
src/maasserver/utils/tests/test_orm.py (+16/-0)
Reviewer Review Type Date Requested Status
Mike Pontillo (community) Approve
Review via email: mp+332741@code.launchpad.net

Commit message

Ensure a good postgresql connection with the connected utility.

All the twisted helpers including the deferToDatabase use the connected() utility. This utility was not verifying that the postgresql connection that it could use was actually a good connection. This now ensures that it is a usable connection before yielding.

Description of the change

How to test:

sudo systemctl start postgresql
sudo systemctl start maas-regiond
sudo systemctl restart postgresql
sudo systemctl start maas-rackd

No stacktrace will occur with "connection already closed". Before this patch "sudo systemctl restart postgresql" would cause the regiond processes to hold onto a connection to a dead postgresql process.

To post a comment you must log in.
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/utils/orm.py b/src/maasserver/utils/orm.py
2index 2ec0590..40f8a3f 100644
3--- a/src/maasserver/utils/orm.py
4+++ b/src/maasserver/utils/orm.py
5@@ -616,14 +616,25 @@ def connected():
6
7 If there is not yet a connection to the database, this will connect on
8 entry and disconnect on exit. Preexisting connections will be left alone.
9+
10+ If the preexisting connection is not usable it is closed and a new
11+ connection is made.
12 """
13 if connection.connection is None:
14+ connection.close_if_unusable_or_obsolete()
15 connection.ensure_connection()
16 try:
17 yield
18 finally:
19 connection.close()
20+ elif connection.is_usable():
21+ yield
22 else:
23+ # Connection is not usable, so we disconnect and reconnect. Since
24+ # the connection was previously connected we do not disconnect this
25+ # new connection.
26+ connection.close_if_unusable_or_obsolete()
27+ connection.ensure_connection()
28 yield
29
30
31diff --git a/src/maasserver/utils/tests/test_orm.py b/src/maasserver/utils/tests/test_orm.py
32index 064f1b0..94ee817 100644
33--- a/src/maasserver/utils/tests/test_orm.py
34+++ b/src/maasserver/utils/tests/test_orm.py
35@@ -1004,6 +1004,22 @@ class TestConnected(MAASTransactionServerTestCase):
36 self.assertThat(connection.connection, Is(preexisting_connection))
37 self.assertThat(connection.connection, Is(preexisting_connection))
38
39+ def test__disconnects_and_reconnects_if_not_usable(self):
40+ connection.ensure_connection()
41+ preexisting_connection = connection.connection
42+
43+ connection.errors_occurred = True
44+ self.patch(connection, "is_usable").return_value = False
45+
46+ self.assertThat(connection.connection, Not(Is(None)))
47+ with orm.connected():
48+ self.assertThat(
49+ connection.connection, Not(Is(preexisting_connection)))
50+ self.assertThat(connection.connection, Not(Is(None)))
51+
52+ self.assertThat(connection.connection, Not(Is(preexisting_connection)))
53+ self.assertThat(connection.connection, Not(Is(None)))
54+
55
56 class TestWithConnection(MAASTransactionServerTestCase):
57 """Tests for the `orm.with_connection` decorator."""

Subscribers

People subscribed via source and target branches