From 3c6f694ff2c062d242c92889af94cac1b0a60a92 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Tue, 15 May 2012 08:50:45 -0500 Subject: Packages: Fix URLError handling (Reported by dikim33 on IRC) Signed-off-by: Sol Jerome --- src/lib/Bcfg2Py3k.py | 2 ++ src/lib/Server/Plugins/Packages/Yum.py | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib/Bcfg2Py3k.py b/src/lib/Bcfg2Py3k.py index ee05b7e41..5d32c79a0 100644 --- a/src/lib/Bcfg2Py3k.py +++ b/src/lib/Bcfg2Py3k.py @@ -14,6 +14,7 @@ try: from urllib2 import install_opener from urllib2 import urlopen from urllib2 import HTTPError + from urllib2 import URLError except ImportError: from urllib.parse import urljoin, urlparse from urllib.request import HTTPBasicAuthHandler @@ -22,6 +23,7 @@ except ImportError: from urllib.request import install_opener from urllib.request import urlopen from urllib.error import HTTPError + from urllib.error import URLError try: from cStringIO import StringIO diff --git a/src/lib/Server/Plugins/Packages/Yum.py b/src/lib/Server/Plugins/Packages/Yum.py index 9ce462c78..d1e97f5b1 100644 --- a/src/lib/Server/Plugins/Packages/Yum.py +++ b/src/lib/Server/Plugins/Packages/Yum.py @@ -11,7 +11,7 @@ import lxml.etree from UserDict import DictMixin from subprocess import Popen, PIPE, STDOUT import Bcfg2.Server.Plugin -from Bcfg2.Bcfg2Py3k import StringIO, cPickle, HTTPError, ConfigParser, file +from Bcfg2.Bcfg2Py3k import StringIO, cPickle, HTTPError, URLError, ConfigParser, file from Bcfg2.Server.Plugins.Packages.Collection import Collection from Bcfg2.Server.Plugins.Packages.Source import SourceInitError, Source, \ fetch_url @@ -564,6 +564,11 @@ class YumSource(Source): except ValueError: self.logger.error("Packages: Bad url string %s" % rmdurl) return [] + except URLError: + err = sys.exc_info()[1] + self.logger.error("Packages: Failed to fetch url %s. %s" % + (rmdurl, err)) + return [] except HTTPError: err = sys.exc_info()[1] self.logger.error("Packages: Failed to fetch url %s. code=%s" % -- cgit v1.2.3-1-g7c22 From ff0fbc90abce96f3ed9b00f785ee9d2055794ae3 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 16 May 2012 08:46:13 -0400 Subject: use whitespace-stripping XML parser in base plugins --- src/lib/Server/Plugin.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index 9b3c5814f..c9de0d89b 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -10,6 +10,7 @@ import posixpath import re import sys import threading +import Bcfg2.Server from Bcfg2.Bcfg2Py3k import ConfigParser from lxml.etree import XML, XMLSyntaxError @@ -256,7 +257,9 @@ class ThreadedStatistics(Statistics, if self.terminate.isSet(): return False - self.work_queue.put_nowait((metadata, lxml.etree.fromstring(pdata))) + self.work_queue.put_nowait((metadata, + lxml.etree.XML(pdata, + parser=Bcfg2.Server.XMLParser))) except Full: self.logger.warning("Queue.Full: Failed to load queue data") break @@ -597,7 +600,8 @@ class SingleXMLFileBacked(XMLFileBacked): def Index(self): """Build local data structures.""" try: - self.xdata = lxml.etree.XML(self.data, base_url=self.name) + self.xdata = lxml.etree.XML(self.data, base_url=self.name, + parser=Bcfg2.Server.XMLParser) except lxml.etree.XMLSyntaxError: err = sys.exc_info()[1] logger.error("Failed to parse %s: %s" % (self.name, err)) @@ -763,7 +767,7 @@ class XMLSrc(XMLFileBacked): return self.items = {} try: - xdata = lxml.etree.XML(data) + xdata = lxml.etree.XML(data, parser=Bcfg2.Server.XMLParser) except lxml.etree.XMLSyntaxError: logger.error("Failed to parse file %s" % (self.name)) return -- cgit v1.2.3-1-g7c22 From 999f692e1fad2e64c316f31ac9d642bc5231b4d4 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 16 May 2012 09:37:33 -0400 Subject: strip whitespace from one more XML parse --- src/lib/Server/Plugin.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index c9de0d89b..d51a13804 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -13,8 +13,6 @@ import threading import Bcfg2.Server from Bcfg2.Bcfg2Py3k import ConfigParser -from lxml.etree import XML, XMLSyntaxError - import Bcfg2.Options # py3k compatibility @@ -574,8 +572,9 @@ class XMLFileBacked(FileBacked): def Index(self): """Build local data structures.""" try: - self.xdata = XML(self.data) - except XMLSyntaxError: + self.xdata = lxml.etree.XML(self.data, + parser=Bcfg2.Server.XMLParser) + except lxml.etree.XMLSyntaxError: logger.error("Failed to parse %s" % (self.name)) return self.entries = self.xdata.getchildren() -- cgit v1.2.3-1-g7c22 From aa510b478ab4a3897191fbf352485a244bcbcacf Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 16 May 2012 13:29:01 -0400 Subject: random names for repos without obvious names breaks ability to use a single cache for multiple clients --- src/lib/Server/Plugins/Packages/Source.py | 11 ++++------- src/lib/Server/Plugins/Packages/Yum.py | 1 - 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/Packages/Source.py b/src/lib/Server/Plugins/Packages/Source.py index 5b0aa4213..4362d19ed 100644 --- a/src/lib/Server/Plugins/Packages/Source.py +++ b/src/lib/Server/Plugins/Packages/Source.py @@ -1,7 +1,6 @@ import os import re import sys -import base64 import Bcfg2.Server.Plugin from Bcfg2.Bcfg2Py3k import HTTPError, HTTPBasicAuthHandler, \ HTTPPasswordMgrWithDefaultRealm, install_opener, build_opener, \ @@ -147,12 +146,10 @@ class Source(Bcfg2.Server.Plugin.Debuggable): if match: name = match.group(1) break - if name is None: - # couldn't figure out the name from the URL or URL map - # (which probably means its a screwy URL), so we just - # generate a random one - name = base64.b64encode(os.urandom(16))[:-2] - rname = "%s-%s" % (self.groups[0], name) + if name is not None: + rname = "%s-%s" % (self.groups[0], name) + else: + rname = self.groups[0] # see yum/__init__.py in the yum source, lines 441-449, for # the source of this regex. yum doesn't like anything but # string.ascii_letters, string.digits, and [-_.:]. There diff --git a/src/lib/Server/Plugins/Packages/Yum.py b/src/lib/Server/Plugins/Packages/Yum.py index d1e97f5b1..44ff1c272 100644 --- a/src/lib/Server/Plugins/Packages/Yum.py +++ b/src/lib/Server/Plugins/Packages/Yum.py @@ -4,7 +4,6 @@ import time import copy import glob import socket -import random import logging import threading import lxml.etree -- cgit v1.2.3-1-g7c22 From e88008fef62328953b60b7670a69f517eae2ea6f Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 21 May 2012 11:21:40 -0400 Subject: made SSLCA respect info.xml --- src/lib/Server/Plugin.py | 26 ++++++++++-------- src/lib/Server/Plugins/SSLCA.py | 61 +++++++++++++++++++++-------------------- src/sbin/bcfg2-info | 13 ++++++--- 3 files changed, 55 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index d51a13804..fa5e3ca9d 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -50,6 +50,19 @@ info_regex = re.compile( \ 'perms:(\s)*(?P\w+)|' + 'sensitive:(\s)*(?P\S+)|') +def bind_info(entry, metadata, infoxml=None, default=default_file_metadata): + for attr, val in list(default.items()): + entry.set(attr, val) + if infoxml: + mdata = dict() + infoxml.pnode.Match(metadata, mdata, entry=entry) + if 'Info' not in mdata: + msg = "Failed to set metadata for file %s" % entry.get('name') + logger.error(msg) + raise PluginExecutionError(msg) + for attr, val in list(mdata['Info'][None].items()): + entry.set(attr, val) + class PluginInitError(Exception): """Error raised in cases of Plugin initialization errors.""" @@ -1074,18 +1087,7 @@ class EntrySet: return cmp(x.specific.prio, y.specific.prio) def bind_info_to_entry(self, entry, metadata): - # first set defaults from global metadata/:info - for key in self.metadata: - entry.set(key, self.metadata[key]) - if self.infoxml: - mdata = {} - self.infoxml.pnode.Match(metadata, mdata, entry=entry) - if 'Info' not in mdata: - logger.error("Failed to set metadata for file %s" % \ - (entry.get('name'))) - raise PluginExecutionError - [entry.attrib.__setitem__(key, value) \ - for (key, value) in list(mdata['Info'][None].items())] + bind_info(entry, metadata, infoxml=self.infoxml, default=self.metadata) def bind_entry(self, entry, metadata): """Return the appropriate interpreted template from the set of available templates.""" diff --git a/src/lib/Server/Plugins/SSLCA.py b/src/lib/Server/Plugins/SSLCA.py index e5bc38fba..97644ebda 100644 --- a/src/lib/Server/Plugins/SSLCA.py +++ b/src/lib/Server/Plugins/SSLCA.py @@ -23,6 +23,10 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): cert_specs = {} CAs = {} + def __init__(self, core, datastore): + Bcfg2.Server.Plugin.GroupSpool.__init__(self, core, datastore) + self.infoxml = dict() + def HandleEvent(self, event=None): """ Updates which files this plugin handles based upon filesystem events. @@ -38,7 +42,7 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): else: ident = self.handles[event.requestID][:-1] - fname = "".join([ident, '/', event.filename]) + fname = os.path.join(ident, event.filename) if event.filename.endswith('.xml'): if action in ['exists', 'created', 'changed']: @@ -70,6 +74,10 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): cp.read(self.core.cfile) self.CAs[ca] = dict(cp.items('sslca_' + ca)) self.Entries['Path'][ident] = self.get_cert + elif event.filename.endswith("info.xml"): + self.infoxml[ident] = Bcfg2.Server.Plugin.InfoXML(epath, + noprio=True) + self.infoxml[ident].HandleEvent(event) if action == 'deleted': if ident in self.Entries['Path']: del self.Entries['Path'][ident] @@ -93,28 +101,26 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): either grabs a prexisting key hostfile, or triggers the generation of a new key if one doesn't exist. """ - # set path type and permissions, otherwise bcfg2 won't bind the file - permdata = {'owner': 'root', - 'group': 'root', - 'type': 'file', - 'perms': '644'} - [entry.attrib.__setitem__(key, permdata[key]) for key in permdata] - # check if we already have a hostfile, or need to generate a new key # TODO: verify key fits the specs path = entry.get('name') - filename = "".join([path, '/', path.rsplit('/', 1)[1], - '.H_', metadata.hostname]) + filename = os.path.join(path, "%s.H_%s" % (os.path.basename(path), + metadata.hostname)) if filename not in list(self.entries.keys()): key = self.build_key(filename, entry, metadata) open(self.data + filename, 'w').write(key) entry.text = key - self.entries[filename] = self.__child__("%s%s" % (self.data, - filename)) + self.entries[filename] = self.__child__(self.data + filename) self.entries[filename].HandleEvent() else: entry.text = self.entries[filename].data + if path in self.infoxml: + Bcfg2.Server.Plugin.bind_info(entry, metadata, + infoxml=self.infoxml[path]) + else: + Bcfg2.Server.Plugin.bind_info(entry, metadata) + def build_key(self, filename, entry, metadata): """ generates a new key according the the specification @@ -133,39 +139,36 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): either grabs a prexisting cert hostfile, or triggers the generation of a new cert if one doesn't exist. """ - # set path type and permissions, otherwise bcfg2 won't bind the file - permdata = {'owner': 'root', - 'group': 'root', - 'type': 'file', - 'perms': '644'} - [entry.attrib.__setitem__(key, permdata[key]) for key in permdata] - path = entry.get('name') - filename = "".join([path, '/', path.rsplit('/', 1)[1], - '.H_', metadata.hostname]) + filename = os.path.join(path, "%s.H_%s" % (os.path.basename(path), + metadata.hostname)) # first - ensure we have a key to work with key = self.cert_specs[entry.get('name')].get('key') - key_filename = "".join([key, '/', key.rsplit('/', 1)[1], - '.H_', metadata.hostname]) + key_filename = os.path.join(key, "%s.H_%s" % (os.path.basename(key), + metadata.hostname)) if key_filename not in self.entries: e = lxml.etree.Element('Path') - e.attrib['name'] = key + e.set('name', key) self.core.Bind(e, metadata) # check if we have a valid hostfile - if filename in list(self.entries.keys()) and self.verify_cert(filename, - key_filename, - entry): + if (filename in list(self.entries.keys()) and + self.verify_cert(filename, key_filename, entry)): entry.text = self.entries[filename].data else: cert = self.build_cert(key_filename, entry, metadata) open(self.data + filename, 'w').write(cert) - self.entries[filename] = self.__child__("%s%s" % (self.data, - filename)) + self.entries[filename] = self.__child__(self.data + filename) self.entries[filename].HandleEvent() entry.text = cert + if path in self.infoxml: + Bcfg2.Server.Plugin.bind_info(entry, metadata, + infoxml=self.infoxml[path]) + else: + Bcfg2.Server.Plugin.bind_info(entry, metadata) + def verify_cert(self, filename, key_filename, entry): if self.verify_cert_against_ca(filename, entry): if self.verify_cert_against_key(filename, key_filename): diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index e09b7ed87..70e327ef3 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -108,11 +108,13 @@ def displayTrace(trace, num=80, sort=('time', 'calls')): class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): """Main class for bcfg2-info.""" - def __init__(self, repo, plgs, passwd, encoding, event_debug, filemonitor='default'): + def __init__(self, repo, plgs, passwd, encoding, event_debug, + cfile='/etc/bcfg2.conf', filemonitor='default'): cmd.Cmd.__init__(self) try: Bcfg2.Server.Core.Core.__init__(self, repo, plgs, passwd, - encoding, filemonitor=filemonitor) + encoding, cfile=cfile, + filemonitor=filemonitor) if event_debug: self.fam.debug = True except Bcfg2.Server.Core.CoreInitError: @@ -590,12 +592,15 @@ if __name__ == '__main__': prof = profile.Profile() loop = prof.runcall(infoCore, setup['repo'], setup['plugins'], setup['password'], setup['encoding'], - setup['event debug'], setup['filemonitor']) + setup['event debug'], cfile=setup['configfile'], + filemonitor=setup['filemonitor']) displayTrace(prof) else: if setup['profile']: print("Profiling functionality not available.") loop = infoCore(setup['repo'], setup['plugins'], setup['password'], - setup['encoding'], setup['event debug'], setup['filemonitor']) + setup['encoding'], setup['event debug'], + cfile=setup['configfile'], + filemonitor=setup['filemonitor']) loop.Run(setup['args']) -- cgit v1.2.3-1-g7c22 From 71f97dc1d8745767df169267fe54515f296ac945 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 21 May 2012 11:30:21 -0400 Subject: handle package sources without packages for an applicable client arch more gracefully --- src/lib/Server/Plugins/Packages/Source.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/lib/Server/Plugins/Packages/Source.py b/src/lib/Server/Plugins/Packages/Source.py index 4362d19ed..88d47fb3e 100644 --- a/src/lib/Server/Plugins/Packages/Source.py +++ b/src/lib/Server/Plugins/Packages/Source.py @@ -177,6 +177,10 @@ class Source(Bcfg2.Server.Plugin.Debuggable): if a in metadata.groups] vdict = dict() for agrp in agroups: + if agrp not in self.provides: + self.logger.warning("%s provides no packages for %s" % + (self, agrp)) + continue for key, value in list(self.provides[agrp].items()): if key not in vdict: vdict[key] = set(value) -- cgit v1.2.3-1-g7c22 From a400a860abe7c373c43a7df3fb55affd9746b292 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 21 May 2012 15:20:04 -0400 Subject: set type on Path entries handled by SSLCA --- src/lib/Server/Plugins/SSLCA.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lib/Server/Plugins/SSLCA.py b/src/lib/Server/Plugins/SSLCA.py index 97644ebda..a50c003ae 100644 --- a/src/lib/Server/Plugins/SSLCA.py +++ b/src/lib/Server/Plugins/SSLCA.py @@ -115,6 +115,7 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): else: entry.text = self.entries[filename].data + entry.set("type", "file") if path in self.infoxml: Bcfg2.Server.Plugin.bind_info(entry, metadata, infoxml=self.infoxml[path]) @@ -163,6 +164,7 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): self.entries[filename].HandleEvent() entry.text = cert + entry.set("type", "file") if path in self.infoxml: Bcfg2.Server.Plugin.bind_info(entry, metadata, infoxml=self.infoxml[path]) -- cgit v1.2.3-1-g7c22 From b147ac47c4820737d112ad7ce7047e31ef68f732 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 22 May 2012 10:51:58 -0400 Subject: added -f flag to bcfg2-info buildall --- src/sbin/bcfg2-info | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index 70e327ef3..1f41ba6b8 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -259,15 +259,23 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): self.help_builddir() def do_buildall(self, args): - if len(args.split()) != 1: - print("Usage: buildall ") + alist = args.split() + for arg in alist: + if arg == '-f': + alist.remove('-f') + flags = [arg] + if len(alist) != 1: + print("Usage: buildall [-f] ") return - try: - os.mkdir(args) - except: - pass + if not os.path.exists(alist[0]): + try: + os.mkdir(alist[0]) + except OSError: + err = sys.exc_info()[1] + logger.error("Could not create %s: %s" % (alist[0], err)) for client in self.metadata.clients: - self.do_build("%s %s/%s.xml" % (client, args, client)) + self.do_build("%s %s %s/%s.xml" % (" ".join(flags), + client, args, client)) def do_buildfile(self, args): """Build a config file for client.""" -- cgit v1.2.3-1-g7c22 From 142642ae176711ffd7f63e1299c9256a5a80b008 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 22 May 2012 10:55:25 -0400 Subject: use provided logger throughout POSIX driver, to make bcfg2-info builddir quieter --- src/lib/Client/Tools/POSIX.py | 48 ++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/lib/Client/Tools/POSIX.py b/src/lib/Client/Tools/POSIX.py index 3591c33ad..049b90d32 100644 --- a/src/lib/Client/Tools/POSIX.py +++ b/src/lib/Client/Tools/POSIX.py @@ -46,35 +46,39 @@ def calcPerms(initial, perms): return tempperms -def normGid(entry): +def normGid(entry, logger=None): """ This takes a group name or gid and returns the corresponding gid or False. """ + if logger is None: + logger = log try: try: return int(entry.get('group')) except: return int(grp.getgrnam(entry.get('group'))[2]) except (OSError, KeyError): - log.error('GID normalization failed for %s. Does group %s exist?' - % (entry.get('name'), entry.get('group'))) + logger.error('GID normalization failed for %s. Does group %s exist?' % + (entry.get('name'), entry.get('group'))) return False -def normUid(entry): +def normUid(entry, logger=None): """ This takes a user name or uid and returns the corresponding uid or False. """ + if logger is None: + logger = log try: try: return int(entry.get('owner')) except: return int(pwd.getpwnam(entry.get('owner'))[2]) except (OSError, KeyError): - log.error('UID normalization failed for %s. Does owner %s exist?' - % (entry.get('name'), entry.get('owner'))) + logger.error('UID normalization failed for %s. Does owner %s exist?' % + (entry.get('name'), entry.get('owner'))) return False @@ -173,8 +177,8 @@ class POSIX(Bcfg2.Client.Tools.Tool): dev_type = entry.get('dev_type') mode = calcPerms(device_map[dev_type], entry.get('mode', '0600')) - owner = normUid(entry) - group = normGid(entry) + owner = normUid(entry, logger=self.logger) + group = normGid(entry, logger=self.logger) if dev_type in ['block', 'char']: # check for incompletely specified entries if entry.get('major') == None or \ @@ -246,7 +250,9 @@ class POSIX(Bcfg2.Client.Tools.Tool): are set as specified by the user. """ os.chmod(entry.get('name'), mode) - os.chown(entry.get('name'), normUid(entry), normGid(entry)) + os.chown(entry.get('name'), + normUid(entry, logger=self.logger), + normGid(entry, logger=self.logger)) return True except KeyError: self.logger.error('Failed to install %s' % entry.get('name')) @@ -285,8 +291,8 @@ class POSIX(Bcfg2.Client.Tools.Tool): mtime = str(finfo[stat.ST_MTIME]) else: mtime = '-1' - pTrue = ((owner == str(normUid(entry))) and - (group == str(normGid(entry))) and + pTrue = ((owner == str(normUid(entry, logger=self.logger))) and + (group == str(normGid(entry, logger=self.logger))) and (perms == entry.get('perms')) and (mtime == entry.get('mtime', '-1'))) @@ -316,7 +322,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): pruneTrue = True if not pTrue: - if owner != str(normUid(entry)): + if owner != str(normUid(entry, logger=self.logger)): entry.set('current_owner', owner) self.logger.debug("%s %s ownership wrong" % \ (entry.tag, entry.get('name'))) @@ -324,7 +330,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): nqtext += "%s owner wrong. is %s should be %s" % \ (entry.get('name'), owner, entry.get('owner')) entry.set('qtext', nqtext) - if group != str(normGid(entry)): + if group != str(normGid(entry, logger=self.logger)): entry.set('current_group', group) self.logger.debug("%s %s group wrong" % \ (entry.tag, entry.get('name'))) @@ -652,7 +658,9 @@ class POSIX(Bcfg2.Client.Tools.Tool): newfile.write(filedata) newfile.close() try: - os.chown(newfile.name, normUid(entry), normGid(entry)) + os.chown(newfile.name, + normUid(entry, logger=self.logger), + normGid(entry, logger=self.logger)) except KeyError: self.logger.error("Failed to chown %s to %s:%s" % (newfile.name, entry.get('owner'), @@ -787,8 +795,8 @@ class POSIX(Bcfg2.Client.Tools.Tool): return False if entry.get('recursive') in ['True', 'true']: # verify ownership information recursively - owner = normUid(entry) - group = normGid(entry) + owner = normUid(entry, logger=self.logger) + group = normGid(entry, logger=self.logger) for root, dirs, files in os.walk(entry.get('name')): for p in dirs + files: @@ -857,8 +865,8 @@ class POSIX(Bcfg2.Client.Tools.Tool): plist = [entry.get('name')] if entry.get('recursive') in ['True', 'true']: # verify ownership information recursively - owner = normUid(entry) - group = normGid(entry) + owner = normUid(entry, logger=self.logger) + group = normGid(entry, logger=self.logger) for root, dirs, files in os.walk(entry.get('name')): for p in dirs + files: @@ -869,7 +877,9 @@ class POSIX(Bcfg2.Client.Tools.Tool): plist.append(path) try: for p in plist: - os.chown(p, normUid(entry), normGid(entry)) + os.chown(p, + normUid(entry, logger=self.logger), + normGid(entry, logger=self.logger)) os.chmod(p, calcPerms(stat.S_IFDIR, entry.get('perms'))) return True except (OSError, KeyError): -- cgit v1.2.3-1-g7c22 From cc5328915f2faa96a24ec8dab343e6cf7e9bdefd Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 22 May 2012 10:55:50 -0400 Subject: bcfg2-info builddir requires "interactive" flag --- src/sbin/bcfg2-info | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index 1f41ba6b8..4dc6349a0 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -567,27 +567,26 @@ if __name__ == '__main__': optinfo = { 'configfile': Bcfg2.Options.CFILE, 'help': Bcfg2.Options.HELP, - } - optinfo.update({ - 'event debug': Bcfg2.Options.DEBUG, - 'profile': Bcfg2.Options.CORE_PROFILE, - 'encoding': Bcfg2.Options.ENCODING, - # Server options - 'repo': Bcfg2.Options.SERVER_REPOSITORY, - 'plugins': Bcfg2.Options.SERVER_PLUGINS, - 'password': Bcfg2.Options.SERVER_PASSWORD, - 'mconnect': Bcfg2.Options.SERVER_MCONNECT, - 'filemonitor': Bcfg2.Options.SERVER_FILEMONITOR, - 'location': Bcfg2.Options.SERVER_LOCATION, - 'static': Bcfg2.Options.SERVER_STATIC, - 'key': Bcfg2.Options.SERVER_KEY, - 'cert': Bcfg2.Options.SERVER_CERT, - 'ca': Bcfg2.Options.SERVER_CA, - 'password': Bcfg2.Options.SERVER_PASSWORD, - 'protocol': Bcfg2.Options.SERVER_PROTOCOL, - # More options - 'logging': Bcfg2.Options.LOGGING_FILE_PATH - }) + 'event debug': Bcfg2.Options.DEBUG, + 'profile': Bcfg2.Options.CORE_PROFILE, + 'encoding': Bcfg2.Options.ENCODING, + # Server options + 'repo': Bcfg2.Options.SERVER_REPOSITORY, + 'plugins': Bcfg2.Options.SERVER_PLUGINS, + 'password': Bcfg2.Options.SERVER_PASSWORD, + 'mconnect': Bcfg2.Options.SERVER_MCONNECT, + 'filemonitor': Bcfg2.Options.SERVER_FILEMONITOR, + 'location': Bcfg2.Options.SERVER_LOCATION, + 'static': Bcfg2.Options.SERVER_STATIC, + 'key': Bcfg2.Options.SERVER_KEY, + 'cert': Bcfg2.Options.SERVER_CERT, + 'ca': Bcfg2.Options.SERVER_CA, + 'password': Bcfg2.Options.SERVER_PASSWORD, + 'protocol': Bcfg2.Options.SERVER_PROTOCOL, + # More options + 'logging': Bcfg2.Options.LOGGING_FILE_PATH, + 'interactive': Bcfg2.Options.INTERACTIVE, + } setup = Bcfg2.Options.OptionParser(optinfo) setup.hm = "Usage:\n %s\n%s" % (setup.buildHelpMessage(), USAGE) -- cgit v1.2.3-1-g7c22 From 583bb62f2da989b2c6e42b99c30978fc4ff87d23 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 22 May 2012 10:56:09 -0400 Subject: minor cleanup --- src/lib/Server/Core.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Core.py b/src/lib/Server/Core.py index 9fa42cfd1..bbeceb3f2 100644 --- a/src/lib/Server/Core.py +++ b/src/lib/Server/Core.py @@ -72,10 +72,9 @@ class Core(Component): try: self.fam = Bcfg2.Server.FileMonitor.available[filemonitor]() except IOError: - logger.error("Failed to instantiate fam driver %s" % filemonitor, - exc_info=1) - raise CoreInitError("failed to instantiate fam driver (used %s)" % \ - filemonitor) + msg = "Failed to instantiate fam driver %s" % filemonitor + logger.error(msg, exc_info=1) + raise CoreInitError(msg) self.pubspace = {} self.cfile = cfile self.cron = {} -- cgit v1.2.3-1-g7c22 From ba48c23030259f46174645d6af3ffda186fa279a Mon Sep 17 00:00:00 2001 From: Tim Laszlo Date: Tue, 22 May 2012 14:59:46 -0500 Subject: Pkgmgr: Fix broken altsrc Use __contains__ instead of has_key in Pkgmgr. Gone in Py3k. Fallback on __getitem__ in PrioDir. Handles cased with an override for __getitem__ is used. --- src/lib/Server/Plugin.py | 3 +++ src/lib/Server/Plugins/Pkgmgr.py | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index fa5e3ca9d..3e3616f46 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -881,6 +881,9 @@ class PrioDir(Plugin, Generator, XMLDirectoryBacked): if self._matches(entry, metadata, [rname]): data = matching[index].cache[1][entry.tag][rname] break + else: + # Fall back on __getitem__. Required if override used + data = matching[index].cache[1][entry.tag][entry.get('name')] if '__text__' in data: entry.text = data['__text__'] if '__children__' in data: diff --git a/src/lib/Server/Plugins/Pkgmgr.py b/src/lib/Server/Plugins/Pkgmgr.py index bc11bfdcf..2a8623379 100644 --- a/src/lib/Server/Plugins/Pkgmgr.py +++ b/src/lib/Server/Plugins/Pkgmgr.py @@ -25,12 +25,14 @@ class FuzzyDict(dict): print("got non-string key %s" % str(key)) return dict.__getitem__(self, key) - def has_key(self, key): + def __contains__(self, key): if isinstance(key, str): mdata = self.fuzzy.match(key) - if self.fuzzy.match(key): - return dict.has_key(self, mdata.groupdict()['name']) - return dict.has_key(self, key) + if mdata: + return dict.__contains__(self, mdata.groupdict()['name']) + else: + print("got non-string key %s" % str(key)) + return dict.__contains__(self, key) def get(self, key, default=None): try: -- cgit v1.2.3-1-g7c22 From 4c4534c2302c869f5f8258eb7107dcf531e0edc7 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 23 May 2012 10:47:13 -0400 Subject: added ability to specify arbitrary repository options to Packages --- src/lib/Server/Plugins/Packages/Source.py | 13 ++++++++++++- src/lib/Server/Plugins/Packages/Yum.py | 7 +++++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/Packages/Source.py b/src/lib/Server/Plugins/Packages/Source.py index 88d47fb3e..627ff561d 100644 --- a/src/lib/Server/Plugins/Packages/Source.py +++ b/src/lib/Server/Plugins/Packages/Source.py @@ -49,7 +49,18 @@ class Source(Bcfg2.Server.Plugin.Debuggable): for key, tag in [('components', 'Component'), ('arches', 'Arch'), ('blacklist', 'Blacklist'), ('whitelist', 'Whitelist')]: - self.__dict__[key] = [item.text for item in xsource.findall(tag)] + setattr(self, key, [item.text for item in xsource.findall(tag)]) + self.server_options = dict() + self.client_options = dict() + opts = xsource.findall("Options") + for el in opts: + repoopts = dict([(k, v) + for k, v in el.attrib.items() + if k != "clientonly" and k != "serveronly"]) + if el.get("clientonly", "false").lower() == "false": + self.server_options.update(repoopts) + if el.get("serveronly", "false").lower() == "false": + self.client_options.update(repoopts) self.gpgkeys = [el.text for el in xsource.findall("GPGKey")] diff --git a/src/lib/Server/Plugins/Packages/Yum.py b/src/lib/Server/Plugins/Packages/Yum.py index 44ff1c272..7fe169fc8 100644 --- a/src/lib/Server/Plugins/Packages/Yum.py +++ b/src/lib/Server/Plugins/Packages/Yum.py @@ -204,6 +204,13 @@ class YumCollection(Collection): config.set(reponame, "includepkgs", " ".join(source.whitelist)) + if raw: + opts = source.server_options + else: + opts = source.client_options + for opt, val in opts.items(): + config.set(reponame, opt, val) + if raw: return config else: -- cgit v1.2.3-1-g7c22 From 9d9dd8f7f83fa6aa43faf9f2bda15a24aa0eab5f Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Thu, 29 Mar 2012 08:26:53 -0500 Subject: backported option to make Packages plugin set version="any" --- src/lib/Server/Plugins/Packages/__init__.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/Packages/__init__.py b/src/lib/Server/Plugins/Packages/__init__.py index b04c299a6..17a3458bd 100644 --- a/src/lib/Server/Plugins/Packages/__init__.py +++ b/src/lib/Server/Plugins/Packages/__init__.py @@ -91,7 +91,9 @@ class Packages(Bcfg2.Server.Plugin.Plugin, def HandleEntry(self, entry, metadata): if entry.tag == 'Package': collection = self._get_collection(metadata) - entry.set('version', 'auto') + entry.set('version', self.config.get("global", + "version", + default="auto")) entry.set('type', collection.ptype) elif entry.tag == 'Path': if (entry.get("name") == self.config.get("global", "yum_config", @@ -182,8 +184,9 @@ class Packages(Bcfg2.Server.Plugin.Plugin, newpkgs.sort() for pkg in newpkgs: lxml.etree.SubElement(independent, 'BoundPackage', name=pkg, - version='auto', type=collection.ptype, - origin='Packages') + version=self.config.get("global", "version", + default="auto"), + type=collection.ptype, origin='Packages') def Refresh(self): '''Packages.Refresh() => True|False\nReload configuration -- cgit v1.2.3-1-g7c22 From facae389378cc1779b380ad2b5871cace8f63cfa Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Fri, 25 May 2012 08:03:06 -0500 Subject: DBStats: Fix missing sys import Signed-off-by: Sol Jerome --- src/lib/Server/Plugins/DBStats.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/lib/Server/Plugins/DBStats.py b/src/lib/Server/Plugins/DBStats.py index 8761d282d..56420f646 100644 --- a/src/lib/Server/Plugins/DBStats.py +++ b/src/lib/Server/Plugins/DBStats.py @@ -3,6 +3,7 @@ import difflib import logging import lxml.etree import platform +import sys import time try: -- cgit v1.2.3-1-g7c22 From b27b471a7086289957d6a4fc6c8e6b6643e95a9b Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Fri, 1 Jun 2012 08:57:38 -0500 Subject: NagiosGen: Catch name resolution errors Signed-off-by: Sol Jerome --- src/lib/Server/Plugins/NagiosGen.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/NagiosGen.py b/src/lib/Server/Plugins/NagiosGen.py index 287e1b0d3..627a83b81 100644 --- a/src/lib/Server/Plugins/NagiosGen.py +++ b/src/lib/Server/Plugins/NagiosGen.py @@ -52,7 +52,12 @@ class NagiosGen(Bcfg2.Server.Plugin.Plugin, def createhostconfig(self, entry, metadata): """Build host specific configuration file.""" - host_address = socket.gethostbyname(metadata.hostname) + try: + host_address = socket.gethostbyname(metadata.hostname) + except socket.gaierror: + LOGGER.error("Failed to find IP address for %s" % + metadata.hostname) + raise Bcfg2.Server.Plugin.PluginExecutionError host_groups = [grp for grp in metadata.groups if os.path.isfile('%s/%s-group.cfg' % (self.data, grp))] host_config = ['define host {', -- cgit v1.2.3-1-g7c22 From 503ea9de36d74ac6d7ad564d04a923a016592ccd Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 4 Jun 2012 17:36:27 -0400 Subject: fixed bcfg2-info buildall without -f --- src/sbin/bcfg2-info | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index 4dc6349a0..e0fb0b475 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -260,10 +260,11 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): def do_buildall(self, args): alist = args.split() + flags = [] for arg in alist: if arg == '-f': alist.remove('-f') - flags = [arg] + flags.append(arg) if len(alist) != 1: print("Usage: buildall [-f] ") return -- cgit v1.2.3-1-g7c22 From a524967e8d5c4c22e49cd619aed20c87a316c0be Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 12 Jun 2012 09:20:10 -0400 Subject: fixed major security flaw in Trigger plugin --- src/lib/Server/Plugins/Trigger.py | 40 ++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/Trigger.py b/src/lib/Server/Plugins/Trigger.py index eb3310a4e..b173031fe 100644 --- a/src/lib/Server/Plugins/Trigger.py +++ b/src/lib/Server/Plugins/Trigger.py @@ -1,17 +1,7 @@ import os +import pipes import Bcfg2.Server.Plugin - - -def async_run(prog, args): - pid = os.fork() - if pid: - os.waitpid(pid, 0) - else: - dpid = os.fork() - if not dpid: - os.system(" ".join([prog] + args)) - os._exit(0) - +from subprocess import Popen, PIPE class Trigger(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Statistics): @@ -30,15 +20,35 @@ class Trigger(Bcfg2.Server.Plugin.Plugin, "unloading" % self.data) raise Bcfg2.Server.Plugin.PluginInitError + def async_run(self, args): + pid = os.fork() + if pid: + os.waitpid(pid, 0) + else: + dpid = os.fork() + if not dpid: + self.debug_log("Running %s" % " ".join(pipes.quote(a) + for a in args)) + proc = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) + (out, err) = proc.communicate() + rv = proc.wait() + if rv != 0: + self.logger.error("Trigger: Error running %s (%s): %s" % + (args[0], rv, err)) + elif err: + self.debug_log("Trigger: Error: %s" % err) + os._exit(0) + def process_statistics(self, metadata, _): args = [metadata.hostname, '-p', metadata.profile, '-g', ':'.join([g for g in metadata.groups])] + self.debug_log("running triggers") for notifier in os.listdir(self.data): + self.debug_log("running %s" % notifier) if ((notifier[-1] == '~') or (notifier[:2] == '.#') or (notifier[-4:] == '.swp') or (notifier in ['SCCS', '.svn', '4913'])): continue - npath = self.data + '/' + notifier - self.logger.debug("Running %s %s" % (npath, " ".join(args))) - async_run(npath, args) + npath = os.path.join(self.data, notifier) + self.async_run([npath] + args) -- cgit v1.2.3-1-g7c22 From 5114a9855a34eed4180bc9b724331927f88c8dfb Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 12 Jun 2012 10:17:25 -0400 Subject: removed extraneous debugging calls --- src/lib/Server/Plugins/Trigger.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/Trigger.py b/src/lib/Server/Plugins/Trigger.py index b173031fe..e16b06914 100644 --- a/src/lib/Server/Plugins/Trigger.py +++ b/src/lib/Server/Plugins/Trigger.py @@ -42,9 +42,7 @@ class Trigger(Bcfg2.Server.Plugin.Plugin, def process_statistics(self, metadata, _): args = [metadata.hostname, '-p', metadata.profile, '-g', ':'.join([g for g in metadata.groups])] - self.debug_log("running triggers") for notifier in os.listdir(self.data): - self.debug_log("running %s" % notifier) if ((notifier[-1] == '~') or (notifier[:2] == '.#') or (notifier[-4:] == '.swp') or -- cgit v1.2.3-1-g7c22 From f379b0e43cfa0137379ad0f78f48223eba7db61a Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 13 Jun 2012 14:36:39 -0400 Subject: improved SSLCA verification routines and logging --- src/lib/Server/Plugins/SSLCA.py | 42 ++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/SSLCA.py b/src/lib/Server/Plugins/SSLCA.py index a50c003ae..dc0aea6d3 100644 --- a/src/lib/Server/Plugins/SSLCA.py +++ b/src/lib/Server/Plugins/SSLCA.py @@ -3,12 +3,15 @@ import Bcfg2.Options import lxml.etree import posixpath import tempfile -import pipes import os from subprocess import Popen, PIPE, STDOUT # Compatibility import from Bcfg2.Bcfg2Py3k import ConfigParser +try: + from hashlib import md5 +except ImportError: + from md5 import md5 class SSLCA(Bcfg2.Server.Plugin.GroupSpool): """ @@ -172,22 +175,29 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): Bcfg2.Server.Plugin.bind_info(entry, metadata) def verify_cert(self, filename, key_filename, entry): - if self.verify_cert_against_ca(filename, entry): - if self.verify_cert_against_key(filename, key_filename): - return True - return False + do_verify = self.CAs[self.cert_specs[entry.get('name')]['ca']].get('verify_certs', True) + if do_verify: + return (self.verify_cert_against_ca(filename, entry) and + self.verify_cert_against_key(filename, key_filename)) + return True def verify_cert_against_ca(self, filename, entry): """ check that a certificate validates against the ca cert, and that it has not expired. """ - chaincert = self.CAs[self.cert_specs[entry.get('name')]['ca']].get('chaincert') + chaincert = \ + self.CAs[self.cert_specs[entry.get('name')]['ca']].get('chaincert') cert = self.data + filename - res = Popen(["openssl", "verify", "-CAfile", chaincert, cert], + res = Popen(["openssl", "verify", "-untrusted", chaincert, "-purpose", + "sslserver", cert], stdout=PIPE, stderr=STDOUT).stdout.read() if res == cert + ": OK\n": + self.debug_log("SSLCA: %s verified successfully against CA" % + entry.get("name")) return True + self.logger.warning("SSLCA: %s failed verification against CA: %s" % + (entry.get("name"), res)) return False def verify_cert_against_key(self, filename, key_filename): @@ -196,14 +206,20 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): """ cert = self.data + filename key = self.data + key_filename - cmd = ("openssl x509 -noout -modulus -in %s | openssl md5" % - pipes.quote(cert)) - cert_md5 = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT).stdout.read() - cmd = ("openssl rsa -noout -modulus -in %s | openssl md5" % - pipes.quote(key)) - key_md5 = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT).stdout.read() + cert_md5 = \ + md5(Popen(["openssl", "x509", "-noout", "-modulus", "-in", cert], + stdout=PIPE, + stderr=STDOUT).stdout.read().strip()).hexdigest() + key_md5 = \ + md5(Popen(["openssl", "rsa", "-noout", "-modulus", "-in", key], + stdout=PIPE, + stderr=STDOUT).stdout.read().strip()).hexdigest() if cert_md5 == key_md5: + self.debug_log("SSLCA: %s verified successfully against key %s" % + (filename, key_filename)) return True + self.logger.warning("SSLCA: %s failed verification against key %s" % + (filename, key_filename)) return False def build_cert(self, key_filename, entry, metadata): -- cgit v1.2.3-1-g7c22 From 7480e8f11d991b75fe5ece33323734451defc7bd Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 13 Jun 2012 16:15:58 -0400 Subject: fixed ProbeData object to actually be a str, not just try (and fail) to imitate one --- src/lib/Server/Plugins/Probes.py | 50 +++++++--------------------------------- 1 file changed, 8 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/Probes.py b/src/lib/Server/Plugins/Probes.py index 2c24d6cc4..59f7e30bd 100644 --- a/src/lib/Server/Plugins/Probes.py +++ b/src/lib/Server/Plugins/Probes.py @@ -41,56 +41,22 @@ class ClientProbeDataSet(dict): dict.__init__(self, *args, **kwargs) -class ProbeData(object): +class ProbeData(str): """ a ProbeData object emulates a str object, but also has .xdata and .json properties to provide convenient ways to use ProbeData objects as XML or JSON data """ def __init__(self, data): - self.data = data + str.__init__(self, data) self._xdata = None self._json = None self._yaml = None - def __str__(self): - return str(self.data) - - def __repr__(self): - return repr(self.data) - - def __getattr__(self, name): - """ make ProbeData act like a str object """ - return getattr(self.data, name) - - def __complex__(self): - return complex(self.data) - - def __int__(self): - return int(self.data) - - def __long__(self): - return long(self.data) - - def __float__(self): - return float(self.data) - - def __eq__(self, other): - return str(self) == str(other) - - def __ne__(self, other): - return str(self) != str(other) - - def __gt__(self, other): - return str(self) > str(other) - - def __lt__(self, other): - return str(self) < str(other) - - def __ge__(self, other): - return self > other or self == other - - def __le__(self, other): - return self < other or self == other - + @property + def data(self): + """ provide backwards compatibility with broken ProbeData + object in bcfg2 1.2.0 thru 1.2.2 """ + return str(self) + @property def xdata(self): if self._xdata is None: -- cgit v1.2.3-1-g7c22 From c3f70edc456bb47c2058a424f99e4673b8586214 Mon Sep 17 00:00:00 2001 From: Tim Laszlo Date: Thu, 14 Jun 2012 11:07:22 -0500 Subject: DBStats: watch for missing work queue (cherry picked from commit d0555789f2af89817b4bf50a4d88e98ad6c20730) --- src/lib/Server/Plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index 3e3616f46..28299d8c7 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -289,7 +289,7 @@ class ThreadedStatistics(Statistics, def run(self): if not self.load(): return - while not self.terminate.isSet(): + while not self.terminate.isSet() and self.work_queue != None: try: (xdata, client) = self.work_queue.get(block=True, timeout=2) except Empty: @@ -299,7 +299,7 @@ class ThreadedStatistics(Statistics, self.logger.error("ThreadedStatistics: %s" % e) continue self.handle_statistic(xdata, client) - if not self.work_queue.empty(): + if self.work_queue != None and not self.work_queue.empty(): self.save() def process_statistics(self, metadata, data): -- cgit v1.2.3-1-g7c22 From 252989b29cf04aadf9775d720da495b381df7a43 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 14 Jun 2012 15:12:13 -0400 Subject: fix ProbeData inheritance from str --- src/lib/Server/Plugins/Probes.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/lib/Server/Plugins/Probes.py b/src/lib/Server/Plugins/Probes.py index 59f7e30bd..64ed4b425 100644 --- a/src/lib/Server/Plugins/Probes.py +++ b/src/lib/Server/Plugins/Probes.py @@ -45,6 +45,9 @@ class ProbeData(str): """ a ProbeData object emulates a str object, but also has .xdata and .json properties to provide convenient ways to use ProbeData objects as XML or JSON data """ + def __new__(cls, data): + str.__new__(cls, data) + def __init__(self, data): str.__init__(self, data) self._xdata = None -- cgit v1.2.3-1-g7c22 From 33e36dd2ac03c71c47e8c1841c50ca35c7ef94d4 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 14 Jun 2012 17:03:07 -0400 Subject: better error message from bcfg2-info packagesources without a hostname --- src/sbin/bcfg2-info | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index e0fb0b475..656532155 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -514,6 +514,9 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): print(" %s" % "\n ".join(unknown)) def do_packagesources(self, args): + if not args: + print("Usage: packagesources ") + return try: metadata = self.build_metadata(args) except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: -- cgit v1.2.3-1-g7c22 From cee325724cd91a7d780b35a6856618ce7e1739a5 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Fri, 15 Jun 2012 07:43:06 -0400 Subject: fixed ProbeData.__new__ to actually return something --- src/lib/Server/Plugins/Probes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/Probes.py b/src/lib/Server/Plugins/Probes.py index 64ed4b425..f312b3833 100644 --- a/src/lib/Server/Plugins/Probes.py +++ b/src/lib/Server/Plugins/Probes.py @@ -46,7 +46,7 @@ class ProbeData(str): and .json properties to provide convenient ways to use ProbeData objects as XML or JSON data """ def __new__(cls, data): - str.__new__(cls, data) + return str.__new__(cls, data) def __init__(self, data): str.__init__(self, data) -- cgit v1.2.3-1-g7c22 From 11f32cb8af475567efb2e1532de61c970cee8f2e Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Fri, 15 Jun 2012 08:03:22 -0400 Subject: really fixed ProbeData init --- src/lib/Server/Plugins/Probes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/Probes.py b/src/lib/Server/Plugins/Probes.py index f312b3833..4f17add3e 100644 --- a/src/lib/Server/Plugins/Probes.py +++ b/src/lib/Server/Plugins/Probes.py @@ -49,7 +49,7 @@ class ProbeData(str): return str.__new__(cls, data) def __init__(self, data): - str.__init__(self, data) + str.__init__(self) self._xdata = None self._json = None self._yaml = None -- cgit v1.2.3-1-g7c22 From cc8685b40db175517bfe036f2a3e94be005727d5 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 19 Jun 2012 11:09:16 -0400 Subject: fixed import --- src/sbin/bcfg2-reports | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/sbin/bcfg2-reports b/src/sbin/bcfg2-reports index 6acdd27e3..3920f519a 100755 --- a/src/sbin/bcfg2-reports +++ b/src/sbin/bcfg2-reports @@ -4,6 +4,7 @@ __revision__ = '$Revision$' import os import sys +from Bcfg2.Bcfg2Py3k import ConfigParser try: import Bcfg2.Server.Reports.settings -- cgit v1.2.3-1-g7c22 From 3cb7b5bf345785d9ad1f3916b21ee06fffb9ce46 Mon Sep 17 00:00:00 2001 From: John 'Skip' Reddy Date: Thu, 17 May 2012 23:56:46 +0000 Subject: Adding DBStats hooks into YUMng YUMng did not have any hooks to save data via the DBStats plugin, so no statistics have been saved. --- src/lib/Client/Tools/YUMng.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/lib/Client/Tools/YUMng.py b/src/lib/Client/Tools/YUMng.py index 9b999df92..cb9c7a87f 100644 --- a/src/lib/Client/Tools/YUMng.py +++ b/src/lib/Client/Tools/YUMng.py @@ -490,6 +490,7 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): _POs = POs if len(_POs) == 0: # Package (name, arch) not installed + entry.set('current_exists', 'false') self.logger.debug(" %s is not installed" % nevraString(nevra)) stat['installed'] = False package_fail = True @@ -520,6 +521,12 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): package_fail = True stat['version_fail'] = True # Just chose the first pkg for the error message + entry.set('current_version', "%s-%s.%s" % (POs[0]['version'], + POs[0]['release'], + POs[0]['arch'])) + entry.set('version', "%s-%s.%s" % (nevra['version'], + nevra['release'], + nevra['arch'])) self.logger.info(" %s: Wrong version installed. " "Want %s, but have %s" % (entry.get("name"), nevraString(nevra), -- cgit v1.2.3-1-g7c22 From 49362b6d633a7784f77650d5218d0e629d50e4fb Mon Sep 17 00:00:00 2001 From: John 'Skip' Reddy Date: Thu, 17 May 2012 23:58:19 +0000 Subject: Adding DB2 support for Statistics Adding DB2 support for Statistics, following guidance from http://code.google.com/p/ibm-db/wiki/ibm_db_django_README --- src/lib/Server/Reports/settings.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/lib/Server/Reports/settings.py b/src/lib/Server/Reports/settings.py index 952e3eae6..957c4237a 100644 --- a/src/lib/Server/Reports/settings.py +++ b/src/lib/Server/Reports/settings.py @@ -43,6 +43,9 @@ DATABASES = { } } +if db_engine == 'ibm_db_django': + DATABASES['default']['ENGINE'] = db_engine + if db_engine != 'sqlite3': DATABASES['default']['USER'] = c.get('statistics', 'database_user') DATABASES['default']['PASSWORD'] = c.get('statistics', 'database_password') -- cgit v1.2.3-1-g7c22 From 16a38827b5bb374da6caaf103f9363a45262f745 Mon Sep 17 00:00:00 2001 From: Tim Laszlo Date: Wed, 23 May 2012 08:24:42 -0500 Subject: YUMng: Fix DBStats hooks for centos5 On centos5 the hooks raise a TypeError. Replacing the keys with attributes. --- src/lib/Client/Tools/YUMng.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib/Client/Tools/YUMng.py b/src/lib/Client/Tools/YUMng.py index cb9c7a87f..febe6b9a0 100644 --- a/src/lib/Client/Tools/YUMng.py +++ b/src/lib/Client/Tools/YUMng.py @@ -521,9 +521,9 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): package_fail = True stat['version_fail'] = True # Just chose the first pkg for the error message - entry.set('current_version', "%s-%s.%s" % (POs[0]['version'], - POs[0]['release'], - POs[0]['arch'])) + entry.set('current_version', "%s-%s.%s" % (POs[0].version, + POs[0].release, + POs[0].arch)) entry.set('version', "%s-%s.%s" % (nevra['version'], nevra['release'], nevra['arch'])) -- cgit v1.2.3-1-g7c22