Merge branch 'unstable' into feature224-envvarforscripts

This commit is contained in:
Jérôme Lebleu 2016-04-25 17:41:45 +02:00
commit b3cfbc21ac
72 changed files with 2561 additions and 2066 deletions

View file

@ -5,10 +5,6 @@ import os
import sys
import argparse
import moulinette
from moulinette.actionsmap import ActionsMap
from moulinette.interfaces.cli import colorize, get_locale
# Either we are in a development environment or not
IN_DEVEL = False
@ -35,6 +31,11 @@ if IN_DEVEL:
LOG_DIR = os.path.join(basedir, 'log')
import moulinette
from moulinette.actionsmap import ActionsMap
from moulinette.interfaces.cli import colorize, get_locale
# Initialization & helpers functions -----------------------------------
def _die(message, title='Error:'):
@ -50,7 +51,7 @@ def _parse_cli_args():
help="Don't use actions map cache",
)
parser.add_argument('--output-as',
choices=['json', 'plain'], default=None,
choices=['json', 'plain', 'none'], default=None,
help="Output result in another format",
)
parser.add_argument('--debug',
@ -149,6 +150,11 @@ def _init_moulinette(debug=False, verbose=False, quiet=False):
'handlers': [],
'propagate': True,
},
'moulinette.interface': {
'level': level,
'handlers': handlers,
'propagate': False,
},
},
'root': {
'level': level,

View file

@ -5,10 +5,6 @@ import os
import sys
import argparse
import moulinette
from moulinette.actionsmap import ActionsMap
from moulinette.interfaces.cli import colorize
# Either we are in a development environment or not
IN_DEVEL = False
@ -39,6 +35,11 @@ if IN_DEVEL:
LOG_DIR = os.path.join(basedir, 'log')
import moulinette
from moulinette.actionsmap import ActionsMap
from moulinette.interfaces.cli import colorize
# Initialization & helpers functions -----------------------------------
def _die(message, title='Error:'):

77
bin/yunopaste Executable file
View file

@ -0,0 +1,77 @@
#!/bin/bash
set -e
set -u
PASTE_URL="https://paste.yunohost.org"
_die() {
printf "Error: %s\n" "$*"
exit 1
}
check_dependencies() {
curl -V > /dev/null 2>&1 || _die "This script requires curl."
}
paste_data() {
json=$(curl -X POST -s -d "$1" "${PASTE_URL}/documents")
[[ -z "$json" ]] && _die "Unable to post the data to the server."
key=$(echo "$json" \
| python -c 'import json,sys;o=json.load(sys.stdin);print o["key"]' \
2>/dev/null)
[[ -z "$key" ]] && _die "Unable to parse the server response."
echo "${PASTE_URL}/${key}"
}
usage() {
printf "Usage: ${0} [OPTION]...
Read from input stream and paste the data to the YunoHost
Haste server.
For example, to paste the output of the YunoHost diagnosis, you
can simply execute the following:
yunohost tools diagnosis | ${0}
It will return the URL where you can access the pasted data.
Options:
-h, --help show this help message and exit
"
}
main() {
# parse options
while (( ${#} )); do
case "${1}" in
--help|-h)
usage
exit 0
;;
*)
echo "Unknown parameter detected: ${1}" >&2
echo >&2
usage >&2
exit 1
;;
esac
shift 1
done
# check input stream
read -t 0 || {
echo -e "Invalid usage: No input is provided.\n" >&2
usage
exit 1
}
paste_data "$(cat)"
}
check_dependencies
main "${@}"

View file

@ -516,6 +516,7 @@ app:
initdb:
action_help: Create database and initialize it with optionnal attached script
api: POST /tools/initdb
deprecated: true
arguments:
user:
help: Name of the DB user
@ -956,60 +957,36 @@ service:
default: 50
type: int
### service_regenconf()
regenconf:
action_help: >
Regenerate the configuration file(s) for a service and compare the result
with the existing configuration file.
Prints the differences between files if any.
### service_regen_conf()
regen-conf:
action_help: Regenerate the configuration file(s) for a service
api: PUT /services/regenconf
configuration:
lock: false
deprecated_alias:
- regenconf
arguments:
-s:
full: --service
help: Regenerate configuration for a specfic service
-f:
full: --force
help: Override the current configuration with the newly generated one, even if it has been modified
names:
help: Services name to regenerate configuration of
nargs: "*"
metavar: NAME
-d:
full: --with-diff
help: Show differences in case of configuration changes
action: store_true
### service_safecopy()
safecopy:
action_help: >
Check if the specific file has been modified and display differences.
Stores the file hash in the services.yml file
arguments:
new_conf_file:
help: Path to the desired conf file
conf_file:
help: Path to the targeted conf file
-s:
full: --service
help: Service name attached to the conf file
extra:
required: True
-f:
full: --force
help: Override the current configuration with the newly generated one, even if it has been modified
help: >
Override all manual modifications in configuration
files
action: store_true
### service_saferemove()
saferemove:
action_help: >
Check if the specific file has been modified before removing it.
Backup the file in /home/yunohost.backup
arguments:
conf_file:
help: Path to the targeted conf file
-s:
full: --service
help: Service name attached to the conf file
extra:
required: True
-f:
full: --force
help: Force file deletion
-n:
full: --dry-run
help: Show what would have been regenerated
action: store_true
-p:
full: --list-pending
help: List pending configuration files and exit
action: store_true
#############################
@ -1378,8 +1355,15 @@ hook:
nargs: "*"
-a:
full: --args
help: Ordered list of arguments to pass to the script
help: Ordered list of arguments to pass to the scripts
nargs: "*"
-q:
full: --no-trace
help: Do not print each command that will be executed
action: store_true
-d:
full: --chdir
help: The directory from where the scripts will be executed
### hook_exec()
exec:
@ -1389,7 +1373,8 @@ hook:
help: Path of the script to execute
-a:
full: --args
help: Arguments to pass to the script
help: Ordered list of arguments to pass to the script
nargs: "*"
--raise-on-error:
help: Raise if the script returns a non-zero exit code
action: store_true

View file

@ -48,27 +48,33 @@ ynh_package_install() {
# usage: ynh_package_install_from_equivs controlfile
# | arg: controlfile - path of the equivs control file
ynh_package_install_from_equivs() {
controlfile=$1
# install equivs package as needed
ynh_package_is_installed 'equivs' \
|| ynh_package_install equivs
# retrieve package information
pkgname=$(grep '^Package: ' $1 | cut -d' ' -f 2)
pkgversion=$(grep '^Version: ' $1 | cut -d' ' -f 2)
pkgname=$(grep '^Package: ' $controlfile | cut -d' ' -f 2)
pkgversion=$(grep '^Version: ' $controlfile | cut -d' ' -f 2)
[[ -z "$pkgname" || -z "$pkgversion" ]] \
&& echo "Invalid control file" && exit 1
controlfile=$(readlink -f "$1")
# update packages cache
ynh_package_update
# build and install the package
TMPDIR=$(ynh_mkdir_tmp)
(cd $TMPDIR \
&& equivs-build "$controlfile" 1>/dev/null \
(cp "$controlfile" "${TMPDIR}/control" \
&& cd "$TMPDIR" \
&& equivs-build ./control 1>/dev/null \
&& sudo dpkg --force-depends \
-i "./${pkgname}_${pkgversion}_all.deb" 2>&1 \
&& sudo apt-get -f -y -qq install) \
&& ([[ -n "$TMPDIR" ]] && rm -rf $TMPDIR)
# check if the package is actually installed
ynh_package_is_installed "$pkgname"
}
# Remove package(s)

View file

@ -20,6 +20,17 @@ ynh_user_get_info() {
sudo yunohost user info "$1" --output-as plain | ynh_get_plain_key "$2"
}
# Get the list of YunoHost users
#
# example: for u in $(ynh_user_list); do ...
#
# usage: ynh_user_list
# | ret: string - one username per line
ynh_user_list() {
sudo yunohost user list --output-as plain --quiet \
| awk '/^##username$/{getline; print}'
}
# Check if a user exists on the system
#
# usage: ynh_system_user_exists username

View file

@ -1,4 +1,4 @@
backup_dir="$1/conf/ynh/mysql"
sudo mkdir -p $backup_dir
sudo cp -a /etc/yunohost/mysql $backup_dir/
sudo cp -a /etc/yunohost/mysql "${backup_dir}/root_pwd"

View file

@ -1,7 +1,4 @@
backup_dir="$1/conf/ynh/"
backup_dir_legacy="$1/yunohost/"
backup_dir="$1/conf/ynh"
sudo mkdir -p $backup_dir
sudo mkdir -p $backup_dir_legacy
sudo cp -a /etc/yunohost/current_host $backup_dir
sudo cp -a /etc/yunohost/current_host $backup_dir_legacy
sudo cp -a /etc/yunohost/current_host "${backup_dir}/current_host"

122
data/hooks/conf_regen/01-yunohost Normal file → Executable file
View file

@ -1,25 +1,111 @@
set -e
#!/bin/bash
force=$1
set -e
cd /usr/share/yunohost/templates/yunohost
services_path="/etc/yunohost/services.yml"
sudo mkdir -p /etc/yunohost
do_init_regen() {
if [[ $EUID -ne 0 ]]; then
echo "You must be root to run this script" 1>&2
exit 1
fi
if [ ! -f /etc/yunohost/current_host ]; then
echo "yunohost.org" | sudo tee /etc/yunohost/current_host
fi
cd /usr/share/yunohost/templates/yunohost
if [ ! -f /etc/yunohost/firewall.yml ]; then
sudo cp firewall.yml /etc/yunohost/firewall.yml
fi
[[ -d /etc/yunohost ]] || mkdir -p /etc/yunohost
if [ ! -f /etc/yunohost/services.yml ]; then
sudo cp services.yml /etc/yunohost/services.yml
fi
# set default current_host
[[ -f /etc/yunohost/current_host ]] \
|| echo "yunohost.org" > /etc/yunohost/current_host
# Allow users to access /media directory
if [ ! -d /etc/skel/media ]; then
mkdir -p /media
ln -s /media /etc/skel/
fi
# copy default services and firewall
[[ -f $services_path ]] \
|| cp services.yml "$services_path"
[[ -f /etc/yunohost/firewall.yml ]] \
|| cp firewall.yml /etc/yunohost/firewall.yml
# allow users to access /media directory
[[ -d /etc/skel/media ]] \
|| (mkdir -p /media && ln -s /media /etc/skel/media)
}
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/yunohost
# update services.yml
if [[ -f $services_path ]]; then
tmp_services_path="${services_path}-tmp"
new_services_path="${services_path}-new"
sudo cp "$services_path" "$tmp_services_path"
_update_services "$new_services_path" || {
sudo mv "$tmp_services_path" "$services_path"
exit 1
}
if [[ -f $new_services_path ]]; then
# replace services.yml with new one
sudo mv "$new_services_path" "$services_path"
sudo mv "$tmp_services_path" "${services_path}-old"
else
sudo rm -f "$tmp_services_path"
fi
else
sudo cp services.yml /etc/yunohost/services.yml
fi
}
_update_services() {
sudo python2 - << EOF
import yaml
with open('services.yml') as f:
new_services = yaml.load(f)
with open('/etc/yunohost/services.yml') as f:
services = yaml.load(f)
updated = False
for service, conf in new_services.items():
# remove service with empty conf
if not conf:
if service in services:
print("removing '{0}' from services".format(service))
del services[service]
updated = True
# add new service
elif not services.get(service, None):
print("adding '{0}' to services".format(service))
services[service] = conf
updated = True
# update service conf
else:
conffiles = services[service].pop('conffiles', {})
if services[service] != conf:
print("update '{0}' service".format(service))
services[service].update(conf)
updated = True
if conffiles:
services[service]['conffiles'] = conffiles
if updated:
with open('/etc/yunohost/services.yml-new', 'w') as f:
yaml.safe_dump(services, f, default_flow_style=False)
EOF
}
FORCE=${2:-0}
DRY_RUN=${3:-0}
case "$1" in
pre)
do_pre_regen $4
;;
post)
;;
init)
do_init_regen
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

135
data/hooks/conf_regen/02-ssl Normal file → Executable file
View file

@ -1,64 +1,93 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [ ! -f /etc/yunohost/installed ]; then
sudo cp $1 $2
else
if [ $force ]; then
sudo yunohost service safecopy \
-s ssl $1 $2 --force
else
sudo yunohost service safecopy \
-s ssl $1 $2
fi
fi
ssl_dir="/usr/share/yunohost/yunohost-config/ssl/yunoCA"
do_init_regen() {
if [[ $EUID -ne 0 ]]; then
echo "You must be root to run this script" 1>&2
exit 1
fi
# create certs and SSL directories
mkdir -p "/etc/yunohost/certs/yunohost.org"
mkdir -p "${ssl_dir}/"{ca,certs,crl,newcerts}
# initialize some files
[[ -f "${ssl_dir}/serial" ]] \
|| echo "00" > "${ssl_dir}/serial"
[[ -f "${ssl_dir}/index.txt" ]] \
|| touch "${ssl_dir}/index.txt"
openssl_conf="/usr/share/yunohost/templates/ssl/openssl.cnf"
# create default certificates
if [[ ! -f /etc/yunohost/certs/yunohost.org/ca.pem ]]; then
openssl req -x509 -new -config "$openssl_conf" \
-days 3650 -out "${ssl_dir}/ca/cacert.pem" \
-keyout "${ssl_dir}/ca/cakey.pem" -nodes -batch 2>&1
cp "${ssl_dir}/ca/cacert.pem" \
/etc/yunohost/certs/yunohost.org/ca.pem
ln -sf /etc/yunohost/certs/yunohost.org/ca.pem \
/etc/ssl/certs/ca-yunohost_crt.pem
update-ca-certificates
fi
if [[ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]]; then
openssl req -new -config "$openssl_conf" \
-days 730 -out "${ssl_dir}/certs/yunohost_csr.pem" \
-keyout "${ssl_dir}/certs/yunohost_key.pem" -nodes -batch 2>&1
openssl ca -config "$openssl_conf" \
-days 730 -in "${ssl_dir}/certs/yunohost_csr.pem" \
-out "${ssl_dir}/certs/yunohost_crt.pem" -batch 2>&1
last_cert=$(ls $ssl_dir/newcerts/*.pem | sort -V | tail -n 1)
chmod 640 "${ssl_dir}/certs/yunohost_key.pem"
chmod 640 "$last_cert"
cp "${ssl_dir}/certs/yunohost_key.pem" \
/etc/yunohost/certs/yunohost.org/key.pem
cp "$last_cert" \
/etc/yunohost/certs/yunohost.org/crt.pem
ln -sf /etc/yunohost/certs/yunohost.org/crt.pem \
/etc/ssl/certs/yunohost_crt.pem
ln -sf /etc/yunohost/certs/yunohost.org/key.pem \
/etc/ssl/private/yunohost_key.pem
fi
}
cd /usr/share/yunohost/templates/ssl
ssl_dir=/usr/share/yunohost/yunohost-config/ssl/yunoCA
do_pre_regen() {
pending_dir=$1
sudo mkdir -p /etc/yunohost/certs/yunohost.org
sudo mkdir -p $ssl_dir/{ca,certs,crl,newcerts}
cd /usr/share/yunohost/templates/ssl
safe_copy openssl.cnf $ssl_dir/openssl.cnf
install -D -m 644 openssl.cnf "${pending_dir}/${ssl_dir}/openssl.cnf"
}
[ -f $ssl_dir/serial ] \
|| (echo "00" | sudo tee $ssl_dir/serial)
do_post_regen() {
regen_conf_files=$1
[ -f $ssl_dir/index.txt ] \
|| sudo touch $ssl_dir/index.txt
# TODO: regenerate certificates if conf changed?
}
if [ ! -f /etc/yunohost/certs/yunohost.org/ca.pem ]; then
sudo openssl req -x509 -new -config $ssl_dir/openssl.cnf \
-days 3650 -out $ssl_dir/ca/cacert.pem \
-keyout $ssl_dir/ca/cakey.pem -nodes -batch
sudo cp $ssl_dir/ca/cacert.pem \
/etc/yunohost/certs/yunohost.org/ca.pem
sudo ln -sf /etc/yunohost/certs/yunohost.org/ca.pem \
/etc/ssl/certs/ca-yunohost_crt.pem
sudo update-ca-certificates
fi
FORCE=${2:-0}
DRY_RUN=${3:-0}
if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then
sudo openssl req -new -config $ssl_dir/openssl.cnf \
-days 730 -out $ssl_dir/certs/yunohost_csr.pem \
-keyout $ssl_dir/certs/yunohost_key.pem -nodes -batch
sudo openssl ca -config $ssl_dir/openssl.cnf \
-days 730 -in $ssl_dir/certs/yunohost_csr.pem \
-out $ssl_dir/certs/yunohost_crt.pem -batch
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
init)
do_init_regen
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
last_cert=$(ls $ssl_dir/newcerts/*.pem | sort -V | tail -n 1)
sudo chmod 640 $ssl_dir/certs/yunohost_key.pem
sudo chmod 640 $last_cert
sudo cp $ssl_dir/certs/yunohost_key.pem \
/etc/yunohost/certs/yunohost.org/key.pem
sudo cp $last_cert \
/etc/yunohost/certs/yunohost.org/crt.pem
sudo ln -sf /etc/yunohost/certs/yunohost.org/crt.pem \
/etc/ssl/certs/yunohost_crt.pem
sudo ln -sf /etc/yunohost/certs/yunohost.org/key.pem \
/etc/ssl/private/yunohost_key.pem
fi
exit 0

63
data/hooks/conf_regen/03-ssh Normal file → Executable file
View file

@ -1,30 +1,45 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [ $force ]; then
sudo yunohost service safecopy \
-s ssh \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s ssh \
$1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/ssh
# only overwrite SSH configuration on an ISO installation
if [[ ! -f /etc/yunohost/from_script ]]; then
# do not listen to IPv6 if unavailable
[[ -f /proc/net/if_inet6 ]] \
|| sed -i "s/ListenAddress ::/#ListenAddress ::/g" sshd_config
install -D -m 644 sshd_config "${pending_dir}/etc/ssh/sshd_config"
fi
}
cd /usr/share/yunohost/templates/ssh
do_post_regen() {
regen_conf_files=$1
# Only overwrite SSH configuration on an ISO installation
if [ ! -f /etc/yunohost/from_script ]; then
if [[ ! -f /etc/yunohost/from_script ]]; then
[[ -z "$regen_conf_files" ]] \
|| sudo service ssh restart
fi
}
# Do not listen to IPv6 if unavailable
if [ ! -f /proc/net/if_inet6 ]; then
sudo sed -i "s/ListenAddress ::/#ListenAddress ::/g" sshd_config
fi
safe_copy sshd_config /etc/ssh/sshd_config
sudo service ssh restart
fi
FORCE=${2:-0}
DRY_RUN=${3:-0}
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

165
data/hooks/conf_regen/06-slapd Normal file → Executable file
View file

@ -1,71 +1,118 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [ ! -f /etc/yunohost/installed ]; then
sudo cp $1 $2
else
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s slapd $1 $2 --force
else
sudo yunohost service safecopy \
-s slapd $1 $2
fi
fi
do_init_regen() {
if [[ $EUID -ne 0 ]]; then
echo "You must be root to run this script" 1>&2
exit 1
fi
do_pre_regen ""
# fix some permissions
chown root:openldap /etc/ldap/slapd.conf
chown -R openldap:openldap /etc/ldap/schema/
# check the slapd config file at first
slaptest -Q -u -f /etc/ldap/slapd.conf
# regenerate LDAP config directory from slapd.conf
rm -Rf /etc/ldap/slapd.d
mkdir /etc/ldap/slapd.d
slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/ 2>&1
chown -R openldap:openldap /etc/ldap/slapd.d/
service slapd restart
}
cd /usr/share/yunohost/templates/slapd
do_pre_regen() {
pending_dir=$1
# Remove legacy configuration file
[ ! -f /etc/yunohost/installed ] \
|| sudo yunohost service saferemove -s slapd \
/etc/ldap/slapd-yuno.conf
cd /usr/share/yunohost/templates/slapd
# Retrieve current backend
backend=$(sudo slapcat -n 0 | sed -n 's/^dn: olcDatabase={1}\(.*\),cn=config$/\1/p')
# remove legacy configuration file
[ ! -f /etc/ldap/slapd-yuno.conf ] \
|| touch "${pending_dir}/etc/ldap/slapd-yuno.conf"
# Save current database in case of a backend change
BACKEND_CHANGE=0
BACKUP_DIR="/var/backups/dc=yunohost,dc=org-${backend}-$(date +%s)"
if [[ -n "$backend" && "$backend" != "mdb" && "$force" == "True" ]]; then
BACKEND_CHANGE=1
sudo mkdir -p "$BACKUP_DIR"
sudo slapcat -b dc=yunohost,dc=org \
-l "${BACKUP_DIR}/dc=yunohost-dc=org.ldif"
fi
# create needed directories
ldap_dir="${pending_dir}/etc/ldap"
schema_dir="${ldap_dir}/schema"
mkdir -p "$ldap_dir" "$schema_dir"
safe_copy sudo.schema /etc/ldap/schema/sudo.schema
safe_copy mailserver.schema /etc/ldap/schema/mailserver.schema
safe_copy ldap.conf /etc/ldap/ldap.conf
safe_copy slapd.default /etc/default/slapd
safe_copy slapd.conf /etc/ldap/slapd.conf
# copy configuration files
cp -a ldap.conf slapd.conf "$ldap_dir"
cp -a sudo.schema mailserver.schema "$schema_dir"
# Fix some permissions
sudo chown root:openldap /etc/ldap/slapd.conf
sudo chown -R openldap:openldap /etc/ldap/schema/
sudo chown -R openldap:openldap /etc/ldap/slapd.d/
install -D -m 644 slapd.default "${pending_dir}/etc/default/slapd"
}
# Check the slapd config file at first
sudo slaptest -Q -u -f /etc/ldap/slapd.conf
do_post_regen() {
regen_conf_files=$1
if [[ $BACKEND_CHANGE -eq 1 ]]; then
# Regenerate LDAP config directory and import database as root
# since the admin user may be unavailable
sudo sh -c "rm -Rf /etc/ldap/slapd.d;
mkdir /etc/ldap/slapd.d;
slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d;
chown -R openldap:openldap /etc/ldap/slapd.d;
slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org \
-l '${BACKUP_DIR}/dc=yunohost-dc=org.ldif';
chown -R openldap:openldap /var/lib/ldap" 2>&1
else
# Regenerate LDAP config directory from slapd.conf
sudo rm -Rf /etc/ldap/slapd.d
sudo mkdir /etc/ldap/slapd.d
sudo slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/ 2>&1
sudo chown -R openldap:openldap /etc/ldap/slapd.d/
fi
# fix some permissions
sudo chown root:openldap /etc/ldap/slapd.conf
sudo chown -R openldap:openldap /etc/ldap/schema/
sudo chown -R openldap:openldap /etc/ldap/slapd.d/
sudo service slapd force-reload
[ -z "$regen_conf_files" ] && exit 0
# retrieve current and new backends
curr_backend=$(sudo slapcat -n 0 \
| sed -n 's/^dn: olcDatabase={1}\(.*\),cn=config$/\1/p')
new_backend=$(grep '^database' /etc/ldap/slapd.conf | awk '{print $2}')
# save current database in case of a backend change
backend_change=0
backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)"
if [[ -n "$curr_backend" && "$curr_backend" != "$new_backend" ]]; then
backend_change=1
sudo mkdir -p "$backup_dir"
sudo slapcat -b dc=yunohost,dc=org \
-l "${backup_dir}/dc=yunohost-dc=org.ldif"
fi
# check the slapd config file at first
sudo slaptest -Q -u -f /etc/ldap/slapd.conf
if [[ $backend_change -eq 1 ]]; then
# regenerate LDAP config directory and import database as root
# since the admin user may be unavailable
sudo sh -c "rm -Rf /etc/ldap/slapd.d;
mkdir /etc/ldap/slapd.d;
slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d;
chown -R openldap:openldap /etc/ldap/slapd.d;
slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org \
-l '${backup_dir}/dc=yunohost-dc=org.ldif';
chown -R openldap:openldap /var/lib/ldap" 2>&1
else
# regenerate LDAP config directory from slapd.conf
sudo rm -Rf /etc/ldap/slapd.d
sudo mkdir /etc/ldap/slapd.d
sudo slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/ 2>&1
sudo chown -R openldap:openldap /etc/ldap/slapd.d/
fi
sudo service slapd force-reload
}
FORCE=${2:-0}
DRY_RUN=${3:-0}
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
init)
do_init_regen
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

48
data/hooks/conf_regen/09-nslcd Normal file → Executable file
View file

@ -1,26 +1,36 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s nslcd \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s nslcd \
$1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/nslcd
install -D -m 644 nslcd.conf "${pending_dir}/etc/nslcd.conf"
}
cd /usr/share/yunohost/templates/nslcd
do_post_regen() {
regen_conf_files=$1
safe_copy nslcd.conf /etc/nslcd.conf
[[ -z "$regen_conf_files" ]] \
|| sudo service nslcd restart
}
# Fix: Add a blank line at the end of the file
# to avoid nscld restart failure
echo -e "\n" | sudo tee -a /etc/nslcd.conf
FORCE=${2:-0}
DRY_RUN=${3:-0}
sudo service nslcd restart
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

120
data/hooks/conf_regen/12-metronome Normal file → Executable file
View file

@ -1,66 +1,76 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s metronome \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s metronome \
$1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/metronome
# create directories for pending conf
metronome_dir="${pending_dir}/etc/metronome"
metronome_conf_dir="${metronome_dir}/conf.d"
mkdir -p "$metronome_conf_dir"
# retrieve variables
main_domain=$(cat /etc/yunohost/current_host)
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
# install main conf file
cat metronome.cfg.lua \
| sed "s/{{ main_domain }}/${main_domain}/g" \
> "${metronome_dir}/metronome.cfg.lua"
# add domain conf files
for domain in $domain_list; do
cat domain.tpl.cfg.lua \
| sed "s/{{ domain }}/${domain}/g" \
> "${metronome_conf_dir}/${domain}.cfg.lua"
done
# remove old domain conf files
conf_files=$(ls -1 /etc/metronome/conf.d \
| awk '/^[^\.]+\.[^\.]+.*\.cfg\.lua$/ { print $1 }')
for file in $conf_files; do
domain=${file%.cfg.lua}
[[ $domain_list =~ $domain ]] \
|| touch "${metronome_conf_dir}/${file}"
done
}
cd /usr/share/yunohost/templates/metronome
do_post_regen() {
regen_conf_files=$1
# Copy configuration files
main_domain=$(cat /etc/yunohost/current_host)
cat metronome.cfg.lua.sed \
| sed "s/{{ main_domain }}/$main_domain/g" \
| sudo tee metronome.cfg.lua
safe_copy metronome.cfg.lua /etc/metronome/metronome.cfg.lua
# fix some permissions
sudo chown -R metronome: /var/lib/metronome/
sudo chown -R metronome: /etc/metronome/conf.d/
need_restart=False
sudo mkdir -p /etc/metronome/conf.d
# retrieve variables
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
domain_list=$(sudo yunohost domain list --output-as plain)
# create metronome directories for domains
for domain in $domain_list; do
sudo mkdir -p "/var/lib/metronome/${domain//./%2e}/pep"
done
# Copy a configuration file for each YunoHost domain
for domain in $domain_list; do
sanitzed_domain="$(echo $domain | sed 's/\./%2e/g')"
sudo mkdir -p /var/lib/metronome/$sanitzed_domain/pep
[[ -z "$regen_conf_files" ]] \
|| sudo service metronome restart
}
cat domain.cfg.lua.sed \
| sed "s/{{ domain }}/$domain/g" \
| sudo tee $domain.cfg.lua
if [[ $(safe_copy $domain.cfg.lua /etc/metronome/conf.d/$domain.cfg.lua | tail -n1) == "True" ]]; then
need_restart=True
fi
done
FORCE=${2:-0}
DRY_RUN=${3:-0}
# Remove old domains files
for file in /etc/metronome/conf.d/*; do
domain=$(echo $file \
| sed 's|/etc/metronome/conf.d/||' \
| sed 's|.cfg.lua||')
sanitzed_domain="$(echo $domain | sed 's/\./%2e/g')"
[[ $domain_list =~ $domain ]] \
|| ([[ $(sudo yunohost service saferemove -s metronome $file | tail -n1) == "True" ]] \
&& sudo rm -rf /var/lib/metronome/$sanitzed_domain)
done
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
# Create domain directory
sudo chown -R metronome: /var/lib/metronome/
sudo chown -R metronome: /etc/metronome/conf.d/
# Restart if need be
if [[ "$need_restart" == "True" ]]; then
sudo service metronome restart
else
sudo service metronome reload \
|| sudo service metronome restart
fi
exit 0

153
data/hooks/conf_regen/15-nginx Normal file → Executable file
View file

@ -1,86 +1,101 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [ ! -f /etc/yunohost/installed ]; then
sudo cp $1 $2
else
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s nginx \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s nginx \
$1 $2
fi
fi
do_init_regen() {
if [[ $EUID -ne 0 ]]; then
echo "You must be root to run this script" 1>&2
exit 1
fi
do_pre_regen ""
}
cd /usr/share/yunohost/templates/nginx
do_pre_regen() {
pending_dir=$1
# Copy plain single configuration files
files="ssowat.conf
global.conf
yunohost_admin.conf
yunohost_admin.conf.inc
yunohost_api.conf.inc
yunohost_panel.conf.inc"
cd /usr/share/yunohost/templates/nginx
for file in $files; do
safe_copy $file /etc/nginx/conf.d/$file
done
nginx_dir="${pending_dir}/etc/nginx"
nginx_conf_dir="${nginx_dir}/conf.d"
mkdir -p "$nginx_conf_dir"
# install plain conf files
cp plain/* "$nginx_conf_dir"
if [ -f /etc/yunohost/installed ]; then
# probably run with init: just disable default site, restart NGINX and exit
if [[ -z "$pending_dir" ]]; then
rm -f "${nginx_dir}/sites-enabled/default"
service nginx restart
exit 0
fi
need_restart=False
domain_list=$(sudo yunohost domain list --output-as plain)
# retrieve variables
main_domain=$(cat /etc/yunohost/current_host)
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
# Copy a configuration file for each YunoHost domain
for domain in $domain_list; do
sudo mkdir -p /etc/nginx/conf.d/$domain.d
cat server.conf.sed \
| sed "s/{{ domain }}/$domain/g" \
| sudo tee $domain.conf
[[ $(safe_copy $domain.conf /etc/nginx/conf.d/$domain.conf | tail -n1) == "True" ]] \
&& need_restart=True
# add domain conf files
for domain in $domain_list; do
domain_conf_dir="${nginx_conf_dir}/${domain}.d"
mkdir -p "$domain_conf_dir"
[ -f /etc/nginx/conf.d/$domain.d/yunohost_local.conf ] \
&& [[ $main_domain != $domain ]] \
&& sudo yunohost service saferemove -s nginx \
/etc/nginx/conf.d/$domain.d/yunohost_local.conf
done
# NGINX server configuration
cat server.tpl.conf \
| sed "s/{{ domain }}/${domain}/g" \
> "${nginx_conf_dir}/${domain}.conf"
[[ $main_domain != $domain ]] \
&& touch "${domain_conf_dir}/yunohost_local.conf" \
|| cp yunohost_local.conf "${domain_conf_dir}/yunohost_local.conf"
done
# Copy 'yunohost.local' to the main domain conf directory
main_domain=$(cat /etc/yunohost/current_host)
safe_copy yunohost_local.conf \
/etc/nginx/conf.d/$main_domain.d/yunohost_local.conf
# remove old domain conf files
conf_files=$(ls -1 /etc/nginx/conf.d \
| awk '/^[^\.]+\.[^\.]+.*\.conf$/ { print $1 }')
for file in $conf_files; do
domain=${file%.conf}
[[ $domain_list =~ $domain ]] \
|| touch "${nginx_conf_dir}/${file}"
done
# disable default site
mkdir -p "${nginx_dir}/sites-enabled"
touch "${nginx_dir}/sites-enabled/default"
}
# Remove old domains files
for file in /etc/nginx/conf.d/*.*.conf; do
domain=$(echo $file \
| sed 's|/etc/nginx/conf.d/||' \
| sed 's|.conf||')
[[ $domain_list =~ $domain ]] \
|| ([[ $(sudo yunohost service saferemove -s nginx $file) == "True" ]] \
&& (sudo rm -r /etc/nginx/conf.d/$domain.d || true))
done
do_post_regen() {
regen_conf_files=$1
else
[ ! -f /etc/nginx/sites-available/default ] \
|| sudo rm -f /etc/nginx/sites-enabled/default
need_restart=True
fi
[ -z "$regen_conf_files" ] && exit 0
# Restart if need be
if [[ "$need_restart" == "True" ]]; then
sudo service nginx restart
else
sudo service nginx reload \
|| sudo service nginx restart
fi
# retrieve variables
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
# create NGINX conf directories for domains
for domain in $domain_list; do
sudo mkdir -p "/etc/nginx/conf.d/${domain}.d"
done
sudo service nginx restart
}
FORCE=${2:-0}
DRY_RUN=${3:-0}
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
init)
do_init_regen
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

96
data/hooks/conf_regen/19-postfix Normal file → Executable file
View file

@ -1,56 +1,56 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s postfix \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s postfix \
$1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/postfix
postfix_dir="${pending_dir}/etc/postfix"
mkdir -p "$postfix_dir"
# install plain conf files
cp plain/* "$postfix_dir"
# prepare main.cf conf file
main_domain=$(cat /etc/yunohost/current_host)
cat main.cf \
| sed "s/{{ main_domain }}/${main_domain}/g" \
> "${postfix_dir}/main.cf"
# adapt it for IPv4-only hosts
if [ ! -f /proc/net/if_inet6 ]; then
sed -i \
's/ \[::ffff:127.0.0.0\]\/104 \[::1\]\/128//g' \
"${postfix_dir}/main.cf"
sed -i \
's/inet_interfaces = all/&\ninet_protocols = ipv4/' \
"${postfix_dir}/main.cf"
fi
}
cd /usr/share/yunohost/templates/postfix
do_post_regen() {
regen_conf_files=$1
# Copy plain single configuration files
files="header_checks
ldap-accounts.cf
ldap-aliases.cf
ldap-domains.cf
master.cf
sender_canonical
smtp_reply_filter"
[[ -z "$regen_conf_files" ]] \
|| sudo service postfix restart
}
for file in $files; do
safe_copy $file /etc/postfix/$file
done
FORCE=${2:-0}
DRY_RUN=${3:-0}
main_domain=$(cat /etc/yunohost/current_host)
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
# Replace main domain in the main configuration file
cat main.cf.sed \
| sed "s/{{ main_domain }}/$main_domain/g" \
| sudo tee main.cf
# And adapt it to IPv4-only hosts
if [ ! -f /proc/net/if_inet6 ]; then
sudo sed -i \
's/ \[::ffff:127.0.0.0\]\/104 \[::1\]\/128//g' \
main.cf
sudo sed -i \
's/inet_interfaces = all/inet_interfaces = all\ninet_protocols = ipv4/' \
main.cf
fi
if [[ $(safe_copy main.cf /etc/postfix/main.cf) == "True" ]]; then
sudo service postfix restart
else
sudo service postfix reload \
|| sudo service postfix restart
fi
exit 0

View file

@ -1,43 +0,0 @@
set -e
# Execute this hook only if we force the configuration regeneration
if [[ "$1" == "True" ]]; then
# Add new email services
sudo yunohost service add rspamd -l /var/log/mail.log \
|| echo "rspamd is already listed in services"
sudo yunohost service add rmilter -l /var/log/mail.log \
|| echo "rmilter is already listed in services"
sudo yunohost service add redis-server -l /var/log/redis/redis-server.log \
|| echo "redis-server is already listed in services"
# Remove previous email services
systemctl is-enabled spamassassin > /dev/null 2>&1 \
&& sudo systemctl disable spamassassin
systemctl is-active spamassassin > /dev/null \
&& sudo systemctl stop spamassassin
sudo rm -f /etc/cron.daily/spamassassin
sudo yunohost service status spamassassin > /dev/null 2>&1 \
&& sudo yunohost service remove spamassassin
# 'systemctl is-enabled' does not work for service with no systemd unit file
sudo ls /etc/rc2.d/S??amavis > /dev/null 2>&1 \
|| sudo systemctl disable amavis
sudo systemctl is-active amavis > /dev/null \
&& sudo systemctl stop amavis
sudo yunohost service status amavis > /dev/null 2>&1 \
&& sudo yunohost service remove amavis
# 'systemctl is-enabled' does not work for service with no systemd unit file
sudo ls /etc/rc2.d/S??postgrey > /dev/null 2>&1 \
|| sudo systemctl disable postgrey
sudo systemctl is-active postgrey > /dev/null \
&& sudo systemctl stop postgrey
sudo yunohost service status postgrey > /dev/null 2>&1 \
&& sudo yunohost service remove postgrey
fi
exit 0

96
data/hooks/conf_regen/25-dovecot Normal file → Executable file
View file

@ -1,51 +1,69 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s dovecot $1 $2 --force
else
sudo yunohost service safecopy \
-s dovecot $1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/dovecot
dovecot_dir="${pending_dir}/etc/dovecot"
mkdir -p "${dovecot_dir}/global_script"
# copy simple conf files
cp dovecot-ldap.conf "${dovecot_dir}/dovecot-ldap.conf"
cp dovecot.sieve "${dovecot_dir}/global_script/dovecot.sieve"
# prepare dovecot.conf conf file
main_domain=$(cat /etc/yunohost/current_host)
cat dovecot.conf \
| sed "s/{{ main_domain }}/${main_domain}/g" \
> "${dovecot_dir}/dovecot.conf"
# adapt it for IPv4-only hosts
if [ ! -f /proc/net/if_inet6 ]; then
sed -i \
's/^\(listen =\).*/\1 */' \
"${dovecot_dir}/dovecot.conf"
fi
}
cd /usr/share/yunohost/templates/dovecot
do_post_regen() {
regen_conf_files=$1
# Create vmail user
sudo id vmail > /dev/null 2>&1 \
|| sudo adduser --system --ingroup mail --uid 500 vmail
# create vmail user
id vmail > /dev/null 2>&1 \
|| sudo adduser --system --ingroup mail --uid 500 vmail
# fix permissions
sudo chown -R vmail:mail /etc/dovecot/global_script
sudo chmod 770 /etc/dovecot/global_script
# Replace main domain in the main configuration file
main_domain=$(cat /etc/yunohost/current_host)
cat dovecot.conf.sed \
| sed "s/{{ main_domain }}/$main_domain/g" \
| sudo tee dovecot.conf
[ -z "$regen_conf_files" ] && exit 0
# compile sieve script
[[ "$regen_conf_files" =~ dovecot\.sieve ]] && {
sudo sievec /etc/dovecot/global_script/dovecot.sieve
sudo chown -R vmail:mail /etc/dovecot/global_script
}
# Handle IPv4 only systems
if [ ! -f /proc/net/if_inet6 ];
then
sudo sed -i 's/^listen.*/listen = \*/' dovecot.conf
fi
sudo service dovecot restart
}
FORCE=${2:-0}
DRY_RUN=${3:-0}
safe_copy dovecot.conf /etc/dovecot/dovecot.conf
safe_copy dovecot-ldap.conf /etc/dovecot/dovecot-ldap.conf
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
# Setup Sieve
sudo mkdir -p /etc/dovecot/global_script
sudo chmod -R 770 /etc/dovecot/global_script
safe_copy dovecot.sieve /etc/dovecot/global_script/dovecot.sieve
sudo chmod 660 /etc/dovecot/global_script/dovecot.sieve > /dev/null 2>&1 \
|| safe_copy dovecot.sieve /etc/dovecot/global_script/dovecot.sieve
sudo sievec /etc/dovecot/global_script/dovecot.sieve
sudo chmod 660 /etc/dovecot/global_script/dovecot.svbin
sudo chown -R vmail:mail /etc/dovecot/global_script
sudo service dovecot restart
exit 0

92
data/hooks/conf_regen/28-rmilter Normal file → Executable file
View file

@ -1,43 +1,69 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s rmilter $1 $2 --force
else
sudo yunohost service safecopy \
-s rmilter $1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/rmilter
install -D -m 644 rmilter.conf \
"${pending_dir}/etc/rmilter.conf"
install -D -m 644 rmilter.socket \
"${pending_dir}/etc/systemd/system/rmilter.socket"
}
cd /usr/share/yunohost/templates/rmilter
do_post_regen() {
regen_conf_files=$1
# Copy Rmilter configuration
safe_copy rmilter.conf /etc/rmilter.conf
# retrieve variables
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
# Override socket configuration
safe_copy rmilter.socket /etc/systemd/system/rmilter.socket
# create DKIM directory
sudo mkdir -p /etc/dkim
# Create DKIM key for each YunoHost domain
sudo mkdir -p /etc/dkim
domain_list=$(sudo yunohost domain list --output-as plain)
# create DKIM key for domains
for domain in $domain_list; do
domain_key="/etc/dkim/${domain}.mail.key"
[ ! -f $domain_key ] && {
sudo opendkim-genkey --domain="$domain" \
--selector=mail --directory=/etc/dkim
sudo mv /etc/dkim/mail.private "$domain_key"
sudo mv /etc/dkim/mail.txt "/etc/dkim/${domain}.mail.txt"
}
done
for domain in $domain_list; do
[ -f /etc/dkim/$domain.mail.key ] \
|| (sudo opendkim-genkey --domain=$domain \
--selector=mail\
--directory=/etc/dkim \
&& sudo mv /etc/dkim/mail.private /etc/dkim/$domain.mail.key \
&& sudo mv /etc/dkim/mail.txt /etc/dkim/$domain.mail.txt)
# fix DKIM keys permissions
sudo chown _rmilter /etc/dkim/*.mail.key
sudo chmod 400 /etc/dkim/*.mail.key
sudo chown _rmilter /etc/dkim/$domain.mail.key
sudo chmod 400 /etc/dkim/$domain.mail.key
done
[ -z "$regen_conf_files" ] && exit 0
# Reload systemd daemon, ensure that the socket is listening and stop
# the service. It will be started again by the socket as needed.
sudo systemctl daemon-reload
sudo systemctl start rmilter.socket
sudo systemctl stop rmilter.service 2>&1 || true
# reload systemd daemon
[[ "$regen_conf_files" =~ rmilter\.socket ]] && {
sudo systemctl -q daemon-reload
}
# ensure that the socket is listening and stop the service - it will be
# started again by the socket as needed
sudo systemctl -q start rmilter.socket
sudo systemctl -q stop rmilter.service 2>&1 || true
}
FORCE=${2:-0}
DRY_RUN=${3:-0}
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

65
data/hooks/conf_regen/31-rspamd Normal file → Executable file
View file

@ -1,33 +1,50 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s rspamd $1 $2 --force
else
sudo yunohost service safecopy \
-s rspamd $1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/rspamd
install -D -m 644 metrics.local.conf \
"${pending_dir}/etc/rspamd/local.d/metrics.conf"
install -D -m 644 rspamd.sieve \
"${pending_dir}/etc/dovecot/global_script/rspamd.sieve"
}
cd /usr/share/yunohost/templates/rspamd
do_post_regen() {
regen_conf_files=$1
# Create configuration directories
sudo mkdir -p /etc/rspamd/local.d /etc/rspamd/override.d
[ -z "$regen_conf_files" ] && exit 0
# Copy specific configuration to rewrite the defaults
safe_copy metrics.conf.local /etc/rspamd/local.d/metrics.conf
# compile sieve script
[[ "$regen_conf_files" =~ rspamd\.sieve ]] && {
sudo sievec /etc/dovecot/global_script/rspamd.sieve
sudo chown -R vmail:mail /etc/dovecot/global_script
sudo systemctl restart dovecot
}
# Install Rspamd sieve script
safe_copy rspamd.sieve /etc/dovecot/global_script/rspamd.sieve
sudo sievec /etc/dovecot/global_script/rspamd.sieve
sudo chmod 660 /etc/dovecot/global_script/rspamd.svbin
sudo chown -R vmail:mail /etc/dovecot/global_script
# ensure that the socket is listening and stop the service - it will be
# started again by the socket as needed
sudo systemctl -q start rspamd.socket
sudo systemctl -q stop rspamd.service 2>&1 || true
}
# Ensure that the socket is listening and stop the service.
sudo systemctl stop rspamd.service 2>&1 || true
sudo systemctl start rspamd.socket
FORCE=${2:-0}
DRY_RUN=${3:-0}
sudo systemctl restart dovecot
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

99
data/hooks/conf_regen/34-mysql Normal file → Executable file
View file

@ -1,35 +1,82 @@
#!/bin/bash
set -e
force=$1
do_pre_regen() {
pending_dir=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s mysql $1 $2 --force
else
sudo yunohost service safecopy \
-s mysql $1 $2
fi
cd /usr/share/yunohost/templates/mysql
install -D -m 644 my.cnf "${pending_dir}/etc/mysql/my.cnf"
}
function randpass () {
[ "$2" == "0" ] && CHAR="[:alnum:]" || CHAR="[:graph:]"
cat /dev/urandom | tr -cd "$CHAR" | head -c ${1:-32}
echo
do_post_regen() {
regen_conf_files=$1
if [ ! -f /etc/yunohost/mysql ]; then
. /usr/share/yunohost/helpers.d/string
# ensure that mysql is running
service mysql status >/dev/null 2>&1 \
|| service mysql start
# generate and set new root password
mysql_password=$(ynh_string_random 10)
sudo mysqladmin -s -u root -pyunohost password "$mysql_password" || {
if [ $FORCE -eq 1 ]; then
. /usr/share/yunohost/helpers.d/package
echo "It seems that you have already configured MySQL." \
"YunoHost needs to have a root access to MySQL to runs its" \
"applications, and is going to reset the MySQL root password." \
"You can find this new password in /etc/yunohost/mysql." >&2
# retrieve MySQL package provider
ynh_package_is_installed "mariadb-server-10.0" \
&& mysql_pkg="mariadb-server-10.0" \
|| mysql_pkg="mysql-server-5.5"
# set new password with debconf
sudo debconf-set-selections << EOF
$mysql_pkg mysql-server/root_password password $mysql_password
$mysql_pkg mysql-server/root_password_again password $mysql_password
EOF
# reconfigure Debian package
sudo dpkg-reconfigure -freadline -u "$mysql_pkg" 2>&1
else
echo "It seems that you have already configured MySQL." \
"YunoHost needs to have a root access to MySQL to runs its" \
"applications, but the MySQL root password is unknown." \
"You must either pass --force to reset the password or" \
"put the current one into the file /etc/yunohost/mysql." >&2
exit 1
fi
}
# store new root password
echo "$mysql_password" | sudo tee /etc/yunohost/mysql
sudo chmod 400 /etc/yunohost/mysql
fi
[[ -z "$regen_conf_files" ]] \
|| sudo service mysql restart
}
cd /usr/share/yunohost/templates/mysql
FORCE=${2:-0}
DRY_RUN=${3:-0}
if [[ "$(safe_copy my.cnf /etc/mysql/my.cnf | tail -n1)" == "True" ]]; then
sudo service mysql restart
fi
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
if [ ! -f /etc/yunohost/mysql ]; then
[[ $(/bin/ps aux | grep '[m]ysqld') == "0" ]] \
&& sudo service mysql start
mysql_password=$(randpass 10 0)
sudo mysqladmin -u root -pyunohost password $mysql_password
echo $mysql_password | sudo tee /etc/yunohost/mysql
sudo chmod 400 /etc/yunohost/mysql
fi
exit 0

46
data/hooks/conf_regen/37-avahi-daemon Normal file → Executable file
View file

@ -1,19 +1,37 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s avahi-daemon $1 $2 --force
else
sudo yunohost service safecopy \
-s avahi-daemon $1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/avahi-daemon
install -D -m 644 avahi-daemon.conf \
"${pending_dir}/etc/avahi/avahi-daemon.conf"
}
cd /usr/share/yunohost/templates/avahi-daemon
do_post_regen() {
regen_conf_files=$1
if [[ "$(safe_copy avahi-daemon.conf /etc/avahi/avahi-daemon.conf | tail -n1)" == "True" ]]; then
sudo service avahi-daemon restart
fi
[[ -z "$regen_conf_files" ]] \
|| sudo service avahi-daemon restart
}
FORCE=${2:-0}
DRY_RUN=${3:-0}
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

45
data/hooks/conf_regen/40-glances Normal file → Executable file
View file

@ -1,19 +1,36 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s glances $1 $2 --force
else
sudo yunohost service safecopy \
-s glances $1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/glances
install -D -m 644 glances.default "${pending_dir}/etc/default/glances"
}
cd /usr/share/yunohost/templates/glances
do_post_regen() {
regen_conf_files=$1
if [[ "$(safe_copy glances.default /etc/default/glances | tail -n1)" == "True" ]]; then
sudo service glances restart
fi
[[ -z "$regen_conf_files" ]] \
|| sudo service glances restart
}
FORCE=${2:-0}
DRY_RUN=${3:-0}
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

101
data/hooks/conf_regen/43-dnsmasq Normal file → Executable file
View file

@ -1,53 +1,66 @@
set -e
#!/bin/bash
force=$1
set -e
. /usr/share/yunohost/helpers
do_pre_regen() {
pending_dir=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s dnsmasq $1 $2 --force
else
sudo yunohost service safecopy \
-s dnsmasq $1 $2
fi
# source ip helpers
. /usr/share/yunohost/helpers.d/ip
cd /usr/share/yunohost/templates/dnsmasq
# create directory for pending conf
dnsmasq_dir="${pending_dir}/etc/dnsmasq.d"
mkdir -p "$dnsmasq_dir"
# retrieve variables
ipv4=$(curl -s -4 https://ip.yunohost.org 2>/dev/null || true)
ynh_validate_ip4 "$ipv4" || ipv4='127.0.0.1'
ipv6=$(curl -s -6 http://ip6.yunohost.org 2>/dev/null || true)
ynh_validate_ip6 "$ipv6" || ipv6=''
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
# add domain conf files
for domain in $domain_list; do
cat domain.tpl \
| sed "s/{{ domain }}/${domain}/g" \
| sed "s/{{ ip }}/${ipv4}/g" \
> "${dnsmasq_dir}/${domain}"
[[ -n $ipv6 ]] \
&& echo "address=/${domain}/${ipv6}" >> "${dnsmasq_dir}/${domain}"
done
# remove old domain conf files
conf_files=$(ls -1 /etc/dnsmasq.d \
| awk '/^[^\.]+\.[^\.]+.*$/ { print $1 }')
for domain in $conf_files; do
[[ $domain_list =~ $domain ]] \
|| touch "${dnsmasq_dir}/${domain}"
done
}
cd /usr/share/yunohost/templates/dnsmasq
do_post_regen() {
regen_conf_files=$1
# Get IPv4 address
ip=$(curl -s -4 https://ip.yunohost.org 2>/dev/null || true)
ynh_validate_ip4 $ip || ip='0.0.0.0'
[[ -z "$regen_conf_files" ]] \
|| sudo service dnsmasq restart
}
# Get IPv6 IP address
ipv6=$(curl -s -6 http://ip6.yunohost.org 2>/dev/null || true)
ynh_validate_ip6 $ipv6 || ipv6=''
FORCE=${2:-0}
DRY_RUN=${3:-0}
sudo mkdir -p /etc/dnsmasq.d
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
domain_list=$(sudo yunohost domain list --output-as plain)
# Copy a configuration file for each YunoHost domain
for domain in $domain_list; do
cat domain.sed \
| sed "s/{{ domain }}/$domain/g" \
| sed "s/{{ ip }}/$ip/g" \
| sudo tee $domain
if [[ "$ipv6" != "" ]]; then
echo "address=/$domain/$ipv6" | sudo tee -a $domain
fi
safe_copy $domain /etc/dnsmasq.d/$domain
done
# Remove old domains files
for file in /etc/dnsmasq.d/*.*; do
domain=$(echo $file | sed 's|/etc/dnsmasq.d/||')
[[ $domain_list =~ $domain ]] \
|| sudo yunohost service saferemove -s dnsmasq $file
done
sudo service dnsmasq reload \
|| sudo service dnsmasq restart
exit 0

45
data/hooks/conf_regen/46-nsswitch Normal file → Executable file
View file

@ -1,19 +1,36 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s nsswitch $1 $2 --force
else
sudo yunohost service safecopy \
-s nsswitch $1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/nsswitch
install -D -m 644 nsswitch.conf "${pending_dir}/etc/nsswitch.conf"
}
cd /usr/share/yunohost/templates/nsswitch
do_post_regen() {
regen_conf_files=$1
if [[ "$(safe_copy nsswitch.conf /etc/nsswitch.conf | tail -n1)" == "True" ]]; then
sudo service nscd restart
fi
[[ -z "$regen_conf_files" ]] \
|| sudo service nscd restart
}
FORCE=${2:-0}
DRY_RUN=${3:-0}
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

54
data/hooks/conf_regen/52-fail2ban Normal file → Executable file
View file

@ -1,28 +1,40 @@
set -e
#!/bin/bash
force=$1
set -e
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s fail2ban $1 $2 --force
else
sudo yunohost service safecopy \
-s fail2ban $1 $2
fi
do_pre_regen() {
pending_dir=$1
cd /usr/share/yunohost/templates/fail2ban
fail2ban_dir="${pending_dir}/etc/fail2ban"
mkdir -p "${fail2ban_dir}/filter.d"
cp yunohost.conf "${fail2ban_dir}/filter.d/yunohost.conf"
cp jail.conf "${fail2ban_dir}/jail.conf"
}
cd /usr/share/yunohost/templates/fail2ban
do_post_regen() {
regen_conf_files=$1
sudo mkdir -p /etc/fail2ban/filter.d
safe_copy yunohost.conf /etc/fail2ban/filter.d/yunohost.conf
[[ -z "$regen_conf_files" ]] \
|| sudo service fail2ban restart
}
# Compatibility: change from HDB to MDB on Jessie
version=$(sed 's/\..*//' /etc/debian_version)
[[ "$version" == '8' ]] \
&& sudo cp jail-jessie.conf jail.conf \
|| sudo cp jail-wheezy.conf jail.conf
FORCE=${2:-0}
DRY_RUN=${3:-0}
if [[ $(safe_copy jail.conf /etc/fail2ban/jail.conf | tail -n1) == "True" ]]; then
sudo service fail2ban restart
fi
case "$1" in
pre)
do_pre_regen $4
;;
post)
do_post_regen $4
;;
*)
echo "hook called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

View file

@ -1,6 +1,42 @@
backup_dir="$1/conf/ynh/mysql"
sudo service mysql restart
sudo cp -a $backup_dir/mysql /etc/yunohost/mysql
mysqlpwd=$(sudo cat /etc/yunohost/mysql)
sudo mysqladmin flush-privileges -p"$mysqlpwd"
# ensure that mysql is running
service mysql status >/dev/null 2>&1 \
|| service mysql start
# retrieve current and new password
[ -f /etc/yunohost/mysql ] \
&& curr_pwd=$(sudo cat /etc/yunohost/mysql) \
|| curr_pwd="yunohost"
new_pwd=$(sudo cat "${backup_dir}/root_pwd" || sudo cat "${backup_dir}/mysql")
# attempt to change it
sudo mysqladmin -s -u root -p"$curr_pwd" password "$new_pwd" || {
. /usr/share/yunohost/helpers.d/package
echo "It seems that you have already configured MySQL." \
"YunoHost needs to have a root access to MySQL to runs its" \
"applications, and is going to reset the MySQL root password." \
"You can find this new password in /etc/yunohost/mysql." >&2
# retrieve MySQL package provider
ynh_package_is_installed "mariadb-server-10.0" \
&& mysql_pkg="mariadb-server-10.0" \
|| mysql_pkg="mysql-server-5.5"
# set new password with debconf
sudo debconf-set-selections << EOF
$mysql_pkg mysql-server/root_password password $new_pwd
$mysql_pkg mysql-server/root_password_again password $new_pwd
EOF
# reconfigure Debian package
sudo dpkg-reconfigure -freadline -u "$mysql_pkg" 2>&1
}
# store new root password
echo "$new_pwd" | sudo tee /etc/yunohost/mysql
sudo chmod 400 /etc/yunohost/mysql
# reload the grant tables
sudo mysqladmin -s -u root -p"$new_pwd" reload

View file

@ -1 +1,3 @@
backup_dir="$1/conf/ynh"
sudo cp -a "${backup_dir}/current_host" /etc/yunohost/current_host

View file

@ -1,346 +0,0 @@
# Fail2Ban configuration file.
#
# This file was composed for Debian systems from the original one
# provided now under /usr/share/doc/fail2ban/examples/jail.conf
# for additional examples.
#
# To avoid merges during upgrades DO NOT MODIFY THIS FILE
# and rather provide your changes in /etc/fail2ban/jail.local
#
# Author: Yaroslav O. Halchenko <debian@onerussian.com>
#
# $Revision$
#
# The DEFAULT allows a global definition of the options. They can be overridden
# in each jail afterwards.
[DEFAULT]
# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
bantime = 600
maxretry = 3
# "backend" specifies the backend used to get files modification. Available
# options are "gamin", "polling" and "auto".
# yoh: For some reason Debian shipped python-gamin didn't work as expected
# This issue left ToDo, so polling is default backend for now
backend = auto
#
# Destination email address used solely for the interpolations in
# jail.{conf,local} configuration files.
destemail = root@localhost
#
# ACTIONS
#
# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
# email action. Since 0.8.1 upstream fail2ban uses sendmail
# MTA for the mailing. Change mta configuration parameter to mail
# if you want to revert to conventional 'mail'.
mta = sendmail
# Default protocol
protocol = tcp
# Specify chain where jumps would need to be added in iptables-* actions
chain = INPUT
#
# Action shortcuts. To be used to define action parameter
# The simplest action to take: ban only
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report to the destemail.
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
# Choose default action. To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s
#
# JAILS
#
# Next jails corresponds to the standard configuration in Fail2ban 0.6 which
# was shipped in Debian. Enable any defined here jail by including
#
# [SECTION_NAME]
# enabled = true
#
# in /etc/fail2ban/jail.local.
#
# Optionally you may override any other parameter (e.g. banaction,
# action, port, logpath, etc) in that section within jail.local
[ssh]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 6
[dropbear]
enabled = false
port = ssh
filter = sshd
logpath = /var/log/dropbear
maxretry = 6
# Generic filter for pam. Has to be used with action which bans all ports
# such as iptables-allports, shorewall
[pam-generic]
enabled = false
# pam-generic filter can be customized to monitor specific subset of 'tty's
filter = pam-generic
# port actually must be irrelevant but lets leave it all for some possible uses
port = all
banaction = iptables-allports
port = anyport
logpath = /var/log/auth.log
maxretry = 6
[xinetd-fail]
enabled = false
filter = xinetd-fail
port = all
banaction = iptables-multiport-log
logpath = /var/log/daemon.log
maxretry = 2
[ssh-ddos]
enabled = false
port = ssh
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 6
#
# HTTP servers
#
[apache]
enabled = false
port = http,https
filter = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 6
# default action is now multiport, so apache-multiport jail was left
# for compatibility with previous (<0.7.6-2) releases
[apache-multiport]
enabled = false
port = http,https
filter = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 6
[apache-noscript]
enabled = false
port = http,https
filter = apache-noscript
logpath = /var/log/apache*/*error.log
maxretry = 6
[apache-overflows]
enabled = false
port = http,https
filter = apache-overflows
logpath = /var/log/apache*/*error.log
maxretry = 2
#
# FTP servers
#
[vsftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = vsftpd
logpath = /var/log/vsftpd.log
# or overwrite it in jails.local to be
# logpath = /var/log/auth.log
# if you want to rely on PAM failed login attempts
# vsftpd's failregex should match both of those formats
maxretry = 6
[proftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = proftpd
logpath = /var/log/proftpd/proftpd.log
maxretry = 6
[pure-ftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = pure-ftpd
logpath = /var/log/auth.log
maxretry = 6
[wuftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = wuftpd
logpath = /var/log/auth.log
maxretry = 6
#
# Mail servers
#
[postfix]
enabled = true
port = smtp,ssmtp
filter = postfix
logpath = /var/log/mail.log
[couriersmtp]
enabled = false
port = smtp,ssmtp
filter = couriersmtp
logpath = /var/log/mail.log
#
# Mail servers authenticators: might be used for smtp,ftp,imap servers, so
# all relevant ports get banned
#
[courierauth]
enabled = false
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
filter = courierlogin
logpath = /var/log/mail.log
[sasl]
enabled = true
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
filter = sasl
# You might consider monitoring /var/log/mail.warn instead if you are
# running postfix since it would provide the same log lines at the
# "warn" level but overall at the smaller filesize.
logpath = /var/log/mail.log
[dovecot]
enabled = true
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
filter = dovecot
logpath = /var/log/mail.log
# DNS Servers
# These jails block attacks against named (bind9). By default, logging is off
# with bind9 installation. You will need something like this:
#
# logging {
# channel security_file {
# file "/var/log/named/security.log" versions 3 size 30m;
# severity dynamic;
# print-time yes;
# };
# category security {
# security_file;
# };
# };
#
# in your named.conf to provide proper logging
# !!! WARNING !!!
# Since UDP is connection-less protocol, spoofing of IP and imitation
# of illegal actions is way too simple. Thus enabling of this filter
# might provide an easy way for implementing a DoS against a chosen
# victim. See
# http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html
# Please DO NOT USE this jail unless you know what you are doing.
#[named-refused-udp]
#
#enabled = false
#port = domain,953
#protocol = udp
#filter = named-refused
#logpath = /var/log/named/security.log
[named-refused-tcp]
enabled = false
port = domain,953
protocol = tcp
filter = named-refused
logpath = /var/log/named/security.log
[nginx]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/nginx*/*error.log
maxretry = 6
[nginx-noscript]
enabled = false
port = http,https
filter = apache-noscript
logpath = /var/log/nginx*/*error.log
maxretry = 6
[nginx-overflows]
enabled = false
port = http,https
filter = apache-overflows
logpath = /var/log/nginx*/*error.log
maxretry = 4
[yunohost]
enabled = true
port = http,https
protocol = tcp
filter = yunohost
logpath = /var/log/nginx/*.log
maxretry = 6

View file

@ -15,8 +15,13 @@ postfix:
log: [/var/log/mail.log,/var/log/mail.err]
rmilter:
status: systemctl status rmilter.socket
log: /var/log/mail.log
rspamd:
status: systemctl status rspamd.socket
log: /var/log/mail.log
redis-server:
status: service
log: /var/log/redis/redis-server.log
mysql:
status: service
log: [/var/log/mysql.log,/var/log/mysql.err]
@ -39,9 +44,6 @@ yunohost-api:
log: /var/log/yunohost/yunohost-api.log
yunohost-firewall:
status: service
postgrey:
status: service
log: /var/log/mail.log
nslcd:
status: service
log: /var/log/syslog
@ -49,3 +51,6 @@ nsswitch:
status: service
udisks2:
status: service
amavis: null
postgrey: null
spamassassin: null

39
debian/changelog vendored
View file

@ -1,3 +1,42 @@
yunohost (2.3.12.1) testing; urgency=low
* [deb] Rely on dh_installinit to restart yunohost-firewall after upgrade
* [deb] Add Install section to yunohost-firewall.service
-- Jérôme Lebleu <jerome@yunohost.org> Sat, 09 Apr 2016 17:22:40 +0200
yunohost (2.3.12) testing; urgency=low
[ Jérôme Lebleu ]
* [enh] Use new rspamd configuration system to override metrics
* [enh] Allow to set script execution directory in hook_exec
* [enh] Add a ynh_user_list helper
* [enh] Call app remove script if installation fails
* [fix] Move imports at the top in yunohost and yunohost-api
* [fix] Use rspamd local.d folder to allow users to override the defaults
* [fix] Execute backup/restore app scripts from the backup dir (bugfix #139)
* [fix] Regenerate SSOwat conf after apps restoration
* [fix] Move imports at the top in backup.py
* [fix] Check if the package is actually installed in equivs helper
* [fix] Improve control file management in equivs helper
* [fix] Remove ending comma in backup.py
* [fix] Call yunohost commands with --quiet in setting helpers
* [fix] Check for tty in root_handlers before remove it in bin/yunohost
* [fix] Use dyndns.yunohost.org instead of dynhost.yunohost.org
* [fix] Set found private key and don't validate it in dyndns_update
* [fix] Update first registered domain with DynDNS instead of current_host
* [i18n] Rename app_requirements_failed err named variable
* [i18n] Update translations from Weblate
[ opi ]
* [enh] Better message during service regenconf.
* [enh] Display hook path on error message.
* [enh] Use named arguments when calling m18n in service.py
* [enh] Use named arguments with m18n.
* [enh] Use named arguments for user_unknown string.
-- Jérôme Lebleu <jerome@yunohost.org> Sat, 09 Apr 2016 12:13:10 +0200
moulinette-yunohost (2.2.4) stable; urgency=low
[ Jérôme Lebleu ]

4
debian/control vendored
View file

@ -10,7 +10,7 @@ Homepage: https://yunohost.org/
Package: yunohost
Architecture: all
Depends: ${python:Depends}, ${misc:Depends}
, moulinette (>= 2.3.4)
, moulinette (>= 2.3.5.1)
, python-psutil, python-requests, python-dnspython
, python-apt, python-miniupnpc
, glances
@ -27,7 +27,7 @@ Depends: ${python:Depends}, ${misc:Depends}
, rspamd (>= 1.2.0), rmilter (>=1.7.0), redis-server, opendkim-tools
Recommends: yunohost-admin
, openssh-server, ntp, inetutils-ping | iputils-ping
, bash-completion, rsyslog
, bash-completion, rsyslog, etckeeper
, php5-gd, php5-curl, php-gettext, php5-mcrypt
, python-pip
, unattended-upgrades

41
debian/postinst vendored
View file

@ -6,13 +6,13 @@ do_configure() {
rm -rf /var/cache/moulinette/*
if [ ! -f /etc/yunohost/installed ]; then
bash /usr/share/yunohost/hooks/conf_regen/01-yunohost True
bash /usr/share/yunohost/hooks/conf_regen/02-ssl True
bash /usr/share/yunohost/hooks/conf_regen/06-slapd True
bash /usr/share/yunohost/hooks/conf_regen/15-nginx True
bash /usr/share/yunohost/hooks/conf_regen/01-yunohost init
bash /usr/share/yunohost/hooks/conf_regen/02-ssl init
bash /usr/share/yunohost/hooks/conf_regen/06-slapd init
bash /usr/share/yunohost/hooks/conf_regen/15-nginx init
else
echo "Regenerating configuration, this might take a while..."
yunohost service regenconf
yunohost service regen-conf --output-as none
# restart yunohost-firewall if it's running
service yunohost-firewall status >/dev/null \
@ -28,23 +28,18 @@ do_configure() {
restart_yunohost_firewall() {
echo "Restarting YunoHost firewall..."
if [ -x /etc/init.d/yunohost-firewall ]; then
update-rc.d yunohost-firewall defaults >/dev/null || true
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
else
invoke-rc.d yunohost-firewall start >/dev/null || true
fi
fi
deb-systemd-helper unmask yunohost-firewall.service >/dev/null || true
if deb-systemd-helper --quiet was-enabled yunohost-firewall.service; then
deb-systemd-helper enable yunohost-firewall.service >/dev/null || true
else
deb-systemd-helper update-state yunohost-firewall.service >/dev/null || true
fi
deb-systemd-helper update-state yunohost-firewall.service >/dev/null || true
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
deb-systemd-invoke try-restart yunohost-firewall.service >/dev/null || true
if [ -x /etc/init.d/yunohost-firewall ]; then
update-rc.d yunohost-firewall enable >/dev/null
if [ -n "$2" ]; then
invoke-rc.d yunohost-firewall restart >/dev/null || exit $?
fi
fi
}
@ -71,16 +66,6 @@ case "$1" in
;;
esac
# Enable and start yunohost-api sysv service
if [ -x /etc/init.d/yunohost-api ]; then
update-rc.d yunohost-api defaults >/dev/null
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
else
invoke-rc.d yunohost-api start || exit $?
fi
fi
#DEBHELPER#
exit 0

1
debian/postrm vendored
View file

@ -3,7 +3,6 @@
set -e
if [ "$1" = "purge" ]; then
update-rc.d yunohost-api remove >/dev/null
update-rc.d yunohost-firewall remove >/dev/null
fi

1
debian/prerm vendored
View file

@ -3,7 +3,6 @@
set -e
if [ -x /etc/init.d/yunohost-api ] && ! [ -d /run/systemd/system ]; then
invoke-rc.d yunohost-api stop || exit $?
invoke-rc.d yunohost-firewall stop || true
fi

12
debian/rules vendored
View file

@ -8,12 +8,14 @@
dh ${@} --with=python2,systemd
override_dh_installinit:
dh_installinit -pyunohost --name=yunohost-api --noscripts
dh_installinit -pyunohost --name=yunohost-api --restart-after-upgrade
dh_installinit -pyunohost --name=yunohost-firewall --noscripts
override_dh_systemd_enable:
dh_systemd_enable --name=yunohost-api
dh_systemd_enable --name=yunohost-firewall --no-enable
dh_systemd_enable --name=yunohost-api \
yunohost-api.service
dh_systemd_enable --name=yunohost-firewall --no-enable \
yunohost-firewall.service
override_dh_systemd_start:
dh_systemd_start --restart-after-upgrade yunohost-api.service
#override_dh_systemd_start:
# dh_systemd_start --restart-after-upgrade yunohost-api.service

View file

@ -9,3 +9,6 @@ ExecStart=/usr/bin/yunohost firewall reload
ExecReload=/usr/bin/yunohost firewall reload
ExecStop=/usr/bin/yunohost firewall stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View file

@ -1,213 +1,213 @@
{
"action_invalid": "Ungültige Aktion '{:s}'",
"admin_password": "Verwaltungspasswort",
"admin_password_change_failed": "Passwort kann nicht geändert werden",
"admin_password_changed": "Verwaltungspasswort wurde erfolgreich geändert",
"app_already_installed": "{:s} ist schon installiert",
"app_argument_choice_invalid": "Invalide Auswahl für Argument '{name:s}'. Muss einer der folgenden Werte sein {choices:s}",
"app_argument_invalid": "Das Argument '{name:s}' hat einen falschen Wert: {error:s}",
"app_argument_required": "Argument '{name:s}' wird benötigt",
"app_extraction_failed": "Installationsdateien konnten nicht entpackt werden",
"app_id_invalid": "Falsche App ID",
"app_install_files_invalid": "Ungültige Installationsdateien",
"app_location_already_used": "Eine andere App ist bereits an diesem Ort installiert",
"app_location_install_failed": "Die App kann an diesem Ort nicht installiert werden",
"app_manifest_invalid": "Ungültiges App Manifest",
"app_no_upgrade": "Keine Aktualisierungen für Apps verfügbar",
"app_not_installed": "{:s} ist nicht intalliert",
"app_recent_version_required": "Für {:s} benötigt eine aktuellere Version von moulinette",
"app_removed": "{:s} wurde erfolgreich entfernt",
"app_sources_fetch_failed": "Quelldateien konnten nicht abgerufen werden",
"app_unknown": "Unbekannte App",
"app_upgrade_failed": "Apps konnten nicht aktualisiert werden",
"app_upgraded": "{:s} wurde erfolgreich aktualisiert",
"appslist_fetched": "Liste der Apps wurde erfolgreich heruntergelanden",
"appslist_removed": "Appliste erfolgreich entfernt",
"appslist_retrieve_error": "Entfernte App Liste kann nicht gezogen werden",
"appslist_unknown": "Unbekannte App Liste",
"ask_current_admin_password": "Derzeitiges Verwaltungspasswort",
"ask_email": "E-Mail Adresse",
"ask_firstname": "Vorname",
"ask_lastname": "Nachname",
"ask_list_to_remove": "Liste enternen",
"ask_main_domain": "Hauptdomain",
"ask_new_admin_password": "Neues Verwaltungskennwort",
"ask_password": "Passwort",
"backup_action_required": "Du musst etwas zum Speichern auswählen",
"backup_app_failed": "Konnte keine Sicherung für '{app:s}' erstellen",
"backup_archive_app_not_found": "App '{app:s}' konnte in keiner Datensicherung gefunden werden",
"backup_archive_hook_not_exec": "Hook '{hook:s}' konnte für diese Datensicherung nicht ausgeführt werden",
"backup_archive_name_exists": "Datensicherung mit dem selben Namen existiert bereits",
"backup_archive_name_unknown": "Unbekanntes lokale Datensicherung mit Namen '{name:s}' gefunden",
"backup_archive_open_failed": "Kann Sicherungsarchiv nicht öfnen",
"backup_cleaning_failed": "Verzeichnis von temporäre Sicherungsdaten konnte nicht geleert werden",
"backup_complete": "Datensicherung komplett",
"backup_creating_archive": "Datensicherung wird erstellt...",
"backup_delete_error": "Pfad '{path:s}' konnte nicht gelöscht werden",
"backup_deleted": "Datensicherung erfolgreich gelöscht",
"backup_extracting_archive": "Entpacke Sicherungsarchiv...",
"backup_hook_unknown": "Datensicherungshook '{hook:s}' unbekannt",
"backup_invalid_archive": "Ungültige Datensicherung",
"backup_nothings_done": "Es gibt keine Änderungen zur Speicherung",
"backup_output_directory_forbidden": "Verbotenes Ausgabeverzeichnis",
"backup_output_directory_not_empty": "Ausgabeordner ist nicht leer",
"backup_output_directory_required": "Für die Datensicherung muss ein Zielverzeichnis angegeben werden",
"backup_running_app_script": "Datensicherung für App '{app:s}' wurd durchgeführt...",
"backup_running_hooks": "Datensicherunghook wird ausgeführt...",
"custom_app_url_required": "Es muss eine URL angegeben um deine benutzerdefinierte App {:s} zu aktualisieren",
"custom_appslist_name_required": "Du musst einen Namen für deine benutzerdefinierte Appliste angeben",
"dnsmasq_isnt_installed": "dnsmasq scheint nicht installiert zu sein. Bitte führe 'apt-get remove bind9 && apt-get install dnsmasq' aus",
"domain_cert_gen_failed": "Zertifikat konnte nicht erzeugt werden",
"domain_created": "Domain erfolgreich erzeugt",
"domain_creation_failed": "Konnte Domain nicht erzeugen",
"domain_deleted": "Domain erfolgreich gelöscht",
"domain_deletion_failed": "Konnte Domain nicht löschen",
"domain_dyndns_already_subscribed": "Du hast dich schon für einen DynDNS-Domain angemeldet",
"domain_dyndns_invalid": "Domain nicht mittels DynDNS nutzbar",
"domain_dyndns_root_unknown": "Unbekannte DynDNS Hauptdomain",
"domain_exists": "Die Domain existiert bereits",
"domain_uninstall_app_first": "Mindestens eine App ist noch für diese Domain installiert. Bitte zuerst die App deinstallieren und erst dann die Domain löschen..",
"domain_unknown": "Unbekannte Domain",
"domain_zone_exists": "DNS Zonen Datei existiert bereits",
"domain_zone_not_found": "DNS Zonen Datei kann nicht für Domäne {:s} gefunden werden",
"done": "Erledigt.",
"downloading": "Wird heruntergeladen...",
"dyndns_cron_installed": "DynDNS Cronjob erfolgreich installiert",
"dyndns_cron_remove_failed": "DynDNS Cronjob konnte nicht entfernt werden",
"dyndns_cron_removed": "DynDNS Cronjob wurde erfolgreich gelöscht",
"dyndns_ip_update_failed": "IP Adresse konnte nicht für DynDNS aktualisiert werden",
"dyndns_ip_updated": "IP Adresse wurde erfolgreich für DynDNS aktualisiert",
"dyndns_key_generating": "DNS Schlüssel wird generiert, das könnte eine Weile dauern...",
"dyndns_registered": "DynDNS Domain erfolgreich registriert",
"dyndns_registration_failed": "DynDNS Domain {:s} konnte nicht registriert werden",
"dyndns_unavailable": "DynDNS Subdomain ist nicht verfügbar",
"executing_command": "Führe Kommendo '{command:s}' aus...",
"executing_script": "Skript '{script:s}' wird ausgeührt...",
"extracting": "Wird entpackt...",
"field_invalid": "Feld '{:s}' ist unbekannt",
"firewall_reload_failed": "Firewall konnte nicht neu geladen werden",
"firewall_reloaded": "Firewall erfolgreich neu geladen",
"firewall_rules_cmd_failed": "Einzelne Firewallregeln konnten nicht übernommen werden. Mehr Informationen sind im Log zu finden.",
"format_datetime_short": "%m/%d/%Y %I:%M %p",
"hook_argument_missing": "Fehlend Argument '{:s}'",
"hook_choice_invalid": "ungültige Wahl '{:s}'",
"hook_exec_failed": "Skriptausführung fehlgeschlagen",
"hook_exec_not_terminated": "Skriptausführung noch nicht beendet",
"hook_list_by_invalid": "Ungültiger Wert zur Anzeige von Hooks",
"hook_name_unknown": "Hook '{:s}' ist nicht bekannt",
"installation_complete": "Installation vollständig",
"installation_failed": "Installation fehlgeschlagen",
"ip6tables_unavailable": "ip6tables kann nicht verwendet werden. Du befindest dich entweder in einem Container, oder es wird nicht vom Kernel unterstützt.",
"iptables_unavailable": "iptables kann nicht verwendet werden. Du befindest dich entweder in einem Container, oder es wird nicht vom Kernel unterstützt.",
"ldap_initialized": "LDAP erfolgreich initialisiert",
"license_undefined": "Undeiniert",
"mail_alias_remove_failed": "E-Mail Alias '{:s}' konnte nicht entfernt werden",
"mail_domain_unknown": "Unbekannte Mail Domain '{:s}'",
"mail_forward_remove_failed": "Mailweiterleitung '{:s}' konnte nicht entfernt werden",
"maindomain_change_failed": "Hauptdomain konnte nicht geändert werden",
"maindomain_changed": "Hauptdomain wurde erfolgreich geändert",
"monitor_disabled": "Servermonitoring erfolgreich deaktiviert",
"monitor_enabled": "Servermonitoring erfolgreich aktiviert",
"monitor_glances_con_failed": "Verbindung mit Glances nicht möglich",
"monitor_not_enabled": "Servermonitoring ist nicht aktiviert",
"monitor_period_invalid": "Falscher Zeitraum",
"monitor_stats_file_not_found": "Statistikdatei nicht gefunden",
"monitor_stats_no_update": "Keine Monitoringstatistik zur Aktualisierung",
"monitor_stats_period_unavailable": "Keine Statistiken für den gewählten Zeitraum verfügbar",
"mountpoint_unknown": "Unbekannten Einhängepunkt",
"mysql_db_creation_failed": "MySQL Datenbankerzeugung fehlgeschlagen",
"mysql_db_init_failed": "MySQL Datenbankinitialisierung fehlgeschlagen",
"mysql_db_initialized": "MySQL Datenbank erfolgreich initialisiert",
"network_check_mx_ko": "Es ist kein DNS MX Eintrag vorhanden",
"network_check_smtp_ko": "Ausgehender Mailverkehr (SMTP Port 25) scheint in deinem Netzwerk blockiert zu sein",
"network_check_smtp_ok": "Ausgehender Mailverkehr (SMTP Port 25) ist blockiert",
"new_domain_required": "Du musst eine neue Hauptdomain angeben",
"no_appslist_found": "Keine Appliste gefunden",
"no_internet_connection": "Der Server ist nicht mit dem Internet verbunden",
"no_ipv6_connectivity": "Eine IPv6 Verbindung steht nicht zur Verfügung",
"no_restore_script": "Es konnte kein Wiederherstellungsskript für '{app:s}' gefunden werden",
"no_such_conf_file": "Datei {file:s}: konnte nicht kopiert werden, da diese nicht existiert",
"packages_no_upgrade": "Es müssen keine Pakete aktualisiert werden",
"packages_upgrade_critical_later": "Wichtiges Paket ({:s}) wird später aktualisiert",
"packages_upgrade_failed": "Es konnten nicht alle Pakete aktualisiert werden",
"path_removal_failed": "Pfad {:s} konnte nicht entfernt werden",
"pattern_backup_archive_name": "Ein gültiger Dateiname kann nur aus alphanumerischen und -_. bestehen",
"pattern_domain": "Muss ein gültiger Domainname sein (z.B. meine-domain.org)",
"pattern_email": "Muss eine gültige E-Mail Adresse sein (z.B. someone@domain.org)",
"pattern_firstname": "Muss ein gültiger Vorname sein",
"pattern_lastname": "Muss ein gültiger Nachname sein",
"pattern_listname": "Kann nur Alphanumerische Zeichen oder Unterstriche enthalten",
"pattern_mailbox_quota": "Muss eine Größe inkl. b/k/M/G/T Suffix, oder 0 zum deaktivieren sein",
"pattern_password": "Muss mindestens drei Zeichen lang sein",
"pattern_port": "Es muss ein valider Port (zwischen 0 und 65535) angegeben werden",
"pattern_port_or_range": "Muss ein valider Port (z.B. 0-65535) oder ein Bereich (z.B. 100:200) sein",
"pattern_username": "Darf nur aus klein geschriebenen alphanumerischen Zeichen und Unterstrichen bestehen",
"port_already_closed": "Port {} wurde bereits für {:s} Verbindungen geschlossen",
"port_already_opened": "Der Port {} wird bereits von {:s} benutzt",
"port_available": "Port {} ist verfügbar",
"port_unavailable": "Der Port {} ist nicht verfügbar",
"restore_action_required": "Du musst etwas zum Wiederherstellen auswählen",
"restore_already_installed_app": "Es ist bereits eine App mit der ID '{app:s}' installiet",
"restore_app_failed": "App '{app:s}' konnte nicht wiederhergestellt werden",
"restore_cleaning_failed": "Temporäres Wiederherstellungsverzeichnis konnte nicht geleert werden",
"restore_complete": "Wiederherstellung abgeschlossen",
"restore_confirm_yunohost_installed": "Möchtest du die Wiederherstellung wirklich starten? [{answers:s}]",
"restore_failed": "System kann nicht Wiederhergestellt werden",
"restore_hook_unavailable": "Der Wiederherstellungshook '{hook:s}' steht auf deinem System nicht zur Verfügung",
"restore_nothings_done": "Es wurde nicht wiederhergestellt",
"restore_running_app_script": "Wiederherstellung wird ausfeührt für App '{app:s}'...",
"restore_running_hooks": "Wiederherstellung wird gestartet...",
"service_add_configuration": "Füge Konfigurationsdatei {file:s} hinzu",
"service_add_failed": "Dienst '{:s}' kann nicht hinzugefügt werden",
"service_added": "Service erfolgreich hinzugefügt",
"service_already_started": "Der Dienst '{:s}' läutt bereits",
"service_already_stopped": "Dienst '{:s}' wurde bereits gestoppt",
"service_cmd_exec_failed": "Kommando '{:s}' kann nicht ausgeführt werden",
"service_configuration_conflict": "Die Datei {file:s} wurde zwischenzeitlich verändert. Bitte übernehme die Änderungen manuell oder nutze die Option --force (diese wird alle Änderungen überschreiben).",
"service_disable_failed": "Dienst'{:s}' konnte nicht deaktiviert werden",
"service_disabled": "Der Dienst '{:s}' wurde erfolgreich deaktiviert",
"service_enable_failed": "Dienst '{:s}' konnte nicht aktiviert werden",
"service_enabled": "Dienst '{:s}' erfolgreich aktiviert",
"service_no_log": "Für den Dienst '{:s}' kann kein Log angezeigt werden",
"service_remove_failed": "Dienst '{:s}' konnte nicht entfernt werden",
"service_removed": "Dienst erfolgreich enternt",
"service_start_failed": "Dienst '{:s}' konnte nicht gestartet werden",
"service_started": "der Dienst '{:s}' wurde erfolgreich gestartet",
"service_status_failed": "Status von '{:s}' kann nicht festgestellt werden",
"service_stop_failed": "Dienst '{:s}' kann nicht gestoppt werden",
"service_stopped": "Dienst '{:s}' wurde erfolgreich beendet",
"service_unknown": "Unbekannte Dienst '{:s}'",
"services_configured": "Konfiguration erfolgreich erstellt",
"show_diff": "Es gibt folgende Änderungen:\n{diff:s}",
"ssowat_conf_generated": "Konfiguration von SSOwat erfolgreich",
"ssowat_conf_updated": "Persistente SSOwat Einstellung erfolgreich aktualisiert",
"system_upgraded": "System wurde erfolgreich aktualisiert",
"system_username_exists": "Der Benutzername existiert bereits",
"unbackup_app": "App '{app:s}' konnte nicht gespeichert werden",
"unexpected_error": "Ein unerwarteter Fehler ist aufgetreten",
"unit_unknown": "Unbekannte Einheit '{:s}'",
"unlimit": "Kein Kontingent",
"unrestore_app": "App '{app:s}' kann nicht Wiederhergestellt werden",
"update_cache_failed": "Konnte APT cache nicht aktualisieren",
"updating_apt_cache": "Liste der verfügbaren Pakete wird aktualisiert...",
"upgrade_complete": "Upgrade vollständig",
"upgrading_packages": "Pakete werden aktualisiert...",
"upnp_dev_not_found": "Es konnten keine UPnP Geräte gefunden werden",
"upnp_disabled": "UPnP wurde erfolgreich deaktiviert",
"upnp_enabled": "UPnP wurde aktiviert",
"upnp_port_open_failed": "UPnP Ports konnten nicht geöffnet werden",
"user_created": "Benutzer erfolgreich erstellt",
"user_creation_failed": "Nutzer konnte nicht erstellt werden",
"user_deleted": "Benutzer wurde erfolgreich entfernt",
"user_deletion_failed": "Nutzer konnte nicht gelöscht werden",
"user_home_creation_failed": "Benutzer Home konnte nicht erstellt werden",
"user_info_failed": "Nutzerinformationen können nicht angezeigt werden",
"user_unknown": "Unbekannter Benutzer",
"user_update_failed": "Benutzer kann nicht aktualisiert werden",
"user_updated": "Benutzer wurde erfolgreich aktualisiert",
"yunohost_already_installed": "YunoHost ist bereits installiert",
"yunohost_ca_creation_failed": "Zertifikatsstelle konnte nicht erstellt werden",
"yunohost_configured": "YunoHost wurde erfolgreich konfiguriert",
"yunohost_installing": "YunoHost wird installiert...",
"action_invalid": "Ungültige Aktion '{action:s}'",
"admin_password": "Verwaltungspasswort",
"admin_password_change_failed": "Passwort kann nicht geändert werden",
"admin_password_changed": "Verwaltungspasswort wurde erfolgreich geändert",
"app_already_installed": "{app:s} ist schon installiert",
"app_argument_choice_invalid": "Invalide Auswahl für Argument '{name:s}'. Muss einer der folgenden Werte sein {choices:s}",
"app_argument_invalid": "Das Argument '{name:s}' hat einen falschen Wert: {error:s}",
"app_argument_required": "Argument '{name:s}' wird benötigt",
"app_extraction_failed": "Installationsdateien konnten nicht entpackt werden",
"app_id_invalid": "Falsche App ID",
"app_install_files_invalid": "Ungültige Installationsdateien",
"app_location_already_used": "Eine andere App ist bereits an diesem Ort installiert",
"app_location_install_failed": "Die App kann an diesem Ort nicht installiert werden",
"app_manifest_invalid": "Ungültiges App Manifest",
"app_no_upgrade": "Keine Aktualisierungen für Apps verfügbar",
"app_not_installed": "{app:s} ist nicht intalliert",
"app_recent_version_required": "Für {:s} benötigt eine aktuellere Version von moulinette",
"app_removed": "{app:s} wurde erfolgreich entfernt",
"app_sources_fetch_failed": "Quelldateien konnten nicht abgerufen werden",
"app_unknown": "Unbekannte App",
"app_upgrade_failed": "Apps konnten nicht aktualisiert werden",
"app_upgraded": "{app:s} wurde erfolgreich aktualisiert",
"appslist_fetched": "Liste der Apps wurde erfolgreich heruntergelanden",
"appslist_removed": "Appliste erfolgreich entfernt",
"appslist_retrieve_error": "Entfernte App Liste kann nicht gezogen werden",
"appslist_unknown": "Unbekannte App Liste",
"ask_current_admin_password": "Derzeitiges Verwaltungspasswort",
"ask_email": "E-Mail Adresse",
"ask_firstname": "Vorname",
"ask_lastname": "Nachname",
"ask_list_to_remove": "Liste enternen",
"ask_main_domain": "Hauptdomain",
"ask_new_admin_password": "Neues Verwaltungskennwort",
"ask_password": "Passwort",
"backup_action_required": "Du musst etwas zum Speichern auswählen",
"backup_app_failed": "Konnte keine Sicherung für '{app:s}' erstellen",
"backup_archive_app_not_found": "App '{app:s}' konnte in keiner Datensicherung gefunden werden",
"backup_archive_hook_not_exec": "Hook '{hook:s}' konnte für diese Datensicherung nicht ausgeführt werden",
"backup_archive_name_exists": "Datensicherung mit dem selben Namen existiert bereits",
"backup_archive_name_unknown": "Unbekanntes lokale Datensicherung mit Namen '{name:s}' gefunden",
"backup_archive_open_failed": "Kann Sicherungsarchiv nicht öfnen",
"backup_cleaning_failed": "Verzeichnis von temporäre Sicherungsdaten konnte nicht geleert werden",
"backup_complete": "Datensicherung komplett",
"backup_creating_archive": "Datensicherung wird erstellt...",
"backup_delete_error": "Pfad '{path:s}' konnte nicht gelöscht werden",
"backup_deleted": "Datensicherung erfolgreich gelöscht",
"backup_extracting_archive": "Entpacke Sicherungsarchiv...",
"backup_hook_unknown": "Datensicherungshook '{hook:s}' unbekannt",
"backup_invalid_archive": "Ungültige Datensicherung",
"backup_nothings_done": "Es gibt keine Änderungen zur Speicherung",
"backup_output_directory_forbidden": "Verbotenes Ausgabeverzeichnis",
"backup_output_directory_not_empty": "Ausgabeordner ist nicht leer",
"backup_output_directory_required": "Für die Datensicherung muss ein Zielverzeichnis angegeben werden",
"backup_running_app_script": "Datensicherung für App '{app:s}' wurd durchgeführt...",
"backup_running_hooks": "Datensicherunghook wird ausgeführt...",
"custom_app_url_required": "Es muss eine URL angegeben um deine benutzerdefinierte App {app:s} zu aktualisieren",
"custom_appslist_name_required": "Du musst einen Namen für deine benutzerdefinierte Appliste angeben",
"dnsmasq_isnt_installed": "dnsmasq scheint nicht installiert zu sein. Bitte führe 'apt-get remove bind9 && apt-get install dnsmasq' aus",
"domain_cert_gen_failed": "Zertifikat konnte nicht erzeugt werden",
"domain_created": "Domain erfolgreich erzeugt",
"domain_creation_failed": "Konnte Domain nicht erzeugen",
"domain_deleted": "Domain erfolgreich gelöscht",
"domain_deletion_failed": "Konnte Domain nicht löschen",
"domain_dyndns_already_subscribed": "Du hast dich schon für einen DynDNS-Domain angemeldet",
"domain_dyndns_invalid": "Domain nicht mittels DynDNS nutzbar",
"domain_dyndns_root_unknown": "Unbekannte DynDNS Hauptdomain",
"domain_exists": "Die Domain existiert bereits",
"domain_uninstall_app_first": "Mindestens eine App ist noch für diese Domain installiert. Bitte zuerst die App deinstallieren und erst dann die Domain löschen..",
"domain_unknown": "Unbekannte Domain",
"domain_zone_exists": "DNS Zonen Datei existiert bereits",
"domain_zone_not_found": "DNS Zonen Datei kann nicht für Domäne {:s} gefunden werden",
"done": "Erledigt.",
"downloading": "Wird heruntergeladen...",
"dyndns_cron_installed": "DynDNS Cronjob erfolgreich installiert",
"dyndns_cron_remove_failed": "DynDNS Cronjob konnte nicht entfernt werden",
"dyndns_cron_removed": "DynDNS Cronjob wurde erfolgreich gelöscht",
"dyndns_ip_update_failed": "IP Adresse konnte nicht für DynDNS aktualisiert werden",
"dyndns_ip_updated": "IP Adresse wurde erfolgreich für DynDNS aktualisiert",
"dyndns_key_generating": "DNS Schlüssel wird generiert, das könnte eine Weile dauern...",
"dyndns_registered": "DynDNS Domain erfolgreich registriert",
"dyndns_registration_failed": "DynDNS Domain konnte nicht registriert werden: {error:s}",
"dyndns_unavailable": "DynDNS Subdomain ist nicht verfügbar",
"executing_command": "Führe Kommendo '{command:s}' aus...",
"executing_script": "Skript '{script:s}' wird ausgeührt...",
"extracting": "Wird entpackt...",
"field_invalid": "Feld '{:s}' ist unbekannt",
"firewall_reload_failed": "Firewall konnte nicht neu geladen werden",
"firewall_reloaded": "Firewall erfolgreich neu geladen",
"firewall_rules_cmd_failed": "Einzelne Firewallregeln konnten nicht übernommen werden. Mehr Informationen sind im Log zu finden.",
"format_datetime_short": "%m/%d/%Y %I:%M %p",
"hook_argument_missing": "Fehlend Argument '{:s}'",
"hook_choice_invalid": "ungültige Wahl '{:s}'",
"hook_exec_failed": "Skriptausführung fehlgeschlagen",
"hook_exec_not_terminated": "Skriptausführung noch nicht beendet",
"hook_list_by_invalid": "Ungültiger Wert zur Anzeige von Hooks",
"hook_name_unknown": "Hook '{name:s}' ist nicht bekannt",
"installation_complete": "Installation vollständig",
"installation_failed": "Installation fehlgeschlagen",
"ip6tables_unavailable": "ip6tables kann nicht verwendet werden. Du befindest dich entweder in einem Container, oder es wird nicht vom Kernel unterstützt.",
"iptables_unavailable": "iptables kann nicht verwendet werden. Du befindest dich entweder in einem Container, oder es wird nicht vom Kernel unterstützt.",
"ldap_initialized": "LDAP erfolgreich initialisiert",
"license_undefined": "Undeiniert",
"mail_alias_remove_failed": "E-Mail Alias '{mail:s}' konnte nicht entfernt werden",
"mail_domain_unknown": "Unbekannte Mail Domain '{domain:s}'",
"mail_forward_remove_failed": "Mailweiterleitung '{mail:s}' konnte nicht entfernt werden",
"maindomain_change_failed": "Hauptdomain konnte nicht geändert werden",
"maindomain_changed": "Hauptdomain wurde erfolgreich geändert",
"monitor_disabled": "Servermonitoring erfolgreich deaktiviert",
"monitor_enabled": "Servermonitoring erfolgreich aktiviert",
"monitor_glances_con_failed": "Verbindung mit Glances nicht möglich",
"monitor_not_enabled": "Servermonitoring ist nicht aktiviert",
"monitor_period_invalid": "Falscher Zeitraum",
"monitor_stats_file_not_found": "Statistikdatei nicht gefunden",
"monitor_stats_no_update": "Keine Monitoringstatistik zur Aktualisierung",
"monitor_stats_period_unavailable": "Keine Statistiken für den gewählten Zeitraum verfügbar",
"mountpoint_unknown": "Unbekannten Einhängepunkt",
"mysql_db_creation_failed": "MySQL Datenbankerzeugung fehlgeschlagen",
"mysql_db_init_failed": "MySQL Datenbankinitialisierung fehlgeschlagen",
"mysql_db_initialized": "MySQL Datenbank erfolgreich initialisiert",
"network_check_mx_ko": "Es ist kein DNS MX Eintrag vorhanden",
"network_check_smtp_ko": "Ausgehender Mailverkehr (SMTP Port 25) scheint in deinem Netzwerk blockiert zu sein",
"network_check_smtp_ok": "Ausgehender Mailverkehr (SMTP Port 25) ist blockiert",
"new_domain_required": "Du musst eine neue Hauptdomain angeben",
"no_appslist_found": "Keine Appliste gefunden",
"no_internet_connection": "Der Server ist nicht mit dem Internet verbunden",
"no_ipv6_connectivity": "Eine IPv6 Verbindung steht nicht zur Verfügung",
"no_restore_script": "Es konnte kein Wiederherstellungsskript für '{app:s}' gefunden werden",
"no_such_conf_file": "Datei {file:s}: konnte nicht kopiert werden, da diese nicht existiert",
"packages_no_upgrade": "Es müssen keine Pakete aktualisiert werden",
"packages_upgrade_critical_later": "Wichtiges Paket ({packages:s}) wird später aktualisiert",
"packages_upgrade_failed": "Es konnten nicht alle Pakete aktualisiert werden",
"path_removal_failed": "Pfad {:s} konnte nicht entfernt werden",
"pattern_backup_archive_name": "Ein gültiger Dateiname kann nur aus alphanumerischen und -_. bestehen",
"pattern_domain": "Muss ein gültiger Domainname sein (z.B. meine-domain.org)",
"pattern_email": "Muss eine gültige E-Mail Adresse sein (z.B. someone@domain.org)",
"pattern_firstname": "Muss ein gültiger Vorname sein",
"pattern_lastname": "Muss ein gültiger Nachname sein",
"pattern_listname": "Kann nur Alphanumerische Zeichen oder Unterstriche enthalten",
"pattern_mailbox_quota": "Muss eine Größe inkl. b/k/M/G/T Suffix, oder 0 zum deaktivieren sein",
"pattern_password": "Muss mindestens drei Zeichen lang sein",
"pattern_port": "Es muss ein valider Port (zwischen 0 und 65535) angegeben werden",
"pattern_port_or_range": "Muss ein valider Port (z.B. 0-65535) oder ein Bereich (z.B. 100:200) sein",
"pattern_username": "Darf nur aus klein geschriebenen alphanumerischen Zeichen und Unterstrichen bestehen",
"port_already_closed": "Port {port:d} wurde bereits für {ip_version:s} Verbindungen geschlossen",
"port_already_opened": "Der Port {port:d} wird bereits von {ip_version:s} benutzt",
"port_available": "Port {port:d} ist verfügbar",
"port_unavailable": "Der Port {port:d} ist nicht verfügbar",
"restore_action_required": "Du musst etwas zum Wiederherstellen auswählen",
"restore_already_installed_app": "Es ist bereits eine App mit der ID '{app:s}' installiet",
"restore_app_failed": "App '{app:s}' konnte nicht wiederhergestellt werden",
"restore_cleaning_failed": "Temporäres Wiederherstellungsverzeichnis konnte nicht geleert werden",
"restore_complete": "Wiederherstellung abgeschlossen",
"restore_confirm_yunohost_installed": "Möchtest du die Wiederherstellung wirklich starten? [{answers:s}]",
"restore_failed": "System kann nicht Wiederhergestellt werden",
"restore_hook_unavailable": "Der Wiederherstellungshook '{hook:s}' steht auf deinem System nicht zur Verfügung",
"restore_nothings_done": "Es wurde nicht wiederhergestellt",
"restore_running_app_script": "Wiederherstellung wird ausfeührt für App '{app:s}'...",
"restore_running_hooks": "Wiederherstellung wird gestartet...",
"service_add_configuration": "Füge Konfigurationsdatei {file:s} hinzu",
"service_add_failed": "Dienst '{service:s}' kann nicht hinzugefügt werden",
"service_added": "Service erfolgreich hinzugefügt",
"service_already_started": "Der Dienst '{service:s}' läutt bereits",
"service_already_stopped": "Dienst '{service:s}' wurde bereits gestoppt",
"service_cmd_exec_failed": "Kommando '{command:s}' kann nicht ausgeführt werden",
"service_configuration_conflict": "Die Datei {file:s} wurde zwischenzeitlich verändert. Bitte übernehme die Änderungen manuell oder nutze die Option --force (diese wird alle Änderungen überschreiben).",
"service_disable_failed": "Dienst '{service:s}' konnte nicht deaktiviert werden",
"service_disabled": "Der Dienst '{service:s}' wurde erfolgreich deaktiviert",
"service_enable_failed": "Dienst '{service:s}' konnte nicht aktiviert werden",
"service_enabled": "Dienst '{service:s}' erfolgreich aktiviert",
"service_no_log": "Für den Dienst '{service:s}' kann kein Log angezeigt werden",
"service_remove_failed": "Dienst '{service:s}' konnte nicht entfernt werden",
"service_removed": "Dienst erfolgreich enternt",
"service_start_failed": "Dienst '{service:s}' konnte nicht gestartet werden",
"service_started": "der Dienst '{service:s}' wurde erfolgreich gestartet",
"service_status_failed": "Status von '{service:s}' kann nicht festgestellt werden",
"service_stop_failed": "Dienst '{service:s}' kann nicht gestoppt werden",
"service_stopped": "Dienst '{service:s}' wurde erfolgreich beendet",
"service_unknown": "Unbekannte Dienst '{service:s}'",
"services_configured": "Konfiguration erfolgreich erstellt",
"show_diff": "Es gibt folgende Änderungen:\n{diff:s}",
"ssowat_conf_generated": "Konfiguration von SSOwat erfolgreich",
"ssowat_conf_updated": "Persistente SSOwat Einstellung erfolgreich aktualisiert",
"system_upgraded": "System wurde erfolgreich aktualisiert",
"system_username_exists": "Der Benutzername existiert bereits",
"unbackup_app": "App '{app:s}' konnte nicht gespeichert werden",
"unexpected_error": "Ein unerwarteter Fehler ist aufgetreten",
"unit_unknown": "Unbekannte Einheit '{unit:s}'",
"unlimit": "Kein Kontingent",
"unrestore_app": "App '{app:s}' kann nicht Wiederhergestellt werden",
"update_cache_failed": "Konnte APT cache nicht aktualisieren",
"updating_apt_cache": "Liste der verfügbaren Pakete wird aktualisiert...",
"upgrade_complete": "Upgrade vollständig",
"upgrading_packages": "Pakete werden aktualisiert...",
"upnp_dev_not_found": "Es konnten keine UPnP Geräte gefunden werden",
"upnp_disabled": "UPnP wurde erfolgreich deaktiviert",
"upnp_enabled": "UPnP wurde aktiviert",
"upnp_port_open_failed": "UPnP Ports konnten nicht geöffnet werden",
"user_created": "Benutzer erfolgreich erstellt",
"user_creation_failed": "Nutzer konnte nicht erstellt werden",
"user_deleted": "Benutzer wurde erfolgreich entfernt",
"user_deletion_failed": "Nutzer konnte nicht gelöscht werden",
"user_home_creation_failed": "Benutzer Home konnte nicht erstellt werden",
"user_info_failed": "Nutzerinformationen können nicht angezeigt werden",
"user_unknown": "Unbekannter Benutzer",
"user_update_failed": "Benutzer kann nicht aktualisiert werden",
"user_updated": "Benutzer wurde erfolgreich aktualisiert",
"yunohost_already_installed": "YunoHost ist bereits installiert",
"yunohost_ca_creation_failed": "Zertifikatsstelle konnte nicht erstellt werden",
"yunohost_configured": "YunoHost wurde erfolgreich konfiguriert",
"yunohost_installing": "YunoHost wird installiert...",
"yunohost_not_installed": "Die YunoHost ist unvollständig. Bitte 'yunohost tools postinstall' ausführen."
}
}

View file

@ -22,7 +22,7 @@
"custom_app_url_required" : "You must provide an URL to upgrade your custom app {app:s}",
"app_requirements_checking" : "Checking required packages...",
"app_requirements_unmeet" : "Requirements are not met, the package {pkgname} ({version}) must be {spec}",
"app_requirements_failed" : "Unable to meet requirements: {err}",
"app_requirements_failed" : "Unable to meet requirements: {error}",
"app_upgraded" : "{app:s} successfully upgraded",
"app_upgrade_failed" : "Unable to upgrade {app:s}",
"app_id_invalid" : "Invalid app id",
@ -34,6 +34,8 @@
"app_extraction_failed" : "Unable to extract installation files",
"app_install_files_invalid" : "Invalid installation files",
"app_manifest_invalid" : "Invalid app manifest",
"app_incompatible" : "The app is incompatible with your YunoHost version",
"app_package_need_update" : "The app package need to be updated to follow YunoHost changes",
"app_argument_choice_invalid" : "Invalid choice for argument '{name:s}', it must be one of {choices:s}",
"app_argument_invalid" : "Invalid value for argument '{name:s}': {error:s}",
"app_argument_required" : "Argument '{name:s}' is required",
@ -128,12 +130,20 @@
"service_status_failed" : "Unable to determine status of service '{service:s}'",
"service_no_log" : "No log to display for service '{service:s}'",
"service_cmd_exec_failed" : "Unable to execute command '{command:s}'",
"service_configured": "Configuration successfully generated for service '{service:s}'",
"service_configured_all": "Configuration successfully generated for every services",
"service_configuration_conflict": "The file {file:s} has been changed since its last generation. Please apply the modifications manually or use the option --force (it will erase all the modifications previously done to the file).",
"no_such_conf_file": "Unable to copy the file {file:s}: the file does not exist",
"service_add_configuration": "Adding the configuration file {file:s}",
"show_diff": "Here are the differences:\n{diff:s}",
"service_regenconf_failed" : "Unable to regenerate the configuration for service(s): {services}",
"service_regenconf_pending_applying" : "Applying pending configuration for service '{service}'...",
"service_regenconf_dry_pending_applying" : "Checking pending configuration which would have been applied for service '{service}'...",
"service_conf_file_manually_removed" : "The configuration file '{conf}' has been manually removed and will not be created",
"service_conf_file_manually_modified" : "The configuration file '{conf}' has been manually modified and will not be updated",
"service_conf_file_not_managed" : "The configuration file '{conf}' is not managed yet and will not be updated",
"service_conf_file_backed_up" : "The configuration file '{conf}' has been backed up to '{backup}'",
"service_conf_file_removed" : "The configuration file '{conf}' has been removed",
"service_conf_file_remove_failed" : "Unable to remove the configuration file '{conf}'",
"service_conf_file_updated" : "The configuration file '{conf}' has been updated",
"service_conf_file_copy_failed" : "Unable to copy the new configuration file '{new}' to '{conf}'",
"service_conf_up_to_date" : "The configuration is already up-to-date for service '{service}'",
"service_conf_updated" : "The configuration has been updated for service '{service}'",
"service_conf_would_be_updated" : "The configuration would have been updated for service '{service}'",
"network_check_smtp_ok" : "Outbound mail (SMTP port 25) is not blocked",
"network_check_smtp_ko" : "Outbound mail (SMTP port 25) seems to be blocked by your network",

View file

@ -1,9 +1,9 @@
{
"action_invalid": "Acción inválida '{:s}'",
"action_invalid": "Acción inválida '{action:s}'",
"admin_password": "Contraseña administrativa",
"admin_password_change_failed": "No se pudo cambiar la contraseña",
"admin_password_changed": "Contraseña administrativa se cambió con éxito",
"app_already_installed": "{:s} ya está instalado ",
"app_already_installed": "{app:s} ya está instalado",
"app_extraction_failed": "No se pudo extraer los archivos de instalación ",
"app_id_invalid": "id de la aplicación inválida ",
"app_install_files_invalid": "Archivos de instalación inválidos ",
@ -11,13 +11,13 @@
"app_location_install_failed": "No se pudo instalar la aplicación en esta lugar",
"app_manifest_invalid": "Manifesto de la aplicación es inválido",
"app_no_upgrade": "Ninguna app a actualizar",
"app_not_installed": "{:s} no está instalado.",
"app_not_installed": "{app:s} no está instalado",
"app_recent_version_required": "{:s} requiere una versión más reciente de moulinette ",
"app_removed": "{:s} era eliminado con éxito ",
"app_removed": "{app:s} era eliminado con éxito",
"app_sources_fetch_failed": "No se pudo descargar los archivos de códigos fuentes",
"app_unknown": "App desconocida",
"app_upgrade_failed": "No se pudo actualizar todas las aplicaciones ",
"app_upgraded": "{:s} actualizado con éxito",
"app_upgraded": "{app:s} actualizado con éxito",
"appslist_fetched": "Lista de aplicaciones se trajo con éxito",
"appslist_removed": "Lista de aplicaciones se eliminó con éxito",
"appslist_retrieve_error": "No se pudo recuperar la lista de aplicaciones a distancia ",
@ -41,7 +41,7 @@
"backup_output_directory_not_empty": "La carpeta de salida no está vacía",
"backup_output_directory_required": "Debe proporcionar un directorio de salida para el backup",
"backup_running_hooks": "Ejecutando los hooks de backup...",
"custom_app_url_required": " Debe proporcionar una URL para actualizar su aplicación personalizada {:s} ",
"custom_app_url_required": "Debe proporcionar una URL para actualizar su aplicación personalizada {app:s}",
"custom_appslist_name_required": "Debe proporcionar un nombre para la lista de aplicaciones personalizadas ",
"dnsmasq_isnt_installed": "Parece que dnsmasq no está instalado, por favor, ejecuta 'apt-get remove bind9 && apt-get install dnsmasq'",
"domain_cert_gen_failed": "No se pudo crear certificado",
@ -66,7 +66,7 @@
"dyndns_ip_updated": "La dirección IP era actualizado en DynDNS con éxito",
"dyndns_key_generating": "Generación del llave de DNS está en curso. Este podría durar unos momentos...",
"dyndns_registered": "El dominio DynDNS era registrado con éxito.",
"dyndns_registration_failed": "No se pudo registrar el dominio DynDNS: {:s}",
"dyndns_registration_failed": "No se pudo registrar el dominio DynDNS: {error:s}",
"dyndns_unavailable": "Subdominio DynDNS no disponible",
"executing_script": "Ejecutando script...",
"extracting": "Extrayendo...",
@ -77,16 +77,16 @@
"hook_argument_missing": "Falta un parámetro '{:s}'",
"hook_choice_invalid": "Selección inválida '{:s}'",
"hook_list_by_invalid": "La propiedad de este hook es inválida",
"hook_name_unknown": "Hook desconocido '{:s}'",
"hook_name_unknown": "Hook desconocido '{name:s}'",
"installation_complete": "La instalación se ha completado",
"installation_failed": "La Instalación se ha fracasado",
"ip6tables_unavailable": "No puedes modificar los ip6tables aquí. Eres en un contenedor o su kernel no soporte este opción.",
"iptables_unavailable": "No puedes modificar los iptables aquí. Eres en un contenedor o su kernel no soporte este opción.",
"ldap_initialized": "LDAP se inició con éxito",
"license_undefined": "indefinido",
"mail_alias_remove_failed": "No se pudo quitar el alias de correos '{:s}'",
"mail_domain_unknown": "El dominio de correos '{:s}' es desconocido",
"mail_forward_remove_failed": "No se pudo quitar la reenvía de correos '{:s}'",
"mail_alias_remove_failed": "No se pudo quitar el alias de correos '{mail:s}'",
"mail_domain_unknown": "El dominio de correos '{domain:s}' es desconocido",
"mail_forward_remove_failed": "No se pudo quitar la reenvía de correos '{mail:s}'",
"maindomain_change_failed": "No se pudo cambiar el dominio principal",
"maindomain_changed": "Dominio principal se cambió con éxito",
"monitor_disabled": "Supervisión del sistema era desactivado con éxito",
@ -105,7 +105,7 @@
"no_appslist_found": "No se encontró ninguna lista de Apps",
"no_internet_connection": "El servidor no está conectado al Internet.",
"packages_no_upgrade": "No hay actualización por ningun paquete",
"packages_upgrade_critical_later": "Los paquetes críticos ({:s}) se actualizarán más tarde",
"packages_upgrade_critical_later": "Los paquetes críticos ({packages:s}) se actualizarán más tarde",
"packages_upgrade_failed": "No se pudo actualizar todo de los paquetes",
"path_removal_failed": "No se pudo quitar la ruta {:s}",
"pattern_backup_archive_name": "Debe que ser un nombre de archivo válido con los caracteres alfanumericos, o los -_.",
@ -118,39 +118,39 @@
"pattern_port": "El numéro del puerto debe ser válido (i.e. 0-65535)",
"pattern_port_or_range": "El numéro del puerto debe ser válido (i.e. 0-65535) o un intervalo de puertos (e.g. 100:200)",
"pattern_username": "Debe contener solamente caracteres alfanuméricos o la guion bajo",
"port_already_closed": "El puerto {} ya está cerrado por {:s} connecciones.",
"port_already_opened": "El puerto {} ya está abierto por {:s} connecciones",
"port_available": "El puerto {} está disponible",
"port_unavailable": "El puerto {} no está disponible",
"port_already_closed": "El puerto {port:d} ya está cerrado por {ip_version:s} connecciones",
"port_already_opened": "El puerto {port:d} ya está abierto por {ip_version:s} connecciones",
"port_available": "El puerto {port:d} está disponible",
"port_unavailable": "El puerto {port:d} no está disponible",
"restore_complete": "Restauración se ha completado",
"restore_confirm_yunohost_installed": "Estás seguro que quieres restaurar a un sistema que ya está instalado? [{answers:s}]",
"restore_failed": "No se pudo restaurar el sistema",
"restore_running_hooks": "Ejecutando hooks de restauración...",
"service_add_failed": "No se pudo añadir el servicio '{:s}'",
"service_add_failed": "No se pudo añadir el servicio '{service:s}'",
"service_added": "Servicio añadido con éxito",
"service_already_started": "El servicio '{:s}' ya se ha empezado",
"service_already_stopped": "El servicio '{:s}' ya está parado ",
"service_cmd_exec_failed": "No se pudo ejecutar comando '{:s}'",
"service_disable_failed": "No se pudo desactivar el servicio '{:s}'",
"service_disabled": "Servicio '{:s}' desactivado con éxito",
"service_enable_failed": "No se pudo activar el servicio '{:s}'",
"service_enabled": "Servicio '{:s}' activado con éxito",
"service_no_log": "No hay archivo historial del servicio '{:s}' a exhibir",
"service_remove_failed": "No se pudo quitar el servicio '{:s}'",
"service_already_started": "El servicio '{service:s}' ya se ha empezado",
"service_already_stopped": "El servicio '{service:s}' ya está parado",
"service_cmd_exec_failed": "No se pudo ejecutar comando '{command:s}'",
"service_disable_failed": "No se pudo desactivar el servicio '{service:s}'",
"service_disabled": "Servicio '{service:s}' desactivado con éxito",
"service_enable_failed": "No se pudo activar el servicio '{service:s}'",
"service_enabled": "Servicio '{service:s}' activado con éxito",
"service_no_log": "No hay archivo historial del servicio '{service:s}' a exhibir",
"service_remove_failed": "No se pudo quitar el servicio '{service:s}'",
"service_removed": "Servicio quitado con éxito",
"service_start_failed": "No se pudo empezar el servicio '{:s}'",
"service_started": "El servicio '{:s}' se empezó con éxito",
"service_status_failed": "No se pudo discernir el estado del servicio '{:s}'",
"service_stop_failed": "No se pudo parar el servicio '{:s}'",
"service_stopped": "Servicio '{:s}' parado con éxito",
"service_unknown": "Servicio desconocido '{:s}'",
"service_start_failed": "No se pudo empezar el servicio '{service:s}'",
"service_started": "El servicio '{service:s}' se empezó con éxito",
"service_status_failed": "No se pudo discernir el estado del servicio '{service:s}'",
"service_stop_failed": "No se pudo parar el servicio '{service:s}'",
"service_stopped": "Servicio '{service:s}' parado con éxito",
"service_unknown": "Servicio desconocido '{service:s}'",
"ssowat_conf_generated": "Configuración SSOwat generado con éxito ",
"ssowat_conf_updated": "Configuración persistente SSOwat actualizada con éxito",
"system_upgraded": "Actualización del sistema se ha completado con éxito.",
"system_username_exists": "Nombre de usuario ya existe en los usuarios del sistema",
"unbackup_app": "La App '{:s}' no será guardada",
"unexpected_error": "Un error ha ocurrido",
"unit_unknown": "Unidad '{:s}' desconocido",
"unit_unknown": "Unidad '{unit:s}' desconocido",
"unrestore_app": "La App '{:s}' no será restaurada",
"update_cache_failed": "No se pudo actualizar el cache APT",
"updating_apt_cache": "Actualizando la lista de paquetes disponibles...",

View file

@ -1,218 +1,235 @@
{
"action_invalid": "Action « {:s} » incorrecte",
"admin_password": "Mot de passe d'administration",
"admin_password_change_failed": "Impossible de modifier le mot de passe d'administration",
"admin_password_changed": "Mot de passe d'administration modifié avec succès",
"app_already_installed": "{app:s} est déjà installé",
"app_argument_choice_invalid": "Choix invalide pour le paramètre « {name:s} », il doit être l'un de {choices:s}",
"app_argument_invalid": "Valeur invalide pour le paramètre « {name:s} » : {error:s}",
"app_argument_missing": "Paramètre manquant « {:s} »",
"app_argument_required": "Le paramètre « {name:s} » est requis",
"app_extraction_failed": "Impossible d'extraire les fichiers d'installation",
"app_id_invalid": "Id d'application incorrect",
"app_install_files_invalid": "Fichiers d'installation incorrects",
"app_location_already_used": "Une application est déjà installée à cet emplacement",
"app_location_install_failed": "Impossible d'installer l'application à cet emplacement",
"app_manifest_invalid": "Manifeste d'application incorrect",
"app_no_upgrade": "Aucune application à mettre à jour",
"app_not_correctly_installed": "{app:s} semble être mal installé",
"app_not_installed": "{app:s} n'est pas installé",
"app_recent_version_required": "{app:s} nécessite une version plus récente de YunoHost",
"app_removed": "{app:s} supprimé avec succès",
"app_sources_fetch_failed": "Impossible de récupérer les fichiers sources",
"app_unknown": "Application inconnue",
"app_unsupported_remote_type": "Le type distant utilisé par l'application n'est pas supporté",
"app_upgrade_failed": "Impossible de mettre à jour {app:s}",
"app_upgraded": "{app:s} mis à jour avec succès",
"appslist_fetched": "Liste d'applications récupérée avec succès",
"appslist_removed": "Liste d'applications supprimée avec succès",
"appslist_retrieve_error": "Impossible de récupérer la liste d'applications distante",
"appslist_unknown": "Liste d'applications inconnue",
"ask_current_admin_password": "Mot de passe d'administration actuel",
"ask_email": "Adresse courriel",
"ask_firstname": "Prénom",
"ask_lastname": "Nom",
"ask_list_to_remove": "Liste à supprimer",
"ask_main_domain": "Domaine principal",
"ask_new_admin_password": "Nouveau mot de passe d'administration",
"ask_password": "Mot de passe",
"backup_action_required": "Vous devez préciser ce qui est à sauvegarder",
"backup_app_failed": "Impossible de sauvegarder l'application « {app:s} »",
"backup_archive_app_not_found": "L'application « {app:s} » n'a pas été trouvée dans l'archive de la sauvegarde",
"backup_archive_hook_not_exec": "Le script « {hook:s} » n'a pas été exécuté dans cette sauvegarde",
"backup_archive_name_exists": "Une archive de sauvegarde avec ce nom existe déjà",
"backup_archive_name_unknown": "L'archive locale de sauvegarde nommée « {name:s} » est inconnue",
"backup_archive_open_failed": "Impossible d'ouvrir l'archive de sauvegarde",
"backup_cleaning_failed": "Impossible de nettoyer le dossier temporaire de sauvegarde",
"backup_complete": "Sauvegarde terminée",
"backup_creating_archive": "Création de l'archive de sauvegarde...",
"backup_delete_error": "Impossible de supprimer « {path:s} »",
"backup_deleted": "La sauvegarde a bien été supprimée",
"backup_extracting_archive": "Extraction de l'archive de sauvegarde...",
"backup_hook_unknown": "Script de sauvegarde « {hook:s} » inconnu",
"backup_invalid_archive": "Archive de sauvegarde incorrecte",
"backup_nothings_done": "Il n'y a rien à sauvegarder",
"backup_output_directory_forbidden": "Dossier de sortie interdit",
"backup_output_directory_not_empty": "Le dossier de sortie n'est pas vide",
"backup_output_directory_required": "Vous devez spécifier un dossier de sortie pour la sauvegarde",
"backup_running_app_script": "Lancement du script de sauvegarde de l'application « {app:s} »...",
"backup_running_hooks": "Exécution des scripts de sauvegarde...",
"custom_app_url_required": "Vous devez spécifier une URL pour mettre à jour votre application locale {app:s}",
"custom_appslist_name_required": "Vous devez spécifier un nom pour votre liste d'applications personnalisée",
"dnsmasq_isnt_installed": "dnsmasq ne semble pas être installé, veuillez lancer « apt-get remove bind9 && apt-get install dnsmasq »",
"domain_cert_gen_failed": "Impossible de générer le certificat",
"domain_created": "Domaine créé avec succès",
"domain_creation_failed": "Impossible de créer le domaine",
"domain_deleted": "Domaine supprimé avec succès",
"domain_deletion_failed": "Impossible de supprimer le domaine",
"domain_dyndns_already_subscribed": "Vous avez déjà souscris à un domaine DynDNS",
"domain_dyndns_invalid": "Domaine incorrect pour un usage avec DynDNS",
"domain_dyndns_root_unknown": "Domaine DynDNS principal inconnu",
"domain_exists": "Le domaine existe déjà",
"domain_uninstall_app_first": "Une ou plusieurs applications sont installées sur ce domaine. Veuillez d'abord les désinstaller avant de supprimer ce domaine.",
"domain_unknown": "Domaine inconnu",
"domain_zone_exists": "Le fichier de zone DNS existe déjà",
"domain_zone_not_found": "Fichier de zone DNS introuvable pour le domaine {:s}",
"done": "Terminé.",
"downloading": "Téléchargement...",
"dyndns_cron_installed": "Tâche cron pour DynDNS installée avec succès",
"dyndns_cron_remove_failed": "Impossible d'enlever la tâche cron pour DynDNS",
"dyndns_cron_removed": "La tâche cron pour DynDNS a été enlevée avec succès",
"dyndns_ip_update_failed": "Impossible de mettre à jour l'adresse IP sur le domaine DynDNS",
"dyndns_ip_updated": "Adresse IP mise à jour avec succès sur le domaine DynDNS",
"dyndns_key_generating": "La clé DNS est en cours de génération, cela peut prendre du temps...",
"dyndns_registered": "Domaine DynDNS enregistré avec succès",
"dyndns_registration_failed": "Impossible d'enregistrer le domaine DynDNS : {:s}",
"dyndns_unavailable": "Sous-domaine DynDNS indisponible",
"executing_command": "Exécution de la commande « {command:s} »...",
"executing_script": "Exécution du script « {script:s} »...",
"extracting": "Extraction...",
"field_invalid": "Champ incorrect : « {:s} »",
"firewall_reload_failed": "Impossible de recharger le pare-feu",
"firewall_reloaded": "Pare-feu rechargé avec succès",
"firewall_rules_cmd_failed": "Certaines règles du pare-feu n'ont pas pu être appliquées. Pour plus d'informations, consultez le journal.",
"format_datetime_short": "%d/%m/%Y %H:%M",
"hook_argument_missing": "Argument manquant : '{:s}'",
"hook_choice_invalid": "Choix incorrect : '{:s}'",
"hook_exec_failed": "Échec de l'exécution du script",
"hook_exec_not_terminated": "L'exécution du script ne s'est pas terminée",
"hook_list_by_invalid": "Propriété pour lister les scripts incorrecte",
"hook_name_unknown": "Nom de script « {:s} » inconnu",
"installation_complete": "Installation terminée",
"installation_failed": "Échec de l'installation",
"ip6tables_unavailable": "Vous ne pouvez pas jouer avec ip6tables ici. Vous êtes sûrement dans un conteneur, ou alors votre noyau ne le supporte pas.",
"iptables_unavailable": "Vous ne pouvez pas jouer avec iptables ici. Vous êtes sûrement dans un conteneur, autrement votre noyau ne le supporte pas.",
"ldap_initialized": "Répertoire LDAP initialisé avec succès",
"license_undefined": "indéfinie",
"mail_alias_remove_failed": "Impossible de supprimer l'adresse mail supplémentaire « {:s} »",
"mail_domain_unknown": "Domaine « {:s} » de l'adresse mail inconnu",
"mail_forward_remove_failed": "Impossible de supprimer l'adresse courriel de transfert « {:s} »",
"maindomain_change_failed": "Impossible de modifier le domaine principal",
"maindomain_changed": "Domaine principal modifié avec succès",
"monitor_disabled": "Le suivi de l'état du serveur a été désactivé avec succès",
"monitor_enabled": "Suivi de l'état du serveur activé avec succès",
"monitor_glances_con_failed": "Impossible de se connecter au serveur Glances",
"monitor_not_enabled": "Le suivi de l'état du serveur n'est pas activé",
"monitor_period_invalid": "Période de temps incorrecte",
"monitor_stats_file_not_found": "Le fichier de statistiques est introuvable",
"monitor_stats_no_update": "Aucune donnée de l'état du serveur à mettre à jour",
"monitor_stats_period_unavailable": "Aucune statistique n'est disponible pour la période",
"mountpoint_unknown": "Point de montage inconnu",
"mysql_db_creation_failed": "Impossible de créer la base de données MySQL",
"mysql_db_init_failed": "Impossible d'initialiser la base de données MySQL",
"mysql_db_initialized": "Base de donnée MySQL initialisée avec succès",
"network_check_mx_ko": "L'enregistrement DNS MX n'est pas précisé",
"network_check_smtp_ko": "Le trafic mail sortant (port 25 SMTP) semble bloqué par votre réseau",
"network_check_smtp_ok": "Le trafic courriel sortant (port 25 SMTP) n'est pas bloqué",
"new_domain_required": "Vous devez spécifier le nouveau domaine principal",
"no_appslist_found": "Aucune liste d'applications trouvée",
"no_internet_connection": "Le serveur n'est pas connecté à internet",
"no_ipv6_connectivity": "La connectivité IPv6 n'est pas disponible",
"no_restore_script": "Le script de sauvegarde n'a pas été trouvé pour l'application « {app:s} »",
"no_such_conf_file": "Le fichier {file:s} nexiste pas, il ne peut pas être copié",
"not_enough_disk_space": "L'espace disque est insuffisant sur « {path:s} »",
"packages_no_upgrade": "Il n'y a aucun paquet à mettre à jour",
"packages_upgrade_critical_later": "Les paquets critiques ({:s}) seront mis à jour ultérieurement",
"packages_upgrade_failed": "Impossible de mettre à jour tous les paquets",
"path_removal_failed": "Impossible de supprimer le chemin {:s}",
"pattern_backup_archive_name": "Doit être un nom de fichier valide composé de caractères alphanumérique et -_. uniquement",
"pattern_domain": "Doit être un nom de domaine valide (ex : mon-domaine.org)",
"pattern_email": "Doit être une adresse courriel valide (ex. : someone@domain.org)",
"pattern_firstname": "Doit être un prénom valide",
"pattern_lastname": "Doit être un nom valide",
"pattern_listname": "Doit être composé uniquement de caractères alphanumériques et de tirets bas",
"pattern_mailbox_quota": "Doit être une taille avec le suffixe b/k/M/G/T ou 0 pour désactiver le quota",
"pattern_password": "Doit être composé d'au moins 3 caractères",
"pattern_port": "Doit être un numéro de port valide (ex. : 0-65535)",
"pattern_port_or_range": "Doit être un numéro de port valide (ex. : 0-65535) ou une gamme de ports (ex. : 100:200)",
"pattern_positive_number": "Doit être un nombre positif",
"pattern_username": "Doit être composé uniquement de caractères alphanumériques minuscules et de tirets bas",
"port_already_closed": "Le port {} est déjà fermé pour les connexions {:s}",
"port_already_opened": "Le port {} est déjà ouvert pour les connexions {:s}",
"port_available": "Le port {port:d} est disponible",
"port_unavailable": "Le port {port:d} n'est pas disponible",
"restore_action_required": "Vous devez préciser ce qui est à restaurer",
"restore_already_installed_app": "Une application est déjà installée avec l'id « {app:s} »",
"restore_app_failed": "Impossible de restaurer l'application « {app:s} »",
"restore_cleaning_failed": "Impossible de nettoyer le dossier temporaire de restauration",
"restore_complete": "Restauration terminée",
"restore_confirm_yunohost_installed": "Voulez-vous vraiment restaurer un système déjà installé ? [{answers:s}]",
"restore_failed": "Impossible de restaurer le système",
"restore_hook_unavailable": "Le script de restauration « {hook:s} » n'est pas disponible sur votre système",
"restore_nothings_done": "Rien n'a été restauré",
"restore_running_app_script": "Lancement du script de restauration pour l'application « {app:s} »...",
"restore_running_hooks": "Exécution des scripts de restauration...",
"service_add_configuration": "Ajout du fichier de configuration {file:s}",
"service_add_failed": "Impossible d'ajouter le service « {:s} »",
"service_added": "Service ajouté avec succès",
"service_already_started": "Le service « {:s} » est déjà démarré",
"service_already_stopped": "Le service « {:s} » est déjà arrêté",
"service_cmd_exec_failed": "Impossible d'exécuter la commande « {:s} »",
"service_configuration_conflict": "Le fichier {file:s} a été modifié depuis sa dernière génération. Veuillez y appliquer les modifications manuellement ou utiliser loption --force (ce qui écrasera toutes les modifications effectuées sur le fichier).",
"service_disable_failed": "Impossible de désactiver le service « {:s} »",
"service_disabled": "Service « {:s} » désactivé avec succès",
"service_enable_failed": "Impossible d'activer le service « {:s} »",
"service_enabled": "Service « {:s} » activé avec succès",
"service_no_log": "Aucun journal à afficher pour le service « {:s} »",
"service_remove_failed": "Impossible d'enlever le service « {:s} »",
"service_removed": "Service enlevé avec succès",
"service_start_failed": "Impossible de démarrer le service « {:s} »",
"service_started": "Le service « {:s} » a démarré avec succès",
"service_status_failed": "Impossible de déterminer le statut du service « {:s} »",
"service_stop_failed": "Impossible d'arrêter le service « {:s} »",
"service_stopped": "Service « {:s} » arrêté avec succès",
"service_unknown": "Service « {:s} » inconnu",
"services_configured": "La configuration a été générée avec succès",
"show_diff": "Voici les différences :\n{diff:s}",
"ssowat_conf_generated": "Configuration de SSOwat générée avec succès",
"ssowat_conf_updated": "La configuration persistante de SSOwat a été mise à jour avec succès",
"system_upgraded": "Système mis à jour avec succès",
"system_username_exists": "Le nom d'utilisateur existe déjà dans les utilisateurs système",
"unbackup_app": "L'application « {app:s} » ne sera pas sauvegardée",
"unexpected_error": "Une erreur inattendue est survenue",
"unit_unknown": "Unité « {:s} » inconnue",
"unlimit": "Pas de quota",
"unrestore_app": "L'application « {app:s} » ne sera pas restaurée",
"update_cache_failed": "Impossible de mettre à jour le cache de l'APT",
"updating_apt_cache": "Mise à jour de la liste des paquets disponibles...",
"upgrade_complete": "Mise à jour terminée",
"upgrading_packages": "Mise à jour des paquets...",
"upnp_dev_not_found": "Aucun périphérique compatible UPnP n'a été trouvé",
"upnp_disabled": "UPnP désactivé avec succès",
"upnp_enabled": "UPnP activé avec succès",
"upnp_port_open_failed": "Impossible d'ouvrir les ports avec UPnP",
"user_created": "Utilisateur créé avec succès",
"user_creation_failed": "Impossible de créer l'utilisateur",
"user_deleted": "Utilisateur supprimé avec succès",
"user_deletion_failed": "Impossible de supprimer l'utilisateur",
"user_home_creation_failed": "Impossible de créer le dossier personnel de l'utilisateur",
"user_info_failed": "Impossible de récupérer les informations de l'utilisateur",
"user_unknown": "Utilisateur inconnu",
"user_update_failed": "Impossible de modifier l'utilisateur",
"user_updated": "Utilisateur modifié avec succès",
"yunohost_already_installed": "YunoHost est déjà installé",
"yunohost_ca_creation_failed": "Impossible de créer l'autorité de certification",
"yunohost_configured": "YunoHost configuré avec succès",
"yunohost_installing": "Installation de YunoHost...",
"action_invalid": "Action « {action:s} » incorrecte",
"admin_password": "Mot de passe d'administration",
"admin_password_change_failed": "Impossible de modifier le mot de passe d'administration",
"admin_password_changed": "Mot de passe d'administration modifié avec succès",
"app_already_installed": "{app:s} est déjà installé",
"app_argument_choice_invalid": "Choix invalide pour le paramètre « {name:s} », il doit être l'un de {choices:s}",
"app_argument_invalid": "Valeur invalide pour le paramètre « {name:s} » : {error:s}",
"app_argument_missing": "Paramètre manquant « {:s} »",
"app_argument_required": "Le paramètre « {name:s} » est requis",
"app_extraction_failed": "Impossible d'extraire les fichiers d'installation",
"app_id_invalid": "Id d'application incorrect",
"app_install_files_invalid": "Fichiers d'installation incorrects",
"app_location_already_used": "Une application est déjà installée à cet emplacement",
"app_location_install_failed": "Impossible d'installer l'application à cet emplacement",
"app_manifest_invalid": "Manifeste d'application incorrect",
"app_no_upgrade": "Aucune application à mettre à jour",
"app_not_correctly_installed": "{app:s} semble être mal installé",
"app_not_installed": "{app:s} n'est pas installé",
"app_not_properly_removed": "{app:s} n'a pas été supprimé correctement",
"app_recent_version_required": "{app:s} nécessite une version plus récente de YunoHost",
"app_removed": "{app:s} supprimé avec succès",
"app_requirements_checking": "Vérification des paquets requis...",
"app_requirements_failed": "Impossible de satisfaire les pré-requis : {error}",
"app_requirements_unmeet": "Les pré-requis ne sont pas satisfaits, le paquet {pkgname} ({version}) doit être {spec}",
"app_sources_fetch_failed": "Impossible de récupérer les fichiers sources",
"app_unknown": "Application inconnue",
"app_unsupported_remote_type": "Le type distant utilisé par l'application n'est pas supporté",
"app_upgrade_failed": "Impossible de mettre à jour {app:s}",
"app_upgraded": "{app:s} mis à jour avec succès",
"appslist_fetched": "Liste d'applications récupérée avec succès",
"appslist_removed": "Liste d'applications supprimée avec succès",
"appslist_retrieve_error": "Impossible de récupérer la liste d'applications distante",
"appslist_unknown": "Liste d'applications inconnue",
"ask_current_admin_password": "Mot de passe d'administration actuel",
"ask_email": "Adresse courriel",
"ask_firstname": "Prénom",
"ask_lastname": "Nom",
"ask_list_to_remove": "Liste à supprimer",
"ask_main_domain": "Domaine principal",
"ask_new_admin_password": "Nouveau mot de passe d'administration",
"ask_password": "Mot de passe",
"backup_action_required": "Vous devez préciser ce qui est à sauvegarder",
"backup_app_failed": "Impossible de sauvegarder l'application « {app:s} »",
"backup_archive_app_not_found": "L'application « {app:s} » n'a pas été trouvée dans l'archive de la sauvegarde",
"backup_archive_hook_not_exec": "Le script « {hook:s} » n'a pas été exécuté dans cette sauvegarde",
"backup_archive_name_exists": "Une archive de sauvegarde avec ce nom existe déjà",
"backup_archive_name_unknown": "L'archive locale de sauvegarde nommée « {name:s} » est inconnue",
"backup_archive_open_failed": "Impossible d'ouvrir l'archive de sauvegarde",
"backup_cleaning_failed": "Impossible de nettoyer le dossier temporaire de sauvegarde",
"backup_complete": "Sauvegarde terminée",
"backup_creating_archive": "Création de l'archive de sauvegarde...",
"backup_delete_error": "Impossible de supprimer « {path:s} »",
"backup_deleted": "La sauvegarde a bien été supprimée",
"backup_extracting_archive": "Extraction de l'archive de sauvegarde...",
"backup_hook_unknown": "Script de sauvegarde « {hook:s} » inconnu",
"backup_invalid_archive": "Archive de sauvegarde incorrecte",
"backup_nothings_done": "Il n'y a rien à sauvegarder",
"backup_output_directory_forbidden": "Dossier de sortie interdit. Les sauvegardes ne peuvent être créées dans les dossiers /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var ou /home/yunohost.backup/archives.",
"backup_output_directory_not_empty": "Le dossier de sortie n'est pas vide",
"backup_output_directory_required": "Vous devez spécifier un dossier de sortie pour la sauvegarde",
"backup_running_app_script": "Lancement du script de sauvegarde de l'application « {app:s} »...",
"backup_running_hooks": "Exécution des scripts de sauvegarde...",
"custom_app_url_required": "Vous devez spécifier une URL pour mettre à jour votre application locale {app:s}",
"custom_appslist_name_required": "Vous devez spécifier un nom pour votre liste d'applications personnalisée",
"diagnostic_debian_version_error": "Impossible de déterminer la version de Debian : {error}",
"diagnostic_kernel_version_error": "Impossible de récupérer la version du noyau : {error}",
"diagnostic_monitor_disk_error": "Impossible de superviser les disques : {error}",
"diagnostic_monitor_network_error": "Impossible de superviser le réseau : {error}",
"diagnostic_monitor_system_error": "Impossible de superviser le système : {error}",
"diagnostic_no_apps": "Aucune application installée",
"dnsmasq_isnt_installed": "dnsmasq ne semble pas être installé, veuillez lancer « apt-get remove bind9 && apt-get install dnsmasq »",
"domain_cert_gen_failed": "Impossible de générer le certificat",
"domain_created": "Domaine créé avec succès",
"domain_creation_failed": "Impossible de créer le domaine",
"domain_deleted": "Domaine supprimé avec succès",
"domain_deletion_failed": "Impossible de supprimer le domaine",
"domain_dyndns_already_subscribed": "Vous avez déjà souscris à un domaine DynDNS",
"domain_dyndns_invalid": "Domaine incorrect pour un usage avec DynDNS",
"domain_dyndns_root_unknown": "Domaine DynDNS principal inconnu",
"domain_exists": "Le domaine existe déjà",
"domain_uninstall_app_first": "Une ou plusieurs applications sont installées sur ce domaine. Veuillez d'abord les désinstaller avant de supprimer ce domaine.",
"domain_unknown": "Domaine inconnu",
"domain_zone_exists": "Le fichier de zone DNS existe déjà",
"domain_zone_not_found": "Fichier de zone DNS introuvable pour le domaine {:s}",
"done": "Terminé.",
"downloading": "Téléchargement...",
"dyndns_cron_installed": "Tâche cron pour DynDNS installée avec succès",
"dyndns_cron_remove_failed": "Impossible d'enlever la tâche cron pour DynDNS",
"dyndns_cron_removed": "La tâche cron pour DynDNS a été enlevée avec succès",
"dyndns_ip_update_failed": "Impossible de mettre à jour l'adresse IP sur le domaine DynDNS",
"dyndns_ip_updated": "Adresse IP mise à jour avec succès sur le domaine DynDNS",
"dyndns_key_generating": "La clé DNS est en cours de génération, cela peut prendre du temps...",
"dyndns_key_not_found": "Clé DNS introuvable pour le domaine",
"dyndns_no_domain_registered": "Aucun domaine n'a été enregistré avec DynDNS",
"dyndns_registered": "Domaine DynDNS enregistré avec succès",
"dyndns_registration_failed": "Impossible d'enregistrer le domaine DynDNS : {error:s}",
"dyndns_unavailable": "Sous-domaine DynDNS indisponible",
"executing_command": "Exécution de la commande « {command:s} »...",
"executing_script": "Exécution du script « {script:s} »...",
"extracting": "Extraction...",
"field_invalid": "Champ incorrect : « {:s} »",
"firewall_reload_failed": "Impossible de recharger le pare-feu",
"firewall_reloaded": "Pare-feu rechargé avec succès",
"firewall_rules_cmd_failed": "Certaines règles du pare-feu n'ont pas pu être appliquées. Pour plus d'informations, consultez le journal.",
"format_datetime_short": "%d/%m/%Y %H:%M",
"hook_argument_missing": "Argument manquant : '{:s}'",
"hook_choice_invalid": "Choix incorrect : '{:s}'",
"hook_exec_failed": "Échec de l'exécution du script « {path:s} »",
"hook_exec_not_terminated": "L'exécution du script « {path:s} » ne s'est pas terminée",
"hook_list_by_invalid": "Propriété pour lister les scripts incorrecte",
"hook_name_unknown": "Nom de script « {name:s} » inconnu",
"installation_complete": "Installation terminée",
"installation_failed": "Échec de l'installation",
"ip6tables_unavailable": "Vous ne pouvez pas jouer avec ip6tables ici. Vous êtes sûrement dans un conteneur, ou alors votre noyau ne le supporte pas.",
"iptables_unavailable": "Vous ne pouvez pas jouer avec iptables ici. Vous êtes sûrement dans un conteneur, autrement votre noyau ne le supporte pas.",
"ldap_initialized": "Répertoire LDAP initialisé avec succès",
"license_undefined": "indéfinie",
"mail_alias_remove_failed": "Impossible de supprimer l'adresse mail supplémentaire « {mail:s} »",
"mail_domain_unknown": "Domaine « {domain:s} » de l'adresse mail inconnu",
"mail_forward_remove_failed": "Impossible de supprimer l'adresse courriel de transfert « {mail:s} »",
"maindomain_change_failed": "Impossible de modifier le domaine principal",
"maindomain_changed": "Domaine principal modifié avec succès",
"monitor_disabled": "Le suivi de l'état du serveur a été désactivé avec succès",
"monitor_enabled": "Suivi de l'état du serveur activé avec succès",
"monitor_glances_con_failed": "Impossible de se connecter au serveur Glances",
"monitor_not_enabled": "Le suivi de l'état du serveur n'est pas activé",
"monitor_period_invalid": "Période de temps incorrecte",
"monitor_stats_file_not_found": "Le fichier de statistiques est introuvable",
"monitor_stats_no_update": "Aucune donnée de l'état du serveur à mettre à jour",
"monitor_stats_period_unavailable": "Aucune statistique n'est disponible pour la période",
"mountpoint_unknown": "Point de montage inconnu",
"mysql_db_creation_failed": "Impossible de créer la base de données MySQL",
"mysql_db_init_failed": "Impossible d'initialiser la base de données MySQL",
"mysql_db_initialized": "Base de donnée MySQL initialisée avec succès",
"network_check_mx_ko": "L'enregistrement DNS MX n'est pas précisé",
"network_check_smtp_ko": "Le trafic mail sortant (port 25 SMTP) semble bloqué par votre réseau",
"network_check_smtp_ok": "Le trafic courriel sortant (port 25 SMTP) n'est pas bloqué",
"new_domain_required": "Vous devez spécifier le nouveau domaine principal",
"no_appslist_found": "Aucune liste d'applications trouvée",
"no_internet_connection": "Le serveur n'est pas connecté à internet",
"no_ipv6_connectivity": "La connectivité IPv6 n'est pas disponible",
"no_restore_script": "Le script de sauvegarde n'a pas été trouvé pour l'application « {app:s} »",
"no_such_conf_file": "Le fichier {file:s} nexiste pas, il ne peut pas être copié",
"not_enough_disk_space": "L'espace disque est insuffisant sur « {path:s} »",
"package_not_installed": "Le paquet « {pkgname} » n'est pas installé",
"package_unexpected_error": "Une erreur inattendue est survenue avec le paquet « {pkgname} »",
"package_unknown": "Paquet « {pkgname} » inconnu",
"packages_no_upgrade": "Il n'y a aucun paquet à mettre à jour",
"packages_upgrade_critical_later": "Les paquets critiques ({packages:s}) seront mis à jour ultérieurement",
"packages_upgrade_failed": "Impossible de mettre à jour tous les paquets",
"path_removal_failed": "Impossible de supprimer le chemin {:s}",
"pattern_backup_archive_name": "Doit être un nom de fichier valide composé de caractères alphanumérique et -_. uniquement",
"pattern_domain": "Doit être un nom de domaine valide (ex : mon-domaine.org)",
"pattern_email": "Doit être une adresse courriel valide (ex. : someone@domain.org)",
"pattern_firstname": "Doit être un prénom valide",
"pattern_lastname": "Doit être un nom valide",
"pattern_listname": "Doit être composé uniquement de caractères alphanumériques et de tirets bas",
"pattern_mailbox_quota": "Doit être une taille avec le suffixe b/k/M/G/T ou 0 pour désactiver le quota",
"pattern_password": "Doit être composé d'au moins 3 caractères",
"pattern_port": "Doit être un numéro de port valide (ex. : 0-65535)",
"pattern_port_or_range": "Doit être un numéro de port valide (ex. : 0-65535) ou une gamme de ports (ex. : 100:200)",
"pattern_positive_number": "Doit être un nombre positif",
"pattern_username": "Doit être composé uniquement de caractères alphanumériques minuscules et de tirets bas",
"port_already_closed": "Le port {port:d} est déjà fermé pour les connexions {ip_version:s}",
"port_already_opened": "Le port {port:d} est déjà ouvert pour les connexions {ip_version:s}",
"port_available": "Le port {port:d} est disponible",
"port_unavailable": "Le port {port:d} n'est pas disponible",
"restore_action_required": "Vous devez préciser ce qui est à restaurer",
"restore_already_installed_app": "Une application est déjà installée avec l'id « {app:s} »",
"restore_app_failed": "Impossible de restaurer l'application « {app:s} »",
"restore_cleaning_failed": "Impossible de nettoyer le dossier temporaire de restauration",
"restore_complete": "Restauration terminée",
"restore_confirm_yunohost_installed": "Voulez-vous vraiment restaurer un système déjà installé ? [{answers:s}]",
"restore_failed": "Impossible de restaurer le système",
"restore_hook_unavailable": "Le script de restauration « {hook:s} » n'est pas disponible sur votre système",
"restore_nothings_done": "Rien n'a été restauré",
"restore_running_app_script": "Lancement du script de restauration pour l'application « {app:s} »...",
"restore_running_hooks": "Exécution des scripts de restauration...",
"service_add_configuration": "Ajout du fichier de configuration {file:s}",
"service_add_failed": "Impossible d'ajouter le service « {service:s} »",
"service_added": "Service « {service:s} » ajouté avec succès",
"service_already_started": "Le service « {service:s} » est déjà démarré",
"service_already_stopped": "Le service « {service:s} » est déjà arrêté",
"service_cmd_exec_failed": "Impossible d'exécuter la commande « {command:s} »",
"service_configuration_conflict": "Le fichier {file:s} a été modifié depuis sa dernière génération. Veuillez y appliquer les modifications manuellement ou utiliser loption --force (ce qui écrasera toutes les modifications effectuées sur le fichier).",
"service_configured": "La configuration du service « {service:s} » a été générée avec succès",
"service_configured_all": "La configuration de tous les services a été générée avec succès",
"service_disable_failed": "Impossible de désactiver le service « {service:s} »",
"service_disabled": "Service « {service:s} » désactivé avec succès",
"service_enable_failed": "Impossible d'activer le service « {service:s} »",
"service_enabled": "Service « {service:s} » activé avec succès",
"service_no_log": "Aucun journal à afficher pour le service « {service:s} »",
"service_remove_failed": "Impossible d'enlever le service « {service:s} »",
"service_removed": "Service « {service:s} » enlevé avec succès",
"service_start_failed": "Impossible de démarrer le service « {service:s} »",
"service_started": "Le service « {service:s} » a démarré avec succès",
"service_status_failed": "Impossible de déterminer le statut du service « {service:s} »",
"service_stop_failed": "Impossible d'arrêter le service « {service:s} »",
"service_stopped": "Service « {service:s} » arrêté avec succès",
"service_unknown": "Service « {service:s} » inconnu",
"services_configured": "La configuration a été générée avec succès",
"show_diff": "Voici les différences :\n{diff:s}",
"ssowat_conf_generated": "Configuration de SSOwat générée avec succès",
"ssowat_conf_updated": "La configuration persistante de SSOwat a été mise à jour avec succès",
"system_upgraded": "Système mis à jour avec succès",
"system_username_exists": "Le nom d'utilisateur existe déjà dans les utilisateurs système",
"unbackup_app": "L'application « {app:s} » ne sera pas sauvegardée",
"unexpected_error": "Une erreur inattendue est survenue",
"unit_unknown": "Unité « {unit:s} » inconnue",
"unlimit": "Pas de quota",
"unrestore_app": "L'application « {app:s} » ne sera pas restaurée",
"update_cache_failed": "Impossible de mettre à jour le cache de l'APT",
"updating_apt_cache": "Mise à jour de la liste des paquets disponibles...",
"upgrade_complete": "Mise à jour terminée",
"upgrading_packages": "Mise à jour des paquets...",
"upnp_dev_not_found": "Aucun périphérique compatible UPnP n'a été trouvé",
"upnp_disabled": "UPnP désactivé avec succès",
"upnp_enabled": "UPnP activé avec succès",
"upnp_port_open_failed": "Impossible d'ouvrir les ports avec UPnP",
"user_created": "Utilisateur créé avec succès",
"user_creation_failed": "Impossible de créer l'utilisateur",
"user_deleted": "Utilisateur supprimé avec succès",
"user_deletion_failed": "Impossible de supprimer l'utilisateur",
"user_home_creation_failed": "Impossible de créer le dossier personnel de l'utilisateur",
"user_info_failed": "Impossible de récupérer les informations de l'utilisateur",
"user_unknown": "Utilisateur « {user:s} » inconnu",
"user_update_failed": "Impossible de modifier l'utilisateur",
"user_updated": "Utilisateur modifié avec succès",
"yunohost_already_installed": "YunoHost est déjà installé",
"yunohost_ca_creation_failed": "Impossible de créer l'autorité de certification",
"yunohost_configured": "YunoHost configuré avec succès",
"yunohost_installing": "Installation de YunoHost...",
"yunohost_not_installed": "YunoHost n'est pas ou pas correctement installé. Veuillez exécuter « yunohost tools postinstall »."
}
}

View file

@ -1,31 +1,31 @@
{
"app_already_installed": "{:s} è già installato",
"app_extraction_failed": "Impossibile estrarre i file di installazione",
"app_not_installed": "{:s} non è installato",
"app_unknown": "Applicazione sconosciuta",
"ask_email": "Indirizzo email",
"ask_password": "Password",
"backup_archive_name_exists": "Il nome dell'archivio del backup esiste già",
"backup_complete": "Backup completo",
"backup_invalid_archive": "Archivio di backup non valido",
"backup_output_directory_not_empty": "Directory di output non è vuota",
"backup_running_app_script": "Esecuzione script di backup dell'applicazione '{:s}'...",
"domain_created": "Dominio creato con successo",
"domain_dyndns_invalid": "Dominio non valido da utilizzare con DynDNS",
"domain_exists": "Dominio esiste già",
"ldap_initialized": "LDAP inizializzato con successo",
"pattern_email": "Deve essere un indirizzo e-mail valido (es someone@domain.org)",
"pattern_mailbox_quota": "Deve essere una dimensione con un suffisso b/k/M/G/T o 0 per disabilitare la quota",
"port_already_opened": "Port {} è già aperto per {:s} connessioni",
"port_unavailable": "Porta {} non è disponibile",
"service_add_failed": "Impossibile aggiungere servizio '{:s}'",
"service_cmd_exec_failed": "Impossibile eseguire il comando '{:s}'",
"service_disabled": "Servizio '{:s}' disattivato con successo",
"service_remove_failed": "Impossibile rimuovere il servizio '{:s}'",
"service_removed": "Servizio rimosso con successo",
"service_stop_failed": "Impossibile arrestare il servizio '{:s}'",
"system_username_exists": "Nome utente esiste già negli utenti del sistema",
"unrestore_app": "Applicazione '{app:s}' non verrà ripristinato",
"upgrading_packages": "Aggiornamento dei pacchetti...",
"app_already_installed": "{app:s} è già installato",
"app_extraction_failed": "Impossibile estrarre i file di installazione",
"app_not_installed": "{app:s} non è installato",
"app_unknown": "Applicazione sconosciuta",
"ask_email": "Indirizzo email",
"ask_password": "Password",
"backup_archive_name_exists": "Il nome dell'archivio del backup esiste già",
"backup_complete": "Backup completo",
"backup_invalid_archive": "Archivio di backup non valido",
"backup_output_directory_not_empty": "Directory di output non è vuota",
"backup_running_app_script": "Esecuzione script di backup dell'applicazione '{app:s}'...",
"domain_created": "Dominio creato con successo",
"domain_dyndns_invalid": "Dominio non valido da utilizzare con DynDNS",
"domain_exists": "Dominio esiste già",
"ldap_initialized": "LDAP inizializzato con successo",
"pattern_email": "Deve essere un indirizzo e-mail valido (es someone@domain.org)",
"pattern_mailbox_quota": "Deve essere una dimensione con un suffisso b/k/M/G/T o 0 per disabilitare la quota",
"port_already_opened": "Port {port:d} è già aperto per {ip_version:s} connessioni",
"port_unavailable": "Porta {port:d} non è disponibile",
"service_add_failed": "Impossibile aggiungere servizio '{service:s}'",
"service_cmd_exec_failed": "Impossibile eseguire il comando '{command:s}'",
"service_disabled": "Servizio '{service:s}' disattivato con successo",
"service_remove_failed": "Impossibile rimuovere il servizio '{service:s}'",
"service_removed": "Servizio rimosso con successo",
"service_stop_failed": "Impossibile arrestare il servizio '{service:s}'",
"system_username_exists": "Nome utente esiste già negli utenti del sistema",
"unrestore_app": "Applicazione '{app:s}' non verrà ripristinato",
"upgrading_packages": "Aggiornamento dei pacchetti...",
"user_deleted": "Utente cancellato con successo"
}
}

View file

@ -1,109 +1,109 @@
{
"action_invalid": "Ongeldige actie '{:s}'",
"admin_password": "Administration password",
"admin_password_changed": "Het admin-wachtwoord is gewijzigd",
"app_already_installed": "{:s} is al geïnstalleerd",
"app_argument_invalid": "'{name:s}' bevat geldige waarde: {error:s}",
"app_argument_required": "Het '{name:s}' moet ingevuld worden",
"app_extraction_failed": "Kan installatiebestanden niet uitpakken",
"app_id_invalid": "Ongeldige app-id",
"app_install_files_invalid": "Ongeldige installatiebestanden",
"app_location_already_used": "Er is al een app geïnstalleerd op deze locatie",
"app_location_install_failed": "Kan app niet installeren op deze locatie",
"app_manifest_invalid": "Ongeldig app-manifest",
"app_no_upgrade": "Geen apps op te upgraden",
"app_not_installed": "{:s} is niet geinstalleerd ",
"app_recent_version_required": "{:s} vereist een nieuwere versie van moulinette",
"app_removed": "{:s} succesvol verwijderd",
"app_sources_fetch_failed": "Kan bronbestanden niet ophalen",
"app_unknown": "Onbekende app",
"app_upgrade_failed": "Kan niet alle apps updaten",
"app_upgraded": "{:s} succesvol geüpgrade ",
"appslist_fetched": "App-lijst succesvol aangemaakt.",
"appslist_removed": "App-lijst succesvol verwijderd",
"appslist_unknown": "Onbekende app-lijst",
"ask_current_admin_password": "Huidig administratorwachtwoord",
"ask_email": "Email-adres",
"ask_firstname": "Voornaam",
"ask_lastname": "Achternaam",
"ask_new_admin_password": "Nieuw administratorwachtwoord",
"ask_password": "Wachtwoord",
"backup_archive_name_exists": "Backuparchief bestaat al",
"backup_cleaning_failed": "Kan tijdelijke backup directory niet leeg maken",
"backup_creating_archive": "Backup wordt gestart...",
"backup_invalid_archive": "Ongeldig backup archief",
"backup_output_directory_not_empty": "Doelmap is niet leeg",
"backup_running_app_script": "Backup script voor app '{app:s}' is gestart...",
"custom_app_url_required": "U moet een URL opgeven om uw aangepaste app {:s} bij te werken",
"custom_appslist_name_required": "U moet een naam opgeven voor uw aangepaste app-lijst",
"dnsmasq_isnt_installed": "dnsmasq lijkt niet geïnstalleerd te zijn, voer alstublieft het volgende commando uit: 'apt-get remove bind9 && apt-get install dnsmasq'",
"domain_cert_gen_failed": "Kan certificaat niet genereren",
"domain_created": "Domein succesvol aangemaakt",
"domain_creation_failed": "Kan domein niet aanmaken",
"domain_deleted": "Domein succesvol verwijderd",
"domain_deletion_failed": "Kan domein niet verwijderen",
"domain_dyndns_already_subscribed": "Dit domein is al geregistreed bij DynDNS",
"domain_dyndns_invalid": "Het domein is ongeldig voor DynDNS",
"domain_dyndns_root_unknown": "Onbekend DynDNS root domein",
"domain_exists": "Domein bestaat al",
"domain_uninstall_app_first": "Een of meerdere apps zijn geïnstalleerd op dit domein, verwijder deze voordat u het domein verwijderd.",
"domain_unknown": "Onbekend domein",
"domain_zone_exists": "DNS zone bestand bestaat al",
"domain_zone_not_found": "DNS zone bestand niet gevonden voor domein: {:s}",
"done": "Voltooid.",
"downloading": "Downloaden...",
"dyndns_cron_remove_failed": "De cron-job voor DynDNS kon niet worden verwijderd",
"dyndns_ip_update_failed": "Kan het IP adres niet updaten bij DynDNS",
"dyndns_ip_updated": "IP adres is aangepast bij DynDNS",
"dyndns_key_generating": "DNS sleutel word aangemaakt, wacht een moment...",
"dyndns_unavailable": "DynDNS subdomein is niet beschikbaar",
"executing_script": "Script uitvoeren...",
"extracting": "Uitpakken...",
"installation_complete": "Installatie voltooid",
"installation_failed": "Installatie gefaald",
"ldap_initialized": "LDAP staat klaar voor gebruik",
"license_undefined": "undefined",
"mail_alias_remove_failed": "Kan mail alias niet verwijderen '{:s}'",
"monitor_stats_no_update": "Er zijn geen recente monitoringstatistieken bij te werken",
"mysql_db_creation_failed": "Aanmaken MySQL database gefaald",
"mysql_db_init_failed": "Initialiseren MySQL database gefaald",
"mysql_db_initialized": "MySQL database succesvol geïnitialiseerd",
"network_check_smtp_ko": "Uitgaande mail (SMPT port 25) wordt blijkbaar geblokkeerd door uw het netwerk",
"no_appslist_found": "Geen app-lijsten gevonden",
"no_internet_connection": "Server is niet verbonden met het internet",
"no_ipv6_connectivity": "IPv6-stack is onbeschikbaar",
"path_removal_failed": "Kan pad niet verwijderen {:s}",
"pattern_email": "Moet een geldig emailadres bevatten (bv. abc@example.org)",
"pattern_listname": "Slechts cijfers, letters en '_' zijn toegelaten",
"pattern_mailbox_quota": "Mailbox quota moet een waarde bevatten met b/k/M/G/T erachter of 0 om geen quota in te stellen",
"pattern_password": "Wachtwoord moet tenminste 3 karakters lang zijn",
"port_already_closed": "Poort {} is al gesloten voor {:s} verbindingen",
"port_already_opened": "Poort {} is al open voor {:s} verbindingen",
"port_available": "Poort {} is beschikbaar",
"port_unavailable": "Poort {} is niet beschikbaar",
"restore_app_failed": "De app '{app:s}' kon niet worden terug gezet",
"restore_hook_unavailable": "De restauration hook '{hook:s}' is niet beschikbaar op dit systeem",
"service_add_failed": "Kan service '{:s}' niet toevoegen",
"service_already_started": "Service '{:s}' draait al",
"service_cmd_exec_failed": "Kan '{:s}' niet uitvoeren",
"service_disabled": "Service '{:s}' is uitgeschakeld",
"service_remove_failed": "Kan service '{:s}' niet verwijderen",
"service_removed": "Service werd verwijderd",
"service_stop_failed": "Kan service '{:s}' niet stoppen",
"service_unknown": "De service '{:s}' bestaat niet",
"show_diff": "Let op de volgende verschillen zijn:\n{diff:s}",
"unexpected_error": "Er is een onbekende fout opgetreden",
"unrestore_app": "App '{app:s}' wordt niet teruggezet",
"updating_apt_cache": "Lijst van beschikbare pakketen wordt bijgewerkt",
"upgrade_complete": "Upgrade voltooid",
"upgrading_packages": "Pakketten worden geüpdate...",
"upnp_dev_not_found": "Geen UPnP apparaten gevonden",
"upnp_disabled": "UPnP successvol uitgeschakeld",
"upnp_enabled": "UPnP succesvol ingeschakeld",
"upnp_port_open_failed": "Kan UPnP poorten niet openen",
"user_deleted": "Gebruiker werd verwijderd",
"user_home_creation_failed": "Kan de map voor deze gebruiker niet aanmaken",
"user_unknown": "Gebruikersnaam is onbekend",
"user_update_failed": "Kan gebruiker niet bijwerken",
"action_invalid": "Ongeldige actie '{action:s}'",
"admin_password": "Administration password",
"admin_password_changed": "Het admin-wachtwoord is gewijzigd",
"app_already_installed": "{app:s} is al geïnstalleerd",
"app_argument_invalid": "'{name:s}' bevat geldige waarde: {error:s}",
"app_argument_required": "Het '{name:s}' moet ingevuld worden",
"app_extraction_failed": "Kan installatiebestanden niet uitpakken",
"app_id_invalid": "Ongeldige app-id",
"app_install_files_invalid": "Ongeldige installatiebestanden",
"app_location_already_used": "Er is al een app geïnstalleerd op deze locatie",
"app_location_install_failed": "Kan app niet installeren op deze locatie",
"app_manifest_invalid": "Ongeldig app-manifest",
"app_no_upgrade": "Geen apps op te upgraden",
"app_not_installed": "{app:s} is niet geinstalleerd",
"app_recent_version_required": "{:s} vereist een nieuwere versie van moulinette",
"app_removed": "{app:s} succesvol verwijderd",
"app_sources_fetch_failed": "Kan bronbestanden niet ophalen",
"app_unknown": "Onbekende app",
"app_upgrade_failed": "Kan niet alle apps updaten",
"app_upgraded": "{app:s} succesvol geüpgrade",
"appslist_fetched": "App-lijst succesvol aangemaakt.",
"appslist_removed": "App-lijst succesvol verwijderd",
"appslist_unknown": "Onbekende app-lijst",
"ask_current_admin_password": "Huidig administratorwachtwoord",
"ask_email": "Email-adres",
"ask_firstname": "Voornaam",
"ask_lastname": "Achternaam",
"ask_new_admin_password": "Nieuw administratorwachtwoord",
"ask_password": "Wachtwoord",
"backup_archive_name_exists": "Backuparchief bestaat al",
"backup_cleaning_failed": "Kan tijdelijke backup directory niet leeg maken",
"backup_creating_archive": "Backup wordt gestart...",
"backup_invalid_archive": "Ongeldig backup archief",
"backup_output_directory_not_empty": "Doelmap is niet leeg",
"backup_running_app_script": "Backup script voor app '{app:s}' is gestart...",
"custom_app_url_required": "U moet een URL opgeven om uw aangepaste app {app:s} bij te werken",
"custom_appslist_name_required": "U moet een naam opgeven voor uw aangepaste app-lijst",
"dnsmasq_isnt_installed": "dnsmasq lijkt niet geïnstalleerd te zijn, voer alstublieft het volgende commando uit: 'apt-get remove bind9 && apt-get install dnsmasq'",
"domain_cert_gen_failed": "Kan certificaat niet genereren",
"domain_created": "Domein succesvol aangemaakt",
"domain_creation_failed": "Kan domein niet aanmaken",
"domain_deleted": "Domein succesvol verwijderd",
"domain_deletion_failed": "Kan domein niet verwijderen",
"domain_dyndns_already_subscribed": "Dit domein is al geregistreed bij DynDNS",
"domain_dyndns_invalid": "Het domein is ongeldig voor DynDNS",
"domain_dyndns_root_unknown": "Onbekend DynDNS root domein",
"domain_exists": "Domein bestaat al",
"domain_uninstall_app_first": "Een of meerdere apps zijn geïnstalleerd op dit domein, verwijder deze voordat u het domein verwijderd.",
"domain_unknown": "Onbekend domein",
"domain_zone_exists": "DNS zone bestand bestaat al",
"domain_zone_not_found": "DNS zone bestand niet gevonden voor domein: {:s}",
"done": "Voltooid.",
"downloading": "Downloaden...",
"dyndns_cron_remove_failed": "De cron-job voor DynDNS kon niet worden verwijderd",
"dyndns_ip_update_failed": "Kan het IP adres niet updaten bij DynDNS",
"dyndns_ip_updated": "IP adres is aangepast bij DynDNS",
"dyndns_key_generating": "DNS sleutel word aangemaakt, wacht een moment...",
"dyndns_unavailable": "DynDNS subdomein is niet beschikbaar",
"executing_script": "Script uitvoeren...",
"extracting": "Uitpakken...",
"installation_complete": "Installatie voltooid",
"installation_failed": "Installatie gefaald",
"ldap_initialized": "LDAP staat klaar voor gebruik",
"license_undefined": "undefined",
"mail_alias_remove_failed": "Kan mail alias niet verwijderen '{mail:s}'",
"monitor_stats_no_update": "Er zijn geen recente monitoringstatistieken bij te werken",
"mysql_db_creation_failed": "Aanmaken MySQL database gefaald",
"mysql_db_init_failed": "Initialiseren MySQL database gefaald",
"mysql_db_initialized": "MySQL database succesvol geïnitialiseerd",
"network_check_smtp_ko": "Uitgaande mail (SMPT port 25) wordt blijkbaar geblokkeerd door uw het netwerk",
"no_appslist_found": "Geen app-lijsten gevonden",
"no_internet_connection": "Server is niet verbonden met het internet",
"no_ipv6_connectivity": "IPv6-stack is onbeschikbaar",
"path_removal_failed": "Kan pad niet verwijderen {:s}",
"pattern_email": "Moet een geldig emailadres bevatten (bv. abc@example.org)",
"pattern_listname": "Slechts cijfers, letters en '_' zijn toegelaten",
"pattern_mailbox_quota": "Mailbox quota moet een waarde bevatten met b/k/M/G/T erachter of 0 om geen quota in te stellen",
"pattern_password": "Wachtwoord moet tenminste 3 karakters lang zijn",
"port_already_closed": "Poort {port:d} is al gesloten voor {ip_version:s} verbindingen",
"port_already_opened": "Poort {port:d} is al open voor {ip_version:s} verbindingen",
"port_available": "Poort {port:d} is beschikbaar",
"port_unavailable": "Poort {port:d} is niet beschikbaar",
"restore_app_failed": "De app '{app:s}' kon niet worden terug gezet",
"restore_hook_unavailable": "De restauration hook '{hook:s}' is niet beschikbaar op dit systeem",
"service_add_failed": "Kan service '{service:s}' niet toevoegen",
"service_already_started": "Service '{service:s}' draait al",
"service_cmd_exec_failed": "Kan '{command:s}' niet uitvoeren",
"service_disabled": "Service '{service:s}' is uitgeschakeld",
"service_remove_failed": "Kan service '{service:s}' niet verwijderen",
"service_removed": "Service werd verwijderd",
"service_stop_failed": "Kan service '{service:s}' niet stoppen",
"service_unknown": "De service '{service:s}' bestaat niet",
"show_diff": "Let op de volgende verschillen zijn:\n{diff:s}",
"unexpected_error": "Er is een onbekende fout opgetreden",
"unrestore_app": "App '{app:s}' wordt niet teruggezet",
"updating_apt_cache": "Lijst van beschikbare pakketen wordt bijgewerkt",
"upgrade_complete": "Upgrade voltooid",
"upgrading_packages": "Pakketten worden geüpdate...",
"upnp_dev_not_found": "Geen UPnP apparaten gevonden",
"upnp_disabled": "UPnP successvol uitgeschakeld",
"upnp_enabled": "UPnP succesvol ingeschakeld",
"upnp_port_open_failed": "Kan UPnP poorten niet openen",
"user_deleted": "Gebruiker werd verwijderd",
"user_home_creation_failed": "Kan de map voor deze gebruiker niet aanmaken",
"user_unknown": "Gebruikersnaam is onbekend",
"user_update_failed": "Kan gebruiker niet bijwerken",
"yunohost_configured": "YunoHost configuratie is OK"
}
}

View file

@ -1,148 +1,148 @@
{
"action_invalid": "Acção Inválida '{:s}'",
"admin_password": "Senha de administração",
"admin_password_change_failed": "Não foi possível alterar a senha",
"admin_password_changed": "Senha de administração alterada com êxito",
"app_already_installed": "{:s} já está instalada",
"app_extraction_failed": "Não foi possível extrair os ficheiros para instalação",
"app_id_invalid": "ID da aplicação invélida",
"app_install_files_invalid": "Ficheiros para instalação corrompidos",
"app_location_already_used": "Já existe uma aplicação instalada neste diretório",
"app_location_install_failed": "Não foi possível instalar a aplicação neste diretório",
"app_manifest_invalid": "Manifesto da aplicação inválido",
"app_no_upgrade": "Não existem aplicações para atualizar",
"app_not_installed": "{:s} não está instalada",
"app_recent_version_required": "{:s} requer uma versão mais recente da moulinette",
"app_removed": "{:s} removida com êxito",
"app_sources_fetch_failed": "Impossível obter os códigos fontes",
"app_unknown": "Aplicação desconhecida",
"app_upgrade_failed": "Unable to upgrade all apps",
"app_upgraded": "{:s} atualizada com êxito",
"appslist_fetched": "Lista de aplicações processada com êxito",
"appslist_removed": "Lista de aplicações removida com êxito",
"appslist_retrieve_error": "Não foi possível obter a lista de aplicações remotas",
"appslist_unknown": "Lista de aplicaçoes desconhecida",
"ask_current_admin_password": "Senha de administração atual",
"ask_email": "Correio eletrónico",
"ask_firstname": "Primeiro nome",
"ask_lastname": "Último nome",
"ask_list_to_remove": "Lista para remover",
"ask_main_domain": "Domínio principal",
"ask_new_admin_password": "Senha de administração nova",
"ask_password": "Senha",
"backup_complete": "Backup completo",
"backup_creating_archive": "A criar ficheiro de backup...",
"backup_invalid_archive": "Arquivo de backup inválido",
"backup_output_directory_not_empty": "A pasta de destino não se encontra vazia",
"custom_app_url_required": "Deve proporcionar uma URL para atualizar a sua aplicação personalizada {:s}",
"custom_appslist_name_required": "Deve fornecer um nome para a sua lista de aplicações personalizada",
"domain_cert_gen_failed": "Não foi possível gerar o certificado",
"domain_created": "Domínio criado com êxito",
"domain_creation_failed": "Não foi possível criar o domínio",
"domain_deleted": "Domínio removido com êxito",
"domain_deletion_failed": "Não foi possível eliminar o domínio",
"domain_dyndns_already_subscribed": "Já subscreveu um domínio DynDNS",
"domain_dyndns_invalid": "Domínio inválido para ser utilizado com DynDNS",
"domain_dyndns_root_unknown": "Domínio root (administrador) DynDNS desconhecido",
"domain_exists": "O domínio já existe",
"domain_uninstall_app_first": "Existem uma ou mais aplicações instaladas neste domínio. Por favor desinstale-as antes de proceder com a remoção do domínio.",
"domain_unknown": "Domínio desconhecido",
"domain_zone_exists": "Ficheiro para zona DMZ já existe",
"domain_zone_not_found": "Ficheiro para zona DMZ não encontrado no domínio {:s}",
"done": "Concluído.",
"downloading": "Transferência em curso...",
"dyndns_cron_installed": "Gestor de tarefas cron DynDNS instalado com êxito",
"dyndns_cron_remove_failed": "Não foi possível remover o gestor de tarefas cron DynDNS",
"dyndns_cron_removed": "Gestor de tarefas cron DynDNS removido com êxito",
"dyndns_ip_update_failed": "Não foi possível atualizar o endereço IP a partir de DynDNS",
"dyndns_ip_updated": "Endereço IP atualizado com êxito a partir de DynDNS",
"dyndns_key_generating": "A chave DNS está a ser gerada, isto pode demorar um pouco...",
"dyndns_registered": "Dom+inio DynDNS registado com êxito",
"dyndns_registration_failed": "Não foi possível registar o domínio DynDNS: {:s}",
"dyndns_unavailable": "Subdomínio DynDNS indisponível",
"executing_script": "A executar o script...",
"extracting": "Extração em curso...",
"field_invalid": "Campo inválido '{:s}'",
"firewall_reloaded": "Firewall recarregada com êxito",
"hook_argument_missing": "Argumento em falta '{:s}'",
"hook_choice_invalid": "Escolha inválida '{:s}'",
"installation_complete": "Instalação concluída",
"installation_failed": "A instalação falhou",
"iptables_unavailable": "Não pode alterar aqui a iptables. Ou o seu kernel não o suporta ou está num espaço reservado.",
"ldap_initialized": "LDAP inicializada com êxito",
"license_undefined": "indefinido",
"mail_alias_remove_failed": "Não foi possível remover a etiqueta de correio '{:s}'",
"mail_domain_unknown": "Domínio de endereço de correio desconhecido '{:s}'",
"mail_forward_remove_failed": "Não foi possível remover o reencaminhamento de correio '{:s}'",
"maindomain_change_failed": "Incapaz alterar o domínio raiz",
"maindomain_changed": "Domínio raiz alterado com êxito",
"monitor_disabled": "Monitorização do servidor parada com êxito",
"monitor_enabled": "Monitorização do servidor ativada com êxito",
"monitor_glances_con_failed": "Não foi possível ligar ao servidor Glances",
"monitor_not_enabled": "A monitorização do servidor não está ativa",
"monitor_period_invalid": "Período de tempo inválido",
"monitor_stats_file_not_found": "Ficheiro de estatísticas não encontrado",
"monitor_stats_no_update": "Não existem estatísticas de monitorização para atualizar",
"monitor_stats_period_unavailable": "Não existem estatísticas disponíveis para este período",
"mountpoint_unknown": "Ponto de montagem desconhecido",
"mysql_db_creation_failed": "Criação da base de dados MySQL falhou",
"mysql_db_init_failed": "Inicialização da base de dados MySQL falhou",
"mysql_db_initialized": "Base de dados MySQL iniciada com êxito",
"new_domain_required": "Deve escrever um novo domínio principal",
"no_appslist_found": "Não foi encontrada a lista de aplicações",
"no_internet_connection": "O servidor não está ligado à Internet",
"packages_no_upgrade": "Não existem pacotes para atualizar",
"packages_upgrade_critical_later": "Os pacotes críticos ({:s}) serão atualizados depois",
"packages_upgrade_failed": "Não foi possível atualizar todos os pacotes",
"path_removal_failed": "Incapaz remover o caminho {:s}",
"pattern_domain": "Deve ser um nome de domínio válido (p.e. meu-dominio.org)",
"pattern_email": "Deve ser um endereço de correio válido (p.e. alguem@dominio.org)",
"pattern_firstname": "Deve ser um primeiro nome válido",
"pattern_lastname": "Deve ser um último nome válido",
"pattern_listname": "Apenas são permitidos caracteres alfanuméricos e travessões",
"pattern_password": "Deve ter no mínimo 3 caracteres",
"pattern_port": "Deve ser um número de porta válido (entre 0-65535)",
"pattern_username": "Must be lower-case alphanumeric and underscore characters only",
"restore_confirm_yunohost_installed": "Quer mesmo restaurar um sistema já instalado? [{answers:s}]",
"service_add_failed": "Incapaz adicionar serviço '{:s}'",
"service_added": "Serviço adicionado com êxito",
"service_already_started": "O serviço '{:s}' já está em execussão",
"service_already_stopped": "O serviço '{:s}' já está parado",
"service_cmd_exec_failed": "Incapaz executar o comando '{:s}'",
"service_disable_failed": "Incapaz desativar o serviço '{:s}'",
"service_disabled": "O serviço '{:s}' foi desativado com êxito",
"service_enable_failed": "Incapaz de ativar o serviço '{:s}'",
"service_enabled": "Serviço '{:s}' ativado com êxito",
"service_no_log": "Não existem registos para mostrar do serviço '{:s}'",
"service_remove_failed": "Incapaz de remover o serviço '{:s}'",
"service_removed": "Serviço eliminado com êxito",
"service_start_failed": "Não foi possível iniciar o serviço '{:s}'",
"service_started": "O serviço '{:s} foi iniciado com êxito",
"service_status_failed": "Incapaz determinar o estado do serviço '{:s}'",
"service_stop_failed": "Incapaz parar o serviço '{:s}",
"service_stopped": "O serviço '{:s}' foi parado com êxito",
"service_unknown": "Serviço desconhecido '{:s}'",
"ssowat_conf_generated": "Configuração SSOwat gerada com êxito",
"ssowat_conf_updated": "Configuração persistente SSOwat atualizada com êxito",
"system_upgraded": "Sistema atualizado com êxito",
"system_username_exists": "O utilizador já existe no registo do sistema",
"unexpected_error": "Ocorreu um erro inesperado",
"unit_unknown": "Unidade desconhecida '{:s}'",
"update_cache_failed": "Não foi possível atualizar os cabeçalhos APT",
"updating_apt_cache": "A atualizar a lista de pacotes disponíveis...",
"upgrade_complete": "Atualização completa",
"upgrading_packages": "Atualização de pacotes em curso...",
"user_created": "Utilizador criado com êxito",
"user_creation_failed": "Não foi possível criar o utilizador",
"user_deleted": "Utilizador eliminado com êxito",
"user_deletion_failed": "Incapaz eliminar o utilizador",
"user_info_failed": "Incapaz obter informações sobre o utilizador",
"user_unknown": "Utilizador desconhecido",
"user_update_failed": "Não foi possível atualizar o utilizador",
"user_updated": "Utilizador atualizado com êxito",
"yunohost_already_installed": "AYunoHost já está instalado",
"yunohost_ca_creation_failed": "Incapaz criar o certificado de autoridade",
"yunohost_configured": "YunoHost configurada com êxito",
"yunohost_installing": "A instalar a YunoHost...",
"action_invalid": "Acção Inválida '{action:s}'",
"admin_password": "Senha de administração",
"admin_password_change_failed": "Não foi possível alterar a senha",
"admin_password_changed": "Senha de administração alterada com êxito",
"app_already_installed": "{app:s} já está instalada",
"app_extraction_failed": "Não foi possível extrair os ficheiros para instalação",
"app_id_invalid": "ID da aplicação invélida",
"app_install_files_invalid": "Ficheiros para instalação corrompidos",
"app_location_already_used": "Já existe uma aplicação instalada neste diretório",
"app_location_install_failed": "Não foi possível instalar a aplicação neste diretório",
"app_manifest_invalid": "Manifesto da aplicação inválido",
"app_no_upgrade": "Não existem aplicações para atualizar",
"app_not_installed": "{app:s} não está instalada",
"app_recent_version_required": "{:s} requer uma versão mais recente da moulinette",
"app_removed": "{app:s} removida com êxito",
"app_sources_fetch_failed": "Impossível obter os códigos fontes",
"app_unknown": "Aplicação desconhecida",
"app_upgrade_failed": "Unable to upgrade all apps",
"app_upgraded": "{app:s} atualizada com êxito",
"appslist_fetched": "Lista de aplicações processada com êxito",
"appslist_removed": "Lista de aplicações removida com êxito",
"appslist_retrieve_error": "Não foi possível obter a lista de aplicações remotas",
"appslist_unknown": "Lista de aplicaçoes desconhecida",
"ask_current_admin_password": "Senha de administração atual",
"ask_email": "Correio eletrónico",
"ask_firstname": "Primeiro nome",
"ask_lastname": "Último nome",
"ask_list_to_remove": "Lista para remover",
"ask_main_domain": "Domínio principal",
"ask_new_admin_password": "Senha de administração nova",
"ask_password": "Senha",
"backup_complete": "Backup completo",
"backup_creating_archive": "A criar ficheiro de backup...",
"backup_invalid_archive": "Arquivo de backup inválido",
"backup_output_directory_not_empty": "A pasta de destino não se encontra vazia",
"custom_app_url_required": "Deve proporcionar uma URL para atualizar a sua aplicação personalizada {app:s}",
"custom_appslist_name_required": "Deve fornecer um nome para a sua lista de aplicações personalizada",
"domain_cert_gen_failed": "Não foi possível gerar o certificado",
"domain_created": "Domínio criado com êxito",
"domain_creation_failed": "Não foi possível criar o domínio",
"domain_deleted": "Domínio removido com êxito",
"domain_deletion_failed": "Não foi possível eliminar o domínio",
"domain_dyndns_already_subscribed": "Já subscreveu um domínio DynDNS",
"domain_dyndns_invalid": "Domínio inválido para ser utilizado com DynDNS",
"domain_dyndns_root_unknown": "Domínio root (administrador) DynDNS desconhecido",
"domain_exists": "O domínio já existe",
"domain_uninstall_app_first": "Existem uma ou mais aplicações instaladas neste domínio. Por favor desinstale-as antes de proceder com a remoção do domínio.",
"domain_unknown": "Domínio desconhecido",
"domain_zone_exists": "Ficheiro para zona DMZ já existe",
"domain_zone_not_found": "Ficheiro para zona DMZ não encontrado no domínio {:s}",
"done": "Concluído.",
"downloading": "Transferência em curso...",
"dyndns_cron_installed": "Gestor de tarefas cron DynDNS instalado com êxito",
"dyndns_cron_remove_failed": "Não foi possível remover o gestor de tarefas cron DynDNS",
"dyndns_cron_removed": "Gestor de tarefas cron DynDNS removido com êxito",
"dyndns_ip_update_failed": "Não foi possível atualizar o endereço IP a partir de DynDNS",
"dyndns_ip_updated": "Endereço IP atualizado com êxito a partir de DynDNS",
"dyndns_key_generating": "A chave DNS está a ser gerada, isto pode demorar um pouco...",
"dyndns_registered": "Dom+inio DynDNS registado com êxito",
"dyndns_registration_failed": "Não foi possível registar o domínio DynDNS: {error:s}",
"dyndns_unavailable": "Subdomínio DynDNS indisponível",
"executing_script": "A executar o script...",
"extracting": "Extração em curso...",
"field_invalid": "Campo inválido '{:s}'",
"firewall_reloaded": "Firewall recarregada com êxito",
"hook_argument_missing": "Argumento em falta '{:s}'",
"hook_choice_invalid": "Escolha inválida '{:s}'",
"installation_complete": "Instalação concluída",
"installation_failed": "A instalação falhou",
"iptables_unavailable": "Não pode alterar aqui a iptables. Ou o seu kernel não o suporta ou está num espaço reservado.",
"ldap_initialized": "LDAP inicializada com êxito",
"license_undefined": "indefinido",
"mail_alias_remove_failed": "Não foi possível remover a etiqueta de correio '{mail:s}'",
"mail_domain_unknown": "Domínio de endereço de correio desconhecido '{domain:s}'",
"mail_forward_remove_failed": "Não foi possível remover o reencaminhamento de correio '{mail:s}'",
"maindomain_change_failed": "Incapaz alterar o domínio raiz",
"maindomain_changed": "Domínio raiz alterado com êxito",
"monitor_disabled": "Monitorização do servidor parada com êxito",
"monitor_enabled": "Monitorização do servidor ativada com êxito",
"monitor_glances_con_failed": "Não foi possível ligar ao servidor Glances",
"monitor_not_enabled": "A monitorização do servidor não está ativa",
"monitor_period_invalid": "Período de tempo inválido",
"monitor_stats_file_not_found": "Ficheiro de estatísticas não encontrado",
"monitor_stats_no_update": "Não existem estatísticas de monitorização para atualizar",
"monitor_stats_period_unavailable": "Não existem estatísticas disponíveis para este período",
"mountpoint_unknown": "Ponto de montagem desconhecido",
"mysql_db_creation_failed": "Criação da base de dados MySQL falhou",
"mysql_db_init_failed": "Inicialização da base de dados MySQL falhou",
"mysql_db_initialized": "Base de dados MySQL iniciada com êxito",
"new_domain_required": "Deve escrever um novo domínio principal",
"no_appslist_found": "Não foi encontrada a lista de aplicações",
"no_internet_connection": "O servidor não está ligado à Internet",
"packages_no_upgrade": "Não existem pacotes para atualizar",
"packages_upgrade_critical_later": "Os pacotes críticos ({packages:s}) serão atualizados depois",
"packages_upgrade_failed": "Não foi possível atualizar todos os pacotes",
"path_removal_failed": "Incapaz remover o caminho {:s}",
"pattern_domain": "Deve ser um nome de domínio válido (p.e. meu-dominio.org)",
"pattern_email": "Deve ser um endereço de correio válido (p.e. alguem@dominio.org)",
"pattern_firstname": "Deve ser um primeiro nome válido",
"pattern_lastname": "Deve ser um último nome válido",
"pattern_listname": "Apenas são permitidos caracteres alfanuméricos e travessões",
"pattern_password": "Deve ter no mínimo 3 caracteres",
"pattern_port": "Deve ser um número de porta válido (entre 0-65535)",
"pattern_username": "Must be lower-case alphanumeric and underscore characters only",
"restore_confirm_yunohost_installed": "Quer mesmo restaurar um sistema já instalado? [{answers:s}]",
"service_add_failed": "Incapaz adicionar serviço '{service:s}'",
"service_added": "Serviço adicionado com êxito",
"service_already_started": "O serviço '{service:s}' já está em execussão",
"service_already_stopped": "O serviço '{service:s}' já está parado",
"service_cmd_exec_failed": "Incapaz executar o comando '{command:s}'",
"service_disable_failed": "Incapaz desativar o serviço '{service:s}'",
"service_disabled": "O serviço '{service:s}' foi desativado com êxito",
"service_enable_failed": "Incapaz de ativar o serviço '{service:s}'",
"service_enabled": "Serviço '{service:s}' ativado com êxito",
"service_no_log": "Não existem registos para mostrar do serviço '{service:s}'",
"service_remove_failed": "Incapaz de remover o serviço '{service:s}'",
"service_removed": "Serviço eliminado com êxito",
"service_start_failed": "Não foi possível iniciar o serviço '{service:s}'",
"service_started": "O serviço '{service:s}' foi iniciado com êxito",
"service_status_failed": "Incapaz determinar o estado do serviço '{service:s}'",
"service_stop_failed": "Incapaz parar o serviço '{service:s}'",
"service_stopped": "O serviço '{service:s}' foi parado com êxito",
"service_unknown": "Serviço desconhecido '{service:s}'",
"ssowat_conf_generated": "Configuração SSOwat gerada com êxito",
"ssowat_conf_updated": "Configuração persistente SSOwat atualizada com êxito",
"system_upgraded": "Sistema atualizado com êxito",
"system_username_exists": "O utilizador já existe no registo do sistema",
"unexpected_error": "Ocorreu um erro inesperado",
"unit_unknown": "Unidade desconhecida '{unit:s}'",
"update_cache_failed": "Não foi possível atualizar os cabeçalhos APT",
"updating_apt_cache": "A atualizar a lista de pacotes disponíveis...",
"upgrade_complete": "Atualização completa",
"upgrading_packages": "Atualização de pacotes em curso...",
"user_created": "Utilizador criado com êxito",
"user_creation_failed": "Não foi possível criar o utilizador",
"user_deleted": "Utilizador eliminado com êxito",
"user_deletion_failed": "Incapaz eliminar o utilizador",
"user_info_failed": "Incapaz obter informações sobre o utilizador",
"user_unknown": "Utilizador desconhecido",
"user_update_failed": "Não foi possível atualizar o utilizador",
"user_updated": "Utilizador atualizado com êxito",
"yunohost_already_installed": "AYunoHost já está instalado",
"yunohost_ca_creation_failed": "Incapaz criar o certificado de autoridade",
"yunohost_configured": "YunoHost configurada com êxito",
"yunohost_installing": "A instalar a YunoHost...",
"yunohost_not_installed": "YunoHost ainda não está corretamente configurado. Por favor execute as 'ferramentas pós-instalação yunohost'."
}
}

View file

@ -1413,12 +1413,24 @@ def _encode_string(value):
def _check_manifest_requirements(manifest):
"""Check if required packages are met from the manifest"""
requirements = manifest.get('requirements', dict())
# FIXME: Deprecate min_version key
if 'min_version' in manifest:
requirements['yunohost'] = '>> {0}'.format(manifest['min_version'])
logger.debug("the manifest key 'min_version' is deprecated, "
"use 'requirements' instead.")
if not requirements:
# Validate multi-instance app
if manifest.get('multi_instance', False):
# Handle backward-incompatible change introduced in yunohost >= 2.3.6
# See https://dev.yunohost.org/issues/156
yunohost_req = requirements.get('yunohost', None)
if (not yunohost_req or
not packages.SpecifierSet(yunohost_req) & '>= 2.3.6'):
raise MoulinetteError(errno.EINVAL, '{0}{1}'.format(
m18n.g('colon', m18n.n('app_incompatible')),
m18n.n('app_package_need_update')))
elif not requirements:
return
logger.info(m18n.n('app_requirements_checking'))
@ -1429,7 +1441,8 @@ def _check_manifest_requirements(manifest):
*requirements.keys(), strict=True, as_dict=True)
except packages.PackageException as e:
raise MoulinetteError(errno.EINVAL,
m18n.n('app_requirements_failed', err=str(e)))
m18n.n('app_requirements_failed',
error=str(e)))
# Iterate over requirements
for pkgname, spec in requirements.items():

View file

@ -39,7 +39,9 @@ from moulinette.core import MoulinetteError
from moulinette.utils import filesystem
from moulinette.utils.log import getActionLogger
from yunohost.app import app_info, app_ssowatconf, _is_installed, _parse_app_instance_name
from yunohost.app import (
app_info, app_ssowatconf, _is_installed, _parse_app_instance_name
)
from yunohost.hook import (
hook_info, hook_callback, hook_exec, custom_hook_folder
)
@ -384,11 +386,11 @@ def backup_restore(auth, name, hooks=[], ignore_hooks=False,
else:
# Retrieve the domain from the backup
try:
with open("%s/yunohost/current_host" % tmp_dir, 'r') as f:
with open("%s/conf/ynh/current_host" % tmp_dir, 'r') as f:
domain = f.readline().rstrip()
except IOError:
logger.debug("unable to retrieve domain from "
"'%s/yunohost/current_host'", tmp_dir, exc_info=1)
logger.debug("unable to retrieve current_host from the backup",
exc_info=1)
raise MoulinetteError(errno.EIO, m18n.n('backup_invalid_archive'))
logger.debug("executing the post-install...")

View file

@ -37,6 +37,8 @@ from urllib import urlopen
from moulinette.core import MoulinetteError
from moulinette.utils.log import getActionLogger
from yunohost.service import service_regen_conf
logger = getActionLogger('yunohost.domain')
@ -78,7 +80,6 @@ def domain_add(auth, domain, dyndns=False):
dyndns -- Subscribe to DynDNS
"""
from yunohost.service import service_regenconf
from yunohost.hook import hook_callback
attr_dict = { 'objectClass' : ['mailDomain', 'top'] }
@ -157,10 +158,8 @@ def domain_add(auth, domain, dyndns=False):
try:
with open('/etc/yunohost/installed', 'r') as f:
service_regenconf(service='nginx')
service_regenconf(service='metronome')
service_regenconf(service='dnsmasq')
service_regenconf(service='rmilter')
service_regen_conf(names=[
'nginx', 'metronome', 'dnsmasq', 'rmilter'])
os.system('yunohost app ssowatconf > /dev/null 2>&1')
except IOError: pass
except:
@ -183,7 +182,6 @@ def domain_remove(auth, domain, force=False):
force -- Force the domain removal
"""
from yunohost.service import service_regenconf
from yunohost.hook import hook_callback
if not force and domain not in domain_list(auth)['domains']:
@ -206,9 +204,7 @@ def domain_remove(auth, domain, force=False):
else:
raise MoulinetteError(errno.EIO, m18n.n('domain_deletion_failed'))
service_regenconf(service='nginx')
service_regenconf(service='metronome')
service_regenconf(service='dnsmasq')
service_regen_conf(names=['nginx', 'metronome', 'dnsmasq'])
os.system('yunohost app ssowatconf > /dev/null 2>&1')
hook_callback('post_domain_remove', args=[domain])

View file

@ -176,6 +176,8 @@ def hook_list(action, list_by='name', show_info=False):
def _append_folder(d, folder):
# Iterate over and add hook from a folder
for f in os.listdir(folder + action):
if f[0] == '.' or f[-1] == '~':
continue
path = '%s%s/%s' % (folder, action, f)
priority, name = _extract_filename_parts(f)
_append_hook(d, priority, name, path)
@ -205,14 +207,22 @@ def hook_list(action, list_by='name', show_info=False):
return { 'hooks': result }
def hook_callback(action, hooks=[], args=None):
def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None,
pre_callback=None, post_callback=None):
"""
Execute all scripts binded to an action
Keyword argument:
action -- Action name
hooks -- List of hooks names to execute
args -- Ordered list of arguments to pass to the script
args -- Ordered list of arguments to pass to the scripts
no_trace -- Do not print each command that will be executed
chdir -- The directory from where the scripts will be executed
pre_callback -- An object to call before each script execution with
(name, priority, path, args) as arguments and which must return
the arguments to pass to the script
post_callback -- An object to call after each script execution with
(name, priority, path, succeed) as arguments
"""
result = { 'succeed': {}, 'failed': {} }
@ -252,26 +262,34 @@ def hook_callback(action, hooks=[], args=None):
if not hooks_dict:
return result
# Format arguments
if args is None:
args = []
elif not isinstance(args, list):
args = [args]
# Validate callbacks
if not callable(pre_callback):
pre_callback = lambda name, priority, path, args: args
if not callable(post_callback):
post_callback = lambda name, priority, path, succeed: None
# Iterate over hooks and execute them
for priority in sorted(hooks_dict):
for name, info in iter(hooks_dict[priority].items()):
state = 'succeed'
filename = '%s-%s' % (priority, name)
path = info['path']
try:
hook_exec(info['path'], args=args, raise_on_error=True)
hook_args = pre_callback(name=name, priority=priority,
path=path, args=args)
hook_exec(path, args=hook_args, chdir=chdir,
no_trace=no_trace, raise_on_error=True)
except MoulinetteError as e:
logger.error(str(e))
state = 'failed'
logger.error(str(e))
post_callback(name=name, priority=priority, path=path,
succeed=False)
else:
post_callback(name=name, priority=priority, path=path,
succeed=True)
try:
result[state][name].append(info['path'])
result[state][name].append(path)
except KeyError:
result[state][name] = [info['path']]
result[state][name] = [path]
return result
@ -282,7 +300,7 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
Keyword argument:
path -- Path of the script to execute
args -- A list of arguments to pass to the script
args -- Ordered list of arguments to pass to the script
raise_on_error -- Raise if the script returns a non-zero exit code
no_trace -- Do not print each command that will be executed
chdir -- The directory from where the script will be executed

View file

@ -30,20 +30,18 @@ import glob
import subprocess
import errno
import shutil
import difflib
import hashlib
from difflib import unified_diff
from moulinette.core import MoulinetteError
from moulinette.utils import log
from moulinette.utils import log, filesystem
template_dir = os.getenv(
'YUNOHOST_TEMPLATE_DIR',
'/usr/share/yunohost/templates'
)
conf_backup_dir = os.getenv(
'YUNOHOST_CONF_BACKUP_DIR',
'/home/yunohost.backup/conffiles'
)
from yunohost.hook import hook_list, hook_callback
base_conf_path = '/home/yunohost.conf'
backup_conf_dir = os.path.join(base_conf_path, 'backup')
pending_conf_dir = os.path.join(base_conf_path, 'pending')
logger = log.getActionLogger('yunohost.service')
@ -273,26 +271,196 @@ def service_log(name, number=50):
return result
def service_regenconf(service=None, force=False):
def service_regen_conf(names=[], with_diff=False, force=False, dry_run=False,
list_pending=False):
"""
Regenerate the configuration file(s) for a service and compare the result
with the existing configuration file.
Prints the differences between files if any.
Regenerate the configuration file(s) for a service
Keyword argument:
service -- Regenerate configuration for a specfic service
force -- Override the current configuration with the newly generated
one, even if it has been modified
names -- Services name to regenerate configuration of
with_diff -- Show differences in case of configuration changes
force -- Override all manual modifications in configuration files
dry_run -- Show what would have been regenerated
list_pending -- List pending configuration files and exit
"""
from yunohost.hook import hook_callback
result = {}
if service is not None:
hook_callback('conf_regen', [service], args=[force])
logger.success(m18n.n('service_configured', service=service))
else:
hook_callback('conf_regen', args=[force])
logger.success(m18n.n('service_configured_all'))
# Return the list of pending conf
if list_pending:
pending_conf = _get_pending_conf(names)
if with_diff:
for service, conf_files in pending_conf.items():
for system_path, pending_path in conf_files.items():
pending_conf[service][system_path] = {
'pending_conf': pending_path,
'diff': _get_files_diff(
system_path, pending_path, True),
}
return pending_conf
# Clean pending conf directory
shutil.rmtree(pending_conf_dir, ignore_errors=True)
filesystem.mkdir(pending_conf_dir, 0755, True)
# Format common hooks arguments
common_args = [1 if force else 0, 1 if dry_run else 0]
# Execute hooks for pre-regen
pre_args = ['pre',] + common_args
def _pre_call(name, priority, path, args):
# create the pending conf directory for the service
service_pending_path = os.path.join(pending_conf_dir, name)
filesystem.mkdir(service_pending_path, 0755, True, uid='admin')
# return the arguments to pass to the script
return pre_args + [service_pending_path,]
pre_result = hook_callback('conf_regen', names, pre_callback=_pre_call)
# Update the services name
names = pre_result['succeed'].keys()
if not names:
raise MoulinetteError(errno.EIO,
m18n.n('service_regenconf_failed',
services=', '.join(pre_result['failed'])))
# Set the processing method
_regen = _process_regen_conf if not dry_run else lambda *a, **k: True
# Iterate over services and process pending conf
for service, conf_files in _get_pending_conf(names).items():
logger.info(m18n.n(
'service_regenconf_pending_applying' if not dry_run else \
'service_regenconf_dry_pending_applying',
service=service))
conf_hashes = _get_conf_hashes(service)
succeed_regen = {}
failed_regen = {}
for system_path, pending_path in conf_files.items():
logger.debug("processing pending conf '%s' to system conf '%s'",
pending_path, system_path)
conf_status = None
regenerated = False
# Get the diff between files
conf_diff = _get_files_diff(
system_path, pending_path, True) if with_diff else None
# Check if the conf must be removed
to_remove = True if os.path.getsize(pending_path) == 0 else False
# Retrieve and calculate hashes
current_hash = conf_hashes.get(system_path, None)
system_hash = _calculate_hash(system_path)
new_hash = None if to_remove else _calculate_hash(pending_path)
# -> system conf does not exists
if not system_hash:
if to_remove:
logger.debug("> system conf is already removed")
os.remove(pending_path)
continue
if not current_hash or force:
if force:
logger.debug("> system conf has been manually removed")
conf_status = 'force-created'
else:
logger.debug("> system conf does not exist yet")
conf_status = 'created'
regenerated = _regen(
system_path, pending_path, save=False)
else:
logger.warning(m18n.n(
'service_conf_file_manually_removed',
conf=system_path))
conf_status = 'removed'
# -> system conf is not managed yet
elif not current_hash:
logger.debug("> system conf is not managed yet")
if system_hash == new_hash:
logger.debug("> no changes to system conf has been made")
conf_status = 'managed'
regenerated = True
elif force and to_remove:
regenerated = _regen(system_path)
conf_status = 'force-removed'
elif force:
regenerated = _regen(system_path, pending_path)
conf_status = 'force-updated'
else:
logger.warning(m18n.n('service_conf_file_not_managed',
conf=system_path))
conf_status = 'unmanaged'
# -> system conf has not been manually modified
elif system_hash == current_hash:
if to_remove:
regenerated = _regen(system_path)
conf_status = 'removed'
elif system_hash != new_hash:
regenerated = _regen(system_path, pending_path)
conf_status = 'updated'
else:
logger.debug("> system conf is already up-to-date")
os.remove(pending_path)
continue
else:
logger.debug("> system conf has been manually modified")
if force:
regenerated = _regen(system_path, pending_path)
conf_status = 'force-updated'
else:
logger.warning(m18n.n(
'service_conf_file_manually_modified',
conf=system_path))
conf_status = 'modified'
# Store the result
conf_result = {'status': conf_status}
if conf_diff is not None:
conf_result['diff'] = conf_diff
if regenerated:
succeed_regen[system_path] = conf_result
conf_hashes[system_path] = new_hash
if os.path.isfile(pending_path):
os.remove(pending_path)
else:
failed_regen[system_path] = conf_result
# Check for service conf changes
if not succeed_regen and not failed_regen:
logger.info(m18n.n('service_conf_up_to_date', service=service))
continue
elif not failed_regen:
logger.success(m18n.n(
'service_conf_updated' if not dry_run else \
'service_conf_would_be_updated',
service=service))
if succeed_regen and not dry_run:
_update_conf_hashes(service, conf_hashes)
# Append the service results
result[service] = {
'applied': succeed_regen,
'pending': failed_regen
}
# Return in case of dry run
if dry_run:
return result
# Execute hooks for post-regen
post_args = ['post',] + common_args
def _pre_call(name, priority, path, args):
# append coma-separated applied changes for the service
if name in result and result[name]['applied']:
regen_conf_files = ','.join(result[name]['applied'].keys())
else:
regen_conf_files = ''
return post_args + [regen_conf_files,]
hook_callback('conf_regen', names, pre_callback=_pre_call)
return result
def _run_service_command(action, service):
@ -380,175 +548,141 @@ def _tail(file, n, offset=None):
except IOError: return []
def _get_diff(string, filename):
"""
Show differences between a string and a file's content
def _get_files_diff(orig_file, new_file, as_string=False, skip_header=True):
"""Compare two files and return the differences
Keyword argument:
string -- The string
filename -- The file to compare with
Read and compare two files. The differences are returned either as a delta
in unified diff format or a formatted string if as_string is True. The
header can also be removed if skip_header is True.
"""
try:
with open(filename, 'r') as f:
file_lines = f.readlines()
contents = [[], []]
for i, path in enumerate((orig_file, new_file)):
try:
with open(path, 'r') as f:
contents[i] = f.readlines()
except IOError:
pass
string = string + '\n'
new_lines = string.splitlines(True)
if file_lines:
while '\n' == file_lines[-1]:
del file_lines[-1]
return difflib.unified_diff(file_lines, new_lines)
except IOError: return []
# Compare files and format output
diff = unified_diff(contents[0], contents[1])
if skip_header:
for i in range(2):
try:
next(diff)
except:
break
if as_string:
result = ''.join(line for line in diff)
return result.rstrip()
return diff
def _hash(filename):
"""
Calculate a MD5 hash of a file
Keyword argument:
filename -- The file to hash
"""
def _calculate_hash(path):
"""Calculate the MD5 hash of a file"""
hasher = hashlib.md5()
try:
with open(filename, 'rb') as f:
buf = f.read()
hasher.update(buf)
with open(path, 'rb') as f:
hasher.update(f.read())
return hasher.hexdigest()
except IOError:
return 'no hash yet'
return None
def service_saferemove(service, conf_file, force=False):
"""
Check if the specific file has been modified before removing it.
Backup the file in /home/yunohost.backup
def _get_pending_conf(services=[]):
"""Get pending configuration for service(s)
Keyword argument:
service -- Service name of the file to delete
conf_file -- The file to write
force -- Force file deletion
Iterate over the pending configuration directory for given service(s) - or
all if empty - and look for files inside. Each file is considered as a
pending configuration file and therefore must be in the same directory
tree than the system file that it replaces.
The result is returned as a dict of services with pending configuration as
key and a dict of `system_conf_path` => `pending_conf_path` as value.
"""
deleted = False
result = {}
if not os.path.isdir(pending_conf_dir):
return result
if not services:
services = os.listdir(pending_conf_dir)
for name in services:
service_conf = {}
service_pending_path = os.path.join(pending_conf_dir, name)
path_index = len(service_pending_path)
for root, dirs, files in os.walk(service_pending_path):
for filename in files:
pending_path = os.path.join(root, filename)
service_conf[pending_path[path_index:]] = pending_path
if service_conf:
result[name] = service_conf
return result
def _get_conf_hashes(service):
"""Get the registered conf hashes for a service"""
try:
return _get_services()[service]['conffiles']
except:
logger.debug("unable to retrieve conf hashes for %s",
service, exc_info=1)
return {}
def _update_conf_hashes(service, hashes):
"""Update the registered conf hashes for a service"""
logger.debug("updating conf hashes for '%s' with: %s",
service, hashes)
services = _get_services()
if not os.path.exists(conf_file):
try:
del services[service]['conffiles'][conf_file]
except KeyError: pass
return True
# Backup existing file
date = time.strftime("%Y%m%d.%H%M%S")
conf_backup_file = conf_backup_dir + conf_file +'-'+ date
process = subprocess.Popen(
['install', '-D', conf_file, conf_backup_file]
)
process.wait()
# Retrieve hashes
if not 'conffiles' in services[service]:
services[service]['conffiles'] = {}
if conf_file in services[service]['conffiles']:
previous_hash = services[service]['conffiles'][conf_file]
else:
previous_hash = 'no hash yet'
current_hash = _hash(conf_file)
# Handle conflicts
if force or previous_hash == current_hash:
os.remove(conf_file)
try:
del services[service]['conffiles'][conf_file]
except KeyError: pass
deleted = True
else:
services[service]['conffiles'][conf_file] = previous_hash
os.remove(conf_backup_file)
if len(previous_hash) == 32 or previous_hash[-32:] != current_hash:
logger.warning(m18n.n('service_configuration_conflict',
file=conf_file))
service_conf = services.get(service, {})
service_conf['conffiles'] = hashes
services[service] = service_conf
_save_services(services)
return deleted
def _process_regen_conf(system_conf, new_conf=None, save=True):
"""Regenerate a given system configuration file
def service_safecopy(service, new_conf_file, conf_file, force=False):
"""
Check if the specific file has been modified and display differences.
Stores the file hash in the services.yml file
Keyword argument:
service -- Service name attached to the conf file
new_conf_file -- Path to the desired conf file
conf_file -- Path to the targeted conf file
force -- Force file overriding
Replace a given system configuration file by a new one or delete it if
new_conf is None. A backup of the file - keeping its directory tree - will
be done in the backup conf directory before any operation if save is True.
"""
regenerated = False
services = _get_services()
if not os.path.exists(new_conf_file):
raise MoulinetteError(errno.EIO, m18n.n('no_such_conf_file', file=new_conf_file))
with open(new_conf_file, 'r') as f:
new_conf = ''.join(f.readlines()).rstrip()
# Backup existing file
date = time.strftime("%Y%m%d.%H%M%S")
conf_backup_file = conf_backup_dir + conf_file +'-'+ date
if os.path.exists(conf_file):
process = subprocess.Popen(
['install', '-D', conf_file, conf_backup_file]
)
process.wait()
else:
logger.info(m18n.n('service_add_configuration', file=conf_file))
# Add the service if it does not exist
if service not in services.keys():
services[service] = {}
# Retrieve hashes
if not 'conffiles' in services[service]:
services[service]['conffiles'] = {}
if conf_file in services[service]['conffiles']:
previous_hash = services[service]['conffiles'][conf_file]
else:
previous_hash = 'no hash yet'
current_hash = _hash(conf_file)
diff = list(_get_diff(new_conf, conf_file))
# Handle conflicts
if force or previous_hash == current_hash:
with open(conf_file, 'w') as f: f.write(new_conf)
new_hash = _hash(conf_file)
if previous_hash != new_hash:
regenerated = True
elif len(diff) == 0:
new_hash = _hash(conf_file)
else:
new_hash = previous_hash
if (len(previous_hash) == 32 or previous_hash[-32:] != current_hash):
logger.warning('{0} {1}'.format(
m18n.n('service_configuration_conflict', file=conf_file),
m18n.n('show_diff', diff=''.join(diff))))
# Remove the backup file if the configuration has not changed
if new_hash == previous_hash:
try:
os.remove(conf_backup_file)
except OSError: pass
services[service]['conffiles'][conf_file] = new_hash
_save_services(services)
return regenerated
if save:
backup_path = os.path.join(backup_conf_dir, '{0}-{1}'.format(
system_conf.lstrip('/'), time.strftime("%Y%m%d.%H%M%S")))
backup_dir = os.path.dirname(backup_path)
if not os.path.isdir(backup_dir):
filesystem.mkdir(backup_dir, 0755, True)
shutil.copy2(system_conf, backup_path)
logger.info(m18n.n('service_conf_file_backed_up',
conf=system_conf, backup=backup_path))
try:
if not new_conf:
os.remove(system_conf)
logger.info(m18n.n('service_conf_file_removed',
conf=system_conf))
else:
system_dir = os.path.dirname(system_conf)
if not os.path.isdir(system_dir):
filesystem.mkdir(system_dir, 0755, True)
shutil.copyfile(new_conf, system_conf)
logger.info(m18n.n('service_conf_file_updated',
conf=system_conf))
except:
if not new_conf and os.path.exists(system_conf):
logger.warning(m18n.n('service_conf_file_remove_failed',
conf=system_conf),
exc_info=1)
return False
elif new_conf:
try:
copy_succeed = os.path.samefile(system_conf, new_conf)
except:
copy_succeed = False
finally:
if not copy_succeed:
logger.warning(m18n.n('service_conf_file_copy_failed',
conf=system_conf, new=new_conf),
exc_info=1)
return False
return True

View file

@ -43,7 +43,7 @@ from yunohost.app import app_fetchlist, app_info, app_upgrade, app_ssowatconf, a
from yunohost.domain import domain_add, domain_list, get_public_ip
from yunohost.dyndns import dyndns_subscribe
from yunohost.firewall import firewall_upnp, firewall_reload
from yunohost.service import service_status, service_regenconf, service_log
from yunohost.service import service_status, service_regen_conf, service_log
from yunohost.monitor import monitor_disk, monitor_network, monitor_system
from yunohost.utils.packages import ynh_packages_version
@ -152,7 +152,7 @@ def tools_maindomain(auth, old_domain=None, new_domain=None, dyndns=False):
try:
with open('/etc/yunohost/installed', 'r') as f:
service_regenconf()
service_regen_conf()
except IOError: pass
logger.success(m18n.n('maindomain_changed'))
@ -170,13 +170,10 @@ def tools_postinstall(domain, password, ignore_dyndns=False):
"""
dyndns = not ignore_dyndns
try:
with open('/etc/yunohost/installed') as f: pass
except IOError:
logger.info(m18n.n('yunohost_installing'))
else:
raise MoulinetteError(errno.EPERM, m18n.n('yunohost_already_installed'))
# Do some checks at first
if os.path.isfile('/etc/yunohost/installed'):
raise MoulinetteError(errno.EPERM,
m18n.n('yunohost_already_installed'))
if len(domain.split('.')) >= 3 and not ignore_dyndns:
try:
r = requests.get('https://dyndns.yunohost.org/domains')
@ -187,10 +184,23 @@ def tools_postinstall(domain, password, ignore_dyndns=False):
dyndomain = '.'.join(domain.split('.')[1:])
if dyndomain in dyndomains:
if requests.get('https://dyndns.yunohost.org/test/%s' % domain).status_code == 200:
dyndns=True
dyndns = True
else:
raise MoulinetteError(errno.EEXIST,
m18n.n('dyndns_unavailable'))
m18n.n('dyndns_unavailable'))
logger.info(m18n.n('yunohost_installing'))
# Instantiate LDAP Authenticator
auth = init_authenticator(('ldap', 'default'),
{'uri': "ldap://localhost:389",
'base_dn': "dc=yunohost,dc=org",
'user_rdn': "cn=admin" })
auth.authenticate('yunohost')
# Initialize LDAP for YunoHost
# TODO: Improve this part by integrate ldapinit into conf_regen hook
tools_ldapinit(auth)
# Create required folders
folders_to_create = [
@ -230,6 +240,7 @@ def tools_postinstall(domain, password, ignore_dyndns=False):
os.system('chmod 644 /etc/ssowat/conf.json.persistent')
# Create SSL CA
service_regen_conf(['ssl'], force=True)
ssl_dir = '/usr/share/yunohost/yunohost-config/ssl/yunoCA'
command_list = [
'echo "01" > %s/serial' % ssl_dir,
@ -247,16 +258,6 @@ def tools_postinstall(domain, password, ignore_dyndns=False):
raise MoulinetteError(errno.EPERM,
m18n.n('yunohost_ca_creation_failed'))
# Instantiate LDAP Authenticator
auth = init_authenticator(('ldap', 'default'),
{ 'uri': "ldap://localhost:389",
'base_dn': "dc=yunohost,dc=org",
'user_rdn': "cn=admin" })
auth.authenticate('yunohost')
# Initialize YunoHost LDAP base
tools_ldapinit(auth)
# New domain config
tools_maindomain(auth, old_domain='yunohost.org', new_domain=domain, dyndns=dyndns)
@ -275,7 +276,7 @@ def tools_postinstall(domain, password, ignore_dyndns=False):
os.system('update-rc.d yunohost-firewall enable')
os.system('service yunohost-firewall start')
service_regenconf(force=True)
service_regen_conf(force=True)
logger.success(m18n.n('yunohost_configured'))
@ -503,4 +504,4 @@ def tools_diagnosis(auth, private=False):
# Domains
diagnosis['private']['domains'] = domain_list(auth)['domains']
return diagnosis
return diagnosis

View file

@ -98,17 +98,22 @@ class Specifier(object):
}
def __init__(self, spec):
match = self._regex.search(spec)
if not match:
raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
if isinstance(spec, basestring):
match = self._regex.search(spec)
if not match:
raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
self._spec = (
match.group("relation").strip(),
match.group("version").strip(),
)
self._spec = (
match.group("relation").strip(),
match.group("version").strip(),
)
elif isinstance(spec, self.__class__):
self._spec = spec._spec
else:
return NotImplemented
def __repr__(self):
return "<Specifier({1!r})>".format(str(self))
return "<Specifier({0!r})>".format(str(self))
def __str__(self):
return "{0}{1}".format(*self._spec)
@ -138,6 +143,12 @@ class Specifier(object):
return self._spec != other._spec
def __and__(self, other):
return self.intersection(other)
def __or__(self, other):
return self.union(other)
def _get_relation(self, op):
return getattr(self, "_compare_{0}".format(self._relations[op]))
@ -167,7 +178,79 @@ class Specifier(object):
def __contains__(self, item):
return self.contains(item)
def intersection(self, other):
"""Make the intersection of two specifiers
Return a new `SpecifierSet` with version specifier(s) common to the
specifier and the other.
Example:
>>> Specifier('>= 2.2') & '>> 2.2.1' == '>> 2.2.1'
>>> Specifier('>= 2.2') & '<< 2.3' == '>= 2.2, << 2.3'
"""
if isinstance(other, basestring):
try:
other = self.__class__(other)
except InvalidSpecifier:
return NotImplemented
elif not isinstance(other, self.__class__):
return NotImplemented
# store spec parts for easy access
rel1, v1 = self.relation, self.version
rel2, v2 = other.relation, other.version
result = []
if other == self:
result = [other]
elif rel1 == '=':
result = [self] if v1 in other else None
elif rel2 == '=':
result = [other] if v2 in self else None
elif v1 == v2:
result = [other if rel1[1] == '=' else self]
elif v2 in self or v1 in other:
is_self_greater = version_compare(v1, v2) > 0
if rel1[0] == rel2[0]:
if rel1[0] == '>':
result = [self if is_self_greater else other]
else:
result = [other if is_self_greater else self]
else:
result = [self, other]
return SpecifierSet(result if result is not None else '')
def union(self, other):
"""Make the union of two version specifiers
Return a new `SpecifierSet` with version specifiers from the
specifier and the other.
Example:
>>> Specifier('>= 2.2') | '<< 2.3' == '>= 2.2, << 2.3'
"""
if isinstance(other, basestring):
try:
other = self.__class__(other)
except InvalidSpecifier:
return NotImplemented
elif not isinstance(other, self.__class__):
return NotImplemented
return SpecifierSet([self, other])
def contains(self, item):
"""Check if the specifier contains an other
Return whether the item is contained in the version specifier.
Example:
>>> '2.2.1' in Specifier('<< 2.3')
>>> '2.4' not in Specifier('<< 2.3')
"""
return self._get_relation(self.relation)(item, self.version)
@ -181,7 +264,9 @@ class SpecifierSet(object):
"""
def __init__(self, specifiers):
specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
if isinstance(specifiers, basestring):
specifiers = [s.strip() for s in specifiers.split(",")
if s.strip()]
parsed = set()
for specifier in specifiers:
@ -190,7 +275,7 @@ class SpecifierSet(object):
self._specs = frozenset(parsed)
def __repr__(self):
return "<SpecifierSet({1!r})>".format(str(self))
return "<SpecifierSet({0!r})>".format(str(self))
def __str__(self):
return ",".join(sorted(str(s) for s in self._specs))
@ -199,14 +284,10 @@ class SpecifierSet(object):
return hash(self._specs)
def __and__(self, other):
if isinstance(other, basestring):
other = SpecifierSet(other)
elif not isinstance(other, SpecifierSet):
return NotImplemented
return self.intersection(other)
specifier = SpecifierSet()
specifier._specs = frozenset(self._specs | other._specs)
return specifiers
def __or__(self, other):
return self.union(other)
def __eq__(self, other):
if isinstance(other, basestring):
@ -237,7 +318,69 @@ class SpecifierSet(object):
def __contains__(self, item):
return self.contains(item)
def intersection(self, other):
"""Make the intersection of two specifiers sets
Return a new `SpecifierSet` with version specifier(s) common to the
set and the other.
Example:
>>> SpecifierSet('>= 2.2') & '>> 2.2.1' == '>> 2.2.1'
>>> SpecifierSet('>= 2.2, << 2.4') & '<< 2.3' == '>= 2.2, << 2.3'
>>> SpecifierSet('>= 2.2, << 2.3') & '>= 2.4' == ''
"""
if isinstance(other, basestring):
other = SpecifierSet(other)
elif not isinstance(other, SpecifierSet):
return NotImplemented
specifiers = set(self._specs | other._specs)
intersection = [specifiers.pop()] if specifiers else []
for specifier in specifiers:
parsed = set()
for spec in intersection:
inter = spec & specifier
if not inter:
parsed.clear()
break
# TODO: validate with other specs in parsed
parsed.update(inter._specs)
intersection = parsed
if not intersection:
break
return SpecifierSet(intersection)
def union(self, other):
"""Make the union of two specifiers sets
Return a new `SpecifierSet` with version specifiers from the set
and the other.
Example:
>>> SpecifierSet('>= 2.2') | '<< 2.3' == '>= 2.2, << 2.3'
"""
if isinstance(other, basestring):
other = SpecifierSet(other)
elif not isinstance(other, SpecifierSet):
return NotImplemented
specifiers = SpecifierSet([])
specifiers._specs = frozenset(self._specs | other._specs)
return specifiers
def contains(self, item):
"""Check if the set contains a version specifier
Return whether the item is contained in all version specifiers.
Example:
>>> '2.2.1' in SpecifierSet('>= 2.2, << 2.3')
>>> '2.4' not in SpecifierSet('>= 2.2, << 2.3')
"""
return all(
s.contains(item)
for s in self._specs