blob: fb3d179c2dbf5d0eae6d8a3d353522f783f5bb5e [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#!/usr/bin/env python -tt
2#
3# Copyright (c) 2011 Intel, Inc.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by the Free
7# Software Foundation; version 2 of the License
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12# for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program; if not, write to the Free Software Foundation, Inc., 59
16# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
Brad Bishop6e60e8b2018-02-01 10:27:11 -050018__all__ = ['ImagerPlugin', 'SourcePlugin']
Patrick Williamsc0f7c042017-02-23 20:41:17 -060019
Brad Bishop6e60e8b2018-02-01 10:27:11 -050020import os
21import logging
22
Patrick Williamsc0f7c042017-02-23 20:41:17 -060023from collections import defaultdict
Brad Bishop6e60e8b2018-02-01 10:27:11 -050024from importlib.machinery import SourceFileLoader
Patrick Williamsc0f7c042017-02-23 20:41:17 -060025
Brad Bishop6e60e8b2018-02-01 10:27:11 -050026from wic import WicError
27from wic.utils.misc import get_bitbake_var
28
29PLUGIN_TYPES = ["imager", "source"]
30
31SCRIPTS_PLUGIN_DIR = "scripts/lib/wic/plugins"
32
33logger = logging.getLogger('wic')
34
35PLUGINS = defaultdict(dict)
36
37class PluginMgr:
38 _plugin_dirs = []
39
40 @classmethod
41 def get_plugins(cls, ptype):
42 """Get dictionary of <plugin_name>:<class> pairs."""
43 if ptype not in PLUGIN_TYPES:
44 raise WicError('%s is not valid plugin type' % ptype)
45
46 # collect plugin directories
47 if not cls._plugin_dirs:
48 cls._plugin_dirs = [os.path.join(os.path.dirname(__file__), 'plugins')]
49 layers = get_bitbake_var("BBLAYERS") or ''
50 for layer_path in layers.split():
51 path = os.path.join(layer_path, SCRIPTS_PLUGIN_DIR)
52 path = os.path.abspath(os.path.expanduser(path))
53 if path not in cls._plugin_dirs and os.path.isdir(path):
54 cls._plugin_dirs.insert(0, path)
55
56 if ptype not in PLUGINS:
57 # load all ptype plugins
58 for pdir in cls._plugin_dirs:
59 ppath = os.path.join(pdir, ptype)
60 if os.path.isdir(ppath):
61 for fname in os.listdir(ppath):
62 if fname.endswith('.py'):
63 mname = fname[:-3]
64 mpath = os.path.join(ppath, fname)
65 logger.debug("loading plugin module %s", mpath)
66 SourceFileLoader(mname, mpath).load_module()
67
68 return PLUGINS.get(ptype)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050069
Patrick Williamsc0f7c042017-02-23 20:41:17 -060070class PluginMeta(type):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060071 def __new__(cls, name, bases, attrs):
72 class_type = type.__new__(cls, name, bases, attrs)
73 if 'name' in attrs:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050074 PLUGINS[class_type.wic_plugin_type][attrs['name']] = class_type
Patrick Williamsc124f4f2015-09-15 14:41:29 -050075
Patrick Williamsc0f7c042017-02-23 20:41:17 -060076 return class_type
Patrick Williamsc124f4f2015-09-15 14:41:29 -050077
Brad Bishop6e60e8b2018-02-01 10:27:11 -050078class ImagerPlugin(metaclass=PluginMeta):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050079 wic_plugin_type = "imager"
80
Brad Bishop6e60e8b2018-02-01 10:27:11 -050081 def do_create(self):
82 raise WicError("Method %s.do_create is not implemented" %
83 self.__class__.__name__)
84
85class SourcePlugin(metaclass=PluginMeta):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050086 wic_plugin_type = "source"
87 """
88 The methods that can be implemented by --source plugins.
89
90 Any methods not implemented in a subclass inherit these.
91 """
92
93 @classmethod
94 def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir,
95 bootimg_dir, kernel_dir, native_sysroot):
96 """
97 Called after all partitions have been prepared and assembled into a
98 disk image. This provides a hook to allow finalization of a
99 disk image e.g. to write an MBR to it.
100 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500101 logger.debug("SourcePlugin: do_install_disk: disk: %s", disk_name)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500102
103 @classmethod
104 def do_stage_partition(cls, part, source_params, creator, cr_workdir,
105 oe_builddir, bootimg_dir, kernel_dir,
106 native_sysroot):
107 """
108 Special content staging hook called before do_prepare_partition(),
109 normally empty.
110
111 Typically, a partition will just use the passed-in parame e.g
112 straight bootimg_dir, etc, but in some cases, things need to
113 be more tailored e.g. to use a deploy dir + /boot, etc. This
114 hook allows those files to be staged in a customized fashion.
115 Not that get_bitbake_var() allows you to acces non-standard
116 variables that you might want to use for this.
117 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500118 logger.debug("SourcePlugin: do_stage_partition: part: %s", part)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500119
120 @classmethod
121 def do_configure_partition(cls, part, source_params, creator, cr_workdir,
122 oe_builddir, bootimg_dir, kernel_dir,
123 native_sysroot):
124 """
125 Called before do_prepare_partition(), typically used to create
126 custom configuration files for a partition, for example
127 syslinux or grub config files.
128 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500129 logger.debug("SourcePlugin: do_configure_partition: part: %s", part)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500130
131 @classmethod
132 def do_prepare_partition(cls, part, source_params, creator, cr_workdir,
133 oe_builddir, bootimg_dir, kernel_dir, rootfs_dir,
134 native_sysroot):
135 """
136 Called to do the actual content population for a partition i.e. it
137 'prepares' the partition to be incorporated into the image.
138 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500139 logger.debug("SourcePlugin: do_prepare_partition: part: %s", part)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500140