From eb8dc40360f0cfef56fb6947cc817a547d6d9bc6 Mon Sep 17 00:00:00 2001 From: Dave Cobbley Date: Tue, 14 Aug 2018 10:05:37 -0700 Subject: [Subtree] Removing import-layers directory As part of the move to subtrees, need to bring all the import layers content to the top level. Change-Id: I4a163d10898cbc6e11c27f776f60e1a470049d8f Signed-off-by: Dave Cobbley Signed-off-by: Brad Bishop --- poky/scripts/wic | 542 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 542 insertions(+) create mode 100755 poky/scripts/wic (limited to 'poky/scripts/wic') diff --git a/poky/scripts/wic b/poky/scripts/wic new file mode 100755 index 000000000..7392bc4e7 --- /dev/null +++ b/poky/scripts/wic @@ -0,0 +1,542 @@ +#!/usr/bin/env python3 +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2013, Intel Corporation. +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION 'wic' is the OpenEmbedded Image Creator that users can +# use to generate bootable images. Invoking it without any arguments +# will display help screens for the 'wic' command and list the +# available 'wic' subcommands. Invoking a subcommand without any +# arguments will likewise display help screens for the specified +# subcommand. Please use that interface for detailed help. +# +# AUTHORS +# Tom Zanussi +# +__version__ = "0.2.0" + +# Python Standard Library modules +import os +import sys +import argparse +import logging + +from collections import namedtuple +from distutils import spawn + +# External modules +scripts_path = os.path.dirname(os.path.realpath(__file__)) +lib_path = scripts_path + '/lib' +sys.path.insert(0, lib_path) +import scriptpath +scriptpath.add_oe_lib_path() + +# Check whether wic is running within eSDK environment +sdkroot = scripts_path +if os.environ.get('SDKTARGETSYSROOT'): + while sdkroot != '' and sdkroot != os.sep: + if os.path.exists(os.path.join(sdkroot, '.devtoolbase')): + # Set BUILDDIR for wic to work within eSDK + os.environ['BUILDDIR'] = sdkroot + # .devtoolbase only exists within eSDK + # If found, initialize bitbake path for eSDK environment and append to PATH + sdkroot = os.path.join(os.path.dirname(scripts_path), 'bitbake', 'bin') + os.environ['PATH'] += ":" + sdkroot + break + sdkroot = os.path.dirname(sdkroot) + +bitbake_exe = spawn.find_executable('bitbake') +if bitbake_exe: + bitbake_path = scriptpath.add_bitbake_lib_path() + from bb import cookerdata + from bb.main import bitbake_main, BitBakeConfigParameters +else: + bitbake_main = None + +from wic import WicError +from wic.misc import get_bitbake_var, BB_VARS +from wic import engine +from wic import help as hlp + + +def wic_logger(): + """Create and convfigure wic logger.""" + logger = logging.getLogger('wic') + logger.setLevel(logging.INFO) + + handler = logging.StreamHandler() + + formatter = logging.Formatter('%(levelname)s: %(message)s') + handler.setFormatter(formatter) + + logger.addHandler(handler) + + return logger + +logger = wic_logger() + +def rootfs_dir_to_args(krootfs_dir): + """ + Get a rootfs_dir dict and serialize to string + """ + rootfs_dir = '' + for key, val in krootfs_dir.items(): + rootfs_dir += ' ' + rootfs_dir += '='.join([key, val]) + return rootfs_dir.strip() + + +class RootfsArgAction(argparse.Action): + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def __call__(self, parser, namespace, value, option_string=None): + if not "rootfs_dir" in vars(namespace) or \ + not type(namespace.__dict__['rootfs_dir']) is dict: + namespace.__dict__['rootfs_dir'] = {} + + if '=' in value: + (key, rootfs_dir) = value.split('=') + else: + key = 'ROOTFS_DIR' + rootfs_dir = value + + namespace.__dict__['rootfs_dir'][key] = rootfs_dir + + +def wic_create_subcommand(options, usage_str): + """ + Command-line handling for image creation. The real work is done + by image.engine.wic_create() + """ + if options.build_rootfs and not bitbake_main: + raise WicError("Can't build rootfs as bitbake is not in the $PATH") + + if not options.image_name: + missed = [] + for val, opt in [(options.rootfs_dir, 'rootfs-dir'), + (options.bootimg_dir, 'bootimg-dir'), + (options.kernel_dir, 'kernel-dir'), + (options.native_sysroot, 'native-sysroot')]: + if not val: + missed.append(opt) + if missed: + raise WicError("The following build artifacts are not specified: %s" % + ", ".join(missed)) + + if options.image_name: + BB_VARS.default_image = options.image_name + else: + options.build_check = False + + if options.vars_dir: + BB_VARS.vars_dir = options.vars_dir + + if options.build_check and not engine.verify_build_env(): + raise WicError("Couldn't verify build environment, exiting") + + if options.debug: + logger.setLevel(logging.DEBUG) + + if options.image_name: + if options.build_rootfs: + argv = ["bitbake", options.image_name] + if options.debug: + argv.append("--debug") + + logger.info("Building rootfs...\n") + if bitbake_main(BitBakeConfigParameters(argv), + cookerdata.CookerConfiguration()): + raise WicError("bitbake exited with error") + + rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", options.image_name) + kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE", options.image_name) + bootimg_dir = get_bitbake_var("STAGING_DATADIR", options.image_name) + + native_sysroot = options.native_sysroot + if options.vars_dir and not native_sysroot: + native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", options.image_name) + else: + if options.build_rootfs: + raise WicError("Image name is not specified, exiting. " + "(Use -e/--image-name to specify it)") + native_sysroot = options.native_sysroot + + if not options.vars_dir and (not native_sysroot or not os.path.isdir(native_sysroot)): + logger.info("Building wic-tools...\n") + if bitbake_main(BitBakeConfigParameters("bitbake wic-tools".split()), + cookerdata.CookerConfiguration()): + raise WicError("bitbake wic-tools failed") + native_sysroot = get_bitbake_var("RECIPE_SYSROOT_NATIVE", "wic-tools") + + if not native_sysroot: + raise WicError("Unable to find the location of the native tools sysroot") + + wks_file = options.wks_file + + if not wks_file.endswith(".wks"): + wks_file = engine.find_canned_image(scripts_path, wks_file) + if not wks_file: + raise WicError("No image named %s found, exiting. (Use 'wic list images' " + "to list available images, or specify a fully-qualified OE " + "kickstart (.wks) filename)" % options.wks_file) + + if not options.image_name: + rootfs_dir = '' + if 'ROOTFS_DIR' in options.rootfs_dir: + rootfs_dir = options.rootfs_dir['ROOTFS_DIR'] + bootimg_dir = options.bootimg_dir + kernel_dir = options.kernel_dir + native_sysroot = options.native_sysroot + if rootfs_dir and not os.path.isdir(rootfs_dir): + raise WicError("--rootfs-dir (-r) not found, exiting") + if not os.path.isdir(bootimg_dir): + raise WicError("--bootimg-dir (-b) not found, exiting") + if not os.path.isdir(kernel_dir): + raise WicError("--kernel-dir (-k) not found, exiting") + if not os.path.isdir(native_sysroot): + raise WicError("--native-sysroot (-n) not found, exiting") + else: + not_found = not_found_dir = "" + if not os.path.isdir(rootfs_dir): + (not_found, not_found_dir) = ("rootfs-dir", rootfs_dir) + elif not os.path.isdir(kernel_dir): + (not_found, not_found_dir) = ("kernel-dir", kernel_dir) + elif not os.path.isdir(native_sysroot): + (not_found, not_found_dir) = ("native-sysroot", native_sysroot) + if not_found: + if not not_found_dir: + not_found_dir = "Completely missing artifact - wrong image (.wks) used?" + logger.info("Build artifacts not found, exiting.") + logger.info(" (Please check that the build artifacts for the machine") + logger.info(" selected in local.conf actually exist and that they") + logger.info(" are the correct artifacts for the image (.wks file)).\n") + raise WicError("The artifact that couldn't be found was %s:\n %s", not_found, not_found_dir) + + krootfs_dir = options.rootfs_dir + if krootfs_dir is None: + krootfs_dir = {} + krootfs_dir['ROOTFS_DIR'] = rootfs_dir + + rootfs_dir = rootfs_dir_to_args(krootfs_dir) + + logger.info("Creating image(s)...\n") + engine.wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir, + native_sysroot, options) + + +def wic_list_subcommand(args, usage_str): + """ + Command-line handling for listing available images. + The real work is done by image.engine.wic_list() + """ + if not engine.wic_list(args, scripts_path): + raise WicError("Bad list arguments, exiting") + + +def wic_ls_subcommand(args, usage_str): + """ + Command-line handling for list content of images. + The real work is done by engine.wic_ls() + """ + engine.wic_ls(args, args.native_sysroot) + +def wic_cp_subcommand(args, usage_str): + """ + Command-line handling for copying files/dirs to images. + The real work is done by engine.wic_cp() + """ + engine.wic_cp(args, args.native_sysroot) + +def wic_rm_subcommand(args, usage_str): + """ + Command-line handling for removing files/dirs from images. + The real work is done by engine.wic_rm() + """ + engine.wic_rm(args, args.native_sysroot) + +def wic_write_subcommand(args, usage_str): + """ + Command-line handling for writing images. + The real work is done by engine.wic_write() + """ + engine.wic_write(args, args.native_sysroot) + +def wic_help_subcommand(args, usage_str): + """ + Command-line handling for help subcommand to keep the current + structure of the function definitions. + """ + pass + + +def wic_help_topic_subcommand(usage_str, help_str): + """ + Display function for help 'sub-subcommands'. + """ + print(help_str) + return + + +wic_help_topic_usage = """ +""" + +helptopics = { + "plugins": [wic_help_topic_subcommand, + wic_help_topic_usage, + hlp.wic_plugins_help], + "overview": [wic_help_topic_subcommand, + wic_help_topic_usage, + hlp.wic_overview_help], + "kickstart": [wic_help_topic_subcommand, + wic_help_topic_usage, + hlp.wic_kickstart_help], + "create": [wic_help_topic_subcommand, + wic_help_topic_usage, + hlp.wic_create_help], + "ls": [wic_help_topic_subcommand, + wic_help_topic_usage, + hlp.wic_ls_help], + "cp": [wic_help_topic_subcommand, + wic_help_topic_usage, + hlp.wic_cp_help], + "rm": [wic_help_topic_subcommand, + wic_help_topic_usage, + hlp.wic_rm_help], + "write": [wic_help_topic_subcommand, + wic_help_topic_usage, + hlp.wic_write_help], + "list": [wic_help_topic_subcommand, + wic_help_topic_usage, + hlp.wic_list_help] +} + + +def wic_init_parser_create(subparser): + subparser.add_argument("wks_file") + + subparser.add_argument("-o", "--outdir", dest="outdir", default='.', + help="name of directory to create image in") + subparser.add_argument("-e", "--image-name", dest="image_name", + help="name of the image to use the artifacts from " + "e.g. core-image-sato") + subparser.add_argument("-r", "--rootfs-dir", action=RootfsArgAction, + help="path to the /rootfs dir to use as the " + ".wks rootfs source") + subparser.add_argument("-b", "--bootimg-dir", dest="bootimg_dir", + help="path to the dir containing the boot artifacts " + "(e.g. /EFI or /syslinux dirs) to use as the " + ".wks bootimg source") + subparser.add_argument("-k", "--kernel-dir", dest="kernel_dir", + help="path to the dir containing the kernel to use " + "in the .wks bootimg") + subparser.add_argument("-n", "--native-sysroot", dest="native_sysroot", + help="path to the native sysroot containing the tools " + "to use to build the image") + subparser.add_argument("-s", "--skip-build-check", dest="build_check", + action="store_false", default=True, help="skip the build check") + subparser.add_argument("-f", "--build-rootfs", action="store_true", help="build rootfs") + subparser.add_argument("-c", "--compress-with", choices=("gzip", "bzip2", "xz"), + dest='compressor', + help="compress image with specified compressor") + subparser.add_argument("-m", "--bmap", action="store_true", help="generate .bmap") + subparser.add_argument("--no-fstab-update" ,action="store_true", + help="Do not change fstab file.") + subparser.add_argument("-v", "--vars", dest='vars_dir', + help="directory with .env files that store " + "bitbake variables") + subparser.add_argument("-D", "--debug", dest="debug", action="store_true", + default=False, help="output debug information") + return + + +def wic_init_parser_list(subparser): + subparser.add_argument("list_type", + help="can be 'images' or 'source-plugins' " + "to obtain a list. " + "If value is a valid .wks image file") + subparser.add_argument("help_for", default=[], nargs='*', + help="If 'list_type' is a valid .wks image file " + "this value can be 'help' to show the help information " + "defined inside the .wks file") + return + +def imgtype(arg): + """ + Custom type for ArgumentParser + Converts path spec to named tuple: (image, partition, path) + """ + image = arg + part = path = None + if ':' in image: + image, part = image.split(':') + if '/' in part: + part, path = part.split('/', 1) + if not path: + path = '/' + + if not os.path.isfile(image): + err = "%s is not a regular file or symlink" % image + raise argparse.ArgumentTypeError(err) + + return namedtuple('ImgType', 'image part path')(image, part, path) + +def wic_init_parser_ls(subparser): + subparser.add_argument("path", type=imgtype, + help="image spec: [:[]]") + subparser.add_argument("-n", "--native-sysroot", + help="path to the native sysroot containing the tools") + +def imgpathtype(arg): + img = imgtype(arg) + if img.part is None: + raise argparse.ArgumentTypeError("partition number is not specified") + return img + +def wic_init_parser_cp(subparser): + subparser.add_argument("src", + help="source spec") + subparser.add_argument("dest", type=imgpathtype, + help="image spec: :[]") + subparser.add_argument("-n", "--native-sysroot", + help="path to the native sysroot containing the tools") + +def wic_init_parser_rm(subparser): + subparser.add_argument("path", type=imgpathtype, + help="path: :") + subparser.add_argument("-n", "--native-sysroot", + help="path to the native sysroot containing the tools") + +def expandtype(rules): + """ + Custom type for ArgumentParser + Converts expand rules to the dictionary {: size} + """ + if rules == 'auto': + return {} + result = {} + for rule in rules.split('-'): + try: + part, size = rule.split(':') + except ValueError: + raise argparse.ArgumentTypeError("Incorrect rule format: %s" % rule) + + if not part.isdigit(): + raise argparse.ArgumentTypeError("Rule '%s': partition number must be integer" % rule) + + # validate size + multiplier = 1 + for suffix, mult in [('K', 1024), ('M', 1024 * 1024), ('G', 1024 * 1024 * 1024)]: + if size.upper().endswith(suffix): + multiplier = mult + size = size[:-1] + break + if not size.isdigit(): + raise argparse.ArgumentTypeError("Rule '%s': size must be integer" % rule) + + result[int(part)] = int(size) * multiplier + + return result + +def wic_init_parser_write(subparser): + subparser.add_argument("image", + help="path to the wic image") + subparser.add_argument("target", + help="target file or device") + subparser.add_argument("-e", "--expand", type=expandtype, + help="expand rules: auto or :[,:]") + subparser.add_argument("-n", "--native-sysroot", + help="path to the native sysroot containing the tools") + +def wic_init_parser_help(subparser): + helpparsers = subparser.add_subparsers(dest='help_topic', help=hlp.wic_usage) + for helptopic in helptopics: + helpparsers.add_parser(helptopic, help=helptopics[helptopic][2]) + return + + +subcommands = { + "create": [wic_create_subcommand, + hlp.wic_create_usage, + hlp.wic_create_help, + wic_init_parser_create], + "list": [wic_list_subcommand, + hlp.wic_list_usage, + hlp.wic_list_help, + wic_init_parser_list], + "ls": [wic_ls_subcommand, + hlp.wic_ls_usage, + hlp.wic_ls_help, + wic_init_parser_ls], + "cp": [wic_cp_subcommand, + hlp.wic_cp_usage, + hlp.wic_cp_help, + wic_init_parser_cp], + "rm": [wic_rm_subcommand, + hlp.wic_rm_usage, + hlp.wic_rm_help, + wic_init_parser_rm], + "write": [wic_write_subcommand, + hlp.wic_write_usage, + hlp.wic_write_help, + wic_init_parser_write], + "help": [wic_help_subcommand, + wic_help_topic_usage, + hlp.wic_help_help, + wic_init_parser_help] +} + + +def init_parser(parser): + parser.add_argument("--version", action="version", + version="%(prog)s {version}".format(version=__version__)) + subparsers = parser.add_subparsers(dest='command', help=hlp.wic_usage) + for subcmd in subcommands: + subparser = subparsers.add_parser(subcmd, help=subcommands[subcmd][2]) + subcommands[subcmd][3](subparser) + + +def main(argv): + parser = argparse.ArgumentParser( + description="wic version %s" % __version__) + + init_parser(parser) + + args = parser.parse_args(argv) + + if "command" in vars(args): + if args.command == "help": + if args.help_topic is None: + parser.print_help() + print() + print("Please specify a help topic") + elif args.help_topic in helptopics: + hlpt = helptopics[args.help_topic] + hlpt[0](hlpt[1], hlpt[2]) + return 0 + + return hlp.invoke_subcommand(args, parser, hlp.wic_help_usage, subcommands) + + +if __name__ == "__main__": + try: + sys.exit(main(sys.argv[1:])) + except WicError as err: + print() + logger.error(err) + sys.exit(1) -- cgit v1.2.3