add PasteDeploy dependency, remove pudge dependency
* upgrade migrate repository structure (fixes #32, #27) * switch to PasteDeploy (fixes #31) * update for SQLAlchemy 0.5 compatibility * add python-gnutls dependency (addresses #35)
This commit is contained in:
parent
483c1f9038
commit
222b35b033
24 changed files with 247 additions and 177 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
||||||
*.pyc
|
*.pyc
|
||||||
*.egg/
|
*.egg/
|
||||||
*.log
|
*.log
|
||||||
|
gva.db
|
||||||
|
|
50
bin/gva
50
bin/gva
|
@ -21,42 +21,20 @@
|
||||||
#
|
#
|
||||||
# Version: $Id$
|
# Version: $Id$
|
||||||
|
|
||||||
import gnuviechadmin.cli.client
|
from paste.deploy import appconfig
|
||||||
import gnuviechadmin.cli.sysuser
|
from sys import argv
|
||||||
import gnuviechadmin.cli.domain
|
from os import getcwd
|
||||||
import gnuviechadmin.cli.record
|
from os.path import isfile
|
||||||
import sys, os, logging.config
|
from logging.config import fileConfig
|
||||||
|
from gnuviechadmin.cli import CommandLineInterface
|
||||||
|
|
||||||
logcfgs = ('gnuviechadmin/logging.cfg', '/etc/gnuviechadmin/logging.cfg',
|
if len(argv) > 1 and isfile(argv[1]):
|
||||||
os.path.expanduser('~/.gva-logging.cfg'))
|
configfile = argv[1]
|
||||||
for cfg in [x for x in logcfgs if os.path.exists(x)]:
|
del argv[1]
|
||||||
logging.config.fileConfig(cfg)
|
else:
|
||||||
|
configfile = 'development.ini'
|
||||||
|
|
||||||
commands = [gnuviechadmin.cli.client.ClientCli,
|
config = appconfig('config:%s' % configfile, relative_to=getcwd())
|
||||||
gnuviechadmin.cli.sysuser.SysuserCli,
|
fileConfig(configfile, config)
|
||||||
gnuviechadmin.cli.domain.DomainCli,
|
|
||||||
gnuviechadmin.cli.record.RecordCli]
|
|
||||||
|
|
||||||
def usage():
|
CommandLineInterface(config, argv).run()
|
||||||
print """%s <command> [commandargs]
|
|
||||||
|
|
||||||
where command is one of
|
|
||||||
""" % sys.argv[0]
|
|
||||||
for command in commands:
|
|
||||||
print "%10s - %s" % (command.name, command.description)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if (sys.argv.__len__() < 2):
|
|
||||||
usage()
|
|
||||||
sys.exit()
|
|
||||||
command = sys.argv[1]
|
|
||||||
commargs = sys.argv[2:]
|
|
||||||
if command in [cmd.name for cmd in commands]:
|
|
||||||
for cmd in commands:
|
|
||||||
if cmd.name == command:
|
|
||||||
cmd(commargs)
|
|
||||||
else:
|
|
||||||
usage()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
62
development.ini
Normal file
62
development.ini
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
[DEFAULT]
|
||||||
|
mailfrom = gva@gnuviech.info
|
||||||
|
mailto = jan@dittberner.info
|
||||||
|
|
||||||
|
suwrapper = sudo
|
||||||
|
backupdir = /var/backups/gnuviechadmin
|
||||||
|
|
||||||
|
[app:main]
|
||||||
|
use = egg:gnuviechadmin#cli
|
||||||
|
|
||||||
|
# The database connection string in a format usable for
|
||||||
|
# sqlalchemy. The default is an sqlite in memory database which is not
|
||||||
|
# very usable for a real installation.
|
||||||
|
#
|
||||||
|
sqlalchemy.uri = sqlite:///%(here)s/gva.db
|
||||||
|
sqlalchemy.echo = false
|
||||||
|
|
||||||
|
database.repository = %(here)s/data/dbrepo
|
||||||
|
migrate.required_version = 3
|
||||||
|
templatedir = %(here)s/data/templates
|
||||||
|
mailtemplates = %(templatedir)s/mails
|
||||||
|
|
||||||
|
client.defaultcountry = de
|
||||||
|
client.create.mail = create_client.txt
|
||||||
|
client.create_subject = A new client ${firstname} ${lastname} has been created.
|
||||||
|
|
||||||
|
# Logging configuration
|
||||||
|
[loggers]
|
||||||
|
keys = root, gnuviechadmin, sqlalchemy
|
||||||
|
|
||||||
|
[handlers]
|
||||||
|
keys = console
|
||||||
|
|
||||||
|
[formatters]
|
||||||
|
keys = generic
|
||||||
|
|
||||||
|
[logger_root]
|
||||||
|
level = INFO
|
||||||
|
handlers = console
|
||||||
|
|
||||||
|
[logger_gnuviechadmin]
|
||||||
|
level = DEBUG
|
||||||
|
handlers =
|
||||||
|
qualname = gnuviechadmin
|
||||||
|
|
||||||
|
[logger_sqlalchemy]
|
||||||
|
level = WARN
|
||||||
|
handlers =
|
||||||
|
qualname = sqlalchemy.engine
|
||||||
|
# "level = INFO" logs SQL queries.
|
||||||
|
# "level = DEBUG" logs SQL queries and results.
|
||||||
|
# "level = WARN" logs neither. (Recommended for production systems.)
|
||||||
|
|
||||||
|
[handler_console]
|
||||||
|
class = StreamHandler
|
||||||
|
args = (sys.stderr,)
|
||||||
|
level = NOTSET
|
||||||
|
formatter = generic
|
||||||
|
|
||||||
|
[formatter_generic]
|
||||||
|
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
|
||||||
|
datefmt = %H:%M:%S
|
|
@ -1,6 +1,6 @@
|
||||||
Metadata-Version: 1.0
|
Metadata-Version: 1.0
|
||||||
Name: gnuviechadmin
|
Name: gnuviechadmin
|
||||||
Version: 0.1.dev-20090718
|
Version: 0.1.dev-20090719
|
||||||
Summary: gnuviechadmin server administration suite
|
Summary: gnuviechadmin server administration suite
|
||||||
Home-page: http://www.gnuviech-server.de/projects/gnuviechadmin
|
Home-page: http://www.gnuviech-server.de/projects/gnuviechadmin
|
||||||
Author: Jan Dittberner
|
Author: Jan Dittberner
|
||||||
|
|
|
@ -7,6 +7,7 @@ gnuviechadmin/exceptions.py
|
||||||
gnuviechadmin.egg-info/PKG-INFO
|
gnuviechadmin.egg-info/PKG-INFO
|
||||||
gnuviechadmin.egg-info/SOURCES.txt
|
gnuviechadmin.egg-info/SOURCES.txt
|
||||||
gnuviechadmin.egg-info/dependency_links.txt
|
gnuviechadmin.egg-info/dependency_links.txt
|
||||||
|
gnuviechadmin.egg-info/entry_points.txt
|
||||||
gnuviechadmin.egg-info/requires.txt
|
gnuviechadmin.egg-info/requires.txt
|
||||||
gnuviechadmin.egg-info/top_level.txt
|
gnuviechadmin.egg-info/top_level.txt
|
||||||
gnuviechadmin/backend/BackendEntity.py
|
gnuviechadmin/backend/BackendEntity.py
|
||||||
|
|
3
gnuviechadmin.egg-info/entry_points.txt
Normal file
3
gnuviechadmin.egg-info/entry_points.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
[paste.app_factory]
|
||||||
|
cli = gnuviechadmin.cli.client
|
|
@ -1,3 +1,5 @@
|
||||||
SQLAlchemy>=0.5
|
SQLAlchemy>=0.5
|
||||||
sqlalchemy-migrate>=0.5
|
sqlalchemy-migrate>=0.5
|
||||||
AuthKit>=0.4
|
AuthKit>=0.4
|
||||||
|
PasteDeploy>=1.3.3
|
||||||
|
python-gnutls>=1.1
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,7 +25,6 @@ import logging
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from gnuviechadmin.exceptions import MissingFieldsError
|
from gnuviechadmin.exceptions import MissingFieldsError
|
||||||
from gnuviechadmin.backend.settings import config
|
|
||||||
from gnuviechadmin.util import gpgmail
|
from gnuviechadmin.util import gpgmail
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
from sqlalchemy.orm import object_mapper
|
from sqlalchemy.orm import object_mapper
|
||||||
|
@ -34,9 +33,10 @@ from sqlalchemy.orm import object_mapper
|
||||||
class BackendEntity(object):
|
class BackendEntity(object):
|
||||||
"""This is the abstract base class for all backend entity classes."""
|
"""This is the abstract base class for all backend entity classes."""
|
||||||
|
|
||||||
def __init__(self, delegateto, verbose = False):
|
def __init__(self, config, delegateto, verbose = False):
|
||||||
self.logger = logging.getLogger("%s.%s" % (
|
self.logger = logging.getLogger("%s.%s" % (
|
||||||
self.__class__.__module__, self.__class__.__name__))
|
self.__class__.__module__, self.__class__.__name__))
|
||||||
|
self.config = config
|
||||||
self.delegateto = delegateto
|
self.delegateto = delegateto
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class BackendEntity(object):
|
||||||
subprocess."""
|
subprocess."""
|
||||||
self.logger.debug("sucommand called: %s (pipedata=%s)", cmdline,
|
self.logger.debug("sucommand called: %s (pipedata=%s)", cmdline,
|
||||||
str(pipedata))
|
str(pipedata))
|
||||||
suwrapper = config.get('common', 'suwrapper')
|
suwrapper = self.config['suwrapper']
|
||||||
toexec = "%s %s" % (suwrapper, cmdline)
|
toexec = "%s %s" % (suwrapper, cmdline)
|
||||||
if pipedata:
|
if pipedata:
|
||||||
pipeproc = Popen(toexec, shell = True, stdin=PIPE)
|
pipeproc = Popen(toexec, shell = True, stdin=PIPE)
|
||||||
|
@ -72,7 +72,7 @@ class BackendEntity(object):
|
||||||
"""Executes multiple commands as root and pipes the output of
|
"""Executes multiple commands as root and pipes the output of
|
||||||
the commands to the input of the next commands."""
|
the commands to the input of the next commands."""
|
||||||
self.logger.debug("supipe called: %s", " | ".join(cmdlines))
|
self.logger.debug("supipe called: %s", " | ".join(cmdlines))
|
||||||
suwrapper = config.get('common', 'suwrapper')
|
suwrapper = self.config['suwrapper']
|
||||||
predecessor = None
|
predecessor = None
|
||||||
for cmdline in cmdlines:
|
for cmdline in cmdlines:
|
||||||
toexec = "%s %s" % (suwrapper, cmdline)
|
toexec = "%s %s" % (suwrapper, cmdline)
|
||||||
|
@ -89,7 +89,7 @@ class BackendEntity(object):
|
||||||
"""This method sends a mail with the given text and subject
|
"""This method sends a mail with the given text and subject
|
||||||
and signs it usign GnuPG. If a public key of the recipient is
|
and signs it usign GnuPG. If a public key of the recipient is
|
||||||
available the mail is encrypted."""
|
available the mail is encrypted."""
|
||||||
gpgmail.send_mail(subject, text)
|
gpgmail.send_mail(self.config, subject, text)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
"""Validates whether all mandatory fields of the entity have
|
"""Validates whether all mandatory fields of the entity have
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -21,38 +21,41 @@
|
||||||
"""This module defines the BackendEntityHandler class."""
|
"""This module defines the BackendEntityHandler class."""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from sqlalchemy.orm import create_session
|
from sqlalchemy.orm import create_session, mapper, relation
|
||||||
|
from gnuviechadmin.backend.tables import dbsetup
|
||||||
|
|
||||||
|
|
||||||
class BackendEntityHandler(object):
|
class BackendEntityHandler(object):
|
||||||
"""This class is a handler for BackendEntity instances."""
|
"""This class is a handler for BackendEntity instances."""
|
||||||
|
|
||||||
def __init__(self, entityclass, toclass, verbose = False):
|
def __init__(self, entityclass, toclass, config, verbose = False):
|
||||||
"""Initialize the handler with a specific entity class,
|
"""Initialize the handler with a specific entity class,
|
||||||
transfer object class and verbosity flag."""
|
transfer object class and verbosity flag."""
|
||||||
self.logger = logging.getLogger("%s.%s" % (
|
self.logger = logging.getLogger("%s.%s" % (
|
||||||
self.__class__.__module__, self.__class__.__name__))
|
self.__class__.__module__, self.__class__.__name__))
|
||||||
|
dbsetup(config)
|
||||||
|
|
||||||
self.entityclass = entityclass
|
self.entityclass = entityclass
|
||||||
self.toclass = toclass
|
self.toclass = toclass
|
||||||
|
self.config = config
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
|
|
||||||
def create(self, **kwargs):
|
def create(self, **kwargs):
|
||||||
"""Create a new entity of the managed type with the fields set
|
"""Create a new entity of the managed type with the fields set
|
||||||
to the values in kwargs."""
|
to the values in kwargs."""
|
||||||
self.logger.debug("create with params %s", str(kwargs))
|
self.logger.debug("create with params %s", str(kwargs))
|
||||||
|
delegate = self.toclass(self.config, **kwargs)
|
||||||
|
entity = self.entityclass(self.config, delegate, self.verbose)
|
||||||
sess = create_session()
|
sess = create_session()
|
||||||
transaction = sess.create_transaction()
|
|
||||||
delegate = self.toclass(**kwargs)
|
|
||||||
entity = self.entityclass(delegate, self.verbose)
|
|
||||||
try:
|
try:
|
||||||
sess.save(delegate)
|
sess.begin()
|
||||||
|
sess.add(delegate)
|
||||||
sess.flush()
|
sess.flush()
|
||||||
sess.refresh(delegate)
|
sess.refresh(delegate)
|
||||||
entity.create_hook(sess)
|
entity.create_hook(sess)
|
||||||
sess.flush()
|
sess.commit()
|
||||||
transaction.commit()
|
|
||||||
except:
|
except:
|
||||||
transaction.rollback()
|
sess.rollback()
|
||||||
self.logger.exception("Exception in create.")
|
self.logger.exception("Exception in create.")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
@ -65,7 +68,7 @@ class BackendEntityHandler(object):
|
||||||
allentities = query.filter_by(**kwargs).all()
|
allentities = query.filter_by(**kwargs).all()
|
||||||
else:
|
else:
|
||||||
allentities = query.all()
|
allentities = query.all()
|
||||||
return [self.entityclass(entity, self.verbose) \
|
return [self.entityclass(self.config, entity, self.verbose) \
|
||||||
for entity in allentities]
|
for entity in allentities]
|
||||||
|
|
||||||
def delete(self, pkvalue):
|
def delete(self, pkvalue):
|
||||||
|
@ -73,19 +76,18 @@ class BackendEntityHandler(object):
|
||||||
specified primary key value."""
|
specified primary key value."""
|
||||||
self.logger.debug("delete with primary key %s", str(pkvalue))
|
self.logger.debug("delete with primary key %s", str(pkvalue))
|
||||||
sess = create_session()
|
sess = create_session()
|
||||||
transaction = sess.create_transaction()
|
|
||||||
try:
|
try:
|
||||||
|
sess.begin()
|
||||||
tobj = sess.query(self.toclass).get(pkvalue)
|
tobj = sess.query(self.toclass).get(pkvalue)
|
||||||
if tobj:
|
if tobj:
|
||||||
entity = self.entityclass(tobj, self.verbose)
|
entity = self.entityclass(self.config, tobj, self.verbose)
|
||||||
self.logger.info("delete %s", str(entity))
|
self.logger.info("delete %s", str(entity))
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print "delete %s" % (str(entity))
|
print "delete %s" % (str(entity))
|
||||||
entity.delete_hook(sess)
|
entity.delete_hook(sess)
|
||||||
sess.delete(tobj)
|
sess.delete(tobj)
|
||||||
sess.flush()
|
sess.commit()
|
||||||
transaction.commit()
|
|
||||||
except Exception:
|
except Exception:
|
||||||
transaction.rollback()
|
sess.rollback()
|
||||||
self.logger.exception("Exception in delete.")
|
self.logger.exception("Exception in delete.")
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,16 +19,15 @@
|
||||||
#
|
#
|
||||||
# Version: $Id$
|
# Version: $Id$
|
||||||
|
|
||||||
from sqlalchemy.orm import object_mapper, mapper, relation
|
from sqlalchemy.orm import object_mapper
|
||||||
from tables import *
|
|
||||||
|
|
||||||
|
|
||||||
class BackendTo(object):
|
class BackendTo(object):
|
||||||
"""Backend transfer object class."""
|
"""Backend transfer object class."""
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, config, **kwargs):
|
||||||
for (key, value) in kwargs.items():
|
for (key, value) in kwargs.items():
|
||||||
self.__setattr__(key, value)
|
self.__setattr__(key, unicode(value, 'utf8'))
|
||||||
|
|
||||||
def __repr__(self, **kwargs):
|
def __repr__(self, **kwargs):
|
||||||
if 'verbose' in kwargs and kwargs['verbose']:
|
if 'verbose' in kwargs and kwargs['verbose']:
|
||||||
|
@ -64,12 +63,3 @@ class Domain(BackendTo):
|
||||||
class Record(BackendTo):
|
class Record(BackendTo):
|
||||||
"""Transfer object class for DNS domain records."""
|
"""Transfer object class for DNS domain records."""
|
||||||
_shortkeys = ("recordid", "domainid", "name", "type", "content")
|
_shortkeys = ("recordid", "domainid", "name", "type", "content")
|
||||||
|
|
||||||
|
|
||||||
client_mapper = mapper(Client, client_table, {
|
|
||||||
'sysusers': relation(Sysuser, backref = 'client')})
|
|
||||||
sysuser_mapper = mapper(Sysuser, sysuser_table, {
|
|
||||||
'domains': relation(Domain, backref = 'sysuser')})
|
|
||||||
domain_mapper = mapper(Domain, domain_table, {
|
|
||||||
'records': relation(Record, cascade = 'all', backref = 'domain')})
|
|
||||||
record_mapper = mapper(Record, record_table)
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,8 +20,7 @@
|
||||||
# Version: $Id$
|
# Version: $Id$
|
||||||
"""This module defines the ClientEntity class."""
|
"""This module defines the ClientEntity class."""
|
||||||
|
|
||||||
from gnuviechadmin.backend.settings import config, get_template, \
|
from gnuviechadmin.backend.settings import get_template, get_template_string
|
||||||
get_template_string
|
|
||||||
from gnuviechadmin.exceptions import CannotDeleteError
|
from gnuviechadmin.exceptions import CannotDeleteError
|
||||||
from gnuviechadmin.backend.BackendTo import Client
|
from gnuviechadmin.backend.BackendTo import Client
|
||||||
from gnuviechadmin.backend.BackendEntity import BackendEntity
|
from gnuviechadmin.backend.BackendEntity import BackendEntity
|
||||||
|
@ -31,9 +30,9 @@ from gnuviechadmin.backend.BackendEntityHandler import BackendEntityHandler
|
||||||
class ClientEntity(BackendEntity):
|
class ClientEntity(BackendEntity):
|
||||||
"""Entity class for clients."""
|
"""Entity class for clients."""
|
||||||
|
|
||||||
def __init__(self, delegate, verbose = False, **kwargs):
|
def __init__(self, config, delegate, verbose = False, **kwargs):
|
||||||
"""Initializes the client entity instance."""
|
"""Initializes the client entity instance."""
|
||||||
BackendEntity.__init__(self, delegate, verbose)
|
BackendEntity.__init__(self, config, delegate, verbose)
|
||||||
for (key, value) in kwargs.items():
|
for (key, value) in kwargs.items():
|
||||||
self.__setattr__(key, value)
|
self.__setattr__(key, value)
|
||||||
if not self.delegateto.country:
|
if not self.delegateto.country:
|
||||||
|
@ -42,8 +41,8 @@ class ClientEntity(BackendEntity):
|
||||||
|
|
||||||
def _client_mail(self):
|
def _client_mail(self):
|
||||||
"""Mails a summary about the creation of the client."""
|
"""Mails a summary about the creation of the client."""
|
||||||
text = get_template(config.get('common', 'mailtemplates'),
|
text = get_template(self.config['mailtemplates'],
|
||||||
config.get('client', 'create.mail')).substitute({
|
self.config['client.create.mail']).substitute({
|
||||||
'firstname': self.delegateto.firstname,
|
'firstname': self.delegateto.firstname,
|
||||||
'lastname': self.delegateto.lastname,
|
'lastname': self.delegateto.lastname,
|
||||||
'email': self.delegateto.email,
|
'email': self.delegateto.email,
|
||||||
|
@ -52,11 +51,11 @@ class ClientEntity(BackendEntity):
|
||||||
'city': self.delegateto.city,
|
'city': self.delegateto.city,
|
||||||
'phone': self.delegateto.phone})
|
'phone': self.delegateto.phone})
|
||||||
subject = get_template_string(
|
subject = get_template_string(
|
||||||
config.get('client', 'create_subject')).substitute({
|
self.config['client.create_subject']).substitute({
|
||||||
'firstname': self.delegateto.firstname,
|
'firstname': self.delegateto.firstname,
|
||||||
'lastname': self.delegateto.lastname})
|
'lastname': self.delegateto.lastname})
|
||||||
self.send_mail(subject, text)
|
self.send_mail(subject, text)
|
||||||
|
|
||||||
def create_hook(self, session):
|
def create_hook(self, session):
|
||||||
"""Actions to perform when a client is created."""
|
"""Actions to perform when a client is created."""
|
||||||
self._client_mail()
|
self._client_mail()
|
||||||
|
@ -72,11 +71,12 @@ class ClientEntity(BackendEntity):
|
||||||
|
|
||||||
def _get_default_country(self):
|
def _get_default_country(self):
|
||||||
"""Gets the default country."""
|
"""Gets the default country."""
|
||||||
return config.get('common', 'defaultcountry')
|
return self.config['client.defaultcountry']
|
||||||
|
|
||||||
|
|
||||||
class ClientHandler(BackendEntityHandler):
|
class ClientHandler(BackendEntityHandler):
|
||||||
"""BackendEntityHandler for Client entities."""
|
"""BackendEntityHandler for Client entities."""
|
||||||
|
|
||||||
def __init__(self, verbose = False):
|
def __init__(self, config, verbose = False):
|
||||||
BackendEntityHandler.__init__(self, ClientEntity, Client, verbose)
|
BackendEntityHandler.__init__(self, ClientEntity, Client, config,
|
||||||
|
verbose)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,32 +25,13 @@ This module handles all central configuration of Gnuviech Admin. It
|
||||||
parses configuration files and provides functions for reading
|
parses configuration files and provides functions for reading
|
||||||
templates."""
|
templates."""
|
||||||
|
|
||||||
import ConfigParser
|
|
||||||
import os
|
import os
|
||||||
from string import Template
|
from string import Template
|
||||||
|
|
||||||
# global settings which must not be user configurable
|
|
||||||
required_version = 3
|
|
||||||
|
|
||||||
# load user configuration
|
def get_template(templatedir, filename):
|
||||||
config = ConfigParser.ConfigParser()
|
|
||||||
config.readfp(open('gnuviechadmin/defaults.cfg'))
|
|
||||||
config.read(['gnuviechadmin/gva.cfg', os.path.expanduser('~/.gva.cfg')])
|
|
||||||
|
|
||||||
dbschema = None
|
|
||||||
if config.get('database', 'uri').startswith('postgres://'):
|
|
||||||
dbschema = 'gva'
|
|
||||||
|
|
||||||
|
|
||||||
def get_template_dir(dirname):
|
|
||||||
"""Returns the template directory for the given directory."""
|
|
||||||
templatepath = config.get('common', 'templatedir')
|
|
||||||
return os.path.join(templatepath, dirname)
|
|
||||||
|
|
||||||
|
|
||||||
def get_template(dirname, filename):
|
|
||||||
"""Returns the template data from the given template file."""
|
"""Returns the template data from the given template file."""
|
||||||
templatefile = file(os.path.join(get_template_dir(dirname),
|
templatefile = file(os.path.join(templatedir,
|
||||||
filename))
|
filename))
|
||||||
templatedata = templatefile.read()
|
templatedata = templatefile.read()
|
||||||
return Template(templatedata.decode('utf_8'))
|
return Template(templatedata.decode('utf_8'))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,57 +19,69 @@
|
||||||
#
|
#
|
||||||
# Version: $Id$
|
# Version: $Id$
|
||||||
|
|
||||||
from sqlalchemy import *
|
from sqlalchemy import MetaData, Table
|
||||||
|
from sqlalchemy.orm import mapper, relation
|
||||||
from sqlalchemy.exceptions import NoSuchTableError
|
from sqlalchemy.exceptions import NoSuchTableError
|
||||||
import sys
|
import sys
|
||||||
import migrate.versioning.api
|
import migrate.versioning.api
|
||||||
from settings import *
|
import logging
|
||||||
|
from gnuviechadmin.backend.BackendTo import Client, Sysuser, Domain, Record
|
||||||
|
|
||||||
try:
|
|
||||||
dbversion = migrate.versioning.api.db_version(
|
def dbsetup(config):
|
||||||
config.get('database', 'uri'),
|
logger = logging.getLogger(__name__)
|
||||||
config.get('database', 'repository'))
|
required_version = int(config['migrate.required_version'])
|
||||||
if dbversion < required_version:
|
try:
|
||||||
print("""Database version is %d but required version is %d. Trying
|
dbversion = migrate.versioning.api.db_version(
|
||||||
automatic upgrade.""" %
|
config['sqlalchemy.uri'], config['database.repository'])
|
||||||
(dbversion, required_version))
|
if dbversion < required_version:
|
||||||
|
logger.info("""Database version is %d but required version \
|
||||||
|
is %d. Trying automatic upgrade.""" % (dbversion, required_version))
|
||||||
|
try:
|
||||||
|
migrate.versioning.api.upgrade(
|
||||||
|
config['sqlalchemy.uri'], config['database.repository'],
|
||||||
|
required_version)
|
||||||
|
except e:
|
||||||
|
logger.error("Automatic upgrade failed.", e)
|
||||||
|
raise
|
||||||
|
elif dbversion > required_version:
|
||||||
|
logger.error("""Database version is %d which is higher than \
|
||||||
|
the required version %d. I cannot handle this situation without possible \
|
||||||
|
data loss.""" % (dbversion, required_version))
|
||||||
|
sys.exit(1)
|
||||||
|
except NoSuchTableError, nste:
|
||||||
|
logger.info("""The database is not versioned. \
|
||||||
|
Trying automatic versioning.""")
|
||||||
try:
|
try:
|
||||||
|
migrate.versioning.api.version_control(
|
||||||
|
config['sqlalchemy.uri'], config['database.repository'])
|
||||||
migrate.versioning.api.upgrade(
|
migrate.versioning.api.upgrade(
|
||||||
config.get('database', 'uri'),
|
config['sqlalchemy.uri'], config['database.repository'],
|
||||||
config.get('database', 'repository'),
|
|
||||||
required_version)
|
required_version)
|
||||||
except:
|
except:
|
||||||
print "Automatic upgrade failed."
|
logger.error("Automatic setup failed.")
|
||||||
raise
|
raise
|
||||||
elif dbversion > required_version:
|
|
||||||
print("""Database version is %d which is higher than the required
|
|
||||||
version %d. I cannot handle this situation without possible data loss.""" %
|
|
||||||
(dbversion, required_version))
|
|
||||||
sys.exit(1)
|
|
||||||
except NoSuchTableError, nste:
|
|
||||||
print """The database is not versioned. Trying automatic versioning."""
|
|
||||||
try:
|
|
||||||
migrate.versioning.api.version_control(
|
|
||||||
config.get('database', 'uri'),
|
|
||||||
config.get('database', 'repository'))
|
|
||||||
migrate.versioning.api.upgrade(
|
|
||||||
config.get('database', 'uri'),
|
|
||||||
config.get('database', 'repository', required_version))
|
|
||||||
except:
|
|
||||||
print "Automatic setup failed."
|
|
||||||
raise
|
|
||||||
|
|
||||||
meta = MetaData(config.get('database', 'uri'))
|
meta = MetaData(config['sqlalchemy.uri'])
|
||||||
#meta.engine.echo = True
|
meta.bind.engine.echo = config['sqlalchemy.echo']
|
||||||
client_table = Table('client', meta, schema = dbschema, autoload = True)
|
|
||||||
sysuser_table = Table('sysuser', meta, schema = dbschema, autoload = True)
|
dbschema = None
|
||||||
domain_table = Table('domain', meta, schema = dbschema, autoload = True)
|
if 'database.schema' in config:
|
||||||
record_table = Table('record', meta, schema = dbschema, autoload = True)
|
dbschema = config['database.schema']
|
||||||
supermaster_table = Table('supermaster', meta, schema = dbschema,
|
|
||||||
autoload = True)
|
(client_table, sysuser_table, domain_table, \
|
||||||
mailaccount_table = Table('mailaccount', meta, schema = dbschema,
|
record_table, supermaster_table, mailaccount_table, \
|
||||||
autoload = True)
|
mailaddress_table, mailtarget_table) = \
|
||||||
mailaddress_table = Table('mailaddress', meta, schema = dbschema,
|
[Table(tabname, meta, schema = dbschema,
|
||||||
autoload = True)
|
autoload = True) for tabname in \
|
||||||
mailtarget_table = Table('mailtarget', meta, schema = dbschema,
|
('client', 'sysuser', 'domain', 'record',
|
||||||
autoload = True)
|
'supermaster', 'mailaccount', 'mailaddress', 'mailtarget')]
|
||||||
|
|
||||||
|
client_mapper = mapper(Client, client_table, {
|
||||||
|
'sysusers': relation(Sysuser, backref = 'client')})
|
||||||
|
sysuser_mapper = mapper(Sysuser, sysuser_table, {
|
||||||
|
'domains': relation(Domain, backref = 'sysuser')})
|
||||||
|
domain_mapper = mapper(Domain, domain_table, {
|
||||||
|
'records': relation(Record, cascade = 'all',
|
||||||
|
backref = 'domain')})
|
||||||
|
record_mapper = mapper(Record, record_table)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -197,9 +197,10 @@ Common options:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
self._handleoption(subcommand, o, a)
|
self._handleoption(subcommand, o, a)
|
||||||
|
|
||||||
def __init__(self, args):
|
def __init__(self, args, config):
|
||||||
"""This initializes the command with the given command line
|
"""This initializes the command with the given command line
|
||||||
arguments and executes it."""
|
arguments and executes it."""
|
||||||
|
self.config = config
|
||||||
self.logger = logging.getLogger("%s.%s" % (
|
self.logger = logging.getLogger("%s.%s" % (
|
||||||
self.__class__.__module__, self.__class__.__name__))
|
self.__class__.__module__, self.__class__.__name__))
|
||||||
self._data = {}
|
self._data = {}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -24,3 +24,39 @@ This package provides modules for the command line interface of the
|
||||||
gnuviechadmin server administration suite."""
|
gnuviechadmin server administration suite."""
|
||||||
|
|
||||||
__all__ = ["client", "sysuser", "domain", "record"]
|
__all__ = ["client", "sysuser", "domain", "record"]
|
||||||
|
|
||||||
|
from logging import getLogger
|
||||||
|
from sys import exit
|
||||||
|
|
||||||
|
|
||||||
|
class CommandLineInterface(object):
|
||||||
|
|
||||||
|
def __init__(self, config, args):
|
||||||
|
self.log = getLogger(__name__)
|
||||||
|
self.config = config
|
||||||
|
if len(args) < 2:
|
||||||
|
self._usage(args[0])
|
||||||
|
exit(1)
|
||||||
|
self.commands = [command for command in self._get_commands() \
|
||||||
|
if command.name == args[1]]
|
||||||
|
self.cmdargs = args[2:]
|
||||||
|
|
||||||
|
|
||||||
|
def _usage(self, callee):
|
||||||
|
print """%s <command> [commandargs]
|
||||||
|
|
||||||
|
where command is one of
|
||||||
|
""" % callee
|
||||||
|
for command in self._get_commands():
|
||||||
|
print "%10s - %s" % (command.name, command.description)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
for cmd in self.commands:
|
||||||
|
cmd(self.cmdargs, self.config)
|
||||||
|
|
||||||
|
def _get_commands(self):
|
||||||
|
from gnuviechadmin.cli.client import ClientCli
|
||||||
|
from gnuviechadmin.cli.sysuser import SysuserCli
|
||||||
|
from gnuviechadmin.cli.domain import DomainCli
|
||||||
|
from gnuviechadmin.cli.record import RecordCli
|
||||||
|
return [ClientCli, SysuserCli, DomainCli, RecordCli]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -61,24 +61,25 @@ class ClientCli(CliCommand.CliCommand):
|
||||||
def _execute(self, subcommand):
|
def _execute(self, subcommand):
|
||||||
self.logger.debug("execute %s with data %s", subcommand,
|
self.logger.debug("execute %s with data %s", subcommand,
|
||||||
str(self._data))
|
str(self._data))
|
||||||
from gnuviechadmin.backend import client
|
from gnuviechadmin.backend.client import ClientHandler
|
||||||
from gnuviechadmin import exceptions
|
from gnuviechadmin.exceptions import CreationFailedError
|
||||||
if subcommand == "create":
|
if subcommand == "create":
|
||||||
try:
|
try:
|
||||||
myclient = client.ClientHandler(self._verbose).create(
|
myclient = ClientHandler(self.config,
|
||||||
**self._data)
|
self._verbose).create(**self._data)
|
||||||
if self._verbose:
|
if self._verbose:
|
||||||
print myclient
|
print myclient
|
||||||
except exceptions.CreationFailedError, cfe:
|
except CreationFailedError, cfe:
|
||||||
self._usage()
|
self._usage()
|
||||||
print cfe
|
print cfe
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
elif subcommand == "list":
|
elif subcommand == "list":
|
||||||
clients = client.ClientHandler(self._verbose).fetchall()
|
clients = ClientHandler(self.config, self._verbose).fetchall()
|
||||||
for client in clients:
|
for client in clients:
|
||||||
print client
|
print client
|
||||||
elif subcommand == "delete":
|
elif subcommand == "delete":
|
||||||
client.ClientHandler(self._verbose).delete(self._data["clientid"])
|
ClientHandler(self.config,
|
||||||
|
self._verbose).delete(self._data["clientid"])
|
||||||
|
|
||||||
def __init__(self, argv):
|
def __init__(self, argv, config):
|
||||||
CliCommand.CliCommand.__init__(self, argv)
|
CliCommand.CliCommand.__init__(self, argv, config)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007, 2008 by Jan Dittberner.
|
# Copyright (C) 2007, 2008, 2009 by Jan Dittberner.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -30,10 +30,8 @@ from email.MIMEText import MIMEText
|
||||||
from pyme import core
|
from pyme import core
|
||||||
from pyme.constants.sig import mode
|
from pyme.constants.sig import mode
|
||||||
|
|
||||||
from gnuviechadmin.backend.settings import config
|
|
||||||
|
|
||||||
|
def send_mail(config, subject, text):
|
||||||
def send_mail(subject, text):
|
|
||||||
"""Send a signed and possibly encrypted mail.
|
"""Send a signed and possibly encrypted mail.
|
||||||
|
|
||||||
This method sends a mail with the given text and subject and signs
|
This method sends a mail with the given text and subject and signs
|
||||||
|
@ -52,8 +50,8 @@ def send_mail(subject, text):
|
||||||
cipher = core.Data()
|
cipher = core.Data()
|
||||||
c = core.Context()
|
c = core.Context()
|
||||||
c.set_armor(1)
|
c.set_armor(1)
|
||||||
signer = config.get('common', 'mailfrom')
|
signer = config['mailfrom']
|
||||||
rcpt = config.get('common', 'mailto')
|
rcpt = config['mailto']
|
||||||
c.signers_clear()
|
c.signers_clear()
|
||||||
for sigkey in [x for x in c.op_keylist_all(signer, 1)]:
|
for sigkey in [x for x in c.op_keylist_all(signer, 1)]:
|
||||||
if sigkey.can_sign:
|
if sigkey.can_sign:
|
||||||
|
@ -64,14 +62,12 @@ def send_mail(subject, text):
|
||||||
keylist = []
|
keylist = []
|
||||||
for key in c.op_keylist_all(rcpt, 0):
|
for key in c.op_keylist_all(rcpt, 0):
|
||||||
valid = 0
|
valid = 0
|
||||||
subkey = key.subkeys
|
for subkey in key.subkeys:
|
||||||
while subkey:
|
|
||||||
keyid = subkey.keyid
|
keyid = subkey.keyid
|
||||||
if keyid == None:
|
if keyid == None:
|
||||||
break
|
break
|
||||||
can_encrypt = subkey.can_encrypt
|
can_encrypt = subkey.can_encrypt
|
||||||
valid += can_encrypt
|
valid += can_encrypt
|
||||||
subkey = subkey.next
|
|
||||||
if valid:
|
if valid:
|
||||||
keylist.append(key)
|
keylist.append(key)
|
||||||
if keylist:
|
if keylist:
|
||||||
|
|
8
setup.py
8
setup.py
|
@ -22,7 +22,6 @@
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pudge
|
|
||||||
import buildutils
|
import buildutils
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
@ -35,7 +34,8 @@ setup(
|
||||||
author_email = 'jan@dittberner.info',
|
author_email = 'jan@dittberner.info',
|
||||||
url = 'http://www.gnuviech-server.de/projects/gnuviechadmin',
|
url = 'http://www.gnuviech-server.de/projects/gnuviechadmin',
|
||||||
install_requires = ['SQLAlchemy>=0.5', 'sqlalchemy-migrate>=0.5',
|
install_requires = ['SQLAlchemy>=0.5', 'sqlalchemy-migrate>=0.5',
|
||||||
'AuthKit>=0.4'],
|
'AuthKit>=0.4', 'PasteDeploy>=1.3.3',
|
||||||
|
'python-gnutls>=1.1'],
|
||||||
packages = find_packages(),
|
packages = find_packages(),
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
exclude_package_data = {'': ['gva.cfg']},
|
exclude_package_data = {'': ['gva.cfg']},
|
||||||
|
@ -46,4 +46,8 @@ it contains tools for maintaining e.g. clients, domains, users, mail
|
||||||
accounts""",
|
accounts""",
|
||||||
license = 'GPL',
|
license = 'GPL',
|
||||||
keywords = 'administration backend frontend',
|
keywords = 'administration backend frontend',
|
||||||
|
entry_points = """
|
||||||
|
[paste.app_factory]
|
||||||
|
cli = gnuviechadmin.cli.client
|
||||||
|
""",
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue