blob: 986c2f016d554e183abe3fc22746468f6589bd50 [file] [log] [blame]
Frederic Lepiedae55c182017-04-14 08:31:34 +02001#!/usr/bin/python3
2# autopkgtest check: enable/disable/configure units
3# (C) 2015 Canonical Ltd.
4# Author: Martin Pitt <martin.pitt@ubuntu.com>
5
6import unittest
7import subprocess
8import os
9import sys
10import tempfile
11from glob import glob
12
13system_unit_dir = subprocess.check_output(
14 ['pkg-config', '--variable=systemdsystemunitdir', 'systemd'],
15 universal_newlines=True).strip()
16systemd_sysv_install = os.path.join(os.path.dirname(system_unit_dir),
17 'systemd-sysv-install')
18
19
20class EnableTests(unittest.TestCase):
21 def tearDown(self):
22 # remove all traces from our test unit
23 f = glob(system_unit_dir + '/test_enable*.service')
24 f += glob(system_unit_dir + '/*/test_enable*.service')
25 f += glob('/etc/systemd/system/test_enable*.service')
26 f += glob('/etc/systemd/system/*/test_enable*.service')
27 f += glob('/etc/init.d/test_enable*')
28 f += glob('/etc/rc?.d/???test_enable*')
29 [os.unlink(i) for i in f]
30 subprocess.check_call(['systemctl', 'daemon-reload'])
31
32 def create_unit(self, suffix='', enable=False):
33 '''Create a test unit'''
34
35 unit = os.path.join(system_unit_dir,
36 'test_enable%s.service' % suffix)
37 with open(unit, 'w') as f:
38 f.write('''[Unit]
39Description=Testsuite unit %s
40[Service]
41ExecStart=/bin/echo hello
42[Install]
43WantedBy=multi-user.target
44''' % suffix)
45
46 if enable:
47 os.symlink(unit, '/etc/systemd/system/multi-user.target.wants/' +
48 os.path.basename(unit))
49
50 return unit
51
52 def create_sysv(self, suffix='', enable=False):
53 '''Create a test SysV script'''
54
55 script = '/etc/init.d/test_enable%s' % suffix
56 with open(script, 'w') as f:
57 f.write('''/bin/sh
58### BEGIN INIT INFO
59# Provides: test_enable%s
60# Required-Start: $remote_fs $syslog
61# Required-Stop: $remote_fs $syslog
62# Default-Start: 2 3 4 5
63# Default-Stop: 0 1 6
64# Short-Description: Testsuite script%s
65### END INIT INFO
66
67echo hello
68''' % (suffix, suffix))
69 os.chmod(script, 0o755)
70
71 if enable:
72 subprocess.check_call(
73 [systemd_sysv_install, 'enable', os.path.basename(script)])
74
75 def assertEnabled(self, enabled, unit='test_enable.service'):
76 '''assert that given unit has expected state'''
77
78 systemctl = subprocess.Popen(['systemctl', 'is-enabled', unit],
79 stdout=subprocess.PIPE,
80 universal_newlines=True)
81 out = systemctl.communicate()[0].strip()
82 if enabled:
83 self.assertEqual(systemctl.returncode, 0)
84 self.assertEqual(out, 'enabled')
85 else:
86 self.assertEqual(systemctl.returncode, 1)
87 self.assertEqual(out, 'disabled')
88
89 def test_unit_enable(self):
90 '''no sysv: enable unit'''
91
92 self.create_unit()
93 self.assertEnabled(False)
94 # also works without .service suffix
95 self.assertEnabled(False, unit='test_enable')
96
97 subprocess.check_call(['systemctl', 'enable', 'test_enable'])
98
99 self.assertEnabled(True)
100 # also works without .service suffix
101 self.assertEnabled(True, unit='test_enable')
102
103 l = '/etc/systemd/system/multi-user.target.wants/test_enable.service'
104 self.assertTrue(os.path.islink(l))
105 self.assertEqual(os.readlink(l),
106 system_unit_dir + '/test_enable.service')
107
108 # enable should be idempotent
109 subprocess.check_call(['systemctl', 'enable', 'test_enable.service'])
110 self.assertEnabled(True)
111
112 def test_unit_disable(self):
113 '''no sysv: disable unit'''
114
115 self.create_unit(enable=True)
116 self.assertEnabled(True)
117 # also works without .service suffix
118 self.assertEnabled(True, unit='test_enable')
119
120 subprocess.check_call(['systemctl', 'disable', 'test_enable'])
121
122 self.assertEnabled(False)
123 # also works without .service suffix
124 self.assertEnabled(False, unit='test_enable')
125
126 l = '/etc/systemd/system/multi-user.target.wants/test_enable.service'
127 self.assertFalse(os.path.islink(l))
128
129 # disable should be idempotent
130 subprocess.check_call(['systemctl', 'disable', 'test_enable.service'])
131 self.assertEnabled(False)
132
133 def test_unit_sysv_enable(self):
134 '''with sysv: enable unit'''
135
136 self.create_unit()
137 self.create_sysv()
138 self.assertEnabled(False)
139 # also works without .service suffix
140 self.assertEnabled(False, unit='test_enable')
141
142 subprocess.check_call(['systemctl', 'enable', 'test_enable'])
143
144 self.assertEnabled(True)
145 # also works without .service suffix
146 self.assertEnabled(True, unit='test_enable')
147
148 l = '/etc/systemd/system/multi-user.target.wants/test_enable.service'
149 self.assertTrue(os.path.islink(l))
150 self.assertEqual(os.readlink(l),
151 system_unit_dir + '/test_enable.service')
152
153 # enabled the sysv script
154 l = glob('/etc/rc2.d/S??test_enable')
155 self.assertEqual(len(l), 1, 'expect one symlink in %s' % repr(l))
156 self.assertEqual(os.readlink(l[0]), '../init.d/test_enable')
157
158 # enable should be idempotent
159 subprocess.check_call(['systemctl', 'enable', 'test_enable.service'])
160 self.assertEnabled(True)
161
162 def test_unit_sysv_disable(self):
163 '''with sysv: disable unit'''
164
165 self.create_unit(enable=True)
166 self.create_sysv(enable=True)
167 self.assertEnabled(True)
168 # also works without .service suffix
169 self.assertEnabled(True, unit='test_enable')
170
171 subprocess.check_call(['systemctl', 'disable', 'test_enable'])
172
173 self.assertEnabled(False)
174 # also works without .service suffix
175 self.assertEnabled(False, unit='test_enable')
176
177 l = '/etc/systemd/system/multi-user.target.wants/test_enable.service'
178 self.assertFalse(os.path.islink(l))
179
180 # disabled the sysv script
181 l = glob('/etc/rc2.d/S??test_enable')
182 self.assertEqual(l, [])
183
184 # disable should be idempotent
185 subprocess.check_call(['systemctl', 'enable', 'test_enable.service'])
186 self.assertEnabled(True)
187
188 def test_unit_alias_enable(self):
189 '''no sysv: enable unit with an alias'''
190
191 u = self.create_unit()
192 with open(u, 'a') as f:
193 f.write('Alias=test_enablea.service\n')
194
195 self.assertEnabled(False)
196
197 subprocess.check_call(['systemctl', 'enable', 'test_enable'])
198
199 self.assertEnabled(True)
200
201 # enablement symlink
202 l = '/etc/systemd/system/multi-user.target.wants/test_enable.service'
203 self.assertTrue(os.path.islink(l))
204 self.assertEqual(os.readlink(l),
205 system_unit_dir + '/test_enable.service')
206
207 # alias symlink
208 l = '/etc/systemd/system/test_enablea.service'
209 self.assertTrue(os.path.islink(l))
210 self.assertEqual(os.readlink(l),
211 system_unit_dir + '/test_enable.service')
212
213 def test_unit_alias_disable(self):
214 '''no sysv: disable unit with an alias'''
215
216 u = self.create_unit()
217 with open(u, 'a') as f:
218 f.write('Alias=test_enablea.service\n')
219 os.symlink(system_unit_dir + '/test_enable.service',
220 '/etc/systemd/system/test_enablea.service')
221
222 subprocess.check_call(['systemctl', 'disable', 'test_enable'])
223
224 self.assertEnabled(False)
225
226 # enablement symlink
227 l = '/etc/systemd/system/multi-user.target.wants/test_enable.service'
228 self.assertFalse(os.path.islink(l))
229
230 # alias symlink
231 l = '/etc/systemd/system/test_enablea.service'
232 self.assertFalse(os.path.islink(l))
233
234 def test_unit_sysv_alias_enable(self):
235 '''with sysv: enable unit with an alias'''
236
237 u = self.create_unit()
238 with open(u, 'a') as f:
239 f.write('Alias=test_enablea.service\n')
240 self.create_sysv()
241
242 self.assertEnabled(False)
243
244 subprocess.check_call(['systemctl', 'enable', 'test_enable'])
245
246 # enablement symlink
247 l = '/etc/systemd/system/multi-user.target.wants/test_enable.service'
248 self.assertTrue(os.path.islink(l))
249 self.assertEqual(os.readlink(l),
250 system_unit_dir + '/test_enable.service')
251
252 # alias symlink
253 l = '/etc/systemd/system/test_enablea.service'
254 self.assertTrue(os.path.islink(l))
255 self.assertEqual(os.readlink(l),
256 system_unit_dir + '/test_enable.service')
257
258 # enabled the sysv script
259 l = glob('/etc/rc2.d/S??test_enable')
260 self.assertEqual(len(l), 1, 'expect one symlink in %s' % repr(l))
261 self.assertEqual(os.readlink(l[0]), '../init.d/test_enable')
262
263 self.assertEnabled(True)
264
265 def test_unit_sysv_alias_disable(self):
266 '''with sysv: disable unit with an alias'''
267
268 u = self.create_unit(enable=True)
269 with open(u, 'a') as f:
270 f.write('Alias=test_enablea.service\n')
271 os.symlink(system_unit_dir + '/test_enable.service',
272 '/etc/systemd/system/test_enablea.service')
273 self.create_sysv(enable=True)
274
275 subprocess.check_call(['systemctl', 'disable', 'test_enable'])
276
277 # enablement symlink
278 l = '/etc/systemd/system/multi-user.target.wants/test_enable.service'
279 self.assertFalse(os.path.islink(l))
280
281 # alias symlink
282 l = '/etc/systemd/system/test_enablea.service'
283 self.assertFalse(os.path.islink(l))
284
285 # disabled the sysv script
286 l = glob('/etc/rc2.d/S??test_enable')
287 self.assertEqual(l, [])
288
289 self.assertEnabled(False)
290
291 def test_sysv_enable(self):
292 '''only sysv: enable'''
293
294 self.create_sysv()
295 subprocess.check_call(['systemctl', 'enable', 'test_enable'])
296
297 # enabled the sysv script
298 l = glob('/etc/rc2.d/S??test_enable')
299 self.assertEqual(len(l), 1, 'expect one symlink in %s' % repr(l))
300 self.assertEqual(os.readlink(l[0]), '../init.d/test_enable')
301
302 # enable should be idempotent
303 subprocess.check_call(['systemctl', 'enable', 'test_enable'])
304 self.assertEnabled(True)
305
306 def test_sysv_disable(self):
307 '''only sysv: disable'''
308
309 self.create_sysv(enable=True)
310 subprocess.check_call(['systemctl', 'disable', 'test_enable'])
311
312 # disabled the sysv script
313 l = glob('/etc/rc2.d/S??test_enable')
314 self.assertEqual(l, [])
315
316 # disable should be idempotent
317 subprocess.check_call(['systemctl', 'disable', 'test_enable'])
318 self.assertEnabled(False)
319
320 def test_unit_link(self):
321 '''systemctl link'''
322
323 with tempfile.NamedTemporaryFile(suffix='.service') as f:
324 f.write(b'[Unit]\n')
325 f.flush()
326 subprocess.check_call(['systemctl', 'link', f.name])
327
328 unit = os.path.basename(f.name)
329 l = os.path.join('/etc/systemd/system', unit)
330 self.assertEqual(os.readlink(l), f.name)
331
332 # disable it again
333 subprocess.check_call(['systemctl', 'disable', unit])
334 # this should also remove the unit symlink
335 self.assertFalse(os.path.islink(l))
336
337 @unittest.skip("do not work under Fedora")
338 def test_unit_enable_full_path(self):
339 '''systemctl enable a unit in a non-default path'''
340
341 with tempfile.NamedTemporaryFile(suffix='.service') as f:
342 f.write(b'''[Unit]
343Description=test
344[Service]
345ExecStart=/bin/true
346[Install]
347WantedBy=multi-user.target''')
348 f.flush()
349 unit = os.path.basename(f.name)
350
351 # now enable it
352 subprocess.check_call(['systemctl', 'enable', f.name])
353 self.assertEnabled(True, unit=unit)
354 l = os.path.join('/etc/systemd/system', unit)
355 self.assertEqual(os.readlink(l), f.name)
356 enable_l = '/etc/systemd/system/multi-user.target.wants/' + unit
357 self.assertEqual(os.readlink(enable_l), f.name)
358
359 # disable it again
360 subprocess.check_call(['systemctl', 'disable', unit])
361 # self.assertEnabled(False) does not work as now systemd does not
362 # know about the unit at all any more
363 self.assertFalse(os.path.islink(enable_l))
364 # this should also remove the unit symlink
365 self.assertFalse(os.path.islink(l))
366
367
368if __name__ == '__main__':
369 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
370 verbosity=2))