87 cnx.set_isolation_level(0) |
87 cnx.set_isolation_level(0) |
88 except AttributeError: |
88 except AttributeError: |
89 # set_isolation_level() is psycopg specific |
89 # set_isolation_level() is psycopg specific |
90 pass |
90 pass |
91 return cnx |
91 return cnx |
92 |
92 |
93 def generate_sources_file(sourcesfile, sourcescfg, keys=None): |
93 def generate_sources_file(sourcesfile, sourcescfg, keys=None): |
94 """serialize repository'sources configuration into a INI like file |
94 """serialize repository'sources configuration into a INI like file |
95 |
95 |
96 the `keys` parameter may be used to sort sections |
96 the `keys` parameter may be used to sort sections |
97 """ |
97 """ |
107 sconfig = sourcescfg[uri] |
107 sconfig = sourcescfg[uri] |
108 if isinstance(sconfig, dict): |
108 if isinstance(sconfig, dict): |
109 # get a Configuration object |
109 # get a Configuration object |
110 _sconfig = Configuration(options=SOURCE_TYPES[sconfig['adapter']].options) |
110 _sconfig = Configuration(options=SOURCE_TYPES[sconfig['adapter']].options) |
111 for attr, val in sconfig.items(): |
111 for attr, val in sconfig.items(): |
112 if attr == 'uri': |
112 if attr == 'uri': |
113 continue |
113 continue |
114 if attr == 'adapter': |
114 if attr == 'adapter': |
115 _sconfig.adapter = val |
115 _sconfig.adapter = val |
116 else: |
116 else: |
117 _sconfig.set_option(attr, val) |
117 _sconfig.set_option(attr, val) |
138 try: |
138 try: |
139 return in_memory_cnx(config, login, pwd) |
139 return in_memory_cnx(config, login, pwd) |
140 except AuthenticationError: |
140 except AuthenticationError: |
141 print 'wrong user/password' |
141 print 'wrong user/password' |
142 login, pwd = manager_userpasswd() |
142 login, pwd = manager_userpasswd() |
143 |
143 |
144 # repository specific command handlers ######################################## |
144 # repository specific command handlers ######################################## |
145 |
145 |
146 class RepositoryCreateHandler(CommandHandler): |
146 class RepositoryCreateHandler(CommandHandler): |
147 cmdname = 'create' |
147 cmdname = 'create' |
148 cfgname = 'repository' |
148 cfgname = 'repository' |
185 sourcescfg['admin'] = sconfig |
185 sourcescfg['admin'] = sconfig |
186 generate_sources_file(sourcesfile, sourcescfg, ['admin', 'system']) |
186 generate_sources_file(sourcesfile, sourcescfg, ['admin', 'system']) |
187 restrict_perms_to_user(sourcesfile) |
187 restrict_perms_to_user(sourcesfile) |
188 # remember selected cubes for later initialization of the database |
188 # remember selected cubes for later initialization of the database |
189 config.write_bootstrap_cubes_file(cubes) |
189 config.write_bootstrap_cubes_file(cubes) |
190 |
190 |
191 def postcreate(self): |
191 def postcreate(self): |
192 if confirm('do you want to create repository\'s system database?'): |
192 if confirm('do you want to create repository\'s system database?'): |
193 verbosity = (self.config.mode == 'installed') and 'y' or 'n' |
193 verbosity = (self.config.mode == 'installed') and 'y' or 'n' |
194 cmd_run('db-create', self.config.appid, '--verbose=%s' % verbosity) |
194 cmd_run('db-create', self.config.appid, '--verbose=%s' % verbosity) |
195 else: |
195 else: |
196 print 'nevermind, you can do it later using the db-create command' |
196 print 'nevermind, you can do it later using the db-create command' |
197 |
197 |
198 USER_OPTIONS = ( |
198 USER_OPTIONS = ( |
199 ('login', {'type' : 'string', |
199 ('login', {'type' : 'string', |
200 'default': REQUIRED, |
200 'default': REQUIRED, |
201 'help': "cubicweb manager account's login " |
201 'help': "cubicweb manager account's login " |
202 '(this user will be created)', |
202 '(this user will be created)', |
234 cnx.commit() |
234 cnx.commit() |
235 except: |
235 except: |
236 cnx.rollback() |
236 cnx.rollback() |
237 raise |
237 raise |
238 |
238 |
239 |
239 |
240 class RepositoryStartHandler(CommandHandler): |
240 class RepositoryStartHandler(CommandHandler): |
241 cmdname = 'start' |
241 cmdname = 'start' |
242 cfgname = 'repository' |
242 cfgname = 'repository' |
243 |
243 |
244 def start_command(self, ctlconf, debug): |
244 def start_command(self, ctlconf, debug): |
245 command = ['cubicweb-ctl start-repository '] |
245 command = ['cubicweb-ctl start-repository '] |
246 if debug: |
246 if debug: |
247 command.append('--debug') |
247 command.append('--debug') |
248 command.append(self.config.appid) |
248 command.append(self.config.appid) |
249 return ' '.join(command) |
249 return ' '.join(command) |
250 |
250 |
251 |
251 |
252 class RepositoryStopHandler(CommandHandler): |
252 class RepositoryStopHandler(CommandHandler): |
253 cmdname = 'stop' |
253 cmdname = 'stop' |
254 cfgname = 'repository' |
254 cfgname = 'repository' |
255 |
255 |
258 unregistered |
258 unregistered |
259 """ |
259 """ |
260 if self.config.pyro_enabled(): |
260 if self.config.pyro_enabled(): |
261 from cubicweb.server.repository import pyro_unregister |
261 from cubicweb.server.repository import pyro_unregister |
262 pyro_unregister(self.config) |
262 pyro_unregister(self.config) |
263 |
263 |
264 |
264 |
265 # repository specific commands ################################################ |
265 # repository specific commands ################################################ |
266 class CreateApplicationDBCommand(Command): |
266 class CreateApplicationDBCommand(Command): |
267 """Create the system database of an application (run after 'create'). |
267 """Create the system database of an application (run after 'create'). |
268 |
268 |
269 You will be prompted for a login / password to use to connect to |
269 You will be prompted for a login / password to use to connect to |
270 the system database. The given user should have almost all rights |
270 the system database. The given user should have almost all rights |
271 on the database (ie a super user on the dbms allowed to create |
271 on the database (ie a super user on the dbms allowed to create |
272 database, users, languages...). |
272 database, users, languages...). |
273 |
273 |
274 <application> |
274 <application> |
275 the identifier of the application to initialize. |
275 the identifier of the application to initialize. |
276 """ |
276 """ |
277 name = 'db-create' |
277 name = 'db-create' |
278 arguments = '<application>' |
278 arguments = '<application>' |
279 |
279 |
280 options = ( |
280 options = ( |
281 ("create-db", |
281 ("create-db", |
282 {'short': 'c', 'type': "yn", 'metavar': '<y or n>', |
282 {'short': 'c', 'type': "yn", 'metavar': '<y or n>', |
283 'default': True, |
283 'default': True, |
284 'help': 'create the database (yes by default)'}), |
284 'help': 'create the database (yes by default)'}), |
326 dbcnx.commit() |
326 dbcnx.commit() |
327 print 'database %s created' % source['db-name'] |
327 print 'database %s created' % source['db-name'] |
328 except: |
328 except: |
329 dbcnx.rollback() |
329 dbcnx.rollback() |
330 raise |
330 raise |
331 cnx = system_source_cnx(source, special_privs='LANGUAGE C', verbose=verbose) |
331 cnx = system_source_cnx(source, special_privs='LANGUAGE C', verbose=verbose) |
332 cursor = cnx.cursor() |
332 cursor = cnx.cursor() |
333 indexer = get_indexer(driver) |
333 indexer = get_indexer(driver) |
334 indexer.init_extensions(cursor) |
334 indexer.init_extensions(cursor) |
335 # postgres specific stuff |
335 # postgres specific stuff |
336 if driver == 'postgres': |
336 if driver == 'postgres': |
337 # install plpythonu/plpgsql language if not installed by the cube |
337 # install plpythonu/plpgsql language if not installed by the cube |
338 for extlang in ('plpythonu', 'plpgsql'): |
338 for extlang in ('plpythonu', 'plpgsql'): |
339 helper.create_language(cursor, extlang) |
339 helper.create_language(cursor, extlang) |
340 cursor.close() |
340 cursor.close() |
344 if confirm('do you want to initialize the system database?'): |
344 if confirm('do you want to initialize the system database?'): |
345 cmd_run('db-init', config.appid) |
345 cmd_run('db-init', config.appid) |
346 else: |
346 else: |
347 print 'nevermind, you can do it later using the db-init command' |
347 print 'nevermind, you can do it later using the db-init command' |
348 |
348 |
349 |
349 |
350 class InitApplicationCommand(Command): |
350 class InitApplicationCommand(Command): |
351 """Initialize the system database of an application (run after 'db-create'). |
351 """Initialize the system database of an application (run after 'db-create'). |
352 |
352 |
353 You will be prompted for a login / password to use to connect to |
353 You will be prompted for a login / password to use to connect to |
354 the system database. The given user should have the create tables, |
354 the system database. The given user should have the create tables, |
355 and grant permissions. |
355 and grant permissions. |
356 |
356 |
357 <application> |
357 <application> |
358 the identifier of the application to initialize. |
358 the identifier of the application to initialize. |
359 """ |
359 """ |
360 name = 'db-init' |
360 name = 'db-init' |
361 arguments = '<application>' |
361 arguments = '<application>' |
362 |
362 |
363 options = ( |
363 options = ( |
364 ("drop", |
364 ("drop", |
365 {'short': 'd', 'action': 'store_true', |
365 {'short': 'd', 'action': 'store_true', |
366 'default': False, |
366 'default': False, |
367 'help': 'insert drop statements to remove previously existant \ |
367 'help': 'insert drop statements to remove previously existant \ |
375 init_repository(config, drop=self.config.drop) |
375 init_repository(config, drop=self.config.drop) |
376 |
376 |
377 |
377 |
378 class GrantUserOnApplicationCommand(Command): |
378 class GrantUserOnApplicationCommand(Command): |
379 """Grant a database user on a repository system database. |
379 """Grant a database user on a repository system database. |
380 |
380 |
381 <application> |
381 <application> |
382 the identifier of the application |
382 the identifier of the application |
383 <user> |
383 <user> |
384 the database's user requiring grant access |
384 the database's user requiring grant access |
385 """ |
385 """ |
386 name = 'db-grant-user' |
386 name = 'db-grant-user' |
387 arguments = '<application> <user>' |
387 arguments = '<application> <user>' |
388 |
388 |
389 options = ( |
389 options = ( |
390 ("set-owner", |
390 ("set-owner", |
391 {'short': 'o', 'type' : "yn", 'metavar' : '<yes or no>', |
391 {'short': 'o', 'type' : "yn", 'metavar' : '<yes or no>', |
392 'default' : False, |
392 'default' : False, |
393 'help': 'Set the user as tables owner if yes (no by default).'} |
393 'help': 'Set the user as tables owner if yes (no by default).'} |
394 ), |
394 ), |
395 ) |
395 ) |
396 def run(self, args): |
396 def run(self, args): |
415 else: |
415 else: |
416 cnx.commit() |
416 cnx.commit() |
417 print 'grants given to %s on application %s' % (appid, user) |
417 print 'grants given to %s on application %s' % (appid, user) |
418 |
418 |
419 |
419 |
420 |
420 |
421 class StartRepositoryCommand(Command): |
421 class StartRepositoryCommand(Command): |
422 """Start an CubicWeb RQL server for a given application. |
422 """Start an CubicWeb RQL server for a given application. |
423 |
423 |
424 The server will be accessible through pyro |
424 The server will be accessible through pyro |
425 |
425 |
426 <application> |
426 <application> |
427 the identifier of the application to initialize. |
427 the identifier of the application to initialize. |
428 """ |
428 """ |
429 name = 'start-repository' |
429 name = 'start-repository' |
430 arguments = '<application>' |
430 arguments = '<application>' |
431 |
431 |
432 options = ( |
432 options = ( |
433 ("debug", |
433 ("debug", |
434 {'short': 'D', 'action' : 'store_true', |
434 {'short': 'D', 'action' : 'store_true', |
435 'help': 'start server in debug mode.'}), |
435 'help': 'start server in debug mode.'}), |
436 ) |
436 ) |
532 continue |
532 continue |
533 try: |
533 try: |
534 applversion = vcconf[cube] |
534 applversion = vcconf[cube] |
535 except KeyError: |
535 except KeyError: |
536 print "no cube version information for %s in version configuration" % cube |
536 print "no cube version information for %s in version configuration" % cube |
537 continue |
537 continue |
538 if softversion == applversion: |
538 if softversion == applversion: |
539 continue |
539 continue |
540 if softversion > applversion: |
540 if softversion > applversion: |
541 return 'needsoftupgrade' |
541 return 'needsoftupgrade' |
542 elif softversion < applversion: |
542 elif softversion < applversion: |
543 return 'needapplupgrade' |
543 return 'needapplupgrade' |
544 return None |
544 return None |
545 |
545 |
546 |
546 |
547 class DBDumpCommand(Command): |
547 class DBDumpCommand(Command): |
548 """Backup the system database of an application. |
548 """Backup the system database of an application. |
549 |
549 |
550 <application> |
550 <application> |
551 the identifier of the application to backup |
551 the identifier of the application to backup |
552 format [[user@]host:]appname |
552 format [[user@]host:]appname |
553 """ |
553 """ |
554 name = 'db-dump' |
554 name = 'db-dump' |
555 arguments = '<application>' |
555 arguments = '<application>' |
556 |
556 |
557 options = ( |
557 options = ( |
558 ("output", |
558 ("output", |
559 {'short': 'o', 'type' : "string", 'metavar' : '<file>', |
559 {'short': 'o', 'type' : "string", 'metavar' : '<file>', |
560 'default' : None, |
560 'default' : None, |
561 'help': 'Specify the backup file where the backup will be stored.'} |
561 'help': 'Specify the backup file where the backup will be stored.'} |
562 ), |
562 ), |
563 ('sudo', |
563 ('sudo', |
564 {'short': 's', 'action' : 'store_true', |
564 {'short': 's', 'action' : 'store_true', |
576 _local_dump(appid, self.config.output) |
576 _local_dump(appid, self.config.output) |
577 |
577 |
578 |
578 |
579 class DBRestoreCommand(Command): |
579 class DBRestoreCommand(Command): |
580 """Restore the system database of an application. |
580 """Restore the system database of an application. |
581 |
581 |
582 <application> |
582 <application> |
583 the identifier of the application to restore |
583 the identifier of the application to restore |
584 """ |
584 """ |
585 name = 'db-restore' |
585 name = 'db-restore' |
586 arguments = '<application> <backupfile>' |
586 arguments = '<application> <backupfile>' |
587 |
587 |
588 options = ( |
588 options = ( |
589 ("no-drop", |
589 ("no-drop", |
590 {'short': 'n', 'action' : 'store_true', |
590 {'short': 'n', 'action' : 'store_true', |
591 'default' : False, |
591 'default' : False, |
592 'help': 'for some reason the database doesn\'t exist and so ' |
592 'help': 'for some reason the database doesn\'t exist and so ' |
593 'should not be dropped.'} |
593 'should not be dropped.'} |
594 ), |
594 ), |
595 ) |
595 ) |
600 _local_restore(appid, backupfile, not self.config.no_drop) |
600 _local_restore(appid, backupfile, not self.config.no_drop) |
601 |
601 |
602 |
602 |
603 class DBCopyCommand(Command): |
603 class DBCopyCommand(Command): |
604 """Copy the system database of an application (backup and restore). |
604 """Copy the system database of an application (backup and restore). |
605 |
605 |
606 <src-application> |
606 <src-application> |
607 the identifier of the application to backup |
607 the identifier of the application to backup |
608 format [[user@]host:]appname |
608 format [[user@]host:]appname |
609 |
609 |
610 <dest-application> |
610 <dest-application> |
646 if self.config.keep_dump: |
646 if self.config.keep_dump: |
647 print 'you can get the dump file at', output |
647 print 'you can get the dump file at', output |
648 else: |
648 else: |
649 os.remove(output) |
649 os.remove(output) |
650 |
650 |
651 |
651 |
652 class CheckRepositoryCommand(Command): |
652 class CheckRepositoryCommand(Command): |
653 """Check integrity of the system database of an application. |
653 """Check integrity of the system database of an application. |
654 |
654 |
655 <application> |
655 <application> |
656 the identifier of the application to check |
656 the identifier of the application to check |
657 """ |
657 """ |
658 name = 'db-check' |
658 name = 'db-check' |
659 arguments = '<application>' |
659 arguments = '<application>' |
660 |
660 |
661 options = ( |
661 options = ( |
662 ("checks", |
662 ("checks", |
663 {'short': 'c', 'type' : "csv", 'metavar' : '<check list>', |
663 {'short': 'c', 'type' : "csv", 'metavar' : '<check list>', |
664 'default' : ('entities', 'relations', 'metadata', 'schema', 'text_index'), |
664 'default' : ('entities', 'relations', 'metadata', 'schema', 'text_index'), |
665 'help': 'Comma separated list of check to run. By default run all \ |
665 'help': 'Comma separated list of check to run. By default run all \ |
666 checks, i.e. entities, relations, text_index and metadata.'} |
666 checks, i.e. entities, relations, text_index and metadata.'} |
667 ), |
667 ), |
668 |
668 |
669 ("autofix", |
669 ("autofix", |
670 {'short': 'a', 'type' : "yn", 'metavar' : '<yes or no>', |
670 {'short': 'a', 'type' : "yn", 'metavar' : '<yes or no>', |
671 'default' : False, |
671 'default' : False, |
672 'help': 'Automatically correct integrity problems if this option \ |
672 'help': 'Automatically correct integrity problems if this option \ |
673 is set to "y" or "yes", else only display them'} |
673 is set to "y" or "yes", else only display them'} |
674 ), |
674 ), |
675 ("reindex", |
675 ("reindex", |
676 {'short': 'r', 'type' : "yn", 'metavar' : '<yes or no>', |
676 {'short': 'r', 'type' : "yn", 'metavar' : '<yes or no>', |
677 'default' : False, |
677 'default' : False, |
678 'help': 're-indexes the database for full text search if this \ |
678 'help': 're-indexes the database for full text search if this \ |
679 option is set to "y" or "yes" (may be long for large database).'} |
679 option is set to "y" or "yes" (may be long for large database).'} |
680 ), |
680 ), |
681 |
681 |
682 ) |
682 ) |
683 |
683 |
684 def run(self, args): |
684 def run(self, args): |
685 from cubicweb.server.checkintegrity import check |
685 from cubicweb.server.checkintegrity import check |
686 appid = pop_arg(args, 1, msg="No application specified !") |
686 appid = pop_arg(args, 1, msg="No application specified !") |
690 self.config.checks, self.config.reindex, self.config.autofix) |
690 self.config.checks, self.config.reindex, self.config.autofix) |
691 |
691 |
692 |
692 |
693 class RebuildFTICommand(Command): |
693 class RebuildFTICommand(Command): |
694 """Rebuild the full-text index of the system database of an application. |
694 """Rebuild the full-text index of the system database of an application. |
695 |
695 |
696 <application> |
696 <application> |
697 the identifier of the application to rebuild |
697 the identifier of the application to rebuild |
698 """ |
698 """ |
699 name = 'db-rebuild-fti' |
699 name = 'db-rebuild-fti' |
700 arguments = '<application>' |
700 arguments = '<application>' |
708 repo, cnx = repo_cnx(config) |
708 repo, cnx = repo_cnx(config) |
709 session = repo._get_session(cnx.sessionid, setpool=True) |
709 session = repo._get_session(cnx.sessionid, setpool=True) |
710 reindex_entities(repo.schema, session) |
710 reindex_entities(repo.schema, session) |
711 cnx.commit() |
711 cnx.commit() |
712 |
712 |
713 |
713 |
714 class SynchronizeApplicationSchemaCommand(Command): |
714 class SynchronizeApplicationSchemaCommand(Command): |
715 """Synchronize persistent schema with cube schema. |
715 """Synchronize persistent schema with cube schema. |
716 |
716 |
717 Will synchronize common stuff between the cube schema and the |
717 Will synchronize common stuff between the cube schema and the |
718 actual persistent schema, but will not add/remove any entity or relation. |
718 actual persistent schema, but will not add/remove any entity or relation. |
719 |
719 |
720 <application> |
720 <application> |
721 the identifier of the application to synchronize. |
721 the identifier of the application to synchronize. |
728 config = ServerConfiguration.config_for(appid) |
728 config = ServerConfiguration.config_for(appid) |
729 mih = config.migration_handler() |
729 mih = config.migration_handler() |
730 mih.cmd_synchronize_schema() |
730 mih.cmd_synchronize_schema() |
731 |
731 |
732 |
732 |
733 register_commands( (CreateApplicationDBCommand, |
733 register_commands( (CreateApplicationDBCommand, |
734 InitApplicationCommand, |
734 InitApplicationCommand, |
735 GrantUserOnApplicationCommand, |
735 GrantUserOnApplicationCommand, |
736 StartRepositoryCommand, |
736 StartRepositoryCommand, |
737 DBDumpCommand, |
737 DBDumpCommand, |
738 DBRestoreCommand, |
738 DBRestoreCommand, |