runqemu fixes
cover runqemu fixes
This series includes several fixes and enhancements for runqemu to better align with the previous shell based implementation.
The following changes since commit 059d475b6bce1e5414170a4fe2e7989f6b0eacd6:
oeqa/utils/decorators: LogResults fix race condition in linkfile (2016-09-15 12:14:40 +0100)
are available in the git repository at:
git://git.openembedded.org/openembedded-core-contrib joshuagl/runqemu
http://cgit.openembedded.org/cgit.cgi/openembedded-core-contrib/log/?h=joshuagl/runqemu
Joshua Lock (6):
runqemu: add guidance to resolve issues with missing files
qemuboot: write the full kernel filename, not the link name
runqemu: clarify an INFO message
qemuboot: also write the kernel link name to the conf file
runqemu: try symlinks when kernel or rootfs can't be found
runqemu: work even if a *.qemuboot.conf isn't found
meta/classes/qemuboot.bbclass | 13 +++++++++++-- scripts/runqemu | 43 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 9 deletions(-)
Signature · 1 line
2.7.4
PATCH 1/6 runqemu: add guidance to resolve issues with missing files
When a required binary cannot be found print some guidance pointing to using a sourced OE build environment or a qemuboot.conf file, based on a similar message from the previous shell-based runqemu.
--- scripts/runqemu | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
scripts/runqemu +16 -3
@@ -28,6 +28,16 @@ import shutil import glob import configparser +class OEPathError(Exception): + """Custom Exception to give better guidance on missing binaries""" + def __init__(self, message): + self.message = "In order for this script to dynamically infer paths\n \ +kernels or filesystem images, you either need bitbake in your PATH\n \ +or to source oe-init-build-env before running this script.\n\n \ +Dynamic path inference can be avoided by passing a *.qemuboot.conf to\n \ +runqemu, i.e. `runqemu /path/to/my-image-name.qemuboot.conf`\n\n %s" % message + + def create_logger(): logger = logging.getLogger('runqemu') logger.setLevel(logging.INFO)
@@ -537,7 +547,7 @@ class BaseConfig(object): elif os.getenv('DEPLOY_DIR_IMAGE'): deploy_dir_image = os.getenv('DEPLOY_DIR_IMAGE') else: - raise Exception("DEPLOY_DIR_IMAGE is NULL!") + raise OEPathError("DEPLOY_DIR_IMAGE is NULL!") if self.rootfs and not os.path.exists(self.rootfs): # Lazy rootfs
@@ -691,7 +701,7 @@ class BaseConfig(object): lockdir = "/tmp/qemu-tap-locks" if not (self.qemuifup and self.qemuifdown and ip): - raise Exception("runqemu-ifup, runqemu-ifdown or ip not found") + raise OEPathError("runqemu-ifup, runqemu-ifdown or ip not found") if not os.path.exists(lockdir): # There might be a race issue when multi runqemu processess are
@@ -808,7 +818,7 @@ class BaseConfig(object): qemu_bin = '%s/%s' % (self.get('STAGING_BINDIR_NATIVE'), qemu_system) if not os.access(qemu_bin, os.X_OK): - raise Exception("No QEMU binary '%s' could be found" % qemu_bin) + raise OEPathError("No QEMU binary '%s' could be found" % qemu_bin) check_libgl(qemu_bin)
@@ -923,6 +933,9 @@ def main(): if __name__ == "__main__": try: ret = main() + except OEPathError as err: + ret = 1 + logger.error(err.message) except Exception as esc: ret = 1 import traceback
Signature · 1 line
2.7.4
PATCH 2/6 qemuboot: write the full kernel filename, not the link name
In reply to Joshua LockKERNEL_IMAGETYPE gives the filename of a symlink to the kernel, which may not be available i.e. if the user downloads some build artefacts to run on a local machine. It's also possible that the link will point to a newer kernel than was intended for use with the rootfs in the qemuboot.conf.
It's much more reliable to read the name of the file KERNEL_IMAGETYPE is linking to and assign the full filename to QB_DEFAULT_KERNEL.
[YOCTO #10285]
--- meta/classes/qemuboot.bbclass | 8 ++++++++ 1 file changed, 8 insertions(+)
meta/classes/qemuboot.bbclass +8 -0
@@ -63,6 +63,14 @@ python write_qemuboot_conf() { cf.add_section('config_bsp') for k in build_vars + qb_vars: cf.set('config_bsp', k, '%s' % d.getVar(k, True)) + + # QB_DEFAULT_KERNEL's value of KERNEL_IMAGETYPE is the name of a symlink + # to the kernel file, which hinders relocatability of the qb conf. + # Read the link and replace it with the full filename of the target. + kernel_link = os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), d.getVar('QB_DEFAULT_KERNEL', True)) + kernel = os.readlink(kernel_link) + cf.set('config_bsp', 'QB_DEFAULT_KERNEL', kernel) + with open(qemuboot, 'w') as f: cf.write(f)
Signature · 1 line
2.7.4
PATCH 3/6 runqemu: clarify an INFO message
In reply to Joshua LockMake it clearer that we are looking for a file which ends with qemuboot.conf
--- scripts/runqemu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
scripts/runqemu +1 -1
@@ -205,7 +205,7 @@ class BaseConfig(object): def is_deploy_dir_image(self, p): if os.path.isdir(p): if not re.search('.qemuboot.conf$', '\n'.join(os.listdir(p)), re.M): - logger.info("Can't find required qemuboot.conf in %s" % p) + logger.info("Can't find required *.qemuboot.conf in %s" % p) return False if not re.search('-image-', '\n'.join(os.listdir(p))): logger.info("Can't find *-image-* in %s" % p)
Signature · 1 line
2.7.4
PATCH 4/6 qemuboot: also write the kernel link name to the conf file
In reply to Joshua LockThis will allow runqemu to fall back to trying the link name when a file matching the full name can't be found.
--- meta/classes/qemuboot.bbclass | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
meta/classes/qemuboot.bbclass +3 -2
@@ -48,8 +48,9 @@ python write_qemuboot_conf() { import configparser build_vars = ['MACHINE', 'TUNE_ARCH', 'DEPLOY_DIR_IMAGE', \ - 'IMAGE_NAME', 'IMAGE_LINK_NAME', 'STAGING_DIR_NATIVE', \ - 'STAGING_BINDIR_NATIVE', 'STAGING_DIR_HOST'] + 'KERNEL_IMAGETYPE', 'IMAGE_NAME', 'IMAGE_LINK_NAME', \ + 'STAGING_DIR_NATIVE', 'STAGING_BINDIR_NATIVE', \ + 'STAGING_DIR_HOST'] # Vars from bsp qb_vars = []
Signature · 1 line
2.7.4
PATCH 5/6 runqemu: try symlinks when kernel or rootfs can't be found
In reply to Joshua LockIf the kernel or rootfs names written to the qemuboot.conf can't be found, try and find the symlinked variant of the filename.
This will help usability of runqemu, for example where a user downloads an image and associated files as the symlinked names yet the qemuboot.conf variables point to the full, non-linked, file names.
--- scripts/runqemu | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
scripts/runqemu +13 -3
@@ -451,7 +451,12 @@ class BaseConfig(object): if all_files: self.rootfs = all_files[0] else: - raise Exception("Failed to find rootfs: %s" % cmd) + cmd = '%s/%s*.%s' % (self.get('DEPLOY_DIR_IMAGE'), self.get('IMAGE_LINK_NAME'), self.fstype) + all_files = glob.glob(cmd) + if all_files: + self.rootfs = all_files[0] + else: + raise Exception("Failed to find rootfs: %s" % cmd) if not os.path.exists(self.rootfs): raise Exception("Can't find rootfs: %s" % self.rootfs)
@@ -462,13 +467,18 @@ class BaseConfig(object): if self.fstype in self.vmtypes: return kernel = self.kernel + deploy_dir_image = self.get('DEPLOY_DIR_IMAGE') if not kernel: - kernel = "%s/%s" % (self.get('DEPLOY_DIR_IMAGE'), self.get('QB_DEFAULT_KERNEL')) + kernel = "%s/%s" % (deploy_dir_image, self.get('QB_DEFAULT_KERNEL')) if os.path.exists(kernel): self.kernel = kernel else: - raise Exception("KERNEL %s not found" % kernel) + kernel = "%s/%s" % (deploy_dir_image, self.get('KERNEL_IMAGETYPE')) + if kernel != deploy_dir_image and os.path.exists(kernel): + self.kernel = kernel + else: + raise Exception("KERNEL %s not found" % kernel) dtb = self.get('QB_DTB') if dtb:
Signature · 1 line
2.7.4
Re: [PATCH 5/6] runqemu: try symlinks when kernel or rootfs can't be found
Quoted 36 lines · Joshua Lock
If the kernel or rootfs names written to the qemuboot.conf can't be found, try and find the symlinked variant of the filename.
This will help usability of runqemu, for example where a user downloads an image and associated files as the symlinked names yet the qemuboot.conf variables point to the full, non-linked, file names.
Signed-off-by Joshua Lock <[email protected]>--- scripts/runqemu | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)scripts/runqemu +7
-1@@ -451,7 +451,12 @@ class BaseConfig(object): if all_files: self.rootfs = all_files[0] else: - raise Exception("Failed to find rootfs: %s" % cmd) + cmd = '%s/%s*.%s' % (self.get('DEPLOY_DIR_IMAGE'), self.get('IMAGE_LINK_NAME'), self.fstype) + all_files = glob.glob(cmd) + if all_files: + self.rootfs = all_files[0] + else: + raise Exception("Failed to find rootfs: %s" % cmd) if not os.path.exists(self.rootfs): raise Exception("Can't find rootfs: %s" % self.rootfs)@@ -462,13 +467,18 @@ class BaseConfig(object): if self.fstype in self.vmtypes: return kernel = self.kernel + deploy_dir_image = self.get('DEPLOY_DIR_IMAGE')
scripts/runqemu class BaseConfig(object): · line 478
Quoted 10 lines
scripts/runqemu +3
-2if not kernel: - kernel = "%s/%s" % (self.get('DEPLOY_DIR_IMAGE'), self.get('QB_DEFAULT_KERNEL')) + kernel = "%s/%s" % (deploy_dir_image, self.get('QB_DEFAULT_KERNEL')) if os.path.exists(kernel): self.kernel = kernel else: - raise Exception("KERNEL %s not found" % kernel) + kernel = "%s/%s" % (deploy_dir_image, self.get('KERNEL_IMAGETYPE')) + if kernel != deploy_dir_image and os.path.exists(kernel):
Thank you very much for fixing this, can we use KERNEL_IMAGETYPE* here, please ? Please take a look at here:
http://autobuilder.yoctoproject.org/pub/releases/yocto-2.2_M3.rc1/machines/qemu/qemuppc/
Its kernel name might be vmlinux-qemuppc.bin, while KERNEL_IMAGETYPE is vmlinux.
I have local patches conflicted with this, they also fix dtb, OECORE_NATIVE_SYSROOT and nfs. I will send a V2 including your patches, and please feel free to comment.
// Robert
Quoted 7 lines
scripts/runqemu +3
-0+ self.kernel = kernel + else: + raise Exception("KERNEL %s not found" % kernel) dtb = self.get('QB_DTB') if dtb:
PATCH 6/6 runqemu: work even if a *.qemuboot.conf isn't found
In reply to Joshua LockA qemuboot conf file is a convenience but it should still be possible to invoke runqemu without them, especially for examples such as using the SDK with an extracted rootfs via NFS.
As read_qemuboot() is always called we need to be sure that function can return cleanly, without throwing Exceptions, even if a qemuboot conf file isn't found.
--- scripts/runqemu | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
scripts/runqemu +7 -1
@@ -557,7 +557,8 @@ class BaseConfig(object): elif os.getenv('DEPLOY_DIR_IMAGE'): deploy_dir_image = os.getenv('DEPLOY_DIR_IMAGE') else: - raise OEPathError("DEPLOY_DIR_IMAGE is NULL!") + logger.info("Can't find qemuboot conf file, DEPLOY_DIR_IMAGE is NULL!") + return if self.rootfs and not os.path.exists(self.rootfs): # Lazy rootfs
@@ -574,6 +575,11 @@ class BaseConfig(object): self.qemuboot = qbs.split()[0] self.qbconfload = True + if not self.qemuboot: + # If we haven't found a .qemuboot.conf at this point it probably + # doesn't exist, continue without + return + if not os.path.exists(self.qemuboot): raise Exception("Failed to find <image>.qemuboot.conf!")
Signature · 1 line
2.7.4