diff options
-rw-r--r-- | doc/appendix/guides/import-existing-ssh-keys.txt | 7 | ||||
-rw-r--r-- | doc/development/testing.txt | 4 | ||||
-rw-r--r-- | doc/installation/building-packages.txt | 1 | ||||
-rw-r--r-- | doc/server/plugins/generators/sshbase.txt | 8 | ||||
-rw-r--r-- | doc/unsorted/emacs_snippet.txt | 2 | ||||
-rw-r--r-- | doc/unsorted/vim_snippet.txt | 6 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Systemd.py | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Reporting/Collector.py | 16 | ||||
-rw-r--r-- | src/lib/Bcfg2/Reporting/Storage/DjangoORM.py | 7 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Core.py | 39 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugin/helpers.py | 3 |
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" |