Refactor plugin configuration
[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.config import Config
25 from ipsilon.util.data import AdminStore
26 from ipsilon.util.log import Log
27
28
29 class Plugins(object):
30
31     def __init__(self):
32         self._providers_tree = None
33
34     def _load_class(self, tree, class_type, file_name):
35         cherrypy.log.error('Check module %s for class %s' % (file_name,
36                                                              class_type))
37         name, ext = os.path.splitext(os.path.split(file_name)[-1])
38         try:
39             if ext.lower() == '.py':
40                 mod = imp.load_source(name, file_name)
41             # elif ext.lower() == '.pyc':
42             #    mod = imp.load_compiled(name, file_name)
43             else:
44                 return
45         except Exception, e:  # pylint: disable=broad-except
46             cherrypy.log.error('Failed to load "%s" module: [%s]' % (name, e))
47             return
48
49         if hasattr(mod, class_type):
50             instance = getattr(mod, class_type)()
51             public_name = getattr(instance, 'name', name)
52             tree[public_name] = instance
53             cherrypy.log.error('Added module %s as %s' % (name, public_name))
54
55     def _load_classes(self, tree, path, class_type):
56         files = None
57         try:
58             files = os.listdir(path)
59         except Exception, e:  # pylint: disable=broad-except
60             cherrypy.log.error('No modules in %s: [%s]' % (path, e))
61             return
62
63         for name in files:
64             filename = os.path.join(path, name)
65             self._load_class(tree, class_type, filename)
66
67     def get_plugins(self, path, class_type):
68         plugins = dict()
69         self._load_classes(plugins, path, class_type)
70         return plugins
71
72
73 class PluginLoader(object):
74
75     def __init__(self, baseobj, facility, plugin_type):
76         config = AdminStore().load_options(facility)
77         cherrypy.log('LOAD: %s\n' % repr(config))
78         whitelist = []
79         if 'global' in config:
80             sec = config['global']
81             if 'order' in sec:
82                 whitelist = sec['order'].split(',')
83         if cherrypy.config.get('debug', False):
84             cherrypy.log('[%s] %s: %s' % (facility, whitelist, config))
85         if config is None:
86             config = dict()
87
88         p = Plugins()
89         (pathname, dummy) = os.path.split(inspect.getfile(baseobj))
90         self._plugins = {
91             'config': config,
92             'available': p.get_plugins(pathname, plugin_type),
93             'whitelist': whitelist,
94             'enabled': []
95         }
96
97     def get_plugin_data(self):
98         return self._plugins
99
100
101 class PluginInstaller(object):
102     def __init__(self, baseobj):
103         (pathname, dummy) = os.path.split(inspect.getfile(baseobj))
104         self._pathname = pathname
105
106     def get_plugins(self):
107         p = Plugins()
108         return p.get_plugins(self._pathname, 'Installer')
109
110
111 class PluginObject(Log):
112
113     def __init__(self):
114         self.name = None
115         self._config = None
116         self._data = AdminStore()
117
118     def import_config(self, config):
119         self._config = config
120
121     def export_config(self):
122         return self._config
123
124     def get_plugin_config(self, facility):
125         return self._data.load_options(facility, self.name)
126
127     def refresh_plugin_config(self, facility):
128         config = self.get_plugin_config(facility)
129         self.import_config(config)
130
131     def save_plugin_config(self, facility, config=None):
132         if config is None:
133             config = self.export_config()
134
135         self._data.save_options(facility, self.name, config)
136
137     def get_data(self, idval=None, name=None, value=None):
138         return self._data.get_data(self.name, idval=idval, name=name,
139                                    value=value)
140
141     def save_data(self, data):
142         self._data.save_data(self.name, data)
143
144     def new_datum(self, datum):
145         self._data.new_datum(self.name, datum)
146
147     def del_datum(self, idval):
148         self._data.del_datum(self.name, idval)
149
150     def wipe_config_values(self, facility):
151         self._data.delete_options(facility, self.name, None)
152
153     def wipe_data(self):
154         self._data.wipe_data(self.name)
155
156
157 class PluginConfig(Log):
158
159     def __init__(self):
160         self._config = None
161
162     def new_config(self, name, *config_args):
163         self._config = Config(name, *config_args)
164
165     def get_config_obj(self):
166         if self._config is None:
167             raise AttributeError('Config not initialized')
168         return self._config
169
170     def import_config(self, config):
171         if not self._config:
172             raise AttributeError('Config not initialized, cannot import')
173
174         for key, value in config.iteritems():
175             if key in self._config:
176                 self._config[key].import_value(str(value))
177
178     def export_config(self):
179         config = dict()
180         for name, option in self._config.iteritems():
181             config[name] = option.export_value()
182         return config
183
184     def get_config_value(self, name):
185         if not self._config:
186             raise AttributeError('Config not initialized')
187         return self._config[name].get_value()
188
189     def set_config_value(self, name, value):
190         if not self._config:
191             raise AttributeError('Config not initialized')
192         return self._config[name].set_value(value)