1
0
Fork 0
gnuviechadmin-historic/gnuviechadmin/backend/domain.py

325 lines
14 KiB
Python

# -*- python -*-
# -*- coding: utf-8 -*-
#
# Copyright (C) 2007, 2008 by Jan Dittberner.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
# Version: $Id: client.py 1101 2007-02-28 21:15:20Z jan $
import datetime, os
from gnuviechadmin.exceptions import *
from settings import *
from BackendTo import Record, Domain
from BackendEntity import BackendEntity
from BackendEntityHandler import BackendEntityHandler
class DomainEntity(BackendEntity):
"""Entity class for DNS domains."""
_valid_domain_types = ("MASTER", "SLAVE")
def __init__(self, delegate, verbose = False, **kwargs):
BackendEntity.__init__(self, delegate, verbose)
self.ns1 = None
self.ns2 = None
self.mx = None
self.ipaddr = None
for (key, value) in kwargs.items():
self.__setattr__(key, value)
if not self.delegateto.type:
self.delegateto.type = self.getdefaultdomaintype()
if not self.ns1:
self.ns1 = config.get('domain', 'defaultns1')
if not self.ns2:
self.ns2 = config.get('domain', 'defaultns2')
if not self.mx:
self.mx = config.get('domain', 'defaultmx')
if not self.ipaddr:
self.ipaddr = config.get('domain', 'defaultip')
self.delegateto.type = self.delegateto.type.upper()
self.validate()
def getdefaultdomaintype(self):
return self._valid_domain_types[0]
def validate(self):
BackendEntity.validate(self)
if not self.delegateto.type in self._valid_domain_types:
raise ValidationFailedError(
self, "invalid domain type %s" % (self.delegateto.type))
if self.delegateto.type == 'SLAVE' and not self.delegateto.master:
raise ValidationFailedError(
self, "you have to specify a master for slave domains.")
if self.delegateto.type == 'MASTER':
if not self.ns1 or not self.ns2:
raise ValidationFailedError(
self, "two nameservers must be specified.")
if not self.mx:
raise ValidationFailedError(
self, "a primary mx host must be specified.")
def _getnewserial(self, oldserial = None):
current = datetime.datetime.now()
datepart = "%04d%02d%02d" % \
(current.year, current.month, current.day)
retval = None
if oldserial:
if str(oldserial)[:len(datepart)] == datepart:
retval = oldserial + 1
if not retval:
retval = int("%s01" % (datepart))
return retval
def _getnewsoa(self):
return '%s %s %d %d %d %d %d' % \
(self.ns1,
config.get('domain', 'defaulthostmaster'),
self._getnewserial(),
config.getint('domain', 'defaultrefresh'),
config.getint('domain', 'defaultretry'),
config.getint('domain', 'defaultexpire'),
config.getint('domain', 'defaultminimumttl'))
def update_serial(self, session):
query = session.query(Record)
soarecord = query.get_by(Record.c.type == 'SOA',
Record.c.domainid == self.delegateto.domainid)
parts = soarecord.content.split(" ")
parts[2] = str(self._getnewserial(int(parts[2])))
soarecord.content = " ".join(parts)
session.save(soarecord)
session.flush()
def _get_vhost_dir(self):
return os.path.join(self.delegateto.sysuser.home,
self.delegateto.name,
config.get('domain', 'htdir'))
def _get_log_dir(self):
return os.path.join(config.get('domain', 'logpath'),
self.delegateto.name)
def _get_stats_dir(self):
return os.path.join(config.get('domain', 'statspath'),
self.delegateto.name)
def _create_vhost_dir(self):
vhostdir = self._get_vhost_dir()
self.logger.debug("creating virtual host dir %s" % (vhostdir))
cmd = 'mkdir -p "%s"' % (vhostdir)
self.sucommand(cmd)
for tpl in [tpl for tpl in os.listdir(
get_template_dir(config.get('domain', 'htdocstemplate'))) \
if not tpl.startswith('.')]:
self.logger.debug("processing template %s" % (tpl))
template = get_template(config.get('domain', 'htdocstemplate'),
tpl)
template = template.substitute({
'domain' : self.delegateto.name})
self.write_to_file(os.path.join(vhostdir, tpl), template)
cmd = 'chown -R %(username)s:%(group)s "%(dir)s"' % {
'username' : self.delegateto.sysuser.username,
'group' : config.get('sysuser', 'defaultgroup'),
'dir' : vhostdir}
self.sucommand(cmd)
def _create_log_dir(self):
cmd = 'mkdir -p "%s"' % (self._get_log_dir())
self.sucommand(cmd)
def _get_auth_userfile(self):
authdir = config.get('domain', 'authdir')
if not os.path.isdir(authdir):
cmd = 'mkdir -p "%s"' % (authdir)
self.sucommand(cmd)
return os.path.join(authdir, '%s.passwd' % (self.delegateto.name))
def _create_stats_dir(self):
"""Creates the statistics directory for the domain and sets
Apache .htaccess password protection."""
statsdir = self._get_stats_dir()
authfile = self._get_auth_userfile()
cmd = 'htpasswd -m -c -b "%s" "%s" "%s"' % (
authfile,
self.delegateto.sysuser.username,
self.delegateto.sysuser.clearpass)
self.sucommand(cmd)
cmd = 'mkdir -p "%s"' % (statsdir)
self.sucommand(cmd)
template = get_template(config.get('domain', 'conftemplates'),
config.get('domain', 'statshtaccesstemplate'))
template = template.substitute({
'domain' : self.delegateto.name,
'userfile' : authfile})
self.write_to_file(os.path.join(self._get_stats_dir(),
'.htaccess'), template)
def _create_stats_conf(self):
modlogandir = os.path.join(config.get('domain',
'modlogandir'),
self.delegateto.sysuser.username)
cmd = 'mkdir -p "%s"' % (modlogandir)
self.sucommand(cmd)
template = get_template(config.get('domain', 'conftemplates'),
config.get('domain', 'modlogantemplate'))
template = template.substitute({
'statsdir' : self._get_stats_dir(),
'logdir' : self._get_log_dir(),
'domain' : self.delegateto.name,
'domainesc' : self.delegateto.name.replace('.', '\.')})
self.write_to_file(os.path.join(modlogandir,
self.delegateto.name + '.conf'),
template)
def _create_apache_conf(self):
template = get_template(config.get('domain', 'conftemplates'),
config.get('domain', 'apachetemplate'))
template = template.substitute({
'ipaddr' : self.ipaddr,
'statsdir' : self._get_stats_dir(),
'logdir' : self._get_log_dir(),
'domain' : self.delegateto.name,
'docroot' : self._get_vhost_dir()})
self.write_to_file(os.path.join(config.get('domain', 'sitesdir'),
self.delegateto.name), template)
def _mail_domain(self):
template = get_template(config.get('common', 'mailtemplates'),
config.get('domain', 'create.mail'))
text = template.substitute({
'sysuser' : self.delegateto.sysuser.username,
'domain' : self.delegateto.name,
'docroot' : self._get_vhost_dir(),
'statspass' : self.delegateto.sysuser.clearpass})
template = get_template_string(config.get('domain', 'create_subject'))
subject = template.substitute({
'domain' : self.delegateto.name})
self.send_mail(subject, text)
def create_hook(self, session):
self.delegateto.records.append(Record(
name = self.delegateto.name, type = 'SOA',
content = self._getnewsoa(),
ttl = config.getint('domain', 'defaultttl')))
self.delegateto.records.append(Record(
name = self.delegateto.name, type = 'NS', content = self.ns1,
ttl = config.getint('domain', 'defaultttl')))
self.delegateto.records.append(Record(
name = self.delegateto.name, type = 'NS', content = self.ns2,
ttl = config.getint('domain', 'defaultttl')))
self.delegateto.records.append(Record(
name = self.delegateto.name, type = 'MX', content = self.mx,
ttl = config.getint('domain', 'defaultttl'),
prio = config.getint('domain', 'defaultmxprio')))
self.delegateto.records.append(Record(
name = self.delegateto.name, type = 'A', content = self.ipaddr,
ttl = config.getint('domain', 'defaultttl')))
self.delegateto.records.append(Record(
name = "www.%s" % (self.delegateto.name), type = 'A',
content = self.ipaddr,
ttl = config.getint('domain', 'defaultttl')))
session.save_or_update(self.delegateto)
session.flush()
self._create_vhost_dir()
self._create_log_dir()
self._create_stats_dir()
self._create_stats_conf()
self._create_apache_conf()
self._mail_domain()
def _delete_apache_conf(self):
cmd = 'a2dissite %s' % (self.delegateto.name)
self.sucommand(cmd)
cmd = 'rm "%s"' % (os.path.join(config.get('domain', 'sitesdir'),
self.delegateto.name))
self.sucommand(cmd)
def _delete_stats_conf(self):
cmd = 'rm "%s"' % (os.path.join(config.get('domain', 'modlogandir'),
self.delegateto.sysuser.username,
self.delegateto.name + '.conf'))
self.sucommand(cmd)
def _archive_stats_dir(self):
archive = os.path.join(self.delegateto.sysuser.home,
'%(domain)s-stats.tar.gz' % {
'domain' : self.delegateto.name})
cmd = 'tar czf "%(archive)s" --directory="%(statsbase)s" "%(statsdir)s"' % {
'archive' : archive,
'statsbase' : config.get('domain', 'statspath'),
'statsdir' : self.delegateto.name}
self.sucommand(cmd)
cmd = 'rm -r "%(statsdir)s"' % {
'statsdir' : self._get_stats_dir()}
self.sucommand(cmd)
cmd = 'chown "%(username)s:%(group)s" "%(archive)s"' % {
'username' : self.delegateto.sysuser.username,
'group' : config.get('sysuser', 'defaultgroup'),
'archive' : archive}
self.sucommand(cmd)
def _archive_log_dir(self):
archive = os.path.join(self.delegateto.sysuser.home,
'%(domain)s-logs.tar.gz' % {
'domain' : self.delegateto.name})
cmd = 'tar czf "%(archive)s" --directory="%(logbase)s" "%(logdir)s"' % {
'archive' : archive,
'logbase' : config.get('domain', 'logpath'),
'logdir' : self.delegateto.name}
self.sucommand(cmd)
cmd = 'rm -r "%(logdir)s"' % {
'logdir' : self._get_log_dir()}
self.sucommand(cmd)
cmd = 'chown "%(username)s:%(group)s" "%(archive)s"' % {
'username' : self.delegateto.sysuser.username,
'group' : config.get('sysuser', 'defaultgroup'),
'archive' : archive}
self.sucommand(cmd)
def _archive_vhost_dir(self):
archive = os.path.join(self.delegateto.sysuser.home,
'%(domain)s-vhost.tar.gz' % {
'domain' : self.delegateto.name})
cmd = 'tar czf "%(archive)s" --directory="%(vhostbase)s" "%(vhostdir)s"' % {
'archive' : archive,
'vhostbase' : self.delegateto.sysuser.home,
'vhostdir' : self.delegateto.name}
self.sucommand(cmd)
cmd = 'rm -r "%(vhostdir)s"' % {
'vhostdir' : os.path.join(self.delegateto.sysuser.home,
self.delegateto.name)}
self.sucommand(cmd)
cmd = 'chown "%(username)s:%(group)s" "%(archive)s"' % {
'username' : self.delegateto.sysuser.username,
'group' : config.get('sysuser', 'defaultgroup'),
'archive' : archive}
self.sucommand(cmd)
def delete_hook(self, session):
self._delete_apache_conf()
self._delete_stats_conf()
self._archive_stats_dir()
self._archive_log_dir()
self._archive_vhost_dir()
class DomainHandler(BackendEntityHandler):
"""BackendEntityHandler for Domain entities."""
def __init__(self, verbose = False):
BackendEntityHandler.__init__(self, DomainEntity, Domain, verbose)