From: JF Ding Date: Tue, 30 Aug 2011 05:32:56 +0000 (+0800) Subject: more compact plugin framwork X-Git-Tag: 0.1~174 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=87d5afa5cc1859883ca205e3e967b4653e0de0e5;p=tools%2Fmic.git more compact plugin framwork --- diff --git a/mic/chroot.py b/mic/chroot.py index 82153c4..026ea7e 100644 --- a/mic/chroot.py +++ b/mic/chroot.py @@ -129,7 +129,7 @@ def setup_chrootenv(chrootdir, bindmounts = None): continue if srcdst[0] in BIND_MOUNTS or srcdst[0] == '/': - pwarning("%s will be mounted by default." % srcdst[0]) + msger.warning("%s will be mounted by default." % srcdst[0]) continue if srcdst[1] == "" or srcdst[1] == "none": @@ -137,7 +137,7 @@ def setup_chrootenv(chrootdir, bindmounts = None): else: srcdst[1] = os.path.abspath(os.path.expanduser(srcdst[1])) if os.path.isdir(chrootdir + "/" + srcdst[1]): - pwarning("%s has existed in %s , skip it." % (srcdst[1], chrootdir)) + msger.warning("%s has existed in %s , skip it." % (srcdst[1], chrootdir)) continue chrootmounts.append(fs_related.BindChrootMount(srcdst[0], chrootdir, srcdst[1])) diff --git a/mic/creator.py b/mic/creator.py index 58eb9d9..e47fa57 100644 --- a/mic/creator.py +++ b/mic/creator.py @@ -44,14 +44,14 @@ class Creator(cmdln.Cmdln): # load pluginmgr self.pluginmgr = pluginmgr.PluginMgr() - self.pluginmgr.loadPlugins() - self.plugincmds = self.pluginmgr.getImagerPlugins() + self.plugincmds = self.pluginmgr.get_plugins('imager') # mix-in do_subcmd interface - for subcmd, klass in self.plugincmds: + for subcmd, klass in self.plugincmds.iteritems(): if not hasattr(klass, 'do_create'): msger.warning("Unsurpport subcmd: %s" % subcmd) continue + func = getattr(klass, 'do_create') setattr(self.__class__, "do_"+subcmd, func) diff --git a/mic/pluginbase/imager_plugin.py b/mic/pluginbase.py similarity index 50% rename from mic/pluginbase/imager_plugin.py rename to mic/pluginbase.py index 35c111a..1fdf390 100644 --- a/mic/pluginbase/imager_plugin.py +++ b/mic/pluginbase.py @@ -17,8 +17,30 @@ # with the express permission of Red Hat, Inc. # -class ImagerPlugin(object): - plugin_type = "imager" +from mic import msger + +class _Plugin(object): + class __metaclass__(type): + def __init__(cls, name, bases, attrs): + if not hasattr(cls, 'plugins'): + cls.plugins = {} + + elif 'mic_plugin_type' in attrs: + if attrs['mic_plugin_type'] not in cls.plugins: + cls.plugins[attrs['mic_plugin_type']] = {} + + elif hasattr(cls, 'mic_plugin_type') and 'name' in attrs: + cls.plugins[cls.mic_plugin_type][attrs['name']] = cls + + def show_plugins(cls): + for cls in cls.plugins[cls.mic_plugin_type]: + print cls + + def get_plugins(cls): + return cls.plugins + +class ImagerPlugin(_Plugin): + mic_plugin_type = "imager" def do_create(self): pass @@ -32,5 +54,17 @@ class ImagerPlugin(object): def do_unpack(self): pass -# [a, b]: a is for subcmd name, b is for plugin class -mic_plugin = ["", None] +class BackendPlugin(_Plugin): + mic_plugin_type="backend" + + def addRepository(self): + pass + +def get_plugins(typen): + ps = ImagerPlugin.get_plugins() + if typen in ps: + return ps[typen] + else: + return None + +__all__ = ['ImagerPlugin', 'BackendPlugin', 'get_plugins'] diff --git a/mic/pluginbase/__init__.py b/mic/pluginbase/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mic/pluginbase/backend_plugin.py b/mic/pluginbase/backend_plugin.py deleted file mode 100644 index c8131db..0000000 --- a/mic/pluginbase/backend_plugin.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/python -tt -# -# Copyright 2008, 2009, 2010 Intel, Inc. -# -# This copyrighted material is made available to anyone wishing to use, modify, -# copy, or redistribute it subject to the terms and conditions of the GNU -# General Public License v.2. This program is distributed in the hope that it -# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the -# implied warranties 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. Any Red Hat -# trademarks that are incorporated in the source code or documentation are not -# subject to the GNU General Public License and may only be used or replicated -# with the express permission of Red Hat, Inc. -# - -class BackendPlugin(object): - plugin_type="backend" - - def addRepository(self): - pass - -# [a, b]: a is for bachend name, b is for bachend class -mic_plugin = ["", None] diff --git a/mic/pluginbase/hook_plugin.py b/mic/pluginbase/hook_plugin.py deleted file mode 100644 index 764062c..0000000 --- a/mic/pluginbase/hook_plugin.py +++ /dev/null @@ -1,3 +0,0 @@ -#/usr/bin/python - -# TODO: implementation diff --git a/mic/pluginmgr.py b/mic/pluginmgr.py index e1a1e49..3569387 100644 --- a/mic/pluginmgr.py +++ b/mic/pluginmgr.py @@ -19,127 +19,62 @@ import os, sys from mic import msger +from mic import pluginbase DEFAULT_PLUGIN_LOCATION = "/usr/lib/mic/plugins" -PLGUIN_TYPES = ["imager", "backend", "hook"] - -STRING_PLUGIN_MARK = "mic_plugin" -STRING_PTYPE_MARK = "plugin_type" +PLUGIN_TYPES = ["imager", "backend"] # TODO "hook" class PluginMgr(object): - def __init__(self, plugin_dirs=[]): - self.plugin_locations = [] - self.plugin_sets = {} - self.plugin_types = PLGUIN_TYPES - - # initial plugin directory - self.addPluginDir(DEFAULT_PLUGIN_LOCATION) - for directory in plugin_dirs: - self.addPluginDir(os.path.expanduser(directory)) - - # intial plugin sets - for plugintype in self.plugin_types: - self.plugin_sets[plugintype] = [] - - def addPluginDir(self, plugin_dir): - if not os.path.isdir(plugin_dir): - msger.debug("Plugin dir is not a directory or does not exist: %s" % plugin_dir) - return - - if plugin_dir not in self.plugin_locations: - self.plugin_locations.append(plugin_dir) - - def pluginCheck(self, pymod): - if not hasattr(pymod, STRING_PLUGIN_MARK): - msger.debug("Not a valid plugin: %s" % pymod.__file__) - msger.debug("Please check whether %s given" % STRING_PLUGIN_MARK) - return False - - plclass = getattr(pymod, STRING_PLUGIN_MARK)[1] - if not hasattr(plclass, STRING_PTYPE_MARK): - msger.debug("Not a valid plugin: %s" % pymod.__file__) - msger.debug("Please check whether %s given" % STRING_PTYPE_MARK) - return False + plugin_dirs = {} - pltype = getattr(plclass, STRING_PTYPE_MARK) - if not (pltype in self.plugin_types): - msger.debug("Unsupported plugin type in %s: %s" % (pymod.__file__, plugintype)) - return False + # make the manager class as singleton + _instance = None + def __new__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super(PluginMgr, cls).__new__(cls, *args, **kwargs) - return True + return cls._instance - def importModule(self, dir_path, plugin_filename): - if plugin_filename.endswith(".pyc"): - return - - if not plugin_filename.endswith(".py"): - msger.debug("Not a python file: %s" % os.path.join(dir_path, plugin_filename)) - return + def __init__(self, plugin_dirs=[]): - if plugin_filename == ".py": - msger.debug("Empty module name: %s" % os.path.join(dir_path, plugin_filename)) - return + # default plugin directory + for pt in PLUGIN_TYPES: + self._add_plugindir(os.path.join(DEFAULT_PLUGIN_LOCATION, pt)) - if plugin_filename == "__init__.py": - msger.debug("Unsupported python file: %s" % os.path.join(dir_path, plugin_filename)) - return + for dir in plugin_dirs: + self._add_plugindir(dir) - modname = os.path.splitext(plugin_filename)[0] - if sys.modules.has_key(modname): - pymod = sys.modules[modname] - msger.debug("Module %s already exists: %s" % (modname, pymod.__file__)) + # load all the plugins + self._load_all() - else: - pymod = __import__(modname) - pymod.__file__ = os.path.join(dir_path, plugin_filename) - msger.debug("Plugin module %s:%s importing" % (modname, pymod.__file__)) + def _add_plugindir(self, dir): + dir = os.path.abspath(os.path.expanduser(dir)) - if not self.pluginCheck(pymod): - msger.warning("Failed to check plugin: %s" % os.path.join(dir_path, plugin_filename)) + if not os.path.isdir(dir): + msger.warning("Plugin dir is not a directory or does not exist: %s" % dir) return - (pname, pcls) = pymod.__dict__[STRING_PLUGIN_MARK] - plugintype = getattr(pcls, STRING_PTYPE_MARK) - self.plugin_sets[plugintype].append((pname, pcls)) - - def loadPlugins(self): - for pdir in map(os.path.abspath, self.plugin_locations): - for pitem in os.walk(pdir): - sys.path.insert(0, pitem[0]) - for pf in pitem[2]: - self.importModule(pitem[0], pf) - del(sys.path[0]) - - def getPluginByCateg(self, categ = None): - if not (categ in self.plugin_types): - msger.warning("Failed to get plugin category: %s" % categ) - return None - else: - return self.plugin_sets[categ] - - def getImagerPlugins(self): - return self.plugin_sets['imager'] - - def getBackendPlugins(self): - return self.plugin_sets['backend'] - - def getHookPlugins(self): - return self.plugin_sets['hook'] - - def listAllPlugins(self): - # just for debug - for key in self.plugin_sets.keys(): - msger.debug("plugin type (%s) :::\n" % key) - for item in self.plugin_sets[key]: - msger.debug("%-6s: %s\n" % (item[0], item[1])) - - def getPluginType(self, plugin_str): - pass - -if __name__ == "__main__": - msger.set_loglevel('debug') - - pluginmgr = PluginMgr() - pluginmgr.loadPlugins() - pluginmgr.listAllPlugins() + if dir not in self.plugin_dirs: + self.plugin_dirs[dir] = False + # the value True/False means "loaded" + + def _load_all(self): + for (pdir, loaded) in self.plugin_dirs.iteritems(): + if loaded: continue + + sys.path.insert(0, pdir) + for mod in [x[:-3] for x in os.listdir(pdir) if x.endswith(".py")]: + if mod and mod != '__init__': + if mod in sys.modules: + msger.debug("Module %s already exists, skip" % mod) + else: + pymod = __import__(mod) + self.plugin_dirs[pdir] = True + msger.debug("Plugin module %s:%s importing" % (mod, pymod.__file__)) + + del(sys.path[0]) + + def get_plugins(self, ptype): + """ the return value is dict of name:class pairs """ + return pluginbase.get_plugins(ptype) diff --git a/plugins/backend/yumpkgmgr.py b/plugins/backend/yumpkgmgr.py index 2c4656f..40118b1 100644 --- a/plugins/backend/yumpkgmgr.py +++ b/plugins/backend/yumpkgmgr.py @@ -32,9 +32,10 @@ import subprocess from mic.utils.errors import * from mic.utils.fs_related import * -from mic.pluginbase.backend_plugin import BackendPlugin from mic.imager.baseimager import BaseImageCreator as ImageCreator + from mic import msger +from mic.pluginbase import BackendPlugin def getRPMCallback(): sys.path.append('/usr/share/yum-cli') @@ -137,6 +138,8 @@ class MyYumRepository(yum.yumRepo.YumRepository): pass class Yum(BackendPlugin, yum.YumBase): + name = 'yum' + def __init__(self, creator = None, recording_pkgs=None): if not isinstance(creator, ImageCreator): raise CreatorError("Invalid argument: creator") @@ -534,5 +537,3 @@ class Yum(BackendPlugin, yum.YumBase): def getAllContent(self): return self.__pkgs_content - -mic_plugin = ["yum", Yum] diff --git a/plugins/backend/zypppkgmgr.py b/plugins/backend/zypppkgmgr.py index 29af211..c93f665 100644 --- a/plugins/backend/zypppkgmgr.py +++ b/plugins/backend/zypppkgmgr.py @@ -16,7 +16,8 @@ from mic.imager.baseimager import BaseImageCreator as ImageCreator from mic.utils.fs_related import * from mic.utils.misc import * from mic.utils.rpmmisc import * -from mic.pluginbase.backend_plugin import BackendPlugin + +from mic.pluginbase import BackendPlugin class RepositoryStub: def __init__(self): @@ -41,6 +42,8 @@ class RpmError(CreatorError): pass class Zypp(BackendPlugin): + name = 'zypp' + def __init__(self, creator = None, recording_pkgs=None): if not isinstance(creator, ImageCreator): raise CreatorError("Invalid argument: creator") @@ -753,5 +756,3 @@ class Zypp(BackendPlugin): repourl = repoinfo.baseUrls()[0].__str__() return get_proxy(repourl) -mic_plugin = ["zypp", Zypp] - diff --git a/plugins/imager/fs_plugin.py b/plugins/imager/fs_plugin.py index 451b9b8..80cd985 100644 --- a/plugins/imager/fs_plugin.py +++ b/plugins/imager/fs_plugin.py @@ -2,7 +2,6 @@ import sys import subprocess -from mic.pluginbase.imager_plugin import ImagerPlugin import mic.utils.cmdln as cmdln import mic.utils.errors as errors import mic.configmgr as configmgr @@ -10,8 +9,11 @@ import mic.pluginmgr as pluginmgr import mic.imager.fs as fs import mic.chroot as chroot +from mic.pluginbase import ImagerPlugin class FsPlugin(ImagerPlugin): + name = 'fs' + @classmethod @cmdln.option("--include-src", dest="include_src", help="include source pakcage") def do_create(self, subcmd, opts, *args): @@ -32,10 +34,10 @@ class FsPlugin(ImagerPlugin): cfgmgr.setProperty("ksconf", ksconf) plgmgr = pluginmgr.PluginMgr() - plgmgr.loadPlugins() - for (key, pcls) in plgmgr.getBackendPlugins(): + for (key, pcls) in plgmgr.get_plugins('backend').iteritems(): if key == createopts['pkgmgr']: pkgmgr = pcls + if not pkgmgr: raise CreatorError("Can't find backend plugin: %s" % createopts['pkgmgr']) @@ -75,4 +77,3 @@ class FsPlugin(ImagerPlugin): chroot.cleanup_after_chroot("dir", None, None, None) return 1 -mic_plugin = ["fs", FsPlugin] diff --git a/plugins/imager/livecd_plugin.py b/plugins/imager/livecd_plugin.py index 5f92283..a0bccca 100644 --- a/plugins/imager/livecd_plugin.py +++ b/plugins/imager/livecd_plugin.py @@ -4,7 +4,6 @@ import subprocess import shutil import tempfile -from mic.pluginbase.imager_plugin import ImagerPlugin import mic.chroot as chroot import mic.utils.misc as misc import mic.utils.fs_related as fs_related @@ -14,7 +13,10 @@ import mic.pluginmgr as pluginmgr import mic.imager.livecd as livecd from mic.utils.errors import * +from mic.pluginbase import ImagerPlugin + class LiveCDPlugin(ImagerPlugin): + name = 'livecd' @classmethod def do_create(self, subcmd, opts, *args): @@ -34,9 +36,8 @@ class LiveCDPlugin(ImagerPlugin): cfgmgr.setProperty("ksconf", ksconf) creatoropts = cfgmgr.create plgmgr = pluginmgr.PluginMgr() - plgmgr.loadPlugins() - for (key, pcls) in plgmgr.getBackendPlugins(): + for (key, pcls) in plgmgr.get_plugins('backend').iteritems(): if key == creatoropts['pkgmgr']: pkgmgr = pcls @@ -168,5 +169,3 @@ class LiveCDPlugin(ImagerPlugin): shutil.rmtree(imgmnt, ignore_errors = True) return rtimage - -mic_plugin = ["livecd", LiveCDPlugin] diff --git a/plugins/imager/liveusb_plugin.py b/plugins/imager/liveusb_plugin.py index f6007af..e4dc98b 100644 --- a/plugins/imager/liveusb_plugin.py +++ b/plugins/imager/liveusb_plugin.py @@ -5,7 +5,7 @@ import subprocess import shutil import tempfile -from mic.pluginbase.imager_plugin import ImagerPlugin +from mic.pluginbase import ImagerPlugin import mic.imager.liveusb as liveusb import mic.utils.misc as misc import mic.utils.fs_related as fs_related @@ -17,6 +17,8 @@ from mic.utils.errors import * import mic.chroot as chroot class LiveUSBPlugin(ImagerPlugin): + name = 'liveusb' + #@cmdln.option @classmethod def do_create(self, subcmd, opts, *args): @@ -37,9 +39,8 @@ class LiveUSBPlugin(ImagerPlugin): creatoropts = cfgmgr.create cfgmgr.setProperty("ksconf", args[0]) plgmgr = pluginmgr.PluginMgr() - plgmgr.loadPlugins() - for (key, pcls) in plgmgr.getBackendPlugins(): + for (key, pcls) in plgmgr.get_plugins('backend').iteritems(): if key == creatoropts['pkgmgr']: pkgmgr = pcls @@ -169,5 +170,3 @@ class LiveUSBPlugin(ImagerPlugin): shutil.rmtree(imgmnt, ignore_errors = True) return rtimage - -mic_plugin = ["liveusb", LiveUSBPlugin] diff --git a/plugins/imager/loop_plugin.py b/plugins/imager/loop_plugin.py index 70dbab5..b002e1a 100644 --- a/plugins/imager/loop_plugin.py +++ b/plugins/imager/loop_plugin.py @@ -6,7 +6,7 @@ import subprocess import shutil import tempfile -from mic.pluginbase.imager_plugin import ImagerPlugin +from mic.pluginbase import ImagerPlugin import mic.utils.misc as misc import mic.utils.cmdln as cmdln import mic.utils.fs_related as fs_related @@ -17,6 +17,8 @@ import mic.imager.loop as loop import mic.chroot as chroot class LoopPlugin(ImagerPlugin): + name = 'loop' + @classmethod def do_create(self, subcmd, opts, *args): """${cmd_name}: create loop image @@ -36,9 +38,8 @@ class LoopPlugin(ImagerPlugin): cfgmgr.setProperty("ksconf", ksconf) plgmgr = pluginmgr.PluginMgr() - plgmgr.loadPlugins() - for (key, pcls) in plgmgr.getBackendPlugins(): + for (key, pcls) in plgmgr.get_plugins('backend').iteritems(): if key == creatoropts['pkgmgr']: pkgmgr = pcls @@ -92,6 +93,3 @@ class LoopPlugin(ImagerPlugin): print "Copying file system..." shutil.copyfile(srcimg, image) return image - -mic_plugin = ["loop", LoopPlugin] - diff --git a/plugins/imager/raw_plugin.py b/plugins/imager/raw_plugin.py index 99c6ccd..6a5659a 100644 --- a/plugins/imager/raw_plugin.py +++ b/plugins/imager/raw_plugin.py @@ -6,7 +6,7 @@ import shutil import re import tempfile -from mic.pluginbase.imager_plugin import ImagerPlugin +from mic.pluginbase import ImagerPlugin import mic.utils.misc as misc import mic.utils.fs_related as fs_related import mic.utils.cmdln as cmdln @@ -18,6 +18,7 @@ import mic.imager.raw as raw import mic.chroot as chroot class RawPlugin(ImagerPlugin): + name = 'raw' @classmethod def do_create(self, subcmd, opts, *args): @@ -37,9 +38,8 @@ class RawPlugin(ImagerPlugin): creatoropts = cfgmgr.create cfgmgr.setProperty("ksconf", ksconf) plgmgr = pluginmgr.PluginMgr() - plgmgr.loadPlugins() - for (key, pcls) in plgmgr.getBackendPlugins(): + for (key, pcls) in plgmgr.get_plugins('backend').iteritems(): if key == creatoropts['pkgmgr']: pkgmgr = pcls @@ -177,6 +177,3 @@ class RawPlugin(ImagerPlugin): srcloop.cleanup() shutil.rmtree(srcmnt, ignore_errors = True) return image - -mic_plugin = ["raw", RawPlugin] - diff --git a/setup.py b/setup.py index a3bc3f1..475d719 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,6 @@ except IOError: PACKAGES = [MOD_NAME, MOD_NAME + '/utils', MOD_NAME + '/imager', - MOD_NAME + '/pluginbase', MOD_NAME + '/urlgrabber', MOD_NAME + '/kickstart', MOD_NAME + '/kickstart/custom_commands',