def latest_part_image(conversion, mender_image): assert os.environ.get("BUILDDIR", False), "BUILDDIR must be set" if conversion: pattern = os.path.splitext(mender_image)[0] else: pattern = "core-image*" # Find latest built rootfs. latest_sdimg = latest_build_artifact(os.environ["BUILDDIR"], "%s.sdimg" % pattern) latest_uefiimg = latest_build_artifact(os.environ["BUILDDIR"], "%s.uefiimg" % pattern) latest_biosimg = latest_build_artifact(os.environ["BUILDDIR"], "%s.biosimg" % pattern) latest_gptimg = latest_build_artifact(os.environ["BUILDDIR"], "%s.gptimg" % pattern) if latest_sdimg: return latest_sdimg elif latest_uefiimg: return latest_uefiimg elif latest_biosimg: return latest_biosimg elif latest_gptimg: return latest_gptimg else: # Tempting to throw an exception here, but this runs even for platforms # that skip the test, so we should return None instead. return None
def test_mender_inventory_network_scripts(self, prepared_test_build, bitbake_image): """ Test the 'inventory-network-scripts' build feature configuration through 'PACKAGECONFIG' is working as expected. This verifies that the 'inventory-network-scripts' option is a part build, and also that the inventory scripts are not included when removed. The test only runs for sdimg, as the build image should not really matter here. """ # # Feature enabled # reset_build_conf(prepared_test_build["build_dir"]) build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['PACKAGECONFIG_append_pn-mender-client = " inventory-network-scripts"'], ) rootfs = latest_build_artifact( prepared_test_build["build_dir"], "core-image*.ext4" ) assert len(rootfs) > 0, "rootfs not generated" output = subprocess.check_output( ["debugfs", "-R", "ls /usr/share/mender/inventory", rootfs] ) assert ( b"mender-inventory-geo" in output, ), "mender-inventory-network-scripts seems not to be a part of the image, like they should" # # Feature disabled # reset_build_conf(prepared_test_build["build_dir"]) build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['PACKAGECONFIG_remove_pn-mender-client = " inventory-network-scripts"'], ) rootfs = latest_build_artifact( prepared_test_build["build_dir"], "core-image*.ext4" ) assert len(rootfs) > 0, "ext4 not generated" output = subprocess.check_output( ["debugfs", "-R", "ls /usr/share/mender/inventory", rootfs] ) assert ( b"mender-inventory-geo" not in output, ), "mender-inventory-network-scripts unexpectedly a part of the image"
def latest_mender_image(conversion, mender_image): assert os.environ.get("BUILDDIR", False), "BUILDDIR must be set" # Find latest built rootfs. if conversion: image_name = os.path.splitext(mender_image)[0] return latest_build_artifact(os.environ["BUILDDIR"], "%s.mender" % image_name) else: return latest_build_artifact(os.environ["BUILDDIR"], "core-image*.mender")
def test_artifact_signing_keys( self, prepared_test_build, bitbake_variables, bitbake_path, bitbake_image ): """Test that MENDER_ARTIFACT_SIGNING_KEY and MENDER_ARTIFACT_VERIFY_KEY works correctly.""" build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, [ 'MENDER_ARTIFACT_SIGNING_KEY = "%s"' % os.path.join(os.getcwd(), signing_key("RSA").private), 'MENDER_ARTIFACT_VERIFY_KEY = "%s"' % os.path.join(os.getcwd(), signing_key("RSA").public), ], ) built_rootfs = latest_build_artifact( prepared_test_build["build_dir"], "core-image*.ext[234]" ) # Copy out the key we just added from the image and use that to # verify instead of the original, just to be sure. subprocess.check_call( [ "debugfs", "-R", "dump -p /etc/mender/artifact-verify-key.pem artifact-verify-key.pem", built_rootfs, ] ) try: built_artifact = latest_build_artifact( prepared_test_build["build_dir"], "core-image*.mender" ) output = subprocess.check_output( [ "mender-artifact", "read", "-k", os.path.join(os.getcwd(), "artifact-verify-key.pem"), built_artifact, ] ).decode() assert output.find("Signature: signed and verified correctly") >= 0 finally: os.remove("artifact-verify-key.pem")
def test_multiple_device_types_compatible(self, prepared_test_build, bitbake_path, bitbake_variables, bitbake_image): """Tests that we can include multiple device_types in the artifact.""" build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['MENDER_DEVICE_TYPES_COMPATIBLE = "machine1 machine2"'], ) image = latest_build_artifact(prepared_test_build["build_dir"], "core-image*.mender") output = run_verbose("mender-artifact read %s" % image, capture=True) assert b"Compatible devices: '[machine1 machine2]'" in output output = subprocess.check_output( "tar xOf %s header.tar.gz | tar xOz header-info" % image, shell=True).decode() data = json.loads(output) if version_is_minimum(bitbake_variables, "mender-artifact", "3.0.0"): assert data["artifact_depends"]["device_type"] == [ "machine1", "machine2" ] else: assert data["device_types_compatible"] == ["machine1", "machine2"]
def test_dataimg_creation(self, bitbake_variables, prepared_test_build, bitbake_image): """Test that we can build a dataimg successfully.""" build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['IMAGE_FSTYPES = "dataimg"'], ) built_img = latest_build_artifact(prepared_test_build["build_dir"], "core-image*.dataimg") # Check that it contains the device_type file, as we expect. with make_tempdir() as tmpdir: menderdir = os.path.join(tmpdir, "mender") if ("ARTIFACTIMG_FSTYPE" in bitbake_variables and bitbake_variables["ARTIFACTIMG_FSTYPE"] == "ubifs"): subprocess.check_call( ["ubireader_extract_files", "-o", tmpdir, built_img]) else: os.mkdir(menderdir) subprocess.check_call([ "debugfs", "-R", "dump -p /mender/device_type %s" % os.path.join(menderdir, "device_type"), built_img, ]) with open(os.path.join(menderdir, "device_type")) as fd: content = fd.read() assert (content == "device_type=%s\n" % bitbake_variables["MENDER_DEVICE_TYPE"])
def test_tenant_token(self, prepared_test_build, bitbake_image): """Test setting a custom tenant-token""" build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, [ 'MENDER_TENANT_TOKEN = "%s"' % "authtentoken", 'IMAGE_FSTYPES += "dataimg"', ], ) built_rootfs = latest_build_artifact(prepared_test_build["build_dir"], "core-image*.dataimg") subprocess.check_call([ "debugfs", "-R", "dump -p /etc/mender/mender.conf mender.conf", built_rootfs, ]) try: with open("mender.conf") as fd: data = json.load(fd) assert data["TenantToken"] == "authtentoken" finally: os.remove("mender.conf")
def ubimg_without_uboot_env(request, latest_ubimg, prepared_test_build, bitbake_image): """The ubireader_utils_info tool and friends don't support our UBI volumes that contain the U-Boot environment and hence not valid UBIFS structures. Therefore, make a new temporary image that doesn't contain U-Boot.""" # The tests are marked with "only_with_image('ubimg')", but that is checked # using a function fixture, and this is a session fixture, which cannot # depend on that. So we need this check here to bail out if we don't find a # ubimg. if not latest_ubimg: pytest.skip("No ubimg found") reset_build_conf(prepared_test_build["build_dir"]) build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['MENDER_FEATURES_DISABLE_append = " mender-uboot"'], ) ubimg = latest_build_artifact(prepared_test_build["build_dir"], "core-image*.ubimg") imgdir = tempfile.mkdtemp() tmpimg = os.path.join(imgdir, os.path.basename(ubimg)) shutil.copyfile(ubimg, tmpimg) def remove_ubimg(): os.unlink(tmpimg) request.addfinalizer(remove_ubimg) return tmpimg
def latest_vexpress_nor(): assert os.environ.get("BUILDDIR", False), "BUILDDIR must be set" # Find latest built ubifs. NOTE: need to include *core-image* otherwise # we'll likely match data partition file - data.ubifs return latest_build_artifact(os.environ["BUILDDIR"], "core-image*.vexpress-nor")
def test_bootloader_embed(self, prepared_test_build, bitbake_image): """Test that MENDER_IMAGE_BOOTLOADER_FILE causes the bootloader to be embedded correctly in the resulting sdimg.""" loader_file = "bootloader.bin" loader_offset = 4 init_env_cmd = "cd %s && . oe-init-build-env %s" % ( prepared_test_build["bitbake_corebase"], prepared_test_build["build_dir"], ) new_bb_vars = get_bitbake_variables( "core-image-minimal", env_setup=init_env_cmd ) loader_dir = new_bb_vars["DEPLOY_DIR_IMAGE"] loader_path = os.path.join(loader_dir, loader_file) run_verbose("mkdir -p %s" % os.path.dirname(loader_path)) run_verbose("cp /etc/os-release %s" % loader_path) build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, [ 'MENDER_IMAGE_BOOTLOADER_FILE = "%s"' % loader_file, 'MENDER_IMAGE_BOOTLOADER_BOOTSECTOR_OFFSET = "%d"' % loader_offset, ], ) built_sdimg = latest_build_artifact( prepared_test_build["build_dir"], "core-image*.sdimg" ) original = os.open(loader_path, os.O_RDONLY) embedded = os.open(built_sdimg, os.O_RDONLY) os.lseek(embedded, loader_offset * 512, 0) block_size = 4096 while True: org_read = os.read(original, block_size) org_read_size = len(org_read) emb_read = os.read(embedded, org_read_size) assert ( org_read == emb_read ), "Embedded bootloader is not identical to the file specified in MENDER_IMAGE_BOOTLOADER_FILE" if org_read_size < block_size: break os.close(original) os.close(embedded)
def setup_colibri_imx7(request, build_dir, connection): latest_uboot = latest_build_artifact(build_dir, "u-boot-nand.imx") latest_ubimg = latest_build_artifact(build_dir, ".ubimg") if not latest_uboot: pytest.fail("failed to find U-Boot binary") if not latest_ubimg: pytest.fail("failed to find latest ubimg for the board") common_board_setup( connection, files=[latest_ubimg, latest_uboot], remote_path="/tmp", image_file=os.path.basename(latest_ubimg), ) def board_cleanup(): common_board_cleanup(connection) request.addfinalizer(board_cleanup)
def versioned_mender_image(request, prepared_test_build, latest_mender_image, bitbake_variables, bitbake_image): """Gets the correct version of the artifact, whether it's the one we build by default, or one we have to produce ourselves. Returns a tuple of version and built image.""" global LAST_BUILD_VERSION version = request.param if version == 1: pytest.fail() if (version >= 2 and not version_is_minimum( bitbake_variables, "mender-artifact", "2.0.0")) or ( version >= 3 and not version_is_minimum( bitbake_variables, "mender-artifact", "3.0.0")): pytest.skip("Requires version %d of mender-artifact format." % version) if version_is_minimum(bitbake_variables, "mender-artifact", "3.0.0"): default_version = 3 elif version_is_minimum(bitbake_variables, "mender-artifact", "2.0.0"): default_version = 2 else: default_version = 2 if LAST_BUILD_VERSION != version: # Run a separate build for this artifact. This doesn't conflict with the # above version because the non-default version ends up in a different # directory. if version != default_version: build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['MENDER_ARTIFACT_EXTRA_ARGS = "-v %d"' % version], ) else: build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ) LAST_BUILD_VERSION = version return ( version, latest_build_artifact(prepared_test_build["build_dir"], "core-image*.mender"), )
def test_module_install( self, prepared_test_build, bitbake_path, latest_rootfs, bitbake_image ): mender_vars = get_bitbake_variables("mender-client") if "modules" in mender_vars["PACKAGECONFIG"].split(): originally_on = True else: originally_on = False output = subprocess.check_output( ["debugfs", "-R", "ls -p /usr/share/mender", latest_rootfs] ).decode() entries = [ elem.split("/")[5] for elem in output.split("\n") if elem.startswith("/") ] if originally_on: assert "modules" in entries build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['PACKAGECONFIG_remove = "modules"'], ) else: assert "modules" not in entries build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['PACKAGECONFIG_append = " modules"'], ) new_rootfs = latest_build_artifact( prepared_test_build["build_dir"], "core-image*.ext4" ) output = subprocess.check_output( ["debugfs", "-R", "ls -p /usr/share/mender", new_rootfs] ).decode() entries = [ elem.split("/")[5] for elem in output.split("\n") if elem.startswith("/") ] if originally_on: assert "modules" not in entries else: assert "modules" in entries
def successful_image_update_mender(request, build_image_fn): """Provide a 'successful_image_update.mender' file in the current directory that contains the latest built update.""" latest_mender_image = latest_build_artifact(build_image_fn(), ".mender") shutil.copy(latest_mender_image, "successful_image_update.mender") print("Copying '%s' to 'successful_image_update.mender'" % latest_mender_image) def cleanup_image_dat(): os.remove("successful_image_update.mender") request.addfinalizer(cleanup_image_dat) return "successful_image_update.mender"
def test_image_rootfs_extra_space(self, prepared_test_build, bitbake_variables, bitbake_image): """Test that setting IMAGE_ROOTFS_EXTRA_SPACE to arbitrary values does not break the build.""" build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['IMAGE_ROOTFS_EXTRA_SPACE_append = " + 640 - 222 + 900"'], ) built_rootfs = latest_build_artifact(prepared_test_build["build_dir"], "core-image*.ext4") assert (os.stat(built_rootfs).st_size == int( bitbake_variables["MENDER_CALC_ROOTFS_SIZE"]) * 1024)
def test_bootimg_creation(self, bitbake_variables, prepared_test_build, bitbake_image): """Test that we can build a bootimg successfully.""" build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['IMAGE_FSTYPES = "bootimg"'], ) built_img = latest_build_artifact(prepared_test_build["build_dir"], "core-image*.bootimg") distro_features = bitbake_variables["MENDER_FEATURES"].split() if "mender-grub" in distro_features and "mender-image-uefi" in distro_features: output = subprocess.check_output( ["mdir", "-i", built_img, "-b", "/EFI/BOOT"]).decode() assert "mender_grubenv1" in output.split("/")
def test_build_artifact_depends_and_provides(self, prepared_test_build, bitbake_image, bitbake_path, dependsprovides): """Test whether a build with enabled Artifact Provides and Depends does indeed add the parameters to the built Artifact""" build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, [param for param in str(dependsprovides).splitlines()], ) image = latest_build_artifact(prepared_test_build["build_dir"], "core-image*.mender") output = run_verbose("mender-artifact read %s" % image, capture=True).decode() other = TestBuild.BuildDependsProvides.parse(output) # MEN-2956: Mender-Artifact now writes rootfs-image-checksum by default. # MEN-3482: The new key for the rootfs image checksum is rootfs-image.checksum assert ( "rootfs-image.checksum" in other.provides or "rootfs_image_checksum" in other.provides ), "Empty rootfs_image_checksum in the built rootfs-image artifact, this should be added by default by `mender-artifact write rootfs-image`" # Then remove it, not to mess up the expected test output if "rootfs-image.checksum" in other.provides.keys(): del other.provides["rootfs-image.checksum"] if "rootfs_image_checksum" in other.provides.keys(): del other.provides["rootfs_image_checksum"] # MEN-3076: Mender-Artifacts writes software version by default # older versions did not, thus we remove the key before asserting the content if "rootfs-image.version" in other.provides.keys(): del other.provides["rootfs-image.version"] assert dependsprovides.__dict__ == other.__dict__
def test_extra_parts(self, latest_part_image, prepared_test_build, bitbake_image): sdimg = latest_part_image.endswith(".sdimg") uefiimg = latest_part_image.endswith(".uefiimg") gptimg = latest_part_image.endswith(".gptimg") biosimg = latest_part_image.endswith(".biosimg") with make_tempdir() as tmpdir1, make_tempdir( ) as tmpdir2, make_tempdir() as tmpdir3, make_tempdir() as tmpdir4: with open(os.path.join(tmpdir1, "tmpfile1"), "w") as fd: fd.write("Test content1\n") with open(os.path.join(tmpdir2, "tmpfile2"), "w") as fd: fd.write("Test content2\n") with open(os.path.join(tmpdir3, "tmpfile3"), "w") as fd: fd.write("Test content3\n") with open(os.path.join(tmpdir4, "tmpfile4"), "w") as fd: fd.write("Test content4\n") build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, [ 'MENDER_EXTRA_PARTS = "test1 test2 test3 test4"', 'MENDER_EXTRA_PARTS[test1] = "--fixed-size 100M --label=test1 --fstype=ext4 --source rootfs --rootfs-dir %s"' % tmpdir1, 'MENDER_EXTRA_PARTS[test2] = "--fixed-size 50M --fstype=ext4 --source rootfs --rootfs-dir %s --label=test2"' % tmpdir2, 'MENDER_EXTRA_PARTS[test3] = "--fixed-size 50M --fstype=ext4 --source rootfs --rootfs-dir %s --label=test3"' % tmpdir3, 'MENDER_EXTRA_PARTS[test4] = "--fixed-size 50M --fstype=ext4 --source rootfs --rootfs-dir %s --label=test4"' % tmpdir4, 'MENDER_EXTRA_PARTS_FSTAB[test1] = "auto nouser"', 'MENDER_EXTRA_PARTS_FSTAB[test2] = "ext4 default,ro"', 'MENDER_EXTRA_PARTS_FSTAB[test3] = "ext4 default,ro 1"', 'MENDER_EXTRA_PARTS_FSTAB[test4] = "ext4 default,ro 1 0"', ], ) image = latest_build_artifact(prepared_test_build["build_dir"], "*img") # Take extended partition into account for MBR partition tables. if uefiimg or gptimg: # Example # 1 16384 49151 16.0 MiB 0700 Microsoft basic data # 2 49152 507903 224.0 MiB 8300 Linux filesystem # 3 507904 966655 224.0 MiB 8300 Linux filesystem # 4 983040 1245183 128.0 MiB 8300 Linux filesystem # 5 1261568 1466367 100.0 MiB 8300 Linux filesystem # 6 1474560 1679359 100.0 MiB 8300 Linux filesystem output = subprocess.check_output(["sgdisk", "-p", image]).decode() test1_re = r"^\s*5\s+([0-9]+)\s+([0-9]+)\s+100.0\s+MiB\s+8300\s+" test2_re = r"^\s*6\s+([0-9]+)\s+([0-9]+)\s+50.0\s+MiB\s+8300\s+" test3_re = r"^\s*7\s+([0-9]+)\s+([0-9]+)\s+50.0\s+MiB\s+8300\s+" test4_re = r"^\s*8\s+([0-9]+)\s+([0-9]+)\s+50.0\s+MiB\s+8300\s+" extra_start = 5 else: # Example: # ...sdimg1 * 16384 49151 32768 16M c W95 FAT32 (LBA) # ...sdimg2 49152 507903 458752 224M 83 Linux # ...sdimg3 507904 966655 458752 224M 83 Linux # ...sdimg4 983039 1576959 593921 290M f W95 Ext'd (LBA) # ...sdimg5 983040 1245183 262144 128M 83 Linux # ...sdimg6 1261568 1466367 204800 100M 83 Linux # ...sdimg7 1474560 1576959 102400 50M 83 Linux output = subprocess.check_output(["fdisk", "-l", image]).decode() test1_re = r"img6(?:\s|\*)+([0-9]+)\s+([0-9]+)\s+[0-9]+\s+100M\s+83\s+" test2_re = r"img7(?:\s|\*)+([0-9]+)\s+([0-9]+)\s+[0-9]+\s+50M\s+83\s+" test3_re = r"img8(?:\s|\*)+([0-9]+)\s+([0-9]+)\s+[0-9]+\s+50M\s+83\s+" test4_re = r"img9(?:\s|\*)+([0-9]+)\s+([0-9]+)\s+[0-9]+\s+50M\s+83\s+" extra_start = 6 match1 = re.search(test1_re, output, flags=re.MULTILINE) match2 = re.search(test2_re, output, flags=re.MULTILINE) match3 = re.search(test3_re, output, flags=re.MULTILINE) match4 = re.search(test4_re, output, flags=re.MULTILINE) assert match1 is not None assert match2 is not None assert match3 is not None assert match4 is not None ext4 = latest_build_artifact(prepared_test_build["build_dir"], "*.ext4") fstab = subprocess.check_output( ["debugfs", "-R", "cat /etc/fstab", ext4]).decode() # Example: # /dev/mmcblk0p5 /mnt/test1 auto nouser 0 2 # /dev/mmcblk0p6 /mnt/test2 auto default,ro 0 2 # /dev/mmcblk0p7 /mnt/test3 auto default,ro 1 2 # /dev/mmcblk0p8 /mnt/test4 auto default,ro 1 0 test1_re = ( r"^/dev/[a-z0-9]+%d\s+/mnt/test1\s+auto\s+nouser\s+0\s+2\s*$" % extra_start) test2_re = r"^/dev/[a-z0-9]+%d\s+/mnt/test2\s+ext4\s+default,ro\s+0\s+2\s*$" % ( extra_start + 1) test3_re = r"^/dev/[a-z0-9]+%d\s+/mnt/test3\s+ext4\s+default,ro\s+1\s+2\s*$" % ( extra_start + 2) test4_re = r"^/dev/[a-z0-9]+%d\s+/mnt/test4\s+ext4\s+default,ro\s+1\s+0\s*$" % ( extra_start + 3) assert re.search(test1_re, fstab, flags=re.MULTILINE) is not None assert re.search(test2_re, fstab, flags=re.MULTILINE) is not None assert re.search(test3_re, fstab, flags=re.MULTILINE) is not None assert re.search(test4_re, fstab, flags=re.MULTILINE) is not None
def test_equal_checksum_ubimg_and_artifact(self, prepared_test_build, bitbake_image): # See ubimg_without_uboot_env() for why this is needed. We need to do it # explicitly here because we need both the artifact and the ubimg. build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['MENDER_FEATURES_DISABLE_append = " mender-uboot"'], ) bufsize = 1048576 # 1MiB with tempfile.NamedTemporaryFile() as tmp_artifact: latest_mender_image = latest_build_artifact( prepared_test_build["build_dir"], "*.mender") subprocess.check_call( "tar xOf %s data/0000.tar.gz | tar xzO > %s" % (latest_mender_image, tmp_artifact.name), shell=True, ) size = os.stat(tmp_artifact.name).st_size hash = hashlib.md5() while True: buf = tmp_artifact.read(bufsize) if len(buf) == 0: break hash.update(buf) artifact_hash = hash.hexdigest() artifact_info = subprocess.check_output( ["ubireader_display_info", tmp_artifact.name]) artifact_ls = subprocess.check_output( ["ls", "-l", tmp_artifact.name]) tmpdir = tempfile.mkdtemp() try: ubifsdir = extract_ubimg_images( latest_build_artifact(prepared_test_build["build_dir"], "*.ubimg"), tmpdir, ) rootfsa = os.path.join(ubifsdir, [ img for img in os.listdir(ubifsdir) if "rootfsa" in img ][0]) bytes_read = 0 hash = hashlib.md5() with open(rootfsa, "rb") as fd: while bytes_read < size: buf = fd.read(min(size - bytes_read, bufsize)) if len(buf) == 0: break bytes_read += len(buf) hash.update(buf) image_hash = hash.hexdigest() image_info = subprocess.check_output( ["ubireader_display_info", rootfsa]) image_ls = subprocess.check_output(["ls", "-l", rootfsa]) finally: shutil.rmtree(tmpdir) assert artifact_info == image_info assert artifact_hash == image_hash, "Artifact:\n%s\nImage:\n%s" % ( artifact_ls, image_ls, )
def latest_ubimg(): assert os.environ.get("BUILDDIR", False), "BUILDDIR must be set" # Find latest built ubimg. return latest_build_artifact(os.environ["BUILDDIR"], "core-image*.ubimg")
def setup_qemu(request, qemu_wrapper, build_dir, conn): latest_sdimg = latest_build_artifact(build_dir, ".sdimg") latest_uefiimg = latest_build_artifact(build_dir, ".uefiimg") latest_biosimg = latest_build_artifact(build_dir, ".biosimg") latest_gptimg = latest_build_artifact(build_dir, ".gptimg") latest_vexpress_nor = latest_build_artifact(build_dir, ".vexpress-nor") if latest_sdimg: qemu, img_path = start_qemu_block_storage(latest_sdimg, suffix=".sdimg", conn=conn, qemu_wrapper=qemu_wrapper) elif latest_uefiimg: qemu, img_path = start_qemu_block_storage(latest_uefiimg, suffix=".uefiimg", conn=conn, qemu_wrapper=qemu_wrapper) elif latest_biosimg: qemu, img_path = start_qemu_block_storage(latest_biosimg, suffix=".biosimg", conn=conn, qemu_wrapper=qemu_wrapper) elif latest_gptimg: qemu, img_path = start_qemu_block_storage(latest_gptimg, suffix=".gptimg", conn=conn, qemu_wrapper=qemu_wrapper) elif latest_vexpress_nor: qemu, img_path = start_qemu_flash(latest_vexpress_nor, conn=conn, qemu_wrapper=qemu_wrapper) else: pytest.fail("cannot find a suitable image type") print("qemu started with pid {}, image {}".format(qemu.pid, img_path)) # Make sure we revert to the first root partition on next reboot, makes test # cases more predictable. def qemu_finalizer(): def qemu_finalizer_impl(conn): # Try clearing firmware variables try: manual_uboot_commit(conn) except: pass # Collect the coverage files from /data/mender/ if present try: conn.run("ls /data/mender/cover*") Path("coverage").mkdir(exist_ok=True) get_no_sftp("/data/mender/cover*", conn, local="coverage") except: pass # Try clean poweroff try: conn.run("poweroff") halt_time = time.time() # Wait up to 30 seconds for shutdown. while halt_time + 30 > time.time() and qemu.poll() is None: time.sleep(1) except: pass # Terminate qemu try: qemu.terminate() except OSError as oserr: # qemu might have exited before we reached this place if oserr.errno == errno.ESRCH: pass else: raise qemu.wait() os.remove(img_path) qemu_finalizer_impl(conn=conn) request.addfinalizer(qemu_finalizer)
def test_boot_partition_population(self, prepared_test_build, bitbake_path, bitbake_image): # Notice in particular a mix of tabs, newlines and spaces. All there to # check that whitespace it treated correctly. build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, [ """ IMAGE_INSTALL_append = " test-boot-files" IMAGE_BOOT_FILES_append = " deployed-test1 deployed-test-dir2/deployed-test2 \ deployed-test3;renamed-deployed-test3 \ deployed-test-dir4/deployed-test4;renamed-deployed-test4 deployed-test5;renamed-deployed-test-dir5/renamed-deployed-test5 \ deployed-test-dir6/deployed-test6;renamed-deployed-test-dir6/renamed-deployed-test6 \ deployed-test-dir7/* \ deployed-test-dir8/*;./ \ deployed-test-dir9/*;renamed-deployed-test-dir9/ \ " """ ], ) image = latest_build_artifact(prepared_test_build["build_dir"], "core-image*.*img") extract_partition(image, 1) try: listing = (run_verbose("mdir -i img1.fs -b -/", capture=True).decode().split()) expected = [ "::/deployed-test1", "::/deployed-test2", "::/renamed-deployed-test3", "::/renamed-deployed-test4", "::/renamed-deployed-test-dir5/renamed-deployed-test5", "::/renamed-deployed-test-dir6/renamed-deployed-test6", "::/deployed-test7", "::/deployed-test8", "::/renamed-deployed-test-dir9/deployed-test9", ] assert all([item in listing for item in expected]) # Conflicting file with the same content should pass. build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['IMAGE_BOOT_FILES_append = " conflict-test1"'], ) # Conflicting file with different content should fail. try: build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['IMAGE_BOOT_FILES_append = " conflict-test2"'], ) pytest.fail( "Bitbake succeeded, but should have failed with a file conflict" ) except subprocess.CalledProcessError: pass finally: os.remove("img1.fs")
def test_state_scripts( self, prepared_test_build, bitbake_variables, bitbake_path, latest_rootfs, latest_mender_image, bitbake_image, ): """Test that state scripts that are specified in the build are included correctly.""" # First verify that the base build does *not* contain any state scripts. # Check rootfs. output = subprocess.check_output( ["debugfs", "-R", "ls -p /etc/mender", latest_rootfs]).decode() for line in output.split("\n"): if len(line) == 0: continue entry = line.split("/") if entry[5] == "scripts": # The scripts directory exists. That is fine in itself, but it # should not contain any script files ("version" is allowed). output = subprocess.check_output([ "debugfs", "-R", "ls -p /etc/mender/scripts", latest_rootfs ]).decode() for line in output.split("\n"): if len(line) == 0: continue entry = line.split("/") assert ( entry[5] == "." or entry[5] == ".." or entry[5] == "version" ), "There should be no script file in /etc/mender/scripts" break # Check artifact. output = subprocess.check_output("tar xOf %s header.tar.gz| tar tz" % latest_mender_image, shell=True).decode() for line in output.strip().split("\n"): if line == "scripts": output = subprocess.check_output( "tar xOf %s header.tar.gz| tar tz scripts" % latest_mender_image, shell=True, ).decode() assert len(output.strip()) == 0, ( "Unexpected scripts in base image: %s" % output) try: # Alright, now build a new image containing scripts. build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, ['IMAGE_INSTALL_append = " example-state-scripts"'], ) found_rootfs_scripts = { "version": False, "Idle_Enter_00": False, "Sync_Enter_10": False, "Sync_Leave_90": False, } found_artifact_scripts = { "ArtifactInstall_Enter_00": False, "ArtifactInstall_Leave_99": False, "ArtifactReboot_Leave_50": False, "ArtifactCommit_Enter_50": False, "ArtifactCommit_Leave_50": False, } # Check new rootfs. built_rootfs = latest_build_artifact( prepared_test_build["build_dir"], "core-image*.ext[234]") output = subprocess.check_output( ["debugfs", "-R", "ls -p /etc/mender/scripts", built_rootfs]).decode() for line in output.split("\n"): if len(line) == 0: continue entry = line.split("/") if entry[5] == "." or entry[5] == "..": continue assert found_rootfs_scripts.get( entry[5]) is not None, ("Unexpected script in rootfs %s" % entry[5]) found_rootfs_scripts[entry[5]] = True for script in found_rootfs_scripts: assert found_rootfs_scripts[script], ( "%s not found in rootfs script list" % script) # Check new artifact. built_mender_image = latest_build_artifact( prepared_test_build["build_dir"], "core-image*.mender") output = subprocess.check_output( "tar xOf %s header.tar.gz| tar tz scripts" % built_mender_image, shell=True, ).decode() for line in output.strip().split("\n"): script = os.path.basename(line) assert found_artifact_scripts.get(script) is not None, ( "Unexpected script in image: %s" % script) found_artifact_scripts[script] = True for script in found_artifact_scripts: assert found_artifact_scripts[script], ( "%s not found in artifact script list" % script) finally: # Clean up the state scripts directory. Ideally this wouldn't be # necessary, but unfortunately bitbake does not clean up deployment # files from recipes that are not included in the current build, so # we have to do it manually. build_image( prepared_test_build["build_dir"], prepared_test_build["bitbake_corebase"], bitbake_image, target="-c clean example-state-scripts", )