summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2014-03-03 09:03:46 -0500
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2014-03-03 09:06:10 -0500
commita6ae7149bd9ba423fb55eacc6eb8f0c1f49c2dc7 (patch)
treea49fe59b88cafa6dc665e477d060f88a52891630
parente7d8c70958e80924408c0e31fa06f1ad06607f99 (diff)
downloadbcfg2-a6ae7149bd9ba423fb55eacc6eb8f0c1f49c2dc7.tar.gz
bcfg2-a6ae7149bd9ba423fb55eacc6eb8f0c1f49c2dc7.tar.bz2
bcfg2-a6ae7149bd9ba423fb55eacc6eb8f0c1f49c2dc7.zip
Core: close all database connections at the end of XML-RPC requests
-rw-r--r--src/lib/Bcfg2/Server/Core.py32
1 files changed, 26 insertions, 6 deletions
diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py
index 03bc7bff4..a8069ff1b 100644
--- a/src/lib/Bcfg2/Server/Core.py
+++ b/src/lib/Bcfg2/Server/Core.py
@@ -18,7 +18,7 @@ import Bcfg2.Server.FileMonitor
from Bcfg2.Cache import Cache
import Bcfg2.Statistics
from itertools import chain
-from Bcfg2.Compat import xmlrpclib # pylint: disable=W0622
+from Bcfg2.Compat import xmlrpclib, wraps # pylint: disable=W0622
from Bcfg2.Server.Plugin.exceptions import * # pylint: disable=W0401,W0614
from Bcfg2.Server.Plugin.interfaces import * # pylint: disable=W0401,W0614
from Bcfg2.Server.Plugin import track_statistics
@@ -67,6 +67,24 @@ def sort_xml(node, key=None):
node[:] = sorted_children
+def close_db_connection(func):
+ """ Decorator that closes the Django database connection at the end of
+ the function. This should decorate any exposed function that
+ might open a database connection. """
+ @wraps(func)
+ def inner(self, *args, **kwargs):
+ """ The decorated function """
+ rv = func(self, *args, **kwargs)
+ if self._database_available: # pylint: disable=W0212
+ from django import db
+ self.logger.debug("%s: Closing database connection" %
+ threading.current_thread().name)
+ db.close_connection()
+ return rv
+
+ return inner
+
+
class CoreInitError(Exception):
""" Raised when the server core cannot be initialized. """
pass
@@ -741,11 +759,6 @@ class BaseCore(object):
self.validate_goals(meta, config)
self.client_run_hook("end_client_run", meta)
- if self._database_available:
- from django import db
- self.logger.debug("%s: Closing database connection" %
- threading.current_thread().name)
- db.close_connection()
sort_xml(config, key=lambda e: e.get('name'))
@@ -1089,6 +1102,7 @@ class BaseCore(object):
@exposed
@track_statistics()
+ @close_db_connection
def DeclareVersion(self, address, version):
""" Declare the client version.
@@ -1111,6 +1125,7 @@ class BaseCore(object):
return True
@exposed
+ @close_db_connection
def GetProbes(self, address):
""" Fetch probes for the client.
@@ -1136,6 +1151,7 @@ class BaseCore(object):
(client, err))
@exposed
+ @close_db_connection
def RecvProbeData(self, address, probedata):
""" Receive probe data from clients.
@@ -1183,6 +1199,7 @@ class BaseCore(object):
return True
@exposed
+ @close_db_connection
def AssertProfile(self, address, profile):
""" Set profile for a client.
@@ -1202,6 +1219,7 @@ class BaseCore(object):
return True
@exposed
+ @close_db_connection
def GetConfig(self, address):
""" Build config for a client by calling
:func:`BuildConfiguration`.
@@ -1221,6 +1239,7 @@ class BaseCore(object):
self.critical_error("Metadata consistency failure for %s" % client)
@exposed
+ @close_db_connection
def RecvStats(self, address, stats):
""" Act on statistics upload with :func:`process_statistics`.
@@ -1258,6 +1277,7 @@ class BaseCore(object):
address)
@exposed
+ @close_db_connection
def GetDecisionList(self, address, mode):
""" Get the decision list for the client with :func:`GetDecisions`.