From d225b15584db0baffc8dd05c1f437883f8d98a64 Mon Sep 17 00:00:00 2001 From: Arach Date: Sat, 5 Jul 2014 02:05:12 +0800 Subject: debsums: read output from stderr instead of stdout --- src/lib/Bcfg2/Client/Tools/APT.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/APT.py b/src/lib/Bcfg2/Client/Tools/APT.py index 39816403a..0a8fe387f 100644 --- a/src/lib/Bcfg2/Client/Tools/APT.py +++ b/src/lib/Bcfg2/Client/Tools/APT.py @@ -91,7 +91,7 @@ class APT(Bcfg2.Client.Tools.Tool): def VerifyDebsums(self, entry, modlist): output = \ self.cmd.run("%s -as %s" % - (self.debsums, entry.get('name'))).stdout.splitlines() + (self.debsums, entry.get('name'))).stderr.splitlines() if len(output) == 1 and "no md5sums for" in output[0]: self.logger.info("Package %s has no md5sums. Cannot verify" % \ entry.get('name')) -- cgit v1.2.3-1-g7c22 From c1e30f4bc8a03a9be535bf126e993ff45e8ab382 Mon Sep 17 00:00:00 2001 From: Nathan Olla Date: Mon, 14 Jul 2014 10:49:44 -0400 Subject: SYSV: Implement downloading and installing SYSV packages from HTTP pkgadd has different syntax for different sources (datastream and file system format) which makes using a single pkgtool variable difficult. Also, SYSV packages in datastream format don't necessarily have uniform names. Therefore, use the existing 'simplename' attribute to specify the datastream file name. --- src/lib/Bcfg2/Client/Tools/SYSV.py | 48 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index aca7d593c..c17c3b712 100644 --- a/src/lib/Bcfg2/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -4,6 +4,9 @@ import tempfile from Bcfg2.Compat import any # pylint: disable=W0622 import Bcfg2.Client.Tools import Bcfg2.Client.XML +import urllib +import copy + # pylint: disable=C0103 noask = ''' @@ -37,6 +40,8 @@ class SYSV(Bcfg2.Client.Tools.PkgTool): # noaskfile needs to live beyond __init__ otherwise file is removed self.noaskfile = tempfile.NamedTemporaryFile() self.noaskname = self.noaskfile.name + # for any pkg files downloaded + self.tmpfiles = [] try: self.noaskfile.write(noask) # flush admin file contents to disk @@ -46,6 +51,45 @@ class SYSV(Bcfg2.Client.Tools.PkgTool): except: # pylint: disable=W0702 self.pkgtool = (self.pkgtool[0] % "", self.pkgtool[1]) + def pkgmogrify(self, pkg): + """ Take a pkg object, check for a 'simplename' attribute. If found, + return a modified pkg object that points to to a temporary file + """ + if pkg.get('simplename'): + self.logger.debug("Pkgmogrifying %s because simplename %s found" % + (pkg.get('name'), pkg.get('simplename'))) + tmpfile = tempfile.NamedTemporaryFile() + self.tmpfiles.append(tmpfile) + self.logger.debug("URL: %s/%s" % + (pkg.get('url'), pkg.get('simplename'))) + urllib.urlretrieve("%s/%s" % + (pkg.get('url'), pkg.get('simplename')), + tmpfile.name) + newpkg = copy.copy(pkg) + newpkg.set('url', tmpfile.name) + return newpkg + return pkg + + def Install(self, packages, states): + for pkg in packages: + pkg = self.pkgmogrify(pkg) + if self.VerifyPackage(pkg, []): + self.logger.info("Forcing state to true for pkg %s" % + (pkg.get('name'))) + states[pkg] = True + else: + self.logger.info("Installing pkg %s version %s" % + (pkg.get('name'), pkg.get('version'))) + + if self.cmd.run(self._get_package_command([pkg])): + states[pkg] = True + else: + self.logger.error("Failed to install package %s" % + pkg.get('name')) + + self.RefreshPackages() + self.modified.extend(entry for entry in packages if states[entry]) + def RefreshPackages(self): """Refresh memory hashes of packages.""" self.installed = {} @@ -80,8 +124,8 @@ class SYSV(Bcfg2.Client.Tools.PkgTool): self.logger.debug("Package %s not installed" % entry.get("name")) else: - if (self.setup['quick'] or - entry.attrib.get('verify', 'true') == 'false'): + if self.setup['quick'] or \ + entry.attrib.get('verify', 'true') == 'false': return True rv = self.cmd.run("/usr/sbin/pkgchk -n %s" % entry.get('name')) if rv.success: -- cgit v1.2.3-1-g7c22 From a9fdf3d7e73c4aabc0b5e5710617c0788b9311c8 Mon Sep 17 00:00:00 2001 From: Nathan Olla Date: Mon, 14 Jul 2014 16:05:22 -0400 Subject: Add urlretrieve to Compat and document --- src/lib/Bcfg2/Client/Tools/SYSV.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index c17c3b712..2d835a8ae 100644 --- a/src/lib/Bcfg2/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -4,8 +4,8 @@ import tempfile from Bcfg2.Compat import any # pylint: disable=W0622 import Bcfg2.Client.Tools import Bcfg2.Client.XML -import urllib import copy +from Bcfg2.Compat import urlretrieve # pylint: disable=C0103 @@ -62,7 +62,7 @@ class SYSV(Bcfg2.Client.Tools.PkgTool): self.tmpfiles.append(tmpfile) self.logger.debug("URL: %s/%s" % (pkg.get('url'), pkg.get('simplename'))) - urllib.urlretrieve("%s/%s" % + urlretrieve("%s/%s" % (pkg.get('url'), pkg.get('simplename')), tmpfile.name) newpkg = copy.copy(pkg) -- cgit v1.2.3-1-g7c22 From f84558cbad0d35ef557f8b767b00f2c14f8907a1 Mon Sep 17 00:00:00 2001 From: Nathan Olla Date: Mon, 14 Jul 2014 16:52:37 -0400 Subject: Fix indenting --- src/lib/Bcfg2/Client/Tools/SYSV.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index 2d835a8ae..811711723 100644 --- a/src/lib/Bcfg2/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -60,11 +60,10 @@ class SYSV(Bcfg2.Client.Tools.PkgTool): (pkg.get('name'), pkg.get('simplename'))) tmpfile = tempfile.NamedTemporaryFile() self.tmpfiles.append(tmpfile) - self.logger.debug("URL: %s/%s" % - (pkg.get('url'), pkg.get('simplename'))) - urlretrieve("%s/%s" % - (pkg.get('url'), pkg.get('simplename')), - tmpfile.name) + self.logger.debug("URL: %s/%s" % (pkg.get('url'), + pkg.get('simplename'))) + urlretrieve("%s/%s" % (pkg.get('url'), pkg.get('simplename')), + tmpfile.name) newpkg = copy.copy(pkg) newpkg.set('url', tmpfile.name) return newpkg -- cgit v1.2.3-1-g7c22 From a4bf68d3c32e6654f53d8e151104850a54ad1e41 Mon Sep 17 00:00:00 2001 From: Nathan Olla Date: Wed, 16 Jul 2014 10:06:25 -0400 Subject: Implement _get_package_command and append _sysv_pkg_path attribute Instead of doing a partially complete Install() method for SYSV, implements a custom _get_package_command that will use the _sysv_pkg_path attribute added by the pkgmogrify call. This will allow the installs to complete. Unfortunately, the single-pass install will still fail if there are any packages with an http:// URL. The pkgadd invocation for 'device' sources doesn't take multiple packages and the 'datastream' invocation doesn't handle packages with an HTTP URL. Finally, there is no reliable standard naming convention for SYSV datastream files, so the simplename attribute is re-used. There is a known issue with this patch - if any packages specified in the PackageList have an http url, the single-pass install will produce an error like: Trying single pass package install for pkgtype sysv pkgadd: ERROR: Failure occurred with http(s) negotiation: <'Peername' doesn't match 'host' or no matching entry> pkgadd: ERROR: unable to download package datastream from . Single Pass Failed because the command that results isn't valid syntax for pkgadd. A workaround would be to add code to skip the single-pass install if any packages had the simplename attribute, or by checking the url for the presence of 'http'. I'm not sure if that should be fixed or if this is reasonable in this case. --- src/lib/Bcfg2/Client/Tools/SYSV.py | 60 +++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 33 deletions(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index 811711723..4f3eea668 100644 --- a/src/lib/Bcfg2/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -50,44 +50,38 @@ class SYSV(Bcfg2.Client.Tools.PkgTool): self.pkgtool[1]) except: # pylint: disable=W0702 self.pkgtool = (self.pkgtool[0] % "", self.pkgtool[1]) + self.origpkgtool = self.pkgtool - def pkgmogrify(self, pkg): - """ Take a pkg object, check for a 'simplename' attribute. If found, - return a modified pkg object that points to to a temporary file + def pkgmogrify(self, packages): + """ Take a list of pkg objects, check for a 'simplename' attribute. + If present, insert a _sysv_pkg_path attribute to the package and + download the datastream format SYSV package to a temporary file. """ - if pkg.get('simplename'): - self.logger.debug("Pkgmogrifying %s because simplename %s found" % - (pkg.get('name'), pkg.get('simplename'))) - tmpfile = tempfile.NamedTemporaryFile() - self.tmpfiles.append(tmpfile) - self.logger.debug("URL: %s/%s" % (pkg.get('url'), - pkg.get('simplename'))) - urlretrieve("%s/%s" % (pkg.get('url'), pkg.get('simplename')), - tmpfile.name) - newpkg = copy.copy(pkg) - newpkg.set('url', tmpfile.name) - return newpkg - return pkg - - def Install(self, packages, states): for pkg in packages: - pkg = self.pkgmogrify(pkg) - if self.VerifyPackage(pkg, []): - self.logger.info("Forcing state to true for pkg %s" % - (pkg.get('name'))) - states[pkg] = True - else: - self.logger.info("Installing pkg %s version %s" % - (pkg.get('name'), pkg.get('version'))) + if pkg.get('simplename'): + tmpfile = tempfile.NamedTemporaryFile() + self.tmpfiles.append(tmpfile) + urlretrieve("%s/%s" % (pkg.get('url'), pkg.get('simplename')), + tmpfile.name) + pkg.set('_sysv_pkg_path', tmpfile.name) - if self.cmd.run(self._get_package_command([pkg])): - states[pkg] = True - else: - self.logger.error("Failed to install package %s" % - pkg.get('name')) + def _get_package_command(self, packages): + """Override the default _get_package_command, replacing the attribute + 'url' if '_sysv_pkg_path' if necessary in the returned command + string""" + if len(packages) == 1 and '_sysv_pkg_path' in packages[0].keys(): + self.pkgtool = (self.pkgtool[0], ('%s %s', + ['_sysv_pkg_path', 'name'])) + else: + self.pkgtool = self.origpkgtool + + pkgcmd = super(SYSV, self)._get_package_command(packages) + self.logger.debug("Calling install command: %s" % pkgcmd) + return pkgcmd - self.RefreshPackages() - self.modified.extend(entry for entry in packages if states[entry]) + def Install(self, packages, states): + self.pkgmogrify(packages) + super(SYSV, self).Install(packages, states) def RefreshPackages(self): """Refresh memory hashes of packages.""" -- cgit v1.2.3-1-g7c22 From d5be1d7f9c9456ee0c6f43b3d05902b200f1dd54 Mon Sep 17 00:00:00 2001 From: Nathan Olla Date: Wed, 16 Jul 2014 10:49:48 -0400 Subject: Remove unused import of copy --- src/lib/Bcfg2/Client/Tools/SYSV.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index 4f3eea668..48d67c4f1 100644 --- a/src/lib/Bcfg2/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -4,7 +4,6 @@ import tempfile from Bcfg2.Compat import any # pylint: disable=W0622 import Bcfg2.Client.Tools import Bcfg2.Client.XML -import copy from Bcfg2.Compat import urlretrieve -- cgit v1.2.3-1-g7c22 From b40dc8df20d8b1566da45ccea0620c60de476222 Mon Sep 17 00:00:00 2001 From: Nathan Olla Date: Wed, 16 Jul 2014 15:21:39 -0400 Subject: Check for origpkgtool attribute to prevent things that subclass SYSV from breaking --- src/lib/Bcfg2/Client/Tools/SYSV.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index 48d67c4f1..712dcce32 100644 --- a/src/lib/Bcfg2/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -67,12 +67,14 @@ class SYSV(Bcfg2.Client.Tools.PkgTool): def _get_package_command(self, packages): """Override the default _get_package_command, replacing the attribute 'url' if '_sysv_pkg_path' if necessary in the returned command - string""" - if len(packages) == 1 and '_sysv_pkg_path' in packages[0].keys(): - self.pkgtool = (self.pkgtool[0], ('%s %s', - ['_sysv_pkg_path', 'name'])) - else: - self.pkgtool = self.origpkgtool + string + """ + if hasattr(self, 'origpkgtool'): + if len(packages) == 1 and '_sysv_pkg_path' in packages[0].keys(): + self.pkgtool = (self.pkgtool[0], ('%s %s', + ['_sysv_pkg_path', 'name'])) + else: + self.pkgtool = self.origpkgtool pkgcmd = super(SYSV, self)._get_package_command(packages) self.logger.debug("Calling install command: %s" % pkgcmd) -- cgit v1.2.3-1-g7c22 From a04304db76ad1ce8e3658c14e8281239210da1dd Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Fri, 18 Jul 2014 08:05:52 -0500 Subject: POSIXUsers.py: Allow supplementary group = primary Signed-off-by: Sol Jerome --- src/lib/Bcfg2/Client/Tools/POSIXUsers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/POSIXUsers.py b/src/lib/Bcfg2/Client/Tools/POSIXUsers.py index 6d18cd176..bbae7abcc 100644 --- a/src/lib/Bcfg2/Client/Tools/POSIXUsers.py +++ b/src/lib/Bcfg2/Client/Tools/POSIXUsers.py @@ -146,7 +146,7 @@ class POSIXUsers(Bcfg2.Client.Tools.Tool): """ Get a list of supplmentary groups that the user in the given entry is a member of """ return [g for g in self.existing['POSIXGroup'].values() - if entry.get("name") in g[3] and g[0] != entry.get("group") + if entry.get("name") in g[3] and self._in_managed_range('POSIXGroup', g[2])] def VerifyPOSIXUser(self, entry, _): -- cgit v1.2.3-1-g7c22 From d5b3c70dccd23f687c8194f6ea1807092370e586 Mon Sep 17 00:00:00 2001 From: Nathan Olla Date: Tue, 19 Aug 2014 17:58:20 -0400 Subject: Log when downloading packages via HTTP --- src/lib/Bcfg2/Client/Tools/SYSV.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index 712dcce32..a29b49efa 100644 --- a/src/lib/Bcfg2/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -60,6 +60,8 @@ class SYSV(Bcfg2.Client.Tools.PkgTool): if pkg.get('simplename'): tmpfile = tempfile.NamedTemporaryFile() self.tmpfiles.append(tmpfile) + self.logger.info("Downloading %s%s to %s" % (pkg.get('url'), + pkg.get('simplename'), tmpfile.name)) urlretrieve("%s/%s" % (pkg.get('url'), pkg.get('simplename')), tmpfile.name) pkg.set('_sysv_pkg_path', tmpfile.name) -- cgit v1.2.3-1-g7c22 From a2b8b3282bc07e1db362d2edd51d2bee3e425d57 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Wed, 15 Oct 2014 14:25:40 -0500 Subject: Proxy.py: Pass through SSL protocol option Previously we were not passing through the SSL protocol specified in the client's bcfg2.conf which caused it to unconditionally be set to xmlrpc/ssl. While this appears to automagically work with newer versions of openssl, the version in e.g. centos5 will fail if the server is set to use TLSv1. This commit passes through the setting from the client's bcfg2.conf so that older clients can talk to servers which are set to TLSv1 (in order to mitigate the effects of POODLE). Signed-off-by: Sol Jerome --- src/lib/Bcfg2/Client/Client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Client.py b/src/lib/Bcfg2/Client/Client.py index 14fe6768a..090921ab2 100644 --- a/src/lib/Bcfg2/Client/Client.py +++ b/src/lib/Bcfg2/Client/Client.py @@ -139,7 +139,8 @@ class Client(object): allowedServerCNs=self.setup['serverCN'], timeout=self.setup['timeout'], retries=int(self.setup['retries']), - delay=int(self.setup['retry_delay'])) + delay=int(self.setup['retry_delay']), + protocol=self.setup['protocol']) return self._proxy def run_probes(self, times=None): -- cgit v1.2.3-1-g7c22 From 234aa9b1c5efc87d71b70e2abc5b422a487ec61e Mon Sep 17 00:00:00 2001 From: Jonathan Billings Date: Thu, 16 Oct 2014 12:46:42 -0400 Subject: YUM: Add options to enable and disable Yum plugins Adds two options you can define: * disabled_plugins: A comma-separated list of plugins to disable * enabled_plugins: A comma-separated list of plugins to enable This allows you to run bcfg2 with certain plugins enabled or disabled when they're not set that way in the yum configuration. This is useful because the Bcfg2 YUM plugin is initialized before it can read in any files that might overwrite yum plugin configuration. --- src/lib/Bcfg2/Client/Tools/YUM.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/YUM.py b/src/lib/Bcfg2/Client/Tools/YUM.py index 15ae5ef8b..a584fec86 100644 --- a/src/lib/Bcfg2/Client/Tools/YUM.py +++ b/src/lib/Bcfg2/Client/Tools/YUM.py @@ -191,6 +191,10 @@ class YUM(Bcfg2.Client.Tools.PkgTool): self.logger.debug("Yum: Reinstall on verify fail: %s" % self.do_reinst) self.logger.debug("Yum: installonlypkgs: %s" % self.installonlypkgs) self.logger.debug("Yum: verify_flags: %s" % self.verify_flags) + self.logger.debug("Yum: disabled_plugins: %s" % + self.setup["yum_disabled_plugins"]) + self.logger.debug("Yum: enabled_plugins: %s" % + self.setup["yum_enabled_plugins"]) def _loadYumBase(self, setup=None, logger=None): ''' this may be called before PkgTool.__init__() is called on @@ -216,6 +220,12 @@ class YUM(Bcfg2.Client.Tools.PkgTool): else: debuglevel = 0 + if setup['yum_disabled_plugins']: + rv.preconf.disabled_plugins = setup['yum_disabled_plugins'] + + if setup['yum_enabled_plugins']: + rv.preconf.enabled_plugins = setup['yum_enabled_plugins'] + # pylint: disable=E1121,W0212 try: rv.preconf.debuglevel = debuglevel -- cgit v1.2.3-1-g7c22 From 835c459b9849b888fdecd045f5d64b37742eb2b3 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Wed, 29 Oct 2014 15:30:26 -0500 Subject: Tools: Fix install of non-whitelisted services Previously, a service restart would occur even when running in whitelist mode without the service being present in the whitelist. Signed-off-by: Sol Jerome --- src/lib/Bcfg2/Client/Tools/Action.py | 22 +++------------------- src/lib/Bcfg2/Client/Tools/__init__.py | 22 ++++++++++++++++++++-- 2 files changed, 23 insertions(+), 21 deletions(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/Action.py b/src/lib/Bcfg2/Client/Tools/Action.py index 0166e4c00..1edf4609b 100644 --- a/src/lib/Bcfg2/Client/Tools/Action.py +++ b/src/lib/Bcfg2/Client/Tools/Action.py @@ -4,7 +4,6 @@ import os import sys import select import Bcfg2.Client.Tools -from Bcfg2.Client.Frame import matches_white_list, passes_black_list from Bcfg2.Compat import input # pylint: disable=W0622 @@ -15,21 +14,6 @@ class Action(Bcfg2.Client.Tools.Tool): __req__ = {'PostInstall': ['name'], 'Action': ['name', 'timing', 'when', 'command', 'status']} - def _action_allowed(self, action): - """ Return true if the given action is allowed to be run by - the whitelist or blacklist """ - if self.setup['decision'] == 'whitelist' and \ - not matches_white_list(action, self.setup['decision_list']): - self.logger.info("In whitelist mode: suppressing Action: %s" % - action.get('name')) - return False - if self.setup['decision'] == 'blacklist' and \ - not passes_black_list(action, self.setup['decision_list']): - self.logger.info("In blacklist mode: suppressing Action: %s" % - action.get('name')) - return False - return True - def RunAction(self, entry): """This method handles command execution and status return.""" shell = False @@ -90,12 +74,12 @@ class Action(Bcfg2.Client.Tools.Tool): def BundleUpdated(self, bundle, states): """Run postinstalls when bundles have been updated.""" for postinst in bundle.findall("PostInstall"): - if not self._action_allowed(postinst): + if not self._install_allowed(postinst): continue self.cmd.run(postinst.get('name')) for action in bundle.findall("Action"): if action.get('timing') in ['post', 'both']: - if not self._action_allowed(action): + if not self._install_allowed(action): continue states[action] = self.RunAction(action) @@ -104,6 +88,6 @@ class Action(Bcfg2.Client.Tools.Tool): for action in bundle.findall("Action"): if action.get('timing') in ['post', 'both'] and \ action.get('when') != 'modified': - if not self._action_allowed(action): + if not self._install_allowed(action): continue states[action] = self.RunAction(action) diff --git a/src/lib/Bcfg2/Client/Tools/__init__.py b/src/lib/Bcfg2/Client/Tools/__init__.py index 703b8ff57..0bec71e20 100644 --- a/src/lib/Bcfg2/Client/Tools/__init__.py +++ b/src/lib/Bcfg2/Client/Tools/__init__.py @@ -1,10 +1,12 @@ """This contains all Bcfg2 Tool modules""" import os -import sys import stat +import sys + import Bcfg2.Client import Bcfg2.Client.XML +from Bcfg2.Client.Frame import matches_white_list, passes_black_list from Bcfg2.Utils import Executor, ClassName from Bcfg2.Compat import walk_packages # pylint: disable=W0622 @@ -141,6 +143,21 @@ class Tool(object): raise ToolInstantiationError("%s: %s not executable" % (self.name, filename)) + def _install_allowed(self, entry): + """ Return true if the given entry is allowed to be installed by + the whitelist or blacklist """ + if self.setup['decision'] == 'whitelist' and \ + not matches_white_list(entry, self.setup['decision_list']): + self.logger.info("In whitelist mode: suppressing %s: %s" % + (entry.tag, entry.get('name'))) + return False + if self.setup['decision'] == 'blacklist' and \ + not passes_black_list(entry, self.setup['decision_list']): + self.logger.info("In blacklist mode: suppressing %s: %s" % + (entry.tag, entry.get('name'))) + return False + return True + def BundleUpdated(self, bundle, states): # pylint: disable=W0613 """ Callback that is invoked when a bundle has been updated. @@ -591,7 +608,8 @@ class SvcTool(Tool): return for entry in bundle: - if not self.handlesEntry(entry): + if (not self.handlesEntry(entry) + or not self._install_allowed(entry)): continue estatus = entry.get('status') -- cgit v1.2.3-1-g7c22 From 4e8bc5c002a54aaee1368330be6374c2e9deda59 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Wed, 5 Nov 2014 16:18:33 +0100 Subject: Client/Tools/APT: handle exceptions gracefully Exceptions during cache update (in kevlar mode) should not prevent the client tool from initializing. In the worst case the old cache would be used for the client run. --- src/lib/Bcfg2/Client/Tools/APT.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/APT.py b/src/lib/Bcfg2/Client/Tools/APT.py index 0a8fe387f..d736b12ea 100644 --- a/src/lib/Bcfg2/Client/Tools/APT.py +++ b/src/lib/Bcfg2/Client/Tools/APT.py @@ -68,7 +68,11 @@ class APT(Bcfg2.Client.Tools.Tool): e = sys.exc_info()[1] self.logger.info("Failed to initialize APT cache: %s" % e) raise Bcfg2.Client.Tools.ToolInstantiationError - self.pkg_cache.update() + try: + self.pkg_cache.update() + except FetchFailedException: + e = sys.exc_info()[1] + self.logger.info("Failed to update APT cache: %s" % e) self.pkg_cache = apt.cache.Cache() if 'req_reinstall_pkgs' in dir(self.pkg_cache): self._newapi = True -- cgit v1.2.3-1-g7c22 From dccd33a479c0ff14d90d2939534f91964e1a393c Mon Sep 17 00:00:00 2001 From: Michael Fenn Date: Thu, 6 Nov 2014 14:05:42 -0500 Subject: SYSV: change instances of simplename to simplefile This is to better match the schema since simplefile already exists. The previous simplename attribute would fail validation. Since pkgmgr already helpfully constructs url for you if simplefile exists, the tool no longer needs to do the concatenation itself. Given the low usage rate of SYSV.py and that the original functionality was introduced in a late 1.3 release, changing the name w/o providing backwards compatiblity seems reasonable. --- src/lib/Bcfg2/Client/Tools/SYSV.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index a29b49efa..27c3d3785 100644 --- a/src/lib/Bcfg2/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -52,18 +52,17 @@ class SYSV(Bcfg2.Client.Tools.PkgTool): self.origpkgtool = self.pkgtool def pkgmogrify(self, packages): - """ Take a list of pkg objects, check for a 'simplename' attribute. + """ Take a list of pkg objects, check for a 'simplefile' attribute. If present, insert a _sysv_pkg_path attribute to the package and download the datastream format SYSV package to a temporary file. """ for pkg in packages: - if pkg.get('simplename'): + if pkg.get('simplefile'): tmpfile = tempfile.NamedTemporaryFile() self.tmpfiles.append(tmpfile) - self.logger.info("Downloading %s%s to %s" % (pkg.get('url'), - pkg.get('simplename'), tmpfile.name)) - urlretrieve("%s/%s" % (pkg.get('url'), pkg.get('simplename')), - tmpfile.name) + self.logger.info("Downloading %s to %s" % (pkg.get('url'), + tmpfile.name)) + urlretrieve(pkg.get('url'), tmpfile.name) pkg.set('_sysv_pkg_path', tmpfile.name) def _get_package_command(self, packages): -- cgit v1.2.3-1-g7c22 From 26f0b52730f7fe5255a6a118b5afb564fc660423 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Mon, 10 Nov 2014 00:21:22 +0100 Subject: Client/Tools/APT: fix exception name --- src/lib/Bcfg2/Client/Tools/APT.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/APT.py b/src/lib/Bcfg2/Client/Tools/APT.py index d736b12ea..66ecf9610 100644 --- a/src/lib/Bcfg2/Client/Tools/APT.py +++ b/src/lib/Bcfg2/Client/Tools/APT.py @@ -70,7 +70,7 @@ class APT(Bcfg2.Client.Tools.Tool): raise Bcfg2.Client.Tools.ToolInstantiationError try: self.pkg_cache.update() - except FetchFailedException: + except apt.cache.FetchFailedException: e = sys.exc_info()[1] self.logger.info("Failed to update APT cache: %s" % e) self.pkg_cache = apt.cache.Cache() -- cgit v1.2.3-1-g7c22 From 0bfc5a946a10712a5d82daa6ae0d1cd50fbb4ba8 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Mon, 10 Nov 2014 01:26:26 +0100 Subject: Client/Tools/APT: fix pylint errors, enable check Previously pep8/pylint checks were disable for the APT tool because there were to many errors. This fix the pylint errors and enables the code style checks. --- src/lib/Bcfg2/Client/Tools/APT.py | 143 +++++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 62 deletions(-) (limited to 'src/lib/Bcfg2/Client') diff --git a/src/lib/Bcfg2/Client/Tools/APT.py b/src/lib/Bcfg2/Client/Tools/APT.py index 66ecf9610..300c9bc51 100644 --- a/src/lib/Bcfg2/Client/Tools/APT.py +++ b/src/lib/Bcfg2/Client/Tools/APT.py @@ -6,11 +6,13 @@ warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) import apt.cache import os +import sys import Bcfg2.Client.Tools + class APT(Bcfg2.Client.Tools.Tool): - """The Debian toolset implements package and service operations and inherits - the rest from Toolset.Toolset. + """The Debian toolset implements package and service operations and + inherits the rest from Toolset.Toolset. """ name = 'APT' @@ -41,21 +43,24 @@ class APT(Bcfg2.Client.Tools.Tool): if not self.setup['debug']: self.pkgcmd += '-q=2 ' self.pkgcmd += '-y install %s' - self.ignores = [entry.get('name') for struct in config \ - for entry in struct \ - if entry.tag == 'Path' and \ + self.ignores = [entry.get('name') for struct in config + for entry in struct + if entry.tag == 'Path' and entry.get('type') == 'ignore'] self.__important__ = self.__important__ + \ - ["%s/cache/debconf/config.dat" % self.var_path, - "%s/cache/debconf/templates.dat" % self.var_path, - '/etc/passwd', '/etc/group', - '%s/apt/apt.conf' % self.etc_path, - '%s/dpkg/dpkg.cfg' % self.etc_path] + \ - [entry.get('name') for struct in config for entry in struct \ - if entry.tag == 'Path' and \ - entry.get('name').startswith('%s/apt/sources.list' % self.etc_path)] - self.nonexistent = [entry.get('name') for struct in config for entry in struct \ - if entry.tag == 'Path' and entry.get('type') == 'nonexistent'] + ["%s/cache/debconf/config.dat" % self.var_path, + "%s/cache/debconf/templates.dat" % self.var_path, + '/etc/passwd', '/etc/group', + '%s/apt/apt.conf' % self.etc_path, + '%s/dpkg/dpkg.cfg' % self.etc_path] + \ + [entry.get('name') for struct in config for entry in struct + if entry.tag == 'Path' and + entry.get('name').startswith( + '%s/apt/sources.list' % self.etc_path)] + self.nonexistent = [entry.get('name') for struct in config + for entry in struct + if entry.tag == 'Path' and + entry.get('type') == 'nonexistent'] os.environ["DEBIAN_FRONTEND"] = 'noninteractive' self.actions = {} if self.setup['kevlar'] and not self.setup['dryrun']: @@ -65,14 +70,14 @@ class APT(Bcfg2.Client.Tools.Tool): try: self.pkg_cache = apt.cache.Cache() except SystemError: - e = sys.exc_info()[1] - self.logger.info("Failed to initialize APT cache: %s" % e) + err = sys.exc_info()[1] + self.logger.info("Failed to initialize APT cache: %s" % err) raise Bcfg2.Client.Tools.ToolInstantiationError try: self.pkg_cache.update() except apt.cache.FetchFailedException: - e = sys.exc_info()[1] - self.logger.info("Failed to update APT cache: %s" % e) + err = sys.exc_info()[1] + self.logger.info("Failed to update APT cache: %s" % err) self.pkg_cache = apt.cache.Cache() if 'req_reinstall_pkgs' in dir(self.pkg_cache): self._newapi = True @@ -88,16 +93,17 @@ class APT(Bcfg2.Client.Tools.Tool): else: extras = [(p.name, p.installedVersion) for p in self.pkg_cache if p.isInstalled and p.name not in packages] - return [Bcfg2.Client.XML.Element('Package', name=name, \ - type='deb', version=version) \ - for (name, version) in extras] + return [Bcfg2.Client.XML.Element('Package', name=name, + type='deb', version=version) + for (name, version) in extras] def VerifyDebsums(self, entry, modlist): + """Verify the package contents with debsum information.""" output = \ self.cmd.run("%s -as %s" % (self.debsums, entry.get('name'))).stderr.splitlines() if len(output) == 1 and "no md5sums for" in output[0]: - self.logger.info("Package %s has no md5sums. Cannot verify" % \ + self.logger.info("Package %s has no md5sums. Cannot verify" % entry.get('name')) entry.set('qtext', "Reinstall Package %s-%s to setup md5sums? (y/N) " % @@ -117,10 +123,10 @@ class APT(Bcfg2.Client.Tools.Tool): # these files should not exist continue elif "is not installed" in item or "missing file" in item: - self.logger.error("Package %s is not fully installed" \ + self.logger.error("Package %s is not fully installed" % entry.get('name')) else: - self.logger.error("Got Unsupported pattern %s from debsums" \ + self.logger.error("Got Unsupported pattern %s from debsums" % item) files.append(item) files = list(set(files) - set(self.ignores)) @@ -131,31 +137,32 @@ class APT(Bcfg2.Client.Tools.Tool): modlist = [os.path.realpath(filename) for filename in modlist] bad = [filename for filename in files if filename not in modlist] if bad: - self.logger.debug("It is suggested that you either manage these " - "files, revert the changes, or ignore false " - "failures:") - self.logger.info("Package %s failed validation. Bad files are:" % \ - entry.get('name')) + self.logger.debug("It is suggested that you either manage " + "these files, revert the changes, or " + "ignore false failures:") + self.logger.info("Package %s failed validation. Bad files are:" + % entry.get('name')) self.logger.info(bad) - entry.set('qtext', - "Reinstall Package %s-%s to fix failing files? (y/N) " % \ - (entry.get('name'), entry.get('version'))) + entry.set( + 'qtext', + "Reinstall Package %s-%s to fix failing files? (y/N) " + % (entry.get('name'), entry.get('version'))) return False return True def VerifyPackage(self, entry, modlist, checksums=True): """Verify package for entry.""" - if not 'version' in entry.attrib: + if 'version' not in entry.attrib: self.logger.info("Cannot verify unversioned package %s" % (entry.attrib['name'])) return False pkgname = entry.get('name') - if self.pkg_cache.has_key(pkgname): + if self.pkg_cache.has_key(pkgname): # noqa if self._newapi: is_installed = self.pkg_cache[pkgname].is_installed else: is_installed = self.pkg_cache[pkgname].isInstalled - if not self.pkg_cache.has_key(pkgname) or not is_installed: + if not self.pkg_cache.has_key(pkgname) or not is_installed: # noqa self.logger.info("Package %s not installed" % (entry.get('name'))) entry.set('current_exists', 'false') return False @@ -168,28 +175,33 @@ class APT(Bcfg2.Client.Tools.Tool): installed_version = pkg.installedVersion candidate_version = pkg.candidateVersion if entry.get('version') == 'auto': + # pylint: disable=W0212 if self._newapi: - is_upgradable = self.pkg_cache._depcache.is_upgradable(pkg._pkg) + is_upgradable = self.pkg_cache._depcache.is_upgradable( + pkg._pkg) else: - is_upgradable = self.pkg_cache._depcache.IsUpgradable(pkg._pkg) + is_upgradable = self.pkg_cache._depcache.IsUpgradable( + pkg._pkg) + # pylint: enable=W0212 if is_upgradable: - desiredVersion = candidate_version + desired_version = candidate_version else: - desiredVersion = installed_version + desired_version = installed_version elif entry.get('version') == 'any': - desiredVersion = installed_version + desired_version = installed_version else: - desiredVersion = entry.get('version') - if desiredVersion != installed_version: + desired_version = entry.get('version') + if desired_version != installed_version: entry.set('current_version', installed_version) - entry.set('qtext', "Modify Package %s (%s -> %s)? (y/N) " % \ + entry.set('qtext', "Modify Package %s (%s -> %s)? (y/N) " % (entry.get('name'), entry.get('current_version'), - desiredVersion)) + desired_version)) return False else: # version matches - if not self.setup['quick'] and entry.get('verify', 'true') == 'true' \ - and checksums: + if not self.setup['quick'] \ + and entry.get('verify', 'true') == 'true' \ + and checksums: pkgsums = self.VerifyDebsums(entry, modlist) return pkgsums return True @@ -207,7 +219,7 @@ class APT(Bcfg2.Client.Tools.Tool): self.pkg_cache[pkg].mark_delete(purge=True) else: self.pkg_cache[pkg].markDelete(purge=True) - except: + except: # pylint: disable=W0702 if self._newapi: self.pkg_cache[pkg].mark_delete() else: @@ -227,33 +239,40 @@ class APT(Bcfg2.Client.Tools.Tool): ipkgs = [] bad_pkgs = [] for pkg in packages: - if not self.pkg_cache.has_key(pkg.get('name')): - self.logger.error("APT has no information about package %s" % (pkg.get('name'))) + if not self.pkg_cache.has_key(pkg.get('name')): # noqa + self.logger.error("APT has no information about package %s" + % (pkg.get('name'))) continue if pkg.get('version') in ['auto', 'any']: if self._newapi: try: - ipkgs.append("%s=%s" % (pkg.get('name'), - self.pkg_cache[pkg.get('name')].candidate.version)) + ipkgs.append("%s=%s" % ( + pkg.get('name'), + self.pkg_cache[pkg.get('name')].candidate.version)) except AttributeError: - self.logger.error("Failed to find %s in apt package cache" % - pkg.get('name')) + self.logger.error("Failed to find %s in apt package " + "cache" % pkg.get('name')) continue else: - ipkgs.append("%s=%s" % (pkg.get('name'), - self.pkg_cache[pkg.get('name')].candidateVersion)) + ipkgs.append("%s=%s" % ( + pkg.get('name'), + self.pkg_cache[pkg.get('name')].candidateVersion)) continue + # pylint: disable=W0212 if self._newapi: - avail_vers = [x.ver_str for x in \ - self.pkg_cache[pkg.get('name')]._pkg.version_list] + avail_vers = [ + x.ver_str for x in + self.pkg_cache[pkg.get('name')]._pkg.version_list] else: - avail_vers = [x.VerStr for x in \ - self.pkg_cache[pkg.get('name')]._pkg.VersionList] + avail_vers = [ + x.VerStr for x in + self.pkg_cache[pkg.get('name')]._pkg.VersionList] + # pylint: enable=W0212 if pkg.get('version') in avail_vers: ipkgs.append("%s=%s" % (pkg.get('name'), pkg.get('version'))) continue else: - self.logger.error("Package %s: desired version %s not in %s" \ + self.logger.error("Package %s: desired version %s not in %s" % (pkg.get('name'), pkg.get('version'), avail_vers)) bad_pkgs.append(pkg.get('name')) @@ -271,6 +290,6 @@ class APT(Bcfg2.Client.Tools.Tool): if states[package]: self.modified.append(package) - def VerifyPath(self, entry, _): + def VerifyPath(self, entry, _): # pylint: disable=W0613 """Do nothing here since we only verify Path type=ignore.""" return True -- cgit v1.2.3-1-g7c22