server/serverctl.py
branchtls-sprint
changeset 1469 ba9759972b52
parent 1263 01152fffd593
child 1682 36bd5cba09de
equal deleted inserted replaced
1468:500ca81a344a 1469:ba9759972b52
    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>
   613     name = 'db-copy'
   613     name = 'db-copy'
   614     arguments = '<src-application> <dest-application>'
   614     arguments = '<src-application> <dest-application>'
   615 
   615 
   616     options = (
   616     options = (
   617         ("no-drop",
   617         ("no-drop",
   618          {'short': 'n', 'action' : 'store_true', 
   618          {'short': 'n', 'action' : 'store_true',
   619           'default' : False,
   619           'default' : False,
   620           'help': 'For some reason the database doesn\'t exist and so '
   620           'help': 'For some reason the database doesn\'t exist and so '
   621           'should not be dropped.'}
   621           'should not be dropped.'}
   622          ),
   622          ),
   623         ("keep-dump",
   623         ("keep-dump",
   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,