リビジョン | a5c9e9d8c4115681e36af9f15b0b41f6a6b921d5 (tree) |
---|---|
日時 | 2009-06-16 14:56:12 |
作者 | Kei Funagayama <kei@kare...> |
コミッター | Kei Funagayama |
add Database copy command.
@@ -0,0 +1,209 @@ | ||
1 | +#!/usr/bin/env python | |
2 | +# -*- coding: utf-8 -*- | |
3 | +# | |
4 | +# This file is part of Pysilhouette. | |
5 | +# | |
6 | +# Copyright (c) 2009 HDE, Inc. | |
7 | +# | |
8 | +# Permission is hereby granted, free of charge, to any person obtaining a copy | |
9 | +# of this software and associated documentation files (the "Software"), to deal | |
10 | +# in the Software without restriction, including without limitation the rights | |
11 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
12 | +# copies of the Software, and to permit persons to whom the Software is | |
13 | +# furnished to do so, subject to the following conditions: | |
14 | +# | |
15 | +# The above copyright notice and this permission notice shall be included in | |
16 | +# all copies or substantial portions of the Software. | |
17 | +# | |
18 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
19 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
20 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
21 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
22 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
23 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
24 | +# THE SOFTWARE. | |
25 | +# | |
26 | + | |
27 | +""" | |
28 | +@author: Kei Funagayama <kei@karesansui-project.info> | |
29 | + | |
30 | + | |
31 | +Database copy command. | |
32 | + | |
33 | +example postgres) | |
34 | + python sqlite2other.py --input=sqlite:////var/opt/pysilhouette/pysilhouette.db --output=postgres://username:password@hostname:port/database | |
35 | + | |
36 | +example mysql) | |
37 | + python sqlite2other.py --input=sqlite:////var/opt/pysilhouette/pysilhouette.db --output=mysql://username:password@hostname/database?charset=utf8 | |
38 | + | |
39 | +""" | |
40 | + | |
41 | +import sys | |
42 | +import os | |
43 | +import logging | |
44 | + | |
45 | +from optparse import OptionParser, OptionValueError | |
46 | + | |
47 | +try: | |
48 | + import sqlalchemy | |
49 | + import pysilhouette | |
50 | +except ImportError, e: | |
51 | + print >>sys.stderr, "".join(e.args) | |
52 | + sys.exit(1) | |
53 | + | |
54 | +import warnings | |
55 | +from sqlalchemy.exc import SADeprecationWarning | |
56 | +#warnings.filterwarnings('ignore', category=SADeprecationWarning) | |
57 | +#warnings.filterwarnings('ignore', category=UserWarning) | |
58 | +warnings.filterwarnings("ignore", "", Warning, "", 0) | |
59 | + | |
60 | + | |
61 | +from pysilhouette.prep import getopts, readconf, chkopts | |
62 | +from pysilhouette.db import Database, reload_mappers | |
63 | +from pysilhouette.db.model import JobGroup, Job | |
64 | + | |
65 | +usage = "%prog [options]" | |
66 | +version = "%prog 0.1" | |
67 | + | |
68 | +DEBUG = False | |
69 | +DATABASE_MODULES = { | |
70 | + "ibase":["kinterbasdb"], | |
71 | + "maxdb":["sapdb"], | |
72 | + "mysql":["MySQLdb"], | |
73 | + "oracle":["cx_Oracle"], | |
74 | + "postgres":["psycopg2"], | |
75 | + "sqlite":["pysqlite2","sqlite3"], | |
76 | +} | |
77 | + | |
78 | +def is_connect(url): | |
79 | + try: | |
80 | + from sqlalchemy import create_engine | |
81 | + from sqlalchemy.exc import OperationalError | |
82 | + engine = create_engine(url, echo=False, convert_unicode=True) | |
83 | + connection = engine.connect() | |
84 | + connection.close() | |
85 | + return True | |
86 | + except Exception, e: | |
87 | + print >>sys.stderr, "[Error] connection refused - %s" % str(e.args) | |
88 | + return False | |
89 | + | |
90 | +def getopts(): | |
91 | + optp = OptionParser(usage=usage, version=version) | |
92 | + # http://www.sqlalchemy.org/docs/05/dbengine.html?highlight=rfc#create-engine-url-arguments | |
93 | + optp.add_option('-i', '--input', dest='input', help='Original database. bind-url. RFC-1738') | |
94 | + optp.add_option('-o', '--output', dest='output', help='Copy, bind-url. RFC-1738') | |
95 | + | |
96 | + return optp.parse_args() | |
97 | + | |
98 | +def chkopts(opts): | |
99 | + if not opts.input: | |
100 | + print >>sys.stderr, "sqlite2other: --input or -i is required." | |
101 | + return True | |
102 | + else: | |
103 | + if is_connect(opts.input) is False: | |
104 | + print >>sys.stderr, \ | |
105 | + "sqlite2other:bind-url \"--input\" is invalid. - input=%s" % opts.input | |
106 | + return True | |
107 | + | |
108 | + if not opts.output: | |
109 | + print >>sys.stderr, "sqlite2other: --output or -o is required." | |
110 | + return True | |
111 | + else: | |
112 | + if is_connect(opts.output) is False: | |
113 | + print >>sys.stderr, \ | |
114 | + "sqlite2other:bind-url \"--output\" is invalid. - output=%s" % opts.output | |
115 | + return True | |
116 | + | |
117 | + return False | |
118 | + | |
119 | +def main(): | |
120 | + (opts, args) = getopts() | |
121 | + if chkopts(opts) is True: | |
122 | + return 1 | |
123 | + | |
124 | + try: | |
125 | + input_db = Database(opts.input, | |
126 | + encoding="utf-8", | |
127 | + convert_unicode=True, | |
128 | + assert_unicode=DEBUG, | |
129 | + echo=DEBUG, | |
130 | + echo_pool=DEBUG | |
131 | + ) | |
132 | + | |
133 | + reload_mappers(input_db.get_metadata()) | |
134 | + | |
135 | + output_db = Database(opts.output, | |
136 | + encoding="utf-8", | |
137 | + convert_unicode=True, | |
138 | + assert_unicode=DEBUG, | |
139 | + echo=DEBUG, | |
140 | + echo_pool=DEBUG | |
141 | + ) | |
142 | + | |
143 | + reload_mappers(output_db.get_metadata()) | |
144 | + | |
145 | + except Exception, e: | |
146 | + print >>sys.stderr, 'Initializing a database error' | |
147 | + raise | |
148 | + | |
149 | + try: | |
150 | + input_session = input_db.get_session() | |
151 | + jobgroups= input_session.query(JobGroup).all() | |
152 | + except: | |
153 | + raise | |
154 | + | |
155 | + output_jobgroups = [] | |
156 | + for j in jobgroups: | |
157 | + _jobgroup = JobGroup(j.name, j.uniq_key) | |
158 | + _jobgroup.id = j.id | |
159 | + #_jobgroup.name = j.name | |
160 | + #_jobgroup.uniq_key = j.uniq_key | |
161 | + _jobgroup.finish_command = j.finish_command | |
162 | + _jobgroup.status = j.status | |
163 | + _jobgroup.register = j.register | |
164 | + _jobgroup.created = j.created | |
165 | + _jobgroup.modified = j.modified | |
166 | + for job in j.jobs: | |
167 | + _job = Job(job.name, job.order, job.action_command) | |
168 | + _job.id = job.id | |
169 | + _job.jobgroup_id = job.jobgroup_id | |
170 | + #_job.name = job.name | |
171 | + #_job.order = job.order | |
172 | + #_job.action_command = job.action_command | |
173 | + _job.rollback_command = job.rollback_command | |
174 | + _job.status = job.status | |
175 | + _job.action_exit_code = job.action_exit_code | |
176 | + _job.action_stdout = job.action_stdout | |
177 | + _job.action_stderr = job.action_stderr | |
178 | + _job.rollback_exit_code = job.rollback_exit_code | |
179 | + _job.rollback_stdout = job.rollback_stdout | |
180 | + _job.rollback_stderr = job.rollback_stderr | |
181 | + _job.progress = job.progress | |
182 | + _job.created = job.created | |
183 | + _job.modified = job.modified | |
184 | + ## | |
185 | + _jobgroup.jobs.append(_job) | |
186 | + | |
187 | + ## | |
188 | + output_jobgroups.append(_jobgroup) | |
189 | + | |
190 | + try: | |
191 | + output_db.get_metadata().drop_all() | |
192 | + output_db.get_metadata().create_all() | |
193 | + print >>sys.stdout, 'Cleanup Database [OK]' | |
194 | + output_session = output_db.get_session() | |
195 | + for j in output_jobgroups: | |
196 | + #import pdb; pdb.set_trace() | |
197 | + output_session.save(j) | |
198 | + output_session.commit() | |
199 | + print >>sys.stderr, 'copy num - %d' % len(output_jobgroups) | |
200 | + | |
201 | + except Exception,e: | |
202 | + print >>sys.stderr, 'database drop and create error.' | |
203 | + raise | |
204 | + | |
205 | + | |
206 | + return 0 | |
207 | + | |
208 | +if __name__ == '__main__': | |
209 | + sys.exit(main()) |