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' |
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 |