summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/appendix/guides/import-existing-ssh-keys.txt7
-rw-r--r--doc/development/testing.txt4
-rw-r--r--doc/installation/building-packages.txt1
-rw-r--r--doc/server/plugins/generators/sshbase.txt8
-rw-r--r--doc/unsorted/emacs_snippet.txt2
-rw-r--r--doc/unsorted/vim_snippet.txt6
-rw-r--r--src/lib/Bcfg2/Client/Tools/Systemd.py2
-rw-r--r--src/lib/Bcfg2/Reporting/Collector.py16
-rw-r--r--src/lib/Bcfg2/Reporting/Storage/DjangoORM.py7
-rw-r--r--src/lib/Bcfg2/Server/Core.py39
-rw-r--r--src/lib/Bcfg2/Server/Plugin/helpers.py3
11 files changed, 69 insertions, 26 deletions
diff --git a/doc/appendix/guides/import-existing-ssh-keys.txt b/doc/appendix/guides/import-existing-ssh-keys.txt
index 64a1b62cd..a0a628c58 100644
--- a/doc/appendix/guides/import-existing-ssh-keys.txt
+++ b/doc/appendix/guides/import-existing-ssh-keys.txt
@@ -1,4 +1,5 @@
.. -*- mode: rst -*-
+.. vim: ft=rst
.. _appendix-guides-import-existing-ssh-keys:
@@ -25,6 +26,10 @@ appropriate entries.::
cat > /tmp/ssh.xml << EOF
<Bundle name='ssh'>
+ <!-- requires a version of openssh that can generate ecdsa keys -->
+ <Path name="/etc/ssh/ssh_host_ecdsa_key"/>
+ <Path name="/etc/ssh/ssh_host_ecdsa_key.pub"/>
+
<Path name='/etc/ssh/ssh_host_dsa_key'/>
<Path name='/etc/ssh/ssh_host_rsa_key'/>
<Path name='/etc/ssh/ssh_host_dsa_key.pub'/>
@@ -86,7 +91,7 @@ Now, we pull the ssh host key data for the client out of the uploaded
stats and insert it as host-specific copies of these files in
``/var/lib/bcfg2/SSHBase``.::
- for key in ssh_host_rsa_key ssh_host_dsa_key ssh_host_key; do
+ for key in ssh_host_ecdsa_key ssh_host_rsa_key ssh_host_dsa_key ssh_host_key; do
sudo bcfg2-admin pull <clientname> Path /etc/ssh/$key
sudo bcfg2-admin pull <clientname> Path /etc/ssh/$key.pub
done
diff --git a/doc/development/testing.txt b/doc/development/testing.txt
index f00193574..b6db98cca 100644
--- a/doc/development/testing.txt
+++ b/doc/development/testing.txt
@@ -69,8 +69,8 @@ Server Testing
Entry: fs13.bgl.mcs.anl.gov.xml
Entry: fs13.bgl.mcs.anl.gov.xml good
Entry: login1.bgl.mcs.anl.gov.xml
- ConfigFile /bin/whatami contents differ
- ConfigFile /bin/whatami differs (in bundle softenv)
+ Path /bin/whatami contents differ
+ Path /bin/whatami differs (in bundle softenv)
Entry: login1.bgl.mcs.anl.gov.xml bad
This can be used to compare configurations for single clients, or
diff --git a/doc/installation/building-packages.txt b/doc/installation/building-packages.txt
index f89b64d9e..b3b775869 100644
--- a/doc/installation/building-packages.txt
+++ b/doc/installation/building-packages.txt
@@ -14,6 +14,7 @@ Building from a tarball
-----------------------
* Create a directory structure for rpmbuild::
+
rpmdev-setuptree
* Copy the tarball to ``~/rpmbuild/SOURCES/``
diff --git a/doc/server/plugins/generators/sshbase.txt b/doc/server/plugins/generators/sshbase.txt
index 2b6c8640b..38631dd3b 100644
--- a/doc/server/plugins/generators/sshbase.txt
+++ b/doc/server/plugins/generators/sshbase.txt
@@ -1,4 +1,5 @@
.. -*- mode: rst -*-
+.. vim: ft=rst
.. _server-plugins-generators-sshbase:
@@ -13,8 +14,9 @@ record for the current system.
It has two functions:
-* Generating new ssh keys -- When a client requests a dsa, rsa, or v1 key,
- and there is no existing key in the repository, one is generated.
+* Generating new ssh keys -- When a client requests a ecdsa, dsa, rsa,
+ or v1 key, and there is no existing key in the repository, one is
+ generated.
* Maintaining the ``ssh_known_hosts`` file -- all current known public
keys (and extra public key stores) are integrated into a single
@@ -31,7 +33,7 @@ Interacting with SSHbase
``<repo>/SSHbase/<key filename>.H_<hostname>``
* Pre-seeding can also be performed using ``bcfg2-admin pull
- ConfigFile /name/of/ssh/key``
+ Path /name/of/ssh/key``
* Revoking existing keys -- deleting
``<repo>/SSHbase/\*.H_<hostname>`` will remove keys for an existing
diff --git a/doc/unsorted/emacs_snippet.txt b/doc/unsorted/emacs_snippet.txt
index b9f7fd25b..4eefb4583 100644
--- a/doc/unsorted/emacs_snippet.txt
+++ b/doc/unsorted/emacs_snippet.txt
@@ -31,7 +31,7 @@ More snippets are under development.
("<Group" "<Group name='${1:groupname}>
$0
</Group>" nil)
- ("<Config" "<ConfigFile name='${1:filename}'/>
+ ("<Path" "<Path name='${1:filename}'/>
$0" nil)
("<Service" "<Service name='${1:svcname}'/>
$0" nil)
diff --git a/doc/unsorted/vim_snippet.txt b/doc/unsorted/vim_snippet.txt
index e4fda7eca..4598b5c1d 100644
--- a/doc/unsorted/vim_snippet.txt
+++ b/doc/unsorted/vim_snippet.txt
@@ -30,9 +30,9 @@ that allow quick composition of bundles and base files.
<Group name='${1:groupname}'>
${2}
</Group>
- # ConfigFile
- snippet <Config
- <ConfigFile name='${1:filename}'/>
+ # Path
+ snippet <Path
+ <Path name='${1:filename}'/>
# Service
snippet <Service
<Service name='${1:svcname}'/>
diff --git a/src/lib/Bcfg2/Client/Tools/Systemd.py b/src/lib/Bcfg2/Client/Tools/Systemd.py
index 20a172d3d..027d91c71 100644
--- a/src/lib/Bcfg2/Client/Tools/Systemd.py
+++ b/src/lib/Bcfg2/Client/Tools/Systemd.py
@@ -13,8 +13,6 @@ class Systemd(Bcfg2.Client.Tools.SvcTool):
__handles__ = [('Service', 'systemd')]
__req__ = {'Service': ['name', 'status']}
- conflicts = ['Chkconfig']
-
def get_svc_command(self, service, action):
return "/bin/systemctl %s %s.service" % (action, service.get('name'))
diff --git a/src/lib/Bcfg2/Reporting/Collector.py b/src/lib/Bcfg2/Reporting/Collector.py
index 0493c907b..8ca145f16 100644
--- a/src/lib/Bcfg2/Reporting/Collector.py
+++ b/src/lib/Bcfg2/Reporting/Collector.py
@@ -1,3 +1,4 @@
+import sys
import atexit
import daemon
import logging
@@ -6,6 +7,7 @@ import traceback
import threading
# pylint: disable=E0611
+from lockfile import LockFailed, LockTimeout
try:
from lockfile.pidlockfile import PIDLockFile
from lockfile import Error as PIDFileError
@@ -119,6 +121,17 @@ class ReportingCollector(object):
try:
self.context.pidfile = PIDLockFile(self.setup['daemon'])
self.context.open()
+ except LockFailed:
+ self.logger.error("Failed to daemonize: %s" %
+ sys.exc_info()[1])
+ self.shutdown()
+ return
+ except LockTimeout:
+ self.logger.error("Failed to daemonize: "
+ "Failed to acquire lock on %s" %
+ self.setup['daemon'])
+ self.shutdown()
+ return
except PIDFileError:
self.logger.error("Error writing pid file: %s" %
traceback.format_exc().splitlines()[-1])
@@ -162,9 +175,6 @@ class ReportingCollector(object):
pass
if self.storage:
self.storage.shutdown()
- from django import db
- self.logger.info("%s: Closing database connection" % self.name)
- db.close_connection()
def reap_children(self):
"""Join any non-live threads"""
diff --git a/src/lib/Bcfg2/Reporting/Storage/DjangoORM.py b/src/lib/Bcfg2/Reporting/Storage/DjangoORM.py
index ef1e92103..e2e565b1d 100644
--- a/src/lib/Bcfg2/Reporting/Storage/DjangoORM.py
+++ b/src/lib/Bcfg2/Reporting/Storage/DjangoORM.py
@@ -18,6 +18,7 @@ from django.core import management
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.db.models import FieldDoesNotExist
from django.core.cache import cache
+from django import db
#Used by GetCurrentEntry
import difflib
@@ -370,6 +371,11 @@ class DjangoORM(StorageBase):
except:
self.logger.error("Failed to import interaction: %s" %
traceback.format_exc().splitlines()[-1])
+ finally:
+ self.logger.info("%s: Closing database connection" %
+ self.__class__.__name__)
+ db.close_connection()
+
def validate(self):
"""Validate backend storage. Should be called once when loaded"""
@@ -451,4 +457,3 @@ class DjangoORM(StorageBase):
else:
ret.append(None)
return ret
-
diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py
index 03bc7bff4..4375512e9 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
@@ -663,9 +681,10 @@ class BaseCore(object):
del entry.attrib['realname']
return ret
except:
- self.logger.error("Failed binding entry %s:%s with altsrc %s" %
- (entry.tag, entry.get('realname'),
- entry.get('name')))
+ self.logger.error(
+ "Failed binding entry %s:%s with altsrc %s: %s" %
+ (entry.tag, entry.get('realname'), entry.get('name'),
+ sys.exc_info()[1]))
entry.set('name', oldname)
self.logger.error("Falling back to %s:%s" %
(entry.tag, entry.get('name')))
@@ -741,11 +760,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 +1103,7 @@ class BaseCore(object):
@exposed
@track_statistics()
+ @close_db_connection
def DeclareVersion(self, address, version):
""" Declare the client version.
@@ -1111,6 +1126,7 @@ class BaseCore(object):
return True
@exposed
+ @close_db_connection
def GetProbes(self, address):
""" Fetch probes for the client.
@@ -1136,6 +1152,7 @@ class BaseCore(object):
(client, err))
@exposed
+ @close_db_connection
def RecvProbeData(self, address, probedata):
""" Receive probe data from clients.
@@ -1183,6 +1200,7 @@ class BaseCore(object):
return True
@exposed
+ @close_db_connection
def AssertProfile(self, address, profile):
""" Set profile for a client.
@@ -1202,6 +1220,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 +1240,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 +1278,7 @@ class BaseCore(object):
address)
@exposed
+ @close_db_connection
def GetDecisionList(self, address, mode):
""" Get the decision list for the client with :func:`GetDecisions`.
diff --git a/src/lib/Bcfg2/Server/Plugin/helpers.py b/src/lib/Bcfg2/Server/Plugin/helpers.py
index de02adc4e..170af50ac 100644
--- a/src/lib/Bcfg2/Server/Plugin/helpers.py
+++ b/src/lib/Bcfg2/Server/Plugin/helpers.py
@@ -199,7 +199,8 @@ class PluginDatabaseModel(object):
inherit from. This is just a mixin; models must also inherit from
django.db.models.Model to be valid Django models."""
- class Meta: # pylint: disable=C0111,W0232
+ class Meta(object): # pylint: disable=W0232
+ """ Model metadata options """
app_label = "Server"