2a55bb2ac64fcb567fbc835553023012073f968a
[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 save_plugin_config(self, facility, plugin, options):
165         SELECT = "SELECT option, value FROM %s WHERE name=?" % facility
166         UPDATE = "UPDATE %s SET value=? WHERE name=? AND option=?" % facility
167         INSERT = "INSERT INTO %s VALUES(?,?,?)" % facility
168         con = None
169         try:
170             con = sqlite3.connect(self._admin_dbname)
171             cur = con.cursor()
172             curvals = dict()
173             for row in cur.execute(SELECT, (plugin,)):
174                 curvals[row[0]] = row[1]
175
176             for name in options:
177                 if name in curvals:
178                     cur.execute(UPDATE, (options[name], plugin, name))
179                 else:
180                     cur.execute(INSERT, (plugin, name, options[name]))
181
182             con.commit()
183         except sqlite3.Error, e:
184             if con:
185                 con.rollback()
186             cherrypy.log.error("Failed to store config: [%s]" % e)
187             raise
188         finally:
189             if con:
190                 con.close()
191
192     def get_data(self, plugin, idval=None, name=None, value=None):
193         con = None
194         rows = []
195         names = None
196         values = ()
197         if idval or name or value:
198             names = ""
199             if idval:
200                 names += " id=?"
201                 values = values + (idval,)
202             if name:
203                 if len(names) != 0:
204                     names += " AND"
205                 names += " name=?"
206                 values = values + (name,)
207             if value:
208                 if len(names) != 0:
209                     names += " AND"
210                 names += " value=?"
211                 values = values + (value,)
212         try:
213             con = sqlite3.connect(self._admin_dbname)
214             cur = con.cursor()
215             cur.execute("CREATE TABLE IF NOT EXISTS " +
216                         plugin + "_data (id INTEGER, name TEXT, value TEXT)")
217             if not names:
218                 cur.execute("SELECT * FROM " + plugin + "_data")
219             else:
220                 cur.execute("SELECT * FROM " + plugin + "_data WHERE" +
221                             names, values)
222             rows = cur.fetchall()
223             con.commit()
224         except sqlite3.Error, e:
225             if con:
226                 con.rollback()
227             cherrypy.log.error("Failed to load %s data: [%s]" % (plugin, e))
228             cherrypy.log.error(repr([names, values]))
229         finally:
230             if con:
231                 con.close()
232
233         data = dict()
234         for row in rows:
235             if row[0] not in data:
236                 data[row[0]] = dict()
237
238             item = data[row[0]]
239             if row[1] in item:
240                 if item[row[1]] is list:
241                     item[row[1]].append(row[2])
242                 else:
243                     v = item[row[1]]
244                     item[row[1]] = [v, row[2]]
245             else:
246                 item[row[1]] = row[2]
247
248         return data
249
250     def save_data(self, plugin, data):
251         SELECT = "SELECT name, value FROM %s_data WHERE id=?" % plugin
252         UPDATE = "UPDATE %s_data SET value=? WHERE id=? AND name=?" % plugin
253         INSERT = "INSERT INTO %s_data VALUES(?,?,?)" % plugin
254         con = None
255         try:
256             con = sqlite3.connect(self._admin_dbname)
257             cur = con.cursor()
258             for idval in data:
259                 curvals = dict()
260                 for row in cur.execute(SELECT, (idval,)):
261                     curvals[row[0]] = row[1]
262
263                 datum = data[idval]
264                 for name in datum:
265                     if name in curvals:
266                         cur.execute(UPDATE, (datum[name], idval, name))
267                     else:
268                         cur.execute(INSERT, (idval, name, datum[name]))
269
270             con.commit()
271         except sqlite3.Error, e:
272             if con:
273                 con.rollback()
274             cherrypy.log.error("Failed to store %s data: [%s]" % (plugin, e))
275             raise
276         finally:
277             if con:
278                 con.close()