import lisa.plugins import pip import shutil import inspect from lisa.server.web.manageplugins.models import Plugin, Description, Rule, Cron, Intent import json, os from twisted.python import log from twisted.python.reflect import namedAny from django.template.loader import render_to_string import datetime from lisa.server.web.weblisa.settings import LISA_PATH, configuration from pymongo import MongoClient class PluginManager(object): """ """ def __init__(self): self.pkgpath = os.path.dirname(lisa.plugins.__file__) self.enabled_plugins = [] mongo = MongoClient(configuration['database']['server'], configuration['database']['port']) self.database = mongo.lisa def getEnabledPlugins(self): return self.enabled_plugins def loadPlugins(self): for plugin in self.database.plugins.find( { "enabled": True, "lang": configuration['lang'] } ): self.enabled_plugins.append(str(plugin['name'])) return self.enabled_plugins def getPluginByName(self, plugin_name): """ Get the plugin correspoding to a given name """ return None def installPlugin(self, plugin_name=None): pip.main(['install', 'lisa-plugin-' + plugin_name]) jsonfile = self.pkgpath + '/' + plugin_name + '/' + plugin_name.lower() + '.json' metadata = json.load(open(jsonfile)) if Plugin.objects(name=plugin_name): return {'status': 'fail', 'log': 'Plugin already installed'} else: plugin = Plugin() description_list = [] for item in metadata: if item != 'cron' or item != 'rules': if item == 'description': for description in metadata[item]: oDescription = Description() for k,v in description.iteritems(): setattr(oDescription, k, v) description_list.append(oDescription) setattr(plugin, item, description_list) elif item == 'enabled': if metadata[item] == 0: setattr(plugin, item, False) else: setattr(plugin, item, True) else: setattr(plugin, item, metadata[item]) plugin.save() for item in metadata: if item == 'rules': for rule_item in metadata['rules']: rule = Rule() for parameter in rule_item: setattr(rule, parameter, rule_item[parameter]) rule.plugin = plugin rule.save() if item == 'crons': for cron_item in metadata['crons']: cron = Cron() for parameter in cron_item: setattr(cron, parameter, cron_item[parameter]) cron.plugin = plugin cron.save() for intent, value in metadata['configuration']['intents'].iteritems(): oIntent = Intent() oIntent.name = intent oIntent.function = value['method'] oIntent.module = '.'.join(['lisa.plugins', plugin_name, 'modules', plugin_name.lower(), plugin_name]) oIntent.enabled = True oIntent.plugin = plugin oIntent.save() os.remove(jsonfile) return {'status': 'success', 'log': 'Plugin installed'} def enablePlugin(self, plugin_name=None, plugin_pk=None): if plugin_pk: plugin_list = Plugin.objects(pk=plugin_pk) else: plugin_list = Plugin.objects(name=plugin_name) for plugin in plugin_list: if plugin.enabled: return {'status': 'fail', 'log': 'Plugin already enabled'} else: plugin.enabled = True plugin.save() for cron in Cron.objects(plugin=plugin): cron.enabled = True cron.save() for rule in Rule.objects(plugin=plugin): rule.enabled = True rule.save() intent_list = Intent.objects(plugin=plugin) for oIntent in intent_list: oIntent.enabled = True oIntent.save() return {'status': 'success', 'log': 'Plugin enabled'} def disablePlugin(self, plugin_name=None, plugin_pk=None): if plugin_pk: plugin_list = Plugin.objects(pk=plugin_pk) else: plugin_list = Plugin.objects(name=plugin_name) for plugin in plugin_list: if not plugin.enabled: return {'status': 'fail', 'log': 'Plugin already disabled'} else: plugin.enabled = False plugin.save() for cron in Cron.objects(plugin=plugin): cron.enabled = False cron.save() for rule in Rule.objects(plugin=plugin): rule.enabled = False rule.save() intent_list = Intent.objects(plugin=plugin) for oIntent in intent_list: oIntent.enabled = False oIntent.save() return {'status': 'success', 'log': 'Plugin disabled'} def uninstallPlugin(self, plugin_name=None, plugin_pk=None): if plugin_pk: plugin_list = Plugin.objects(pk=plugin_pk) else: plugin_list = Plugin.objects(name=plugin_name) if not plugin_list: return {'status': 'fail', 'log': 'Plugin not installed'} else: for plugin in plugin_list: pip.main(['uninstall', 'lisa-plugin-' + plugin_name]) plugin.delete() for cron in Cron.objects(plugin=plugin): cron.delete() for rule in Rule.objects(plugin=plugin): rule.delete() intent_list = Intent.objects(plugin=plugin) for oIntent in intent_list: oIntent.delete() return {'status': 'success', 'log': 'Plugin uninstalled'} def methodListPlugin(plugin_name=None): if plugin_name: plugin_list = Plugin.objects(name=plugin_name) else: plugin_list = Plugin.objects.all() listallmethods = [] for plugin in plugin_list: plugininstance = namedAny('.'.join(('lisa.plugins',str(plugin.name).lower(), 'modules', str(plugin.name).lower(), str(plugin.name))))() listpluginmethods = [] for m in inspect.getmembers(plugininstance, predicate=inspect.ismethod): if not "__init__" in m: listpluginmethods.append(m[0]) listallmethods.append({ 'plugin': plugin.name, 'methods': listpluginmethods}) for f in os.listdir(os.path.normpath(LISA_PATH + '/core')): fileName, fileExtension = os.path.splitext(f) if os.path.isfile(os.path.join(os.path.normpath(LISA_PATH + '/core'), f)) and not f.startswith('__init__') and fileExtension != '.pyc': coreinstance = namedAny('.'.join(('core', str(fileName).lower(), str(fileName).capitalize())))() listcoremethods = [] for m in inspect.getmembers(coreinstance, predicate=inspect.ismethod): #init shouldn't be listed in methods and _ is for translation if not "__init__" in m: listcoremethods.append(m[0]) listallmethods.append({ 'core': fileName, 'methods': listcoremethods}) log.msg(listallmethods) return listallmethods def _template_to_file(self, filename, template, context): import codecs codecs.open(filename, 'w', 'utf-8').write(render_to_string(template, context)) def createPlugin(self, plugin_name, author_name, author_email): import requests import pytz metareq = requests.get('/'.join([configuration['plugin_store'], 'plugins.json'])) if(metareq.ok): for item in json.loads(metareq.text or metareq.content): if item['name'].lower() == plugin_name.lower(): return {'status': 'fail', 'log': 'Plugin already exist in the store'} context = { 'plugin_name': plugin_name, 'plugin_name_lower': plugin_name.lower(), 'author_name': author_name, 'author_email': author_email, 'creation_date': pytz.UTC.localize(datetime.datetime.now()).strftime("%Y-%m-%d %H:%M%z") } os.mkdir(os.path.normpath(self.pkgpath + '/' + plugin_name)) # Lang stuff os.mkdir(os.path.normpath(self.pkgpath + '/' + plugin_name + '/lang')) os.mkdir(os.path.normpath(self.pkgpath + '/' + plugin_name + '/lang/en')) os.mkdir(os.path.normpath(self.pkgpath + '/' + plugin_name + '/lang/en/LC_MESSAGES')) self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/lang/en/LC_MESSAGES/' + plugin_name.lower() + '.po'), template='plugin/lang/en/LC_MESSAGES/module.po', context=context) # Module stuff os.mkdir(os.path.normpath(self.pkgpath + '/' + plugin_name + '/modules')) self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/modules/' + plugin_name.lower() + '.py'), template='plugin/modules/module.tpl', context=context) open(os.path.normpath(self.pkgpath + '/' + plugin_name + '/modules/__init__.py'), "a") # Web stuff os.mkdir(os.path.normpath(self.pkgpath + '/' + plugin_name + '/web')) os.mkdir(os.path.normpath(self.pkgpath + '/' + plugin_name + '/web/templates')) shutil.copy(src=os.path.normpath(LISA_PATH + '/web/manageplugins/templates/plugin/web/templates/widget.html'), dst=os.path.normpath(self.pkgpath + '/' + plugin_name + '/web/templates/widget.html')) shutil.copy(src=os.path.normpath(LISA_PATH + '/web/manageplugins/templates/plugin/web/templates/index.html'), dst=os.path.normpath(self.pkgpath + '/' + plugin_name + '/web/templates/index.html')) open(os.path.normpath(self.pkgpath + '/' + plugin_name + '/web/__init__.py'), "a") self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/web/api.py'), template='plugin/web/api.tpl', context=context) self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/web/models.py'), template='plugin/web/models.tpl', context=context) self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/web/tests.py'), template='plugin/web/tests.tpl', context=context) self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/web/urls.py'), template='plugin/web/urls.tpl', context=context) self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/web/views.py'), template='plugin/web/views.tpl', context=context) # Plugin stuff (metadata) self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/__init__.py'), template='plugin/__init__.tpl', context=context) self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/README.rst'), template='plugin/README.rst', context=context) self._template_to_file(filename=os.path.normpath(self.pkgpath + '/' + plugin_name + '/' + plugin_name.lower() + '.json'), template='plugin/module.json', context=context) return {'status': 'success', 'log': 'Plugin created'}