209 |
- |
1 |
def ConfigureService(serviceName, description, lsbStartDep, lsbStopDep, lsbStartBefore,
|
|
|
2 |
lsbStopAfter, chkcfgStartLevel, chkcfgStopLevel):
|
|
|
3 |
"""
|
|
|
4 |
Configure a service using the program appropriate for the current system.
|
|
|
5 |
Right now we support insserv, chkconfig, and update-rc.d
|
|
|
6 |
|
|
|
7 |
******** READ ME ... IMPORTANT!
|
|
|
8 |
********
|
|
|
9 |
******** This function expects the component using it to have the initinfo scripts in
|
|
|
10 |
******** initinfo/initinfo.*. They shouldn't be installed, they should just be included
|
|
|
11 |
******** in the component. Without them, it will fail.
|
|
|
12 |
********
|
|
|
13 |
|
|
|
14 |
@param serviceName: The service name, matches the script name
|
|
|
15 |
@param description: Text description of the service. Single-line only
|
|
|
16 |
@param lsbStartDep: Space separated list of services that must be started *before* this service.
|
|
|
17 |
@param lsbStopDep: Space separated list of services that must be stopped *after* this service.
|
|
|
18 |
@param lsbStartBefore: Space separated list of reverse deps. This package must start before these.
|
|
|
19 |
@param lsbStopAfter: Space separated list of reverse deps. This package must stop after these.
|
|
|
20 |
@param chkcfgStartLevel: The start number for chkconfig or update-rc.d scripts
|
|
|
21 |
@param chkcfgStopLevel: The stop number for chkconfig or update-rc.d scripts
|
|
|
22 |
"""
|
|
|
23 |
scriptFile = INITSCRIPTDIR/serviceName
|
|
|
24 |
if not INITSCRIPTDIR or not scriptFile.exists():
|
|
|
25 |
# TODO: Raise a dialog informing the user that we are unable to add init script links.
|
|
|
26 |
# TODO: This can take the place of Workstation's current message for Gentoo and Arch
|
|
|
27 |
# TODO: systems.
|
|
|
28 |
return
|
|
|
29 |
script = scriptFile.text()
|
|
|
30 |
|
|
|
31 |
(initType, initProgram) = InitConfigProgram()
|
|
|
32 |
|
|
|
33 |
if not initType:
|
|
|
34 |
# We can't use a program to do it for us, lay down the links ourselves.
|
|
|
35 |
if not INITDIR:
|
|
|
36 |
# TODO: Raise a dialog informing the user that we are unable to add init script links.
|
|
|
37 |
# TODO: This can take the place of Workstation's current message for Gentoo and Arch
|
|
|
38 |
# TODO: systems.
|
|
|
39 |
log.Warn('INITDIR has not been set. No rc?.d style dirs '
|
|
|
40 |
'to populate.')
|
|
|
41 |
return
|
|
|
42 |
|
|
|
43 |
script = INITSCRIPTDIR/serviceName
|
|
|
44 |
pattern = 'rc%(runlevel)d.d/%(letter)s%(priority)02d%(name)s'
|
|
|
45 |
|
|
|
46 |
for runlevel in (2, 3, 5):
|
|
|
47 |
# Build symlinks for this runlevel
|
|
|
48 |
startLink = path(INITDIR/(pattern % {'runlevel': runlevel, 'letter': 'S',
|
|
|
49 |
'priority': chkcfgStartLevel, 'name': serviceName}))
|
|
|
50 |
stopLink = path(INITDIR/(pattern % {'runlevel': runlevel, 'letter': 'K',
|
|
|
51 |
'priority': chkcfgStopLevel, 'name': serviceName}))
|
|
|
52 |
try:
|
|
|
53 |
script.symlink(startLink)
|
|
|
54 |
except OSError as e:
|
|
|
55 |
pass # Okay if it already exists
|
|
|
56 |
try:
|
|
|
57 |
script.symlink(stopLink)
|
|
|
58 |
except OSError as e:
|
|
|
59 |
pass # Okay if it already exists
|
|
|
60 |
|
|
|
61 |
# Register files with the installer. It will clean them up on uninstall.
|
|
|
62 |
inst.RegisterFile(startLink)
|
|
|
63 |
inst.RegisterFile(stopLink)
|
|
|
64 |
|
|
|
65 |
if initType == 'insserv':
|
|
|
66 |
# Add the insserv style header and add our service
|
|
|
67 |
initheader = inst.GetFileText('initinfo/initinfo.lsb')
|
|
|
68 |
initheader = re.sub('@@SERVICE_NAME@@', serviceName, initheader)
|
|
|
69 |
initheader = re.sub('@@LSB_SERVICE_START_DEP@@', lsbStartDep, initheader)
|
|
|
70 |
initheader = re.sub('@@LSB_SERVICE_STOP_DEP@@', lsbStopDep, initheader)
|
|
|
71 |
initheader = re.sub('@@LSB_SERVICE_START_BEFORE_DEP@@', lsbStartBefore, initheader)
|
|
|
72 |
initheader = re.sub('@@LSB_SERVICE_STOP_AFTER_DEP@@', lsbStopAfter, initheader)
|
|
|
73 |
initheader = re.sub('@@SERVICE_DESCRIPTION@@', description, initheader)
|
|
|
74 |
txt = re.sub('# VMWARE_INIT_INFO', initheader, script, re.DOTALL)
|
|
|
75 |
scriptFile.write_text(txt)
|
|
|
76 |
inst.RunCommand('/bin/sh', '-c', '%s -f %s >/dev/null 2>&1' % (initProgram, serviceName), ignoreErrors=True)
|
|
|
77 |
|
|
|
78 |
if initType == 'chkconfig':
|
|
|
79 |
# Add the chkconfig style header and add our service
|
|
|
80 |
initheader = inst.GetFileText('initinfo/initinfo.chkconfig')
|
|
|
81 |
initheader = re.sub('@@CHKCFG_START_LEVEL@@', str(chkcfgStartLevel), initheader)
|
|
|
82 |
initheader = re.sub('@@CHKCFG_STOP_LEVEL@@', str(chkcfgStopLevel), initheader)
|
|
|
83 |
initheader = re.sub('@@SERVICE_DESCRIPTION@@', description, initheader)
|
|
|
84 |
txt = re.sub('# VMWARE_INIT_INFO', initheader, script, re.DOTALL)
|
|
|
85 |
scriptFile.write_text(txt)
|
|
|
86 |
inst.RunCommand(initProgram, '--add', serviceName, ignoreErrors=True)
|
|
|
87 |
|
|
|
88 |
if initType == 'update-rc.d':
|
|
|
89 |
# Add the insserv style header and add our service
|
|
|
90 |
initheader = inst.GetFileText('initinfo/initinfo.updaterc')
|
|
|
91 |
initheader = re.sub('@@SERVICE_NAME@@', serviceName, initheader)
|
|
|
92 |
initheader = re.sub('@@LSB_SERVICE_START_DEP@@', lsbStartDep, initheader)
|
|
|
93 |
initheader = re.sub('@@LSB_SERVICE_STOP_DEP@@', lsbStopDep, initheader)
|
|
|
94 |
initheader = re.sub('@@LSB_SERVICE_START_BEFORE_DEP@@', lsbStartBefore, initheader)
|
|
|
95 |
initheader = re.sub('@@LSB_SERVICE_STOP_AFTER_DEP@@', lsbStopAfter, initheader)
|
|
|
96 |
initheader = re.sub('@@SERVICE_DESCRIPTION@@', description, initheader)
|
|
|
97 |
txt = re.sub('# VMWARE_INIT_INFO', initheader, script, re.DOTALL)
|
|
|
98 |
scriptFile.write_text(txt)
|
|
|
99 |
inst.RunCommand(initProgram, serviceName,
|
|
|
100 |
'start', chkcfgStartLevel, '2', '3', '4', '.',
|
|
|
101 |
'stop', chkcfgStopLevel, '0', '6', '.', ignoreErrors=True)
|
|
|
102 |
|
|
|
103 |
log.Info('Installed Service: %s' % serviceName)
|
|
|
104 |
|
|
|
105 |
def DeconfigureService(serviceName):
|
|
|
106 |
(initType, initProgram) = InitConfigProgram()
|
|
|
107 |
if not initType:
|
|
|
108 |
# The links have been registered with the installer. It will remove them on
|
|
|
109 |
# uninstall.
|
|
|
110 |
pass
|
|
|
111 |
|
|
|
112 |
if initType == 'insserv':
|
|
|
113 |
inst.RunCommand('/bin/sh', '-c', '%s -f -r %s >/dev/null 2>&1' % (initProgram, serviceName), ignoreErrors=True)
|
|
|
114 |
if initType == 'chkconfig':
|
|
|
115 |
inst.RunCommand(initProgram, '--del', serviceName, ignoreErrors=True)
|
|
|
116 |
if initType == 'update-rc.d':
|
|
|
117 |
inst.RunCommand(initProgram, '-f', serviceName, 'remove', ignoreErrors=True)
|
|
|
118 |
|
|
|
119 |
log.Info('Uninstalled Service: %s' % serviceName)
|
|
|
120 |
|
|
|
121 |
def InitConfigProgram():
|
|
|
122 |
"""
|
|
|
123 |
Scan the system to try and guess the program that sets up the init script links.
|
|
|
124 |
On RHEL, it's chkconfig, on SuSE it's insserv, and on Ubuntu it's update-rc.d.
|
|
|
125 |
|
|
|
126 |
NOTE: Don't use insserv on Ubuntu per bug 776485. Ubuntu so very wisely ships
|
|
|
127 |
it but expects developers not to use it.
|
|
|
128 |
"""
|
|
|
129 |
|
|
|
130 |
# First, check for update-rc.d b/c we want to use it instead
|
|
|
131 |
# of insserv on Ubuntu and Debian systems.
|
|
|
132 |
if path('/usr/sbin/update-rc.d').isexe():
|
|
|
133 |
return ('update-rc.d', '/usr/sbin/update-rc.d')
|
|
|
134 |
elif path('/sbin/update-rc.d').isexe():
|
|
|
135 |
return ('update-rc.d', '/sbin/update-rc.d')
|
|
|
136 |
elif (_which('update-rc.d')):
|
|
|
137 |
return ('update-rc.d', _which('update-rc.d'))
|
|
|
138 |
|
|
|
139 |
if path('/sbin/insserv').isexe():
|
|
|
140 |
return ('insserv', '/sbin/insserv')
|
|
|
141 |
elif _which('insserv'):
|
|
|
142 |
return ('insserv', _which('insserv'))
|
|
|
143 |
|
|
|
144 |
if path('/sbin/chkconfig').isexe():
|
|
|
145 |
return ('chkconfig', '/sbin/chkconfig')
|
|
|
146 |
elif (_which('chkconfig')):
|
|
|
147 |
return ('chkconfig', _which('chkconfig'))
|
|
|
148 |
|
|
|
149 |
# XXX: Add support for upstart in the future.
|
|
|
150 |
|
|
|
151 |
return (None, None)
|
|
|
152 |
|
|
|
153 |
def _which(program):
|
|
|
154 |
"""
|
|
|
155 |
Gets the PATH environment variable and checks for program
|
|
|
156 |
in order.
|
|
|
157 |
|
|
|
158 |
@param program: Executable to search for
|
|
|
159 |
@returns: Full path if found and executable, None otherwise
|
|
|
160 |
"""
|
|
|
161 |
# XXX: Borrowed from util/shell.py. This should be broken into a
|
|
|
162 |
# utility file to be used by both components and the main code.
|
|
|
163 |
systemPath = ENV['PATH']
|
|
|
164 |
paths = systemPath.split(':')
|
|
|
165 |
for p in paths:
|
|
|
166 |
fullPath = path(p)/program
|
|
|
167 |
if fullPath.isexe():
|
|
|
168 |
return str(fullPath) # Return a string, not a path object
|
|
|
169 |
|
|
|
170 |
return None
|