summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Client/Tools/SYSV.py
blob: a29b49efa5587d59a1204a8f95329b0695a0355d (plain)
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""This provides bcfg2 support for Solaris SYSV packages."""

import tempfile
from Bcfg2.Compat import any  # pylint: disable=W0622
import Bcfg2.Client.Tools
import Bcfg2.Client.XML
from Bcfg2.Compat import urlretrieve


# pylint: disable=C0103
noask = '''
mail=
instance=overwrite
partial=nocheck
runlevel=nocheck
idepend=nocheck
rdepend=nocheck
space=ask
setuid=nocheck
conflict=nocheck
action=nocheck
basedir=default
'''
# pylint: enable=C0103


class SYSV(Bcfg2.Client.Tools.PkgTool):
    """Solaris SYSV package support."""
    __execs__ = ["/usr/sbin/pkgadd", "/usr/bin/pkginfo"]
    __handles__ = [('Package', 'sysv')]
    __req__ = {'Package': ['name', 'version']}
    __ireq__ = {'Package': ['name', 'url', 'version']}
    name = 'SYSV'
    pkgtype = 'sysv'
    pkgtool = ("/usr/sbin/pkgadd %s -n -d %%s", (('%s %s', ['url', 'name'])))

    def __init__(self, logger, setup, config):
        Bcfg2.Client.Tools.PkgTool.__init__(self, logger, setup, config)
        # 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
            self.noaskfile.flush()
            self.pkgtool = (self.pkgtool[0] % ("-a %s" % (self.noaskname)),
                            self.pkgtool[1])
        except:  # pylint: disable=W0702
            self.pkgtool = (self.pkgtool[0] % "", self.pkgtool[1])
        self.origpkgtool = self.pkgtool

    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.
        """
        for pkg in packages:
            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)

    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 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)
        return pkgcmd

    def Install(self, packages, states):
        self.pkgmogrify(packages)
        super(SYSV, self).Install(packages, states)

    def RefreshPackages(self):
        """Refresh memory hashes of packages."""
        self.installed = {}
        # Build list of packages
        lines = self.cmd.run("/usr/bin/pkginfo -x").stdout.splitlines()
        while lines:
            # Splitting on whitespace means that packages with spaces in
            # their version numbers don't work right.  Found this with
            # IBM TSM software with package versions like
            #           "Version 6 Release 1 Level 0.0"
            # Should probably be done with a regex but this works.
            version = lines.pop().split(') ')[1]
            pkg = lines.pop().split()[0]
            self.installed[pkg] = version

    def VerifyPackage(self, entry, modlist):
        """Verify Package status for entry."""
        desired_version = entry.get('version')
        if desired_version == 'any':
            desired_version = self.installed.get(entry.get('name'),
                                                 desired_version)

        if not self.cmd.run(["/usr/bin/pkginfo", "-q", "-v",
                             desired_version, entry.get('name')]):
            if entry.get('name') in self.installed:
                self.logger.debug("Package %s version incorrect: "
                                  "have %s want %s" %
                                  (entry.get('name'),
                                   self.installed[entry.get('name')],
                                   desired_version))
            else:
                self.logger.debug("Package %s not installed" %
                                  entry.get("name"))
        else:
            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:
                return True
            else:
                output = [line for line in rv.stdout.splitlines()
                          if line[:5] == 'ERROR']
                if any(name for name in output
                       if name.split()[-1] not in modlist):
                    self.logger.debug("Package %s content verification failed"
                                      % entry.get('name'))
                else:
                    return True
        return False

    def Remove(self, packages):
        """Remove specified Sysv packages."""
        names = [pkg.get('name') for pkg in packages]
        self.logger.info("Removing packages: %s" % (names))
        self.cmd.run("/usr/sbin/pkgrm -a %s -n %s" %
                     (self.noaskname, names))
        self.RefreshPackages()
        self.extra = self.FindExtra()