9222a3541536adfc9b9f3d11a02bea99f0ee7528
[cascardo/ipsilon.git] / ipsilon / util / plugin.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2013  Simo Sorce <simo@redhat.com>
4 #
5 # see file 'COPYING' for use and warranty information
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 import os
21 import imp
22 import cherrypy
23 import inspect
24 from ipsilon.util.data import AdminStore
25 from ipsilon.util.log import Log
26
27
28 class Plugins(object):
29
30     def __init__(self):
31         self._providers_tree = None
32
33     def _load_class(self, tree, class_type, file_name):
34         cherrypy.log.error('Check module %s for class %s' % (file_name,
35                                                              class_type))
36         name, ext = os.path.splitext(os.path.split(file_name)[-1])
37         try:
38             if ext.lower() == '.py':
39                 mod = imp.load_source(name, file_name)
40             # elif ext.lower() == '.pyc':
41             #    mod = imp.load_compiled(name, file_name)
42             else:
43                 return
44         except Exception, e:  # pylint: disable=broad-except
45             cherrypy.log.error('Failed to load "%s" module: [%s]' % (name, e))
46             return
47
48         if hasattr(mod, class_type):
49             instance = getattr(mod, class_type)()
50             public_name = getattr(instance, 'name', name)
51             tree[public_name] = instance
52             cherrypy.log.error('Added module %s as %s' % (name, public_name))
53
54     def _load_classes(self, tree, path, class_type):
55         files = None
56         try:
57             files = os.listdir(path)
58         except Exception, e:  # pylint: disable=broad-except
59             cherrypy.log.error('No modules in %s: [%s]' % (path, e))
60             return
61
62         for name in files:
63             filename = os.path.join(path, name)
64             self._load_class(tree, class_type, filename)
65
66     def get_plugins(self, path, class_type):
67         plugins = dict()
68         self._load_classes(plugins, path, class_type)
69         return plugins
70
71
72 class PluginLoader(object):
73
74     def __init__(self, baseobj, facility, plugin_type):
75         config = AdminStore().load_options(facility)
76         cherrypy.log('LOAD: %s\n' % repr(config))
77         whitelist = []
78         if 'global' in config:
79             sec = config['global']
80             if 'order' in sec:
81                 whitelist = sec['order'].split(',')
82         if cherrypy.config.get('debug', False):
83             cherrypy.log('[%s] %s: %s' % (facility, whitelist, config))
84         if config is None:
85             config = dict()
86
87         p = Plugins()
88         (pathname, dummy) = os.path.split(inspect.getfile(baseobj))
89         self._plugins = {
90             'config': config,
91             'available': p.get_plugins(pathname, plugin_type),
92             'whitelist': whitelist,
93             'enabled': []
94         }
95
96     def get_plugin_data(self):
97         return self._plugins
98
99
100 class PluginInstaller(object):
101     def __init__(self, baseobj):
102         (pathname, dummy) = os.path.split(inspect.getfile(baseobj))
103         self._pathname = pathname
104
105     def get_plugins(self):
106         p = Plugins()
107         return p.get_plugins(self._pathname, 'Installer')
108
109
110 class PluginObject(Log):
111
112     def __init__(self):
113         self.name = None
114         self._config = None
115         self._options = None
116         self._data = AdminStore()
117
118     def get_config_desc(self, name=None):
119         """ The configuration description is a dictionary that provides
120             A description of the supported configuration options, as well
121             as the default configuration option values.
122             The key is the option name, the value is an array of 3 elements:
123              - description
124              - option type
125              - default value
126         """
127         if name is None:
128             return self._options
129
130         opt = self._options.get(name, None)
131         if opt is None:
132             return ''
133         return opt[0]
134
135     def _value_to_list(self, name):
136         if name not in self._config:
137             return
138         value = self._config[name]
139         if type(value) is list:
140             return
141         vlist = [x.strip() for x in value.split(',')]
142         self._config[name] = vlist
143
144     def set_config(self, config):
145         self._config = config
146         if self._config is None:
147             return
148         if self._options:
149             for name, opt in self._options.iteritems():
150                 if opt[1] == 'list':
151                     self._value_to_list(name)
152
153     def get_config_value(self, name):
154         value = None
155         if self._config:
156             value = self._config.get(name, None)
157         if not value:
158             if self._options:
159                 opt = self._options.get(name, None)
160                 if opt:
161                     value = opt[2]
162
163         if cherrypy.config.get('debug', False):
164             cherrypy.log('[%s] %s: %s' % (self.name, name, value))
165
166         return value
167
168     def set_config_value(self, option, value):
169         if not self._config:
170             self._config = dict()
171         self._config[option] = value
172         if self._options and option in self._options:
173             if self._options[option][1] == 'list':
174                 self._value_to_list(option)
175
176     def get_plugin_config(self, facility):
177         return self._data.load_options(facility, self.name)
178
179     def refresh_plugin_config(self, facility):
180         config = self.get_plugin_config(facility)
181         self.set_config(config)
182
183     def save_plugin_config(self, facility, config=None):
184         if config is None:
185             config = self._config
186         config = config.copy()
187
188         for key, value in config.items():
189             if type(value) is list:
190                 config[key] = ','.join(value)
191
192         self._data.save_options(facility, self.name, config)
193
194     def get_data(self, idval=None, name=None, value=None):
195         return self._data.get_data(self.name, idval=idval, name=name,
196                                    value=value)
197
198     def save_data(self, data):
199         self._data.save_data(self.name, data)
200
201     def new_datum(self, datum):
202         self._data.new_datum(self.name, datum)
203
204     def del_datum(self, idval):
205         self._data.del_datum(self.name, idval)
206
207     def wipe_config_values(self, facility):
208         self._data.delete_options(facility, self.name, None)
209
210     def wipe_data(self):
211         self._data.wipe_data(self.name)