From 598eef149378a0676a921559f7eef379ed2db46f Mon Sep 17 00:00:00 2001 From: asaf Date: Fri, 15 Oct 2010 14:27:25 +0200 Subject: Packages plugin / Client tools : add support for pacman based distros(arch, parabola), needs some more work --- src/lib/Client/Tools/Pacman.py | 81 +++++++++++++++++++++++++++ src/lib/Server/Plugins/Packages.py | 112 +++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 src/lib/Client/Tools/Pacman.py diff --git a/src/lib/Client/Tools/Pacman.py b/src/lib/Client/Tools/Pacman.py new file mode 100644 index 000000000..f155adfd4 --- /dev/null +++ b/src/lib/Client/Tools/Pacman.py @@ -0,0 +1,81 @@ +"""This is the bcfg2 support for pacman""" + +import Bcfg2.Client.Tools +import Bcfg2.Options +import Bcfg2.Client.Tools + +class Pacman(Bcfg2.Client.Tools.PkgTool): + '''Archlinux package support''' + name = 'Pacman' + __execs__ = ["/usr/bin/pacman"] + __handles__ = [('Package', 'txz')] + __req__ = {'Package': ['name', 'version']} + pkgtype = 'pacman' + pkgtool = ("/usr/bin/pacman --needed --noconfirm --noprogressbar -S %s") + + def __init__(self, logger, setup, config): + Bcfg2.Client.Tools.PkgTool.__init__(self, logger, setup, config) + self.installed = {} + self.RefreshPackages() + + def RefreshPackages(self): + '''Refresh memory hashes of packages''' + pkgcache = self.cmd.run("/usr/bin/pacman -Q")[1] + self.installed = {} + for pkg in pkgcache: + pkgname = pkg.split(' ')[0].strip() + version = pkg.split(' ')[1].strip() + #self.logger.info(" pkgname: %s, version: %s" % (pkgname, version)) + self.installed[pkgname] = version + + def VerifyPackage(self, entry, modlist): + '''Verify Package status for entry''' + if not 'version' in entry.attrib: + self.logger.info("Cannot verify unversioned package %s" % + (entry.attrib['name'])) + return False + + if entry.attrib['name'] in self.installed: + if self.installed[entry.attrib['name']] == entry.attrib['version']: + #if not self.setup['quick'] and \ + # entry.get('verify', 'true') == 'true': + #FIXME: We should be able to check this once + # http://trac.macports.org/ticket/15709 is implemented + return True + else: + entry.set('current_version', self.installed[entry.get('name')]) + self.logger.info("attribname: %s" % (entry.attrib['name'])) + self.logger.info("attribname: %s" % (entry.attrib['name'])) + return False + entry.set('current_exists', 'false') + self.logger.info("attribname: %s" % (entry.attrib['name'])) + return False + + def RemovePackages(self, packages): + '''Remove extra packages''' + names = [pkg.get('name') for pkg in packages] + self.logger.info("Removing packages: %s" % " ".join(names)) + self.cmd.run("/usr/bin/pacman --noconfirm --noprogressbar -R %s" % \ + " ".join(names)) + self.RefreshPackages() + self.extra = self.FindExtraPackages() + + def Install(self, packages, states): + ''' + Pacman Install + ''' + pkgline = "" + for pkg in packages: + pkgline += " " + pkg.get('name') + + print "packages : " + pkgline + + try: + self.logger.debug('Running Pacman.Install()') + print "AAAAA" + s = self.cmd.run("%s install" % self.pkgtool) + print "BBB: " + str(s) + except Exception as ex: + print "error in cmd.run ", ex + + self.logger.debug('Running Pacman.Install()') diff --git a/src/lib/Server/Plugins/Packages.py b/src/lib/Server/Plugins/Packages.py index b83b7444f..b24cd48da 100644 --- a/src/lib/Server/Plugins/Packages.py +++ b/src/lib/Server/Plugins/Packages.py @@ -1,6 +1,7 @@ import cPickle import copy import gzip +import tarfile import glob import logging import lxml.etree @@ -467,6 +468,114 @@ class APTSource(Source): pkg not in self.blacklist and \ (len(self.whitelist) == 0 or pkg in self.whitelist) +class PACSource(Source): + basegroups = ['arch', 'parabola'] + ptype = 'txz' + + def __init__(self, basepath, url, version, arches, components, groups, + rawurl, blacklist, whitelist, recommended): + Source.__init__(self, basepath, url, version, arches, components, groups, + rawurl, blacklist, whitelist, recommended) + self.pkgnames = set() + + self.url_map = [{'rawurl': self.rawurl, 'url': self.url, 'version': self.version, \ + 'components': self.components, 'arches': self.arches, 'groups': self.groups}] + + def save_state(self): + cache = file(self.cachefile, 'wb') + cPickle.dump((self.pkgnames, self.deps, self.provides), + cache, 2) + cache.close() + + def load_state(self): + data = file(self.cachefile) + self.pkgnames, self.deps, self.provides = cPickle.load(data) + + def filter_unknown(self, unknown): + filtered = set([u for u in unknown if u.startswith('choice')]) + unknown.difference_update(filtered) + + def get_urls(self): + if not self.rawurl: + return ["%s/%s/os/%s/%s.db.tar.gz" % \ + (self.url, part, arch, part) for part in self.components \ + for arch in self.arches] + else: + raise Exception("PACSource : RAWUrl not supported (yet)") + urls = property(get_urls) + + + def read_files(self): + bdeps = dict() + bprov = dict() + + if self.recommended: + depfnames = ['Depends', 'Pre-Depends', 'Recommends'] + else: + depfnames = ['Depends', 'Pre-Depends'] + + for fname in self.files: + if not self.rawurl: + barch = [x for x in fname.split('@') if x in self.arches][0] + else: + # RawURL entries assume that they only have one + # element and that it is the architecture of the source. + barch = self.arches[0] + + if barch not in bdeps: + bdeps[barch] = dict() + bprov[barch] = dict() + try: + print "try to read : " + fname + tar = tarfile.open(fname, "r") + reader = gzip.GzipFile(fname) + except: + print("Failed to read file %s" % fname) + raise + + for tarinfo in tar: + if tarinfo.isdir(): + self.pkgnames.add(tarinfo.name.rsplit("-",2)[0]) + print "added : " + tarinfo.name.rsplit("-",2)[0] + tar.close() + + self.deps['global'] = dict() + self.provides['global'] = dict() + for barch in bdeps: + self.deps[barch] = dict() + self.provides[barch] = dict() + for pkgname in self.pkgnames: + pset = set() + for barch in bdeps: + if pkgname not in bdeps[barch]: + bdeps[barch][pkgname] = [] + pset.add(tuple(bdeps[barch][pkgname])) + if len(pset) == 1: + self.deps['global'][pkgname] = pset.pop() + else: + for barch in bdeps: + self.deps[barch][pkgname] = bdeps[barch][pkgname] + provided = set() + for bprovided in bprov.values(): + provided.update(set(bprovided)) + for prov in provided: + prset = set() + for barch in bprov: + if prov not in bprov[barch]: + continue + prset.add(tuple(bprov[barch].get(prov, ()))) + if len(prset) == 1: + self.provides['global'][prov] = prset.pop() + else: + for barch in bprov: + self.provides[barch][prov] = bprov[barch].get(prov, ()) + self.save_state() + + def is_package(self, _, pkg): + return pkg in self.pkgnames and \ + pkg not in self.blacklist and \ + (len(self.whitelist) == 0 or pkg in self.whitelist) + class Packages(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.StructureValidator, Bcfg2.Server.Plugin.Generator, @@ -742,6 +851,9 @@ class Packages(Bcfg2.Server.Plugin.Plugin, self.sources.append(APTSource(self.cachepath, **source_from_xml(s))) for s in xdata.findall('.//YUMSource'): self.sources.append(YUMSource(self.cachepath, **source_from_xml(s))) + for s in xdata.findall('.//PACSource'): + self.sources.append(PACSource(self.cachepath, **source_from_xml(s))) + cachefiles = [] for source in self.sources: cachefiles.append(source.cachefile) -- cgit v1.2.3-1-g7c22 From 2a4716d8726e383291637e8f5ae2dff49248ac9b Mon Sep 17 00:00:00 2001 From: Asaf Date: Sun, 17 Oct 2010 07:44:56 +0200 Subject: changed package type to 'pacman', if request package version is 'auto' and its installed dont re-install --- src/lib/Client/Tools/Pacman.py | 21 +++++++++++++-------- src/lib/Server/Plugins/Packages.py | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/lib/Client/Tools/Pacman.py b/src/lib/Client/Tools/Pacman.py index f155adfd4..a9edc4d65 100644 --- a/src/lib/Client/Tools/Pacman.py +++ b/src/lib/Client/Tools/Pacman.py @@ -8,10 +8,10 @@ class Pacman(Bcfg2.Client.Tools.PkgTool): '''Archlinux package support''' name = 'Pacman' __execs__ = ["/usr/bin/pacman"] - __handles__ = [('Package', 'txz')] + __handles__ = [('Package', 'pacman')] __req__ = {'Package': ['name', 'version']} pkgtype = 'pacman' - pkgtool = ("/usr/bin/pacman --needed --noconfirm --noprogressbar -S %s") + pkgtool = ("/usr/bin/pacman --needed --noconfirm --noprogressbar") def __init__(self, logger, setup, config): Bcfg2.Client.Tools.PkgTool.__init__(self, logger, setup, config) @@ -30,13 +30,18 @@ class Pacman(Bcfg2.Client.Tools.PkgTool): def VerifyPackage(self, entry, modlist): '''Verify Package status for entry''' + + print "VerifyPackage : " + entry.get('name')+ " : " + entry.get('version') + if not 'version' in entry.attrib: self.logger.info("Cannot verify unversioned package %s" % (entry.attrib['name'])) return False if entry.attrib['name'] in self.installed: - if self.installed[entry.attrib['name']] == entry.attrib['version']: + if entry.attrib['version'] == 'auto': + return True + elif self.installed[entry.attrib['name']] == entry.attrib['version']: #if not self.setup['quick'] and \ # entry.get('verify', 'true') == 'true': #FIXME: We should be able to check this once @@ -55,8 +60,8 @@ class Pacman(Bcfg2.Client.Tools.PkgTool): '''Remove extra packages''' names = [pkg.get('name') for pkg in packages] self.logger.info("Removing packages: %s" % " ".join(names)) - self.cmd.run("/usr/bin/pacman --noconfirm --noprogressbar -R %s" % \ - " ".join(names)) + self.cmd.run("%s --noconfirm --noprogressbar -R %s" % \ + (self.pkgtool, " ".join(names))) self.RefreshPackages() self.extra = self.FindExtraPackages() @@ -72,9 +77,9 @@ class Pacman(Bcfg2.Client.Tools.PkgTool): try: self.logger.debug('Running Pacman.Install()') - print "AAAAA" - s = self.cmd.run("%s install" % self.pkgtool) - print "BBB: " + str(s) + print "running : %s -S %s" % (self.pkgtool, pkgline) + s = self.cmd.run("%s -S %s" % (self.pkgtool, pkgline)) + print "pacman : " + str(s) except Exception as ex: print "error in cmd.run ", ex diff --git a/src/lib/Server/Plugins/Packages.py b/src/lib/Server/Plugins/Packages.py index b24cd48da..194330723 100644 --- a/src/lib/Server/Plugins/Packages.py +++ b/src/lib/Server/Plugins/Packages.py @@ -470,7 +470,7 @@ class APTSource(Source): class PACSource(Source): basegroups = ['arch', 'parabola'] - ptype = 'txz' + ptype = 'pacman' def __init__(self, basepath, url, version, arches, components, groups, rawurl, blacklist, whitelist, recommended): -- cgit v1.2.3-1-g7c22 From e560e2c7f384bdd5ca675465b85cc5a6c911f747 Mon Sep 17 00:00:00 2001 From: Asaf Ohaion Date: Sun, 17 Oct 2010 10:18:50 +0200 Subject: merged 9a2bb764cf73911885a8e801882219b052f11475 from Sol J --- doc/quickstart/centos.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/quickstart/centos.txt b/doc/quickstart/centos.txt index 2aaa8d744..4a702683e 100644 --- a/doc/quickstart/centos.txt +++ b/doc/quickstart/centos.txt @@ -424,7 +424,7 @@ packages. Currently, the way to manage them is using :ref:`BoundEntries .. code-block:: xml - + @@ -445,6 +445,8 @@ packages. Currently, the way to manage them is using :ref:`BoundEntries +.. note:: version="foo" is just a dummy attribute for the gpg-pubkey Package + To actually push the gpg keys out via Bcfg2, you will need to manage the files as well. This can be done by adding Path entries for each of the gpg keys you want to manage -- cgit v1.2.3-1-g7c22