1*96ff1984SBrad Bishop#!/usr/bin/env python3
2eb8dc403SDave Cobbley#
3eb8dc403SDave Cobbley# Copyright (c) 2011 Intel, Inc.
4eb8dc403SDave Cobbley#
5c342db35SBrad Bishop# SPDX-License-Identifier: GPL-2.0-only
6eb8dc403SDave Cobbley#
7eb8dc403SDave Cobbley
8eb8dc403SDave Cobbley__all__ = ['ImagerPlugin', 'SourcePlugin']
9eb8dc403SDave Cobbley
10eb8dc403SDave Cobbleyimport os
11eb8dc403SDave Cobbleyimport logging
12eb8dc403SDave Cobbley
13eb8dc403SDave Cobbleyfrom collections import defaultdict
14eb8dc403SDave Cobbleyfrom importlib.machinery import SourceFileLoader
15eb8dc403SDave Cobbley
16eb8dc403SDave Cobbleyfrom wic import WicError
17eb8dc403SDave Cobbleyfrom wic.misc import get_bitbake_var
18eb8dc403SDave Cobbley
19eb8dc403SDave CobbleyPLUGIN_TYPES = ["imager", "source"]
20eb8dc403SDave Cobbley
21eb8dc403SDave CobbleySCRIPTS_PLUGIN_DIR = "scripts/lib/wic/plugins"
22eb8dc403SDave Cobbley
23eb8dc403SDave Cobbleylogger = logging.getLogger('wic')
24eb8dc403SDave Cobbley
25eb8dc403SDave CobbleyPLUGINS = defaultdict(dict)
26eb8dc403SDave Cobbley
27eb8dc403SDave Cobbleyclass PluginMgr:
28eb8dc403SDave Cobbley    _plugin_dirs = []
29eb8dc403SDave Cobbley
30eb8dc403SDave Cobbley    @classmethod
31eb8dc403SDave Cobbley    def get_plugins(cls, ptype):
32eb8dc403SDave Cobbley        """Get dictionary of <plugin_name>:<class> pairs."""
33eb8dc403SDave Cobbley        if ptype not in PLUGIN_TYPES:
34eb8dc403SDave Cobbley            raise WicError('%s is not valid plugin type' % ptype)
35eb8dc403SDave Cobbley
36eb8dc403SDave Cobbley        # collect plugin directories
37eb8dc403SDave Cobbley        if not cls._plugin_dirs:
38eb8dc403SDave Cobbley            cls._plugin_dirs = [os.path.join(os.path.dirname(__file__), 'plugins')]
39eb8dc403SDave Cobbley            layers = get_bitbake_var("BBLAYERS") or ''
40eb8dc403SDave Cobbley            for layer_path in layers.split():
41eb8dc403SDave Cobbley                path = os.path.join(layer_path, SCRIPTS_PLUGIN_DIR)
42eb8dc403SDave Cobbley                path = os.path.abspath(os.path.expanduser(path))
43eb8dc403SDave Cobbley                if path not in cls._plugin_dirs and os.path.isdir(path):
44eb8dc403SDave Cobbley                    cls._plugin_dirs.insert(0, path)
45eb8dc403SDave Cobbley
46eb8dc403SDave Cobbley        if ptype not in PLUGINS:
47eb8dc403SDave Cobbley            # load all ptype plugins
48eb8dc403SDave Cobbley            for pdir in cls._plugin_dirs:
49eb8dc403SDave Cobbley                ppath = os.path.join(pdir, ptype)
50eb8dc403SDave Cobbley                if os.path.isdir(ppath):
51eb8dc403SDave Cobbley                    for fname in os.listdir(ppath):
52eb8dc403SDave Cobbley                        if fname.endswith('.py'):
53eb8dc403SDave Cobbley                            mname = fname[:-3]
54eb8dc403SDave Cobbley                            mpath = os.path.join(ppath, fname)
55eb8dc403SDave Cobbley                            logger.debug("loading plugin module %s", mpath)
56eb8dc403SDave Cobbley                            SourceFileLoader(mname, mpath).load_module()
57eb8dc403SDave Cobbley
58eb8dc403SDave Cobbley        return PLUGINS.get(ptype)
59eb8dc403SDave Cobbley
60eb8dc403SDave Cobbleyclass PluginMeta(type):
61eb8dc403SDave Cobbley    def __new__(cls, name, bases, attrs):
62eb8dc403SDave Cobbley        class_type = type.__new__(cls, name, bases, attrs)
63eb8dc403SDave Cobbley        if 'name' in attrs:
64eb8dc403SDave Cobbley            PLUGINS[class_type.wic_plugin_type][attrs['name']] = class_type
65eb8dc403SDave Cobbley
66eb8dc403SDave Cobbley        return class_type
67eb8dc403SDave Cobbley
68eb8dc403SDave Cobbleyclass ImagerPlugin(metaclass=PluginMeta):
69eb8dc403SDave Cobbley    wic_plugin_type = "imager"
70eb8dc403SDave Cobbley
71eb8dc403SDave Cobbley    def do_create(self):
72eb8dc403SDave Cobbley        raise WicError("Method %s.do_create is not implemented" %
73eb8dc403SDave Cobbley                       self.__class__.__name__)
74eb8dc403SDave Cobbley
75eb8dc403SDave Cobbleyclass SourcePlugin(metaclass=PluginMeta):
76eb8dc403SDave Cobbley    wic_plugin_type = "source"
77eb8dc403SDave Cobbley    """
78eb8dc403SDave Cobbley    The methods that can be implemented by --source plugins.
79eb8dc403SDave Cobbley
80eb8dc403SDave Cobbley    Any methods not implemented in a subclass inherit these.
81eb8dc403SDave Cobbley    """
82eb8dc403SDave Cobbley
83eb8dc403SDave Cobbley    @classmethod
84eb8dc403SDave Cobbley    def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir,
85eb8dc403SDave Cobbley                        bootimg_dir, kernel_dir, native_sysroot):
86eb8dc403SDave Cobbley        """
87eb8dc403SDave Cobbley        Called after all partitions have been prepared and assembled into a
88eb8dc403SDave Cobbley        disk image.  This provides a hook to allow finalization of a
89eb8dc403SDave Cobbley        disk image e.g. to write an MBR to it.
90eb8dc403SDave Cobbley        """
91eb8dc403SDave Cobbley        logger.debug("SourcePlugin: do_install_disk: disk: %s", disk_name)
92eb8dc403SDave Cobbley
93eb8dc403SDave Cobbley    @classmethod
94eb8dc403SDave Cobbley    def do_stage_partition(cls, part, source_params, creator, cr_workdir,
95eb8dc403SDave Cobbley                           oe_builddir, bootimg_dir, kernel_dir,
96eb8dc403SDave Cobbley                           native_sysroot):
97eb8dc403SDave Cobbley        """
98eb8dc403SDave Cobbley        Special content staging hook called before do_prepare_partition(),
99eb8dc403SDave Cobbley        normally empty.
100eb8dc403SDave Cobbley
101eb8dc403SDave Cobbley        Typically, a partition will just use the passed-in parame e.g
102eb8dc403SDave Cobbley        straight bootimg_dir, etc, but in some cases, things need to
103eb8dc403SDave Cobbley        be more tailored e.g. to use a deploy dir + /boot, etc.  This
104eb8dc403SDave Cobbley        hook allows those files to be staged in a customized fashion.
105eb8dc403SDave Cobbley        Not that get_bitbake_var() allows you to acces non-standard
106eb8dc403SDave Cobbley        variables that you might want to use for this.
107eb8dc403SDave Cobbley        """
108eb8dc403SDave Cobbley        logger.debug("SourcePlugin: do_stage_partition: part: %s", part)
109eb8dc403SDave Cobbley
110eb8dc403SDave Cobbley    @classmethod
111eb8dc403SDave Cobbley    def do_configure_partition(cls, part, source_params, creator, cr_workdir,
112eb8dc403SDave Cobbley                               oe_builddir, bootimg_dir, kernel_dir,
113eb8dc403SDave Cobbley                               native_sysroot):
114eb8dc403SDave Cobbley        """
115eb8dc403SDave Cobbley        Called before do_prepare_partition(), typically used to create
116eb8dc403SDave Cobbley        custom configuration files for a partition, for example
117eb8dc403SDave Cobbley        syslinux or grub config files.
118eb8dc403SDave Cobbley        """
119eb8dc403SDave Cobbley        logger.debug("SourcePlugin: do_configure_partition: part: %s", part)
120eb8dc403SDave Cobbley
121eb8dc403SDave Cobbley    @classmethod
122eb8dc403SDave Cobbley    def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
123eb8dc403SDave Cobbley                             oe_builddir, bootimg_dir, kernel_dir, rootfs_dir,
124eb8dc403SDave Cobbley                             native_sysroot):
125eb8dc403SDave Cobbley        """
126eb8dc403SDave Cobbley        Called to do the actual content population for a partition i.e. it
127eb8dc403SDave Cobbley        'prepares' the partition to be incorporated into the image.
128eb8dc403SDave Cobbley        """
129eb8dc403SDave Cobbley        logger.debug("SourcePlugin: do_prepare_partition: part: %s", part)
130eb8dc403SDave Cobbley
131eb8dc403SDave Cobbley    @classmethod
132eb8dc403SDave Cobbley    def do_post_partition(cls, part, source_params, creator, cr_workdir,
133eb8dc403SDave Cobbley                             oe_builddir, bootimg_dir, kernel_dir, rootfs_dir,
134eb8dc403SDave Cobbley                             native_sysroot):
135eb8dc403SDave Cobbley        """
136eb8dc403SDave Cobbley        Called after the partition is created. It is useful to add post
137eb8dc403SDave Cobbley        operations e.g. security signing the partition.
138eb8dc403SDave Cobbley        """
139eb8dc403SDave Cobbley        logger.debug("SourcePlugin: do_post_partition: part: %s", part)
140