Merge branch 'release/0.5.0' into production
* release/0.5.0: update docs version, add release to changelog add missing - to install parameter add return value as documented add logging for set_file_ssh_authorized_keys add new task set_file_ssh_authorized_keys improved logging in fileservertasks.tasks
This commit is contained in:
commit
420d34dfea
6 changed files with 146 additions and 69 deletions
|
@ -1,6 +1,12 @@
|
||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
* :release:`0.5.0 <2015-01-29>`
|
||||||
|
* :feature:`-` add new task set_file_ssh_authorized_keys to add SSH keys for
|
||||||
|
users
|
||||||
|
* :support:`-` improved logging in fileservertasks.tasks, got rid of
|
||||||
|
GVAFileException
|
||||||
|
|
||||||
* :release:`0.4.0 <2015-01-26>`
|
* :release:`0.4.0 <2015-01-26>`
|
||||||
* :feature:`-` implement new tasks create_file_website_hierarchy and
|
* :feature:`-` implement new tasks create_file_website_hierarchy and
|
||||||
delete_file_website_hierarchy
|
delete_file_website_hierarchy
|
||||||
|
|
|
@ -20,12 +20,6 @@ The project module :py:mod:`gvafile`
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
:py:mod:`exceptions <gvafile.exceptions>`
|
|
||||||
-----------------------------------------
|
|
||||||
|
|
||||||
.. automodule:: gvafile.exceptions
|
|
||||||
|
|
||||||
|
|
||||||
:py:mod:`settings <gvafile.settings>`
|
:py:mod:`settings <gvafile.settings>`
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
@ -33,8 +27,8 @@ The project module :py:mod:`gvafile`
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
:py:mod:`fileservertasks` app
|
:py:mod:`fileservertasks` module
|
||||||
=============================
|
================================
|
||||||
|
|
||||||
.. automodule:: fileservertasks
|
.. automodule:: fileservertasks
|
||||||
|
|
||||||
|
|
|
@ -59,9 +59,9 @@ copyright = u'2014, 2015 Jan Dittberner'
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.4'
|
version = '0.5'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.4.0'
|
release = '0.5.0'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|
|
@ -8,16 +8,14 @@ from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from tempfile import mkstemp
|
||||||
|
|
||||||
from gvafile import settings
|
from gvafile import settings
|
||||||
|
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
from celery.utils.log import get_task_logger
|
from celery.utils.log import get_task_logger
|
||||||
|
|
||||||
from gvafile.exceptions import GVAFileException
|
_LOGGER = get_task_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
_logger = get_task_logger(__name__)
|
|
||||||
|
|
||||||
SUDO_CMD = '/usr/bin/sudo'
|
SUDO_CMD = '/usr/bin/sudo'
|
||||||
INSTALL_CMD = '/usr/bin/install'
|
INSTALL_CMD = '/usr/bin/install'
|
||||||
|
@ -25,6 +23,34 @@ SETFACL_CMD = '/usr/bin/setfacl'
|
||||||
RM_CMD = '/bin/rm'
|
RM_CMD = '/bin/rm'
|
||||||
|
|
||||||
|
|
||||||
|
def log_and_raise(exception, message, *args):
|
||||||
|
"""
|
||||||
|
Log and raise a :py:class:`subprocess.CalledProcessError`.
|
||||||
|
|
||||||
|
:param exception: exception
|
||||||
|
:param str message: log message
|
||||||
|
:param args: arguments to fill placeholders in message
|
||||||
|
:raises Exception: raises an exception with the formatted message
|
||||||
|
|
||||||
|
"""
|
||||||
|
logargs = list(args) + [exception.returncode, exception.output]
|
||||||
|
_LOGGER.error(message + "\nreturncode: %d\noutput:\n%s", *logargs)
|
||||||
|
raise Exception(message % args)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_authorized_keys_path(username):
|
||||||
|
"""
|
||||||
|
Constructs the file path for the authorized_keys file for a given username.
|
||||||
|
|
||||||
|
:param str username: the user name
|
||||||
|
:return: the file name
|
||||||
|
:rtype: str
|
||||||
|
|
||||||
|
"""
|
||||||
|
return os.path.join(
|
||||||
|
settings.GVAFILE_SFTP_AUTHKEYS_DIRECTORY, username, 'keys')
|
||||||
|
|
||||||
|
|
||||||
def _build_sftp_directory_name(username):
|
def _build_sftp_directory_name(username):
|
||||||
"""
|
"""
|
||||||
Constructs the SFTP directory name for a given username.
|
Constructs the SFTP directory name for a given username.
|
||||||
|
@ -61,11 +87,11 @@ def setup_file_sftp_userdir(username):
|
||||||
subprocess.check_output([
|
subprocess.check_output([
|
||||||
SUDO_CMD, SETFACL_CMD, '-m', 'www-data:--x',
|
SUDO_CMD, SETFACL_CMD, '-m', 'www-data:--x',
|
||||||
sftp_directory], stderr=subprocess.STDOUT)
|
sftp_directory], stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError as cpe:
|
||||||
_logger.exception(
|
log_and_raise(
|
||||||
'could not create SFTP directory for user %s', username)
|
cpe, 'cold not create SFTP directory for user %s', username)
|
||||||
raise GVAFileException(
|
_LOGGER.info(
|
||||||
"could not create SFTP directory for user %s" % username)
|
'created sftp directory %s for user %s', sftp_directory, username)
|
||||||
return sftp_directory
|
return sftp_directory
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,11 +112,11 @@ def delete_file_sftp_userdir(username):
|
||||||
subprocess.check_output([
|
subprocess.check_output([
|
||||||
SUDO_CMD, RM_CMD, '-r', '-f', sftp_directory],
|
SUDO_CMD, RM_CMD, '-r', '-f', sftp_directory],
|
||||||
stderr=subprocess.STDOUT)
|
stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError as cpe:
|
||||||
_logger.exception(
|
log_and_raise(
|
||||||
'could not remove SFTP directory for user %s', username)
|
cpe, 'could not remove SFTP directory for user %s', username)
|
||||||
raise GVAFileException(
|
_LOGGER.info(
|
||||||
"could not remove SFTP directory for user %s" % username)
|
"deleted sftp directory %s of user %s", sftp_directory, username)
|
||||||
return sftp_directory
|
return sftp_directory
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,11 +138,11 @@ def setup_file_mail_userdir(username):
|
||||||
subprocess.check_output([
|
subprocess.check_output([
|
||||||
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||||
'-m', '0500', '-d', mail_directory], stderr=subprocess.STDOUT)
|
'-m', '0500', '-d', mail_directory], stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError as cpe:
|
||||||
_logger.exception(
|
log_and_raise(
|
||||||
'could not create mail base directory for user %s', username)
|
cpe, 'could not create mail base directory for user %s', username)
|
||||||
raise GVAFileException(
|
_LOGGER.info(
|
||||||
"could not create mail base directory for user %s" % username)
|
'created mail directory %s for user %s', mail_directory, username)
|
||||||
return mail_directory
|
return mail_directory
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,11 +163,11 @@ def delete_file_mail_userdir(username):
|
||||||
subprocess.check_output([
|
subprocess.check_output([
|
||||||
SUDO_CMD, RM_CMD, '-r', '-f', mail_directory],
|
SUDO_CMD, RM_CMD, '-r', '-f', mail_directory],
|
||||||
stderr=subprocess.STDOUT)
|
stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError as cpe:
|
||||||
_logger.exception(
|
log_and_raise(
|
||||||
'could not remove mail base directory of user %s', username)
|
cpe, 'could not remove mail base directory of user %s', username)
|
||||||
raise GVAFileException(
|
_LOGGER.info(
|
||||||
"could not remove mail base directory of user %s" % username)
|
'deleted mail directory %s of user %s', mail_directory, username)
|
||||||
return mail_directory
|
return mail_directory
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,7 +179,7 @@ def create_file_mailbox(username, mailboxname):
|
||||||
|
|
||||||
:param str username: the user name
|
:param str username: the user name
|
||||||
:param str mailboxname: the mailbox name
|
:param str mailboxname: the mailbox name
|
||||||
:raises GVAFileException: if the mailbox directory cannot be created
|
:raises Exception: if the mailbox directory cannot be created
|
||||||
:return: the created mailbox directory name
|
:return: the created mailbox directory name
|
||||||
:rtype: str
|
:rtype: str
|
||||||
|
|
||||||
|
@ -164,12 +190,13 @@ def create_file_mailbox(username, mailboxname):
|
||||||
subprocess.check_output([
|
subprocess.check_output([
|
||||||
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||||
'-m', '0700', '-d', mailbox_directory], stderr=subprocess.STDOUT)
|
'-m', '0700', '-d', mailbox_directory], stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError as cpe:
|
||||||
_logger.exception(
|
log_and_raise(
|
||||||
'could not create mailbox %s for user %s', mailboxname, username)
|
cpe, 'could not create mailbox %s for user %s', mailboxname,
|
||||||
raise GVAFileException(
|
username)
|
||||||
"could not create mailbox %s for user %s" % (mailboxname, username)
|
_LOGGER.info(
|
||||||
)
|
'created mailbox directory %s for user %s', mailbox_directory,
|
||||||
|
username)
|
||||||
return mailbox_directory
|
return mailbox_directory
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,7 +207,7 @@ def delete_file_mailbox(username, mailboxname):
|
||||||
|
|
||||||
:param str username: the user name
|
:param str username: the user name
|
||||||
:param str mailboxname: the mailbox name
|
:param str mailboxname: the mailbox name
|
||||||
:raises GVAFileException: if the mailbox directory cannot be deleted
|
:raises Exception: if the mailbox directory cannot be deleted
|
||||||
:return: the deleted mailbox directory name
|
:return: the deleted mailbox directory name
|
||||||
:rtype: str
|
:rtype: str
|
||||||
|
|
||||||
|
@ -191,11 +218,12 @@ def delete_file_mailbox(username, mailboxname):
|
||||||
subprocess.check_output([
|
subprocess.check_output([
|
||||||
SUDO_CMD, RM_CMD, '-r', '-f', mailbox_directory],
|
SUDO_CMD, RM_CMD, '-r', '-f', mailbox_directory],
|
||||||
stderr=subprocess.STDOUT)
|
stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError as cpe:
|
||||||
_logger.exception(
|
log_and_raise(
|
||||||
'could not remove mailbox %s of user %s', mailboxname, username)
|
cpe, 'could not remove mailbox %s of user %s', mailboxname,
|
||||||
raise GVAFileException(
|
username)
|
||||||
"could not remove mailbox %s of user %s" % (mailboxname, username))
|
_LOGGER.info(
|
||||||
|
'deleted mailbox directory %s of user %s', mailbox_directory, username)
|
||||||
return mailbox_directory
|
return mailbox_directory
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,6 +234,8 @@ def create_file_website_hierarchy(username, sitename):
|
||||||
|
|
||||||
:param str username: the user name
|
:param str username: the user name
|
||||||
:param str sitename: name of the website
|
:param str sitename: name of the website
|
||||||
|
:raises Exception: if the website directory hierarchy directory cannot be
|
||||||
|
created
|
||||||
:return: the directory name
|
:return: the directory name
|
||||||
:rtype: str
|
:rtype: str
|
||||||
|
|
||||||
|
@ -233,13 +263,14 @@ def create_file_website_hierarchy(username, sitename):
|
||||||
subprocess.check_output([
|
subprocess.check_output([
|
||||||
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||||
'-m', '0750', '-d', tmpdir], stderr=subprocess.STDOUT)
|
'-m', '0750', '-d', tmpdir], stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError as cpe:
|
||||||
_logger.exception(
|
log_and_raise(
|
||||||
|
cpe,
|
||||||
("could not setup website file hierarchy for user %s's "
|
("could not setup website file hierarchy for user %s's "
|
||||||
"website %s"), username, sitename)
|
"website %s"), username, sitename)
|
||||||
raise GVAFileException(
|
_LOGGER.info(
|
||||||
("could not setup website file hierarchy for user %s's "
|
'created website directory %s for user %s', website_directory,
|
||||||
"website %s") % (username, sitename))
|
username)
|
||||||
return website_directory
|
return website_directory
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,6 +281,8 @@ def delete_file_website_hierarchy(username, sitename):
|
||||||
|
|
||||||
:param str username: the user name
|
:param str username: the user name
|
||||||
:param str sitename: name of the website
|
:param str sitename: name of the website
|
||||||
|
:raises Exception: if the website directory hierarchy directory cannot be
|
||||||
|
deleted
|
||||||
:return: the directory name
|
:return: the directory name
|
||||||
:rtype: str
|
:rtype: str
|
||||||
|
|
||||||
|
@ -260,11 +293,65 @@ def delete_file_website_hierarchy(username, sitename):
|
||||||
subprocess.check_output([
|
subprocess.check_output([
|
||||||
SUDO_CMD, RM_CMD, '-r', '-f', website_directory],
|
SUDO_CMD, RM_CMD, '-r', '-f', website_directory],
|
||||||
stderr=subprocess.STDOUT)
|
stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError as cpe:
|
||||||
_logger.exception(
|
log_and_raise(
|
||||||
|
cpe,
|
||||||
("could not delete the website file hierarchy of user %s's "
|
("could not delete the website file hierarchy of user %s's "
|
||||||
"website %s"), username, sitename)
|
"website %s"), username, sitename)
|
||||||
raise GVAFileException(
|
_LOGGER.info(
|
||||||
("could not delete the website file hierarchy of user %s's "
|
'deleted website directory %s of user %s', website_directory, username)
|
||||||
"website %s") % (username, sitename))
|
|
||||||
return website_directory
|
return website_directory
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def set_file_ssh_authorized_keys(username, ssh_keys):
|
||||||
|
"""
|
||||||
|
This task sets the authorized keys for ssh logins.
|
||||||
|
|
||||||
|
:param str username: the user name
|
||||||
|
:param list ssh_key: an ssh_key
|
||||||
|
:raises Exception: if the update of the creation or update of ssh
|
||||||
|
authorized_keys failed
|
||||||
|
:return: the name of the authorized_keys file
|
||||||
|
:rtype: str
|
||||||
|
|
||||||
|
"""
|
||||||
|
ssh_authorized_keys_file = _build_authorized_keys_path(username)
|
||||||
|
if ssh_keys:
|
||||||
|
try:
|
||||||
|
authkeystemp, filename = mkstemp()
|
||||||
|
conffile = os.fdopen(authkeystemp, 'w')
|
||||||
|
conffile.write("\n".join(ssh_keys))
|
||||||
|
finally:
|
||||||
|
if conffile:
|
||||||
|
conffile.close()
|
||||||
|
try:
|
||||||
|
subprocess.check_output([
|
||||||
|
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||||
|
'-m', '0500', '-d', os.path.dirname(ssh_authorized_keys_file)],
|
||||||
|
stderr=subprocess.STDOUT)
|
||||||
|
subprocess.check_output([
|
||||||
|
SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
|
||||||
|
'-m', '0400', filename, ssh_authorized_keys_file],
|
||||||
|
stderr=subprocess.STDOUT)
|
||||||
|
subprocess.check_output([
|
||||||
|
SUDO_CMD, RM_CMD, filename], stderr=subprocess.STDOUT)
|
||||||
|
_LOGGER.info(
|
||||||
|
'set %d authorized_keys for user %s', len(ssh_keys), username)
|
||||||
|
except subprocess.CalledProcessError as cpe:
|
||||||
|
log_and_raise(
|
||||||
|
cpe, 'could not write authorized_keys file for user %s',
|
||||||
|
username)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subprocess.check_output([
|
||||||
|
SUDO_CMD, RM_CMD, '-rf',
|
||||||
|
os.path.dirname(ssh_authorized_keys_file)],
|
||||||
|
stderr=subprocess.STDOUT)
|
||||||
|
_LOGGER.info(
|
||||||
|
'deleted authorized_keys of user %s', username)
|
||||||
|
except subprocess.CalledProcessError as cpe:
|
||||||
|
log_and_raise(
|
||||||
|
cpe, 'could not remove the authorized_keys file of user %s',
|
||||||
|
username)
|
||||||
|
return ssh_authorized_keys_file
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
"""
|
|
||||||
This module defines exceptions for gvafile.
|
|
||||||
|
|
||||||
"""
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
|
|
||||||
class GVAFileException(Exception):
|
|
||||||
"""
|
|
||||||
Generic Exception class for gvafile.
|
|
||||||
|
|
||||||
"""
|
|
|
@ -42,4 +42,6 @@ BROKER_URL = get_env_setting('GVAFILE_BROKER_URL')
|
||||||
########## GVAFILE CONFIGURATION
|
########## GVAFILE CONFIGURATION
|
||||||
GVAFILE_SFTP_DIRECTORY = get_env_setting('GVAFILE_SFTP_DIRECTORY')
|
GVAFILE_SFTP_DIRECTORY = get_env_setting('GVAFILE_SFTP_DIRECTORY')
|
||||||
GVAFILE_MAIL_DIRECTORY = get_env_setting('GVAFILE_MAIL_DIRECTORY')
|
GVAFILE_MAIL_DIRECTORY = get_env_setting('GVAFILE_MAIL_DIRECTORY')
|
||||||
|
GVAFILE_SFTP_AUTHKEYS_DIRECTORY = get_env_setting(
|
||||||
|
'GVAFILE_SFTP_AUTHKEYS_DIRECTORY')
|
||||||
########## END GVAFILE CONFIGURATION
|
########## END GVAFILE CONFIGURATION
|
||||||
|
|
Loading…
Reference in a new issue