1
0
Fork 0

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:
Jan Dittberner 2009-07-19 01:03:23 +02:00
parent 483c1f9038
commit 222b35b033
24 changed files with 247 additions and 177 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
*.pyc *.pyc
*.egg/ *.egg/
*.log *.log
gva.db

50
bin/gva
View File

@ -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
View 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

View File

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

View File

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

View File

@ -0,0 +1,3 @@
[paste.app_factory]
cli = gnuviechadmin.cli.client

View File

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

View File

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

View File

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

View File

@ -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)

View File

@ -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)

View File

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

View File

@ -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)

View File

@ -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 = {}

View File

@ -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]

View File

@ -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)

View File

@ -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:

View File

@ -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
""",
) )