1
# This is the bcfg2 support for solaris
2
'''This provides bcfg2 support for Solaris'''
3
__revision__ = '$Revision: 2160 $'
7
from os import stat, unlink
8
from re import compile as regcompile
9
from tempfile import mktemp
11
from Bcfg2.Client.Toolset import Toolset
27
class ToolsetImpl(Toolset):
28
'''This class implelements support for SYSV/blastware/encap packages
29
and standard SMF services'''
30
pkgtool = {'sysv':("/usr/sbin/pkgadd %s -d %%s -n %%%%s", (("%s", ["name"]))),
31
'blast':("/opt/csw/bin/pkg-get install %s", ("%s", ["name"])),
32
'encap':("/local/sbin/epkg -l -f -q %s", ("%s", ["url"]))}
33
splitter = regcompile('.*/(?P<name>[\w-]+)\-(?P<version>[\w\.-]+)')
37
def __init__(self, cfg, setup):
38
Toolset.__init__(self, cfg, setup)
39
self.extra_services = []
41
self.noaskname = mktemp()
43
open(self.noaskname, 'w+').write(noask)
44
self.pkgtool['sysv'] = (self.pkgtool['sysv'][0] % ("-a %s" % (self.noaskname)), self.pkgtool['sysv'][1])
46
self.pkgtool['sysv'] = (self.pkgtool['sysv'][0] % (""), self.pkgtool['sysv'][1])
48
stat("/opt/csw/bin/pkg-get")
49
self.saferun("/opt/csw/bin/pkg-get -U > /dev/null")
53
for pkg in [cpkg for cpkg in self.cfg.findall(".//Package") if not cpkg.attrib.has_key('type')]:
54
pkg.set('type', 'sysv')
55
for pkg in [cpkg for cpkg in self.cfg.findall(".//Package") if cpkg.get('type') == 'sysv']:
56
if pkg.attrib.has_key('url'):
57
pkg.set('url', '/'.join(pkg.get('url').split('/')[:-1]))
58
pkg.set('type', "sysv-%s" % (pkg.get('url')))
59
if not self.pkgtool.has_key(pkg.get('type')):
60
self.pkgtool[pkg.get('type')] = (self.pkgtool['sysv'][0] % (pkg.get('url')),
61
self.pkgtool['sysv'][1])
64
'''Refresh memory hashes of packages'''
67
# Build list of packages
68
lines = self.saferun("/usr/bin/pkginfo -x")[1]
70
version = lines.pop().split()[1]
71
pkg = lines.pop().split()[0]
72
self.installed[pkg] = version
73
self.ptypes[pkg] = 'sysv'
74
# try to find encap packages
75
for pkg in glob("/local/encap/*"):
76
match = self.splitter.match(pkg)
78
self.installed[match.group('name')] = match.group('version')
79
self.ptypes[match.group('name')] = 'encap'
81
print "Failed to split name %s" % pkg
82
#print self.installed.keys()
84
def VerifyService(self, entry):
85
'''Verify Service status for entry'''
86
if not entry.attrib.has_key('FMRI'):
87
name = self.saferun("/usr/bin/svcs -H -o FMRI %s 2>/dev/null" % entry.get('name'))[1]
89
entry.set('FMRI', name[0])
91
self.logger.info('Failed to locate FMRI for service %s' % entry.get('name'))
93
if entry.get('FMRI').startswith('lrc'):
94
filename = entry.get('FMRI').split('/')[-1]
95
# this is a legacy service
96
gname = "/etc/rc*.d/%s" % filename
97
files = glob(gname.replace('_', '.'))
99
self.logger.debug("Matched %s with %s" % \
100
(entry.get("FMRI"), ":".join(files)))
101
return entry.get('status') == 'on'
103
self.logger.debug("No service matching %s" % (entry.get("FMRI")))
104
return entry.get('status') == 'off'
106
srvdata = self.saferun("/usr/bin/svcs -H -o STA %s" % entry.attrib['name'])[1][0].split()
108
# Ocurrs when no lines are returned (service not installed)
111
if entry.get('status') == 'on':
112
return srvdata[0] == 'ON'
114
return srvdata[0] in ['OFF', 'UN', 'MNT', 'DIS', 'DGD']
116
def InstallService(self, entry):
117
'''Install Service entry'''
118
if not entry.attrib.has_key('status'):
119
self.logger.info('Insufficient information for Service %s; cannot Install' % entry.get('name'))
121
if not entry.attrib.has_key('FMRI'):
122
name = self.saferun("/usr/bin/svcs -H -o FMRI %s 2>/dev/null" % entry.get('name'))[1]
124
entry.set('FMRI', name[0])
126
self.logger.info('Failed to locate FMRI for service %s' % entry.get('name'))
128
self.logger.info("Installing Service %s" % (entry.get('name')))
129
if entry.attrib['status'] == 'off':
130
if self.setup['dryrun']:
131
print "Disabling Service %s" % (entry.get('name'))
133
if entry.get("FMRI").startswith('lrc'):
135
loc = entry.get("FMRI")[4:].replace('_', '.')
136
self.logger.debug("Renaming file %s to %s" % \
137
(loc, loc.replace('/S', '/DISABLED.S')))
138
os.rename(loc, loc.replace('/S', '/DISABLED.S'))
141
self.logger.error("Failed to rename init script %s" % (loc))
143
cmdrc = self.saferun("/usr/sbin/svcadm disable -r %s" % (entry.attrib['FMRI']))[0]
145
if self.setup['dryrun']:
146
print "Enabling Service %s" % (entry.attrib['name'])
148
if entry.get('FMRI').startswith('lrc'):
149
loc = entry.get("FMRI")[4:].replace('_', ',')
151
stat(loc.replace('/S', '/Disabled.'))
152
self.logger.debug("Renaming file %s to %s" % \
153
(loc.replace('/S', '/DISABLED.S'), loc))
154
os.rename(loc.replace('/S', '/DISABLED.S'), loc)
157
self.logger.debug("Failed to rename %s to %s" \
158
% (loc.replace('/S', '/DISABLED.S'), loc))
161
cmdrc = self.saferun("/usr/sbin/svcadm enable -r %s" % (entry.attrib['FMRI']))[0]
164
def VerifyPackage(self, entry, modlist):
165
'''Verify Package status for entry'''
166
if not entry.get('version'):
167
self.logger.info("Insufficient information of Package %s; cannot Verify" % entry.get('name'))
169
if entry.get('type') in ['sysv', 'blast'] or entry.get('type')[:4] == 'sysv':
170
cmdrc = self.saferun("/usr/bin/pkginfo -q -v \"%s\" %s" % (entry.get('version'), entry.get('name')))[0]
171
elif entry.get('type') in ['encap']:
172
cmdrc = self.saferun("/local/sbin/epkg -q -S -k %s-%s >/dev/null" %
173
(entry.get('name'), entry.get('version')))[0]
175
self.logger.debug("Package %s version incorrect" % entry.get('name'))
177
if self.setup['quick'] or entry.get('type') == 'encap' or \
178
entry.attrib.get('verify', 'true') == 'false':
180
(vstat, odata) = self.saferun("/usr/sbin/pkgchk -n %s" % (entry.get('name')))
184
output = [line for line in odata if line[:5] == 'ERROR']
185
if len([name for name in output if name.split()[-1] not in modlist]):
186
self.logger.debug("Package %s content verification failed" % \
193
'''Do standard inventory plus debian extra service check'''
194
Toolset.Inventory(self)
195
allsrv = [name for name, version in [ srvc.strip().split() for srvc in
196
self.saferun("/usr/bin/svcs -a -H -o FMRI,STATE")[1] ]
197
if version != 'disabled']
198
csrv = self.cfg.findall(".//Service")
199
# need to build a service name map. services map to a fullname if they are already installed
201
name = self.saferun("/usr/bin/svcs -H -o FMRI %s 2>/dev/null" % srv.get('name'))[1]
203
srv.set('FMRI', name[0])
205
self.logger.info("Failed to locate FMRI for service %s" % srv.get('name'))
206
#nsrv = [ r for r in [ popen("/usr/bin/svcs -H -o FMRI %s " % s).read().strip() for s in csrv ] if r ]
207
[allsrv.remove(svc.get('FMRI')) for svc in csrv if
208
svc.get('status') == 'on' and svc.get("FMRI") in allsrv]
209
self.extra_services = allsrv
211
def HandleExtra(self):
212
'''Deal with extra configuration detected'''
213
if len(self.pkgwork) > 0:
214
if self.setup['remove'] in ['all', 'packages']:
215
self.logger.info("Removing packages: %s" % (self.pkgwork['remove']))
216
sysvrmpkgs = [pkg for pkg in self.pkgwork['remove'] if self.ptypes[pkg] == 'sysv']
217
enrmpkgs = [pkg for pkg in self.pkgwork['remove'] if self.ptypes[pkg] == 'encap']
219
if not self.saferun("/usr/sbin/pkgrm -a %s -n %s" % \
220
(self.noaskname, " ".join(sysvrmpkgs)))[0]:
221
[self.pkgwork['remove'].remove(pkg) for pkg in sysvrmpkgs]
223
if not self.saferun("/local/sbin/epkg -l -q -r %s" % " ".join(enrmpkgs))[0]:
224
[self.pkgwork['remove'].remove(pkg) for pkg in enrmpkgs]
226
self.logger.info("Need to remove packages: %s" % (self.pkgwork['remove']))
227
if len(self.extra_services) > 0:
228
self.logger.info("Here")
229
self.logger.info('removal mode is: %s' % (self.setup))
230
if self.setup['remove'] in ['all', 'services']:
231
self.logger.info("Removing services: %s" % (self.extra_services))
232
for service in [svc for svc in self.extra_services if not svc.startswith('lrc:')]:
233
if not self.saferun("/usr/sbin/svcadm disable %s" % service)[0]:
234
self.extra_services.remove(service)
235
for svc in [svc for svc in self.extra_services if svc.startswith('lrc:')]:
236
loc = svc[4:].replace('_', '.')
237
self.logger.info("Renaming file %s to %s" % \
238
(loc, loc.replace('/S', '/DISABLED.S')))
240
os.rename(loc, loc.replace('/S', '/DISABLED.S'))
241
self.extra_services.remove(svc)
243
self.logger.error("Failed to rename %s" % loc)
246
self.logger.info("Need to remove services: %s" % (self.extra_services))
249
'''Local install method handling noaskfiles'''
250
Toolset.Install(self)
252
unlink(self.noaskname)
256
def RestartService(self, service):
257
'''Restart a service'''
258
if service.get("FMRI").startswith('lrc'):
259
Toolset.RestartService(self, service)
261
if service.get('status') == 'on':
262
self.logger.debug("Restarting service %s" % (service.get("FMRI")))
263
self.saferun("svcadm restart %s" % (service.get("FMRI")))