summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Client/Tools/SMF.py
blob: 4409b40f3b8ffccdf4172f5f4e6ec7cde23df1a8 (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
"""SMF support for Bcfg2"""

import glob
import os

import Bcfg2.Client.Tools


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

    def get_svc_command(self, service, action):
        if service.get('type') == 'lrc':
            return Bcfg2.Client.Tools.SvcTool.get_svc_command(self,
                                                              service, action)
        if action == 'stop':
            return "/usr/sbin/svcadm disable %s" % (service.get('FMRI'))
        elif action == 'restart':
            return "/usr/sbin/svcadm restart %s" % (service.get('FMRI'))
        elif action == 'start':
            return "/usr/sbin/svcadm enable %s" % (service.get('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:
            # Occurs when no lines are returned (service not installed)
            return False

        entry.set('current_status', srvdata[0])
        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']

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