8d6ae11c6ee4b8febc384dca3e6ff35a55b3431f
[cascardo/ipsilon.git] / ipsilon / util / data.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 sqlite3
22 import cherrypy
23
24
25 class Store(object):
26
27     def __init__(self, path=None):
28         if path is None:
29             self._path = os.getcwd()
30         else:
31             self._path = path
32         self._admin_dbname = self._get_admin_dbname()
33         self._user_dbname = self._get_userprefs_dbname()
34
35     def _get_admin_dbname(self):
36         path = None
37         if 'admin.config.db' in cherrypy.config:
38             path = cherrypy.config['admin.config.db']
39         if not path:
40             path = os.path.join(self._path, 'adminconfig.sqlite')
41         return path
42
43     def _get_userprefs_dbname(self):
44         path = None
45         if 'user.prefs.db' in cherrypy.config:
46             path = cherrypy.config['user.prefs.db']
47         if not path:
48             path = os.path.join(self._path, 'userprefs.sqlite')
49         return path
50
51     def _load_config(self, dbname):
52         con = None
53         rows = []
54         try:
55             con = sqlite3.connect(dbname)
56             cur = con.cursor()
57             cur.executescript("""
58                 CREATE TABLE IF NOT EXISTS config(name TEXT, value TEXT)
59                 """)
60             cur.execute("SELECT * FROM config")
61             rows = cur.fetchall()
62             con.commit()
63         except sqlite3.Error, e:
64             if con:
65                 con.rollback()
66             cherrypy.log.error("Failed to load config: [%s]" % e)
67         finally:
68             if con:
69                 con.close()
70
71         conf = {}
72         for row in rows:
73             if row[0] in conf:
74                 # multivalued
75                 if conf[row[0]] is list:
76                     conf[row[0]].append(row[1])
77                 else:
78                     v = conf[row[0]]
79                     conf[row[0]] = [v, row[1]]
80             else:
81                 conf[row[0]] = row[1]
82
83         return conf
84
85     def get_admin_config(self):
86         return self._load_config(self._admin_dbname)
87
88     def _load_user_prefs(self, dbname, user):
89         con = None
90         rows = []
91         try:
92             con = sqlite3.connect(dbname)
93             cur = con.cursor()
94             cur.executescript("""
95                 CREATE TABLE IF NOT EXISTS users(name TEXT,
96                                                  option TEXT,
97                                                  value TEXT)
98                 """)
99             cur.execute("SELECT option, value FROM users "
100                         "where name = '%s'" % user)
101             rows = cur.fetchall()
102             con.commit()
103         except sqlite3.Error, e:
104             if con:
105                 con.rollback()
106             cherrypy.log.error("Failed to load %s's prefs from "
107                                "%s: [%s]" % (user, dbname, e))
108         finally:
109             if con:
110                 con.close()
111
112         conf = {}
113         for row in rows:
114             conf[row[0]] = row[1]
115
116         return conf
117
118     def get_user_preferences(self, user):
119         return self._load_user_prefs(self._user_dbname, user)
120
121     def get_plugins_config(self, facility):
122         con = None
123         rows = []
124         try:
125             con = sqlite3.connect(self._admin_dbname)
126             cur = con.cursor()
127             cur.execute("CREATE TABLE IF NOT EXISTS " +
128                         facility + " (name TEXT,option TEXT,value TEXT)")
129             cur.execute("SELECT * FROM " + facility)
130             rows = cur.fetchall()
131             con.commit()
132         except sqlite3.Error, e:
133             if con:
134                 con.rollback()
135             cherrypy.log.error("Failed to load %s config: [%s]" % (facility,
136                                                                    e))
137         finally:
138             if con:
139                 con.close()
140
141         lpo = []
142         plco = dict()
143         for row in rows:
144             if row[0] == 'global':
145                 if row[1] == 'order':
146                     lpo = row[2].split(',')
147                 continue
148             if row[0] not in plco:
149                 # one dict per provider
150                 plco[row[0]] = dict()
151
152             conf = plco[row[0]]
153             if row[1] in conf:
154                 if conf[row[1]] is list:
155                     conf[row[1]].append(row[2])
156                 else:
157                     v = conf[row[1]]
158                     conf[row[1]] = [v, row[2]]
159             else:
160                 conf[row[1]] = row[2]
161
162         return (lpo, plco)
163
164     def get_plugin_config(self, facility, plugin):
165         con = None
166         rows = []
167         try:
168             con = sqlite3.connect(self._admin_dbname)
169             cur = con.cursor()
170             cur.execute("CREATE TABLE IF NOT EXISTS " +
171                         facility + " (name TEXT,option TEXT,value TEXT)")
172             cur.execute("SELECT option, value FROM " +
173                         facility + " WHERE name=?", (plugin,))
174             rows = cur.fetchall()
175             con.commit()
176         except sqlite3.Error, e:
177             if con:
178                 con.rollback()
179             fpe = (facility, plugin, e)
180             cherrypy.log.error("Failed to get %s/%s config: [%s]" % fpe)
181             raise
182         finally:
183             if con:
184                 con.close()
185
186         res = dict()
187         for (option, value) in rows:
188             if option in res:
189                 if res[option] is list:
190                     res[option].append(value)
191                 else:
192                     v = res[option]
193                     res[option] = [v, value]
194             else:
195                 res[option] = value
196
197         return res
198
199     def save_plugin_config(self, facility, plugin, options):
200         SELECT = "SELECT option, value FROM %s WHERE name=?" % facility
201         UPDATE = "UPDATE %s SET value=? WHERE name=? AND option=?" % facility
202         INSERT = "INSERT INTO %s VALUES(?,?,?)" % facility
203         con = None
204         try:
205             con = sqlite3.connect(self._admin_dbname)
206             cur = con.cursor()
207             cur.execute("CREATE TABLE IF NOT EXISTS " +
208                         facility + " (name TEXT,option TEXT,value TEXT)")
209             curvals = dict()
210             for row in cur.execute(SELECT, (plugin,)):
211                 curvals[row[0]] = row[1]
212
213             for name in options:
214                 if name in curvals:
215                     cur.execute(UPDATE, (options[name], plugin, name))
216                 else:
217                     cur.execute(INSERT, (plugin, name, options[name]))
218
219             con.commit()
220         except sqlite3.Error, e:
221             if con:
222                 con.rollback()
223             cherrypy.log.error("Failed to store config: [%s]" % e)
224             raise
225         finally:
226             if con:
227                 con.close()
228
229     def wipe_plugin_config(self, facility, plugin):
230         # Try to backup old data first, just in case ?
231         try:
232             con = sqlite3.connect(self._admin_dbname)
233             cur = con.cursor()
234             cur.execute("CREATE TABLE IF NOT EXISTS " +
235                         facility + " (name TEXT,option TEXT,value TEXT)")
236             cur.execute("DELETE FROM " + facility + " WHERE name=?",
237                         (plugin,))
238             con.commit()
239         except sqlite3.Error, e:
240             if con:
241                 con.rollback()
242             cherrypy.log.error("Failed to wipe %s config: [%s]" % (plugin, e))
243             raise
244         finally:
245             if con:
246                 con.close()
247
248     def get_data(self, plugin, idval=None, name=None, value=None):
249         con = None
250         rows = []
251         names = None
252         values = ()
253         if idval or name or value:
254             names = ""
255             if idval:
256                 names += " id=?"
257                 values = values + (idval,)
258             if name:
259                 if len(names) != 0:
260                     names += " AND"
261                 names += " name=?"
262                 values = values + (name,)
263             if value:
264                 if len(names) != 0:
265                     names += " AND"
266                 names += " value=?"
267                 values = values + (value,)
268         try:
269             con = sqlite3.connect(self._admin_dbname)
270             cur = con.cursor()
271             cur.execute("CREATE TABLE IF NOT EXISTS " +
272                         plugin + "_data (id INTEGER, name TEXT, value TEXT)")
273             if not names:
274                 cur.execute("SELECT * FROM " + plugin + "_data")
275             else:
276                 cur.execute("SELECT * FROM " + plugin + "_data WHERE" +
277                             names, values)
278             rows = cur.fetchall()
279             con.commit()
280         except sqlite3.Error, e:
281             if con:
282                 con.rollback()
283             cherrypy.log.error("Failed to load %s data: [%s]" % (plugin, e))
284             cherrypy.log.error(repr([names, values]))
285         finally:
286             if con:
287                 con.close()
288
289         data = dict()
290         for row in rows:
291             if row[0] not in data:
292                 data[row[0]] = dict()
293
294             item = data[row[0]]
295             if row[1] in item:
296                 if item[row[1]] is list:
297                     item[row[1]].append(row[2])
298                 else:
299                     v = item[row[1]]
300                     item[row[1]] = [v, row[2]]
301             else:
302                 item[row[1]] = row[2]
303
304         return data
305
306     def save_data(self, plugin, data):
307         SELECT = "SELECT name, value FROM %s_data WHERE id=?" % plugin
308         UPDATE = "UPDATE %s_data SET value=? WHERE id=? AND name=?" % plugin
309         INSERT = "INSERT INTO %s_data VALUES(?,?,?)" % plugin
310         con = None
311         try:
312             con = sqlite3.connect(self._admin_dbname)
313             cur = con.cursor()
314             for idval in data:
315                 curvals = dict()
316                 for row in cur.execute(SELECT, (idval,)):
317                     curvals[row[0]] = row[1]
318
319                 datum = data[idval]
320                 for name in datum:
321                     if name in curvals:
322                         cur.execute(UPDATE, (datum[name], idval, name))
323                     else:
324                         cur.execute(INSERT, (idval, name, datum[name]))
325
326             con.commit()
327         except sqlite3.Error, e:
328             if con:
329                 con.rollback()
330             cherrypy.log.error("Failed to store %s data: [%s]" % (plugin, e))
331             raise
332         finally:
333             if con:
334                 con.close()
335
336     def wipe_data(self, plugin):
337         # Try to backup old data first, just in case
338         try:
339             con = sqlite3.connect(self._admin_dbname)
340             cur = con.cursor()
341             cur.execute("DROP TABLE IF EXISTS " + plugin + "_data")
342             cur.execute("CREATE TABLE " + plugin + "_data"
343                         "(id INTEGER, name TEXT, value TEXT)")
344             con.commit()
345         except sqlite3.Error, e:
346             if con:
347                 con.rollback()
348             cherrypy.log.error("Failed to wipe %s data: [%s]" % (plugin, e))
349             raise
350         finally:
351             if con:
352                 con.close()