Exemplo n.º 1
0
def wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir, native_sysroot,
               options):
    """
    Create image

    wks_file - user-defined OE kickstart file
    rootfs_dir - absolute path to the build's /rootfs dir
    bootimg_dir - absolute path to the build's boot artifacts directory
    kernel_dir - absolute path to the build's kernel directory
    native_sysroot - absolute path to the build's native sysroots dir
    image_output_dir - dirname to create for image
    options - wic command line options (debug, bmap, etc)

    Normally, the values for the build artifacts values are determined
    by 'wic -e' from the output of the 'bitbake -e' command given an
    image name e.g. 'core-image-minimal' and a given machine set in
    local.conf.  If that's the case, the variables get the following
    values from the output of 'bitbake -e':

    rootfs_dir:        IMAGE_ROOTFS
    kernel_dir:        DEPLOY_DIR_IMAGE
    native_sysroot:    STAGING_DIR_NATIVE

    In the above case, bootimg_dir remains unset and the
    plugin-specific image creation code is responsible for finding the
    bootimg artifacts.

    In the case where the values are passed in explicitly i.e 'wic -e'
    is not used but rather the individual 'wic' options are used to
    explicitly specify these values.
    """
    try:
        oe_builddir = os.environ["BUILDDIR"]
    except KeyError:
        raise WicError(
            "BUILDDIR not found, exiting. (Did you forget to source oe-init-build-env?)"
        )

    if not os.path.exists(options.outdir):
        os.makedirs(options.outdir)

    pname = options.imager
    plugin_class = PluginMgr.get_plugins('imager').get(pname)
    if not plugin_class:
        raise WicError('Unknown plugin: %s' % pname)

    plugin = plugin_class(wks_file, rootfs_dir, bootimg_dir, kernel_dir,
                          native_sysroot, oe_builddir, options)

    plugin.do_create()

    logger.info("The image(s) were created using OE kickstart file:\n  %s",
                wks_file)
Exemplo n.º 2
0
    def _build_initramfs_path(rootfs_dir, cr_workdir):
        """
        Create path for initramfs image
        """

        initrd = get_bitbake_var("INITRD_LIVE") or get_bitbake_var("INITRD")
        if not initrd:
            initrd_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
            if not initrd_dir:
                raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting.")

            image_name = get_bitbake_var("IMAGE_BASENAME")
            if not image_name:
                raise WicError("Couldn't find IMAGE_BASENAME, exiting.")

            image_type = get_bitbake_var("INITRAMFS_FSTYPES")
            if not image_type:
                raise WicError("Couldn't find INITRAMFS_FSTYPES, exiting.")

            machine = os.path.basename(initrd_dir)

            initrd = glob.glob(
                '%s/%s*%s.%s' %
                (initrd_dir, image_name, machine, image_type))[0]

        if not os.path.exists(initrd):
            # Create initrd from rootfs directory
            initrd = "%s/initrd.cpio.gz" % cr_workdir
            initrd_dir = "%s/INITRD" % cr_workdir
            shutil.copytree("%s" % rootfs_dir, \
                            "%s" % initrd_dir, symlinks=True)

            if os.path.isfile("%s/init" % rootfs_dir):
                shutil.copy2("%s/init" % rootfs_dir, "%s/init" % initrd_dir)
            elif os.path.lexists("%s/init" % rootfs_dir):
                os.symlink(os.readlink("%s/init" % rootfs_dir), \
                            "%s/init" % initrd_dir)
            elif os.path.isfile("%s/sbin/init" % rootfs_dir):
                shutil.copy2("%s/sbin/init" % rootfs_dir, \
                            "%s" % initrd_dir)
            elif os.path.lexists("%s/sbin/init" % rootfs_dir):
                os.symlink(os.readlink("%s/sbin/init" % rootfs_dir), \
                            "%s/init" % initrd_dir)
            else:
                raise WicError("Couldn't find or build initrd, exiting.")

            exec_cmd("cd %s && find . | cpio -o -H newc -R +0:+0 >./initrd.cpio " \
                    % initrd_dir, as_shell=True)
            exec_cmd("gzip -f -9 -c %s/initrd.cpio > %s" \
                    % (cr_workdir, initrd), as_shell=True)
            shutil.rmtree(initrd_dir)

        return initrd
Exemplo n.º 3
0
    def _get_part_image(self, pnum):
        if pnum not in self.partitions:
            raise WicError("Partition %s is not in the image")
        part = self.partitions[pnum]
        if not part.fstype.startswith("fat"):
            raise WicError("Not supported fstype: {}".format(part.fstype))
        if pnum not in self._partimages:
            tmpf = tempfile.NamedTemporaryFile(prefix="wic-part")
            dst_fname = tmpf.name
            tmpf.close()
            sparse_copy(self.imagepath, dst_fname, skip=part.start, length=part.size)
            self._partimages[pnum] = dst_fname

        return self._partimages[pnum]
Exemplo n.º 4
0
    def do_copy_mender_env(self, deploydir, cr_workdir, hdddir, source_params):
        """
        Copy mender grub env files
        """

        if not 'mender_grub_env' in source_params:
            raise WicError("mender_grub_env is unset!")

        if not source_params['mender_grub_env']:
            raise WicError("bad mender_grub_env!")

        copy_tree(
            "%s/grub-mender-grubenv/%s/EFI" %
            (deploydir, source_params['mender_grub_env']), "%s/EFI" % hdddir)
Exemplo n.º 5
0
    def do_prepare_partition(cls, part, source_params, cr, cr_workdir,
                             oe_builddir, bootimg_dir, kernel_dir, rootfs_dir,
                             native_sysroot):
        """
        Called to do the actual content population for a partition i.e. it
        'prepares' the partition to be incorporated into the image.
        """
        if not kernel_dir:
            kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
            if not kernel_dir:
                raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")

        logger.debug('Kernel dir: %s', kernel_dir)

        if 'file' not in source_params:
            raise WicError("No file specified")

        if 'unpack' in source_params:
            img = os.path.join(kernel_dir, source_params['file'])
            src = os.path.join(cr_workdir,
                               os.path.splitext(source_params['file'])[0])
            RawCopyPlugin.do_image_uncompression(img, src, cr_workdir)
        else:
            src = os.path.join(kernel_dir, source_params['file'])

        dst = os.path.join(
            cr_workdir,
            "%s.%s" % (os.path.basename(source_params['file']), part.lineno))

        if not os.path.exists(os.path.dirname(dst)):
            os.makedirs(os.path.dirname(dst))

        if 'skip' in source_params:
            sparse_copy(src, dst, skip=int(source_params['skip']))
        else:
            sparse_copy(src, dst)

        # get the size in the right units for kickstart (kB)
        du_cmd = "du -Lbks %s" % dst
        out = exec_cmd(du_cmd)
        filesize = int(out.split()[0])

        if filesize > part.size:
            part.size = filesize

        if part.label:
            RawCopyPlugin.do_image_label(part.fstype, dst, part.label)

        part.source_file = dst
Exemplo n.º 6
0
    def __init__(self, wks_file, rootfs_dir, bootimg_dir, kernel_dir,
                 native_sysroot, oe_builddir, options):
        try:
            self.ks = KickStart(wks_file)
        except KickStartError as err:
            raise WicError(str(err))

        # parse possible 'rootfs=name' items
        self.rootfs_dir = dict(rdir.split('=') for rdir in rootfs_dir.split(' '))
        self.bootimg_dir = bootimg_dir
        self.kernel_dir = kernel_dir
        self.native_sysroot = native_sysroot
        self.oe_builddir = oe_builddir

        self.outdir = options.outdir
        self.compressor = options.compressor
        self.bmap = options.bmap

        self.name = "%s-%s" % (os.path.splitext(os.path.basename(wks_file))[0],
                               strftime("%Y%m%d%H%M"))
        self.workdir = tempfile.mkdtemp(dir=self.outdir, prefix='tmp.wic.')
        self._image = None
        self.ptable_format = self.ks.bootloader.ptable
        self.parts = self.ks.partitions

        # as a convenience, set source to the boot partition source
        # instead of forcing it to be set via bootloader --source
        for part in self.parts:
            if not self.ks.bootloader.source and part.mountpoint == "/boot":
                self.ks.bootloader.source = part.source
                break

        image_path = self._full_path(self.workdir, self.parts[0].disk, "direct")
        self._image = PartitionedImage(image_path, self.ptable_format,
                                       self.parts, self.native_sysroot)
Exemplo n.º 7
0
    def do_prepare_partition(
        cls,
        part,
        source_params,
        cr,
        cr_workdir,
        oe_builddir,
        bootimg_dir,
        kernel_dir,
        dir_dict,
        native_sysroot,
    ):
        """Populate a partition given directory with files."""
        img_link_name = get_bitbake_var("IMAGE_LINK_NAME")
        signed_base64_root_hash_suffix = ".root_hash.txt.sha256.base64"
        img_deploy_dir = get_bitbake_var("IMGDEPLOYDIR")

        try:
            subdir = source_params["subdir"]
        except KeyError:
            raise WicError(
                "Required source parameter 'subdir' not found, exiting")

        subdir_src = os.path.join(img_deploy_dir, subdir)
        subdir_dst = os.path.join(cr_workdir, subdir)

        logger.debug("Subdir source dir: {}".format(subdir_src))
        logger.debug("Subdir dest dir: {}".format(subdir_dst))

        shutil.copytree(subdir_src, subdir_dst)

        part.prepare_rootfs(cr_workdir, oe_builddir, subdir_dst,
                            native_sysroot, False)
Exemplo n.º 8
0
 def do_image_label(fstype, dst, label):
     if fstype.startswith('ext'):
         cmd = 'tune2fs -L %s %s' % (label, dst)
     elif fstype in ('msdos', 'vfat'):
         cmd = 'dosfslabel %s %s' % (dst, label)
     elif fstype == 'btrfs':
         cmd = 'btrfs filesystem label %s %s' % (dst, label)
     elif fstype == 'swap':
         cmd = 'mkswap -L %s %s' % (label, dst)
     elif fstype == 'squashfs':
         raise WicError("It's not possible to update a squashfs "
                        "filesystem label '%s'" % (label))
     else:
         raise WicError("Cannot update filesystem label: "
                        "Unknown fstype: '%s'" % (fstype))
     exec_cmd(cmd)
Exemplo n.º 9
0
    def gen_ubootscript(cls, part, source_params, cr, rootdir, hdddir):
        u_boot_script = os.path.join(rootdir, "etc/default/u-boot-script")
        if not os.path.exists(u_boot_script):
            raise WicError("u-boot-scripts package not installed")

        # Write new /etc/default/u-boot-script
        '''
        with open(u_boot_script, 'w') as cfg:
            cfg.write('# Generated by wic, bootpart plugin\n')
            cfg.write('ROOT_PARTITION="%d"\n' % part.realnum)
            cfg.write('KERNEL_ARGS="root=%s %s"\n' % \
                (cr.rootdev, cr.ks.bootloader.append or ""))
            no_initrd = source_params.get('no_initrd') or ''
            cfg.write('NO_INITRD="%s"\n' % no_initrd)
            overlays = source_params.get('overlays') or ''
            cfg.write('OVERLAYS="%s"\n' % overlays)
            script_prepend = source_params.get('script_prepend') or ''
            cfg.write('SCRIPT_PREPEND="%s"\n' % script_prepend)
        '''
        # Run update-u-boot-script in the target rootfs
        results = glob.glob(os.path.join("/usr/bin/qemu-*-static"))
        qemu_static = results[0] if len(results) > 0 else None
        if qemu_static:
            cp_cmd = "cp -L %s %s/usr/bin" % (qemu_static, rootdir)
            exec_cmd(cp_cmd)
        update_cmd = "chroot %s sh -c update-u-boot-script" % rootdir
        exec_cmd(update_cmd)
        if qemu_static:
            rm_cmd = "rm -f %s/usr/bin/%s" % (rootdir, qemu_static)
            exec_cmd(rm_cmd)
def runtool(cmdln_or_args):
    """ wrapper for most of the subprocess calls
    input:
        cmdln_or_args: can be both args and cmdln str (shell=True)
    return:
        rc, output
    """
    if isinstance(cmdln_or_args, list):
        cmd = cmdln_or_args[0]
        shell = False
    else:
        import shlex
        cmd = shlex.split(cmdln_or_args)[0]
        shell = True

    sout = subprocess.PIPE
    serr = subprocess.STDOUT

    try:
        process = subprocess.Popen(cmdln_or_args, stdout=sout,
                                   stderr=serr, shell=shell)
        sout, serr = process.communicate()
        # combine stdout and stderr, filter None out and decode
        out = ''.join([out.decode('utf-8') for out in [sout, serr] if out])
    except OSError as err:
        if err.errno == 2:
            # [Errno 2] No such file or directory
            raise WicError('Cannot run command: %s, lost dependency?' % cmd)
        else:
            raise # relay

    return process.returncode, out
Exemplo n.º 11
0
def wic_list(args, scripts_path):
    """
    Print the list of images or source plugins.
    """
    if args.list_type is None:
        return False

    if args.list_type == "images":

        list_canned_images(scripts_path)
        return True
    elif args.list_type == "source-plugins":
        list_source_plugins()
        return True
    elif len(args.help_for) == 1 and args.help_for[0] == 'help':
        wks_file = args.list_type
        fullpath = find_canned_image(scripts_path, wks_file)
        if not fullpath:
            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)" % wks_file)

        list_canned_image_help(scripts_path, fullpath)
        return True

    return False
Exemplo n.º 12
0
    def get_plugins(cls, ptype):
        """Get dictionary of <plugin_name>:<class> pairs."""
        if ptype not in PLUGIN_TYPES:
            raise WicError('%s is not valid plugin type' % ptype)

        # collect plugin directories
        if not cls._plugin_dirs:
            cls._plugin_dirs = [os.path.join(os.path.dirname(__file__), 'plugins')]
            layers = get_bitbake_var("BBLAYERS") or ''
            for layer_path in layers.split():
                for script_plugin_dir in SCRIPTS_PLUGIN_DIR:
                    path = os.path.join(layer_path, script_plugin_dir)
                    path = os.path.abspath(os.path.expanduser(path))
                    if path not in cls._plugin_dirs and os.path.isdir(path):
                        cls._plugin_dirs.insert(0, path)

        if ptype not in PLUGINS:
            # load all ptype plugins
            for pdir in cls._plugin_dirs:
                ppath = os.path.join(pdir, ptype)
                if os.path.isdir(ppath):
                    for fname in os.listdir(ppath):
                        if fname.endswith('.py'):
                            mname = fname[:-3]
                            mpath = os.path.join(ppath, fname)
                            logger.debug("loading plugin module %s", mpath)
                            SourceFileLoader(mname, mpath).load_module()

        return PLUGINS.get(ptype)
Exemplo n.º 13
0
 def remove(self, pnum, path):
     """Remove files/dirs from the partition."""
     partimg = self._get_part_image(pnum)
     if self.partitions[pnum].fstype.startswith('ext'):
         cmd = "{} {} -wR 'rm {}'".format(self.debugfs,
                                             self._get_part_image(pnum),
                                             path)
         out = exec_cmd(cmd , as_shell=True)
         for line in out.splitlines():
             if line.startswith("rm:"):
                 if "file is a directory" in line:
                     # Try rmdir to see if this is an empty directory. This won't delete
                     # any non empty directory so let user know about any error that this might
                     # generate.
                     print(exec_cmd("{} {} -wR 'rmdir {}'".format(self.debugfs,
                                                 self._get_part_image(pnum),
                                                 path), as_shell=True))
                 else:
                     raise WicError("Could not complete operation: wic %s" % str(line))
     else: # fat
         cmd = "{} -i {} ::{}".format(self.mdel, partimg, path)
         try:
             exec_cmd(cmd)
         except WicError as err:
             if "not found" in str(err) or "non empty" in str(err):
                 # mdel outputs 'File ... not found' or 'directory .. non empty"
                 # try to use mdeltree as path could be a directory
                 cmd = "{} -i {} ::{}".format(self.mdeltree,
                                              partimg, path)
                 exec_cmd(cmd)
             else:
                 raise err
     self._put_part_image(pnum)
Exemplo n.º 14
0
    def get_rootfs_size(self, actual_rootfs_size=0):
        """
        Calculate the required size of rootfs taking into consideration
        --size/--fixed-size flags as well as overhead and extra space, as
        specified in kickstart file. Raises an error if the
        `actual_rootfs_size` is larger than fixed-size rootfs.

        """
        if self.fixed_size:
            rootfs_size = self.fixed_size
            if actual_rootfs_size > rootfs_size:
                raise WicError("Actual rootfs size (%d kB) is larger than "
                               "allowed size %d kB" %
                               (actual_rootfs_size, rootfs_size))
        else:
            extra_blocks = self.get_extra_block_count(actual_rootfs_size)
            if extra_blocks < self.extra_space:
                extra_blocks = self.extra_space

            rootfs_size = actual_rootfs_size + extra_blocks
            rootfs_size *= self.overhead_factor

            logger.debug(
                "Added %d extra blocks to %s to get to %d total blocks",
                extra_blocks, self.mountpoint, rootfs_size)

        return rootfs_size
Exemplo n.º 15
0
    def do_prepare_partition(cls, part, source_params, cr, cr_workdir,
                             oe_builddir, bootimg_dir, kernel_dir, rootfs_dir,
                             native_sysroot):
        """
        Called to do the actual content population for a partition i.e. it
        'prepares' the partition to be incorporated into the image.
        In this case, does the following:
        - sets up a vfat partition
        - copies all files listed in IMAGE_BOOT_FILES variable
        """
        hdddir = "%s/boot.%d" % (cr_workdir, part.lineno)

        if not kernel_dir:
            kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE")
            if not kernel_dir:
                raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting")

        logger.debug('Kernel dir: %s', bootimg_dir)

        for task in cls.install_task:
            src_path, dst_path = task
            logger.debug('Install %s as %s', src_path, dst_path)
            install_cmd = "install -m 0644 -D %s %s" \
                          % (os.path.join(kernel_dir, src_path),
                             os.path.join(hdddir, dst_path))
            exec_cmd(install_cmd)

        logger.debug('Prepare boot partition using rootfs in %s', hdddir)
        part.prepare_rootfs(cr_workdir, oe_builddir, hdddir, native_sysroot,
                            False)
Exemplo n.º 16
0
    def __init__(self, imagepath, native_sysroot, fstypes=('fat', 'ext')):
        self.imagepath = imagepath
        self.native_sysroot = native_sysroot
        self.fstypes = fstypes
        self._partitions = None
        self._partimages = {}
        self._lsector_size = None
        self._psector_size = None
        self._ptable_format = None

        # find parted
        # read paths from $PATH environment variable
        # if it fails, use hardcoded paths
        pathlist = "/bin:/usr/bin:/usr/sbin:/sbin/"
        try:
            self.paths = os.environ['PATH'] + ":" + pathlist
        except KeyError:
            self.paths = pathlist

        if native_sysroot:
            for path in pathlist.split(':'):
                self.paths = "%s%s:%s" % (native_sysroot, path, self.paths)

        self.parted = find_executable("parted", self.paths)
        if not self.parted:
            raise WicError("Can't find executable parted")

        self.partitions = self.get_partitions()
Exemplo n.º 17
0
 def _prop(self, name):
     """Get path to the executable in a lazy way."""
     aname = "_%s" % name
     if getattr(self, aname) is None:
         setattr(self, aname, find_executable(name, self.paths))
         if not getattr(self, aname):
             raise WicError("Can't find executable {}".format(name))
     return getattr(self, aname)
Exemplo n.º 18
0
    def do_configure_partition(cls, part, source_params, creator, cr_workdir,
                               oe_builddir, bootimg_dir, kernel_dir,
                               native_sysroot):
        """
        Called before do_prepare_partition(), creates syslinux config
        """
        hdddir = "%s/hdd/boot" % cr_workdir

        install_cmd = "install -d %s" % hdddir
        exec_cmd(install_cmd)

        bootloader = creator.ks.bootloader

        custom_cfg = None
        if bootloader.configfile:
            custom_cfg = get_custom_config(bootloader.configfile)
            if custom_cfg:
                # Use a custom configuration for grub
                syslinux_conf = custom_cfg
                logger.debug(
                    "Using custom configuration file %s "
                    "for syslinux.cfg", bootloader.configfile)
            else:
                raise WicError("configfile is specified but failed to "
                               "get it from %s." % bootloader.configfile)

        if not custom_cfg:
            # Create syslinux configuration using parameters from wks file
            splash = os.path.join(cr_workdir, "/hdd/boot/splash.jpg")
            if os.path.exists(splash):
                splashline = "menu background splash.jpg"
            else:
                splashline = ""

            syslinux_conf = ""
            syslinux_conf += "PROMPT 0\n"
            syslinux_conf += "TIMEOUT " + str(bootloader.timeout) + "\n"
            syslinux_conf += "\n"
            syslinux_conf += "ALLOWOPTIONS 1\n"
            syslinux_conf += "SERIAL 0 115200\n"
            syslinux_conf += "\n"
            if splashline:
                syslinux_conf += "%s\n" % splashline
            syslinux_conf += "DEFAULT boot\n"
            syslinux_conf += "LABEL boot\n"

            kernel = get_bitbake_var("KERNEL_IMAGE")
            initrd = get_bitbake_var("INITRD_IMAGE")
            syslinux_conf += "KERNEL " + kernel + "\n"

            syslinux_conf += "APPEND label=boot root=%s initrd=%s %s\n" % \
                             (creator.rootdev, initrd, bootloader.append)

        logger.debug("Writing syslinux config %s/hdd/boot/syslinux.cfg",
                     cr_workdir)
        cfg = open("%s/hdd/boot/syslinux.cfg" % cr_workdir, "w")
        cfg.write(syslinux_conf)
        cfg.close()
Exemplo n.º 19
0
    def do_configure_systemdboot(cls, hdddir, creator, cr_workdir, source_params):
        """
        Create loader-specific systemd-boot config
        """
        if source_params.get("initrd"):
            logger.debug("Ignoring initrd")

        install_cmd = "install -d {}/loader".format(hdddir)
        exec_cmd(install_cmd)

        install_cmd = "install -d {}/loader/entries".format(hdddir)
        exec_cmd(install_cmd)

        bootloader = creator.ks.bootloader

        copied = False
        for p in creator.ks.partitions:
            srcparams = splitsrcparams(p.sourceparams)
            if not isrootfs(srcparams):
                continue

            def write_entry_conf(conf, cfgpath):
                logger.debug("Writing systemd-boot entry config")
                cfg = open(cfgpath, "w")
                cfg.write(conf)
                cfg.close()

            def write_part_loader_conf(conf, cfgpath):
                logger.debug("Writing systemd-boot partition loader.conf")
                cfg = open(cfgpath, "w")
                cfg.write(loaderconf)
                cfg.close()

            if not p.label:
                raise WicError("Missing --label for rootfs")

            kernel = "/kernel/{}/bzImage".format(p.label)
            title = srcparams["boot-title"] if "boot-title" in srcparams else p.label

            bootconf = ""
            bootconf += "title {}\n".format(title)
            bootconf += "linux {}\n".format(kernel)
            bootconf += "options LABEL={} root=PARTUUID={} {}\n".format(p.label, p.uuid, bootloader.append)
            write_entry_conf(bootconf, "{}/hdd/boot/loader/entries/{}.conf".format(cr_workdir, p.label))

            install_cmd = "install -d {}/hdd/boot/kernel/{}".format(cr_workdir, p.label)
            exec_cmd(install_cmd)
            loaderconf = ""
            loaderconf += "default {}\n".format(p.label)
            loaderconf += "timeout {}\n".format(bootloader.timeout)
            confpath = "{}/hdd/boot/kernel/{}/loader.conf".format(cr_workdir, p.label)
            write_part_loader_conf(loaderconf, confpath)

            if not copied:
                shutil.copyfile(confpath, "{}/hdd/boot/loader/loader.conf".format(cr_workdir))
                copied = True

        assert copied, "copied must be True here"
Exemplo n.º 20
0
def runtool(cmdln_or_args, catch=1):
    """ wrapper for most of the subprocess calls
    input:
        cmdln_or_args: can be both args and cmdln str (shell=True)
        catch: 0, quitely run
               1, only STDOUT
               2, only STDERR
               3, both STDOUT and STDERR
    return:
        (rc, output)
        if catch==0: the output will always None
    """

    if catch not in (0, 1, 2, 3):
        # invalid catch selection, will cause exception, that's good
        return None

    if isinstance(cmdln_or_args, list):
        cmd = cmdln_or_args[0]
        shell = False
    else:
        import shlex
        cmd = shlex.split(cmdln_or_args)[0]
        shell = True

    if catch != 3:
        dev_null = os.open("/dev/null", os.O_WRONLY)

    if catch == 0:
        sout = dev_null
        serr = dev_null
    elif catch == 1:
        sout = subprocess.PIPE
        serr = dev_null
    elif catch == 2:
        sout = dev_null
        serr = subprocess.PIPE
    elif catch == 3:
        sout = subprocess.PIPE
        serr = subprocess.STDOUT

    try:
        process = subprocess.Popen(cmdln_or_args, stdout=sout,
                                   stderr=serr, shell=shell)
        (sout, serr) = process.communicate()
        # combine stdout and stderr, filter None out and decode
        out = ''.join([out.decode('utf-8') for out in [sout, serr] if out])
    except OSError as err:
        if err.errno == 2:
            # [Errno 2] No such file or directory
            raise WicError('Cannot run command: %s, lost dependency?' % cmd)
        else:
            raise # relay
    finally:
        if catch != 3:
            os.close(dev_null)

    return (process.returncode, out)
Exemplo n.º 21
0
    def remove_ext(self, pnum, path, recursive):
        """
        Remove files/dirs and their contents from the partition.
        This only applies to ext* partition.
        """
        abs_path = re.sub('\/\/+', '/', path)
        cmd = "{} {} -wR 'rm \"{}\"'".format(self.debugfs,
                                             self._get_part_image(pnum),
                                             abs_path)
        out = exec_cmd(cmd, as_shell=True)
        for line in out.splitlines():
            if line.startswith("rm:"):
                if "file is a directory" in line:
                    if recursive:
                        # loop through content and delete them one by one if
                        # flaged with -r
                        subdirs = iter(self.dir(pnum, abs_path).splitlines())
                        next(subdirs)
                        for subdir in subdirs:
                            dir = subdir.split(':')[1].split(" ", 1)[1]
                            if not dir == "." and not dir == "..":
                                self.remove_ext(pnum,
                                                "%s/%s" % (abs_path, dir),
                                                recursive)

                    rmdir_out = exec_cmd("{} {} -wR 'rmdir \"{}\"'".format(
                        self.debugfs, self._get_part_image(pnum),
                        abs_path.rstrip('/')),
                                         as_shell=True)

                    for rmdir_line in rmdir_out.splitlines():
                        if "directory not empty" in rmdir_line:
                            raise WicError(
                                "Could not complete operation: \n%s \n"
                                "use -r to remove non-empty directory" %
                                rmdir_line)
                        if rmdir_line.startswith("rmdir:"):
                            raise WicError(
                                "Could not complete operation: \n%s "
                                "\n%s" % (str(line), rmdir_line))

                else:
                    raise WicError("Could not complete operation: \n%s "
                                   "\nUnable to remove %s" %
                                   (str(line), abs_path))
Exemplo n.º 22
0
    def do_configure_partition(cls, part, source_params, creator, cr_workdir,
                               oe_builddir, bootimg_dir, kernel_dir,
                               native_sysroot):
        """
        Called before do_prepare_partition(), creates loader-specific config
        """
        if "loader" not in source_params:
            raise WicError("multi-bootimg-efi requires a loader, none specified")

        hdddir = "{}/hdd/boot".format(cr_workdir)

        install_cmd = "install -d {}/EFI/BOOT".format(hdddir)
        exec_cmd(install_cmd)

        if source_params["loader"] == "systemd-boot":
            cls.do_configure_systemdboot(hdddir, creator, cr_workdir, source_params)
        else:
            raise WicError("Unrecognized multi-bootimg-efi loader: {}".format(source_params["loader"]))
Exemplo n.º 23
0
    def _get_bootimg_dir(cls, bootimg_dir, dirname):
        """
        Check if dirname exists in default bootimg_dir or in STAGING_DIR.
        """
        for result in (bootimg_dir, get_bitbake_var("STAGING_DATADIR")):
            if os.path.exists("%s/%s" % (result, dirname)):
                return result

        raise WicError("Couldn't find correct bootimg_dir, exiting")
Exemplo n.º 24
0
    def setup_workdir(self, workdir):
        if workdir:
            if os.path.exists(workdir):
                raise WicError("Internal workdir '%s' specified in wic arguments already exists!" % (workdir))

            os.makedirs(workdir)
            return workdir
        else:
            return tempfile.mkdtemp(dir=self.outdir, prefix='tmp.wic.')
Exemplo n.º 25
0
    def do_prepare_partition(cls, part, source_params, image_creator,
                             image_creator_workdir, oe_builddir, bootimg_dir,
                             kernel_dir, krootfs_dir, native_sysroot):
        """
        Creates partition out of rootfs directory

        Prepare content for a rootfs partition i.e. create a partition
        and fill it from a /rootfs dir.
        Install syslinux bootloader into root partition image file
        """
        def is_exe(exepath):
            """Verify exepath is an executable file"""
            return os.path.isfile(exepath) and os.access(exepath, os.X_OK)

        # Make sure syslinux-nomtools is available in native sysroot or fail
        native_syslinux_nomtools = os.path.join(native_sysroot, "usr/bin/syslinux-nomtools")
        if not is_exe(native_syslinux_nomtools):
            logger.info("building syslinux-native...")
            exec_cmd("bitbake syslinux-native")
        if not is_exe(native_syslinux_nomtools):
            raise WicError("Couldn't find syslinux-nomtools (%s), exiting" %
                           native_syslinux_nomtools)

        if part.rootfs is None:
            if 'ROOTFS_DIR' not in krootfs_dir:
                raise WicError("Couldn't find --rootfs-dir, exiting")
            rootfs_dir = krootfs_dir['ROOTFS_DIR']
        else:
            if part.rootfs in krootfs_dir:
                rootfs_dir = krootfs_dir[part.rootfs]
            elif part.rootfs:
                rootfs_dir = part.rootfs
            else:
                raise WicError("Couldn't find --rootfs-dir=%s connection or "
                               "it is not a valid path, exiting" % part.rootfs)

        real_rootfs_dir = cls._get_rootfs_dir(rootfs_dir)

        part.rootfs_dir = real_rootfs_dir
        part.prepare_rootfs(image_creator_workdir, oe_builddir, real_rootfs_dir, native_sysroot)

        # install syslinux into rootfs partition
        syslinux_cmd = "syslinux-nomtools -d /boot -i %s" % part.source_file
        exec_native_cmd(syslinux_cmd, native_sysroot)
Exemplo n.º 26
0
    def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir,
                       native_sysroot):
        """
        Prepare content for a rootfs partition i.e. create a partition
        and fill it from a /rootfs dir.

        Currently handles ext2/3/4, btrfs and vfat.
        """
        p_prefix = os.environ.get("PSEUDO_PREFIX", "%s/usr" % native_sysroot)
        p_localstatedir = os.environ.get("PSEUDO_LOCALSTATEDIR",
                                         "%s/../pseudo" % rootfs_dir)
        p_passwd = os.environ.get("PSEUDO_PASSWD", rootfs_dir)
        p_nosymlinkexp = os.environ.get("PSEUDO_NOSYMLINKEXP", "1")
        pseudo = "export PSEUDO_PREFIX=%s;" % p_prefix
        pseudo += "export PSEUDO_LOCALSTATEDIR=%s;" % p_localstatedir
        pseudo += "export PSEUDO_PASSWD=%s;" % p_passwd
        pseudo += "export PSEUDO_NOSYMLINKEXP=%s;" % p_nosymlinkexp
        pseudo += "%s " % get_bitbake_var("FAKEROOTCMD")

        rootfs = "%s/rootfs_%s.%s.%s" % (cr_workdir, self.label, self.lineno,
                                         self.fstype)
        if os.path.isfile(rootfs):
            os.remove(rootfs)

        if not self.fstype:
            raise WicError("File system for partition %s not specified in "
                           "kickstart, use --fstype option" % self.mountpoint)

        # Get rootfs size from bitbake variable if it's not set in .ks file
        if not self.size:
            # Bitbake variable ROOTFS_SIZE is calculated in
            # Image._get_rootfs_size method from meta/lib/oe/image.py
            # using IMAGE_ROOTFS_SIZE, IMAGE_ROOTFS_ALIGNMENT,
            # IMAGE_OVERHEAD_FACTOR and IMAGE_ROOTFS_EXTRA_SPACE
            rsize_bb = get_bitbake_var('ROOTFS_SIZE')
            if rsize_bb:
                logger.warning(
                    'overhead-factor was specified, but size was not,'
                    ' so bitbake variables will be used for the size.'
                    ' In this case both IMAGE_OVERHEAD_FACTOR and '
                    '--overhead-factor will be applied')
                self.size = int(round(float(rsize_bb)))

        for prefix in ("ext", "btrfs", "vfat", "squashfs"):
            if self.fstype.startswith(prefix):
                method = getattr(self, "prepare_rootfs_" + prefix)
                method(rootfs, oe_builddir, rootfs_dir, native_sysroot, pseudo)

                self.source_file = rootfs

                # get the rootfs size in the right units for kickstart (kB)
                du_cmd = "du -Lbks %s" % rootfs
                out = exec_cmd(du_cmd)
                self.size = int(out.split()[0])

                break
Exemplo n.º 27
0
def verify_build_env():
    """
    Verify that the build environment is sane.

    Returns True if it is, false otherwise
    """
    if not os.environ.get("BUILDDIR"):
        raise WicError("BUILDDIR not found, exiting. (Did you forget to source oe-init-build-env?)")

    return True
Exemplo n.º 28
0
    def __get_rootfs_dir(rootfs_dir):
        if os.path.isdir(rootfs_dir):
            return os.path.realpath(rootfs_dir)

        image_rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", rootfs_dir)
        if not os.path.isdir(image_rootfs_dir):
            raise WicError("No valid artifact IMAGE_ROOTFS from image "
                           "named %s has been found at %s, exiting." %
                           (rootfs_dir, image_rootfs_dir))

        return os.path.realpath(image_rootfs_dir)
Exemplo n.º 29
0
    def do_configure_partition(cls, part, source_params, creator, cr_workdir,
                               oe_builddir, bootimg_dir, kernel_dir,
                               native_sysroot):
        """
        Called before do_prepare_partition(), creates loader-specific config
        """
        hdddir = "%s/hdd/boot" % cr_workdir

        install_cmd = "install -d %s/EFI/BOOT" % hdddir
        exec_cmd(install_cmd)

        try:
            if source_params['loader'] == 'grub-efi':
                cls.do_configure_grubefi(creator, cr_workdir)
            elif source_params['loader'] == 'systemd-boot':
                cls.do_configure_systemdboot(hdddir, creator, cr_workdir, source_params)
            else:
                raise WicError("unrecognized bootimg-efi loader: %s" % source_params['loader'])
        except KeyError:
            raise WicError("bootimg-efi requires a loader, none specified")
Exemplo n.º 30
0
 def __getattr__(self, name):
     """Get path to the executable in a lazy way."""
     if name in ("mdir", "mcopy", "mdel", "mdeltree", "sfdisk", "e2fsck",
                 "resize2fs", "mkswap", "mkdosfs", "debugfs"):
         aname = "_%s" % name
         if aname not in self.__dict__:
             setattr(self, aname, find_executable(name, self.paths))
             if aname not in self.__dict__ or self.__dict__[aname] is None:
                 raise WicError("Can't find executable '{}'".format(name))
         return self.__dict__[aname]
     return self.__dict__[name]