80 else: |
84 else: |
81 raise ConfigValueError(_(u"Not a boolean: '%s'") % |
85 raise ConfigValueError(_(u"Not a boolean: '%s'") % |
82 get_unicode(value)) |
86 get_unicode(value)) |
83 |
87 |
84 def getboolean(self, section, option): |
88 def getboolean(self, section, option): |
85 """Returns the boolean value of the option, in the given section. |
89 """Returns the boolean value of the option, in the given |
|
90 section. |
86 |
91 |
87 For a boolean True, the value must be set to '1', 'on', 'yes', |
92 For a boolean True, the value must be set to '1', 'on', 'yes', |
88 'true' or True. For a boolean False, the value must set to '0', |
93 'true' or True. For a boolean False, the value must set to '0', |
89 'off', 'no', 'false' or False. |
94 'off', 'no', 'false' or False. |
90 If the option has another value assigned this method will raise a |
95 If the option has another value assigned this method will raise |
91 ValueError. |
96 a ValueError. |
|
97 |
92 """ |
98 """ |
93 # if the setting was modified it may be still a boolean value lets see |
99 # if the setting was modified it may be still a boolean value lets see |
94 tmp = self.get(section, option) |
100 tmp = self.get(section, option) |
95 if isinstance(tmp, bool): |
101 if isinstance(tmp, bool): |
96 return tmp |
102 return tmp |
97 if not tmp.lower() in self._boolean_states: |
103 if not tmp.lower() in self._boolean_states: |
98 raise ValueError, 'Not a boolean: %s' % tmp |
104 raise ValueError('Not a boolean: %s' % tmp) |
99 return self._boolean_states[tmp.lower()] |
105 return self._boolean_states[tmp.lower()] |
100 |
106 |
101 def _get_section_option(self, section_option): |
107 def _get_section_option(self, section_option): |
102 """splits ``section_option`` (section\ **.**\ option) in two parts |
108 """splits ``section_option`` (section.option) in two parts and |
103 and returns them as list ``[section, option]``, if: |
109 returns them as list ``[section, option]``, if: |
104 |
110 |
105 * it likes the format of ``section_option`` |
111 * it likes the format of ``section_option`` |
106 * the ``section`` is known |
112 * the ``section`` is known |
107 * the ``option`` is known |
113 * the ``option`` is known |
108 |
114 |
109 Else one of the following exceptions will be thrown: |
115 Else one of the following exceptions will be thrown: |
110 |
116 |
111 * `BadOptionError` |
117 * `BadOptionError` |
112 * `NoSectionError` |
118 * `NoSectionError` |
113 * `NoOptionError` |
119 * `NoOptionError` |
|
120 |
114 """ |
121 """ |
115 sect_opt = section_option.lower().split('.') |
122 sect_opt = section_option.lower().split('.') |
116 # TODO: cache it |
123 # TODO: cache it |
117 if len(sect_opt) != 2:# do we need a regexp to check the format? |
124 if len(sect_opt) != 2:# do we need a regexp to check the format? |
118 raise BadOptionError( |
125 raise BadOptionError( |
123 if not sect_opt[1] in self._cfg[sect_opt[0]]: |
130 if not sect_opt[1] in self._cfg[sect_opt[0]]: |
124 raise NoOptionError(sect_opt[1], sect_opt[0]) |
131 raise NoOptionError(sect_opt[1], sect_opt[0]) |
125 return sect_opt |
132 return sect_opt |
126 |
133 |
127 def items(self, section): |
134 def items(self, section): |
128 """returns an iterable that returns key, value ``tuples`` from the |
135 """returns an iterable that returns key, value ``tuples`` from |
129 given ``section``.""" |
136 the given ``section``. |
|
137 |
|
138 """ |
130 if section in self._sections:# check if the section was parsed |
139 if section in self._sections:# check if the section was parsed |
131 d2 = self._sections[section] |
140 sect = self._sections[section] |
132 elif not section in self._cfg: |
141 elif not section in self._cfg: |
133 raise NoSectionError(section) |
142 raise NoSectionError(section) |
134 else: |
143 else: |
135 return ((k, self._cfg[section][k].default) \ |
144 return ((k, self._cfg[section][k].default) \ |
136 for k in self._cfg[section].iterkeys()) |
145 for k in self._cfg[section].iterkeys()) |
137 # still here? Get defaults and merge defaults with configured setting |
146 # still here? Get defaults and merge defaults with configured setting |
138 d = dict((k, self._cfg[section][k].default) \ |
147 defaults = dict((k, self._cfg[section][k].default) \ |
139 for k in self._cfg[section].iterkeys()) |
148 for k in self._cfg[section].iterkeys()) |
140 d.update(d2) |
149 defaults.update(sect) |
141 if '__name__' in d: |
150 if '__name__' in defaults: |
142 del d['__name__'] |
151 del defaults['__name__'] |
143 return d.iteritems() |
152 return defaults.iteritems() |
144 |
153 |
145 def dget(self, option): |
154 def dget(self, option): |
146 """Returns the value of the `option`. |
155 """Returns the value of the `option`. |
147 |
156 |
148 If the option could not be found in the configuration file, the |
157 If the option could not be found in the configuration file, the |
273 |
291 |
274 Arguments: |
292 Arguments: |
275 |
293 |
276 `filename` : str |
294 `filename` : str |
277 path to the configuration file |
295 path to the configuration file |
|
296 |
278 """ |
297 """ |
279 LazyConfig.__init__(self) |
298 LazyConfig.__init__(self) |
280 self._cfgFileName = filename |
299 self._cfg_filename = filename |
281 self._cfgFile = None |
300 self._cfg_file = None |
282 self.__missing = {} |
301 self.__missing = {} |
283 |
302 |
284 LCO = LazyConfigOption |
303 LCO = LazyConfigOption |
285 bool_t = self.bool_new |
304 bool_t = self.bool_new |
286 self._cfg = { |
305 self._cfg = { |
287 'account': { |
306 'account': { |
288 'delete_directory': LCO(bool_t, False, self.getboolean), |
307 'delete_directory': LCO(bool_t, False, self.getboolean), |
289 'directory_mode': LCO(int, 448, self.getint), |
308 'directory_mode': LCO(int, 448, self.getint), |
290 'disk_usage': LCO(bool_t, False, self.getboolean), |
309 'disk_usage': LCO(bool_t, False, self.getboolean), |
291 'password_length': LCO(int, 8, self.getint), |
310 'password_length': LCO(int, 8, self.getint), |
292 'random_password': LCO(bool_t, False, self.getboolean), |
311 'random_password': LCO(bool_t, False, self.getboolean), |
293 'imap' : LCO(bool_t, True, self.getboolean), |
312 'imap': LCO(bool_t, True, self.getboolean), |
294 'pop3' : LCO(bool_t, True, self.getboolean), |
313 'pop3': LCO(bool_t, True, self.getboolean), |
295 'sieve': LCO(bool_t, True, self.getboolean), |
314 'sieve': LCO(bool_t, True, self.getboolean), |
296 'smtp' : LCO(bool_t, True, self.getboolean), |
315 'smtp': LCO(bool_t, True, self.getboolean), |
297 }, |
316 }, |
298 'bin': { |
317 'bin': { |
299 'dovecotpw': LCO(str, '/usr/sbin/dovecotpw', self.get, exec_ok), |
318 'dovecotpw': LCO(str, '/usr/sbin/dovecotpw', self.get, |
300 'du': LCO(str, '/usr/bin/du', self.get, exec_ok), |
319 exec_ok), |
301 'postconf': LCO(str, '/usr/sbin/postconf', self.get, exec_ok), |
320 'du': LCO(str, '/usr/bin/du', self.get, exec_ok), |
|
321 'postconf': LCO(str, '/usr/sbin/postconf', self.get, exec_ok), |
302 }, |
322 }, |
303 'database': { |
323 'database': { |
304 'host': LCO(str, 'localhost', self.get), |
324 'host': LCO(str, 'localhost', self.get), |
305 'name': LCO(str, 'mailsys', self.get), |
325 'name': LCO(str, 'mailsys', self.get), |
306 'pass': LCO(str, None, self.get), |
326 'pass': LCO(str, None, self.get), |
307 'user': LCO(str, None, self.get), |
327 'user': LCO(str, None, self.get), |
308 }, |
328 }, |
309 'domain': { |
329 'domain': { |
310 'auto_postmaster': LCO(bool_t, True, self.getboolean), |
330 'auto_postmaster': LCO(bool_t, True, self.getboolean), |
311 'delete_directory': LCO(bool_t, False, self.getboolean), |
331 'delete_directory': LCO(bool_t, False, self.getboolean), |
312 'directory_mode': LCO(int, 504, self.getint), |
332 'directory_mode': LCO(int, 504, self.getint), |
313 'force_deletion': LCO(bool_t, False, self.getboolean), |
333 'force_deletion': LCO(bool_t, False, self.getboolean), |
314 }, |
334 }, |
315 'maildir': { |
335 'maildir': { |
316 'folders': LCO(str, 'Drafts:Sent:Templates:Trash', self.get), |
336 'folders': LCO(str, 'Drafts:Sent:Templates:Trash', self.get), |
317 'name': LCO(str, 'Maildir', self.get), |
337 'name': LCO(str, 'Maildir', self.get), |
318 }, |
338 }, |
319 'misc': { |
339 'misc': { |
320 'base_directory': LCO(str, '/srv/mail', self.get, is_dir), |
340 'base_directory': LCO(str, '/srv/mail', self.get, is_dir), |
321 'dovecot_version': LCO(int, 12, self.getint), |
341 'dovecot_version': LCO(int, 12, self.getint), |
322 'gid_mail': LCO(int, 8, self.getint), |
342 'gid_mail': LCO(int, 8, self.getint), |
323 'password_scheme': LCO(str, 'CRAM-MD5', self.get, |
343 'password_scheme': LCO(str, 'CRAM-MD5', self.get, |
324 self.known_scheme), |
344 self.known_scheme), |
325 'transport': LCO(str, 'dovecot:', self.get), |
345 'transport': LCO(str, 'dovecot:', self.get), |
326 }, |
346 }, |
327 } |
347 } |
328 |
|
329 def configure(self, sections): |
|
330 raise NotImplementedError |
|
331 |
348 |
332 def load(self): |
349 def load(self): |
333 """Loads the configuration, read only. |
350 """Loads the configuration, read only. |
334 |
351 |
335 Raises a VMMConfigException if the configuration syntax is invalid. |
352 Raises a VMMConfigException if the configuration syntax is |
|
353 invalid. |
|
354 |
336 """ |
355 """ |
337 try: |
356 try: |
338 self._cfgFile = open(self._cfgFileName, 'r') |
357 self._cfg_file = open(self._cfg_filename, 'r') |
339 self.readfp(self._cfgFile) |
358 self.readfp(self._cfg_file) |
340 except (MissingSectionHeaderError, ParsingError), e: |
359 except (MissingSectionHeaderError, ParsingError), err: |
341 raise VMMConfigException(str(e), CONF_ERROR) |
360 raise VMMConfigException(str(err), CONF_ERROR) |
342 finally: |
361 finally: |
343 if self._cfgFile and not self._cfgFile.closed: |
362 if self._cfg_file and not self._cfg_file.closed: |
344 self._cfgFile.close() |
363 self._cfg_file.close() |
345 |
364 |
346 def check(self): |
365 def check(self): |
347 """Performs a configuration check. |
366 """Performs a configuration check. |
348 |
367 |
349 Raises a VMMConfigException if the check fails. |
368 Raises a VMMConfigException if the check fails. |
|
369 |
350 """ |
370 """ |
351 # TODO: There are only two settings w/o defaults. |
371 # TODO: There are only two settings w/o defaults. |
352 # So there is no need for cStringIO |
372 # So there is no need for cStringIO |
353 if not self.__chkCfg(): |
373 if not self.__chk_cfg(): |
354 errmsg = StringIO() |
374 errmsg = StringIO() |
355 errmsg.write(_(u'Missing options, which have no default value.\n')) |
375 errmsg.write(_(u'Missing options, which have no default value.\n')) |
356 errmsg.write(_(u'Using configuration file: %s\n') % |
376 errmsg.write(_(u'Using configuration file: %s\n') % |
357 self._cfgFileName) |
377 self._cfg_filename) |
358 for section, options in self.__missing.iteritems(): |
378 for section, options in self.__missing.iteritems(): |
359 errmsg.write(_(u'* Section: %s\n') % section) |
379 errmsg.write(_(u'* Section: %s\n') % section) |
360 for option in options: |
380 for option in options: |
361 errmsg.write((u' %s\n') % option) |
381 errmsg.write((u' %s\n') % option) |
362 raise VMMConfigException(errmsg.getvalue(), CONF_ERROR) |
382 raise VMMConfigException(errmsg.getvalue(), CONF_ERROR) |
365 """Converts `scheme` to upper case and checks if is known by |
385 """Converts `scheme` to upper case and checks if is known by |
366 Dovecot (listed in VirtualMailManager.SCHEMES). |
386 Dovecot (listed in VirtualMailManager.SCHEMES). |
367 |
387 |
368 Throws a `ConfigValueError` if the scheme is not listed in |
388 Throws a `ConfigValueError` if the scheme is not listed in |
369 VirtualMailManager.SCHEMES. |
389 VirtualMailManager.SCHEMES. |
|
390 |
370 """ |
391 """ |
371 scheme = scheme.upper() |
392 scheme = scheme.upper() |
372 # TODO: VMM.SCHEMES |
393 # TODO: VMM.SCHEMES |
373 |
394 |
374 def unicode(self, section, option): |
395 def unicode(self, section, option): |
375 """Returns the value of the `option` from `section`, converted to |
396 """Returns the value of the `option` from `section`, converted |
376 Unicode.""" |
397 to Unicode. |
|
398 |
|
399 """ |
377 return get_unicode(self.get(section, option)) |
400 return get_unicode(self.get(section, option)) |
378 |
401 |
379 def __chkCfg(self): |
402 def __chk_cfg(self): |
380 """Checks all section's options for settings w/o a default value. |
403 """Checks all section's options for settings w/o a default |
381 |
404 value. |
382 Returns `True` if everything is fine, else `False`.""" |
405 |
|
406 Returns `True` if everything is fine, else `False`. |
|
407 |
|
408 """ |
383 errors = False |
409 errors = False |
384 for section in self._cfg.iterkeys(): |
410 for section in self._cfg.iterkeys(): |
385 missing = [] |
411 missing = [] |
386 for option, value in self._cfg[section].iteritems(): |
412 for option, value in self._cfg[section].iteritems(): |
387 if (value.default is None and |
413 if (value.default is None and |
388 not RawConfigParser.has_option(self, section, option)): |
414 not RawConfigParser.has_option(self, section, option)): |
389 missing.append(option) |
415 missing.append(option) |
390 errors = True |
416 errors = True |
391 if missing: |
417 if missing: |
392 self.__missing[section] = missing |
418 self.__missing[section] = missing |
393 return not errors |
419 return not errors |
|
420 |
|
421 |
|
422 del _ |