root / pykota / trunk / initscripts / postgresql / upgrade-from-before-1.03.py @ 2890

Revision 2622, 6.9 kB (checked in by jerome, 19 years ago)

Added 2006 to the copyright's years.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2
3# PyKota Print Quota Warning sender
4#
5# PyKota - Print Quotas for CUPS and LPRng
6#
7# (c) 2003, 2004, 2005, 2006 Jerome Alet <alet@librelogiciel.com>
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21#
22# $Id$
23#
24# THIS IS AN UPGRADE SCRIPT FOR OLD PYKOTA DATABASES TO THE 1.03 VERSION
25#
26
27import sys
28import os
29try :
30    import pg
31except ImportError :   
32    sys.stderr.write("The PyGreSQL Python module doesn't seem to be available. ABORTED.\n")
33    sys.exit(-1)
34
35def dump_old_database() :
36    """Dumps the existing PyKota database to a file, to avoir loosing data.
37   
38       Returns 1 if dump is successfull, 0 if it isn't.
39    """   
40    pipeinput = os.popen("pg_dump -C -D -N -U postgres -f pykota-dump.sql pykota")
41    dummy = pipeinput.read()
42    return (pipeinput.close() is None) or 0
43
44def create_new_database() :
45    """Creates the empty database."""
46    pipeinput = os.popen("psql -U postgres template1 <pykota-postgresql.sql")
47    dummy = pipeinput.read()
48    return (pipeinput.close() is None) or 0
49   
50def restore_original_database() :
51    """Creates the empty database."""
52    pipeinput = os.popen("psql -U postgres template1 <pykota-dump.sql")
53    dummy = pipeinput.read()
54    return (pipeinput.close() is None) or 0
55   
56def open_database(dbname="pykota") :
57    """Returns the database object or None if we can't connect to it."""
58    try :
59        pykotadb = pg.connect(host="localhost", port=5432, dbname=dbname, user="postgres")
60    except pg.error, msg :     
61        sys.stderr.write("%s\n" % msg)
62        sys.stderr.write("Unable to connect to the local PostgreSQL server.\nPlease modify the open_database() method in %s\nto connect to the correct PostgreSQL server\nand relaunch the script.\n" % sys.argv[0])
63        return 
64    else :   
65        return pykotadb
66       
67       
68def doQuote(field) :
69    """Quotes a field for use as a string in SQL queries."""
70    if type(field) == type(0) : # TODO : do something safer
71        typ = "decimal"
72    else :   
73        typ = "text"
74    return pg._quote(field, typ)
75       
76def main() :
77    """Does the work."""
78   
79    # First we make a dump of the old database
80    print "Dumping old database for safety...",
81    if not dump_old_database() :
82        sys.stderr.write("Error while dumping old database. ABORTED.\n")
83        return -1
84    print "Done."
85       
86    # Second we try to connect to it   
87    print "Extracting datas from old database...", 
88    db = open_database()
89    if db is None :
90        sys.stderr.write("Impossible to connect to old PyKota database. ABORTED.\nAre you sure you are upgrading an existing installation ?\n")
91        return -1
92   
93    # Third we extract datas
94    oldprinters = db.query("SELECT * FROM printers ORDER BY id;")
95    oldusers = db.query("SELECT * FROM users ORDER BY id;")
96    oldquotas = db.query("SELECT * FROM userpquota ORDER BY printerid, userid;")
97   
98    # Fourth close the database
99    db.close()
100    print "Done."
101   
102    # Fifth we delete the old database !
103    answer = raw_input("The old database will be deleted for the upgrade to take place.\nAre you sure you want to continue (y/N) ? ")
104    if answer[0:1].upper() != 'Y' :
105        sys.stderr.write("User wants to stop now ! ABORTED.\n")
106        return -1
107    db = open_database("template1")
108    if db is None :
109        sys.stderr.write("Impossible to connect to database template1. ABORTED.\nPlease report to your Database administrator.\n")
110        return -1
111    try :
112        db.query("DROP DATABASE pykota;")
113    except pg.error, msg :
114        sys.stderr.write("Impossible to delete old database. ABORTED.\n%s\n" % msg)
115        db.close()
116        return -1
117    else :   
118        db.close()
119       
120    # Sixth we create the new database
121    print "Creating the new database...",
122    if not create_new_database() :
123        sys.stderr.write("impossible to create new database ! ABORTED.\n")
124        return -1
125    print "Done."
126   
127    # Seventh we restore old data
128    print "Restoring old datas..."
129    db = open_database()
130    if db is None :
131        sys.stderr.write("Impossible to connect to new PyKota database. ABORTED.\nOld database will be restored if possible.")
132        print "An error occured, I'll try to restore the original database..."
133        if not restore_original_database() :
134            sys.stderr.write("Shit ! A double-error occured !!!\nPlease report problem to your database administrator.\n")
135            sys.stderr.write("And file a bug report to alet@librelogiciel.com\n")
136        else :   
137            print "Done."
138        return -1
139    db.query("BEGIN;")   
140    try :
141        newprinters = {}
142        for oldprinter in oldprinters.dictresult() :
143            db.query("INSERT INTO printers (printername) VALUES (%s);" % doQuote(oldprinter["printername"]))
144            newid = db.query("SELECT id FROM printers WHERE printername='%s';" % oldprinter["printername"]).dictresult()[0]["id"]
145            newprinters[oldprinter["id"]] = newid
146        newusers = {}   
147        for olduser in oldusers.dictresult() :   
148            db.query("INSERT INTO users (username) VALUES (%s);" % doQuote(olduser["username"]))
149            newid = db.query("SELECT id FROM users WHERE username='%s';" % olduser["username"]).dictresult()[0]["id"]
150            newusers[olduser["id"]] = newid
151        for oldquota in oldquotas.dictresult() :   
152            db.query("INSERT INTO userpquota (userid, printerid, pagecounter, lifepagecounter, softlimit, hardlimit, datelimit) VALUES (%s, %s, %s, %s, %s, %s, %s);" % 
153                                              (doQuote(newusers[oldquota["userid"]]) , doQuote(newprinters[oldquota["printerid"]]), doQuote(oldquota["pagecounter"]), doQuote(oldquota["lifepagecounter"]), doQuote(oldquota["softlimit"]), doQuote(oldquota["hardlimit"]), doQuote(oldquota["datelimit"])))
154    except pg.error, msg :   
155        sys.stderr.write("ERROR : %s\nABORTED.\n" % msg)
156        db.query("ROLLBACK;")
157        db.close()   
158        return -1
159    except :   
160        sys.stderr.write("Unknown error ! ABORTED.\n")
161        db.query("ROLLBACK;")
162        db.close()   
163        return -1
164    else :   
165        db.query("COMMIT;")
166        db.close()
167    print "Done."
168    print "NB : Last job on each printer was lost. This is normal !"
169    return 0
170   
171if __name__ == "__main__" :
172    sys.exit(main())
Note: See TracBrowser for help on using the browser.