From 1d17b980a15a2fd138ad746d51e148befa26faa0 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Sun, 6 Mar 2011 12:04:33 -0600 Subject: Better handling of backup files in paranoid mode (Patch from mkd ticket #995) 1. Client removes only one excess backup copy at every configfile change, even if there are more backup copies eligible for deletion. Moreover, lowering the max_copies parameter could cause client to never remove any excess files from there. 2. Space character in backup file names is mildly annoying - datetime.isoformat() will put a 'T' there instead. 3. More robust handling of 'paranoid' attribute values from info.xml (paranoid='True' should also be allowed - currently only paranoid='true' works as expected). A simple patch (attached) addresses all these issues. /mkd Signed-off-by: Sol Jerome --- src/lib/Client/Tools/POSIX.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/POSIX.py b/src/lib/Client/Tools/POSIX.py index c883fc17a..bcb9f48b3 100644 --- a/src/lib/Client/Tools/POSIX.py +++ b/src/lib/Client/Tools/POSIX.py @@ -542,7 +542,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): return False # If we get here, then the parent directory should exist - if (entry.get("paranoid", False) == 'true') and \ + if (entry.get("paranoid", False) in ['true', 'True']) and \ self.setup.get("paranoid", False) and not \ (entry.get('current_exists', 'true') == 'false'): bkupnam = entry.get('name').replace('/', '_') @@ -550,7 +550,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): bkuplist = [f for f in os.listdir(self.ppath) if f.startswith(bkupnam)] bkuplist.sort() - if len(bkuplist) == int(self.max_copies): + while len(bkuplist) >= int(self.max_copies): # remove the oldest backup available oldest = bkuplist.pop(0) self.logger.info("Removing %s" % oldest) @@ -563,7 +563,8 @@ class POSIX(Bcfg2.Client.Tools.Tool): try: # backup existing file shutil.copy(entry.get('name'), - "%s/%s_%s" % (self.ppath, bkupnam, datetime.now())) + "%s/%s_%s" % (self.ppath, bkupnam, + datetime.isoformat(datetime.now()))) self.logger.info("Backup of %s saved to %s" % (entry.get('name'), self.ppath)) except IOError, e: -- cgit v1.2.3-1-g7c22 From 7c048802e67f5a35890758b64519d7f61532dbe6 Mon Sep 17 00:00:00 2001 From: Jack Neely Date: Thu, 10 Feb 2011 18:18:16 -0500 Subject: Add error checking to make sure gpg-pubkeys have all needed information (cherry picked from commit 81fce09fb9671c652703c37a5f9b48d020a34307) --- src/lib/Client/Tools/YUMng.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/YUMng.py b/src/lib/Client/Tools/YUMng.py index 44d56ff9f..8db1683e4 100644 --- a/src/lib/Client/Tools/YUMng.py +++ b/src/lib/Client/Tools/YUMng.py @@ -463,6 +463,14 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): self.logger.debug(" Not checking version for virtual package") _POs = [po for po in POs] # Make a copy elif entry.get('name') == 'gpg-pubkey': + if 'version' not in nevra: + m = "Skipping verify: gpg-pubkey without an RPM version." + self.logger.warning(m) + continue + if 'release' not in nevra: + m = "Skipping verify: gpg-pubkey without an RPM release." + self.logger.warning(m) + continue _POs = [p for p in POs if p.version == nevra['version'] \ and p.release == nevra['release']] else: -- cgit v1.2.3-1-g7c22 From 9fde0bc9a7d45c3215f6d4125f6bbbe257f05f15 Mon Sep 17 00:00:00 2001 From: Joe Digilio Date: Fri, 25 Mar 2011 11:56:50 -0500 Subject: add ability to ignore a debian Service --- src/lib/Client/Tools/DebInit.py | 4 ++++ src/lib/Client/Tools/Upstart.py | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/DebInit.py b/src/lib/Client/Tools/DebInit.py index 119036b32..fc67a73e4 100644 --- a/src/lib/Client/Tools/DebInit.py +++ b/src/lib/Client/Tools/DebInit.py @@ -21,6 +21,10 @@ class DebInit(Bcfg2.Client.Tools.SvcTool): # implement entry (Verify|Install) ops def VerifyService(self, entry, _): """Verify Service status for entry.""" + + if entry.get('status') == 'ignore': + return True + rawfiles = glob.glob("/etc/rc*.d/[SK]*%s" % (entry.get('name'))) files = [] diff --git a/src/lib/Client/Tools/Upstart.py b/src/lib/Client/Tools/Upstart.py index b75b0927e..7a94a07f3 100644 --- a/src/lib/Client/Tools/Upstart.py +++ b/src/lib/Client/Tools/Upstart.py @@ -29,6 +29,10 @@ class Upstart(Bcfg2.Client.Tools.SvcTool): /etc/init/servicename.conf. All we need to do is make sure the service is running when it should be. """ + + if entry.get('status') == 'ignore': + return True + if entry.get('parameters'): params = entry.get('parameters') else: -- cgit v1.2.3-1-g7c22 From f1cf457edb2a9552adf82d72541af69487f897f4 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Wed, 6 Apr 2011 16:30:33 -0500 Subject: APT: Catch apt-python initialization failures (#1001) This still needs to be fixed in apt-python, but we can at least give the user a smarter failure and disable the client tool properly here. Signed-off-by: Sol Jerome --- src/lib/Client/Tools/APT.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/APT.py b/src/lib/Client/Tools/APT.py index fe1ef6fdd..a838f5e27 100644 --- a/src/lib/Client/Tools/APT.py +++ b/src/lib/Client/Tools/APT.py @@ -69,7 +69,11 @@ class APT(Bcfg2.Client.Tools.Tool): if self.setup['kevlar'] and not self.setup['dryrun']: self.cmd.run("%s --force-confold --configure --pending" % DPKG) self.cmd.run("%s clean" % APTGET) - self.pkg_cache = apt.cache.Cache() + try: + self.pkg_cache = apt.cache.Cache() + except SystemError, e: + self.logger.info("Failed to initialize APT cache: %s" % e) + raise Bcfg2.Client.Tools.toolInstantiationError self.pkg_cache.update() self.pkg_cache = apt.cache.Cache() -- cgit v1.2.3-1-g7c22 From 1d2b0215f5957d4ec0d320984c93328a39d3b08c Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Thu, 7 Apr 2011 13:51:24 -0500 Subject: Client: PY3K + PEP8 fixes Signed-off-by: Sol Jerome --- src/lib/Client/Frame.py | 29 +++++++++++++++------ src/lib/Client/Tools/Action.py | 7 +++++- src/lib/Client/Tools/Pacman.py | 2 +- src/lib/Client/Tools/YUM24.py | 54 +++++++++++++++++++++++----------------- src/lib/Client/Tools/YUMng.py | 27 ++++++++++---------- src/lib/Client/Tools/__init__.py | 19 ++++++++++---- 6 files changed, 88 insertions(+), 50 deletions(-) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Frame.py b/src/lib/Client/Frame.py index 545d4b584..f87610dcb 100644 --- a/src/lib/Client/Frame.py +++ b/src/lib/Client/Frame.py @@ -8,6 +8,7 @@ import logging import time import Bcfg2.Client.Tools + def cmpent(ent1, ent2): """Sort entries.""" if ent1.tag != ent2.tag: @@ -15,6 +16,7 @@ def cmpent(ent1, ent2): else: return cmp(ent1.get('name'), ent2.get('name')) + def promptFilter(prompt, entries): """Filter a supplied list based on user input.""" ret = [] @@ -25,7 +27,12 @@ def promptFilter(prompt, entries): else: iprompt = prompt % (entry.tag, entry.get('name')) try: - if raw_input(iprompt) in ['y', 'Y']: + # py3k compatibility + try: + ans = raw_input(iprompt) + except NameError: + ans = input(iprompt) + if ans in ['y', 'Y']: ret.append(entry) except EOFError: # python 2.4.3 on CentOS doesn't like ^C for some reason @@ -35,6 +42,7 @@ def promptFilter(prompt, entries): continue return ret + def matches_entry(entryspec, entry): # both are (tag, name) if entryspec == entry: @@ -52,11 +60,16 @@ def matches_entry(entryspec, entry): return False return True + def matches_white_list(entry, whitelist): - return True in [matches_entry(we, (entry.tag, entry.get('name'))) for we in whitelist] + return True in [matches_entry(we, (entry.tag, entry.get('name'))) + for we in whitelist] + def passes_black_list(entry, blacklist): - return True not in [matches_entry(be, (entry.tag, entry.get('name'))) for be in blacklist] + return True not in [matches_entry(be, (entry.tag, entry.get('name'))) + for be in blacklist] + class Frame: """Frame is the container for all Tool objects and state information.""" @@ -134,8 +147,10 @@ class Frame: self.logger.error(["%s:%s:%s" % (entry.tag, entry.get('type'), \ entry.get('name')) for entry in problems]) self.logger.error("") - entries = [(entry.tag, entry.get('name')) for struct in config for entry in struct] - pkgs = [(entry.get('name'), entry.get('origin')) for struct in config for entry in struct if entry.tag == 'Package'] + entries = [(entry.tag, entry.get('name')) + for struct in config for entry in struct] + pkgs = [(entry.get('name'), entry.get('origin')) + for struct in config for entry in struct if entry.tag == 'Package'] multi = [] for entry in entries[:]: if entries.count(entry) > 1: @@ -151,7 +166,6 @@ class Frame: self.logger.debug("The following packages are prereqs added by Packages:") self.logger.debug([pkg[0] for pkg in pkgs if pkg[1] == 'Packages']) - def __getattr__(self, name): if name in ['extra', 'handled', 'modified', '__important__']: ret = [] @@ -268,7 +282,8 @@ class Frame: if b_to_remv: self.logger.info("Not installing entries from Bundle %s" % \ (bundle.get('name'))) - self.logger.info(["%s:%s" % (e.tag, e.get('name')) for e in b_to_remv]) + self.logger.info(["%s:%s" % (e.tag, e.get('name')) + for e in b_to_remv]) [self.whitelist.remove(ent) for ent in b_to_remv] if self.setup['interactive']: diff --git a/src/lib/Client/Tools/Action.py b/src/lib/Client/Tools/Action.py index 452788f94..bc57a0e27 100644 --- a/src/lib/Client/Tools/Action.py +++ b/src/lib/Client/Tools/Action.py @@ -31,7 +31,12 @@ class Action(Bcfg2.Client.Tools.Tool): if self.setup['interactive']: prompt = ('Run Action %s, %s: (y/N): ' % (entry.get('name'), entry.get('command'))) - if raw_input(prompt) not in ['y', 'Y']: + # py3k compatibility + try: + ans = raw_input(prompt) + except NameError: + ans = input(prompt) + if ans not in ['y', 'Y']: return False if self.setup['servicemode'] == 'build': if entry.get('build', 'true') == 'false': diff --git a/src/lib/Client/Tools/Pacman.py b/src/lib/Client/Tools/Pacman.py index be3fb0c94..082897934 100644 --- a/src/lib/Client/Tools/Pacman.py +++ b/src/lib/Client/Tools/Pacman.py @@ -73,7 +73,7 @@ class Pacman(Bcfg2.Client.Tools.PkgTool): for pkg in packages: pkgline += " " + pkg.get('name') - print "packages : " + pkgline + self.logger.info("packages : " + pkgline) try: self.logger.debug("Running : %s -S %s" % (self.pkgtool, pkgline)) diff --git a/src/lib/Client/Tools/YUM24.py b/src/lib/Client/Tools/YUM24.py index efe92a059..04d9f5c07 100644 --- a/src/lib/Client/Tools/YUM24.py +++ b/src/lib/Client/Tools/YUM24.py @@ -30,6 +30,7 @@ except: if not hasattr(Bcfg2.Client.Tools.RPMng, 'RPMng'): raise ImportError + def build_yname(pkgname, inst): """Build yum appropriate package name.""" ypname = pkgname @@ -45,6 +46,7 @@ def build_yname(pkgname, inst): ypname += ".%s" % (inst.get('arch')) return ypname + class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): """Support for Yum packages.""" pkgtype = 'yum' @@ -59,7 +61,8 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): __ireq__ = {'Package': ['name']} #__ireq__ = {'Package': ['name', 'version']} - __new_req__ = {'Package': ['name'], 'Instance': ['version', 'release', 'arch']} + __new_req__ = {'Package': ['name'], + 'Instance': ['version', 'release', 'arch']} __new_ireq__ = {'Package': ['name'], \ 'Instance': []} #__new_ireq__ = {'Package': ['name', 'uri'], \ @@ -68,8 +71,10 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): __gpg_req__ = {'Package': ['name', 'version']} __gpg_ireq__ = {'Package': ['name', 'version']} - __new_gpg_req__ = {'Package': ['name'], 'Instance': ['version', 'release']} - __new_gpg_ireq__ = {'Package': ['name'], 'Instance': ['version', 'release']} + __new_gpg_req__ = {'Package': ['name'], + 'Instance': ['version', 'release']} + __new_gpg_ireq__ = {'Package': ['name'], + 'Instance': ['version', 'release']} conflicts = ['YUMng', 'RPMng'] @@ -101,10 +106,14 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): data = {pkg.arch: (pkg.epoch, pkg.version, pkg.release)} else: pname = pkg[0] - if pkg[1] is None: a = 'noarch' - else: a = pkg[1] - if pkg[2] is None: e = '0' - else: e = pkg[2] + if pkg[1] is None: + a = 'noarch' + else: + a = pkg[1] + if pkg[2] is None: + e = '0' + else: + e = pkg[2] data = {a: (e, pkg[3], pkg[4])} if pname in dest: dest[pname].update(data) @@ -137,24 +146,24 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): if entry.get('type', False) == 'yum': # Check for virtual provides or packages. If we don't have # this package use Yum to resolve it to a real package name - knownPkgs = self.yum_installed.keys() + self.yum_avail.keys() + knownPkgs = list(self.yum_installed.keys()) + list(self.yum_avail.keys()) if entry.get('name') not in knownPkgs: # If the package name matches something installed # or available the that's the correct package. try: - pkgDict = dict( [ (i.name, i) for i in \ - self.yb.returnPackagesByDep(entry.get('name')) ] ) + pkgDict = dict([(i.name, i) for i in \ + self.yb.returnPackagesByDep(entry.get('name'))]) except yum.Errors.YumBaseError, e: self.logger.error('Yum Error Depsolving for %s: %s' % \ (entry.get('name'), str(e))) pkgDict = {} if len(pkgDict) > 1: - # What do we do with multiple packages? + # What do we do with multiple packages? s = "YUMng: returnPackagesByDep(%s) returned many packages" self.logger.info(s % entry.get('name')) s = "YUMng: matching packages: %s" - self.logger.info(s % str(pkgDict.keys())) + self.logger.info(s % str(list(pkgDict.keys()))) pkgs = set(pkgDict.keys()) & set(self.yum_installed.keys()) if len(pkgs) > 0: # Virtual packages matches an installed real package @@ -166,7 +175,7 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): # and Yum should Do The Right Thing on package install pkg = None elif len(pkgDict) == 1: - pkg = pkgDict.values()[0] + pkg = list(pkgDict.values())[0] else: # len(pkgDict) == 0 s = "YUMng: returnPackagesByDep(%s) returned no results" self.logger.info(s % entry.get('name')) @@ -252,16 +261,16 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): self.logger.error("GPG key has no simplefile attribute") continue key_arg = os.path.join(self.instance_status[inst].get('pkg').get('uri'), \ - inst.get('simplefile')) + inst.get('simplefile')) cmdrc, output = self.cmd.run("rpm --import %s" % key_arg) if cmdrc != 0: self.logger.debug("Unable to install %s-%s" % \ - (self.instance_status[inst].get('pkg').get('name'), \ - self.str_evra(inst))) + (self.instance_status[inst].get('pkg').get('name'), \ + self.str_evra(inst))) else: self.logger.debug("Installed %s-%s-%s" % \ - (self.instance_status[inst].get('pkg').get('name'), \ - inst.get('version'), inst.get('release'))) + (self.instance_status[inst].get('pkg').get('name'), \ + inst.get('version'), inst.get('release'))) self.RefreshPackages() self.gpg_keyids = self.getinstalledgpg() pkg = self.instance_status[gpg_keys[0]].get('pkg') @@ -374,9 +383,9 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): pkg_arg = pkg_arg + '.' + inst.get('arch') erase_args.append(pkg_arg) else: - pkgspec = { 'name':pkg.get('name'), - 'version':inst.get('version'), - 'release':inst.get('release')} + pkgspec = {'name': pkg.get('name'), + 'version': inst.get('version'), + 'release': inst.get('release')} self.logger.info("WARNING: gpg-pubkey package not in configuration %s %s"\ % (pkgspec.get('name'), self.str_evra(pkgspec))) self.logger.info(" This package will be deleted in a future version of the RPMng driver.") @@ -395,7 +404,7 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): for inst in pkg: if pkg.get('name') != 'gpg-pubkey': pkg_arg = pkg.get('name') + '-' - if inst.attrib.has_key('epoch'): + if 'epoch' in inst.attrib: pkg_arg = pkg_arg + inst.get('epoch') + ':' pkg_arg = pkg_arg + inst.get('version') + '-' + inst.get('release') if 'arch' in inst.attrib: @@ -416,6 +425,5 @@ class YUM24(Bcfg2.Client.Tools.RPMng.RPMng): if pkg_modified == True: self.modified.append(pkg) - self.RefreshPackages() self.extra = self.FindExtraPackages() diff --git a/src/lib/Client/Tools/YUMng.py b/src/lib/Client/Tools/YUMng.py index 8db1683e4..c9e7aa15e 100644 --- a/src/lib/Client/Tools/YUMng.py +++ b/src/lib/Client/Tools/YUMng.py @@ -300,7 +300,7 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): # Okay deal with a buggy yum multilib and verify packages = self.yb.rpmdb.searchNevra(name=po.name, epoch=po.epoch, - ver=po.version, rel=po.release) # find all arches of pkg + ver=po.version, rel=po.release) # find all arches of pkg if len(packages) == 1: return results # No mathcing multilib packages @@ -319,13 +319,13 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): v = verify(p) self.verifyCache[k] = v - for fn, probs in v.items(): + for fn, probs in list(v.items()): # file problems must exist in ALL multilib packages to be real if fn in files: common[fn] = common.get(fn, 0) + 1 flag = len(packages) - 1 - for fn, i in common.items(): + for fn, i in list(common.items()): if i == flag: # this fn had verify problems in all but one of the multilib # packages. That means its correct in the package that's @@ -512,7 +512,7 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): ignores = [ig.get('name') for ig in entry.findall('Ignore')] + \ [ig.get('name') for ig in inst.findall('Ignore')] + \ self.ignores - for fn, probs in vResult.items(): + for fn, probs in list(vResult.items()): if fn in modlist: self.logger.debug(" %s in modlist, skipping" % fn) continue @@ -537,7 +537,7 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): "these files, revert the changes, or ignore " "false failures:") self.logger.debug(" Verify Problems:") - for fn, probs in stat['verify'].items(): + for fn, probs in list(stat['verify'].items()): self.logger.debug(" %s" % fn) for p in probs: self.logger.debug(" %s: %s" % p) @@ -577,7 +577,7 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): extra_entry = Bcfg2.Client.XML.Element('Package', name=name, type=self.pkgtype) instances = self._buildInstances(entry) - _POs = [p for p in POs] # Shallow copy + _POs = [p for p in POs] # Shallow copy # Algorythm is sensitive to duplicates, check for them checked = [] @@ -588,7 +588,7 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): flag = True if len(pkgs) > 0: if pkgs[0] in checked: - continue # We've already taken care of this Instance + continue # We've already taken care of this Instance else: checked.append(pkgs[0]) _POs.remove(pkgs[0]) @@ -609,16 +609,17 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): packages = [e.get('name') for e in self.getSupportedEntries()] extras = [] - for p in self.installed.keys(): + for p in list(self.installed.keys()): if p not in packages: entry = Bcfg2.Client.XML.Element('Package', name=p, type=self.pkgtype) for i in self.installed[p]: - inst = Bcfg2.Client.XML.SubElement(entry, 'Instance', \ - epoch = i['epoch'], - version = i['version'], - release = i['release'], - arch = i['arch']) + inst = Bcfg2.Client.XML.SubElement(entry, + 'Instance', + epoch=i['epoch'], + version=i['version'], + release=i['release'], + arch=i['arch']) extras.append(entry) diff --git a/src/lib/Client/Tools/__init__.py b/src/lib/Client/Tools/__init__.py index b5120db71..7d8d58957 100644 --- a/src/lib/Client/Tools/__init__.py +++ b/src/lib/Client/Tools/__init__.py @@ -57,7 +57,7 @@ class executor: runpipe = readonlypipe(command, bufsize=16384) output = [] - try:#macosx doesn't like this + try: # macosx doesn't like this runpipe.fromchild.flush() except IOError: pass @@ -185,7 +185,9 @@ class Tool: if 'failure' in entry.attrib: self.logger.error("Entry %s:%s reports bind failure: %s" % \ - (entry.tag, entry.get('name'), entry.get('failure'))) + (entry.tag, + entry.get('name'), + entry.get('failure'))) return False missing = [attr for attr in self.__req__[entry.tag] \ @@ -198,7 +200,8 @@ class Tool: try: self.gatherCurrentData(entry) except: - self.logger.error("Unexpected error in gatherCurrentData", exc_info=1) + self.logger.error("Unexpected error in gatherCurrentData", + exc_info=1) return False return True @@ -255,7 +258,8 @@ class PkgTool(Tool): self.logger.info("Trying single pass package install for pkgtype %s" % \ self.pkgtype) - data = [tuple([pkg.get(field) for field in self.pkgtool[1][1]]) for pkg in packages] + data = [tuple([pkg.get(field) for field in self.pkgtool[1][1]]) + for pkg in packages] pkgargs = " ".join([self.pkgtool[1][0] % datum for datum in data]) self.logger.debug("Installing packages: :%s:" % pkgargs) @@ -358,7 +362,12 @@ class SvcTool(Tool): else: if self.setup['interactive']: prompt = 'Restart service %s?: (y/N): ' % entry.get('name') - if raw_input(prompt) not in ['y', 'Y']: + # py3k compatibility + try: + ans = raw_input(prompt) + except NameError: + ans = input(prompt) + if ans not in ['y', 'Y']: continue rc = self.restart_service(entry) else: -- cgit v1.2.3-1-g7c22 From 545dda76d34a06ae25efa2eb3d0c8c0bd70127d0 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Tue, 12 Apr 2011 10:18:55 -0500 Subject: Tools: Skip Installation for mode='manual' services (#965) This allows for verification of specified services, but skips installation completely when mode is set to manual. This means that incorrect services will still show up in reports, but they won't be modified in an automated way. Signed-off-by: Sol Jerome --- src/lib/Client/Tools/Chkconfig.py | 5 +++++ src/lib/Client/Tools/DebInit.py | 5 +++++ src/lib/Client/Tools/RcUpdate.py | 5 +++++ src/lib/Client/Tools/SMF.py | 5 +++++ src/lib/Client/Tools/Upstart.py | 5 +++++ src/lib/Client/Tools/launchd.py | 5 +++++ 6 files changed, 30 insertions(+) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/Chkconfig.py b/src/lib/Client/Tools/Chkconfig.py index bf2a2c1e1..d1639732a 100644 --- a/src/lib/Client/Tools/Chkconfig.py +++ b/src/lib/Client/Tools/Chkconfig.py @@ -76,6 +76,11 @@ class Chkconfig(Bcfg2.Client.Tools.SvcTool): def InstallService(self, entry): """Install Service entry.""" + # don't take any actions for mode='manual' + if entry.get('mode', 'default') == 'manual': + self.logger.info("Service %s mode set to manual. Skipping " + "installation." % (entry.get('name'))) + return True rcmd = "/sbin/chkconfig %s %s" self.cmd.run("/sbin/chkconfig --add %s"%(entry.attrib['name'])) self.logger.info("Installing Service %s" % (entry.get('name'))) diff --git a/src/lib/Client/Tools/DebInit.py b/src/lib/Client/Tools/DebInit.py index fc67a73e4..254b55d98 100644 --- a/src/lib/Client/Tools/DebInit.py +++ b/src/lib/Client/Tools/DebInit.py @@ -75,6 +75,11 @@ class DebInit(Bcfg2.Client.Tools.SvcTool): def InstallService(self, entry): """Install Service for entry.""" + # don't take any actions for mode='manual' + if entry.get('mode', 'default') == 'manual': + self.logger.info("Service %s mode set to manual. Skipping " + "installation." % (entry.get('name'))) + return True self.logger.info("Installing Service %s" % (entry.get('name'))) try: os.stat('/etc/init.d/%s' % entry.get('name')) diff --git a/src/lib/Client/Tools/RcUpdate.py b/src/lib/Client/Tools/RcUpdate.py index 159172b78..0c99e8a98 100644 --- a/src/lib/Client/Tools/RcUpdate.py +++ b/src/lib/Client/Tools/RcUpdate.py @@ -57,6 +57,11 @@ class RcUpdate(Bcfg2.Client.Tools.SvcTool): In supervised mode we also take care it's (not) running. """ + # don't take any actions for mode='manual' + if entry.get('mode', 'default') == 'manual': + self.logger.info("Service %s mode set to manual. Skipping " + "installation." % (entry.get('name'))) + return True self.logger.info('Installing Service %s' % entry.get('name')) if entry.get('status') == 'on': # make sure it's running if in supervised mode diff --git a/src/lib/Client/Tools/SMF.py b/src/lib/Client/Tools/SMF.py index 96c7d9d28..0403ff62e 100644 --- a/src/lib/Client/Tools/SMF.py +++ b/src/lib/Client/Tools/SMF.py @@ -74,6 +74,11 @@ class SMF(Bcfg2.Client.Tools.SvcTool): def InstallService(self, entry): """Install SMF Service entry.""" + # don't take any actions for mode='manual' + if entry.get('mode', 'default') == 'manual': + self.logger.info("Service %s mode set to manual. Skipping " + "installation." % (entry.get('name'))) + return True self.logger.info("Installing Service %s" % (entry.get('name'))) if entry.get('status') == 'off': if entry.get("FMRI").startswith('lrc'): diff --git a/src/lib/Client/Tools/Upstart.py b/src/lib/Client/Tools/Upstart.py index 7a94a07f3..2fba6b797 100644 --- a/src/lib/Client/Tools/Upstart.py +++ b/src/lib/Client/Tools/Upstart.py @@ -70,6 +70,11 @@ class Upstart(Bcfg2.Client.Tools.SvcTool): def InstallService(self, entry): """Install Service for entry.""" + # don't take any actions for mode='manual' + if entry.get('mode', 'default') == 'manual': + self.logger.info("Service %s mode set to manual. Skipping " + "installation." % (entry.get('name'))) + return True if entry.get('status') == 'on': pstatus = self.cmd.run(self.get_svc_command(entry, 'start'))[0] elif entry.get('status') == 'off': diff --git a/src/lib/Client/Tools/launchd.py b/src/lib/Client/Tools/launchd.py index db6d94c1b..90569052d 100644 --- a/src/lib/Client/Tools/launchd.py +++ b/src/lib/Client/Tools/launchd.py @@ -82,6 +82,11 @@ class launchd(Bcfg2.Client.Tools.Tool): def InstallService(self, entry): """Enable or disable launchd item.""" + # don't take any actions for mode='manual' + if entry.get('mode', 'default') == 'manual': + self.logger.info("Service %s mode set to manual. Skipping " + "installation." % (entry.get('name'))) + return True name = entry.get('name') if entry.get('status') == 'on': self.logger.error("Installing service %s" % name) -- cgit v1.2.3-1-g7c22 From 41edd7fddc7cb53d0fe3880c7707eb0f58879e59 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Wed, 13 Apr 2011 09:24:40 -0500 Subject: VCS: Initial commit (#754) Preliminary support for version control checkouts onto the client. This client tool is still fairly picky and has some known problems (incorrect git index file, for one). All the abstraction libraries left quite a bit to be desired. Also, none were packaged in popular distributions. Signed-off-by: Sol Jerome --- src/lib/Client/Tools/VCS.py | 137 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/lib/Client/Tools/VCS.py (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/VCS.py b/src/lib/Client/Tools/VCS.py new file mode 100644 index 000000000..fa7748574 --- /dev/null +++ b/src/lib/Client/Tools/VCS.py @@ -0,0 +1,137 @@ +"""VCS support.""" + +# TODO: +# * git_write_index +# * add svn support +# * integrate properly with reports +missing = [] + +import os +import sys +# python-dulwich git imports +try: + import dulwich + import dulwich.index + from dulwich.errors import NotGitRepository +except: + missing.append('git') +# subversion import +try: + import pysvn +except: + missing.append('svn') + +import Bcfg2.Client.Tools + + +class VCS(Bcfg2.Client.Tools.Tool): + """VCS support.""" + name = 'VCS' + __handles__ = [('Path', 'vcs')] + __req__ = {'Path': ['name', + 'type', + 'vcstype', + 'sourceurl', + 'revision']} + + def __init__(self, logger, cfg, setup): + Bcfg2.Client.Tools.Tool.__init__(self, logger, cfg, setup) + self.cfg = cfg + + def git_write_index(self, entry): + """Write the git index""" + pass + + def Verifygit(self, entry, _): + """Verify git repositories""" + try: + repo = dulwich.repo.Repo(entry.get('name')) + except NotGitRepository: + self.logger.info("Repository %s does not exist" % + entry.get('name')) + return False + cur_rev = repo.head() + + if cur_rev != entry.get('revision'): + self.logger.info("At revision %s need to go to revision %s" % + (cur_rev, entry.get('revision'))) + return False + + return True + + def Installgit(self, entry): + """Checkout contents from a git repository""" + destname = entry.get('name') + destr = dulwich.repo.Repo.init(destname, mkdir=True) + cl, host_path = dulwich.client.get_transport_and_path(entry.get('sourceurl')) + remote_refs = cl.fetch(host_path, + destr, + determine_wants=destr.object_store.determine_wants_all, + progress=sys.stdout.write) + destr.refs['refs/heads/master'] = entry.get('revision') + dtree = destr[entry.get('revision')].tree + obj_store = destr.object_store + for fname, mode, sha in obj_store.iter_tree_contents(dtree): + fullpath = os.path.join(destname, fname) + try: + f = open(os.path.join(destname, fname), 'wb') + except IOError: + dir = os.path.split(fullpath)[0] + os.makedirs(dir) + f = open(os.path.join(destname, fname), 'wb') + f.write(destr[sha].data) + f.close() + os.chmod(os.path.join(destname, fname), mode) + return True + # FIXME: figure out how to write the git index properly + #iname = "%s/.git/index" % entry.get('name') + #f = open(iname, 'w+') + #entries = obj_store[sha].iteritems() + #try: + # dulwich.index.write_index(f, entries) + #finally: + # f.close() + + def Verifysvn(self, entry, _): + """Verify svn repositories""" + client = pysvn.Client() + try: + cur_rev = str(client.info(entry.get('name')).revision.number) + except: + self.logger.info("Repository %s does not exist" % entry.get('name')) + return False + + if cur_rev != entry.get('revision'): + self.logger.info("At revision %s need to go to revision %s" % + (cur_rev, entry.get('revision'))) + return False + + return True + + def Installsvn(self, entry): + """Checkout contents from a svn repository""" + try: + client = pysvn.Client.update(entry.get('name'), recurse=True) + except: + self.logger.error("Failed to update repository", exc_info=1) + return False + + return True + + def VerifyPath(self, entry, _): + vcs = entry.get('vcstype') + if vcs in missing: + self.logger.error("Missing %s python libraries. Cannot verify" % + vcs) + return False + ret = getattr(self, 'Verify%s' % vcs) + return ret(entry, _) + + def InstallPath(self, entry): + vcs = entry.get('vcstype') + if vcs in missing: + self.logger.error("Missing %s python libraries. " + "Unable to install" % vcs) + return False + ret = getattr(self, 'Install%s' % vcs) + return ret(entry) -- cgit v1.2.3-1-g7c22 From 20974e1311168b75e621cad14894fe7b217b61a2 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Tue, 19 Apr 2011 16:34:58 -0500 Subject: Add basic support for systemd services. To use, add "Systemd" to the "drivers" option in the "client" section of bcfg2.conf on the client. Then, define services on the server like this: --- src/lib/Client/Tools/Systemd.py | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/lib/Client/Tools/Systemd.py (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/Systemd.py b/src/lib/Client/Tools/Systemd.py new file mode 100644 index 000000000..e3f6a4169 --- /dev/null +++ b/src/lib/Client/Tools/Systemd.py @@ -0,0 +1,59 @@ +# This is the bcfg2 support for systemd + +"""This is systemd support.""" + +import Bcfg2.Client.Tools +import Bcfg2.Client.XML + +class Systemd(Bcfg2.Client.Tools.SvcTool): + """Systemd support for Bcfg2.""" + name = 'Systemd' + __execs__ = ['/bin/systemctl'] + __handles__ = [('Service', 'systemd')] + __req__ = {'Service': ['name', 'status']} + + def get_svc_command(self, service, action): + return "/bin/systemctl %s %s.service" % (action, service.get('name')) + + def VerifyService(self, entry, _): + """Verify Service status for entry.""" + cmd = "/bin/systemctl status %s.service " % (entry.get('name')) + raw = ''.join(self.cmd.run(cmd)[1]) + + if raw.find('Loaded: error') >= 0: + entry.set('current_status', 'off') + status = False + + elif raw.find('Active: active') >= 0: + entry.set('current_status', 'on') + if entry.get('status') == 'off': + status = False + else: + status = True + + else: + entry.set('current_status', 'off') + if entry.get('status') == 'on': + status = False + else: + status = True + + return status + + def InstallService(self, entry): + """Install Service entry.""" + # don't take any actions for mode = 'manual' + if entry.get('mode', 'default') == 'manual': + self.logger.info("Service %s mode set to manual. Skipping " + "installation." % (entry.get('name'))) + return True + + if entry.get('status') == 'on': + pstatus = self.cmd.run(self.get_svc_command(entry, 'enable'))[0] + pstatus = self.cmd.run(self.get_svc_command(entry, 'start'))[0] + + else: + pstatus = self.cmd.run(self.get_svc_command(entry, 'stop'))[0] + pstatus = self.cmd.run(self.get_svc_command(entry, 'disable'))[0] + + return not pstatus -- cgit v1.2.3-1-g7c22 From 6da7d24710fe67c80c4a71f227cd01675eebca88 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 21 Apr 2011 08:50:06 -0400 Subject: Lots of cleanup for bcfg2-repo-validate rewrite: * Changed all references to bcfg2-repo-validate in the documentation to bcfg2-lint * Wrote man pages for bcfg2-lint and bcfg2-lint.conf * Cleaned up straggling references to bcfg2-repo-validate in Makefiles, spec files, and the POSIX tool * A few minor bug fixes --- src/lib/Client/Tools/POSIX.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/POSIX.py b/src/lib/Client/Tools/POSIX.py index bcb9f48b3..af3d1a473 100644 --- a/src/lib/Client/Tools/POSIX.py +++ b/src/lib/Client/Tools/POSIX.py @@ -137,14 +137,14 @@ class POSIX(Bcfg2.Client.Tools.Tool): entry.get('owner') == None or \ entry.get('group') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % (entry.get('name'))) + 'Try running bcfg2-lint.' % (entry.get('name'))) return False if entry.get('dev_type') in ['block', 'char']: # check if major/minor are properly specified if entry.get('major') == None or \ entry.get('minor') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % (entry.get('name'))) + 'Try running bcfg2-lint.' % (entry.get('name'))) return False try: # check for file existence @@ -167,7 +167,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): if entry.get('major') == None or \ entry.get('minor') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % (entry.get('name'))) + 'Try running bcfg2-lint.' % (entry.get('name'))) return False major = int(entry.get('major')) minor = int(entry.get('minor')) @@ -218,7 +218,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): if entry.get('major') == None or \ entry.get('minor') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % (entry.get('name'))) + 'Try running bcfg2-lint.' % (entry.get('name'))) return False major = int(entry.get('major')) minor = int(entry.get('minor')) @@ -240,7 +240,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): entry.get('owner') == None or \ entry.get('group') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % (entry.get('name'))) + 'Try running bcfg2-lint.' % (entry.get('name'))) return False while len(entry.get('perms', '')) < 4: entry.set('perms', '0' + entry.get('perms', '')) @@ -348,7 +348,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): entry.get('owner') == None or \ entry.get('group') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % \ + 'Try running bcfg2-lint.' % \ (entry.get('name'))) return False self.logger.info("Installing directory %s" % (entry.get('name'))) @@ -614,7 +614,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): """Verify HardLink entry.""" if entry.get('to') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % \ + 'Try running bcfg2-lint.' % \ (entry.get('name'))) return False try: @@ -637,7 +637,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): """Install HardLink entry.""" if entry.get('to') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % \ + 'Try running bcfg2-lint.' % \ (entry.get('name'))) return False self.logger.info("Installing Hardlink %s" % (entry.get('name'))) @@ -713,7 +713,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): entry.get('owner') == None or \ entry.get('group') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % (entry.get('name'))) + 'Try running bcfg2-lint.' % (entry.get('name'))) return False try: os.chown(entry.get('name'), normUid(entry), normGid(entry)) @@ -728,7 +728,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): """Verify Path type='symlink' entry.""" if entry.get('to') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % \ + 'Try running bcfg2-lint.' % \ (entry.get('name'))) return False try: @@ -751,7 +751,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): """Install Path type='symlink' entry.""" if entry.get('to') == None: self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-repo-validate.' % \ + 'Try running bcfg2-lint.' % \ (entry.get('name'))) return False self.logger.info("Installing symlink %s" % (entry.get('name'))) -- cgit v1.2.3-1-g7c22 From b748d1a5fde80fa18913b67ae6eccf415d78fed3 Mon Sep 17 00:00:00 2001 From: Jonathan Billings Date: Mon, 25 Apr 2011 11:19:06 -0400 Subject: Fix the bcfg2 client -r option The man page for 'bcfg2' says to use -r 'all', 'Service' or 'Package', but the code only responded to -r 'all', 'service' or 'package'. Update the client to allow 'all', 'service', 'Service', 'package' and 'Package'. --- src/lib/Client/Frame.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Frame.py b/src/lib/Client/Frame.py index f87610dcb..60d158eb1 100644 --- a/src/lib/Client/Frame.py +++ b/src/lib/Client/Frame.py @@ -200,10 +200,10 @@ class Frame: if self.setup['remove']: if self.setup['remove'] == 'all': self.removal = self.extra - elif self.setup['remove'] == 'services': + elif self.setup['remove'] in ['services', 'Services']: self.removal = [entry for entry in self.extra \ if entry.tag == 'Service'] - elif self.setup['remove'] == 'packages': + elif self.setup['remove'] in ['packages', 'Packages']: self.removal = [entry for entry in self.extra \ if entry.tag == 'Package'] -- cgit v1.2.3-1-g7c22 From 4a693086d5f980de8407a7eaeb585aa989916f43 Mon Sep 17 00:00:00 2001 From: Tim Laszlo Date: Mon, 25 Apr 2011 14:56:19 -0500 Subject: SvcTool: adding interactive_only mode --- src/lib/Client/Tools/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/__init__.py b/src/lib/Client/Tools/__init__.py index 7d8d58957..6a934fe52 100644 --- a/src/lib/Client/Tools/__init__.py +++ b/src/lib/Client/Tools/__init__.py @@ -352,7 +352,9 @@ class SvcTool(Tool): return for entry in [ent for ent in bundle if self.handlesEntry(ent)]: - if entry.get('mode', 'default') == 'manual': + mode = entry.get('mode', 'default') + if mode == 'manual' or \ + (mode == 'interactive_only' and not self.setup['interactive']): continue # need to handle servicemode = (build|default) # need to handle mode = (default|supervised) -- cgit v1.2.3-1-g7c22 From aae7818428e13dcaf54457be1acfdd29e73ea943 Mon Sep 17 00:00:00 2001 From: Tim Laszlo Date: Mon, 25 Apr 2011 17:43:51 -0500 Subject: SvcTools: Change return from mode="manual" to false so the entries report a Bad state --- src/lib/Client/Tools/Chkconfig.py | 2 +- src/lib/Client/Tools/DebInit.py | 2 +- src/lib/Client/Tools/RcUpdate.py | 2 +- src/lib/Client/Tools/SMF.py | 2 +- src/lib/Client/Tools/Upstart.py | 2 +- src/lib/Client/Tools/launchd.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/Chkconfig.py b/src/lib/Client/Tools/Chkconfig.py index d1639732a..0c78b0fb5 100644 --- a/src/lib/Client/Tools/Chkconfig.py +++ b/src/lib/Client/Tools/Chkconfig.py @@ -80,7 +80,7 @@ class Chkconfig(Bcfg2.Client.Tools.SvcTool): if entry.get('mode', 'default') == 'manual': self.logger.info("Service %s mode set to manual. Skipping " "installation." % (entry.get('name'))) - return True + return False rcmd = "/sbin/chkconfig %s %s" self.cmd.run("/sbin/chkconfig --add %s"%(entry.attrib['name'])) self.logger.info("Installing Service %s" % (entry.get('name'))) diff --git a/src/lib/Client/Tools/DebInit.py b/src/lib/Client/Tools/DebInit.py index 254b55d98..d6ce16c52 100644 --- a/src/lib/Client/Tools/DebInit.py +++ b/src/lib/Client/Tools/DebInit.py @@ -79,7 +79,7 @@ class DebInit(Bcfg2.Client.Tools.SvcTool): if entry.get('mode', 'default') == 'manual': self.logger.info("Service %s mode set to manual. Skipping " "installation." % (entry.get('name'))) - return True + return False self.logger.info("Installing Service %s" % (entry.get('name'))) try: os.stat('/etc/init.d/%s' % entry.get('name')) diff --git a/src/lib/Client/Tools/RcUpdate.py b/src/lib/Client/Tools/RcUpdate.py index 0c99e8a98..d832d98a8 100644 --- a/src/lib/Client/Tools/RcUpdate.py +++ b/src/lib/Client/Tools/RcUpdate.py @@ -61,7 +61,7 @@ class RcUpdate(Bcfg2.Client.Tools.SvcTool): if entry.get('mode', 'default') == 'manual': self.logger.info("Service %s mode set to manual. Skipping " "installation." % (entry.get('name'))) - return True + return False self.logger.info('Installing Service %s' % entry.get('name')) if entry.get('status') == 'on': # make sure it's running if in supervised mode diff --git a/src/lib/Client/Tools/SMF.py b/src/lib/Client/Tools/SMF.py index 0403ff62e..944408326 100644 --- a/src/lib/Client/Tools/SMF.py +++ b/src/lib/Client/Tools/SMF.py @@ -78,7 +78,7 @@ class SMF(Bcfg2.Client.Tools.SvcTool): if entry.get('mode', 'default') == 'manual': self.logger.info("Service %s mode set to manual. Skipping " "installation." % (entry.get('name'))) - return True + return False self.logger.info("Installing Service %s" % (entry.get('name'))) if entry.get('status') == 'off': if entry.get("FMRI").startswith('lrc'): diff --git a/src/lib/Client/Tools/Upstart.py b/src/lib/Client/Tools/Upstart.py index 2fba6b797..a9d4b166b 100644 --- a/src/lib/Client/Tools/Upstart.py +++ b/src/lib/Client/Tools/Upstart.py @@ -74,7 +74,7 @@ class Upstart(Bcfg2.Client.Tools.SvcTool): if entry.get('mode', 'default') == 'manual': self.logger.info("Service %s mode set to manual. Skipping " "installation." % (entry.get('name'))) - return True + return Fasle if entry.get('status') == 'on': pstatus = self.cmd.run(self.get_svc_command(entry, 'start'))[0] elif entry.get('status') == 'off': diff --git a/src/lib/Client/Tools/launchd.py b/src/lib/Client/Tools/launchd.py index 90569052d..03dd97e71 100644 --- a/src/lib/Client/Tools/launchd.py +++ b/src/lib/Client/Tools/launchd.py @@ -86,7 +86,7 @@ class launchd(Bcfg2.Client.Tools.Tool): if entry.get('mode', 'default') == 'manual': self.logger.info("Service %s mode set to manual. Skipping " "installation." % (entry.get('name'))) - return True + return False name = entry.get('name') if entry.get('status') == 'on': self.logger.error("Installing service %s" % name) -- cgit v1.2.3-1-g7c22 From 99ee7bb5e10e63b80f1ffff7e634815a289ad6ff Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Thu, 28 Apr 2011 19:45:08 -0500 Subject: Client/Tools: Get rid of popen2 (in favor of subprocess) Signed-off-by: Sol Jerome --- src/lib/Client/Tools/__init__.py | 52 ++++++---------------------------------- 1 file changed, 7 insertions(+), 45 deletions(-) (limited to 'src/lib/Client') 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: -- cgit v1.2.3-1-g7c22 From 11b3757156c5c9e5c4095ebd315443baa70f78b7 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Mon, 9 May 2011 09:46:47 -0500 Subject: Upstart: Fix typo reported by justintime on IRC Signed-off-by: Sol Jerome --- src/lib/Client/Tools/Upstart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/Client') diff --git a/src/lib/Client/Tools/Upstart.py b/src/lib/Client/Tools/Upstart.py index a9d4b166b..41a585c23 100644 --- a/src/lib/Client/Tools/Upstart.py +++ b/src/lib/Client/Tools/Upstart.py @@ -74,7 +74,7 @@ class Upstart(Bcfg2.Client.Tools.SvcTool): if entry.get('mode', 'default') == 'manual': self.logger.info("Service %s mode set to manual. Skipping " "installation." % (entry.get('name'))) - return Fasle + return False if entry.get('status') == 'on': pstatus = self.cmd.run(self.get_svc_command(entry, 'start'))[0] elif entry.get('status') == 'off': -- cgit v1.2.3-1-g7c22