##// END OF EJS Templates
db migrations:...
marcink -
r838:12eb1a01 beta
parent child Browse files
Show More
@@ -1,382 +1,402 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.db_manage
4 4 ~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 Database creation, and setup module for RhodeCode
6 Database creation, and setup module for RhodeCode. Used for creation
7 of database as well as for migration operations
7 8
8 9 :created_on: Apr 10, 2010
9 10 :author: marcink
10 11 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
11 12 :license: GPLv3, see COPYING for more details.
12 13 """
13 14 # This program is free software; you can redistribute it and/or
14 15 # modify it under the terms of the GNU General Public License
15 16 # as published by the Free Software Foundation; version 2
16 17 # of the License or (at your opinion) any later version of the license.
17 18 #
18 19 # This program is distributed in the hope that it will be useful,
19 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 22 # GNU General Public License for more details.
22 23 #
23 24 # You should have received a copy of the GNU General Public License
24 25 # along with this program; if not, write to the Free Software
25 26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 27 # MA 02110-1301, USA.
27 28
28 29 import os
29 30 import sys
30 31 import uuid
31 32 import logging
32 33 from os.path import dirname as dn, join as jn
33 34
34 35 from rhodecode import __dbversion__
35 36 from rhodecode.model import meta
36 37
37 38 from rhodecode.lib.auth import get_crypt_password
38 39 from rhodecode.lib.utils import ask_ok
39 40 from rhodecode.model import init_model
40 41 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
41 42 UserToPerm, DbMigrateVersion
42 43
43 44 from sqlalchemy.engine import create_engine
44 45
45 46
46 47 log = logging.getLogger(__name__)
47 48
48 49 class DbManage(object):
49 50 def __init__(self, log_sql, dbconf, root, tests=False):
50 51 self.dbname = dbconf.split('/')[-1]
51 52 self.tests = tests
52 53 self.root = root
53 54 self.dburi = dbconf
54 55 engine = create_engine(self.dburi, echo=log_sql)
55 56 init_model(engine)
56 57 self.sa = meta.Session()
57 58 self.db_exists = False
58 59
59 60 def check_for_db(self, override):
60 61 db_path = jn(self.root, self.dbname)
61 62 if self.dburi.startswith('sqlite'):
62 63 log.info('checking for existing db in %s', db_path)
63 64 if os.path.isfile(db_path):
64 65
65 66 self.db_exists = True
66 67 if not override:
67 68 raise Exception('database already exists')
68 69
69 70 def create_tables(self, override=False):
70 71 """Create a auth database
71 72 """
72 73
73 74 self.check_for_db(override)
74 75 if self.db_exists:
75 76 log.info("database exist and it's going to be destroyed")
76 77 if self.tests:
77 78 destroy = True
78 79 else:
79 80 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
80 81 if not destroy:
81 82 sys.exit()
82 83 if self.db_exists and destroy:
83 84 os.remove(jn(self.root, self.dbname))
84 85 checkfirst = not override
85 86 meta.Base.metadata.create_all(checkfirst=checkfirst)
86 87 log.info('Created tables for %s', self.dbname)
87 88
88 89
89 90
90 91 def set_db_version(self):
91 92 try:
92 93 ver = DbMigrateVersion()
93 94 ver.version = __dbversion__
94 95 ver.repository_id = 'rhodecode_db_migrations'
95 96 ver.repository_path = 'versions'
96 97 self.sa.add(ver)
97 98 self.sa.commit()
98 99 except:
99 100 self.sa.rollback()
100 101 raise
101 102 log.info('db version set to: %s', __dbversion__)
102 103
103 104 def fix_repo_paths(self):
104 105 """Fixes a old rhodecode version path into new one without a '*'
105 106 """
106 107
107 108 paths = self.sa.query(RhodeCodeUi)\
108 109 .filter(RhodeCodeUi.ui_key == '/')\
109 110 .scalar()
110 111
111 112 paths.ui_value = paths.ui_value.replace('*', '')
112 113
113 114 try:
114 115 self.sa.add(paths)
115 116 self.sa.commit()
116 117 except:
117 118 self.sa.rollback()
118 119 raise
119 120
121 def fix_default_user(self):
122 """Fixes a old default user with some 'nicer' default values,
123 used mostly for anonymous access
124 """
125 def_user = self.sa.query(User)\
126 .filter(User.username == 'default')\
127 .one()
128
129 def_user.name = 'Anonymous'
130 def_user.lastname = 'User'
131 def_user.email = 'anonymous@rhodecode.org'
132
133 try:
134 self.sa.add(def_user)
135 self.sa.commit()
136 except:
137 self.sa.rollback()
138 raise
139
120 140
121 141
122 142 def admin_prompt(self, second=False):
123 143 if not self.tests:
124 144 import getpass
125 145
126 146
127 147 def get_password():
128 148 password = getpass.getpass('Specify admin password (min 6 chars):')
129 149 confirm = getpass.getpass('Confirm password:')
130 150
131 151 if password != confirm:
132 152 log.error('passwords mismatch')
133 153 return False
134 154 if len(password) < 6:
135 155 log.error('password is to short use at least 6 characters')
136 156 return False
137 157
138 158 return password
139 159
140 160 username = raw_input('Specify admin username:')
141 161
142 162 password = get_password()
143 163 if not password:
144 164 #second try
145 165 password = get_password()
146 166 if not password:
147 167 sys.exit()
148 168
149 169 email = raw_input('Specify admin email:')
150 170 self.create_user(username, password, email, True)
151 171 else:
152 172 log.info('creating admin and regular test users')
153 173 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
154 174 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
155 175 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
156 176
157 177 def create_ui_settings(self):
158 178 """Creates ui settings, fills out hooks
159 179 and disables dotencode
160 180
161 181 """
162 182 #HOOKS
163 183 hooks1_key = 'changegroup.update'
164 184 hooks1_ = self.sa.query(RhodeCodeUi)\
165 185 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
166 186
167 187 hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
168 188 hooks1.ui_section = 'hooks'
169 189 hooks1.ui_key = hooks1_key
170 190 hooks1.ui_value = 'hg update >&2'
171 191 hooks1.ui_active = False
172 192
173 193 hooks2_key = 'changegroup.repo_size'
174 194 hooks2_ = self.sa.query(RhodeCodeUi)\
175 195 .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
176 196
177 197 hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
178 198 hooks2.ui_section = 'hooks'
179 199 hooks2.ui_key = hooks2_key
180 200 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
181 201
182 202 hooks3 = RhodeCodeUi()
183 203 hooks3.ui_section = 'hooks'
184 204 hooks3.ui_key = 'pretxnchangegroup.push_logger'
185 205 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
186 206
187 207 hooks4 = RhodeCodeUi()
188 208 hooks4.ui_section = 'hooks'
189 209 hooks4.ui_key = 'preoutgoing.pull_logger'
190 210 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
191 211
192 212 #For mercurial 1.7 set backward comapatibility with format
193 213 dotencode_disable = RhodeCodeUi()
194 214 dotencode_disable.ui_section = 'format'
195 215 dotencode_disable.ui_key = 'dotencode'
196 216 dotencode_disable.ui_value = 'false'
197 217
198 218 try:
199 219 self.sa.add(hooks1)
200 220 self.sa.add(hooks2)
201 221 self.sa.add(hooks3)
202 222 self.sa.add(hooks4)
203 223 self.sa.add(dotencode_disable)
204 224 self.sa.commit()
205 225 except:
206 226 self.sa.rollback()
207 227 raise
208 228
209 229
210 230 def create_ldap_options(self):
211 231 """Creates ldap settings"""
212 232
213 233 try:
214 234 for k in ['ldap_active', 'ldap_host', 'ldap_port', 'ldap_ldaps',
215 235 'ldap_dn_user', 'ldap_dn_pass', 'ldap_base_dn']:
216 236
217 237 setting = RhodeCodeSettings(k, '')
218 238 self.sa.add(setting)
219 239 self.sa.commit()
220 240 except:
221 241 self.sa.rollback()
222 242 raise
223 243
224 244 def config_prompt(self, test_repo_path=''):
225 245 log.info('Setting up repositories config')
226 246
227 247 if not self.tests and not test_repo_path:
228 248 path = raw_input('Specify valid full path to your repositories'
229 249 ' you can change this later in application settings:')
230 250 else:
231 251 path = test_repo_path
232 252
233 253 if not os.path.isdir(path):
234 254 log.error('You entered wrong path: %s', path)
235 255 sys.exit()
236 256
237 257 self.create_ui_settings()
238 258
239 259 #HG UI OPTIONS
240 260 web1 = RhodeCodeUi()
241 261 web1.ui_section = 'web'
242 262 web1.ui_key = 'push_ssl'
243 263 web1.ui_value = 'false'
244 264
245 265 web2 = RhodeCodeUi()
246 266 web2.ui_section = 'web'
247 267 web2.ui_key = 'allow_archive'
248 268 web2.ui_value = 'gz zip bz2'
249 269
250 270 web3 = RhodeCodeUi()
251 271 web3.ui_section = 'web'
252 272 web3.ui_key = 'allow_push'
253 273 web3.ui_value = '*'
254 274
255 275 web4 = RhodeCodeUi()
256 276 web4.ui_section = 'web'
257 277 web4.ui_key = 'baseurl'
258 278 web4.ui_value = '/'
259 279
260 280 paths = RhodeCodeUi()
261 281 paths.ui_section = 'paths'
262 282 paths.ui_key = '/'
263 283 paths.ui_value = path
264 284
265 285
266 286 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
267 287 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
268 288
269 289
270 290 try:
271 291 self.sa.add(web1)
272 292 self.sa.add(web2)
273 293 self.sa.add(web3)
274 294 self.sa.add(web4)
275 295 self.sa.add(paths)
276 296 self.sa.add(hgsettings1)
277 297 self.sa.add(hgsettings2)
278 298
279 299 self.sa.commit()
280 300 except:
281 301 self.sa.rollback()
282 302 raise
283 303
284 304 self.create_ldap_options()
285 305
286 306 log.info('created ui config')
287 307
288 308 def create_user(self, username, password, email='', admin=False):
289 309 log.info('creating administrator user %s', username)
290 310 new_user = User()
291 311 new_user.username = username
292 312 new_user.password = get_crypt_password(password)
293 313 new_user.name = 'RhodeCode'
294 314 new_user.lastname = 'Admin'
295 315 new_user.email = email
296 316 new_user.admin = admin
297 317 new_user.active = True
298 318
299 319 try:
300 320 self.sa.add(new_user)
301 321 self.sa.commit()
302 322 except:
303 323 self.sa.rollback()
304 324 raise
305 325
306 326 def create_default_user(self):
307 327 log.info('creating default user')
308 328 #create default user for handling default permissions.
309 329 def_user = User()
310 330 def_user.username = 'default'
311 331 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
312 332 def_user.name = 'Anonymous'
313 333 def_user.lastname = 'User'
314 334 def_user.email = 'anonymous@rhodecode.org'
315 335 def_user.admin = False
316 336 def_user.active = False
317 337 try:
318 338 self.sa.add(def_user)
319 339 self.sa.commit()
320 340 except:
321 341 self.sa.rollback()
322 342 raise
323 343
324 344 def create_permissions(self):
325 345 #module.(access|create|change|delete)_[name]
326 346 #module.(read|write|owner)
327 347 perms = [('repository.none', 'Repository no access'),
328 348 ('repository.read', 'Repository read access'),
329 349 ('repository.write', 'Repository write access'),
330 350 ('repository.admin', 'Repository admin access'),
331 351 ('hg.admin', 'Hg Administrator'),
332 352 ('hg.create.repository', 'Repository create'),
333 353 ('hg.create.none', 'Repository creation disabled'),
334 354 ('hg.register.none', 'Register disabled'),
335 355 ('hg.register.manual_activate', 'Register new user with rhodecode without manual activation'),
336 356 ('hg.register.auto_activate', 'Register new user with rhodecode without auto activation'),
337 357 ]
338 358
339 359 for p in perms:
340 360 new_perm = Permission()
341 361 new_perm.permission_name = p[0]
342 362 new_perm.permission_longname = p[1]
343 363 try:
344 364 self.sa.add(new_perm)
345 365 self.sa.commit()
346 366 except:
347 367 self.sa.rollback()
348 368 raise
349 369
350 370 def populate_default_permissions(self):
351 371 log.info('creating default user permissions')
352 372
353 373 default_user = self.sa.query(User)\
354 374 .filter(User.username == 'default').scalar()
355 375
356 376 reg_perm = UserToPerm()
357 377 reg_perm.user = default_user
358 378 reg_perm.permission = self.sa.query(Permission)\
359 379 .filter(Permission.permission_name == 'hg.register.manual_activate')\
360 380 .scalar()
361 381
362 382 create_repo_perm = UserToPerm()
363 383 create_repo_perm.user = default_user
364 384 create_repo_perm.permission = self.sa.query(Permission)\
365 385 .filter(Permission.permission_name == 'hg.create.repository')\
366 386 .scalar()
367 387
368 388 default_repo_perm = UserToPerm()
369 389 default_repo_perm.user = default_user
370 390 default_repo_perm.permission = self.sa.query(Permission)\
371 391 .filter(Permission.permission_name == 'repository.read')\
372 392 .scalar()
373 393
374 394 try:
375 395 self.sa.add(reg_perm)
376 396 self.sa.add(create_repo_perm)
377 397 self.sa.add(default_repo_perm)
378 398 self.sa.commit()
379 399 except:
380 400 self.sa.rollback()
381 401 raise
382 402
@@ -1,101 +1,104 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.dbmigrate.__init__
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Database migration modules
7 7
8 8 :created_on: Dec 11, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27
28 28 import logging
29 29 from sqlalchemy import engine_from_config
30 30
31 31 from rhodecode import __dbversion__
32 32 from rhodecode.lib.dbmigrate.migrate.versioning import api
33 33 from rhodecode.lib.dbmigrate.migrate.exceptions import \
34 34 DatabaseNotControlledError
35 35 from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
36 36 from rhodecode.lib.db_manage import DbManage
37 37
38 38 log = logging.getLogger(__name__)
39 39
40 40 class UpgradeDb(BasePasterCommand):
41 41 """Command used for paster to upgrade our database to newer version
42 42 """
43 43
44 44 max_args = 1
45 45 min_args = 1
46 46
47 47 usage = "CONFIG_FILE"
48 48 summary = "Upgrades current db to newer version given configuration file"
49 49 group_name = "RhodeCode"
50 50
51 51 parser = Command.standard_parser(verbose=True)
52 52
53 53 def command(self):
54 54 from pylons import config
55 55
56 56 add_cache(config)
57 57
58 58
59 59
60 60 repository_path = 'rhodecode/lib/dbmigrate'
61 61 db_uri = config['sqlalchemy.db1.url']
62 62
63 63 try:
64 64 curr_version = api.db_version(db_uri, repository_path)
65 65 msg = ('Found current database under version'
66 66 ' control with version %s' % curr_version)
67 67
68 68 except (RuntimeError, DatabaseNotControlledError), e:
69 69 curr_version = 1
70 70 msg = ('Current database is not under version control setting'
71 71 ' as version %s' % curr_version)
72 72 api.version_control(db_uri, repository_path, curr_version)
73 73
74 74 self.notify_msg(msg)
75 75
76 76 #now we have our dbversion we can do upgrade
77 77 self.notify_msg('attempting to do database upgrade to version %s' \
78 78 % __dbversion__)
79 79
80 80 api.upgrade(db_uri, repository_path, __dbversion__)
81 81 self.notify_msg('Schema upgrade completed')
82 82
83 83 #we need to make now some extra operations into database
84 self.notify_msg('Prociding with database updates')
84 self.notify_msg('Propagating database updates')
85 85
86 86 dbmanage = DbManage(log_sql=True, dbconf=db_uri,
87 87 root=config['here'], tests=False)
88 88
89 self.notify_msg('Patching repo paths for newer version of rhodecode')
89 self.notify_msg('Patching repo paths for newer version of RhodeCode')
90 90 dbmanage.fix_repo_paths()
91 91
92 self.notify_msg('Patching default user of RhodeCode')
93 dbmanage.fix_default_user()
94
92 95 self.notify_msg('Changing ui settings')
93 96 dbmanage.create_ui_settings()
94 97
95 98
96 99 def update_parser(self):
97 100 self.parser.add_option('--sql',
98 101 action='store_true',
99 102 dest='just_sql',
100 103 help="Prints upgrade sql for further investigation",
101 104 default=False)
General Comments 0
You need to be logged in to leave comments. Login now