summaryrefslogtreecommitdiffstats
path: root/lib/oeqa/selftest/cases/updater_qemux86_64.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/oeqa/selftest/cases/updater_qemux86_64.py')
-rw-r--r--lib/oeqa/selftest/cases/updater_qemux86_64.py428
1 files changed, 428 insertions, 0 deletions
diff --git a/lib/oeqa/selftest/cases/updater_qemux86_64.py b/lib/oeqa/selftest/cases/updater_qemux86_64.py
new file mode 100644
index 0000000..bef6cdc
--- /dev/null
+++ b/lib/oeqa/selftest/cases/updater_qemux86_64.py
@@ -0,0 +1,428 @@
1# pylint: disable=C0111,C0325
2import os
3import logging
4import re
5import unittest
6from time import sleep
7
8from oeqa.selftest.case import OESelftestTestCase
9from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars
10from testutils import qemu_launch, qemu_send_command, qemu_terminate, \
11 akt_native_run, verifyNotProvisioned, verifyProvisioned
12
13
14class GeneralTests(OESelftestTestCase):
15 def test_credentials(self):
16 logger = logging.getLogger("selftest")
17 logger.info('Running bitbake to build core-image-minimal')
18 self.append_config('SOTA_CLIENT_PROV = "aktualizr-auto-prov"')
19 bitbake('core-image-minimal')
20 credentials = get_bb_var('SOTA_PACKED_CREDENTIALS')
21 # skip the test if the variable SOTA_PACKED_CREDENTIALS is not set
22 if credentials is None:
23 raise unittest.SkipTest("Variable 'SOTA_PACKED_CREDENTIALS' not set.")
24 # Check if the file exists
25 self.assertTrue(os.path.isfile(credentials), "File %s does not exist" % credentials)
26 deploydir = get_bb_var('DEPLOY_DIR_IMAGE')
27 imagename = get_bb_var('IMAGE_LINK_NAME', 'core-image-minimal')
28 # Check if the credentials are included in the output image
29 result = runCmd('tar -jtvf %s/%s.tar.bz2 | grep sota_provisioning_credentials.zip' %
30 (deploydir, imagename), ignore_status=True)
31 self.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output)
32
33
34class AktualizrToolsTests(OESelftestTestCase):
35
36 @classmethod
37 def setUpClass(cls):
38 super(AktualizrToolsTests, cls).setUpClass()
39 logger = logging.getLogger("selftest")
40 logger.info('Running bitbake to build aktualizr-native tools')
41 bitbake('aktualizr-native')
42
43 def test_cert_provider_help(self):
44 akt_native_run(self, 'aktualizr-cert-provider --help')
45
46 def test_cert_provider_local_output(self):
47 logger = logging.getLogger("selftest")
48 logger.info('Running bitbake to build aktualizr-ca-implicit-prov')
49 bitbake('aktualizr-ca-implicit-prov')
50 bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS', 'T'], 'aktualizr-native')
51 creds = bb_vars['SOTA_PACKED_CREDENTIALS']
52 temp_dir = bb_vars['T']
53 bb_vars_prov = get_bb_vars(['STAGING_DIR_HOST', 'libdir'], 'aktualizr-ca-implicit-prov')
54 config = bb_vars_prov['STAGING_DIR_HOST'] + bb_vars_prov['libdir'] + '/sota/sota_implicit_prov_ca.toml'
55
56 akt_native_run(self, 'aktualizr-cert-provider -c {creds} -r -l {temp} -g {config}'
57 .format(creds=creds, temp=temp_dir, config=config))
58
59 # Might be nice if these names weren't hardcoded.
60 cert_path = temp_dir + '/var/sota/import/client.pem'
61 self.assertTrue(os.path.isfile(cert_path), "Client certificate not found at %s." % cert_path)
62 self.assertTrue(os.path.getsize(cert_path) > 0, "Client certificate at %s is empty." % cert_path)
63 pkey_path = temp_dir + '/var/sota/import/pkey.pem'
64 self.assertTrue(os.path.isfile(pkey_path), "Private key not found at %s." % pkey_path)
65 self.assertTrue(os.path.getsize(pkey_path) > 0, "Private key at %s is empty." % pkey_path)
66 ca_path = temp_dir + '/var/sota/import/root.crt'
67 self.assertTrue(os.path.isfile(ca_path), "Client certificate not found at %s." % ca_path)
68 self.assertTrue(os.path.getsize(ca_path) > 0, "Client certificate at %s is empty." % ca_path)
69
70
71class AutoProvTests(OESelftestTestCase):
72
73 def setUpLocal(self):
74 layer = "meta-updater-qemux86-64"
75 result = runCmd('bitbake-layers show-layers')
76 if re.search(layer, result.output) is None:
77 # Assume the directory layout for finding other layers. We could also
78 # make assumptions by using 'show-layers', but either way, if the
79 # layers we need aren't where we expect them, we are out of luck.
80 path = os.path.abspath(os.path.dirname(__file__))
81 metadir = path + "/../../../../../"
82 self.meta_qemu = metadir + layer
83 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu)
84 else:
85 self.meta_qemu = None
86 self.append_config('MACHINE = "qemux86-64"')
87 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
88 self.qemu, self.s = qemu_launch(machine='qemux86-64')
89
90 def tearDownLocal(self):
91 qemu_terminate(self.s)
92 if self.meta_qemu:
93 runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True)
94
95 def qemu_command(self, command):
96 return qemu_send_command(self.qemu.ssh_port, command)
97
98 def test_provisioning(self):
99 print('Checking machine name (hostname) of device:')
100 stdout, stderr, retcode = self.qemu_command('hostname')
101 self.assertEqual(retcode, 0, "Unable to check hostname. " +
102 "Is an ssh daemon (such as dropbear or openssh) installed on the device?")
103 machine = get_bb_var('MACHINE', 'core-image-minimal')
104 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode())
105 # Strip off line ending.
106 value = stdout.decode()[:-1]
107 self.assertEqual(value, machine,
108 'MACHINE does not match hostname: ' + machine + ', ' + value)
109
110 verifyProvisioned(self, machine)
111
112
113class ManualControlTests(OESelftestTestCase):
114
115 def setUpLocal(self):
116 layer = "meta-updater-qemux86-64"
117 result = runCmd('bitbake-layers show-layers')
118 if re.search(layer, result.output) is None:
119 # Assume the directory layout for finding other layers. We could also
120 # make assumptions by using 'show-layers', but either way, if the
121 # layers we need aren't where we expect them, we are out of like.
122 path = os.path.abspath(os.path.dirname(__file__))
123 metadir = path + "/../../../../../"
124 self.meta_qemu = metadir + layer
125 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu)
126 else:
127 self.meta_qemu = None
128 self.append_config('MACHINE = "qemux86-64"')
129 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
130 self.append_config('SYSTEMD_AUTO_ENABLE_aktualizr = "disable"')
131 self.qemu, self.s = qemu_launch(machine='qemux86-64')
132
133 def tearDownLocal(self):
134 qemu_terminate(self.s)
135 if self.meta_qemu:
136 runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True)
137
138 def qemu_command(self, command):
139 return qemu_send_command(self.qemu.ssh_port, command)
140
141 def test_manual_run_mode_once(self):
142 """
143 Disable the systemd service then run aktualizr manually
144 """
145 sleep(20)
146 stdout, stderr, retcode = self.qemu_command('aktualizr-info')
147 self.assertIn(b'Can\'t open database', stderr,
148 'Aktualizr should not have run yet' + stderr.decode() + stdout.decode())
149
150 stdout, stderr, retcode = self.qemu_command('aktualizr once')
151
152 stdout, stderr, retcode = self.qemu_command('aktualizr-info')
153 self.assertIn(b'Fetched metadata: yes', stdout,
154 'Aktualizr should have run' + stderr.decode() + stdout.decode())
155
156
157class ImplProvTests(OESelftestTestCase):
158
159 def setUpLocal(self):
160 layer = "meta-updater-qemux86-64"
161 result = runCmd('bitbake-layers show-layers')
162 if re.search(layer, result.output) is None:
163 # Assume the directory layout for finding other layers. We could also
164 # make assumptions by using 'show-layers', but either way, if the
165 # layers we need aren't where we expect them, we are out of luck.
166 path = os.path.abspath(os.path.dirname(__file__))
167 metadir = path + "/../../../../../"
168 self.meta_qemu = metadir + layer
169 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu)
170 else:
171 self.meta_qemu = None
172 self.append_config('MACHINE = "qemux86-64"')
173 self.append_config('SOTA_CLIENT_PROV = " aktualizr-ca-implicit-prov "')
174 self.append_config('SOTA_DEPLOY_CREDENTIALS = "0"')
175 runCmd('bitbake -c cleanall aktualizr aktualizr-ca-implicit-prov')
176 self.qemu, self.s = qemu_launch(machine='qemux86-64')
177
178 def tearDownLocal(self):
179 qemu_terminate(self.s)
180 if self.meta_qemu:
181 runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True)
182
183 def qemu_command(self, command):
184 return qemu_send_command(self.qemu.ssh_port, command)
185
186 def test_provisioning(self):
187 print('Checking machine name (hostname) of device:')
188 stdout, stderr, retcode = self.qemu_command('hostname')
189 self.assertEqual(retcode, 0, "Unable to check hostname. " +
190 "Is an ssh daemon (such as dropbear or openssh) installed on the device?")
191 machine = get_bb_var('MACHINE', 'core-image-minimal')
192 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode())
193 # Strip off line ending.
194 value = stdout.decode()[:-1]
195 self.assertEqual(value, machine,
196 'MACHINE does not match hostname: ' + machine + ', ' + value)
197
198 verifyNotProvisioned(self, machine)
199
200 # Run aktualizr-cert-provider.
201 bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS'], 'aktualizr-native')
202 creds = bb_vars['SOTA_PACKED_CREDENTIALS']
203 bb_vars_prov = get_bb_vars(['STAGING_DIR_HOST', 'libdir'], 'aktualizr-ca-implicit-prov')
204 config = bb_vars_prov['STAGING_DIR_HOST'] + bb_vars_prov['libdir'] + '/sota/sota_implicit_prov_ca.toml'
205
206 print('Provisining at root@localhost:%d' % self.qemu.ssh_port)
207 akt_native_run(self, 'aktualizr-cert-provider -c {creds} -t root@localhost -p {port} -s -u -r -g {config}'
208 .format(creds=creds, port=self.qemu.ssh_port, config=config))
209
210 verifyProvisioned(self, machine)
211
212
213class HsmTests(OESelftestTestCase):
214
215 def setUpLocal(self):
216 layer = "meta-updater-qemux86-64"
217 result = runCmd('bitbake-layers show-layers')
218 if re.search(layer, result.output) is None:
219 # Assume the directory layout for finding other layers. We could also
220 # make assumptions by using 'show-layers', but either way, if the
221 # layers we need aren't where we expect them, we are out of luck.
222 path = os.path.abspath(os.path.dirname(__file__))
223 metadir = path + "/../../../../../"
224 self.meta_qemu = metadir + layer
225 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu)
226 else:
227 self.meta_qemu = None
228 self.append_config('MACHINE = "qemux86-64"')
229 self.append_config('SOTA_CLIENT_PROV = "aktualizr-hsm-prov"')
230 self.append_config('SOTA_DEPLOY_CREDENTIALS = "0"')
231 self.append_config('SOTA_CLIENT_FEATURES = "hsm"')
232 self.append_config('IMAGE_INSTALL_append = " softhsm-testtoken"')
233 runCmd('bitbake -c cleanall aktualizr aktualizr-hsm-prov')
234 self.qemu, self.s = qemu_launch(machine='qemux86-64')
235
236 def tearDownLocal(self):
237 qemu_terminate(self.s)
238 if self.meta_qemu:
239 runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True)
240
241 def qemu_command(self, command):
242 return qemu_send_command(self.qemu.ssh_port, command)
243
244 def test_provisioning(self):
245 print('Checking machine name (hostname) of device:')
246 stdout, stderr, retcode = self.qemu_command('hostname')
247 self.assertEqual(retcode, 0, "Unable to check hostname. " +
248 "Is an ssh daemon (such as dropbear or openssh) installed on the device?")
249 machine = get_bb_var('MACHINE', 'core-image-minimal')
250 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode())
251 # Strip off line ending.
252 value = stdout.decode()[:-1]
253 self.assertEqual(value, machine,
254 'MACHINE does not match hostname: ' + machine + ', ' + value)
255
256 verifyNotProvisioned(self, machine)
257
258 # Verify that HSM is not yet initialized.
259 pkcs11_command = 'pkcs11-tool --module=/usr/lib/softhsm/libsofthsm2.so -O'
260 stdout, stderr, retcode = self.qemu_command(pkcs11_command)
261 self.assertNotEqual(retcode, 0, 'pkcs11-tool succeeded before initialization: ' +
262 stdout.decode() + stderr.decode())
263 softhsm2_command = 'softhsm2-util --show-slots'
264 stdout, stderr, retcode = self.qemu_command(softhsm2_command)
265 self.assertNotEqual(retcode, 0, 'softhsm2-tool succeeded before initialization: ' +
266 stdout.decode() + stderr.decode())
267
268 # Run aktualizr-cert-provider.
269 bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS'], 'aktualizr-native')
270 creds = bb_vars['SOTA_PACKED_CREDENTIALS']
271 bb_vars_prov = get_bb_vars(['STAGING_DIR_HOST', 'libdir'], 'aktualizr-hsm-prov')
272 config = bb_vars_prov['STAGING_DIR_HOST'] + bb_vars_prov['libdir'] + '/sota/sota_hsm_prov.toml'
273
274 akt_native_run(self, 'aktualizr-cert-provider -c {creds} -t root@localhost -p {port} -r -s -u -g {config}'
275 .format(creds=creds, port=self.qemu.ssh_port, config=config))
276
277 # Verify that HSM is able to initialize.
278 ran_ok = False
279 for delay in [5, 5, 5, 5, 10]:
280 sleep(delay)
281 p11_out, p11_err, p11_ret = self.qemu_command(pkcs11_command)
282 hsm_out, hsm_err, hsm_ret = self.qemu_command(softhsm2_command)
283 if p11_ret == 0 and hsm_ret == 0 and hsm_err == b'':
284 ran_ok = True
285 break
286 self.assertTrue(ran_ok, 'pkcs11-tool or softhsm2-tool failed: ' + p11_err.decode() +
287 p11_out.decode() + hsm_err.decode() + hsm_out.decode())
288 self.assertIn(b'present token', p11_err, 'pkcs11-tool failed: ' + p11_err.decode() + p11_out.decode())
289 self.assertIn(b'X.509 cert', p11_out, 'pkcs11-tool failed: ' + p11_err.decode() + p11_out.decode())
290 self.assertIn(b'Initialized: yes', hsm_out, 'softhsm2-tool failed: ' +
291 hsm_err.decode() + hsm_out.decode())
292 self.assertIn(b'User PIN init.: yes', hsm_out, 'softhsm2-tool failed: ' +
293 hsm_err.decode() + hsm_out.decode())
294
295 # Check that pkcs11 output matches sofhsm output.
296 p11_p = re.compile(r'Using slot [0-9] with a present token \((0x[0-9a-f]*)\)\s')
297 p11_m = p11_p.search(p11_err.decode())
298 self.assertTrue(p11_m, 'Slot number not found with pkcs11-tool: ' + p11_err.decode() + p11_out.decode())
299 self.assertGreater(p11_m.lastindex, 0, 'Slot number not found with pkcs11-tool: ' +
300 p11_err.decode() + p11_out.decode())
301 hsm_p = re.compile(r'Description:\s*SoftHSM slot ID (0x[0-9a-f]*)\s')
302 hsm_m = hsm_p.search(hsm_out.decode())
303 self.assertTrue(hsm_m, 'Slot number not found with softhsm2-tool: ' + hsm_err.decode() + hsm_out.decode())
304 self.assertGreater(hsm_m.lastindex, 0, 'Slot number not found with softhsm2-tool: ' +
305 hsm_err.decode() + hsm_out.decode())
306 self.assertEqual(p11_m.group(1), hsm_m.group(1), 'Slot number does not match: ' +
307 p11_err.decode() + p11_out.decode() + hsm_err.decode() + hsm_out.decode())
308
309 verifyProvisioned(self, machine)
310
311
312class SecondaryTests(OESelftestTestCase):
313 def setUpLocal(self):
314 layer = "meta-updater-qemux86-64"
315 result = runCmd('bitbake-layers show-layers')
316 if re.search(layer, result.output) is None:
317 # Assume the directory layout for finding other layers. We could also
318 # make assumptions by using 'show-layers', but either way, if the
319 # layers we need aren't where we expect them, we are out of luck.
320 path = os.path.abspath(os.path.dirname(__file__))
321 metadir = path + "/../../../../../"
322 self.meta_qemu = metadir + layer
323 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu)
324 else:
325 self.meta_qemu = None
326 self.append_config('MACHINE = "qemux86-64"')
327 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
328 self.qemu, self.s = qemu_launch(machine='qemux86-64', imagename='secondary-image')
329
330 def tearDownLocal(self):
331 qemu_terminate(self.s)
332 if self.meta_qemu:
333 runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True)
334
335 def qemu_command(self, command):
336 return qemu_send_command(self.qemu.ssh_port, command)
337
338 def test_secondary_present(self):
339 print('Checking aktualizr-secondary is present')
340 stdout, stderr, retcode = self.qemu_command('aktualizr-secondary --help')
341 self.assertEqual(retcode, 0, "Unable to run aktualizr-secondary --help")
342 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode())
343
344 def test_secondary_listening(self):
345 print('Checking aktualizr-secondary service is listening')
346 stdout, stderr, retcode = self.qemu_command('aktualizr-check-discovery')
347 self.assertEqual(retcode, 0, "Unable to connect to secondary")
348
349
350class PrimaryTests(OESelftestTestCase):
351 def setUpLocal(self):
352 layer = "meta-updater-qemux86-64"
353 result = runCmd('bitbake-layers show-layers')
354 if re.search(layer, result.output) is None:
355 # Assume the directory layout for finding other layers. We could also
356 # make assumptions by using 'show-layers', but either way, if the
357 # layers we need aren't where we expect them, we are out of luck.
358 path = os.path.abspath(os.path.dirname(__file__))
359 metadir = path + "/../../../../../"
360 self.meta_qemu = metadir + layer
361 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu)
362 else:
363 self.meta_qemu = None
364 self.append_config('MACHINE = "qemux86-64"')
365 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
366 self.append_config('SOTA_CLIENT_FEATURES = "secondary-network"')
367 self.qemu, self.s = qemu_launch(machine='qemux86-64', imagename='primary-image')
368
369 def tearDownLocal(self):
370 qemu_terminate(self.s)
371 if self.meta_qemu:
372 runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True)
373
374 def qemu_command(self, command):
375 return qemu_send_command(self.qemu.ssh_port, command)
376
377 def test_aktualizr_present(self):
378 print('Checking aktualizr is present')
379 stdout, stderr, retcode = self.qemu_command('aktualizr --help')
380 self.assertEqual(retcode, 0, "Unable to run aktualizr --help")
381 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode())
382
383
384class ResourceControlTests(OESelftestTestCase):
385 def setUpLocal(self):
386 layer = "meta-updater-qemux86-64"
387 result = runCmd('bitbake-layers show-layers')
388 if re.search(layer, result.output) is None:
389 # Assume the directory layout for finding other layers. We could also
390 # make assumptions by using 'show-layers', but either way, if the
391 # layers we need aren't where we expect them, we are out of luck.
392 path = os.path.abspath(os.path.dirname(__file__))
393 metadir = path + "/../../../../../"
394 self.meta_qemu = metadir + layer
395 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu)
396 else:
397 self.meta_qemu = None
398 self.append_config('MACHINE = "qemux86-64"')
399 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
400 self.append_config('IMAGE_INSTALL_append += " aktualizr-resource-control "')
401 self.append_config('RESOURCE_CPU_WEIGHT_pn-aktualizr = "1000"')
402 self.append_config('RESOURCE_MEMORY_HIGH_pn-aktualizr = "50M"')
403 self.append_config('RESOURCE_MEMORY_MAX_pn-aktualizr = "1M"')
404 self.qemu, self.s = qemu_launch(machine='qemux86-64')
405
406 def tearDownLocal(self):
407 qemu_terminate(self.s)
408 if self.meta_qemu:
409 runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True)
410
411 def qemu_command(self, command):
412 return qemu_send_command(self.qemu.ssh_port, command)
413
414 def test_aktualizr_resource_control(self):
415 print('Checking aktualizr was killed')
416 stdout, stderr, retcode = self.qemu_command('systemctl --no-pager show aktualizr')
417 self.assertIn(b'CPUWeight=1000', stdout, 'CPUWeight was not set correctly')
418 self.assertIn(b'MemoryHigh=52428800', stdout, 'MemoryHigh was not set correctly')
419 self.assertIn(b'MemoryMax=1048576', stdout, 'MemoryMax was not set correctly')
420 self.assertIn(b'ExecMainStatus=9', stdout, 'Aktualizr was not killed')
421
422 self.qemu_command('systemctl --runtime set-property aktualizr MemoryMax=')
423 self.qemu_command('systemctl restart aktualizr')
424
425 stdout, stderr, retcode = self.qemu_command('systemctl --no-pager show --property=ExecMainStatus aktualizr')
426 self.assertIn(b'ExecMainStatus=0', stdout, 'Aktualizr did not restart')
427
428# vim:set ts=4 sw=4 sts=4 expandtab: