1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
"""This is the Bcfg2 tool for the Gentoo Portage system."""
import re
import Bcfg2.Client.Tools
class Portage(Bcfg2.Client.Tools.PkgTool):
"""The Gentoo toolset implements package and service operations and
inherits the rest from Toolset.Toolset."""
name = 'Portage'
__execs__ = ['/usr/bin/emerge', '/usr/bin/equery']
__handles__ = [('Package', 'ebuild')]
__req__ = {'Package': ['name', 'version']}
pkgtype = 'ebuild'
# requires a working PORTAGE_BINHOST in make.conf
_binpkgtool = ('emerge --getbinpkgonly %s', ('=%s-%s', ['name',
'version']))
pkgtool = ('emerge %s', ('=%s-%s', ['name', 'version']))
def __init__(self, logger, cfg, setup):
self._initialised = False
Bcfg2.Client.Tools.PkgTool.__init__(self, logger, cfg, setup)
self._initialised = True
self.__important__ = self.__important__ + ['/etc/make.conf']
self._pkg_pattern = re.compile(r'(.*)-(\d.*)')
self._ebuild_pattern = re.compile('(ebuild|binary)')
self.cfg = cfg
self.installed = {}
self._binpkgonly = self.setup.get('portage_binpkgonly', False)
if self._binpkgonly:
self.pkgtool = self._binpkgtool
self.RefreshPackages()
def RefreshPackages(self):
"""Refresh memory hashes of packages."""
if not self._initialised:
return
self.logger.info('Getting list of installed packages')
self.installed = {}
for pkg in self.cmd.run(["equery", "-q",
"list", "*"]).stdout.splitlines():
if self._pkg_pattern.match(pkg):
name = self._pkg_pattern.match(pkg).group(1)
version = self._pkg_pattern.match(pkg).group(2)
self.installed[name] = version
else:
self.logger.info("Failed to parse pkg name %s" % pkg)
def VerifyPackage(self, entry, modlist):
"""Verify package for entry."""
if not 'version' in entry.attrib:
self.logger.info("Cannot verify unversioned package %s" %
(entry.get('name')))
return False
if not (entry.get('name') in self.installed):
# Can't verify package that isn't installed
entry.set('current_exists', 'false')
return False
# get the installed version
version = self.installed[entry.get('name')]
entry.set('current_version', version)
if not self.setup['quick']:
if ('verify' not in entry.attrib or
entry.get('verify').lower() == 'true'):
# Check the package if:
# - Not running in quick mode
# - No verify option is specified in the literal configuration
# OR
# - Verify option is specified and is true
self.logger.debug('Running equery check on %s' %
entry.get('name'))
for line in self.cmd.run(
["/usr/bin/equery", "-N", "check",
'=%s-%s' % (entry.get('name'),
entry.get('version'))]).stdout.splitlines():
if '!!!' in line and line.split()[1] not in modlist:
return False
# By now the package must be in one of the following states:
# - Not require checking
# - Have no files modified at all
# - Have modified files in the modlist only
if self.installed[entry.get('name')] == version:
# Specified package version is installed
# Specified package version may be any in literal configuration
return True
# Something got skipped. Indicates a bug
return False
def Remove(self, packages):
"""Deal with extra configuration detected."""
pkgnames = " ".join([pkg.get('name') for pkg in packages])
if len(packages) > 0:
self.logger.info('Removing packages:')
self.logger.info(pkgnames)
self.cmd.run("emerge --unmerge --quiet %s" %
" ".join(pkgnames.split(' ')))
self.RefreshPackages()
self.extra = self.FindExtra()
|