summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/Options.py19
-rw-r--r--src/lib/Server/Plugin.py6
-rw-r--r--src/lib/Server/Plugins/Cfg.py20
-rw-r--r--src/lib/Server/Plugins/FileProbes.py148
-rw-r--r--src/lib/Server/Plugins/Packages/Source.py10
-rw-r--r--src/lib/Server/Plugins/Packages/Yum.py6
-rw-r--r--src/lib/Server/Plugins/SSHbase.py4
-rw-r--r--src/lib/Server/Plugins/Trigger.py13
-rw-r--r--src/lib/Server/Reports/reports/templates/base.html2
9 files changed, 129 insertions, 99 deletions
diff --git a/src/lib/Options.py b/src/lib/Options.py
index dc9818c78..2f535397f 100644
--- a/src/lib/Options.py
+++ b/src/lib/Options.py
@@ -27,12 +27,7 @@ class Option(object):
def getCFP(self):
if not self.__cfp:
self.__cfp = ConfigParser.ConfigParser()
- # FIXME: Remove this hack when except: pass below is fixed
- try:
- self.__cfp.readfp(open(self.cfpath))
- except IOError:
- e = sys.exc_info()[1]
- print("Unable to read bcfg2.conf: %s" % e)
+ self.__cfp.readfp(open(self.cfpath))
return self.__cfp
cfp = property(getCFP)
@@ -116,11 +111,7 @@ class Option(object):
self.value = self.get_cooked_value(os.environ[self.env])
return
if self.cf:
- """
- FIXME: This is masking any sort of error present in getCFP, we
- need to remove this catchall exception and figure out something
- better
- """
+ # FIXME: This is potentially masking a lot of errors
try:
self.value = self.get_cooked_value(self.cfp.get(*self.cf))
return
@@ -383,3 +374,9 @@ class OptionParser(OptionSet):
Option.cfpath = self.Bootstrap['configfile']
Option.__cfp = False
OptionSet.__init__(self, args)
+ try:
+ f = open(Option.cfpath, 'r')
+ f.close()
+ except IOError:
+ e = sys.exc_info()[1]
+ print("Warning! Unable to read specified configuration file: %s" % e)
diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py
index 6a4020b12..1ceed702d 100644
--- a/src/lib/Server/Plugin.py
+++ b/src/lib/Server/Plugin.py
@@ -992,6 +992,12 @@ class EntrySet:
self.entry_init(event)
else:
if event.filename not in self.entries:
+ logger.warning("Got %s event for unknown file %s" %
+ (action, event.filename))
+ if action == 'changed':
+ # received a bogus changed event; warn, but treat
+ # it like a created event
+ self.entry_init(event)
return
if action == 'changed':
self.entries[event.filename].handle_event(event)
diff --git a/src/lib/Server/Plugins/Cfg.py b/src/lib/Server/Plugins/Cfg.py
index d2e6e8a1d..1ea8e4e75 100644
--- a/src/lib/Server/Plugins/Cfg.py
+++ b/src/lib/Server/Plugins/Cfg.py
@@ -221,32 +221,32 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet):
return "%s.H_%s" % (bfname, specific.hostname)
def write_update(self, specific, new_entry, log):
- # FIXME: need to redo print with python's logging module
if 'text' in new_entry:
name = self.build_filename(specific)
if os.path.exists("%s.genshi" % name):
- print("Cfg: Unable to pull data for genshi types")
+ self.logger.error("Cfg: Unable to pull data for genshi types")
raise Bcfg2.Server.Plugin.PluginExecutionError
elif os.path.exists("%s.cheetah" % name):
- print("Cfg: Unable to pull data for cheetah types")
+ self.logger.error("Cfg: Unable to pull data for cheetah types")
raise Bcfg2.Server.Plugin.PluginExecutionError
try:
etext = new_entry['text'].encode(self.encoding)
except:
- print("Cfg: Cannot encode content of %s as %s" % (name, self.encoding))
+ self.logger.error("Cfg: Cannot encode content of %s as %s" % (name, self.encoding))
raise Bcfg2.Server.Plugin.PluginExecutionError
open(name, 'w').write(etext)
- if log:
- print("Wrote file %s" % name)
+ self.debug_log("Wrote file %s" % name, flag=log)
badattr = [attr for attr in ['owner', 'group', 'perms']
if attr in new_entry]
if badattr:
# check for info files and inform user of their removal
if os.path.exists(self.path + "/:info"):
- print("Removing :info file and replacing with info.xml")
+ self.logger.info("Removing :info file and replacing with "
+ "info.xml")
os.remove(self.path + "/:info")
if os.path.exists(self.path + "/info"):
- print("Removing info file and replacing with info.xml")
+ self.logger.info("Removing info file and replacing with "
+ "info.xml")
os.remove(self.path + "/info")
metadata_updates = {}
metadata_updates.update(self.metadata)
@@ -259,8 +259,8 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet):
ofile = open(self.path + "/info.xml", "w")
ofile.write(lxml.etree.tostring(infoxml, pretty_print=True))
ofile.close()
- if log:
- print("Wrote file %s" % (self.path + "/info.xml"))
+ self.debug_log("Wrote file %s" % (self.path + "/info.xml"),
+ flag=log)
class Cfg(Bcfg2.Server.Plugin.GroupSpool,
diff --git a/src/lib/Server/Plugins/FileProbes.py b/src/lib/Server/Plugins/FileProbes.py
index 269664ef4..c58040b65 100644
--- a/src/lib/Server/Plugins/FileProbes.py
+++ b/src/lib/Server/Plugins/FileProbes.py
@@ -6,6 +6,7 @@ the client """
__revision__ = '$Revision: 1465 $'
import os
+import sys
import errno
import binascii
import lxml.etree
@@ -89,33 +90,27 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin,
interpreter="/usr/bin/env python")
probe.text = probecode % path
self.probes[metadata.hostname].append(probe)
- self.logger.debug("Adding file probe for %s to %s" %
- (path, metadata.hostname))
+ self.debug_log("Adding file probe for %s to %s" %
+ (path, metadata.hostname))
return self.probes[metadata.hostname]
def ReceiveData(self, metadata, datalist):
"""Receive data from probe."""
- self.logger.debug("Receiving file probe data from %s" %
- metadata.hostname)
+ self.debug_log("Receiving file probe data from %s" % metadata.hostname)
for data in datalist:
if data.text is None:
self.logger.error("Got null response to %s file probe from %s" %
(data.get('name'), metadata.hostname))
else:
- self.logger.debug("%s:fileprobe:%s:%s" %
- (metadata.hostname,
- data.get("name"),
- data.text))
try:
- filedata = lxml.etree.XML(data.text)
- self.write_file(filedata, metadata)
+ self.write_data(lxml.etree.XML(data.text), metadata)
except lxml.etree.XMLSyntaxError:
# if we didn't get XML back from the probe, assume
# it's an error message
self.logger.error(data.text)
- def write_file(self, data, metadata):
+ def write_data(self, data, metadata):
"""Write the probed file data to the bcfg2 specification."""
filename = data.get("name")
contents = binascii.a2b_base64(data.text)
@@ -139,74 +134,80 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin,
entrydata = entry.text
if create:
- self.logger.info("Writing new probed file %s" % fileloc)
- try:
- os.makedirs(os.path.dirname(fileloc))
- except OSError, err:
- if err.errno == errno.EEXIST:
- pass
- else:
- raise
- open(fileloc, 'wb').write(contents)
-
- infoxml = os.path.join("%s%s" % (cfg.data, filename),
- "info.xml")
- if not os.path.exists(infoxml):
- self.write_infoxml(infoxml, entry, data)
-
- # Service the FAM events queued up by the key generation
- # so the data structure entries will be available for
- # binding.
- #
- # NOTE: We wait for up to ten seconds. There is some
- # potential for race condition, because if the file
- # monitor doesn't get notified about the new key files in
- # time, those entries won't be available for binding. In
- # practice, this seems "good enough".
- tries = 0
- is_bound = False
- while not is_bound:
- if tries >= 10:
- self.logger.error("%s still not registered" % filename)
- raise Bcfg2.Server.Plugin.PluginExecutionError
- self.core.fam.handle_events_in_interval(1)
- try:
- cfg.entries[filename].bind_entry(entry, metadata)
- is_bound = True
- except Bcfg2.Server.Plugin.PluginExecutionError:
- pass
- tries += 1
+ self.logger.info("Writing new probed file %s" % fileloc)
+ self.write_file(fileloc, contents)
+ self.verify_file(filename, contents, metadata)
+ infoxml = os.path.join("%s%s" % (cfg.data, filename), "info.xml")
+ self.write_infoxml(infoxml, entry, data)
elif entrydata == contents:
- self.logger.debug("Existing %s contents match probed contents" %
- filename)
+ self.debug_log("Existing %s contents match probed contents" %
+ filename)
return
elif (entry.get('update', 'false').lower() == "true"):
self.logger.info("Writing updated probed file %s" % fileloc)
- open(fileloc, 'wb').write(contents)
-
- # service FAM events
- tries = 0
- updated = False
- while not updated:
- if tries >= 10:
- self.logger.error("%s still not registered" % filename)
- raise Bcfg2.Server.Plugin.PluginExecutionError
- self.core.fam.handle_events_in_interval(1)
- cfg.entries[filename].bind_entry(entry, metadata)
- # get current entry data
- if entry.get("encoding") == "base64":
- entrydata = binascii.a2b_base64(entry.text)
- else:
- entrydata = entry.text
- if entrydata == contents:
- updated = True
- tries += 1
+ self.write_file(fileloc, contents)
+ self.verify_file(filename, contents, metadata)
else:
self.logger.info("Skipping updated probed file %s" % fileloc)
return
+
+ def write_file(self, fileloc, contents):
+ try:
+ os.makedirs(os.path.dirname(fileloc))
+ except OSError:
+ err = sys.exc_info()[1]
+ if err.errno == errno.EEXIST:
+ pass
+ else:
+ self.logger.error("Could not create parent directories for %s: "
+ "%s" % (fileloc, err))
+ return
+
+ try:
+ open(fileloc, 'wb').write(contents)
+ except IOError:
+ err = sys.exc_info()[1]
+ self.logger.error("Could not write %s: %s" % (fileloc, err))
+ return
+
+ def verify_file(self, filename, contents, metadata):
+ # Service the FAM events queued up by the key generation so
+ # the data structure entries will be available for binding.
+ #
+ # NOTE: We wait for up to ten seconds. There is some potential
+ # for race condition, because if the file monitor doesn't get
+ # notified about the new key files in time, those entries
+ # won't be available for binding. In practice, this seems
+ # "good enough".
+ entry = self.entries[metadata.hostname][filename]
+ cfg = self.core.plugins['Cfg']
+ tries = 0
+ updated = False
+ while not updated:
+ if tries >= 10:
+ self.logger.error("%s still not registered" % filename)
+ return
+ self.core.fam.handle_events_in_interval(1)
+ try:
+ cfg.entries[filename].bind_entry(entry, metadata)
+ except Bcfg2.Server.Plugin.PluginExecutionError:
+ tries += 1
+ continue
+
+ # get current entry data
+ if entry.get("encoding") == "base64":
+ entrydata = binascii.a2b_base64(entry.text)
+ else:
+ entrydata = entry.text
+ if entrydata == contents:
+ updated = True
+ tries += 1
def write_infoxml(self, infoxml, entry, data):
""" write an info.xml for the file """
+ if os.path.exists(infoxml):
+ return
+
self.logger.info("Writing info.xml at %s for %s" %
(infoxml, data.get("name")))
info = \
@@ -222,5 +223,10 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin,
root = lxml.etree.Element("FileInfo")
root.append(info)
- open(infoxml, "w").write(lxml.etree.tostring(root,
- pretty_print=True))
+ try:
+ open(infoxml, "w").write(lxml.etree.tostring(root,
+ pretty_print=True))
+ except IOError:
+ err = sys.exc_info()[1]
+ self.logger.error("Could not write %s: %s" % (fileloc, err))
+ return
diff --git a/src/lib/Server/Plugins/Packages/Source.py b/src/lib/Server/Plugins/Packages/Source.py
index 910a90cac..1dfeecc40 100644
--- a/src/lib/Server/Plugins/Packages/Source.py
+++ b/src/lib/Server/Plugins/Packages/Source.py
@@ -136,7 +136,7 @@ class Source(Bcfg2.Server.Plugin.Debuggable):
def get_repo_name(self, url_map):
# try to find a sensible name for a repo
if url_map['component']:
- return url_map['component']
+ rname = url_map['component']
else:
name = None
for repo_re in (self.mrepo_re,
@@ -144,14 +144,18 @@ class Source(Bcfg2.Server.Plugin.Debuggable):
self.genericrepo_re):
match = repo_re.search(url_map['url'])
if match:
- name = match.group(1).replace('/', '-')
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]
- return "%s-%s" % (self.groups[0], name)
+ rname = "%s-%s" % (self.groups[0], name)
+ # 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
+ # doesn't seem to be a reason for this, because yum.
+ return re.sub(r'[^A-Za-z0-9-_.:]', '-', rname)
def __str__(self):
if self.rawurl:
diff --git a/src/lib/Server/Plugins/Packages/Yum.py b/src/lib/Server/Plugins/Packages/Yum.py
index a5fe706cd..416602b27 100644
--- a/src/lib/Server/Plugins/Packages/Yum.py
+++ b/src/lib/Server/Plugins/Packages/Yum.py
@@ -124,6 +124,7 @@ class YumCollection(Collection):
mainopts = dict(cachedir=self.cachefile,
keepcache="0",
sslverify="0",
+ debuglevel="0",
reposdir="/dev/null")
try:
for opt in self.config.options("yum"):
@@ -394,6 +395,11 @@ class YumCollection(Collection):
if rv:
self.logger.error("Packages: error running bcfg2-yum-helper "
"(returned %d): %s" % (rv, stderr))
+ elif self.debug_flag:
+ self.logger.debug("Packages: debug info from bcfg2-yum-helper: %s" %
+ stderr)
+ self.logger.debug("Packages: output from bcfg2-yum-helper: %s" %
+ stderr)
try:
return json.loads(stdout)
except ValueError:
diff --git a/src/lib/Server/Plugins/SSHbase.py b/src/lib/Server/Plugins/SSHbase.py
index 724d169f5..eb91bea39 100644
--- a/src/lib/Server/Plugins/SSHbase.py
+++ b/src/lib/Server/Plugins/SSHbase.py
@@ -235,6 +235,8 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin,
if entry.specific.match(event.filename):
entry.handle_event(event)
if event.filename.endswith(".pub"):
+ self.logger.info("New public key %s; invalidating "
+ "ssh_known_hosts cache" % event.filename)
self.skn = False
return
@@ -244,6 +246,8 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin,
return
if event.filename.endswith('.static'):
+ self.logger.info("Static key %s %s; invalidating ssh_known_hosts "
+ "cache" % (event.filename, action))
if action == "deleted" and event.filename in self.static:
del self.static[event.filename]
self.skn = False
diff --git a/src/lib/Server/Plugins/Trigger.py b/src/lib/Server/Plugins/Trigger.py
index f6dd47e12..eb3310a4e 100644
--- a/src/lib/Server/Plugins/Trigger.py
+++ b/src/lib/Server/Plugins/Trigger.py
@@ -26,12 +26,19 @@ class Trigger(Bcfg2.Server.Plugin.Plugin,
try:
os.stat(self.data)
except:
- self.logger.error("Trigger: spool directory %s does not exist; unloading" % self.data)
+ self.logger.error("Trigger: spool directory %s does not exist; "
+ "unloading" % self.data)
raise Bcfg2.Server.Plugin.PluginInitError
def process_statistics(self, metadata, _):
args = [metadata.hostname, '-p', metadata.profile, '-g',
':'.join([g for g in metadata.groups])]
for notifier in os.listdir(self.data):
- n = self.data + '/' + notifier
- async_run(n, args)
+ 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)
diff --git a/src/lib/Server/Reports/reports/templates/base.html b/src/lib/Server/Reports/reports/templates/base.html
index a12bf66ba..f541c0d2b 100644
--- a/src/lib/Server/Reports/reports/templates/base.html
+++ b/src/lib/Server/Reports/reports/templates/base.html
@@ -87,7 +87,7 @@
<div style='clear:both'></div>
</div><!-- document -->
<div id="footer">
- <span>Bcfg2 Version 1.2.1</span>
+ <span>Bcfg2 Version 1.2.2</span>
</div>
<div id="calendar_div" style='position:absolute; visibility:hidden; background-color:white; layer-background-color:white;'></div>