summaryrefslogtreecommitdiffstats
path: root/lib/oeqa/selftest
diff options
context:
space:
mode:
Diffstat (limited to 'lib/oeqa/selftest')
-rw-r--r--lib/oeqa/selftest/cases/testutils.py128
-rw-r--r--lib/oeqa/selftest/cases/updater_minnowboard.py60
-rw-r--r--lib/oeqa/selftest/cases/updater_native.py47
-rw-r--r--lib/oeqa/selftest/cases/updater_qemux86_64.py (renamed from lib/oeqa/selftest/cases/updater.py)396
-rw-r--r--lib/oeqa/selftest/cases/updater_qemux86_64_ptest.py52
-rw-r--r--lib/oeqa/selftest/cases/updater_raspberrypi.py86
6 files changed, 430 insertions, 339 deletions
diff --git a/lib/oeqa/selftest/cases/testutils.py b/lib/oeqa/selftest/cases/testutils.py
new file mode 100644
index 0000000..2ad99ad
--- /dev/null
+++ b/lib/oeqa/selftest/cases/testutils.py
@@ -0,0 +1,128 @@
1import os
2import logging
3import re
4import subprocess
5from time import sleep
6
7from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars
8from qemucommand import QemuCommand
9
10
11def qemu_launch(efi=False, machine=None, imagename=None):
12 logger = logging.getLogger("selftest")
13 if imagename is None:
14 imagename = 'core-image-minimal'
15 logger.info('Running bitbake to build {}'.format(imagename))
16 bitbake(imagename)
17 # Create empty object.
18 args = type('', (), {})()
19 args.imagename = imagename
20 args.mac = None
21 # Could use DEPLOY_DIR_IMAGE here but it's already in the machine
22 # subdirectory.
23 args.dir = 'tmp/deploy/images'
24 args.efi = efi
25 args.machine = machine
26 qemu_use_kvm = get_bb_var("QEMU_USE_KVM")
27 if qemu_use_kvm and \
28 (qemu_use_kvm == 'True' and 'x86' in machine or
29 get_bb_var('MACHINE') in qemu_use_kvm.split()):
30 args.kvm = True
31 else:
32 args.kvm = None # Autodetect
33 args.no_gui = True
34 args.gdb = False
35 args.pcap = None
36 args.overlay = None
37 args.dry_run = False
38 args.secondary_network = False
39
40 qemu = QemuCommand(args)
41 cmdline = qemu.command_line()
42 print('Booting image with run-qemu-ota...')
43 s = subprocess.Popen(cmdline)
44 sleep(10)
45 return qemu, s
46
47
48def qemu_terminate(s):
49 try:
50 s.terminate()
51 except KeyboardInterrupt:
52 pass
53
54
55def qemu_send_command(port, command, timeout=60):
56 command = ['ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@localhost -p ' +
57 str(port) + ' "' + command + '"']
58 s2 = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
59 stdout, stderr = s2.communicate(timeout=timeout)
60 return stdout, stderr, s2.returncode
61
62
63def akt_native_run(testInst, cmd, **kwargs):
64 # run a command supplied by aktualizr-native and checks that:
65 # - the executable exists
66 # - the command runs without error
67 # NOTE: the base test class must have built aktualizr-native (in
68 # setUpClass, for example)
69 bb_vars = get_bb_vars(['SYSROOT_DESTDIR', 'base_prefix', 'libdir', 'bindir'],
70 'aktualizr-native')
71 sysroot = bb_vars['SYSROOT_DESTDIR'] + bb_vars['base_prefix']
72 sysrootbin = bb_vars['SYSROOT_DESTDIR'] + bb_vars['bindir']
73 libdir = bb_vars['libdir']
74
75 program, *_ = cmd.split(' ')
76 p = '{}/{}'.format(sysrootbin, program)
77 testInst.assertTrue(os.path.isfile(p), msg="No {} found ({})".format(program, p))
78 env = dict(os.environ)
79 env['LD_LIBRARY_PATH'] = libdir
80 result = runCmd(cmd, env=env, native_sysroot=sysroot, ignore_status=True, **kwargs)
81 testInst.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output)
82
83
84def verifyNotProvisioned(testInst, machine):
85 print('Checking output of aktualizr-info:')
86 ran_ok = False
87 for delay in [5, 5, 5, 5, 10, 10, 10, 10]:
88 stdout, stderr, retcode = testInst.qemu_command('aktualizr-info')
89 if retcode == 0 and stderr == b'':
90 ran_ok = True
91 break
92 sleep(delay)
93 testInst.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode())
94
95 # Verify that device has NOT yet provisioned.
96 testInst.assertIn(b'Couldn\'t load device ID', stdout,
97 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
98 testInst.assertIn(b'Couldn\'t load ECU serials', stdout,
99 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
100 testInst.assertIn(b'Provisioned on server: no', stdout,
101 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
102 testInst.assertIn(b'Fetched metadata: no', stdout,
103 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
104
105
106def verifyProvisioned(testInst, machine):
107 # Verify that device HAS provisioned.
108 ran_ok = False
109 for delay in [5, 5, 5, 5, 10, 10, 10, 10]:
110 stdout, stderr, retcode = testInst.qemu_command('aktualizr-info')
111 if retcode == 0 and stderr == b'' and stdout.decode().find('Fetched metadata: yes') >= 0:
112 ran_ok = True
113 break
114 sleep(delay)
115 testInst.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode())
116
117 testInst.assertIn(b'Device ID: ', stdout, 'Provisioning failed: ' + stderr.decode() + stdout.decode())
118 testInst.assertIn(b'Primary ecu hardware ID: ' + machine.encode(), stdout,
119 'Provisioning failed: ' + stderr.decode() + stdout.decode())
120 testInst.assertIn(b'Fetched metadata: yes', stdout, 'Provisioning failed: ' + stderr.decode() + stdout.decode())
121 p = re.compile(r'Device ID: ([a-z0-9-]*)\n')
122 m = p.search(stdout.decode())
123 testInst.assertTrue(m, 'Device ID could not be read: ' + stderr.decode() + stdout.decode())
124 testInst.assertGreater(m.lastindex, 0, 'Device ID could not be read: ' + stderr.decode() + stdout.decode())
125 logger = logging.getLogger("selftest")
126 logger.info('Device successfully provisioned with ID: ' + m.group(1))
127
128# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/oeqa/selftest/cases/updater_minnowboard.py b/lib/oeqa/selftest/cases/updater_minnowboard.py
new file mode 100644
index 0000000..f5df584
--- /dev/null
+++ b/lib/oeqa/selftest/cases/updater_minnowboard.py
@@ -0,0 +1,60 @@
1import os
2import re
3
4from oeqa.selftest.case import OESelftestTestCase
5from oeqa.utils.commands import runCmd, get_bb_var
6from testutils import qemu_launch, qemu_send_command, qemu_terminate, verifyProvisioned
7
8
9class MinnowTests(OESelftestTestCase):
10
11 def setUpLocal(self):
12 layer_intel = "meta-intel"
13 layer_minnow = "meta-updater-minnowboard"
14 result = runCmd('bitbake-layers show-layers')
15 # Assume the directory layout for finding other layers. We could also
16 # make assumptions by using 'show-layers', but either way, if the
17 # layers we need aren't where we expect them, we are out of luck.
18 path = os.path.abspath(os.path.dirname(__file__))
19 metadir = path + "/../../../../../"
20 if re.search(layer_intel, result.output) is None:
21 self.meta_intel = metadir + layer_intel
22 runCmd('bitbake-layers add-layer "%s"' % self.meta_intel)
23 else:
24 self.meta_intel = None
25 if re.search(layer_minnow, result.output) is None:
26 self.meta_minnow = metadir + layer_minnow
27 runCmd('bitbake-layers add-layer "%s"' % self.meta_minnow)
28 else:
29 self.meta_minnow = None
30 self.append_config('MACHINE = "intel-corei7-64"')
31 self.append_config('OSTREE_BOOTLOADER = "grub"')
32 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
33 self.qemu, self.s = qemu_launch(efi=True, machine='intel-corei7-64')
34
35 def tearDownLocal(self):
36 qemu_terminate(self.s)
37 if self.meta_intel:
38 runCmd('bitbake-layers remove-layer "%s"' % self.meta_intel, ignore_status=True)
39 if self.meta_minnow:
40 runCmd('bitbake-layers remove-layer "%s"' % self.meta_minnow, ignore_status=True)
41
42 def qemu_command(self, command):
43 return qemu_send_command(self.qemu.ssh_port, command)
44
45 def test_provisioning(self):
46 print('Checking machine name (hostname) of device:')
47 stdout, stderr, retcode = self.qemu_command('hostname')
48 self.assertEqual(retcode, 0, "Unable to check hostname. " +
49 "Is an ssh daemon (such as dropbear or openssh) installed on the device?")
50 machine = get_bb_var('MACHINE', 'core-image-minimal')
51 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode())
52 # Strip off line ending.
53 value = stdout.decode()[:-1]
54 self.assertEqual(value, machine,
55 'MACHINE does not match hostname: ' + machine + ', ' + value +
56 '\nIs TianoCore ovmf installed on your host machine?')
57
58 verifyProvisioned(self, machine)
59
60# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/oeqa/selftest/cases/updater_native.py b/lib/oeqa/selftest/cases/updater_native.py
new file mode 100644
index 0000000..1fc9cb8
--- /dev/null
+++ b/lib/oeqa/selftest/cases/updater_native.py
@@ -0,0 +1,47 @@
1# pylint: disable=C0111,C0325
2import logging
3
4from oeqa.selftest.case import OESelftestTestCase
5from oeqa.utils.commands import runCmd, bitbake, get_bb_var
6from testutils import akt_native_run
7
8
9class SotaToolsTests(OESelftestTestCase):
10
11 @classmethod
12 def setUpClass(cls):
13 super(SotaToolsTests, cls).setUpClass()
14 logger = logging.getLogger("selftest")
15 logger.info('Running bitbake to build aktualizr-native tools')
16 bitbake('aktualizr-native')
17
18 def test_push_help(self):
19 akt_native_run(self, 'garage-push --help')
20
21 def test_deploy_help(self):
22 akt_native_run(self, 'garage-deploy --help')
23
24 def test_garagesign_help(self):
25 akt_native_run(self, 'garage-sign --help')
26
27
28class GeneralTests(OESelftestTestCase):
29
30 def test_feature_sota(self):
31 result = get_bb_var('DISTRO_FEATURES').find('sota')
32 self.assertNotEqual(result, -1, 'Feature "sota" not set at DISTRO_FEATURES')
33
34 def test_feature_usrmerge(self):
35 result = get_bb_var('DISTRO_FEATURES').find('usrmerge')
36 self.assertNotEqual(result, -1, 'Feature "sota" not set at DISTRO_FEATURES')
37
38 def test_feature_systemd(self):
39 result = get_bb_var('DISTRO_FEATURES').find('systemd')
40 self.assertNotEqual(result, -1, 'Feature "systemd" not set at DISTRO_FEATURES')
41
42 def test_java(self):
43 result = runCmd('which java', ignore_status=True)
44 self.assertEqual(result.status, 0,
45 "Java not found. Do you have a JDK installed on your host machine?")
46
47# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/oeqa/selftest/cases/updater.py b/lib/oeqa/selftest/cases/updater_qemux86_64.py
index 550d9de..9f32bcf 100644
--- a/lib/oeqa/selftest/cases/updater.py
+++ b/lib/oeqa/selftest/cases/updater_qemux86_64.py
@@ -2,48 +2,16 @@
2import os 2import os
3import logging 3import logging
4import re 4import re
5import subprocess
6import unittest 5import unittest
7from time import sleep 6from time import sleep
8 7
9from oeqa.selftest.case import OESelftestTestCase 8from oeqa.selftest.case import OESelftestTestCase
10from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars 9from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars
11from qemucommand import QemuCommand 10from testutils import qemu_launch, qemu_send_command, qemu_terminate, \
12 11 akt_native_run, verifyNotProvisioned, verifyProvisioned
13
14class SotaToolsTests(OESelftestTestCase):
15
16 @classmethod
17 def setUpClass(cls):
18 super(SotaToolsTests, cls).setUpClass()
19 logger = logging.getLogger("selftest")
20 logger.info('Running bitbake to build aktualizr-native tools')
21 bitbake('aktualizr-native')
22
23 def test_push_help(self):
24 akt_native_run(self, 'garage-push --help')
25
26 def test_deploy_help(self):
27 akt_native_run(self, 'garage-deploy --help')
28
29 def test_garagesign_help(self):
30 akt_native_run(self, 'garage-sign --help')
31 12
32 13
33class GeneralTests(OESelftestTestCase): 14class GeneralTests(OESelftestTestCase):
34
35 def test_feature_sota(self):
36 result = get_bb_var('DISTRO_FEATURES').find('sota')
37 self.assertNotEqual(result, -1, 'Feature "sota" not set at DISTRO_FEATURES')
38
39 def test_feature_usrmerge(self):
40 result = get_bb_var('DISTRO_FEATURES').find('usrmerge')
41 self.assertNotEqual(result, -1, 'Feature "sota" not set at DISTRO_FEATURES')
42
43 def test_feature_systemd(self):
44 result = get_bb_var('DISTRO_FEATURES').find('systemd')
45 self.assertNotEqual(result, -1, 'Feature "systemd" not set at DISTRO_FEATURES')
46
47 def test_credentials(self): 15 def test_credentials(self):
48 logger = logging.getLogger("selftest") 16 logger = logging.getLogger("selftest")
49 logger.info('Running bitbake to build core-image-minimal') 17 logger.info('Running bitbake to build core-image-minimal')
@@ -62,11 +30,6 @@ class GeneralTests(OESelftestTestCase):
62 (deploydir, imagename), ignore_status=True) 30 (deploydir, imagename), ignore_status=True)
63 self.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output) 31 self.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output)
64 32
65 def test_java(self):
66 result = runCmd('which java', ignore_status=True)
67 self.assertEqual(result.status, 0,
68 "Java not found. Do you have a JDK installed on your host machine?")
69
70 33
71class AktualizrToolsTests(OESelftestTestCase): 34class AktualizrToolsTests(OESelftestTestCase):
72 35
@@ -143,16 +106,6 @@ class AutoProvTests(OESelftestTestCase):
143 value = stdout.decode()[:-1] 106 value = stdout.decode()[:-1]
144 self.assertEqual(value, machine, 107 self.assertEqual(value, machine,
145 'MACHINE does not match hostname: ' + machine + ', ' + value) 108 'MACHINE does not match hostname: ' + machine + ', ' + value)
146 print(value)
147 print('Checking output of aktualizr-info:')
148 ran_ok = False
149 for delay in [1, 2, 5, 10, 15]:
150 stdout, stderr, retcode = self.qemu_command('aktualizr-info')
151 if retcode == 0 and stderr == b'':
152 ran_ok = True
153 break
154 sleep(delay)
155 self.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode())
156 109
157 verifyProvisioned(self, machine) 110 verifyProvisioned(self, machine)
158 111
@@ -191,7 +144,7 @@ class ManualControlTests(OESelftestTestCase):
191 """ 144 """
192 sleep(20) 145 sleep(20)
193 stdout, stderr, retcode = self.qemu_command('aktualizr-info') 146 stdout, stderr, retcode = self.qemu_command('aktualizr-info')
194 self.assertIn(b'Can\'t open database', stdout, 147 self.assertIn(b'Can\'t open database', stderr,
195 'Aktualizr should not have run yet' + stderr.decode() + stdout.decode()) 148 'Aktualizr should not have run yet' + stderr.decode() + stdout.decode())
196 149
197 stdout, stderr, retcode = self.qemu_command('aktualizr once') 150 stdout, stderr, retcode = self.qemu_command('aktualizr once')
@@ -201,144 +154,6 @@ class ManualControlTests(OESelftestTestCase):
201 'Aktualizr should have run' + stderr.decode() + stdout.decode()) 154 'Aktualizr should have run' + stderr.decode() + stdout.decode())
202 155
203 156
204class RpiTests(OESelftestTestCase):
205
206 def setUpLocal(self):
207 # Add layers before changing the machine type, otherwise the sanity
208 # checker complains loudly.
209 layer_python = "meta-openembedded/meta-python"
210 layer_rpi = "meta-raspberrypi"
211 layer_upd_rpi = "meta-updater-raspberrypi"
212 result = runCmd('bitbake-layers show-layers')
213 # Assume the directory layout for finding other layers. We could also
214 # make assumptions by using 'show-layers', but either way, if the
215 # layers we need aren't where we expect them, we are out of luck.
216 path = os.path.abspath(os.path.dirname(__file__))
217 metadir = path + "/../../../../../"
218 if re.search(layer_python, result.output) is None:
219 self.meta_python = metadir + layer_python
220 runCmd('bitbake-layers add-layer "%s"' % self.meta_python)
221 else:
222 self.meta_python = None
223 if re.search(layer_rpi, result.output) is None:
224 self.meta_rpi = metadir + layer_rpi
225 runCmd('bitbake-layers add-layer "%s"' % self.meta_rpi)
226 else:
227 self.meta_rpi = None
228 if re.search(layer_upd_rpi, result.output) is None:
229 self.meta_upd_rpi = metadir + layer_upd_rpi
230 runCmd('bitbake-layers add-layer "%s"' % self.meta_upd_rpi)
231 else:
232 self.meta_upd_rpi = None
233
234 # This is trickier that I would've thought. The fundamental problem is
235 # that the qemu layer changes the u-boot file extension to .rom, but
236 # raspberrypi still expects .bin. To prevent this, the qemu layer must
237 # be temporarily removed if it is present. It has to be removed by name
238 # without the complete path, but to add it back when we are done, we
239 # need the full path.
240 p = re.compile(r'meta-updater-qemux86-64\s*(\S*meta-updater-qemux86-64)\s')
241 m = p.search(result.output)
242 if m and m.lastindex > 0:
243 self.meta_qemu = m.group(1)
244 runCmd('bitbake-layers remove-layer meta-updater-qemux86-64')
245 else:
246 self.meta_qemu = None
247
248 self.append_config('MACHINE = "raspberrypi3"')
249 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
250
251 def tearDownLocal(self):
252 if self.meta_qemu:
253 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu, ignore_status=True)
254 if self.meta_upd_rpi:
255 runCmd('bitbake-layers remove-layer "%s"' % self.meta_upd_rpi, ignore_status=True)
256 if self.meta_rpi:
257 runCmd('bitbake-layers remove-layer "%s"' % self.meta_rpi, ignore_status=True)
258 if self.meta_python:
259 runCmd('bitbake-layers remove-layer "%s"' % self.meta_python, ignore_status=True)
260
261 def test_rpi(self):
262 logger = logging.getLogger("selftest")
263 logger.info('Running bitbake to build core-image-minimal')
264 self.append_config('SOTA_CLIENT_PROV = "aktualizr-auto-prov"')
265 bitbake('core-image-minimal')
266 credentials = get_bb_var('SOTA_PACKED_CREDENTIALS')
267 # Skip the test if the variable SOTA_PACKED_CREDENTIALS is not set.
268 if credentials is None:
269 raise unittest.SkipTest("Variable 'SOTA_PACKED_CREDENTIALS' not set.")
270 # Check if the file exists.
271 self.assertTrue(os.path.isfile(credentials), "File %s does not exist" % credentials)
272 deploydir = get_bb_var('DEPLOY_DIR_IMAGE')
273 imagename = get_bb_var('IMAGE_LINK_NAME', 'core-image-minimal')
274 # Check if the credentials are included in the output image.
275 result = runCmd('tar -jtvf %s/%s.tar.bz2 | grep sota_provisioning_credentials.zip' %
276 (deploydir, imagename), ignore_status=True)
277 self.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output)
278
279
280class GrubTests(OESelftestTestCase):
281
282 def setUpLocal(self):
283 layer_intel = "meta-intel"
284 layer_minnow = "meta-updater-minnowboard"
285 result = runCmd('bitbake-layers show-layers')
286 # Assume the directory layout for finding other layers. We could also
287 # make assumptions by using 'show-layers', but either way, if the
288 # layers we need aren't where we expect them, we are out of luck.
289 path = os.path.abspath(os.path.dirname(__file__))
290 metadir = path + "/../../../../../"
291 if re.search(layer_intel, result.output) is None:
292 self.meta_intel = metadir + layer_intel
293 runCmd('bitbake-layers add-layer "%s"' % self.meta_intel)
294 else:
295 self.meta_intel = None
296 if re.search(layer_minnow, result.output) is None:
297 self.meta_minnow = metadir + layer_minnow
298 runCmd('bitbake-layers add-layer "%s"' % self.meta_minnow)
299 else:
300 self.meta_minnow = None
301 self.append_config('MACHINE = "intel-corei7-64"')
302 self.append_config('OSTREE_BOOTLOADER = "grub"')
303 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
304 self.qemu, self.s = qemu_launch(efi=True, machine='intel-corei7-64')
305
306 def tearDownLocal(self):
307 qemu_terminate(self.s)
308 if self.meta_intel:
309 runCmd('bitbake-layers remove-layer "%s"' % self.meta_intel, ignore_status=True)
310 if self.meta_minnow:
311 runCmd('bitbake-layers remove-layer "%s"' % self.meta_minnow, ignore_status=True)
312
313 def qemu_command(self, command):
314 return qemu_send_command(self.qemu.ssh_port, command)
315
316 def test_grub(self):
317 print('Checking machine name (hostname) of device:')
318 stdout, stderr, retcode = self.qemu_command('hostname')
319 self.assertEqual(retcode, 0, "Unable to check hostname. " +
320 "Is an ssh daemon (such as dropbear or openssh) installed on the device?")
321 machine = get_bb_var('MACHINE', 'core-image-minimal')
322 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode())
323 # Strip off line ending.
324 value = stdout.decode()[:-1]
325 self.assertEqual(value, machine,
326 'MACHINE does not match hostname: ' + machine + ', ' + value +
327 '\nIs TianoCore ovmf installed on your host machine?')
328 print(value)
329 print('Checking output of aktualizr-info:')
330 ran_ok = False
331 for delay in [1, 2, 5, 10, 15]:
332 stdout, stderr, retcode = self.qemu_command('aktualizr-info')
333 if retcode == 0 and stderr == b'':
334 ran_ok = True
335 break
336 sleep(delay)
337 self.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode())
338
339 verifyProvisioned(self, machine)
340
341
342class ImplProvTests(OESelftestTestCase): 157class ImplProvTests(OESelftestTestCase):
343 158
344 def setUpLocal(self): 159 def setUpLocal(self):
@@ -379,25 +194,8 @@ class ImplProvTests(OESelftestTestCase):
379 value = stdout.decode()[:-1] 194 value = stdout.decode()[:-1]
380 self.assertEqual(value, machine, 195 self.assertEqual(value, machine,
381 'MACHINE does not match hostname: ' + machine + ', ' + value) 196 'MACHINE does not match hostname: ' + machine + ', ' + value)
382 print(value) 197
383 print('Checking output of aktualizr-info:') 198 verifyNotProvisioned(self, machine)
384 ran_ok = False
385 for delay in [1, 2, 5, 10, 15]:
386 stdout, stderr, retcode = self.qemu_command('aktualizr-info')
387 if retcode == 0 and stderr == b'':
388 ran_ok = True
389 break
390 sleep(delay)
391 self.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode())
392 # Verify that device has NOT yet provisioned.
393 self.assertIn(b'Couldn\'t load device ID', stdout,
394 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
395 self.assertIn(b'Couldn\'t load ECU serials', stdout,
396 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
397 self.assertIn(b'Provisioned on server: no', stdout,
398 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
399 self.assertIn(b'Fetched metadata: no', stdout,
400 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
401 199
402 # Run aktualizr-cert-provider. 200 # Run aktualizr-cert-provider.
403 bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS'], 'aktualizr-native') 201 bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS'], 'aktualizr-native')
@@ -454,25 +252,8 @@ class HsmTests(OESelftestTestCase):
454 value = stdout.decode()[:-1] 252 value = stdout.decode()[:-1]
455 self.assertEqual(value, machine, 253 self.assertEqual(value, machine,
456 'MACHINE does not match hostname: ' + machine + ', ' + value) 254 'MACHINE does not match hostname: ' + machine + ', ' + value)
457 print(value) 255
458 print('Checking output of aktualizr-info:') 256 verifyNotProvisioned(self, machine)
459 ran_ok = False
460 for delay in [1, 2, 5, 10, 15]:
461 stdout, stderr, retcode = self.qemu_command('aktualizr-info')
462 if retcode == 0 and stderr == b'':
463 ran_ok = True
464 break
465 sleep(delay)
466 self.assertTrue(ran_ok, 'aktualizr-info failed: ' + stderr.decode() + stdout.decode())
467 # Verify that device has NOT yet provisioned.
468 self.assertIn(b'Couldn\'t load device ID', stdout,
469 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
470 self.assertIn(b'Couldn\'t load ECU serials', stdout,
471 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
472 self.assertIn(b'Provisioned on server: no', stdout,
473 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
474 self.assertIn(b'Fetched metadata: no', stdout,
475 'Device already provisioned!? ' + stderr.decode() + stdout.decode())
476 257
477 # Verify that HSM is not yet initialized. 258 # Verify that HSM is not yet initialized.
478 pkcs11_command = 'pkcs11-tool --module=/usr/lib/softhsm/libsofthsm2.so -O' 259 pkcs11_command = 'pkcs11-tool --module=/usr/lib/softhsm/libsofthsm2.so -O'
@@ -482,7 +263,7 @@ class HsmTests(OESelftestTestCase):
482 softhsm2_command = 'softhsm2-util --show-slots' 263 softhsm2_command = 'softhsm2-util --show-slots'
483 stdout, stderr, retcode = self.qemu_command(softhsm2_command) 264 stdout, stderr, retcode = self.qemu_command(softhsm2_command)
484 self.assertNotEqual(retcode, 0, 'softhsm2-tool succeeded before initialization: ' + 265 self.assertNotEqual(retcode, 0, 'softhsm2-tool succeeded before initialization: ' +
485 stdout.decode() + stderr.decode()) 266 stdout.decode() + stderr.decode())
486 267
487 # Run aktualizr-cert-provider. 268 # Run aktualizr-cert-provider.
488 bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS'], 'aktualizr-native') 269 bb_vars = get_bb_vars(['SOTA_PACKED_CREDENTIALS'], 'aktualizr-native')
@@ -529,13 +310,6 @@ class HsmTests(OESelftestTestCase):
529 310
530 311
531class SecondaryTests(OESelftestTestCase): 312class SecondaryTests(OESelftestTestCase):
532 @classmethod
533 def setUpClass(cls):
534 super(SecondaryTests, cls).setUpClass()
535 logger = logging.getLogger("selftest")
536 logger.info('Running bitbake to build secondary-image')
537 bitbake('secondary-image')
538
539 def setUpLocal(self): 313 def setUpLocal(self):
540 layer = "meta-updater-qemux86-64" 314 layer = "meta-updater-qemux86-64"
541 result = runCmd('bitbake-layers show-layers') 315 result = runCmd('bitbake-layers show-layers')
@@ -567,20 +341,8 @@ class SecondaryTests(OESelftestTestCase):
567 self.assertEqual(retcode, 0, "Unable to run aktualizr-secondary --help") 341 self.assertEqual(retcode, 0, "Unable to run aktualizr-secondary --help")
568 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode()) 342 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode())
569 343
570 def test_secondary_listening(self):
571 print('Checking aktualizr-secondary service is listening')
572 stdout, stderr, retcode = self.qemu_command('aktualizr-check-discovery')
573 self.assertEqual(retcode, 0, "Unable to connect to secondary")
574
575 344
576class PrimaryTests(OESelftestTestCase): 345class PrimaryTests(OESelftestTestCase):
577 @classmethod
578 def setUpClass(cls):
579 super(PrimaryTests, cls).setUpClass()
580 logger = logging.getLogger("selftest")
581 logger.info('Running bitbake to build primary-image')
582 bitbake('primary-image')
583
584 def setUpLocal(self): 346 def setUpLocal(self):
585 layer = "meta-updater-qemux86-64" 347 layer = "meta-updater-qemux86-64"
586 result = runCmd('bitbake-layers show-layers') 348 result = runCmd('bitbake-layers show-layers')
@@ -614,99 +376,55 @@ class PrimaryTests(OESelftestTestCase):
614 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode()) 376 self.assertEqual(stderr, b'', 'Error: ' + stderr.decode())
615 377
616 378
617def qemu_launch(efi=False, machine=None, imagename=None): 379class ResourceControlTests(OESelftestTestCase):
618 logger = logging.getLogger("selftest") 380 def setUpLocal(self):
619 logger.info('Running bitbake to build core-image-minimal') 381 layer = "meta-updater-qemux86-64"
620 bitbake('core-image-minimal') 382 result = runCmd('bitbake-layers show-layers')
621 # Create empty object. 383 if re.search(layer, result.output) is None:
622 args = type('', (), {})() 384 # Assume the directory layout for finding other layers. We could also
623 if imagename: 385 # make assumptions by using 'show-layers', but either way, if the
624 args.imagename = imagename 386 # layers we need aren't where we expect them, we are out of luck.
625 else: 387 path = os.path.abspath(os.path.dirname(__file__))
626 args.imagename = 'core-image-minimal' 388 metadir = path + "/../../../../../"
627 args.mac = None 389 self.meta_qemu = metadir + layer
628 # Could use DEPLOY_DIR_IMAGE here but it's already in the machine 390 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu)
629 # subdirectory. 391 else:
630 args.dir = 'tmp/deploy/images' 392 self.meta_qemu = None
631 args.efi = efi 393 self.append_config('MACHINE = "qemux86-64"')
632 args.machine = machine 394 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
633 qemu_use_kvm = get_bb_var("QEMU_USE_KVM") 395 self.append_config('IMAGE_INSTALL_append += " aktualizr-resource-control "')
634 if qemu_use_kvm and \ 396 self.append_config('RESOURCE_CPU_WEIGHT_pn-aktualizr = "1000"')
635 (qemu_use_kvm == 'True' and 'x86' in machine or \ 397 self.append_config('RESOURCE_MEMORY_HIGH_pn-aktualizr = "50M"')
636 get_bb_var('MACHINE') in qemu_use_kvm.split()): 398 self.append_config('RESOURCE_MEMORY_MAX_pn-aktualizr = "1M"')
637 args.kvm = True 399 self.qemu, self.s = qemu_launch(machine='qemux86-64')
638 else: 400
639 args.kvm = None # Autodetect 401 def tearDownLocal(self):
640 args.no_gui = True 402 qemu_terminate(self.s)
641 args.gdb = False 403 if self.meta_qemu:
642 args.pcap = None 404 runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True)
643 args.overlay = None 405
644 args.dry_run = False 406 def qemu_command(self, command):
645 args.secondary_network = False 407 return qemu_send_command(self.qemu.ssh_port, command)
646 408
647 qemu = QemuCommand(args) 409 def test_aktualizr_resource_control(self):
648 cmdline = qemu.command_line() 410 print('Checking aktualizr was killed')
649 print('Booting image with run-qemu-ota...') 411 ran_ok = False
650 s = subprocess.Popen(cmdline) 412 for delay in [5, 5, 5, 5]:
651 sleep(10) 413 sleep(delay)
652 return qemu, s 414 stdout, stderr, retcode = self.qemu_command('systemctl --no-pager show aktualizr')
653 415 if retcode == 0 and b'ExecMainStatus=9' in stdout:
654 416 ran_ok = True
655def qemu_terminate(s): 417 break
656 try: 418 self.assertTrue(ran_ok, 'Aktualizr was not killed')
657 s.terminate() 419
658 except KeyboardInterrupt: 420 self.assertIn(b'CPUWeight=1000', stdout, 'CPUWeight was not set correctly')
659 pass 421 self.assertIn(b'MemoryHigh=52428800', stdout, 'MemoryHigh was not set correctly')
660 422 self.assertIn(b'MemoryMax=1048576', stdout, 'MemoryMax was not set correctly')
661 423
662def qemu_send_command(port, command): 424 self.qemu_command('systemctl --runtime set-property aktualizr MemoryMax=')
663 command = ['ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@localhost -p ' + 425 self.qemu_command('systemctl restart aktualizr')
664 str(port) + ' "' + command + '"']
665 s2 = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
666 stdout, stderr = s2.communicate(timeout=60)
667 return stdout, stderr, s2.returncode
668
669
670def akt_native_run(testInst, cmd, **kwargs):
671 # run a command supplied by aktualizr-native and checks that:
672 # - the executable exists
673 # - the command runs without error
674 # NOTE: the base test class must have built aktualizr-native (in
675 # setUpClass, for example)
676 bb_vars = get_bb_vars(['SYSROOT_DESTDIR', 'base_prefix', 'libdir', 'bindir'],
677 'aktualizr-native')
678 sysroot = bb_vars['SYSROOT_DESTDIR'] + bb_vars['base_prefix']
679 sysrootbin = bb_vars['SYSROOT_DESTDIR'] + bb_vars['bindir']
680 libdir = bb_vars['libdir']
681
682 program, *_ = cmd.split(' ')
683 p = '{}/{}'.format(sysrootbin, program)
684 testInst.assertTrue(os.path.isfile(p), msg="No {} found ({})".format(program, p))
685 env = dict(os.environ)
686 env['LD_LIBRARY_PATH'] = libdir
687 result = runCmd(cmd, env=env, native_sysroot=sysroot, ignore_status=True, **kwargs)
688 testInst.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output)
689
690
691def verifyProvisioned(testInst, machine):
692 # Verify that device HAS provisioned.
693 ran_ok = False
694 for delay in [5, 5, 5, 5, 10, 10, 10, 10]:
695 stdout, stderr, retcode = testInst.qemu_command('aktualizr-info')
696 if retcode == 0 and stderr == b'' and stdout.decode().find('Fetched metadata: yes') >= 0:
697 ran_ok = True
698 break
699 sleep(delay)
700 testInst.assertIn(b'Device ID: ', stdout, 'Provisioning failed: ' + stderr.decode() + stdout.decode())
701 testInst.assertIn(b'Primary ecu hardware ID: ' + machine.encode(), stdout,
702 'Provisioning failed: ' + stderr.decode() + stdout.decode())
703 testInst.assertIn(b'Fetched metadata: yes', stdout, 'Provisioning failed: ' + stderr.decode() + stdout.decode())
704 p = re.compile(r'Device ID: ([a-z0-9-]*)\n')
705 m = p.search(stdout.decode())
706 testInst.assertTrue(m, 'Device ID could not be read: ' + stderr.decode() + stdout.decode())
707 testInst.assertGreater(m.lastindex, 0, 'Device ID could not be read: ' + stderr.decode() + stdout.decode())
708 logger = logging.getLogger("selftest")
709 logger.info('Device successfully provisioned with ID: ' + m.group(1))
710 426
427 stdout, stderr, retcode = self.qemu_command('systemctl --no-pager show --property=ExecMainStatus aktualizr')
428 self.assertIn(b'ExecMainStatus=0', stdout, 'Aktualizr did not restart')
711 429
712# vim:set ts=4 sw=4 sts=4 expandtab: 430# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/oeqa/selftest/cases/updater_qemux86_64_ptest.py b/lib/oeqa/selftest/cases/updater_qemux86_64_ptest.py
new file mode 100644
index 0000000..a04032c
--- /dev/null
+++ b/lib/oeqa/selftest/cases/updater_qemux86_64_ptest.py
@@ -0,0 +1,52 @@
1# pylint: disable=C0111,C0325
2import os
3import re
4
5from oeqa.selftest.case import OESelftestTestCase
6from oeqa.utils.commands import runCmd
7from testutils import qemu_launch, qemu_send_command, qemu_terminate
8
9
10class PtestTests(OESelftestTestCase):
11
12 def setUpLocal(self):
13 layer = "meta-updater-qemux86-64"
14 result = runCmd('bitbake-layers show-layers')
15 if re.search(layer, result.output) is None:
16 # Assume the directory layout for finding other layers. We could also
17 # make assumptions by using 'show-layers', but either way, if the
18 # layers we need aren't where we expect them, we are out of like.
19 path = os.path.abspath(os.path.dirname(__file__))
20 metadir = path + "/../../../../../"
21 self.meta_qemu = metadir + layer
22 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu)
23 else:
24 self.meta_qemu = None
25 self.append_config('MACHINE = "qemux86-64"')
26 self.append_config('SYSTEMD_AUTO_ENABLE_aktualizr = "disable"')
27 self.append_config('PTEST_ENABLED_pn-aktualizr = "1"')
28 self.append_config('IMAGE_INSTALL_append += "aktualizr-ptest ptest-runner "')
29 self.qemu, self.s = qemu_launch(machine='qemux86-64')
30
31 def tearDownLocal(self):
32 qemu_terminate(self.s)
33 if self.meta_qemu:
34 runCmd('bitbake-layers remove-layer "%s"' % self.meta_qemu, ignore_status=True)
35
36 def qemu_command(self, command, timeout=60):
37 return qemu_send_command(self.qemu.ssh_port, command, timeout=timeout)
38
39 def test_run_ptests(self):
40 # simulate a login shell, so that /usr/sbin is in $PATH (from /etc/profile)
41 stdout, stderr, retcode = self.qemu_command('sh -l -c ptest-runner', timeout=None)
42 output = stdout.decode()
43 print(output)
44 self.assertEqual(retcode, 0)
45
46 has_failure = re.search('^FAIL', output, flags=re.MULTILINE) is not None
47 if has_failure:
48 print("Full test suite log:")
49 stdout, stderr, retcode = self.qemu_command('cat /tmp/aktualizr-ptest.log', timeout=None)
50 print(stdout.decode())
51
52 self.assertFalse(has_failure)
diff --git a/lib/oeqa/selftest/cases/updater_raspberrypi.py b/lib/oeqa/selftest/cases/updater_raspberrypi.py
new file mode 100644
index 0000000..785d703
--- /dev/null
+++ b/lib/oeqa/selftest/cases/updater_raspberrypi.py
@@ -0,0 +1,86 @@
1# pylint: disable=C0111,C0325
2import os
3import logging
4import re
5import unittest
6
7from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import runCmd, bitbake, get_bb_var
9
10
11class RpiTests(OESelftestTestCase):
12
13 def setUpLocal(self):
14 # Add layers before changing the machine type, otherwise the sanity
15 # checker complains loudly.
16 layer_python = "meta-openembedded/meta-python"
17 layer_rpi = "meta-raspberrypi"
18 layer_upd_rpi = "meta-updater-raspberrypi"
19 result = runCmd('bitbake-layers show-layers')
20 # Assume the directory layout for finding other layers. We could also
21 # make assumptions by using 'show-layers', but either way, if the
22 # layers we need aren't where we expect them, we are out of luck.
23 path = os.path.abspath(os.path.dirname(__file__))
24 metadir = path + "/../../../../../"
25 if re.search(layer_python, result.output) is None:
26 self.meta_python = metadir + layer_python
27 runCmd('bitbake-layers add-layer "%s"' % self.meta_python)
28 else:
29 self.meta_python = None
30 if re.search(layer_rpi, result.output) is None:
31 self.meta_rpi = metadir + layer_rpi
32 runCmd('bitbake-layers add-layer "%s"' % self.meta_rpi)
33 else:
34 self.meta_rpi = None
35 if re.search(layer_upd_rpi, result.output) is None:
36 self.meta_upd_rpi = metadir + layer_upd_rpi
37 runCmd('bitbake-layers add-layer "%s"' % self.meta_upd_rpi)
38 else:
39 self.meta_upd_rpi = None
40
41 # This is trickier that I would've thought. The fundamental problem is
42 # that the qemu layer changes the u-boot file extension to .rom, but
43 # raspberrypi still expects .bin. To prevent this, the qemu layer must
44 # be temporarily removed if it is present. It has to be removed by name
45 # without the complete path, but to add it back when we are done, we
46 # need the full path.
47 p = re.compile(r'meta-updater-qemux86-64\s*(\S*meta-updater-qemux86-64)\s')
48 m = p.search(result.output)
49 if m and m.lastindex > 0:
50 self.meta_qemu = m.group(1)
51 runCmd('bitbake-layers remove-layer meta-updater-qemux86-64')
52 else:
53 self.meta_qemu = None
54
55 self.append_config('MACHINE = "raspberrypi3"')
56 self.append_config('SOTA_CLIENT_PROV = " aktualizr-auto-prov "')
57
58 def tearDownLocal(self):
59 if self.meta_qemu:
60 runCmd('bitbake-layers add-layer "%s"' % self.meta_qemu, ignore_status=True)
61 if self.meta_upd_rpi:
62 runCmd('bitbake-layers remove-layer "%s"' % self.meta_upd_rpi, ignore_status=True)
63 if self.meta_rpi:
64 runCmd('bitbake-layers remove-layer "%s"' % self.meta_rpi, ignore_status=True)
65 if self.meta_python:
66 runCmd('bitbake-layers remove-layer "%s"' % self.meta_python, ignore_status=True)
67
68 def test_build(self):
69 logger = logging.getLogger("selftest")
70 logger.info('Running bitbake to build core-image-minimal')
71 self.append_config('SOTA_CLIENT_PROV = "aktualizr-auto-prov"')
72 bitbake('core-image-minimal')
73 credentials = get_bb_var('SOTA_PACKED_CREDENTIALS')
74 # Skip the test if the variable SOTA_PACKED_CREDENTIALS is not set.
75 if credentials is None:
76 raise unittest.SkipTest("Variable 'SOTA_PACKED_CREDENTIALS' not set.")
77 # Check if the file exists.
78 self.assertTrue(os.path.isfile(credentials), "File %s does not exist" % credentials)
79 deploydir = get_bb_var('DEPLOY_DIR_IMAGE')
80 imagename = get_bb_var('IMAGE_LINK_NAME', 'core-image-minimal')
81 # Check if the credentials are included in the output image.
82 result = runCmd('tar -jtvf %s/%s.tar.bz2 | grep sota_provisioning_credentials.zip' %
83 (deploydir, imagename), ignore_status=True)
84 self.assertEqual(result.status, 0, "Status not equal to 0. output: %s" % result.output)
85
86# vim:set ts=4 sw=4 sts=4 expandtab: