vmm.cfg: dealt with the most overdue section/option renaming.
Added new options. Details:
old new
------------------------------------------------------------
domdir.mode -> domain.directory_mode
domdir.delete -> domain.delete_directory
domdir.base -> misc.base_dir
domdir -> _section domdir deleted_
maildir.mode -> account.directory_mode
maildir.diskusage -> account.disk_usage
maildir.delete -> account.delete_directory
misc.forcedel -> domain.force_del
misc.passwdscheme -> misc.password_scheme
misc.dovecotvers -> misc.dovecot_vers
services.smtp -> account.smtp
services.pop3 -> account.pop3
services.imap -> account.imap
services.sieve -> account.sieve
services -> _section services deleted_
_NEW_.random_password -> account.random_password
_NEW_.password_len -> account.password_len
_NEW_.auto_postmaster -> domain.auto_postmaster
# -*- coding: UTF-8 -*-
# Copyright (c) 2007 - 2010, Pascal Volk
# See COPYING for distribution information.
"""Configuration class for read, modify and write the
configuration from Virtual Mail Manager.
"""
from shutil import copy2
from ConfigParser import ConfigParser, MissingSectionHeaderError, ParsingError
from cStringIO import StringIO
from __main__ import ENCODING, ERR, w_std
from Exceptions import VMMConfigException
class Config(ConfigParser):
"""This class is for reading and modifying vmm's configuration file."""
def __init__(self, filename):
"""Creates a new Config instance
Arguments:
filename -- path to the configuration file
"""
ConfigParser.__init__(self)
self.__cfgFileName = filename
self.__cfgFile = None
self.__VMMsections = ('account', 'bin', 'database', 'domain',
'maildir', 'misc', 'config')
self.__changes = False
self.__missing = {}
self.__dbopts = [
['host', 'localhot'],
['user', 'vmm'],
['pass', 'your secret password'],
['name', 'mailsys']
]
self.__mdopts = [
['name', 'Maildir'],
['folders', 'Drafts:Sent:Templates:Trash'],
]
self.__accountopts = [
['delete_directory', 'false'],
['directory_mode', 448],
['disk_usage', 'false'],
['password_len', 8],
['random_password', 'false'],
['smtp', 'true'],
['pop3', 'true'],
['imap', 'true'],
['sieve', 'true']
]
self.__domdopts = [
['auto_postmaster', 'true'],
['delete_directory', 'false'],
['directory_mode', 504],
['force_del', 'false'],
]
self.__binopts = [
['dovecotpw', '/usr/sbin/dovecotpw'],
['du', '/usr/bin/du'],
['postconf', '/usr/sbin/postconf']
]
self.__miscopts = [
['base_dir', '/srv/mail'],
['dovecot_vers', '11'],
['gid_mail', 8],
['password_scheme', 'PLAIN'],
['transport', 'dovecot:'],
]
def load(self):
"""Loads the configuration, read only.
Raises a VMMConfigException if the configuration syntax is invalid.
"""
try:
self.__cfgFile = file(self.__cfgFileName, 'r')
self.readfp(self.__cfgFile)
except (MissingSectionHeaderError, ParsingError), e:
self.__cfgFile.close()
raise VMMConfigException(str(e), ERR.CONF_ERROR)
self.__cfgFile.close()
def check(self):
"""Performs a configuration check.
Raises a VMMConfigException if the check fails.
"""
if not self.__chkSections():
errmsg = StringIO()
errmsg.write(_("Using configuration file: %s\n") %\
self.__cfgFileName)
for k,v in self.__missing.items():
if v[0] is True:
errmsg.write(_(u"missing section: %s\n") % k)
else:
errmsg.write(_(u"missing options in section %s:\n") % k)
for o in v:
errmsg.write(" * %s\n" % o)
raise VMMConfigException(errmsg.getvalue(), ERR.CONF_ERROR)
def getsections(self):
"""Return a list with all configurable sections."""
return self.__VMMsections[:-1]
def get(self, section, option, raw=False, vars=None):
return unicode(ConfigParser.get(self, section, option, raw, vars),
ENCODING, 'replace')
def configure(self, sections):
"""Interactive method for configuring all options in the given sections
Arguments:
sections -- list of strings with section names
"""
if not isinstance(sections, list):
raise TypeError("Argument 'sections' is not a list.")
# if [config] done = false (default at 1st run),
# then set changes true
try:
if not self.getboolean('config', 'done'):
self.__changes = True
except ValueError:
self.set('config', 'done', 'False')
self.__changes = True
w_std(_(u'Using configuration file: %s\n') % self.__cfgFileName)
for s in sections:
if s != 'config':
w_std(_(u'* Config section: “%s”') % s )
for opt, val in self.items(s):
newval = raw_input(
_('Enter new value for option %(opt)s [%(val)s]: ').encode(
ENCODING, 'replace') % {'opt': opt, 'val': val})
if newval and newval != val:
self.set(s, opt, newval)
self.__changes = True
print
if self.__changes:
self.__saveChanges()
def __saveChanges(self):
"""Writes changes to the configuration file."""
self.set('config', 'done', 'true')
copy2(self.__cfgFileName, self.__cfgFileName+'.bak')
self.__cfgFile = file(self.__cfgFileName, 'w')
self.write(self.__cfgFile)
self.__cfgFile.close()
def __chkSections(self):
"""Checks if all configuration sections are existing."""
errors = False
for s in self.__VMMsections:
if not self.has_section(s):
self.__missing[s] = [True]
elif not self.__chkOptions(s):
errors = True
return not errors
def __chkOptions(self, section):
"""Checks if all configuration options in section are existing.
Arguments:
section -- the section to be checked
"""
retval = True
missing = []
if section == 'database':
opts = self.__dbopts
elif section == 'maildir':
opts = self.__mdopts
elif section == 'account':
opts = self.__accountopts
elif section == 'domain':
opts = self.__domdopts
elif section == 'bin':
opts = self.__binopts
elif section == 'misc':
opts = self.__miscopts
elif section == 'config':
opts = [['done', 'false']]
for o, v in opts:
if not self.has_option(section, o):
missing.append(o)
retval = False
if len(missing):
self.__missing[section] = missing
return retval