server/serverconfig.py
changeset 6427 c8a5ac2d1eaa
parent 6333 e3994fcc21c3
child 6478 8098e1295cf0
equal deleted inserted replaced
6426:541659c39f6a 6427:c8a5ac2d1eaa
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    18 """server.serverconfig definition"""
    18 """server.serverconfig definition"""
    19 
    19 
    20 __docformat__ = "restructuredtext en"
    20 __docformat__ = "restructuredtext en"
    21 
    21 
       
    22 import sys
    22 from os.path import join, exists
    23 from os.path import join, exists
    23 
    24 from StringIO import StringIO
    24 from logilab.common.configuration import REQUIRED, Method, Configuration, \
    25 
    25      ini_format_section
    26 import logilab.common.configuration as lgconfig
    26 from logilab.common.decorators import wproperty, cached
    27 from logilab.common.decorators import wproperty, cached
    27 
    28 
    28 from cubicweb.toolsutils import read_config, restrict_perms_to_user
    29 from cubicweb.toolsutils import read_config, restrict_perms_to_user
    29 from cubicweb.cwconfig import CubicWebConfiguration, merge_options
    30 from cubicweb.cwconfig import CubicWebConfiguration, merge_options
    30 from cubicweb.server import SOURCE_TYPES
    31 from cubicweb.server import SOURCE_TYPES
    36                'help': "cubicweb manager account's login "
    37                'help': "cubicweb manager account's login "
    37                '(this user will be created)',
    38                '(this user will be created)',
    38                'level': 0,
    39                'level': 0,
    39                }),
    40                }),
    40     ('password', {'type' : 'password',
    41     ('password', {'type' : 'password',
    41                   'default': REQUIRED,
    42                   'default': lgconfig.REQUIRED,
    42                   'help': "cubicweb manager account's password",
    43                   'help': "cubicweb manager account's password",
    43                   'level': 0,
    44                   'level': 0,
    44                   }),
    45                   }),
    45     )
    46     )
    46 
    47 
    47 class SourceConfiguration(Configuration):
    48 class SourceConfiguration(lgconfig.Configuration):
    48     def __init__(self, appconfig, options):
    49     def __init__(self, appconfig, options):
    49         self.appconfig = appconfig # has to be done before super call
    50         self.appconfig = appconfig # has to be done before super call
    50         super(SourceConfiguration, self).__init__(options=options)
    51         super(SourceConfiguration, self).__init__(options=options)
    51 
    52 
    52     # make Method('default_instance_id') usable in db option defs (in native.py)
    53     # make Method('default_instance_id') usable in db option defs (in native.py)
    53     def default_instance_id(self):
    54     def default_instance_id(self):
    54         return self.appconfig.appid
    55         return self.appconfig.appid
    55 
    56 
    56     def input_option(self, option, optdict, inputlevel):
    57     def input_option(self, option, optdict, inputlevel):
    57         if self['db-driver'] == 'sqlite':
    58         try:
    58             if option in ('db-user', 'db-password'):
    59             dbdriver = self['db-driver']
    59                 return
    60         except lgconfig.OptionError:
    60             if option == 'db-name':
    61             pass
    61                 optdict = optdict.copy()
    62         else:
    62                 optdict['help'] = 'path to the sqlite database'
    63             if dbdriver == 'sqlite':
    63                 optdict['default'] = join(self.appconfig.appdatahome,
    64                 if option in ('db-user', 'db-password'):
    64                                           self.appconfig.appid + '.sqlite')
    65                     return
       
    66                 if option == 'db-name':
       
    67                     optdict = optdict.copy()
       
    68                     optdict['help'] = 'path to the sqlite database'
       
    69                     optdict['default'] = join(self.appconfig.appdatahome,
       
    70                                               self.appconfig.appid + '.sqlite')
    65         super(SourceConfiguration, self).input_option(option, optdict, inputlevel)
    71         super(SourceConfiguration, self).input_option(option, optdict, inputlevel)
    66 
    72 
    67 
    73 
    68 def generate_sources_file(appconfig, sourcesfile, sourcescfg, keys=None):
    74 
    69     """serialize repository'sources configuration into a INI like file
    75 def ask_source_config(appconfig, type, inputlevel=0):
    70 
    76     options = SOURCE_TYPES[type].options
    71     the `keys` parameter may be used to sort sections
    77     sconfig = SourceConfiguration(appconfig, options=options)
    72     """
    78     sconfig.input_config(inputlevel=inputlevel)
    73     if keys is None:
    79     return sconfig
    74         keys = sourcescfg.keys()
    80 
    75     else:
    81 def generate_source_config(sconfig):
    76         for key in sourcescfg:
    82     """serialize a repository source configuration as text"""
    77             if not key in keys:
    83     stream = StringIO()
    78                 keys.append(key)
    84     optsbysect = list(sconfig.options_by_section())
    79     stream = open(sourcesfile, 'w')
    85     assert len(optsbysect) == 1, 'all options for a source should be in the same group'
    80     for uri in keys:
    86     lgconfig.ini_format(stream, optsbysect[0][1], sys.stdin.encoding)
    81         sconfig = sourcescfg[uri]
    87     return stream.getvalue()
    82         if isinstance(sconfig, dict):
       
    83             # get a Configuration object
       
    84             if uri == 'admin':
       
    85                 options = USER_OPTIONS
       
    86             else:
       
    87                 options = SOURCE_TYPES[sconfig['adapter']].options
       
    88             _sconfig = SourceConfiguration(appconfig, options=options)
       
    89             for attr, val in sconfig.items():
       
    90                 if attr == 'uri':
       
    91                     continue
       
    92                 if attr == 'adapter':
       
    93                     _sconfig.adapter = val
       
    94                 else:
       
    95                     _sconfig.set_option(attr, val)
       
    96             sconfig = _sconfig
       
    97         optsbysect = list(sconfig.options_by_section())
       
    98         assert len(optsbysect) == 1, 'all options for a source should be in the same group'
       
    99         ini_format_section(stream, uri, optsbysect[0][1])
       
   100         if hasattr(sconfig, 'adapter'):
       
   101             print >> stream
       
   102             print >> stream, '# adapter for this source (YOU SHOULD NOT CHANGE THIS)'
       
   103             print >> stream, 'adapter=%s' % sconfig.adapter
       
   104         print >> stream
       
   105 
    88 
   106 
    89 
   107 class ServerConfiguration(CubicWebConfiguration):
    90 class ServerConfiguration(CubicWebConfiguration):
   108     """standalone RQL server"""
    91     """standalone RQL server"""
   109     name = 'repository'
    92     name = 'repository'
   119           'help': 'host name if not correctly detectable through gethostname',
   102           'help': 'host name if not correctly detectable through gethostname',
   120           'group': 'main', 'level': 1,
   103           'group': 'main', 'level': 1,
   121           }),
   104           }),
   122         ('pid-file',
   105         ('pid-file',
   123          {'type' : 'string',
   106          {'type' : 'string',
   124           'default': Method('default_pid_file'),
   107           'default': lgconfig.Method('default_pid_file'),
   125           'help': 'repository\'s pid file',
   108           'help': 'repository\'s pid file',
   126           'group': 'main', 'level': 2,
   109           'group': 'main', 'level': 2,
   127           }),
   110           }),
   128         ('uid',
   111         ('uid',
   129          {'type' : 'string',
   112          {'type' : 'string',
   280         """return a dictionnaries containing sources definitions indexed by
   263         """return a dictionnaries containing sources definitions indexed by
   281         sources'uri
   264         sources'uri
   282         """
   265         """
   283         return self.read_sources_file()
   266         return self.read_sources_file()
   284 
   267 
   285     def source_enabled(self, uri):
   268     def source_enabled(self, source):
   286         return not self.enabled_sources or uri in self.enabled_sources
   269         if self.sources_mode is not None:
       
   270             if 'migration' in self.sources_mode:
       
   271                 assert len(self.sources_mode) == 1
       
   272                 if source.connect_for_migration:
       
   273                     return True
       
   274                 print 'not connecting to source', uri, 'during migration'
       
   275                 return False
       
   276             if 'all' in self.sources_mode:
       
   277                 assert len(self.sources_mode) == 1
       
   278                 return True
       
   279             return source.uri in self.sources_mode
       
   280         if self.quick_start:
       
   281             return False
       
   282         return (not source.disabled and (
       
   283             not self.enabled_sources or source.uri in self.enabled_sources))
   287 
   284 
   288     def write_sources_file(self, sourcescfg):
   285     def write_sources_file(self, sourcescfg):
       
   286         """serialize repository'sources configuration into a INI like file"""
   289         sourcesfile = self.sources_file()
   287         sourcesfile = self.sources_file()
   290         if exists(sourcesfile):
   288         if exists(sourcesfile):
   291             import shutil
   289             import shutil
   292             shutil.copy(sourcesfile, sourcesfile + '.bak')
   290             shutil.copy(sourcesfile, sourcesfile + '.bak')
   293         generate_sources_file(self, sourcesfile, sourcescfg,
   291         stream = open(sourcesfile, 'w')
   294                               ['admin', 'system'])
   292         for section in ('admin', 'system'):
       
   293             sconfig = sourcescfg[section]
       
   294             if isinstance(sconfig, dict):
       
   295                 # get a Configuration object
       
   296                 assert section == 'system'
       
   297                 _sconfig = SourceConfiguration(
       
   298                     self, options=SOURCE_TYPES['native'].options)
       
   299                 for attr, val in sconfig.items():
       
   300                     _sconfig.set_option(attr, val)
       
   301                 sconfig = _sconfig
       
   302             print >> stream, '[%s]' % section
       
   303             print >> stream, generate_source_config(sconfig)
       
   304             print >> stream
   295         restrict_perms_to_user(sourcesfile)
   305         restrict_perms_to_user(sourcesfile)
   296 
   306 
   297     def pyro_enabled(self):
   307     def pyro_enabled(self):
   298         """pyro is always enabled in standalone repository configuration"""
   308         """pyro is always enabled in standalone repository configuration"""
   299         return True
   309         return True
   316         from cubicweb.schema import BootstrapSchemaLoader
   326         from cubicweb.schema import BootstrapSchemaLoader
   317         schema = BootstrapSchemaLoader().load(self)
   327         schema = BootstrapSchemaLoader().load(self)
   318         schema.name = 'bootstrap'
   328         schema.name = 'bootstrap'
   319         return schema
   329         return schema
   320 
   330 
       
   331     sources_mode = None
   321     def set_sources_mode(self, sources):
   332     def set_sources_mode(self, sources):
   322         if 'migration' in sources:
   333         self.sources_mode = sources
   323             from cubicweb.server.sources import source_adapter
       
   324             assert len(sources) == 1
       
   325             enabled_sources = []
       
   326             for uri, config in self.sources().iteritems():
       
   327                 if uri == 'admin':
       
   328                     continue
       
   329                 if source_adapter(config).connect_for_migration:
       
   330                     enabled_sources.append(uri)
       
   331                 else:
       
   332                     print 'not connecting to source', uri, 'during migration'
       
   333         elif 'all' in sources:
       
   334             assert len(sources) == 1
       
   335             enabled_sources = None
       
   336         else:
       
   337             known_sources = self.sources()
       
   338             for uri in sources:
       
   339                 assert uri in known_sources, uri
       
   340             enabled_sources = sources
       
   341         self.enabled_sources = enabled_sources
       
   342 
   334 
   343     def migration_handler(self, schema=None, interactive=True,
   335     def migration_handler(self, schema=None, interactive=True,
   344                           cnx=None, repo=None, connect=True, verbosity=None):
   336                           cnx=None, repo=None, connect=True, verbosity=None):
   345         """return a migration handler instance"""
   337         """return a migration handler instance"""
   346         from cubicweb.server.migractions import ServerMigrationHelper
   338         from cubicweb.server.migractions import ServerMigrationHelper