summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Bcfg2/Reporting/templates/base.html2
-rwxr-xr-xsrc/lib/Bcfg2/Server/Encryption.py34
-rw-r--r--src/lib/Bcfg2/Server/MultiprocessingCore.py35
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Probes.py14
-rw-r--r--src/lib/Bcfg2/version.py2
5 files changed, 53 insertions, 34 deletions
diff --git a/src/lib/Bcfg2/Reporting/templates/base.html b/src/lib/Bcfg2/Reporting/templates/base.html
index 0b2b7dd36..7edf3a949 100644
--- a/src/lib/Bcfg2/Reporting/templates/base.html
+++ b/src/lib/Bcfg2/Reporting/templates/base.html
@@ -93,7 +93,7 @@ This is needed for Django versions less than 1.5
<div style='clear:both'></div>
</div><!-- document -->
<div id="footer">
- <span>Bcfg2 Version 1.3.2</span>
+ <span>Bcfg2 Version 1.3.3</span>
</div>
<div id="calendar_div" style='position:absolute; visibility:hidden; background-color:white; layer-background-color:white;'></div>
diff --git a/src/lib/Bcfg2/Server/Encryption.py b/src/lib/Bcfg2/Server/Encryption.py
index c0c2816ac..02c7a0eb8 100755
--- a/src/lib/Bcfg2/Server/Encryption.py
+++ b/src/lib/Bcfg2/Server/Encryption.py
@@ -197,6 +197,33 @@ def bruteforce_decrypt(crypted, passphrases=None, algorithm=None):
raise EVPError("Failed to decrypt")
+def print_xml(element, keep_text=False):
+ """ Render an XML element for error output. This prefixes the
+ line number and removes children for nicer display.
+
+ :param element: The element to render
+ :type element: lxml.etree._Element
+ :param keep_text: Do not discard text content from the element for
+ display
+ :type keep_text: boolean
+ """
+ xml = None
+ if len(element) or element.text:
+ el = copy.copy(element)
+ if el.text and not keep_text:
+ el.text = '...'
+ for child in el.iterchildren():
+ el.remove(child)
+ xml = lxml.etree.tostring(
+ el,
+ xml_declaration=False).decode("UTF-8").strip()
+ else:
+ xml = lxml.etree.tostring(
+ element,
+ xml_declaration=False).decode("UTF-8").strip()
+ return "%s (line %s)" % (xml, element.sourceline)
+
+
class PassphraseError(Exception):
""" Exception raised when there's a problem determining the
passphrase to encrypt or decrypt with """
@@ -403,6 +430,7 @@ class PropertiesEncryptor(Encryptor, PropertiesCryptoMixin):
except PassphraseError:
self.logger.error(str(sys.exc_info()[1]))
return False
+ self.logger.debug("Encrypting %s" % print_xml(elt))
elt.text = ssl_encrypt(elt.text, passphrase).strip()
elt.set("encrypted", pname)
return xdata
@@ -423,10 +451,14 @@ class PropertiesDecryptor(Decryptor, PropertiesCryptoMixin):
except PassphraseError:
self.logger.error(str(sys.exc_info()[1]))
return False
- decrypted = ssl_decrypt(elt.text, passphrase).strip()
+ self.logger.debug("Decrypting %s" % print_xml(elt))
try:
+ decrypted = ssl_decrypt(elt.text, passphrase).strip()
elt.text = decrypted.encode('ascii', 'xmlcharrefreplace')
elt.set("encrypted", pname)
+ except Bcfg2.Encryption.EVPError:
+ self.logger.error("Could not decrypt %s, skipping" %
+ print_xml(elt))
except UnicodeDecodeError:
# we managed to decrypt the value, but it contains
# content that can't even be encoded into xml
diff --git a/src/lib/Bcfg2/Server/MultiprocessingCore.py b/src/lib/Bcfg2/Server/MultiprocessingCore.py
index 58a05c85d..f58d53c42 100644
--- a/src/lib/Bcfg2/Server/MultiprocessingCore.py
+++ b/src/lib/Bcfg2/Server/MultiprocessingCore.py
@@ -19,7 +19,7 @@ import Bcfg2.Options
import Bcfg2.Server.Cache
import Bcfg2.Server.Plugin
from itertools import cycle
-from Bcfg2.Compat import Queue, Empty, wraps
+from Bcfg2.Compat import Empty, wraps
from Bcfg2.Server.Core import Core, exposed
from Bcfg2.Server.BuiltinCore import BuiltinCore
from multiprocessing.connection import Listener, Client
@@ -41,8 +41,7 @@ class RPCQueue(Bcfg2.Server.Plugin.Debuggable):
Bcfg2.Server.Plugin.Debuggable.__init__(self)
self._terminate = threading.Event()
self._queues = dict()
- self._available_listeners = Queue()
- self._blocking_listeners = []
+ self._listeners = []
def add_subscriber(self, name):
""" Add a subscriber to the queue. This returns the
@@ -63,23 +62,14 @@ class RPCQueue(Bcfg2.Server.Plugin.Debuggable):
:class:`multiprocessing.connection.Listener` and passes the
Listener address to the child as part of the RPC call, so that
the child can connect to the Listener to submit its results.
-
- Listeners are reused when possible to minimize overhead.
"""
- try:
- listener = self._available_listeners.get_nowait()
- self.logger.debug("Reusing existing RPC listener at %s" %
- listener.address)
- except Empty:
- listener = Listener()
- self.logger.debug("Created new RPC listener at %s" %
- listener.address)
- self._blocking_listeners.append(listener)
+ listener = Listener()
+ self.logger.debug("Created new RPC listener at %s" % listener.address)
+ self._listeners.append(listener)
try:
self._queues[dest].put((listener.address,
(method, args or [], kwargs or dict())))
conn = listener.accept()
- self._blocking_listeners.remove(listener)
try:
while not self._terminate.is_set():
if conn.poll(self.poll_wait):
@@ -87,7 +77,8 @@ class RPCQueue(Bcfg2.Server.Plugin.Debuggable):
finally:
conn.close()
finally:
- self._available_listeners.put(listener)
+ listener.close()
+ self._listeners.remove(listener)
def close(self):
""" Close queues and connections. """
@@ -99,21 +90,11 @@ class RPCQueue(Bcfg2.Server.Plugin.Debuggable):
# close any listeners that are waiting for connections
self.logger.debug("Closing RPC connections")
- for listener in self._blocking_listeners:
+ for listener in self._listeners:
self.logger.debug("Closing RPC connection at %s" %
listener.address)
listener.close()
- self.logger.debug("Closing RPC listeners")
- try:
- while True:
- listener = self._available_listeners.get_nowait()
- self.logger.debug("Closing RPC listener at %s" %
- listener.address)
- listener.close()
- except Empty:
- pass
-
class DualEvent(object):
""" DualEvent is a clone of :class:`threading.Event` that
diff --git a/src/lib/Bcfg2/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py
index ec5c1ab9f..9f2375fcd 100644
--- a/src/lib/Bcfg2/Server/Plugins/Probes.py
+++ b/src/lib/Bcfg2/Server/Plugins/Probes.py
@@ -175,9 +175,16 @@ class DBProbeStore(ProbeStore, Bcfg2.Server.Plugin.DatabaseBacked):
expire_metadata = False
for probe, pdata in data.items():
self._datacache[hostname][probe] = pdata
- record, created = ProbesDataModel.objects.get_or_create(
- hostname=hostname,
- probe=probe)
+ try:
+ record, created = ProbesDataModel.objects.get_or_create(
+ hostname=hostname,
+ probe=probe)
+ except ProbesDataModel.MultipleObjectsReturned:
+ ProbesDataModel.objects.filter(hostname=hostname,
+ probe=probe).delete()
+ record, created = ProbesDataModel.objects.get_or_create(
+ hostname=hostname,
+ probe=probe)
expire_metadata |= created
if record.data != pdata:
record.data = pdata
@@ -447,7 +454,6 @@ class Probes(Bcfg2.Server.Plugin.Probing,
def GetProbes(self, metadata):
return self.probes.get_probe_data(metadata)
- @track_statistics()
def ReceiveData(self, client, datalist):
cgroups = set()
cdata = dict()
diff --git a/src/lib/Bcfg2/version.py b/src/lib/Bcfg2/version.py
index 140fb6937..35d4cfa0a 100644
--- a/src/lib/Bcfg2/version.py
+++ b/src/lib/Bcfg2/version.py
@@ -2,7 +2,7 @@
import re
-__version__ = "1.3.2"
+__version__ = "1.3.3"
class Bcfg2VersionInfo(tuple): # pylint: disable=E0012,R0924