From: michael.opdenacker@bootlin.com
To: openembedded-core@lists.openembedded.org
Cc: Michael Opdenacker <michael.opdenacker@bootlin.com>,
Richard Purdie <richard.purdie@linuxfoundation.org>,
Thomas Petazzoni <thomas.petazzoni@bootlin.com>,
Bruce Ashfield <bruce.ashfield@gmail.com>
Subject: [RFC][PATCH] oeqa/runtime/cases: new image_upgrade test
Date: Thu, 25 Apr 2024 17:46:07 +0200 [thread overview]
Message-ID: <20240425154607.566716-1-michael.opdenacker@bootlin.com> (raw)
From: Michael Opdenacker <michael.opdenacker@bootlin.com>
New oe-selftest and associated "testimage" test to check that generated
package feeds can be used to update the latest image built
by the Yocto Project autobuilder.
Currently, only the "core-image-full-cmdline" image with IPK packages
and the "poky-altcfg" distro is supported.
Test it by running:
oe-selftest -r image_upgrade
Signed-off-by: Michael Opdenacker <michael.opdenacker@bootlin.com>
Suggested-by: Richard Purdie <richard.purdie@linuxfoundation.org>
CC: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
CC: Bruce Ashfield <bruce.ashfield@gmail.com>
---
Tested on the latest master against yocto-5.0_M3
Interested in your feedback about which settings (such as IMAGE)
can be hardcoded in the scripts or provided by the calling environment.
---
.../lib/oeqa/runtime/cases/opkg_sysupgrade.py | 68 ++++++++++
meta/lib/oeqa/selftest/cases/image_upgrade.py | 124 ++++++++++++++++++
2 files changed, 192 insertions(+)
create mode 100644 meta/lib/oeqa/runtime/cases/opkg_sysupgrade.py
create mode 100755 meta/lib/oeqa/selftest/cases/image_upgrade.py
diff --git a/meta/lib/oeqa/runtime/cases/opkg_sysupgrade.py b/meta/lib/oeqa/runtime/cases/opkg_sysupgrade.py
new file mode 100644
index 0000000000..05b5847b4a
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/opkg_sysupgrade.py
@@ -0,0 +1,68 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# Test that generated ipk packages can be used to upgrade
+# an older image version.
+#
+# This is done by the meta/lib/oeqa/selftest/cases/image_upgrade.py oe-selftest
+# replacing the newly generated image by an older image
+# generated by the Yocto Project autobuilder.
+#
+# Here, we replace the package feeds in our image by our own
+#
+# This test is not meant to be used as a regular "testimage" test
+# run on the fresh image.
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+from oeqa.utils.httpserver import HTTPService
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.data import skipIfNotDataVar, skipIfNotFeature, skipIfFeature
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class OpkgSysUpgradeTest(OERuntimeTestCase):
+
+ def pkg(self, command, expected = 0):
+ command = 'opkg %s' % command
+ status, output = self.target.run(command, 1500)
+ message = os.linesep.join([command, output])
+ self.assertEqual(status, expected, message)
+ return output
+
+class OpkgRepoTest(OpkgSysUpgradeTest):
+
+ @classmethod
+ def setUp(cls):
+ service_repo = os.path.join(cls.tc.td['DEPLOY_DIR_IPK'])
+ cls.repo_server = HTTPService(service_repo,
+ '0.0.0.0', port=cls.tc.target.server_port,
+ logger=cls.tc.logger)
+ cls.repo_server.start()
+
+ @classmethod
+ def tearDown(cls):
+ cls.repo_server.stop()
+
+ def setup_source_config_for_package_install(self):
+ source_server = 'http://%s:%s' % (self.tc.target.server_ip, self.repo_server.port)
+ sourceslist_dir = '/etc/opkg'
+ pkgarch = self.tc.td["TUNE_PKGARCH"]
+ machinedir = self.tc.td["MACHINE"].replace("-", "_")
+ self.target.run('cd %s; echo src/gz all %s/all > base-feeds.conf' % (sourceslist_dir, source_server))
+ self.target.run('cd %s; echo src/gz %s %s/%s >> base-feeds.conf' % (sourceslist_dir, pkgarch, source_server, pkgarch))
+ self.target.run('cd %s; echo src/gz %s %s/%s >> base-feeds.conf' % (sourceslist_dir, machinedir, source_server, machinedir))
+
+ @skipIfNotFeature('package-management',
+ 'Test requires package-management to be in IMAGE_FEATURES')
+ @skipIfNotDataVar('IMAGE_PKGTYPE', 'ipk',
+ 'IPK is not the primary package manager')
+ @skipIfFeature('read-only-rootfs',
+ 'Test does not work with read-only-rootfs in IMAGE_FEATURES')
+ @OEHasPackage(['opkg'])
+ def test_opkg_system_upgrade_from_repo(self):
+ self.setup_source_config_for_package_install()
+ self.pkg('update')
+ self.pkg('upgrade')
+
diff --git a/meta/lib/oeqa/selftest/cases/image_upgrade.py b/meta/lib/oeqa/selftest/cases/image_upgrade.py
new file mode 100755
index 0000000000..3e26c7eed0
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/image_upgrade.py
@@ -0,0 +1,124 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+import os
+import subprocess
+from oeqa.selftest.case import OESelftestTestCase
+from oeqa.utils.commands import bitbake, runCmd, get_bb_var
+from oeqa.core.decorator.data import skipIfNotQemu
+
+basepath = os.path.abspath(os.path.dirname(__file__) + '/../../../../../')
+
+# Version string utilities copied from yocto-autobuilder-helper/scripts/utils.py
+
+def get_string_from_version(version, milestone=None, rc=None):
+ """ Point releases finishing by 0 (e.g 4.0.0, 4.1.0) do no exists,
+ those are major releases
+ """
+ if len(version) == 3 and version[-1] == 0:
+ version = version[:-1]
+
+ result = ".".join(list(map(str, version)))
+ if milestone:
+ result += "_M" + str(milestone)
+ if rc:
+ result += ".rc" + str(rc)
+ return result
+
+def get_tag_from_version(version, milestone):
+ if not milestone:
+ return "yocto-" + get_string_from_version(version, milestone)
+ return get_string_from_version(version, milestone)
+
+def get_version_from_string(raw_version):
+ """ Get version as list of int from raw_version.
+
+ Raw version _can_ be prefixed by "yocto-",
+ Raw version _can_ be suffixed by "_MX"
+ Raw version _can_ be suffixed by ".rcY"
+ """
+ version = None
+ milestone = None
+ rc = None
+ if raw_version[:6] == "yocto-":
+ raw_version = raw_version[6:]
+ raw_version = raw_version.split(".")
+ if raw_version[-1][:2] == "rc":
+ rc = int(raw_version[-1][-1])
+ raw_version = raw_version[:-1]
+ if raw_version[-1][-3:-1] == "_M":
+ milestone = int(raw_version[-1][-1])
+ raw_version = raw_version[:-1] + [raw_version[-1][:-3]]
+ version = list(map(int, raw_version))
+ """ Point releases finishing by 0 (e.g 4.0.0, 4.1.0) do no exists,
+ those are major releases
+ """
+ if len(version) == 3 and version[-1] == 0:
+ version = version[:-1]
+ return version, milestone, rc
+
+def get_latest_image_url(machine, machine_variant, image_file):
+
+ """Returns the URL of the latest generated image for the current branch"""
+
+ baseversion, milestone, _ = get_version_from_string(subprocess.check_output(["git", "describe", "--abbrev=0"], cwd=basepath).decode('utf-8').strip())
+ tag = get_tag_from_version(baseversion, milestone)
+ downloads_base = "https://downloads.yoctoproject.org/releases/yocto/"
+
+ if milestone is not None:
+ downloads_base += "milestones/yocto-%s" % tag
+ else:
+ downloads_base += tag
+
+ return "%s/machines/qemu/%s%s/%s" % (downloads_base, machine, machine_variant, image_file)
+
+class ImageIpkUpgrade(OESelftestTestCase):
+
+ @skipIfNotQemu()
+ def test_image_upgrade(self):
+ """
+ Summary: Test that generated ipk packages can
+ be used to upgrade an older image version.
+ This is done by generating an image but then replacing it
+ by an older image shared by the Yocto Project autobuilder.
+ We then run QEMU on the old image and replace the original
+ original package feeds by our own.
+ """
+
+ image = 'core-image-full-cmdline'
+ machine = get_bb_var("MACHINE")
+
+ features = 'DISTRO = "poky-altcfg"\n'
+ features += 'EXTRA_IMAGE_FEATURES += "package-management"\n'
+ features += 'PACKAGE_CLASSES = "package_ipk"\n'
+ features += 'IMAGE_CLASSES += "testimage"\n'
+ features += 'TEST_SUITES="opkg_sysupgrade"\n'
+ self.write_config(features)
+
+ # Need to build a full image to build the .json file needed by QEMU.
+ # Therefore, it is not sufficient to run only "package_write_ipk" for the image.
+
+ self.logger.info("Generating '%s' and package index for latest commit in this branch..." % image)
+ bitbake(image)
+ bitbake('package-index')
+
+ # Download previously generated image
+
+ image_file = '%s-%s.rootfs.ext4' % (image, machine)
+ image_path = '%s/tmp/deploy/images/%s/%s' % (self.builddir, machine, image_file)
+ machine_variant = '-alt'
+
+ os.remove(image_path)
+ image_url = get_latest_image_url(machine, machine_variant, image_file)
+ self.logger.info("Downloading image: %s..." % image_url)
+ cmd = 'wget -O %s %s' % (image_path, image_url)
+ result = runCmd(cmd)
+ self.assertEqual(0, result.status, cmd + ' returned a non 0 status: %s' % result.output)
+
+ # Now run the upgrade tests on the old image
+
+ self.logger.info("Running upgrade tests on the downloaded image, using the package feeds generated here...")
+ bitbake(image + ' -c testimage')
--
2.34.1
next reply other threads:[~2024-04-25 15:46 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-25 15:46 michael.opdenacker [this message]
2024-04-25 20:40 ` [RFC][PATCH] oeqa/runtime/cases: new image_upgrade test Richard Purdie
2024-04-29 15:21 ` [OE-core] " Michael Opdenacker
2024-04-29 16:14 ` Richard Purdie
2024-04-26 8:20 ` Alexander Kanavin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240425154607.566716-1-michael.opdenacker@bootlin.com \
--to=michael.opdenacker@bootlin.com \
--cc=bruce.ashfield@gmail.com \
--cc=openembedded-core@lists.openembedded.org \
--cc=richard.purdie@linuxfoundation.org \
--cc=thomas.petazzoni@bootlin.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox