diff options
author | Sol Jerome <sol.jerome@gmail.com> | 2011-05-03 14:06:26 -0500 |
---|---|---|
committer | Sol Jerome <sol.jerome@gmail.com> | 2011-05-03 14:06:26 -0500 |
commit | 136d7397a067d815d986b49e06d6d3217fdb18f8 (patch) | |
tree | 2decb82d93bdd67365162ddfcbb472caffdbbd06 | |
parent | 20ed074b7a05b8b3817b1ca9a11d8a4b09b719ce (diff) | |
parent | 71a026b3b7c13fdf242d387b255d6e0daefce0ca (diff) | |
download | bcfg2-136d7397a067d815d986b49e06d6d3217fdb18f8.tar.gz bcfg2-136d7397a067d815d986b49e06d6d3217fdb18f8.tar.bz2 bcfg2-136d7397a067d815d986b49e06d6d3217fdb18f8.zip |
Merge branch 'py3k'
28 files changed, 305 insertions, 247 deletions
diff --git a/doc/installation/prerequisites.txt b/doc/installation/prerequisites.txt index c86e86774..deeaba203 100644 --- a/doc/installation/prerequisites.txt +++ b/doc/installation/prerequisites.txt @@ -21,7 +21,7 @@ Bcfg2 Client +----------------------------+------------------------+--------------------------------+ | libxslt (if lxml is used) | Any | libxml2 | +----------------------------+------------------------+--------------------------------+ -| python | 2.3-2.4, 2.5-2.7 [#f1] | | +| python | 2.4 and greater [#f1] | | +----------------------------+------------------------+--------------------------------+ | lxml or elementtree [#f2]_ | Any | lxml: libxml2, libxslt, python | +----------------------------+------------------------+--------------------------------+ diff --git a/src/lib/Bcfg2Py3Incompat.py b/src/lib/Bcfg2Py3Incompat.py new file mode 100644 index 000000000..6b66e72b0 --- /dev/null +++ b/src/lib/Bcfg2Py3Incompat.py @@ -0,0 +1,2 @@ +def fprint(s, f): + print(s, file=f) diff --git a/src/lib/Bcfg2Py3k.py b/src/lib/Bcfg2Py3k.py index 0f5321a41..c9e48a49b 100644 --- a/src/lib/Bcfg2Py3k.py +++ b/src/lib/Bcfg2Py3k.py @@ -1,3 +1,5 @@ +import sys + try: from email.Utils import formatdate except ImportError: @@ -5,7 +7,7 @@ except ImportError: # urllib imports try: - from urlparse import urljoin + from urlparse import urljoin, urlparse from urllib2 import HTTPBasicAuthHandler from urllib2 import HTTPPasswordMgrWithDefaultRealm from urllib2 import build_opener @@ -13,7 +15,7 @@ try: from urllib import urlopen from urllib2 import HTTPError except ImportError: - from urllib.parse import urljoin + from urllib.parse import urljoin, urlparse from urllib.request import HTTPBasicAuthHandler from urllib.request import HTTPPasswordMgrWithDefaultRealm from urllib.request import build_opener @@ -37,10 +39,43 @@ except ImportError: import pickle as cPickle try: - from Queue import Queue - from Queue import Empty - from Queue import Full + from Queue import Queue, Empty, Full +except ImportError: + from queue import Queue, Empty, Full + +# xmlrpc imports +try: + import xmlrpclib, SimpleXMLRPCServer +except ImportError: + import xmlrpc.client as xmlrpclib + import xmlrpc.server as SimpleXMLRPCServer + +# socketserver import +try: + import SocketServer +except ImportError: + import socketserver as SocketServer + +# httplib imports +try: + import httplib except ImportError: - from queue import Queue - from queue import Empty - from queue import Full + import http.client as httplib + +# print to file compatibility +def u_str(string): + if sys.hexversion >= 0x03000000: + return string + else: + return unicode(string) + +""" +In order to use the new syntax for printing to a file, we need to do +a conditional import because there is a syntax incompatibility between +the two versions of python. +""" +if sys.hexversion >= 0x03000000: + from Bcfg2.Bcfg2Py3Incompat import fprint +else: + def fprint(s, f): + print >> f, s diff --git a/src/lib/Client/Tools/__init__.py b/src/lib/Client/Tools/__init__.py index 6a934fe52..88609c2f6 100644 --- a/src/lib/Client/Tools/__init__.py +++ b/src/lib/Client/Tools/__init__.py @@ -4,9 +4,9 @@ import warnings warnings.filterwarnings("ignore", "The popen2 module is deprecated.*", DeprecationWarning) import os -import popen2 import stat import sys +from subprocess import Popen, PIPE import time import Bcfg2.Client.XML @@ -25,26 +25,6 @@ class toolInstantiationError(Exception): pass -class readonlypipe(popen2.Popen4): - """This pipe sets up stdin --> /dev/null.""" - - def __init__(self, cmd, bufsize=-1): - popen2._cleanup() - c2pread, c2pwrite = os.pipe() - null = open('/dev/null', 'w+') - self.pid = os.fork() - if self.pid == 0: - # Child - os.dup2(null.fileno(), sys.__stdin__.fileno()) - #os.dup2(p2cread, 0) - os.dup2(c2pwrite, 1) - os.dup2(c2pwrite, 2) - self._run_child(cmd) - os.close(c2pwrite) - self.fromchild = os.fdopen(c2pread, 'r', bufsize) - popen2._active.append(self) - - class executor: """This class runs stuff for us""" @@ -53,30 +33,12 @@ class executor: def run(self, command): """Run a command in a pipe dealing with stdout buffer overloads.""" - self.logger.debug('> %s' % command) - - runpipe = readonlypipe(command, bufsize=16384) - output = [] - try: # macosx doesn't like this - runpipe.fromchild.flush() - except IOError: - pass - line = runpipe.fromchild.readline() - cmdstat = -1 - while cmdstat == -1: - while line: - if len(line) > 0: - self.logger.debug('< %s' % line[:-1]) - output.append(line[:-1]) - line = runpipe.fromchild.readline() - time.sleep(0.1) - cmdstat = runpipe.poll() - output += [line[:-1] for line in runpipe.fromchild.readlines() \ - if line] - # The exit code from the program is in the upper byte of the - # value returned by cmdstat. Shift it down for tools looking at - # the value. - return ((cmdstat >> 8), output) + p = Popen(command, shell=True, bufsize=16384, + stdin=PIPE, stdout=PIPE, close_fds=True) + output = p.communicate()[0] + for line in output.splitlines(): + self.logger.debug('< %s' % line) + return (p.returncode, output.splitlines()) class Tool: diff --git a/src/lib/Component.py b/src/lib/Component.py index 33b1c9289..88dce906e 100644 --- a/src/lib/Component.py +++ b/src/lib/Component.py @@ -11,12 +11,12 @@ import pydoc import sys import time import threading -import urlparse -import xmlrpclib import Bcfg2.Logger from Bcfg2.Statistics import Statistics from Bcfg2.SSLServer import XMLRPCServer +# Compatibility import +from Bcfg2.Bcfg2Py3k import xmlrpclib, urlparse, fprint logger = logging.getLogger() @@ -56,11 +56,11 @@ def run_component(component_cls, location, daemon, pidfile_name, to_file, os.chdir(os.sep) pidfile = open(pidfile_name or "/dev/null", "w") - print >> pidfile, os.getpid() + fprint(os.getpid(), pidfile) pidfile.close() component = component_cls(cfile=cfile, **cls_kwargs) - up = urlparse.urlparse(location) + up = urlparse(location) port = tuple(up[1].split(':')) port = (port[0], int(port[1])) try: @@ -153,30 +153,31 @@ class Component (object): automatic == True. """ - for name, func in inspect.getmembers(self, callable): - if getattr(func, "automatic", False): - need_to_lock = not getattr(func, 'locking', False) - if (time.time() - func.automatic_ts) > \ - func.automatic_period: - if need_to_lock: - t1 = time.time() - self.lock.acquire() - t2 = time.time() - self.instance_statistics.add_value('component_lock', t2-t1) - try: - mt1 = time.time() + for name, func in inspect.getmembers(self): + if name == '__call__': + if getattr(func, "automatic", False): + need_to_lock = not getattr(func, 'locking', False) + if (time.time() - func.automatic_ts) > \ + func.automatic_period: + if need_to_lock: + t1 = time.time() + self.lock.acquire() + t2 = time.time() + self.instance_statistics.add_value('component_lock', t2-t1) try: - func() - except: - self.logger.error("Automatic method %s failed" \ - % (name), exc_info=1) - finally: - mt2 = time.time() - - if need_to_lock: - self.lock.release() - self.instance_statistics.add_value(name, mt2-mt1) - func.__dict__['automatic_ts'] = time.time() + mt1 = time.time() + try: + func() + except: + self.logger.error("Automatic method %s failed" \ + % (name), exc_info=1) + finally: + mt2 = time.time() + + if need_to_lock: + self.lock.release() + self.instance_statistics.add_value(name, mt2-mt1) + func.__dict__['automatic_ts'] = time.time() def _resolve_exposed_method(self, method_name): """Resolve an exposed method. @@ -209,7 +210,8 @@ class Component (object): except NoExposedMethod: self.logger.error("Unknown method %s" % (method)) raise xmlrpclib.Fault(7, "Unknown method %s" % method) - except Exception, e: + except Exception: + e = sys.exc_info()[1] if getattr(e, "log", True): self.logger.error(e, exc_info=True) raise xmlrpclib.Fault(getattr(e, "fault_code", 1), str(e)) @@ -233,7 +235,8 @@ class Component (object): self.instance_statistics.add_value(method, method_done - method_start) except xmlrpclib.Fault: raise - except Exception, e: + except Exception: + e = sys.exc_info()[1] if getattr(e, "log", True): self.logger.error(e, exc_info=True) raise xmlrpclib.Fault(getattr(e, "fault_code", 1), str(e)) diff --git a/src/lib/Logger.py b/src/lib/Logger.py index ae73a6d41..b49a7069f 100644 --- a/src/lib/Logger.py +++ b/src/lib/Logger.py @@ -10,6 +10,8 @@ import socket import struct import sys import termios +# Compatibility import +from Bcfg2.Bcfg2Py3k import fprint logging.raiseExceptions = 0 @@ -116,7 +118,7 @@ class FragmentingSysLogHandler(logging.handlers.SysLogHandler): def emit(self, record): """Chunk and deliver records.""" record.name = self.procname - if str(record.msg) > 250: + if len(record.msg) > 250: msgs = [] error = record.exc_info record.exc_info = None @@ -134,7 +136,7 @@ class FragmentingSysLogHandler(logging.handlers.SysLogHandler): newrec.levelname.lower()), self.format(newrec)) try: - self.socket.send(msg) + self.socket.send(msg.encode('ascii')) except socket.error: for i in range(10): try: @@ -229,7 +231,7 @@ def trace_process(**kwargs): filename = filename[:-1] name = frame.f_globals["__name__"] line = linecache.getline(filename, lineno) - print >> log_file, "%s:%s: %s" % (name, lineno, line.rstrip()) + fprint("%s:%s: %s" % (name, lineno, line.rstrip()), log_file) return traceit sys.settrace(traceit) diff --git a/src/lib/Options.py b/src/lib/Options.py index 1973e7091..d5304e696 100644 --- a/src/lib/Options.py +++ b/src/lib/Options.py @@ -1,11 +1,12 @@ """Option parsing library for utilities.""" __revision__ = '$Revision$' -import ConfigParser import getopt import os import sys import Bcfg2.Client.Tools +# Compatibility imports +from Bcfg2.Bcfg2Py3k import ConfigParser def bool_cook(x): if x: @@ -146,7 +147,8 @@ class OptionSet(dict): try: opts, args = getopt.getopt(argv, self.buildGetopt(), self.buildLongGetopt()) - except getopt.GetoptError, err: + except getopt.GetoptError: + err = sys.exc_info()[1] self.helpExit(err) if '-h' in argv: self.helpExit('', 0) diff --git a/src/lib/Proxy.py b/src/lib/Proxy.py index 8b3fcb87c..8a1ad683e 100644 --- a/src/lib/Proxy.py +++ b/src/lib/Proxy.py @@ -11,9 +11,6 @@ load_config -- read configuration files __revision__ = '$Revision: $' -from xmlrpclib import _Method - -import httplib import logging import re import socket @@ -25,7 +22,7 @@ import socket try: import ssl SSL_LIB = 'py26_ssl' -except ImportError, e: +except ImportError: from M2Crypto import SSL import M2Crypto.SSL.Checker SSL_LIB = 'm2crypto' @@ -33,8 +30,9 @@ except ImportError, e: import sys import time -import urlparse -import xmlrpclib + +# Compatibility imports +from Bcfg2.Bcfg2Py3k import httplib, xmlrpclib, urlparse version = sys.version_info[:2] has_py23 = version >= (2, 3) @@ -51,7 +49,7 @@ class CertificateError(Exception): self.commonName = commonName -class RetryMethod(_Method): +class RetryMethod(xmlrpclib._Method): """Method with error handling and retries built in.""" log = logging.getLogger('xmlrpc') max_retries = 4 @@ -59,21 +57,24 @@ class RetryMethod(_Method): def __call__(self, *args): for retry in range(self.max_retries): try: - return _Method.__call__(self, *args) - except xmlrpclib.ProtocolError, err: + return xmlrpclib._Method.__call__(self, *args) + except xmlrpclib.ProtocolError: + err = sys.exc_info()[1] self.log.error("Server failure: Protocol Error: %s %s" % \ (err.errcode, err.errmsg)) raise xmlrpclib.Fault(20, "Server Failure") except xmlrpclib.Fault: raise - except socket.error, err: + except socket.error: + err = sys.exc_info()[1] if hasattr(err, 'errno') and err.errno == 336265218: self.log.error("SSL Key error") break if retry == 3: self.log.error("Server failure: %s" % err) raise xmlrpclib.Fault(20, err) - except CertificateError, ce: + except CertificateError: + ce = sys.exc_info()[1] self.log.error("Got unallowed commonName %s from server" \ % ce.commonName) break @@ -87,7 +88,7 @@ class RetryMethod(_Method): raise xmlrpclib.Fault(20, "Server Failure") # sorry jon -xmlrpclib._Method = RetryMethod +_Method = RetryMethod class SSLHTTPConnection(httplib.HTTPConnection): @@ -242,7 +243,8 @@ class SSLHTTPConnection(httplib.HTTPConnection): try: self.sock.connect((hostname, self.port)) # automatically checks cert matches host - except M2Crypto.SSL.Checker.WrongHost, wr: + except M2Crypto.SSL.Checker.WrongHost: + wr = sys.exc_info()[1] raise CertificateError(wr) @@ -325,7 +327,7 @@ def ComponentProxy(url, user=None, password=None, """ if user and password: - method, path = urlparse.urlparse(url)[:2] + method, path = urlparse(url)[:2] newurl = "%s://%s:%s@%s" % (method, user, password, path) else: newurl = url diff --git a/src/lib/SSLServer.py b/src/lib/SSLServer.py index 2395bb84f..a89beabbb 100644 --- a/src/lib/SSLServer.py +++ b/src/lib/SSLServer.py @@ -8,10 +8,7 @@ __all__ = [ import os import sys -import xmlrpclib import socket -import SocketServer -import SimpleXMLRPCServer import base64 import select import signal @@ -19,6 +16,8 @@ import logging import ssl import threading import time +# Compatibility imports +from Bcfg2.Bcfg2Py3k import xmlrpclib, SimpleXMLRPCServer, SocketServer class ForkedChild(Exception): @@ -51,7 +50,8 @@ class XMLRPCDispatcher (SimpleXMLRPCServer.SimpleXMLRPCDispatcher): raw_response = xmlrpclib.dumps(response, methodresponse=1, allow_none=self.allow_none, encoding=self.encoding) - except xmlrpclib.Fault, fault: + except xmlrpclib.Fault: + fault = sys.exc_info()[1] raw_response = xmlrpclib.dumps(fault, allow_none=self.allow_none, encoding=self.encoding) @@ -258,7 +258,8 @@ class XMLRPCRequestHandler (SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): # If we hit SSL3_WRITE_PENDING here try to resend. self.wfile.write(response) break - except ssl.SSLError, e: + except ssl.SSLError: + e = sys.exc_info()[1] if str(e).find("SSL3_WRITE_PENDING") < 0: raise self.logger.error("SSL3_WRITE_PENDING") diff --git a/src/lib/Server/Admin/Init.py b/src/lib/Server/Admin/Init.py index 9771fd10b..e69412a5e 100644 --- a/src/lib/Server/Admin/Init.py +++ b/src/lib/Server/Admin/Init.py @@ -138,7 +138,7 @@ def create_key(hostname, keypath, certpath, country, state, location): keypath, certpath)) subprocess.call((ccstr), shell=True) - os.chmod(keypath, stat.S_IRUSR|stat.S_IWUSR) # 0600 + os.chmod(keypath, stat.S_IRUSR | stat.S_IWUSR) # 0600 def create_conf(confpath, confdata): @@ -156,8 +156,9 @@ def create_conf(confpath, confdata): return try: open(confpath, "w").write(confdata) - os.chmod(keypath, stat.S_IRUSR|stat.S_IWUSR) # 0600 - except Exception, e: + os.chmod(keypath, stat.S_IRUSR | stat.S_IWUSR) # 0600 + except Exception: + e = sys.exc_info()[1] print("Error %s occured while trying to write configuration " "file to '%s'.\n" % (e, confpath)) @@ -381,7 +382,8 @@ class Init(Bcfg2.Server.Admin.Mode): '', ["Bcfg2.Server.Plugins"]) cls = getattr(module, plugin) cls.init_repo(self.repopath) - except Exception, e: + except Exception: + e = sys.exc_info()[1] print("Plugin setup for %s failed: %s\n" "Check that dependencies are installed?" % (plugin, e)) diff --git a/src/lib/Server/Admin/Query.py b/src/lib/Server/Admin/Query.py index 207b65035..9e1d7cc88 100644 --- a/src/lib/Server/Admin/Query.py +++ b/src/lib/Server/Admin/Query.py @@ -26,7 +26,8 @@ class Query(Bcfg2.Server.Admin.Mode): self.bcore = Bcfg2.Server.Core.Core(self.get_repo_path(), ['Metadata', 'Probes'], 'foo', False, 'UTF-8') - except Bcfg2.Server.Core.CoreInitError, msg: + except Bcfg2.Server.Core.CoreInitError: + msg = sys.exc_info()[1] self.errExit("Core load failed because %s" % msg) self.bcore.fam.handle_events_in_interval(1) self.meta = self.bcore.metadata diff --git a/src/lib/Server/Admin/Reports.py b/src/lib/Server/Admin/Reports.py index ee3a4473f..942477a49 100644 --- a/src/lib/Server/Admin/Reports.py +++ b/src/lib/Server/Admin/Reports.py @@ -1,7 +1,6 @@ '''Admin interface for dynamic reports''' import Bcfg2.Logger import Bcfg2.Server.Admin -import ConfigParser import datetime import os import logging @@ -14,6 +13,9 @@ from Bcfg2.Server.Reports.updatefix import update_database from Bcfg2.Server.Reports.utils import * from lxml.etree import XML, XMLSyntaxError +# Compatibility import +from Bcfg2.Bcfg2Py3k import ConfigParser + # FIXME: Remove when server python dep is 2.5 or greater if sys.version_info >= (2, 5): from hashlib import md5 @@ -26,7 +28,8 @@ import django.core.management # FIXME - settings file uses a hardcoded path for /etc/bcfg2.conf try: import Bcfg2.Server.Reports.settings -except Exception, e: +except Exception: + e = sys.exc_info()[1] sys.stderr.write("Failed to load configuration settings. %s\n" % e) sys.exit(1) @@ -185,7 +188,8 @@ class Reports(Bcfg2.Server.Admin.Mode): # Currently only reasons are a problem try: start_count = Reason.objects.count() - except Exception, e: + except Exception: + e = sys.exc_info()[1] self.log.error("Failed to load reason objects: %s" % e) return dup_reasons = [] @@ -216,7 +220,8 @@ class Reports(Bcfg2.Server.Admin.Mode): cursor.executemany('update reports_entries_interactions set reason_id=%s where reason_id=%s', batch_update) cursor.executemany('delete from reports_reason where id = %s', dup_reasons) transaction.set_dirty() - except Exception, ex: + except Exception: + ex = sys.exc_info()[1] self.log.error("Failed to delete reasons: %s" % ex) raise diff --git a/src/lib/Server/Admin/Snapshots.py b/src/lib/Server/Admin/Snapshots.py index d58873174..052545b61 100644 --- a/src/lib/Server/Admin/Snapshots.py +++ b/src/lib/Server/Admin/Snapshots.py @@ -8,6 +8,8 @@ import Bcfg2.Server.Snapshots import Bcfg2.Server.Snapshots.model from Bcfg2.Server.Snapshots.model import Snapshot, Client, Metadata, Base, \ File, Group, Package, Service +# Compatibility import +from Bcfg2.Bcfg2Py3k import u_str class Snapshots(Bcfg2.Server.Admin.Mode): __shorthelp__ = "Interact with the Snapshots system" @@ -71,7 +73,7 @@ class Snapshots(Bcfg2.Server.Admin.Mode): session.commit() elif args[0] == 'dump': client = args[1] - snap = Snapshot.get_current(self.session, unicode(client)) + snap = Snapshot.get_current(self.session, u_str(client)) if not snap: print("Current snapshot for %s not found" % client) sys.exit(1) @@ -105,7 +107,7 @@ class Snapshots(Bcfg2.Server.Admin.Mode): print("Usage: bcfg2-admin snapshots -b <client>") return client = args[2] - snap = Snapshot.get_current(self.session, unicode(client)) + snap = Snapshot.get_current(self.session, u_str(client)) if not snap: print("Current snapshot for %s not found" % client) sys.exit(1) @@ -128,7 +130,7 @@ class Snapshots(Bcfg2.Server.Admin.Mode): elif '-e' in args[1:]: # Query a single host for extra entries client = args[2] - snap = Snapshot.get_current(self.session, unicode(client)) + snap = Snapshot.get_current(self.session, u_str(client)) if not snap: print("Current snapshot for %s not found" % client) sys.exit(1) diff --git a/src/lib/Server/Admin/Viz.py b/src/lib/Server/Admin/Viz.py index a77502b5d..f39e6d7a8 100644 --- a/src/lib/Server/Admin/Viz.py +++ b/src/lib/Server/Admin/Viz.py @@ -45,7 +45,8 @@ class Viz(Bcfg2.Server.Admin.MetadataCore): opts, args = getopt.getopt(args, 'Hbko:', ['includehosts', 'includebundles', 'includekey', 'outfile=']) - except getopt.GetoptError, msg: + except getopt.GetoptError: + msg = sys.exc_info()[1] print(msg) #FIXME: is this for --raw? diff --git a/src/lib/Server/Admin/Xcmd.py b/src/lib/Server/Admin/Xcmd.py index e761a5e3d..fd5794f88 100644 --- a/src/lib/Server/Admin/Xcmd.py +++ b/src/lib/Server/Admin/Xcmd.py @@ -1,10 +1,12 @@ import sys -import xmlrpclib import Bcfg2.Options import Bcfg2.Proxy import Bcfg2.Server.Admin +# Compatibility import +from Bcfg2.Bcfg2Py3k import xmlrpclib + class Xcmd(Bcfg2.Server.Admin.Mode): __shorthelp__ = ("XML-RPC Command Interface") @@ -39,7 +41,8 @@ class Xcmd(Bcfg2.Server.Admin.Mode): args = tuple(setup['args'][1:]) try: data = getattr(proxy, cmd)(*args) - except xmlrpclib.Fault, flt: + except xmlrpclib.Fault: + flt = sys.exc_info()[1] if flt.faultCode == 7: print("Unknown method %s" % cmd) return diff --git a/src/lib/Server/Admin/__init__.py b/src/lib/Server/Admin/__init__.py index 411f909ee..8915492a3 100644 --- a/src/lib/Server/Admin/__init__.py +++ b/src/lib/Server/Admin/__init__.py @@ -19,13 +19,14 @@ __all__ = [ 'Xcmd' ] -import ConfigParser import logging import lxml.etree import sys import Bcfg2.Server.Core import Bcfg2.Options +# Compatibility import +from Bcfg2.Bcfg2Py3k import ConfigParser class ModeOperationError(Exception): @@ -126,7 +127,8 @@ class MetadataCore(Mode): self.bcore = Bcfg2.Server.Core.Core(self.get_repo_path(), setup['plugins'], 'foo', 'UTF-8') - except Bcfg2.Server.Core.CoreInitError, msg: + except Bcfg2.Server.Core.CoreInitError: + msg = sys.exc_info()[1] self.errExit("Core load failed because %s" % msg) self.bcore.fam.handle_events_in_interval(5) self.metadata = self.bcore.metadata diff --git a/src/lib/Server/Core.py b/src/lib/Server/Core.py index e82e05a89..ac0a51e23 100644 --- a/src/lib/Server/Core.py +++ b/src/lib/Server/Core.py @@ -5,14 +5,18 @@ import atexit import logging import lxml.etree import select +import sys import threading import time -import xmlrpclib from Bcfg2.Component import Component, exposed from Bcfg2.Server.Plugin import PluginInitError, PluginExecutionError import Bcfg2.Server.FileMonitor import Bcfg2.Server.Plugins.Metadata +# Compatibility imports +from Bcfg2.Bcfg2Py3k import xmlrpclib +if sys.hexversion >= 0x03000000: + from functools import reduce logger = logging.getLogger('Bcfg2.Server.Core') @@ -142,7 +146,7 @@ class Core(Component): try: mod = getattr(__import__("Bcfg2.Server.Plugins.%s" % (plugin)).Server.Plugins, plugin) - except ImportError, e: + except ImportError: try: mod = __import__(plugin) except: @@ -177,7 +181,8 @@ class Core(Component): plugin.validate_structures(metadata, data) elif base_cls == Bcfg2.Server.Plugin.GoalValidator: plugin.validate_goals(metadata, data) - except Bcfg2.Server.Plugin.ValidationError, err: + except Bcfg2.Server.Plugin.ValidationError: + err = sys.exc_info()[1] logger.error("Plugin %s structure validation failed: %s" \ % (plugin.name, err.message)) raise diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index 6351a9eb1..cd2b63656 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -18,6 +18,9 @@ import Bcfg2.Options # py3k compatibility if sys.hexversion >= 0x03000000: from functools import reduce + from io import FileIO as BUILTIN_FILE_TYPE +else: + BUILTIN_FILE_TYPE = file from Bcfg2.Bcfg2Py3k import Queue from Bcfg2.Bcfg2Py3k import Empty from Bcfg2.Bcfg2Py3k import Full @@ -346,7 +349,7 @@ class FileBacked(object): if event and event.code2str() not in ['exists', 'changed', 'created']: return try: - self.data = file(self.name).read() + self.data = BUILTIN_FILE_TYPE(self.name).read() self.Index() except IOError: logger.error("Failed to read file %s" % (self.name)) @@ -577,7 +580,7 @@ class XMLSrc(XMLFileBacked): def HandleEvent(self, _=None): """Read file upon update.""" try: - data = file(self.name).read() + data = BUILTIN_FILE_TYPE(self.name).read() except IOError: logger.error("Failed to read file %s" % (self.name)) return diff --git a/src/lib/Server/Plugins/Packages.py b/src/lib/Server/Plugins/Packages.py index 1178aadaa..19152074e 100644 --- a/src/lib/Server/Plugins/Packages.py +++ b/src/lib/Server/Plugins/Packages.py @@ -17,6 +17,12 @@ from Bcfg2.Bcfg2Py3k import install_opener from Bcfg2.Bcfg2Py3k import build_opener from Bcfg2.Bcfg2Py3k import urlopen +# py3k compatibility +if sys.hexversion >= 0x03000000: + from io import FileIO as BUILTIN_FILE_TYPE +else: + BUILTIN_FILE_TYPE = file + # FIXME: Remove when server python dep is 2.5 or greater if sys.version_info >= (2, 5): from hashlib import md5 @@ -177,7 +183,7 @@ class Source(object): logger.error("Packages: Failed to fetch url %s. code=%s" \ % (url, h.code)) continue - file(fname, 'w').write(data) + BUILTIN_FILE_TYPE(fname, 'w').write(data) def applies(self, metadata): return len([g for g in self.basegroups if g in metadata.groups]) != 0 and \ @@ -231,13 +237,13 @@ class YUMSource(Source): self.file_to_arch = dict() def save_state(self): - cache = file(self.cachefile, 'wb') + cache = BUILTIN_FILE_TYPE(self.cachefile, 'wb') cPickle.dump((self.packages, self.deps, self.provides, self.filemap, self.url_map), cache, 2) cache.close() def load_state(self): - data = file(self.cachefile) + data = BUILTIN_FILE_TYPE(self.cachefile) (self.packages, self.deps, self.provides, \ self.filemap, self.url_map) = cPickle.load(data) @@ -378,13 +384,13 @@ class APTSource(Source): 'components': self.components, 'arches': self.arches, 'groups': self.groups}] def save_state(self): - cache = file(self.cachefile, 'wb') + cache = BUILTIN_FILE_TYPE(self.cachefile, 'wb') cPickle.dump((self.pkgnames, self.deps, self.provides), cache, 2) cache.close() def load_state(self): - data = file(self.cachefile) + data = BUILTIN_FILE_TYPE(self.cachefile) self.pkgnames, self.deps, self.provides = cPickle.load(data) def filter_unknown(self, unknown): @@ -423,7 +429,7 @@ class APTSource(Source): print("Failed to read file %s" % fname) raise for line in reader.readlines(): - words = line.strip().split(':', 1) + words = line.strip().split(b':', 1) if words[0] == 'Package': pkgname = words[1].strip().rstrip() self.pkgnames.add(pkgname) @@ -500,13 +506,13 @@ class PACSource(Source): 'components': self.components, 'arches': self.arches, 'groups': self.groups}] def save_state(self): - cache = file(self.cachefile, 'wb') + cache = BUILTIN_FILE_TYPE(self.cachefile, 'wb') cPickle.dump((self.pkgnames, self.deps, self.provides), cache, 2) cache.close() def load_state(self): - data = file(self.cachefile) + data = BUILTIN_FILE_TYPE(self.cachefile) self.pkgnames, self.deps, self.provides = cPickle.load(data) def filter_unknown(self, unknown): diff --git a/src/lib/Server/Plugins/TGenshi.py b/src/lib/Server/Plugins/TGenshi.py index cd268e967..83b60c958 100644 --- a/src/lib/Server/Plugins/TGenshi.py +++ b/src/lib/Server/Plugins/TGenshi.py @@ -98,7 +98,7 @@ class TemplateFile: entry.text = textdata else: if entry.get('encoding') == 'base64': - # take care of case where file needs base64 encoding + # take care of case where file needs base64 encoding entry.text = binascii.b2a_base64(textdata) else: entry.text = unicode(textdata, self.encoding) diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2 index 56f98ade4..7f7d8f5c6 100755 --- a/src/sbin/bcfg2 +++ b/src/sbin/bcfg2 @@ -3,18 +3,20 @@ """Bcfg2 Client""" __revision__ = '$Revision$' +import fcntl import logging import os import signal +import stat import sys import tempfile import time -import xmlrpclib -import fcntl import Bcfg2.Options import Bcfg2.Client.XML import Bcfg2.Client.Frame import Bcfg2.Client.Tools +# Compatibility imports +from Bcfg2.Bcfg2Py3k import xmlrpclib import Bcfg2.Proxy import Bcfg2.Logger @@ -135,7 +137,9 @@ class Client: script.write(probe.text) script.close() os.close(scripthandle) - os.chmod(script.name, 0755) + os.chmod(script.name, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | + stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH | + stat.S_IWUSR) # 0755 ret.text = os.popen(script.name).read().strip() self.logger.info("Probe %s has result:\n%s" % (name, ret.text)) finally: @@ -188,7 +192,8 @@ class Client: try: probe_data = proxy.GetProbes() - except xmlrpclib.Fault, flt: + except xmlrpclib.Fault: + flt = sys.exc_info()[1] self.logger.error("Failed to download probes from bcfg2") self.logger.error(flt.faultString) raise SystemExit(1) @@ -197,7 +202,8 @@ class Client: try: probes = Bcfg2.Client.XML.XML(probe_data) - except Bcfg2.Client.XML.ParseError, syntax_error: + except Bcfg2.Client.XML.ParseError: + syntax_error = sys.exc_info()[1] self.fatal_error( "Server returned invalid probe requests: %s" % (syntax_error)) @@ -228,7 +234,8 @@ class Client: self.setup['decision']) self.logger.info("Got decision list from server:") self.logger.info(self.setup['decision_list']) - except xmlrpclib.Fault, f: + except xmlrpclib.Fault: + f = sys.exc_info()[1] if f.faultCode == 1: print("GetDecisionList method not supported by server") else: @@ -254,7 +261,8 @@ class Client: try: self.config = Bcfg2.Client.XML.XML(rawconfig) - except Bcfg2.Client.XML.ParseError, syntax_error: + except Bcfg2.Client.XML.ParseError: + syntax_error = sys.exc_info()[1] self.fatal_error("The configuration could not be parsed: %s" % (syntax_error)) return(1) diff --git a/src/sbin/bcfg2-admin b/src/sbin/bcfg2-admin index 2c9a43859..36be6ab14 100755 --- a/src/sbin/bcfg2-admin +++ b/src/sbin/bcfg2-admin @@ -2,11 +2,12 @@ """bcfg2-admin is a script that helps to administrate a Bcfg2 deployment.""" from optparse import OptionParser -from StringIO import StringIO import logging import Bcfg2.Server.Core import Bcfg2.Logger import Bcfg2.Options +# Compatibility import +from Bcfg2.Bcfg2Py3k import StringIO log = logging.getLogger('bcfg2-admin') @@ -56,14 +57,15 @@ def main(): else: # Print short help for all modes parser.print_help() - print create_description() + print(create_description()) raise SystemExit(0) if args[0] in get_modes(): modname = args[0].capitalize() try: mode_cls = mode_import(modname) - except ImportError, e: + except ImportError: + e = sys.exc_info()[1] log.error("Failed to load admin mode %s: %s" % (modname, e)) raise SystemExit(1) mode = mode_cls(options.configfile) @@ -73,7 +75,7 @@ def main(): else: log.error("Unknown mode %s" % args[0]) parser.print_help() - print create_description() + print(create_description()) raise SystemExit(1) if __name__ == '__main__': diff --git a/src/sbin/bcfg2-build-reports b/src/sbin/bcfg2-build-reports index 231f52105..7122fb300 100755 --- a/src/sbin/bcfg2-build-reports +++ b/src/sbin/bcfg2-build-reports @@ -13,8 +13,9 @@ import os import socket import sys from time import asctime, strptime -from ConfigParser import ConfigParser, NoSectionError, NoOptionError from lxml.etree import XML, XSLT, parse, Element, ElementTree, SubElement, tostring, XMLSyntaxError +# Compatibility imports +from Bcfg2.Bcfg2Py3k import ConfigParser def generatereport(rspec, nrpt): """ @@ -42,9 +43,9 @@ def generatereport(rspec, nrpt): # This line actually sorts from most recent to oldest. statisticslist.sort(lambda y, x: cmp(strptime(x.get("time")), strptime(y.get("time")))) stats = statisticslist[0] - + [node.remove(item) for item in node.findall('Statistics')] - + # Add a good tag if node is good and we wnat to report such. if reportgood == 'Y' and stats.get('state') == 'clean': SubElement(stats,"Good") @@ -52,7 +53,7 @@ def generatereport(rspec, nrpt): [stats.remove(item) for item in stats.findall("Bad") + stats.findall("Modified") if \ item.getchildren() == []] [stats.remove(item) for item in stats.findall("Modified") if reportmodified == 'N'] - + # Test for staleness -if stale add Stale tag. if stats.get("time").find(current_date) == -1: SubElement(stats,"Stale") @@ -64,7 +65,7 @@ def mail(mailbody, confi): try: mailer = confi.get('statistics', 'sendmailpath') - except (NoSectionError, NoOptionError): + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): mailer = "/usr/sbin/sendmail" # Open a pipe to the mail program and # write the data to the pipe. @@ -72,7 +73,7 @@ def mail(mailbody, confi): pipe.write(mailbody) exitcode = pipe.close() if exitcode: - print "Exit code: %s" % exitcode + print("Exit code: %s" % exitcode) def rss(reportxml, delivery, report): """rss appends a new report to the specified rss file @@ -98,7 +99,7 @@ def rss(reportxml, delivery, report): chantitle = SubElement(channel, "title") chantitle.text = report.attrib['name'] chanlink = SubElement(channel, "link") - + # This can later link to WWW report if one gets published # simultaneously? chanlink.text = "http://www.mcs.anl.gov/cobalt/bcfg2" @@ -119,7 +120,7 @@ def www(reportxml, delivery): """www outputs report to.""" # This can later link to WWW report if one gets published - # simultaneously? + # simultaneously? for destination in delivery.findall('Destination'): fil = open(destination.attrib['address'], 'w') @@ -138,15 +139,15 @@ def pretty_print(element, level=0): """Produce a pretty-printed text representation of element.""" if element.text: fmt = "%s<%%s %%s>%%s</%%s>" % (level*" ") - data = (element.tag, (" ".join(["%s='%s'" % keyval for keyval in element.attrib.iteritems()])), + data = (element.tag, (" ".join(["%s='%s'" % keyval for keyval in list(element.attrib.items())])), element.text, element.tag) if element._children: fmt = "%s<%%s %%s>\n" % (level*" ",) + (len(element._children) * "%s") + "%s</%%s>\n" % (level*" ") - data = (element.tag, ) + (" ".join(["%s='%s'" % keyval for keyval in element.attrib.iteritems()]),) + data = (element.tag, ) + (" ".join(["%s='%s'" % keyval for keyval in list(element.attrib.items())]),) data += tuple([pretty_print(entry, level+2) for entry in element._children]) + (element.tag, ) else: fmt = "%s<%%s %%s/>\n" % (level * " ") - data = (element.tag, " ".join(["%s='%s'" % keyval for keyval in element.attrib.iteritems()])) + data = (element.tag, " ".join(["%s='%s'" % keyval for keyval in list(element.attrib.items())])) return fmt % data @@ -157,14 +158,14 @@ if __name__ == '__main__': cfpath = sys.argv[sys.argv.index('-C') + 1] else: cfpath = '/etc/bcfg2.conf' - c = ConfigParser() + c = ConfigParser.ConfigParser() c.read([cfpath]) configpath = "%s/etc/report-configuration.xml" % c.get('server', 'repository') statpath = "%s/etc/statistics.xml" % c.get('server', 'repository') clientsdatapath = "%s/Metadata/clients.xml" % c.get('server', 'repository') try: prefix = c.get('server', 'prefix') - except (NoSectionError, NoOptionError): + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): prefix = '/usr' transformpath = "/%s/share/bcfg2/xsl-transforms/" % (prefix) @@ -172,13 +173,14 @@ if __name__ == '__main__': try: opts, args = getopt.getopt(sys.argv[1:], "C:hAc:Ns:", ["help", "all", "config=","no-ping", "stats="]) - except getopt.GetoptError, mesg: + except getopt.GetoptError: + mesg = sys.exc_info()[1] # Print help information and exit: - print "%s\nUsage:\nbcfg2-build-reports [-h][-A (include ALL clients)] [-c <configuration-file>] [-s <statistics-file>][-N (do not ping clients)]" % (mesg) - raise SystemExit, 2 + print("%s\nUsage:\nbcfg2-build-reports [-h][-A (include ALL clients)] [-c <configuration-file>] [-s <statistics-file>][-N (do not ping clients)]" % (mesg)) + raise SystemExit(2) for o, a in opts: if o in ("-h", "--help"): - print "Usage:\nbcfg2-build-reports [-h] [-c <configuration-file>] [-s <statistics-file>]" + print("Usage:\nbcfg2-build-reports [-h] [-c <configuration-file>] [-s <statistics-file>]") raise SystemExit if o in ("-A", "--all"): all=True @@ -205,17 +207,17 @@ if __name__ == '__main__': statsdata = XML(open(statpath).read()) except (IOError, XMLSyntaxError): print("bcfg2-build-reports: Failed to parse %s"%(statpath)) - raise SystemExit, 1 + raise SystemExit(1) try: configdata = XML(open(configpath).read()) except (IOError, XMLSyntaxError): print("bcfg2-build-reports: Failed to parse %s"%(configpath)) - raise SystemExit, 1 + raise SystemExit(1) try: clientsdata = XML(open(clientsdatapath).read()) except (IOError, XMLSyntaxError): print("bcfg2-build-reports: Failed to parse %s"%(clientsdatapath)) - raise SystemExit, 1 + raise SystemExit(1) # Merge data from three sources. nodereport = Element("Report", attrib={"time" : asctime()}) @@ -229,7 +231,7 @@ if __name__ == '__main__': for statel in nod.findall("Statistics"): nodel.append(statel) nodereport.append(nodel) - + if all: for nod in statsdata.findall("Node"): for client in clientsdata.findall("Client"): @@ -242,8 +244,8 @@ if __name__ == '__main__': for statel in nod.findall("Statistics"): nodel.append(statel) nodereport.append(nodel) - - + + for reprt in configdata.findall('Report'): nodereport.set("name", reprt.get("name", default="BCFG Report")) @@ -254,7 +256,7 @@ if __name__ == '__main__': for deliv in reprt.findall('Delivery'): # Is a deepcopy of procnodereport necessary? - + delivtype = deliv.get('type', default='nodes-digest') deliverymechanism = deliv.get('mechanism', default='www') @@ -269,14 +271,14 @@ if __name__ == '__main__': except: print("bcfg2-build-reports: Invalid report type or delivery mechanism.\n Can't find: "\ + transformpath + transform) - raise SystemExit, 1 + raise SystemExit(1) try: # Try to parse stylesheet. stylesheet = XSLT(parse(transformpath + transform)) except: print("bcfg2-build-reports: invalid XSLT transform file.") - raise SystemExit, 1 - + raise SystemExit(1) + if deliverymechanism == 'mail': if delivtype == 'nodes-individual': reportdata = copy.deepcopy(procnodereport) @@ -285,7 +287,7 @@ if __name__ == '__main__': reportdata.append(noden) result = stylesheet.apply(ElementTree(reportdata)) outputstring = stylesheet.tostring(result) - + if not outputstring == None: toastring = '' for desti in deliv.findall("Destination"): @@ -295,13 +297,13 @@ if __name__ == '__main__': outputstring = "To: %s\nFrom: root@%s\n%s"% \ (toastring, socket.getfqdn(), outputstring) mail(outputstring, c) #call function to send - + else: reportdata = copy.deepcopy(procnodereport) result = stylesheet.apply(ElementTree(reportdata)) outputstring = stylesheet.tostring(result) - + if not outputstring == None: toastring = '' for desti in deliv.findall("Destination"): diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index a6d236bc8..161fee441 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -27,6 +27,40 @@ import Bcfg2.Server.Plugins.Metadata import Bcfg2.Server.Plugin logger = logging.getLogger('bcfg2-info') +USAGE = """Commands: +build <hostname> <filename> - Build config for hostname, writing to filename +builddir <hostname> <dirname> - Build config for hostname, writing separate files to dirname +buildall <directory> - Build configs for all clients in directory +buildfile <filename> <hostname> - Build config file for hostname (not written to disk) +bundles - Print out group/bundle information +clients - Print out client/profile information +config - Print out the configuration of the Bcfg2 server +debug - Shell out to native python interpreter +event_debug - Display filesystem events as they are processed +generators - List current versions of generators +groups - List groups +help - Print this list of available commands +mappings <type*> <name*> - Print generator mappings for optional type and name +profile <command> <args> - Profile a single bcfg2-info command +quit - Exit the bcfg2-info command line +showentries <hostname> <type> - Show abstract configuration entries for a given host +showclient <client1> <client2> - Show metadata for given hosts +update - Process pending file events +version - Print version of this tool""" + +BUILDDIR_USAGE = """Usage: builddir [-f] <hostname> <output dir> + +Generates a config for client <hostname> and writes the +individual configuration files out separately in a tree +under <output dir>. The <output dir> directory must be +rooted under /tmp unless the -f argument is provided, in +which case it can be located anywhere. + +NOTE: Currently only handles file entries and writes +all content with the default owner and permissions. These +could be much more permissive than would be created by the +Bcfg2 client itself.""" + class mockLog(object): def error(self, *args, **kwargs): @@ -75,7 +109,8 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): encoding) if event_debug: self.fam.debug = True - except Bcfg2.Server.Core.CoreInitError, msg: + except Bcfg2.Server.Core.CoreInitError: + msg = sys.exc_info()[1] print("Core load failed because %s" % msg) raise SystemExit(1) self.prompt = '> ' @@ -89,7 +124,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): try: self.cmdloop('Welcome to bcfg2-info\n' 'Type "help" for more information') - except SystemExit, val: + except SystemExit: raise except Bcfg2.Server.Plugin.PluginExecutionError: continue @@ -106,7 +141,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): try: opts, _ = getopt.getopt(args.split(), 'nf:') except: - print "Usage: debug [-n] [-f <command list>]" + print("Usage: debug [-n] [-f <command list>]") return self.cont = False scriptmode = False @@ -136,7 +171,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): Exit program. Usage: [quit|exit] """ - for plugin in self.plugins.values(): + for plugin in list(self.plugins.values()): plugin.shutdown() os._exit(0) @@ -145,27 +180,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): def do_help(self, _): """Print out usage info.""" - print 'Commands:' - print 'build <hostname> <filename> - Build config for hostname, writing to filename' - print 'builddir <hostname> <dirname> - Build config for hostname, writing separate files to dirname' - print 'buildall <directory> - Build configs for all clients in directory' - print 'buildfile <filename> <hostname> - Build config file for hostname (not written to disk)' - print 'bundles - Print out group/bundle information' - print 'clients - Print out client/profile information' - print 'config - Print out the configuration of the Bcfg2 server' - print 'debug - Shell out to native python interpreter' - print 'event_debug - Display filesystem events as they are processed' - print 'generators - List current versions of generators' - print 'groups - List groups' - print 'help - Print this list of available commands' - print 'mappings <type*> <name*> - Print generator mappings for optional type and name' - print 'profile <command> <args> - Profile a single bcfg2-info command' - print 'quit - Exit the bcfg2-info command line' - print 'showentries <hostname> <type> - Show abstract configuration entries for a given host' - print 'showclient <client1> <client2> - Show metadata for given hosts' - print 'update - Process pending file events' - print 'version - Print version of this tool' - + print(USAGE) def do_update(self, _): """Process pending filesystem events.""" @@ -198,18 +213,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): def help_builddir(self): """Display help for builddir command.""" - print('Usage: builddir [-f] <hostname> <output dir>') - print('') - print('Generates a config for client <hostname> and writes the') - print('individual configuration files out separately in a tree') - print('under <output dir>. The <output dir> directory must be') - print('rooted under /tmp unless the -f argument is provided, in') - print('which case it can be located anywhere.') - print('') - print('NOTE: Currently only handles file entries and writes') - print('all content with the default owner and permissions. These') - print('could be much more permissive than would be created by the') - print('Bcfg2 client itself.') + print(BUILDDIR_USAGE) def do_builddir(self, args): """Build client configuration as separate files within a dir.""" @@ -238,7 +242,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): p = Bcfg2.Client.Tools.POSIX.POSIX(log, setup, client_config) states = dict() p.Inventory(states) - p.Install(states.keys(), states) + p.Install(list(states.keys()), states) else: print('Error: Incorrect number of parameters.') self.help_builddir() @@ -262,7 +266,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): try: metadata = self.build_metadata(client) self.Bind(entry, metadata) - print(lxml.etree.tostring(entry, encoding="UTF-8", + print(lxml.etree.tostring(entry, encoding="UTF-8", xml_declaration=True)) except: print("Failed to build entry %s for host %s" % (fname, client)) @@ -371,22 +375,22 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): except: print("Client %s not defined" % client) continue - print "Hostname:\t", client_meta.hostname - print "Profile:\t", client_meta.profile - print "Groups:\t\t", list(client_meta.groups)[0] + print("Hostname:\t", client_meta.hostname) + print("Profile:\t", client_meta.profile) + print("Groups:\t\t", list(client_meta.groups)[0]) for grp in list(client_meta.groups)[1:]: - print '\t\t%s' % grp + print('\t\t%s' % grp) if client_meta.bundles: - print "Bundles:\t", list(client_meta.bundles)[0] + print("Bundles:\t", list(client_meta.bundles)[0]) for bnd in list(client_meta.bundles)[1:]: - print '\t\t%s' % bnd + print('\t\t%s' % bnd) if client_meta.connectors: - print "Connector data" - print "=" * 80 + print("Connector data") + print("=" * 80) for conn in client_meta.connectors: if getattr(client_meta, conn): - print "%s:\t" % (conn), getattr(client_meta, conn) - print "=" * 80 + print("%s:\t" % (conn), getattr(client_meta, conn)) + print("=" * 80) def do_mappings(self, args): """Print out mapping info.""" @@ -402,11 +406,11 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): interested = [(etype, [args.split()[1]]) for etype in etypes] else: - interested = [(etype, generator.Entries[etype]) - for etype in etypes + interested = [(etype, generator.Entries[etype]) + for etype in etypes if etype in generator.Entries] for etype, names in interested: - for name in [name for name in names if name in + for name in [name for name in names if name in generator.Entries.get(etype, {})]: data.append((generator.name, etype, name)) printTabular(data) diff --git a/src/sbin/bcfg2-lint b/src/sbin/bcfg2-lint index e6a530408..18632e316 100755 --- a/src/sbin/bcfg2-lint +++ b/src/sbin/bcfg2-lint @@ -6,11 +6,12 @@ __revision__ = '$Revision$' import sys import inspect import logging -import ConfigParser import Bcfg2.Logger import Bcfg2.Options import Bcfg2.Server.Core import Bcfg2.Server.Lint +# Compatibility imports +from Bcfg2.Bcfg2Py3k import ConfigParser logger = logging.getLogger('bcfg2-lint') @@ -29,7 +30,7 @@ class Parser(ConfigParser.ConfigParser): def run_serverless_plugins(plugins, config=None, setup=None): logger.debug("Running serverless plugins") errors = (0, 0) - for plugin_name, plugin in plugins.items(): + for plugin_name, plugin in list(plugins.items()): plugin_errors = run_plugin(plugin, plugin_name, setup=setup, config=config, files=files) errors = [errors[n] + plugin_errors[n] @@ -40,7 +41,7 @@ def run_server_plugins(plugins, config=None, setup=None): core = load_server(setup) logger.debug("Running server plugins") errors = (0, 0) - for plugin_name, plugin in plugins.items(): + for plugin_name, plugin in list(plugins.items()): plugin_errors = run_plugin(plugin, plugin_name, args=[core], setup=setup, config=config, files=files) errors = [errors[n] + plugin_errors[n] @@ -140,7 +141,8 @@ if __name__ == '__main__': except ImportError: try: mod = __import__(plugin_name) - except Exception, err: + except Exception: + err = sys.exc_info()[1] logger.error("Failed to load plugin %s: %s" % (plugin_name, err)) raise SystemExit(1) @@ -160,8 +162,8 @@ if __name__ == '__main__': errors = [errors[n] + perrors[n] for n in range(0, len(errors))] if errors[0] or errors[1] or setup['verbose']: - print "%d errors" % errors[0] - print "%d warnings" % errors[1] + print("%d errors" % errors[0]) + print("%d warnings" % errors[1]) if errors[0]: raise SystemExit(2) diff --git a/src/sbin/bcfg2-ping-sweep b/src/sbin/bcfg2-ping-sweep index 718ad69d0..70f718690 100755 --- a/src/sbin/bcfg2-ping-sweep +++ b/src/sbin/bcfg2-ping-sweep @@ -33,7 +33,7 @@ if __name__ == '__main__': osname = uname()[0] while hostlist or pids: - if hostlist and len(pids.keys()) < 15: + if hostlist and len(list(pids.keys())) < 15: host = hostlist.pop() pid = fork() if pid == 0: diff --git a/src/sbin/bcfg2-reports b/src/sbin/bcfg2-reports index 559e9fb43..20288fc5e 100755 --- a/src/sbin/bcfg2-reports +++ b/src/sbin/bcfg2-reports @@ -93,13 +93,13 @@ def print_fields(fields, cli, max_name, entrydict): if len(entrydict) > 0: display += " " display += str(entrydict[cli]) - print display + print(display) def print_entry(item, max_name): fmt = ("%%-%ds " % (max_name)) fdata = item.entry.kind + ":" + item.entry.name display = fmt % (fdata) - print display + print(display) fields = "" sort = "" @@ -137,14 +137,14 @@ if expire != "": if expire == c_inst.name: if c_inst.expiration == None: c_inst.expiration = datetime.datetime.now() - print "Host expired." + print("Host expired.") else: c_inst.expiration = None - print "Host un-expired." + print("Host un-expired.") c_inst.save() elif '-h' in args: - print """Usage: bcfg2-reports [option] ... + print("""Usage: bcfg2-reports [option] ... Options and arguments (and corresponding environment variables): -a : shows all hosts, including expired hosts @@ -170,13 +170,13 @@ Options and arguments (and corresponding environment variables): (name,time,state) --sort=ARG1,ARG2,... : sorts output on ARG1,ARG2,... (name,time,state) --stale : shows hosts which haven't run in the last 24 hours -""" +""") elif singlehost != "": for c_inst in c_list: if singlehost == c_inst.name: baditems = c_inst.current_interaction.bad() if len(baditems) > 0 and ('-b' in args or '-s' in args): - print "Bad Entries:" + print("Bad Entries:") max_name = -1 for item in baditems: if len(item.entry.name) > max_name: @@ -185,7 +185,7 @@ elif singlehost != "": print_entry(item, max_name) extraitems = c_inst.current_interaction.extra() if len(extraitems) > 0 and ('-e' in args or '-s' in args): - print "Extra Entries:" + print("Extra Entries:") max_name = -1 for item in extraitems: if len(item.entry.name) > max_name: diff --git a/src/sbin/bcfg2-server b/src/sbin/bcfg2-server index cf44f1699..f4bd5e5b7 100755 --- a/src/sbin/bcfg2-server +++ b/src/sbin/bcfg2-server @@ -69,7 +69,8 @@ if __name__ == '__main__': certfile=setup['cert'], ca=setup['ca'], ) - except CoreInitError, msg: + except CoreInitError: + msg = sys.exc_info()[1] logger.error(msg) logger.error("exiting") sys.exit(1) |