14 # details. |
14 # details. |
15 # |
15 # |
16 # You should have received a copy of the GNU Lesser General Public License along |
16 # You should have received a copy of the GNU Lesser General Public License along |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
18 """cubicweb-ctl commands and command handlers specific to the repository""" |
18 """cubicweb-ctl commands and command handlers specific to the repository""" |
|
19 from __future__ import print_function |
19 |
20 |
20 __docformat__ = 'restructuredtext en' |
21 __docformat__ = 'restructuredtext en' |
21 |
22 |
22 # *ctl module should limit the number of import to be imported as quickly as |
23 # *ctl module should limit the number of import to be imported as quickly as |
23 # possible (for cubicweb-ctl reactivity, necessary for instance for usable bash |
24 # possible (for cubicweb-ctl reactivity, necessary for instance for usable bash |
53 if dbname is None: |
54 if dbname is None: |
54 dbname = source['db-name'] |
55 dbname = source['db-name'] |
55 driver = source['db-driver'] |
56 driver = source['db-driver'] |
56 dbhelper = get_db_helper(driver) |
57 dbhelper = get_db_helper(driver) |
57 if interactive: |
58 if interactive: |
58 print '-> connecting to %s database' % driver, |
59 print('-> connecting to %s database' % driver, end=' ') |
59 if dbhost: |
60 if dbhost: |
60 print '%s@%s' % (dbname, dbhost), |
61 print('%s@%s' % (dbname, dbhost), end=' ') |
61 else: |
62 else: |
62 print dbname, |
63 print(dbname, end=' ') |
63 if dbhelper.users_support: |
64 if dbhelper.users_support: |
64 if not interactive or (not special_privs and source.get('db-user')): |
65 if not interactive or (not special_privs and source.get('db-user')): |
65 user = source.get('db-user', os.environ.get('USER', '')) |
66 user = source.get('db-user', os.environ.get('USER', '')) |
66 if interactive: |
67 if interactive: |
67 print 'as', user |
68 print('as', user) |
68 password = source.get('db-password') |
69 password = source.get('db-password') |
69 else: |
70 else: |
70 print |
71 print() |
71 if special_privs: |
72 if special_privs: |
72 print 'WARNING' |
73 print('WARNING') |
73 print ('the user will need the following special access rights ' |
74 print ('the user will need the following special access rights ' |
74 'on the database:') |
75 'on the database:') |
75 print special_privs |
76 print(special_privs) |
76 print |
77 print() |
77 default_user = source.get('db-user', os.environ.get('USER', '')) |
78 default_user = source.get('db-user', os.environ.get('USER', '')) |
78 user = raw_input('Connect as user ? [%r]: ' % default_user) |
79 user = raw_input('Connect as user ? [%r]: ' % default_user) |
79 user = user.strip() or default_user |
80 user = user.strip() or default_user |
80 if user == source.get('db-user'): |
81 if user == source.get('db-user'): |
81 password = source.get('db-password') |
82 password = source.get('db-password') |
144 try: |
145 try: |
145 repo = repoapi.get_repository(config=config) |
146 repo = repoapi.get_repository(config=config) |
146 cnx = repoapi.connect(repo, login, password=pwd) |
147 cnx = repoapi.connect(repo, login, password=pwd) |
147 return repo, cnx |
148 return repo, cnx |
148 except AuthenticationError: |
149 except AuthenticationError: |
149 print '-> Error: wrong user/password.' |
150 print('-> Error: wrong user/password.') |
150 # reset cubes else we'll have an assertion error on next retry |
151 # reset cubes else we'll have an assertion error on next retry |
151 config._cubes = None |
152 config._cubes = None |
152 login, pwd = manager_userpasswd() |
153 login, pwd = manager_userpasswd() |
153 |
154 |
154 |
155 |
162 """create an instance by copying files from the given cube and by asking |
163 """create an instance by copying files from the given cube and by asking |
163 information necessary to build required configuration files |
164 information necessary to build required configuration files |
164 """ |
165 """ |
165 config = self.config |
166 config = self.config |
166 if not automatic: |
167 if not automatic: |
167 print underline_title('Configuring the repository') |
168 print(underline_title('Configuring the repository')) |
168 config.input_config('email', inputlevel) |
169 config.input_config('email', inputlevel) |
169 print '\n'+underline_title('Configuring the sources') |
170 print('\n'+underline_title('Configuring the sources')) |
170 sourcesfile = config.sources_file() |
171 sourcesfile = config.sources_file() |
171 # hack to make Method('default_instance_id') usable in db option defs |
172 # hack to make Method('default_instance_id') usable in db option defs |
172 # (in native.py) |
173 # (in native.py) |
173 sconfig = SourceConfiguration(config, |
174 sconfig = SourceConfiguration(config, |
174 options=SOURCE_TYPES['native'].options) |
175 options=SOURCE_TYPES['native'].options) |
175 if not automatic: |
176 if not automatic: |
176 sconfig.input_config(inputlevel=inputlevel) |
177 sconfig.input_config(inputlevel=inputlevel) |
177 print |
178 print() |
178 sourcescfg = {'system': sconfig} |
179 sourcescfg = {'system': sconfig} |
179 if automatic: |
180 if automatic: |
180 # XXX modify a copy |
181 # XXX modify a copy |
181 password = generate_password() |
182 password = generate_password() |
182 print '-> set administrator account to admin / %s' % password |
183 print('-> set administrator account to admin / %s' % password) |
183 USER_OPTIONS[1][1]['default'] = password |
184 USER_OPTIONS[1][1]['default'] = password |
184 sconfig = Configuration(options=USER_OPTIONS) |
185 sconfig = Configuration(options=USER_OPTIONS) |
185 else: |
186 else: |
186 sconfig = Configuration(options=USER_OPTIONS) |
187 sconfig = Configuration(options=USER_OPTIONS) |
187 sconfig.input_config(inputlevel=inputlevel) |
188 sconfig.input_config(inputlevel=inputlevel) |
195 CWCTL.run(['db-create', '--automatic', self.config.appid]) |
196 CWCTL.run(['db-create', '--automatic', self.config.appid]) |
196 elif ASK.confirm('Run db-create to create the system database ?'): |
197 elif ASK.confirm('Run db-create to create the system database ?'): |
197 CWCTL.run(['db-create', '--config-level', str(inputlevel), |
198 CWCTL.run(['db-create', '--config-level', str(inputlevel), |
198 self.config.appid]) |
199 self.config.appid]) |
199 else: |
200 else: |
200 print ('-> nevermind, you can do it later with ' |
201 print('-> nevermind, you can do it later with ' |
201 '"cubicweb-ctl db-create %s".' % self.config.appid) |
202 '"cubicweb-ctl db-create %s".' % self.config.appid) |
202 |
203 |
203 |
204 |
204 @contextmanager |
205 @contextmanager |
205 def db_transaction(source, privilege): |
206 def db_transaction(source, privilege): |
206 """Open a transaction to the instance database""" |
207 """Open a transaction to the instance database""" |
240 def _drop_namespace(self, source): |
241 def _drop_namespace(self, source): |
241 db_namespace = source.get('db-namespace') |
242 db_namespace = source.get('db-namespace') |
242 with db_transaction(source, privilege='DROP SCHEMA') as cursor: |
243 with db_transaction(source, privilege='DROP SCHEMA') as cursor: |
243 helper = get_db_helper(source['db-driver']) |
244 helper = get_db_helper(source['db-driver']) |
244 helper.drop_schema(cursor, db_namespace) |
245 helper.drop_schema(cursor, db_namespace) |
245 print '-> database schema %s dropped' % db_namespace |
246 print('-> database schema %s dropped' % db_namespace) |
246 |
247 |
247 def _drop_database(self, source): |
248 def _drop_database(self, source): |
248 dbname = source['db-name'] |
249 dbname = source['db-name'] |
249 if source['db-driver'] == 'sqlite': |
250 if source['db-driver'] == 'sqlite': |
250 print 'deleting database file %(db-name)s' % source |
251 print('deleting database file %(db-name)s' % source) |
251 os.unlink(source['db-name']) |
252 os.unlink(source['db-name']) |
252 print '-> database %(db-name)s dropped.' % source |
253 print('-> database %(db-name)s dropped.' % source) |
253 else: |
254 else: |
254 helper = get_db_helper(source['db-driver']) |
255 helper = get_db_helper(source['db-driver']) |
255 with db_sys_transaction(source, privilege='DROP DATABASE') as cursor: |
256 with db_sys_transaction(source, privilege='DROP DATABASE') as cursor: |
256 print 'dropping database %(db-name)s' % source |
257 print('dropping database %(db-name)s' % source) |
257 cursor.execute('DROP DATABASE "%(db-name)s"' % source) |
258 cursor.execute('DROP DATABASE "%(db-name)s"' % source) |
258 print '-> database %(db-name)s dropped.' % source |
259 print('-> database %(db-name)s dropped.' % source) |
259 |
260 |
260 def _drop_user(self, source): |
261 def _drop_user(self, source): |
261 user = source['db-user'] or None |
262 user = source['db-user'] or None |
262 if user is not None: |
263 if user is not None: |
263 with db_sys_transaction(source, privilege='DROP USER') as cursor: |
264 with db_sys_transaction(source, privilege='DROP USER') as cursor: |
264 print 'dropping user %s' % user |
265 print('dropping user %s' % user) |
265 cursor.execute('DROP USER %s' % user) |
266 cursor.execute('DROP USER %s' % user) |
266 |
267 |
267 def _cleanup_steps(self, source): |
268 def _cleanup_steps(self, source): |
268 # 1/ delete namespace if used |
269 # 1/ delete namespace if used |
269 db_namespace = source.get('db-namespace') |
270 db_namespace = source.get('db-namespace') |
286 for msg, step, default in self._cleanup_steps(source): |
287 for msg, step, default in self._cleanup_steps(source): |
287 if ASK.confirm(msg, default_is_yes=default): |
288 if ASK.confirm(msg, default_is_yes=default): |
288 try: |
289 try: |
289 step(source) |
290 step(source) |
290 except Exception as exc: |
291 except Exception as exc: |
291 print 'ERROR', exc |
292 print('ERROR', exc) |
292 if ASK.confirm('An error occurred. Continue anyway?', |
293 if ASK.confirm('An error occurred. Continue anyway?', |
293 default_is_yes=False): |
294 default_is_yes=False): |
294 continue |
295 continue |
295 raise ExecutionError(str(exc)) |
296 raise ExecutionError(str(exc)) |
296 |
297 |
355 if os.path.exists(dbname) and ( |
356 if os.path.exists(dbname) and ( |
356 automatic or |
357 automatic or |
357 ASK.confirm('Database %s already exists. Drop it?' % dbname)): |
358 ASK.confirm('Database %s already exists. Drop it?' % dbname)): |
358 os.unlink(dbname) |
359 os.unlink(dbname) |
359 elif self.config.create_db: |
360 elif self.config.create_db: |
360 print '\n'+underline_title('Creating the system database') |
361 print('\n'+underline_title('Creating the system database')) |
361 # connect on the dbms system base to create our base |
362 # connect on the dbms system base to create our base |
362 dbcnx = _db_sys_cnx(source, 'CREATE/DROP DATABASE and / or USER', |
363 dbcnx = _db_sys_cnx(source, 'CREATE/DROP DATABASE and / or USER', |
363 interactive=not automatic) |
364 interactive=not automatic) |
364 cursor = dbcnx.cursor() |
365 cursor = dbcnx.cursor() |
365 try: |
366 try: |
366 if helper.users_support: |
367 if helper.users_support: |
367 user = source['db-user'] |
368 user = source['db-user'] |
368 if not helper.user_exists(cursor, user) and (automatic or \ |
369 if not helper.user_exists(cursor, user) and (automatic or \ |
369 ASK.confirm('Create db user %s ?' % user, default_is_yes=False)): |
370 ASK.confirm('Create db user %s ?' % user, default_is_yes=False)): |
370 helper.create_user(source['db-user'], source.get('db-password')) |
371 helper.create_user(source['db-user'], source.get('db-password')) |
371 print '-> user %s created.' % user |
372 print('-> user %s created.' % user) |
372 if dbname in helper.list_databases(cursor): |
373 if dbname in helper.list_databases(cursor): |
373 if automatic or ASK.confirm('Database %s already exists -- do you want to drop it ?' % dbname): |
374 if automatic or ASK.confirm('Database %s already exists -- do you want to drop it ?' % dbname): |
374 cursor.execute('DROP DATABASE "%s"' % dbname) |
375 cursor.execute('DROP DATABASE "%s"' % dbname) |
375 else: |
376 else: |
376 print ('you may want to run "cubicweb-ctl db-init ' |
377 print('you may want to run "cubicweb-ctl db-init ' |
377 '--drop %s" manually to continue.' % config.appid) |
378 '--drop %s" manually to continue.' % config.appid) |
378 return |
379 return |
379 createdb(helper, source, dbcnx, cursor) |
380 createdb(helper, source, dbcnx, cursor) |
380 dbcnx.commit() |
381 dbcnx.commit() |
381 print '-> database %s created.' % dbname |
382 print('-> database %s created.' % dbname) |
382 except BaseException: |
383 except BaseException: |
383 dbcnx.rollback() |
384 dbcnx.rollback() |
384 raise |
385 raise |
385 cnx = system_source_cnx(source, special_privs='CREATE LANGUAGE/SCHEMA', |
386 cnx = system_source_cnx(source, special_privs='CREATE LANGUAGE/SCHEMA', |
386 interactive=not automatic) |
387 interactive=not automatic) |
398 for extlang in langs: |
399 for extlang in langs: |
399 if automatic or ASK.confirm('Create language %s ?' % extlang): |
400 if automatic or ASK.confirm('Create language %s ?' % extlang): |
400 try: |
401 try: |
401 helper.create_language(cursor, extlang) |
402 helper.create_language(cursor, extlang) |
402 except Exception as exc: |
403 except Exception as exc: |
403 print '-> ERROR:', exc |
404 print('-> ERROR:', exc) |
404 print '-> could not create language %s, some stored procedures might be unusable' % extlang |
405 print('-> could not create language %s, some stored procedures might be unusable' % extlang) |
405 cnx.rollback() |
406 cnx.rollback() |
406 else: |
407 else: |
407 cnx.commit() |
408 cnx.commit() |
408 print '-> database for instance %s created and necessary extensions installed.' % appid |
409 print('-> database for instance %s created and necessary extensions installed.' % appid) |
409 print |
410 print() |
410 if automatic: |
411 if automatic: |
411 CWCTL.run(['db-init', '--automatic', '--config-level', '0', |
412 CWCTL.run(['db-init', '--automatic', '--config-level', '0', |
412 config.appid]) |
413 config.appid]) |
413 elif ASK.confirm('Run db-init to initialize the system database ?'): |
414 elif ASK.confirm('Run db-init to initialize the system database ?'): |
414 CWCTL.run(['db-init', '--config-level', |
415 CWCTL.run(['db-init', '--config-level', |
415 str(self.config.config_level), config.appid]) |
416 str(self.config.config_level), config.appid]) |
416 else: |
417 else: |
417 print ('-> nevermind, you can do it later with ' |
418 print('-> nevermind, you can do it later with ' |
418 '"cubicweb-ctl db-init %s".' % config.appid) |
419 '"cubicweb-ctl db-init %s".' % config.appid) |
419 |
420 |
420 |
421 |
421 class InitInstanceCommand(Command): |
422 class InitInstanceCommand(Command): |
422 """Initialize the system database of an instance (run after 'db-create'). |
423 """Initialize the system database of an instance (run after 'db-create'). |
423 |
424 |
504 cubes = repo.get_cubes() |
505 cubes = repo.get_cubes() |
505 while True: |
506 while True: |
506 type = raw_input('source type (%s): ' |
507 type = raw_input('source type (%s): ' |
507 % ', '.join(sorted(SOURCE_TYPES))) |
508 % ', '.join(sorted(SOURCE_TYPES))) |
508 if type not in SOURCE_TYPES: |
509 if type not in SOURCE_TYPES: |
509 print '-> unknown source type, use one of the available types.' |
510 print('-> unknown source type, use one of the available types.') |
510 continue |
511 continue |
511 sourcemodule = SOURCE_TYPES[type].module |
512 sourcemodule = SOURCE_TYPES[type].module |
512 if not sourcemodule.startswith('cubicweb.'): |
513 if not sourcemodule.startswith('cubicweb.'): |
513 # module names look like cubes.mycube.themodule |
514 # module names look like cubes.mycube.themodule |
514 sourcecube = SOURCE_TYPES[type].module.split('.', 2)[1] |
515 sourcecube = SOURCE_TYPES[type].module.split('.', 2)[1] |
522 while True: |
523 while True: |
523 parser = raw_input('parser type (%s): ' |
524 parser = raw_input('parser type (%s): ' |
524 % ', '.join(sorted(repo.vreg['parsers']))) |
525 % ', '.join(sorted(repo.vreg['parsers']))) |
525 if parser in repo.vreg['parsers']: |
526 if parser in repo.vreg['parsers']: |
526 break |
527 break |
527 print '-> unknown parser identifier, use one of the available types.' |
528 print('-> unknown parser identifier, use one of the available types.') |
528 while True: |
529 while True: |
529 sourceuri = raw_input('source identifier (a unique name used to ' |
530 sourceuri = raw_input('source identifier (a unique name used to ' |
530 'tell sources apart): ').strip() |
531 'tell sources apart): ').strip() |
531 if not sourceuri: |
532 if not sourceuri: |
532 print '-> mandatory.' |
533 print('-> mandatory.') |
533 else: |
534 else: |
534 sourceuri = unicode(sourceuri, sys.stdin.encoding) |
535 sourceuri = unicode(sourceuri, sys.stdin.encoding) |
535 if sourceuri in used: |
536 if sourceuri in used: |
536 print '-> uri already used, choose another one.' |
537 print('-> uri already used, choose another one.') |
537 else: |
538 else: |
538 break |
539 break |
539 url = raw_input('source URL (leave empty for none): ').strip() |
540 url = raw_input('source URL (leave empty for none): ').strip() |
540 url = unicode(url) if url else None |
541 url = unicode(url) if url else None |
541 # XXX configurable inputlevel |
542 # XXX configurable inputlevel |
581 set_owner=set_owner), cursor) |
582 set_owner=set_owner), cursor) |
582 except Exception as ex: |
583 except Exception as ex: |
583 cnx.rollback() |
584 cnx.rollback() |
584 import traceback |
585 import traceback |
585 traceback.print_exc() |
586 traceback.print_exc() |
586 print '-> an error occurred:', ex |
587 print('-> an error occurred:', ex) |
587 else: |
588 else: |
588 cnx.commit() |
589 cnx.commit() |
589 print '-> rights granted to %s on instance %s.' % (appid, user) |
590 print('-> rights granted to %s on instance %s.' % (appid, user)) |
590 |
591 |
591 |
592 |
592 class ResetAdminPasswordCommand(Command): |
593 class ResetAdminPasswordCommand(Command): |
593 """Reset the administrator password. |
594 """Reset the administrator password. |
594 |
595 |
615 config = ServerConfiguration.config_for(appid) |
616 config = ServerConfiguration.config_for(appid) |
616 sourcescfg = config.read_sources_file() |
617 sourcescfg = config.read_sources_file() |
617 try: |
618 try: |
618 adminlogin = sourcescfg['admin']['login'] |
619 adminlogin = sourcescfg['admin']['login'] |
619 except KeyError: |
620 except KeyError: |
620 print '-> Error: could not get cubicweb administrator login.' |
621 print('-> Error: could not get cubicweb administrator login.') |
621 sys.exit(1) |
622 sys.exit(1) |
622 cnx = source_cnx(sourcescfg['system']) |
623 cnx = source_cnx(sourcescfg['system']) |
623 driver = sourcescfg['system']['db-driver'] |
624 driver = sourcescfg['system']['db-driver'] |
624 dbhelper = get_db_helper(driver) |
625 dbhelper = get_db_helper(driver) |
625 cursor = cnx.cursor() |
626 cursor = cnx.cursor() |
626 # check admin exists |
627 # check admin exists |
627 cursor.execute("SELECT * FROM cw_CWUser WHERE cw_login=%(l)s", |
628 cursor.execute("SELECT * FROM cw_CWUser WHERE cw_login=%(l)s", |
628 {'l': adminlogin}) |
629 {'l': adminlogin}) |
629 if not cursor.fetchall(): |
630 if not cursor.fetchall(): |
630 print ("-> error: admin user %r specified in sources doesn't exist " |
631 print("-> error: admin user %r specified in sources doesn't exist " |
631 "in the database" % adminlogin) |
632 "in the database" % adminlogin) |
632 print " fix your sources file before running this command" |
633 print(" fix your sources file before running this command") |
633 cnx.close() |
634 cnx.close() |
634 sys.exit(1) |
635 sys.exit(1) |
635 if self.config.password is None: |
636 if self.config.password is None: |
636 # ask for a new password |
637 # ask for a new password |
637 msg = 'new password for %s' % adminlogin |
638 msg = 'new password for %s' % adminlogin |
648 config.write_sources_file(sourcescfg) |
649 config.write_sources_file(sourcescfg) |
649 except Exception as ex: |
650 except Exception as ex: |
650 cnx.rollback() |
651 cnx.rollback() |
651 import traceback |
652 import traceback |
652 traceback.print_exc() |
653 traceback.print_exc() |
653 print '-> an error occurred:', ex |
654 print('-> an error occurred:', ex) |
654 else: |
655 else: |
655 cnx.commit() |
656 cnx.commit() |
656 print '-> password reset, sources file regenerated.' |
657 print('-> password reset, sources file regenerated.') |
657 cnx.close() |
658 cnx.close() |
658 |
659 |
659 |
660 |
660 |
661 |
661 def _remote_dump(host, appid, output, sudo=False): |
662 def _remote_dump(host, appid, output, sudo=False): |
664 filename = '%s-%s.tgz' % (appid, date.today().strftime('%Y-%m-%d')) |
665 filename = '%s-%s.tgz' % (appid, date.today().strftime('%Y-%m-%d')) |
665 dmpcmd = 'cubicweb-ctl db-dump -o /tmp/%s %s' % (filename, appid) |
666 dmpcmd = 'cubicweb-ctl db-dump -o /tmp/%s %s' % (filename, appid) |
666 if sudo: |
667 if sudo: |
667 dmpcmd = 'sudo %s' % (dmpcmd) |
668 dmpcmd = 'sudo %s' % (dmpcmd) |
668 dmpcmd = 'ssh -t %s "%s"' % (host, dmpcmd) |
669 dmpcmd = 'ssh -t %s "%s"' % (host, dmpcmd) |
669 print dmpcmd |
670 print(dmpcmd) |
670 if os.system(dmpcmd): |
671 if os.system(dmpcmd): |
671 raise ExecutionError('Error while dumping the database') |
672 raise ExecutionError('Error while dumping the database') |
672 if output is None: |
673 if output is None: |
673 output = filename |
674 output = filename |
674 cmd = 'scp %s:/tmp/%s %s' % (host, filename, output) |
675 cmd = 'scp %s:/tmp/%s %s' % (host, filename, output) |
675 print cmd |
676 print(cmd) |
676 if os.system(cmd): |
677 if os.system(cmd): |
677 raise ExecutionError('Error while retrieving the dump at /tmp/%s' % filename) |
678 raise ExecutionError('Error while retrieving the dump at /tmp/%s' % filename) |
678 rmcmd = 'ssh -t %s "rm -f /tmp/%s"' % (host, filename) |
679 rmcmd = 'ssh -t %s "rm -f /tmp/%s"' % (host, filename) |
679 print rmcmd |
680 print(rmcmd) |
680 if os.system(rmcmd) and not ASK.confirm( |
681 if os.system(rmcmd) and not ASK.confirm( |
681 'An error occurred while deleting remote dump at /tmp/%s. ' |
682 'An error occurred while deleting remote dump at /tmp/%s. ' |
682 'Continue anyway?' % filename): |
683 'Continue anyway?' % filename): |
683 raise ExecutionError('Error while deleting remote dump at /tmp/%s' % filename) |
684 raise ExecutionError('Error while deleting remote dump at /tmp/%s' % filename) |
684 |
685 |
699 repo = mih.repo |
700 repo = mih.repo |
700 # version of the database |
701 # version of the database |
701 dbversions = repo.get_versions() |
702 dbversions = repo.get_versions() |
702 mih.shutdown() |
703 mih.shutdown() |
703 if not dbversions: |
704 if not dbversions: |
704 print "bad or missing version information in the database, don't upgrade file system" |
705 print("bad or missing version information in the database, don't upgrade file system") |
705 return |
706 return |
706 # version of installed software |
707 # version of installed software |
707 eversion = dbversions['cubicweb'] |
708 eversion = dbversions['cubicweb'] |
708 status = instance_status(config, eversion, dbversions) |
709 status = instance_status(config, eversion, dbversions) |
709 # * database version > installed software |
710 # * database version > installed software |
710 if status == 'needsoftupgrade': |
711 if status == 'needsoftupgrade': |
711 print "** The database of %s is more recent than the installed software!" % config.appid |
712 print("** The database of %s is more recent than the installed software!" % config.appid) |
712 print "** Upgrade your software, then migrate the database by running the command" |
713 print("** Upgrade your software, then migrate the database by running the command") |
713 print "** 'cubicweb-ctl upgrade %s'" % config.appid |
714 print("** 'cubicweb-ctl upgrade %s'" % config.appid) |
714 return |
715 return |
715 # * database version < installed software, an upgrade will be necessary |
716 # * database version < installed software, an upgrade will be necessary |
716 # anyway, just rewrite vc.conf and warn user he has to upgrade |
717 # anyway, just rewrite vc.conf and warn user he has to upgrade |
717 elif status == 'needapplupgrade': |
718 elif status == 'needapplupgrade': |
718 print "** The database of %s is older than the installed software." % config.appid |
719 print("** The database of %s is older than the installed software." % config.appid) |
719 print "** Migrate the database by running the command" |
720 print("** Migrate the database by running the command") |
720 print "** 'cubicweb-ctl upgrade %s'" % config.appid |
721 print("** 'cubicweb-ctl upgrade %s'" % config.appid) |
721 return |
722 return |
722 # * database version = installed software, database version = instance fs version |
723 # * database version = installed software, database version = instance fs version |
723 # ok! |
724 # ok! |
724 |
725 |
725 def instance_status(config, cubicwebapplversion, vcconf): |
726 def instance_status(config, cubicwebapplversion, vcconf): |
730 return 'needapplupgrade' |
731 return 'needapplupgrade' |
731 for cube in config.cubes(): |
732 for cube in config.cubes(): |
732 try: |
733 try: |
733 softversion = config.cube_version(cube) |
734 softversion = config.cube_version(cube) |
734 except ConfigurationError: |
735 except ConfigurationError: |
735 print '-> Error: no cube version information for %s, please check that the cube is installed.' % cube |
736 print('-> Error: no cube version information for %s, please check that the cube is installed.' % cube) |
736 continue |
737 continue |
737 try: |
738 try: |
738 applversion = vcconf[cube] |
739 applversion = vcconf[cube] |
739 except KeyError: |
740 except KeyError: |
740 print '-> Error: no cube version information for %s in version configuration.' % cube |
741 print('-> Error: no cube version information for %s in version configuration.' % cube) |
741 continue |
742 continue |
742 if softversion == applversion: |
743 if softversion == applversion: |
743 continue |
744 continue |
744 if softversion > applversion: |
745 if softversion > applversion: |
745 return 'needsoftupgrade' |
746 return 'needsoftupgrade' |
881 else: |
882 else: |
882 _local_dump(srcappid, output, format=self.config.format) |
883 _local_dump(srcappid, output, format=self.config.format) |
883 _local_restore(destappid, output, not self.config.no_drop, |
884 _local_restore(destappid, output, not self.config.no_drop, |
884 self.config.format) |
885 self.config.format) |
885 if self.config.keep_dump: |
886 if self.config.keep_dump: |
886 print '-> you can get the dump file at', output |
887 print('-> you can get the dump file at', output) |
887 else: |
888 else: |
888 os.remove(output) |
889 os.remove(output) |
889 |
890 |
890 |
891 |
891 class CheckRepositoryCommand(Command): |
892 class CheckRepositoryCommand(Command): |
1001 stats = source.pull_data(cnx, force=True, raise_on_error=True) |
1002 stats = source.pull_data(cnx, force=True, raise_on_error=True) |
1002 finally: |
1003 finally: |
1003 repo.shutdown() |
1004 repo.shutdown() |
1004 for key, val in stats.iteritems(): |
1005 for key, val in stats.iteritems(): |
1005 if val: |
1006 if val: |
1006 print key, ':', val |
1007 print(key, ':', val) |
1007 |
1008 |
1008 |
1009 |
1009 |
1010 |
1010 def permissionshandler(relation, perms): |
1011 def permissionshandler(relation, perms): |
1011 from yams.schema import RelationDefinitionSchema |
1012 from yams.schema import RelationDefinitionSchema |