blob: 306b32437ea14df7bd01a1c532f19a69ca8d8ea0 [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
18import os, sys
19
20from wic import msger
21from wic import pluginbase
22from wic.utils import errors
23from wic.utils.oe.misc import get_bitbake_var
24
25__ALL__ = ['PluginMgr', 'pluginmgr']
26
27PLUGIN_TYPES = ["imager", "source"]
28
29PLUGIN_DIR = "/lib/wic/plugins" # relative to scripts
30SCRIPTS_PLUGIN_DIR = "scripts" + PLUGIN_DIR
31
Patrick Williamsc0f7c042017-02-23 20:41:17 -060032class PluginMgr():
Patrick Williamsc124f4f2015-09-15 14:41:29 -050033 plugin_dirs = {}
34
35 # make the manager class as singleton
36 _instance = None
37 def __new__(cls, *args, **kwargs):
38 if not cls._instance:
39 cls._instance = super(PluginMgr, cls).__new__(cls, *args, **kwargs)
40
41 return cls._instance
42
43 def __init__(self):
44 wic_path = os.path.dirname(__file__)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060045 eos = wic_path.rfind('scripts') + len('scripts')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050046 scripts_path = wic_path[:eos]
47 self.scripts_path = scripts_path
48 self.plugin_dir = scripts_path + PLUGIN_DIR
49 self.layers_path = None
50
51 def _build_plugin_dir_list(self, plugin_dir, ptype):
52 if self.layers_path is None:
53 self.layers_path = get_bitbake_var("BBLAYERS")
54 layer_dirs = []
55
56 if self.layers_path is not None:
57 for layer_path in self.layers_path.split():
58 path = os.path.join(layer_path, SCRIPTS_PLUGIN_DIR, ptype)
59 layer_dirs.append(path)
60
61 path = os.path.join(plugin_dir, ptype)
62 layer_dirs.append(path)
63
64 return layer_dirs
65
66 def append_dirs(self, dirs):
67 for path in dirs:
68 self._add_plugindir(path)
69
70 # load all the plugins AGAIN
71 self._load_all()
72
73 def _add_plugindir(self, path):
74 path = os.path.abspath(os.path.expanduser(path))
75
76 if not os.path.isdir(path):
77 return
78
79 if path not in self.plugin_dirs:
80 self.plugin_dirs[path] = False
81 # the value True/False means "loaded"
82
83 def _load_all(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060084 for (pdir, loaded) in self.plugin_dirs.items():
Patrick Williamsc124f4f2015-09-15 14:41:29 -050085 if loaded:
86 continue
87
88 sys.path.insert(0, pdir)
89 for mod in [x[:-3] for x in os.listdir(pdir) if x.endswith(".py")]:
90 if mod and mod != '__init__':
91 if mod in sys.modules:
92 #self.plugin_dirs[pdir] = True
93 msger.warning("Module %s already exists, skip" % mod)
94 else:
95 try:
96 pymod = __import__(mod)
97 self.plugin_dirs[pdir] = True
98 msger.debug("Plugin module %s:%s imported"\
99 % (mod, pymod.__file__))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600100 except ImportError as err:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101 msg = 'Failed to load plugin %s/%s: %s' \
102 % (os.path.basename(pdir), mod, err)
103 msger.warning(msg)
104
105 del sys.path[0]
106
107 def get_plugins(self, ptype):
108 """ the return value is dict of name:class pairs """
109
110 if ptype not in PLUGIN_TYPES:
111 raise errors.CreatorError('%s is not valid plugin type' % ptype)
112
113 plugins_dir = self._build_plugin_dir_list(self.plugin_dir, ptype)
114
115 self.append_dirs(plugins_dir)
116
117 return pluginbase.get_plugins(ptype)
118
119 def get_source_plugins(self):
120 """
121 Return list of available source plugins.
122 """
123 plugins_dir = self._build_plugin_dir_list(self.plugin_dir, 'source')
124
125 self.append_dirs(plugins_dir)
126
127 return self.get_plugins('source')
128
129
130 def get_source_plugin_methods(self, source_name, methods):
131 """
132 The methods param is a dict with the method names to find. On
133 return, the dict values will be filled in with pointers to the
134 corresponding methods. If one or more methods are not found,
135 None is returned.
136 """
137 return_methods = None
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600138 for _source_name, klass in self.get_plugins('source').items():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500139 if _source_name == source_name:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600140 for _method_name in methods:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500141 if not hasattr(klass, _method_name):
142 msger.warning("Unimplemented %s source interface for: %s"\
143 % (_method_name, _source_name))
144 return None
145 func = getattr(klass, _method_name)
146 methods[_method_name] = func
147 return_methods = methods
148 return return_methods
149
150pluginmgr = PluginMgr()