summaryrefslogtreecommitdiffstats
path: root/src/lib/Client/Tools/SMF.py
blob: 399418986d855602c77a5b5f9e9e568be052dd6c (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
'''SMF support for Bcfg2'''
__revision__ = '$Revision$'

import glob, os
import Bcfg2.Client.Tools

class SMF(Bcfg2.Client.Tools.Tool):
    '''Support for Solaris SMF Services'''
    __handles__ = [('Service', 'smf')]
    __execs__ = ['/usr/sbin/svcadm', '/usr/bin/svcs']
    name = 'SMF'
    __req__ = {'Service':['name', 'status']}
    __ireq__ = {'Service': ['name', 'status', 'FMRI']}

    def GetFMRI(self, entry):
        '''Perform FMRI resolution for service'''
        if not 'FMRI' in entry.attrib:
            name = self.cmd.run("/usr/bin/svcs -H -o FMRI %s 2>/dev/null" % \
                                entry.get('name'))[1]
            if name:
                entry.set('FMRI', name[0])
                return True
            else:
                self.logger.info('Failed to locate FMRI for service %s' % \
                                 entry.get('name'))
                return False
        return True
    
    def VerifyService(self, entry, _):
        '''Verify SMF Service Entry'''
        if not self.GetFMRI(entry):
            self.logger.error("smf service %s doesn't have FMRI set" % \
                              entry.get('name'))
            return False
        if entry.get('FMRI').startswith('lrc'):
            filename = entry.get('FMRI').split('/')[-1]
            # this is a legacy service
            gname = "/etc/rc*.d/%s" % filename
            files = glob.glob(gname.replace('_', '.'))
            if files:
                self.logger.debug("Matched %s with %s" % \
                                  (entry.get("FMRI"), ":".join(files)))
                return entry.get('status') == 'on'
            else:
                self.logger.debug("No service matching %s" % (entry.get("FMRI")))
                return entry.get('status') == 'off'
        try:
            srvdata = self.cmd.run("/usr/bin/svcs -H -o STA %s" % \
                                   entry.get('FMRI'))[1][0].split()
        except IndexError:
            # Ocurrs when no lines are returned (service not installed)
            return False

        if entry.get('status') == 'on':
            return srvdata[0] == 'ON'
        else:
            return srvdata[0] in ['OFF', 'UN', 'MNT', 'DIS', 'DGD']

    def InstallService(self, entry):
        '''Install SMF Service Entry'''
        self.logger.info("Installing Service %s" % (entry.get('name')))
        if entry.get('status') == 'off':
            if entry.get("FMRI").startswith('lrc'):
                try:
                    loc = entry.get("FMRI")[4:].replace('_', '.')
                    self.logger.debug("Renaming file %s to %s" % \
                                      (loc, loc.replace('/S', '/DISABLED.S')))
                    os.rename(loc, loc.replace('/S', '/DISABLED.S'))
                    return True
                except OSError:
                    self.logger.error("Failed to rename init script %s" % (loc))
                    return False
            else:
                cmdrc = self.cmd.run("/usr/sbin/svcadm disable %s" % \
                                     (entry.get('FMRI')))[0]
        else:
            if entry.get('FMRI').startswith('lrc'):
                loc = entry.get("FMRI")[4:].replace('_', '.')
                try:
                    os.stat(loc.replace('/S', '/Disabled.'))
                    self.logger.debug("Renaming file %s to %s" % \
                                      (loc.replace('/S', '/DISABLED.S'), loc))
                    os.rename(loc.replace('/S', '/DISABLED.S'), loc)
                    cmdrc = 0
                except OSError:
                    self.logger.debug("Failed to rename %s to %s" \
                                      % (loc.replace('/S', '/DISABLED.S'), loc))
                    cmdrc = 1
            else:
                srvdata = self.cmd.run("/usr/bin/svcs -H -o STA %s" %
                                       entry.get('FMRI'))[1] [0].split()
                if srvdata[0] == 'MNT':
                    cmdarg = 'clear'
                else:
                    cmdarg = 'enable'
                cmdrc = self.cmd.run("/usr/sbin/svcadm %s -r %s" % \
                                     (cmdarg, entry.get('FMRI')))[0]
        return cmdrc == 0

    def Remove(self, svcs):
        '''Remove Extra SMF entries'''
        # Extra service entry removal is nonsensical
        # Extra service entries should be reflected in config, even if disabled
        pass

    def FindExtra(self):
        '''Find Extra SMF Services'''
        allsrv = [name for name, version in \
                  [srvc.split() for srvc in
                   self.cmd.run("/usr/bin/svcs -a -H -o FMRI,STATE")[1]]
                  if version != 'disabled']

        [allsrv.remove(svc.get('FMRI')) for svc in self.getSupportedEntries() \
         if svc.get("FMRI") in allsrv]
        return [Bcfg2.Client.XML.Element("Service", type='smf', name=name) \
                for name in allsrv]

    def BundleUpdated(self, bundle, states):
        '''Restart smf services'''
        for entry in [entry for entry in bundle if self.handlesEntry(entry)]:
            if not self.canInstall(entry):
                self.logger.error("Insufficient information to restart service %s" % \
                                  (entry.get('name')))
            else:
                if entry.get("FMRI").startswith('lrc'):
                    if entry.get('status') == 'on':
                        self.logger.info("Restarting smf/lrc service %s"%(entry.get("name")))
                        self.cmd.run("/etc/init.d/%s %s" % (entry.get('name'),
                                                            entry.get('reload', 'reload')))
                else:
                    if entry.get('status') == 'on':
                        self.logger.info("Restarting smf service %s" % (entry.get("FMRI")))
                        self.cmd.run("/usr/sbin/svcadm restart %s" % (entry.get("FMRI")))
                    else:
                        self.cmd.run("/usr/sbin/svcadm disable %s" % (entry.get("FMRI")))