summaryrefslogtreecommitdiffstats
path: root/src/lib/Client/Debian.py
blob: fc5e3b2bcc4a12498a77b3638e65d2762aa6a82a (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
'''This is the bcfg2 support for debian'''
__revision__ = '$Revision$'

import apt_pkg, glob, os, re, sys, Bcfg2.Client.Toolset

class ToolsetImpl(Bcfg2.Client.Toolset.Toolset):
    '''The Debian toolset implements package and service operations and inherits
    the rest from Toolset.Toolset'''
    __name__ = 'Debian'
    __important__ = ["/etc/apt/sources.list", "/var/cache/debconf/config.dat", \
                     "/var/cache/debconf/templates.dat", '/etc/passwd', '/etc/group', \
                     '/etc/apt/apt.conf']
    pkgtool = {'deb':('DEBIAN_FRONTEND=noninteractive apt-get --reinstall -q=2 --force-yes -y install %s',
                      ('%s=%s', ['name', 'version']))}
    svcre = re.compile("/etc/.*/[SK]\d\d(?P<name>\S+)")

    def __init__(self, cfg, setup):
        Bcfg2.Client.Toolset.Toolset.__init__(self, cfg, setup)
        self.cfg = cfg
        self.logger.debug('Configuring Debian toolset')
        os.environ["DEBIAN_FRONTEND"] = 'noninteractive'
        # dup /dev/null on top of stdin
        null = open('/dev/null', 'w+')
        os.dup2(null.fileno(), sys.__stdin__.fileno())
        self.saferun("dpkg --force-confold --configure -a")
        if not self.setup['build']:
            self.saferun("/usr/sbin/dpkg-reconfigure -f noninteractive debconf < /dev/null")
        self.saferun("apt-get clean")
        self.saferun("apt-get -q=2 -y update")
        self.installed = {}
        self.pkgwork = {'add':[], 'update':[], 'remove':[]}
        for pkg in [cpkg for cpkg in self.cfg.findall(".//Package") if not cpkg.attrib.has_key('type')]:
            pkg.set('type', 'deb')
        self.Refresh()
        self.logger.debug('Done configuring Debian toolset')

    def Refresh(self):
        '''Refresh memory hashes of packages'''
        apt_pkg.init()
        cache = apt_pkg.GetCache()
        self.installed = {}
        for pkg in cache.Packages:
            if pkg.CurrentVer:
                self.installed[pkg.Name] = pkg.CurrentVer.VerStr

    # implement entry (Verify|Install) ops
    def VerifyService(self, entry):
        '''Verify Service status for entry'''
        rawfiles = glob.glob("/etc/rc*.d/*%s" % (entry.get('name')))
        files = [filename for filename in rawfiles if self.svcre.match(filename).group('name') == entry.get('name')]
        if entry.get('status') == 'off':
            if files:
                return False
            else:
                return True
        else:
            if files:
                return True
            else:
                return False

    def InstallService(self, entry):
        '''Install Service for entry'''
        cmdrc = 1
        self.logger.info("Installing Service %s" % (entry.get('name')))
        try:
            os.stat('/etc/init.d/%s' % entry.get('name'))
        except OSError:
            self.logger.debug("Init script for service %s does not exist" % entry.get('name'))
            return False
        
        if entry.attrib['status'] == 'off':
            if self.setup['dryrun']:
                self.logger.info("Disabling service %s" % (entry.get('name')))
            else:
                self.saferun("/etc/init.d/%s stop" % (entry.get('name')))
                cmdrc = self.saferun("/usr/sbin/update-rc.d -f %s remove" % entry.get('name'))[0]
        else:
            if self.setup['dryrun']:
                self.logger.info("Enabling service %s" % (entry.attrib['name']))
            else:
                cmdrc = self.saferun("/usr/sbin/update-rc.d %s defaults" % (entry.attrib['name']))[0]
        if cmdrc:
            return False
        return True

    def VerifyPackage(self, entry, modlist):
        '''Verify package for entry'''
        if not entry.attrib.has_key('version'):
            self.logger.info("Cannot verify unversioned package %s" %
                             (entry.attrib['name']))
            return False
        if self.installed.has_key(entry.attrib['name']):
            if self.installed[entry.attrib['name']] == entry.attrib['version']:
                if not self.setup['quick']:
                    output = self.saferun("/usr/bin/debsums -s %s" % entry.get('name'))[1]
                    if [filename for filename in output if filename not in modlist]:
                        return False
                return True
        return False

    def Inventory(self):
        '''Do standard inventory plus debian extra service check'''
        Bcfg2.Client.Toolset.Toolset.Inventory(self)
        allsrv = []
        [allsrv.append(self.svcre.match(fname).group('name')) for fname in
         glob.glob("/etc/rc[12345].d/S*") if self.svcre.match(fname).group('name') not in allsrv]
        self.logger.debug("Found active services:")
        self.logger.debug(allsrv)
        csrv = self.cfg.findall(".//Service")
        [allsrv.remove(svc.get('name')) for svc in csrv if
         svc.get('status') == 'on' and svc.get('name') in allsrv]
        self.extra_services = allsrv

    def HandleExtra(self):
        '''Deal with extra configuration detected'''
        if self.setup['dryrun']:
            return
        
        if len(self.pkgwork) > 0:
            if self.setup['remove'] in ['all', 'packages']:
                self.logger.info('Removing packages:')
                self.logger.info(self.pkgwork['remove'])
                if not self.saferun("apt-get remove -y --force-yes %s" % " ".join(self.pkgwork['remove']))[0]:
                    self.pkgwork['remove'] = []
            else:
                self.logger.info("Need to remove packages:")
                self.logger.info(self.pkgwork['remove'])
                
        if len(self.extra_services) > 0:
            if self.setup['remove'] in ['all', 'services']:
                self.logger.info('Removing services:')
                self.logger.info(self.extra_services)
                [self.extra_services.remove(serv) for serv in self.extra_services if
                 not self.saferun("rm -f /etc/rc*.d/S??%s" % serv)[0]]
            else:
                self.logger.info('Need to remove services:')
                self.logger.info(self.extra_services)