Merge branch 'stretch-unstable' into rework-migration-system

This commit is contained in:
Alexandre Aubin 2019-09-10 14:27:56 +02:00 committed by GitHub
commit dc7b8d1faa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 878 additions and 207 deletions

View file

@ -1,42 +1,45 @@
# YunoHost core
- [YunoHost project website](https://yunohost.org)
This repository is the core of YunoHost code.
<a href="https://translate.yunohost.org/engage/yunohost/?utm_source=widget">
<img src="https://translate.yunohost.org/widgets/yunohost/-/287x66-white.png" alt="Translation status" />
</a>
- [YunoHost project website](https://yunohost.org)
- [Butracker](https://github.com/YunoHost/issues).
## Issues
- [Please report issues on YunoHost bugtracker](https://github.com/YunoHost/issues).
## Contributing
## Contribute
- You can develop on this repository using [ynh-dev tool](https://github.com/YunoHost/ynh-dev) with `use-git` sub-command.
- On this repository we are [following this workflow](https://yunohost.org/#/build_system_en): `stable <— testing <— branch`.
- You can develop on this repository using [ynh-dev](https://github.com/YunoHost/ynh-dev) with `use-git` sub-command.
- On this repository we are [following this workflow](https://yunohost.org/#/build_system_en): `stable <- testing <- unstable <- your_branch`.
- Note: if you modify python scripts, you will have to modifiy the actions map.
- You can help with translation on [our translation platform](https://translate.yunohost.org/engage/yunohost/?utm_source=widget)
<img src="https://translate.yunohost.org/widgets/yunohost/-/multi-auto.svg" alt="Translation status" />
## Repository content
- [YunoHost core Python 2.7 scripts](https://github.com/YunoHost/yunohost/tree/stable/src/yunohost).
- [An actionsmap](https://github.com/YunoHost/yunohost/blob/stable/data/actionsmap/yunohost.yml) used by moulinette.
- [Services configuration templates](https://github.com/YunoHost/yunohost/tree/stable/data/templates).
- [Hooks](https://github.com/YunoHost/yunohost/tree/stable/data/hooks).
- [Locales](https://github.com/YunoHost/yunohost/tree/stable/locales) for translations of `yunohost` command.
- [Shell helpers](https://github.com/YunoHost/yunohost/tree/stable/data/helpers.d) for [application packaging](https://yunohost.org/#/packaging_apps_helpers_en).
- [Modules for the XMPP server Metronome](https://github.com/YunoHost/yunohost/tree/stable/lib/metronome/modules).
- [Debian files](https://github.com/YunoHost/yunohost/tree/stable/debian) for package creation.
- [YunoHost core Python 2.7 scripts](./src/yunohost).
- [An actionsmap](./data/actionsmap/yunohost.yml) used by moulinette.
- [Services configuration templates](./data/templates).
- [Hooks](./data/hooks).
- [Locales](./locales) for translations of `yunohost` command.
- [Shell helpers](./helpers.d) for [application packaging](https://yunohost.org/#/packaging_apps_helpers_en).
- [Modules for the XMPP server Metronome](./lib/metronome/modules).
- [Debian files](./debian) for package creation.
## How does it work?
- Python core scripts are accessible through two interfaces thanks to the [moulinette framework](https://github.com/YunoHost/moulinette):
- [CLI](https://en.wikipedia.org/wiki/Command-line_interface) for `yunohost` command.
- [API](https://en.wikipedia.org/wiki/Application_programming_interface) for [web administration module](https://github.com/YunoHost/yunohost-admin) (other modules could be implemented).
- You can find more details about how YunoHost works on this [documentation (in french)](https://yunohost.org/#/package_list_fr).
## Dependencies
- [Python 2.7](https://www.python.org/download/releases/2.7)
- [Moulinette](https://github.com/YunoHost/moulinette)
- [Bash](https://www.gnu.org/software/bash/bash.html)
- [Debian Jessie](https://www.debian.org/releases/jessie)
- [Debian Stretch](https://www.debian.org/releases/stretch)
## License
As [other components of YunoHost core code](https://yunohost.org/#/faq_en), this repository is under GNU AGPL v.3 license.

View file

@ -1533,6 +1533,14 @@ dyndns:
-i:
full: --ipv4
help: IP address to send
-f:
full: --force
help: Force the update (for debugging only)
action: store_true
-D:
full: --dry-run
help: Only display the generated zone
action: store_true
-6:
full: --ipv6
help: IPv6 address to send
@ -1585,6 +1593,9 @@ tools:
postinstall:
action_help: YunoHost post-install
api: POST /postinstall
configuration:
# We need to be able to run the postinstall without being authenticated, otherwise we can't run the postinstall
authenticate: false
arguments:
-d:
full: --domain

View file

@ -231,7 +231,7 @@ ynh_mysql_remove_db () {
fi
# Remove mysql user if it exists
if $(ynh_mysql_user_exists --user=$db_user); then
if ynh_mysql_user_exists --user=$db_user; then
ynh_mysql_drop_user $db_user
fi
}

View file

@ -16,8 +16,8 @@ ynh_install_n () {
ynh_print_info --message="Installation of N - Node.js version management"
# Build an app.src for n
mkdir -p "../conf"
echo "SOURCE_URL=https://github.com/tj/n/archive/v2.1.7.tar.gz
SOURCE_SUM=2ba3c9d4dd3c7e38885b37e02337906a1ee91febe6d5c9159d89a9050f2eea8f" > "../conf/n.src"
echo "SOURCE_URL=https://github.com/tj/n/archive/v4.1.0.tar.gz
SOURCE_SUM=3983fa3f00d4bf85ba8e21f1a590f6e28938093abe0bb950aeea52b1717471fc" > "../conf/n.src"
# Download and extract n
ynh_setup_source --dest_dir="$n_install_dir/git" --source_id=n
# Install n

View file

@ -283,11 +283,11 @@ ynh_psql_test_if_first_run() {
sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$psql_root_password'" postgres
# force all user to connect to local database using passwords
# force all user to connect to local databases using hashed passwords
# https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF
# Note: we can't use peer since YunoHost create users with nologin
# See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user
ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3password" --target_file="$pg_hba"
ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba"
# Advertise service in admin panel
yunohost service add postgresql --log "$logfile"

View file

@ -78,6 +78,9 @@ do_init_regen() {
ln -sf "$ynh_crt" /etc/ssl/certs/yunohost_crt.pem
ln -sf "$ynh_key" /etc/ssl/private/yunohost_key.pem
fi
chown -R root:ssl-cert /etc/yunohost/certs/yunohost.org/
chmod o-rwx /etc/yunohost/certs/yunohost.org/
}
do_pre_regen() {

View file

@ -15,6 +15,7 @@ do_init_regen() {
# fix some permissions
chown root:openldap /etc/ldap/slapd.conf
chown -R openldap:openldap /etc/ldap/schema/
usermod -aG ssl-cert openldap
# check the slapd config file at first
slaptest -Q -u -f /etc/ldap/slapd.conf
@ -43,7 +44,7 @@ do_pre_regen() {
|| touch "${pending_dir}/etc/ldap/slapd-yuno.conf"
# remove temporary backup file
sudo rm -f "$tmp_backup_dir_file"
rm -f "$tmp_backup_dir_file"
# retrieve current and new backends
curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2>/dev/null | awk '{print $2}')
@ -52,8 +53,8 @@ do_pre_regen() {
# save current database before any conf changes
if [[ -n "$curr_backend" && "$curr_backend" != "$new_backend" ]]; then
backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)"
sudo mkdir -p "$backup_dir"
sudo slapcat -b dc=yunohost,dc=org \
mkdir -p "$backup_dir"
slapcat -b dc=yunohost,dc=org \
-l "${backup_dir}/dc=yunohost-dc=org.ldif"
echo "$backup_dir" > "$tmp_backup_dir_file"
fi
@ -69,27 +70,30 @@ do_post_regen() {
regen_conf_files=$1
# ensure that slapd.d exists
sudo mkdir -p /etc/ldap/slapd.d
mkdir -p /etc/ldap/slapd.d
# 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/
# Add openldap user in the ssl-cert group to let it access the certificate for TLS
sudo usermod -aG ssl-cert openldap
echo "Making sure we have the right permissions needed ..."
# penldap user should be in the ssl-cert group to let it access the certificate for TLS
usermod -aG ssl-cert openldap
chown root:openldap /etc/ldap/slapd.conf
chown -R openldap:openldap /etc/ldap/schema/
chown -R openldap:openldap /etc/ldap/slapd.d/
chown -R root:ssl-cert /etc/yunohost/certs/yunohost.org/
chmod o-rwx /etc/yunohost/certs/yunohost.org/
[ -z "$regen_conf_files" ] && exit 0
# check the slapd config file at first
sudo slaptest -Q -u -f /etc/ldap/slapd.conf
slaptest -Q -u -f /etc/ldap/slapd.conf
# check if a backup should be restored
backup_dir=$(cat "$tmp_backup_dir_file" 2>/dev/null || true)
if [[ -n "$backup_dir" && -f "${backup_dir}/dc=yunohost-dc=org.ldif" ]]; 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;
echo "Regenerate LDAP config directory and import the database using slapadd"
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;
@ -98,15 +102,18 @@ do_post_regen() {
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/
echo "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/
fi
sudo -u openldap slapindex
echo "Running slapdindex"
su openldap -s "/bin/bash" -c "/usr/sbin/slapindex"
sudo service slapd force-reload
echo "Reloading slapd"
service slapd force-reload
# on slow hardware/vm this regen conf would exit before the admin user that
# is stored in ldap is available because ldap seems to slow to restart

View file

@ -1,7 +1,7 @@
#!/bin/bash
set -e
MYSQL_PKG="mariadb-server-10.1"
MYSQL_PKG="$(dpkg --list | sed -ne 's/^ii \(mariadb-server-[[:digit:].]\+\) .*$/\1/p')"
. /usr/share/yunohost/helpers
do_pre_regen() {

View file

@ -1,5 +1,5 @@
backup_dir="$1/conf/ynh/mysql"
MYSQL_PKG="mariadb-server-10.1"
MYSQL_PKG="$(dpkg --list | sed -ne 's/^ii \(mariadb-server-[[:digit:].]\+\) .*$/\1/p')"
. /usr/share/yunohost/helpers

View file

@ -42,8 +42,8 @@ sizelimit 500
tool-threads 1
# TLS Support
TLSCertificateFile /etc/ssl/private/yunohost_crt.pem
TLSCertificateKeyFile /etc/ssl/private/yunohost_key.pem
TLSCertificateFile /etc/yunohost/certs/yunohost.org/crt.pem
TLSCertificateKeyFile /etc/yunohost/certs/yunohost.org/key.pem
#######################################################################
# Specific Backend Directives for mdb:

6
debian/changelog vendored
View file

@ -1,3 +1,9 @@
yunohost (3.6.4.6) stable; urgency=low
- [fix] Hopefully fix the issue about corrupted logs metadata files (d507d447, 1cec9d78)
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 05 Aug 2019 18:37:00 +0000
yunohost (3.6.4.5) stable; urgency=low
- [fix] Typo in hotfix...

2
debian/install vendored
View file

@ -6,7 +6,7 @@ data/actionsmap/* /usr/share/moulinette/actionsmap/
data/hooks/* /usr/share/yunohost/hooks/
data/other/yunoprompt.service /etc/systemd/system/
data/other/password/* /usr/share/yunohost/other/password/
data/other/dpkg-origins /etc/dpkg/origins/yunohost
data/other/dpkg-origins/yunohost /etc/dpkg/origins
data/other/* /usr/share/yunohost/yunohost-config/moulinette/
data/templates/* /usr/share/yunohost/templates/
data/helpers /usr/share/yunohost/

View file

@ -25,14 +25,14 @@
"app_manifest_invalid": "Manifest d'aplicació incorrecte: {error}",
"app_no_upgrade": "No hi ha cap aplicació per actualitzar",
"app_not_correctly_installed": "{app:s} sembla estar mal instal·lada",
"app_not_installed": "{app:s} no està instal·lada",
"app_not_installed": "L'aplicació «{app:s}» no està instal·lada. Aquí hi ha la llista d'aplicacions instal·lades: {all_apps}",
"app_not_properly_removed": "{app:s} no s'ha pogut suprimir correctament",
"app_package_need_update": "El paquet de l'aplicació {app} ha de ser actualitzat per poder seguir els canvis de YunoHost",
"app_removed": "{app:s} ha estat suprimida",
"app_requirements_checking": "Verificació dels paquets requerits per {app}…",
"app_requirements_failed": "No es poden satisfer els requeriments per {app}: {error}",
"app_requirements_unmeet": "No es compleixen els requeriments per {app}, el paquet {pkgname} ({version}) ha de ser {spec}",
"app_sources_fetch_failed": "No s'han pogut carregar els fitxers font",
"app_sources_fetch_failed": "No s'han pogut carregar els fitxers font, l'URL és correcta?",
"app_unknown": "Aplicació desconeguda",
"app_unsupported_remote_type": "El tipus remot utilitzat per l'aplicació no està suportat",
"app_upgrade_app_name": "Actualitzant l'aplicació {app}…",
@ -127,7 +127,7 @@
"backup_with_no_restore_script_for_app": "L'aplicació {app:s} no té un script de restauració, no podreu restaurar automàticament la còpia de seguretat d'aquesta aplicació.",
"certmanager_acme_not_configured_for_domain": "El certificat pel domini {domain:s} sembla que no està instal·lat correctament. Si us plau executeu primer cert-install per aquest domini.",
"certmanager_attempt_to_renew_nonLE_cert": "El certificat pel domini {domain:s} no ha estat emès per Let's Encrypt. No es pot renovar automàticament!",
"certmanager_attempt_to_renew_valid_cert": "El certificat pel domini {domain:s} està a punt de caducar! Utilitzeu --force per ometre",
"certmanager_attempt_to_renew_valid_cert": "El certificat pel domini {domain:s} està a punt de caducar! (Utilitzeu --force si sabeu el que esteu fent)",
"certmanager_attempt_to_replace_valid_cert": "Esteu intentant sobreescriure un certificat correcte i vàlid pel domini {domain:s}! (Utilitzeu --force per ometre)",
"certmanager_cannot_read_cert": "S'ha produït un error al intentar obrir el certificat actual pel domini {domain:s} (arxiu: {file:s}), raó: {reason:s}",
"certmanager_cert_install_success": "S'ha instal·lat correctament un certificat Let's Encrypt pel domini {domain:s}!",
@ -175,7 +175,7 @@
"domain_dyndns_dynette_is_unreachable": "No s'ha pogut abastar la dynette YunoHost, o bé YunoHost no està connectat a internet correctament o bé el servidor dynette està caigut. Error: {error}",
"domain_dyndns_invalid": "Domini no vàlid per utilitzar amb DynDNS",
"domain_dyndns_root_unknown": "Domini DynDNS principal desconegut",
"domain_hostname_failed": "No s'ha pogut establir un nou nom d'amfitrió",
"domain_hostname_failed": "No s'ha pogut establir un nou nom d'amfitrió. Això podria causar problemes més tard (no és segur ... podria no passar res).",
"domain_uninstall_app_first": "Hi ha una o més aplicacions instal·lades en aquest domini. Desinstal·leu les abans d'eliminar el domini",
"domain_unknown": "Domini desconegut",
"domain_zone_exists": "El fitxer de zona DNS ja existeix",
@ -236,7 +236,7 @@
"invalid_url_format": "Format d'URL invàlid",
"ip6tables_unavailable": "No podeu modificar les ip6tables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció",
"iptables_unavailable": "No podeu modificar les iptables aquí. O bé sou en un contenidor o bé el vostre nucli no és compatible amb aquesta opció",
"log_corrupted_md_file": "El fitxer de metadades yaml associat amb els registres està malmès: « {md_file} »",
"log_corrupted_md_file": "El fitxer de metadades yaml associat amb els registres està malmès: « {md_file} »\nError: {error}",
"log_category_404": "La categoria de registres « {category} » no existeix",
"log_link_to_log": "El registre complet d'aquesta operació: «<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>»",
"log_help_to_get_log": "Per veure el registre de l'operació « {desc} », utilitzeu l'ordre «yunohost log display {name} »",
@ -275,7 +275,311 @@
"log_tools_migrations_migrate_forward": "Migrar",
"log_tools_migrations_migrate_backward": "Migrar endarrera",
"log_tools_postinstall": "Fer la post instal·lació del servidor YunoHost",
"log_tools_upgrade": "Actualitza els paquets Debian",
"log_tools_upgrade": "Actualitza els paquets del sistema",
"log_tools_shutdown": "Apaga el servidor",
"log_tools_reboot": "Reinicia el servidor"
"log_tools_reboot": "Reinicia el servidor",
"already_up_to_date": "No hi ha res a fer! Tot està al dia!",
"dpkg_lock_not_available": "No es pot utilitzar aquesta comanda en aquest moment ja que sembla que un altre programa està utilitzant el lock de dpkg (el gestor de paquets del sistema)",
"global_settings_setting_security_postfix_compatibility": "Solució de compromís entre compatibilitat i seguretat pel servidor Postfix. Afecta els criptògrafs (i altres aspectes relacionats amb la seguretat)",
"ldap_init_failed_to_create_admin": "La inicialització de LDAP no ha pogut crear l'usuari admin",
"ldap_initialized": "S'ha iniciat LDAP",
"license_undefined": "indefinit",
"mail_alias_remove_failed": "No s'han pogut eliminar els alias del correu «{mail:s}»",
"mail_domain_unknown": "Domini d'adreça de correu «{domain:s}» desconegut",
"mail_forward_remove_failed": "No s'han pogut eliminar el reenviament de correu «{mail:s}»",
"mailbox_used_space_dovecot_down": "S'ha d'engegar el servei de correu Dovecot per poder obtenir l'espai utilitzat per la bústia de correu",
"mail_unavailable": "Aquesta adreça de correu esta reservada i ha de ser atribuïda automàticament el primer usuari",
"maindomain_change_failed": "No s'ha pogut canviar el domini principal",
"maindomain_changed": "S'ha canviat el domini principal",
"migrate_tsig_end": "La migració cap a hmac-sha512 s'ha acabat",
"migrate_tsig_failed": "Ha fallat la migració del domini dyndns {domain} cap a hmac-sha512, anul·lant les modificacions. Error: {error_code} - {error}",
"migrate_tsig_start": "L'algoritme de generació de claus no es prou segur per a la signatura TSIG del domini «{domain}», començant la migració cap a un de més segur hmac-sha512",
"migrate_tsig_wait": "Esperar 3 minuts per a que el servidor dyndns tingui en compte la nova clau…",
"migrate_tsig_wait_2": "2 minuts…",
"migrate_tsig_wait_3": "1 minut…",
"migrate_tsig_wait_4": "30 segons…",
"migrate_tsig_not_needed": "Sembla que no s'utilitza cap domini dyndns, no és necessari fer cap migració!",
"migration_description_0001_change_cert_group_to_sslcert": "Canvia els permisos del grup dels certificats de «metronome»a «ssl-cert»",
"migration_description_0002_migrate_to_tsig_sha256": "Millora la seguretat de dyndns TSIG utilitzant SHA512 en lloc de MD5",
"migration_description_0003_migrate_to_stretch": "Actualització del sistema a Debian Stretch i YunoHost 3.0",
"migration_description_0004_php5_to_php7_pools": "Tornar a configurar els pools PHP per utilitzar PHP 7 en lloc de PHP 5",
"migration_description_0005_postgresql_9p4_to_9p6": "Migració de les bases de dades de postgresql 9.4 a 9.6",
"migration_description_0006_sync_admin_and_root_passwords": "Sincronitzar les contrasenyes admin i root",
"migration_description_0007_ssh_conf_managed_by_yunohost_step1": "La configuració SSH serà gestionada per YunoHost (pas 1, automàtic)",
"migration_description_0008_ssh_conf_managed_by_yunohost_step2": "La configuració SSH serà gestionada per YunoHost (pas 2, manual)",
"migration_description_0009_decouple_regenconf_from_services": "Desvincula el mecanisme regen-conf dels serveis",
"migration_description_0010_migrate_to_apps_json": "Elimina la appslists (desfasat) i utilitza la nova llista unificada «apps.json» en el seu lloc",
"migration_0003_backward_impossible": "La migració Stretch no és reversible.",
"migration_0003_start": "Ha començat la migració a Stretch. Els registres estaran disponibles a {logfile}.",
"migration_0003_patching_sources_list": "Modificant el fitxer sources.lists…",
"migration_0003_main_upgrade": "Començant l'actualització principal…",
"migration_0003_fail2ban_upgrade": "Començant l'actualització de fail2ban…",
"migration_0003_restoring_origin_nginx_conf": "El fitxer /etc/nginx/nginx.conf ha estat editat. La migració el tornarà al seu estat original... El fitxer anterior estarà disponible com a {backup_dest}.",
"migration_0003_yunohost_upgrade": "Començant l'actualització del paquet yunohost... La migració acabarà, però l'actualització actual es farà just després. Després de completar aquesta operació, pot ser que us hagueu de tornar a connectar a la web d'administració.",
"migration_0003_not_jessie": "La distribució Debian actual no és Jessie!",
"migration_0003_system_not_fully_up_to_date": "El vostre sistema no està completament actualitzat. S'ha de fer una actualització normal abans de fer la migració a Stretch.",
"migration_0003_still_on_jessie_after_main_upgrade": "Hi ha hagut un problema durant l'actualització principal: el sistema encara està amb Jessie!? Per investigar el problema, mireu el registres a {log}:s…",
"migration_0003_general_warning": "Tingueu en compte que la migració és una operació delicada. Tot i que l'equip de YunoHost a fet els possibles per revisar-la i provar-la, la migració pot provocar errors en parts del sistema o aplicacions.\n\nPer tant, recomanem:\n - Fer una còpia de seguretat de les dades o aplicacions importants. Més informació a https://yunohost.org/backup;\n - Sigueu pacient un cop llençada la migració: en funció de la connexió a internet i el maquinari, pot trigar fins a unes hores per actualitzar-ho tot.\n\nD'altra banda, el port per SMTP, utilitzat per clients de correu externs (com Thunderbird o K9-Mail) ha canviat de 465 (SSL/TLS) a 587 (STARTTLS). L'antic port 465 serà tancat automàticament i el nou port 587 serà obert en el tallafocs. Tots els usuaris *hauran* d'adaptar la configuració dels clients de correu en acord amb aquests canvis!",
"migration_0003_problematic_apps_warning": "Tingueu en compte que s'han detectat les aplicacions, possiblement, problemàtiques següents. Sembla que aquestes no s'han instal·lat des d'una applist o que no estan marcades com a «working». Per conseqüent, no podem garantir que segueixin funcionant després de l'actualització: {problematic_apps}",
"migration_0003_modified_files": "Tingueu en compte que s'han detectat els següents fitxers que han estat modificats manualment i podrien sobreescriure's al final de l'actualització: {manually_modified_files}",
"migration_0005_postgresql_94_not_installed": "Postgresql no està instal·lat en el sistema. No hi ha res per fer!",
"migration_0005_postgresql_96_not_installed": "S'ha trobat Postgresql 9.4 instal·lat, però no Postgresql 9.6!? Alguna cosa estranya a passat en el sistema :( …",
"migration_0005_not_enough_space": "No hi ha prou espai disponible en {path} per fer la migració en aquest moment :(.",
"migration_0006_disclaimer": "YunoHost esperar que les contrasenyes admin i root estiguin sincronitzades. Fent aquesta migració, la contrasenya root serà reemplaçada per la contrasenya admin.",
"migration_0007_cancelled": "YunoHost no ha pogut millorar la gestió de la configuració SSH.",
"migration_0007_cannot_restart": "No es pot reiniciar SSH després d'haver intentat cancel·lar la migració numero 6.",
"migration_0008_general_disclaimer": "Per millorar la seguretat del servidor, es recomana que sigui YunoHost qui gestioni la configuració SSH. La configuració SSH actual és diferent a la configuració recomanada. Si deixeu que YunoHost ho reconfiguri, la manera de connectar-se al servidor mitjançant SSH canviarà de la següent manera:",
"migration_0008_port": " - la connexió es farà utilitzant el port 22 en lloc del port SSH personalitzat actual. Es pot reconfigurar;",
"migration_0008_root": " - no es podrà connectar com a root a través de SSH. S'haurà d'utilitzar l'usuari admin per fer-ho;",
"migration_0008_dsa": " - es desactivarà la clau DSA. Per tant, es podria haver d'invalidar un missatge esgarrifós del client SSH, i tornar a verificar l'empremta digital del servidor;",
"migration_0008_warning": "Si heu entès els avisos i accepteu que YunoHost sobreescrigui la configuració actual, comenceu la migració. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.",
"migration_0008_no_warning": "No s'han detectat riscs importants per sobreescriure la configuració SSH, però no es pot estar del tot segur ;)! Si accepteu que YunoHost sobreescrigui la configuració actual, comenceu la migració. Sinó, podeu saltar-vos la migració, tot i que no està recomanat.",
"migration_0009_not_needed": "Sembla que ja s'ha fet aquesta migració? Ometent.",
"migrations_backward": "Migració cap enrere.",
"migrations_bad_value_for_target": "Nombre invàlid pel paràmetre target, els nombres de migració disponibles són 0 o {}",
"migrations_cant_reach_migration_file": "No s'ha pogut accedir als fitxers de migració al camí %s",
"migrations_current_target": "La migració objectiu és {}",
"migrations_error_failed_to_load_migration": "ERROR: no s'ha pogut carregar la migració {number} {name}",
"migrations_forward": "Migració endavant",
"migrations_list_conflict_pending_done": "No es pot utilitzar --previous i --done al mateix temps.",
"migrations_loading_migration": "Carregant la migració {number} {name}…",
"migrations_migration_has_failed": "La migració {number} {name} ha fallat amb l'excepció {exception}, cancel·lant",
"migrations_no_migrations_to_run": "No hi ha cap migració a fer",
"migrations_show_currently_running_migration": "Fent la migració {number} {name}…",
"migrations_show_last_migration": "L'última migració feta és {}",
"migrations_skip_migration": "Saltant migració {number} {name}…",
"migrations_success": "S'ha completat la migració {number} {name} amb èxit!",
"migrations_to_be_ran_manually": "La migració {number} {name} s'ha de fer manualment. Aneu a Eines > Migracions a la interfície admin, o executeu «yunohost tools migrations migrate».",
"migrations_need_to_accept_disclaimer": "Per fer la migració {number} {name}, heu d'acceptar aquesta clàusula de no responsabilitat:\n---\n{disclaimer}\n---\nSi accepteu fer la migració, torneu a executar l'ordre amb l'opció --accept-disclaimer.",
"monitor_disabled": "El monitoratge del servidor ha estat desactivat",
"monitor_enabled": "El monitoratge del servidor ha estat activat",
"monitor_glances_con_failed": "No s'ha pogut connectar al servidor Glances",
"monitor_not_enabled": "El monitoratge del servidor no està activat",
"monitor_period_invalid": "Període de temps invàlid",
"monitor_stats_file_not_found": "No s'ha pogut trobar el fitxer d'estadístiques",
"monitor_stats_no_update": "No hi ha dades de monitoratge per actualitzar",
"monitor_stats_period_unavailable": "No s'han trobat estadístiques per aquest període",
"mountpoint_unknown": "Punt de muntatge desconegut",
"mysql_db_creation_failed": "No s'ha pogut crear la base de dades MySQL",
"mysql_db_init_failed": "No s'ha pogut inicialitzar la base de dades MySQL",
"mysql_db_initialized": "S'ha inicialitzat la base de dades MySQL",
"network_check_mx_ko": "El registre DNS MX no està configurat",
"network_check_smtp_ko": "El tràfic de correu sortint (SMTP port 25) sembla que està bloquejat per la xarxa",
"network_check_smtp_ok": "El tràfic de correu sortint (SMTP port 25) no està bloquejat",
"new_domain_required": "S'ha d'especificar un nou domini principal",
"no_appslist_found": "No s'ha trobat cap llista d'aplicacions",
"no_internet_connection": "El servidor no està connectat a Internet",
"no_ipv6_connectivity": "La connectivitat IPv6 no està disponible",
"no_restore_script": "No hi ha cap script de restauració per l'aplicació «{app:s}»",
"not_enough_disk_space": "No hi ha prou espai en «{path:s}»",
"package_not_installed": "El paquet «{pkgname}» no està instal·lat",
"package_unexpected_error": "Hi ha hagut un error inesperat processant el paquet «{pkgname}»",
"package_unknown": "Paquet desconegut «{pkgname}»",
"packages_upgrade_critical_later": "Els paquets crítics ({packages:s}) seran actualitzats més tard",
"packages_upgrade_failed": "No s'han pogut actualitzar tots els paquets",
"path_removal_failed": "No s'ha pogut eliminar el camí {:s}",
"pattern_backup_archive_name": "Ha de ser un nom d'arxiu vàlid amb un màxim de 30 caràcters, compost per caràcters alfanumèrics i -_. exclusivament",
"pattern_domain": "Ha de ser un nom de domini vàlid (ex.: el-meu-domini.cat)",
"pattern_email": "Ha de ser una adreça de correu vàlida (ex.: algu@domini.cat)",
"pattern_firstname": "Ha de ser un nom vàlid",
"pattern_lastname": "Ha de ser un cognom vàlid",
"pattern_listname": "Ha d'estar compost per caràcters alfanumèrics i guió baix exclusivament",
"pattern_mailbox_quota": "Ha de ser una mida amb el sufix b/k/M/G/T o 0 per desactivar la quota",
"pattern_password": "Ha de tenir un mínim de 3 caràcters",
"pattern_port": "Ha de ser un número de port vàlid (i.e. 0-65535)",
"pattern_port_or_range": "Ha de ser un número de port vàlid (i.e. 0-65535) o un interval de ports (ex. 100:200)",
"pattern_positive_number": "Ha de ser un nombre positiu",
"pattern_username": "Ha d'estar compost per caràcters alfanumèrics en minúscula i guió baix exclusivament",
"pattern_password_app": "Les contrasenyes no haurien de tenir els següents caràcters: {forbidden_chars}",
"port_already_closed": "El port {port:d} ja està tancat per les connexions {ip_version:s}",
"port_already_opened": "El port {port:d} ja està obert per les connexions {ip_version:s}",
"port_available": "El port {port:d} està disponible",
"port_unavailable": "El port {port:d} no està disponible",
"recommend_to_add_first_user": "La post instal·lació s'ha acabat, però YunoHost necessita com a mínim un usuari per funcionar correctament, hauríeu d'afegir un usuari executant «yunohost user create $username» o amb la interfície d'administració.",
"regenconf_file_backed_up": "S'ha guardat una còpia de seguretat del fitxer de configuració «{conf}» a «{backup}»",
"regenconf_file_copy_failed": "No s'ha pogut copiar el nou fitxer de configuració «{new}» a «{conf}»",
"regenconf_file_kept_back": "S'espera que el fitxer de configuració «{conf}» sigui suprimit per regen-conf (categoria {category}) però s'ha mantingut.",
"regenconf_file_manually_modified": "El fitxer de configuració «{conf}» s'ha modificat manualment i no serà actualitzat",
"regenconf_file_manually_removed": "El fitxer de configuració «{conf}» s'ha suprimit manualment i no serà creat",
"regenconf_file_remove_failed": "No s'ha pogut eliminar el fitxer de configuració «{conf}»",
"regenconf_file_removed": "El fitxer de configuració «{conf}» ha estat suprimit",
"regenconf_file_updated": "El fitxer de configuració «{conf}» ha estat actualitzat",
"regenconf_now_managed_by_yunohost": "El fitxer de configuració «{conf}» serà gestionat per YunoHost a partir d'ara (categoria {category}).",
"regenconf_up_to_date": "La configuració ja està al dia per la categoria «{category}»",
"regenconf_updated": "La configuració ha estat actualitzada per la categoria «{category}»",
"regenconf_would_be_updated": "La configuració hagués estat actualitzada per la categoria «{category}»",
"regenconf_dry_pending_applying": "Verificació de la configuració pendent que s'hauria d'haver aplicat per la categoria «{category}»…",
"regenconf_failed": "No s'ha pogut regenerar la configuració per la/les categoria/es : {categories}",
"regenconf_pending_applying": "Aplicació de la configuració pendent per la categoria «{category}»…",
"restore_action_required": "S'ha d'especificar quelcom a restaurar",
"restore_already_installed_app": "Ja hi ha una aplicació instal·lada amb l'id «{app:s}»",
"restore_app_failed": "No s'ha pogut restaurar l'aplicació «{app:s}»",
"restore_cleaning_failed": "No s'ha pogut netejar el directori temporal de restauració",
"restore_complete": "Restauració completada",
"restore_confirm_yunohost_installed": "Esteu segur de voler restaurar un sistema ja instal·lat? [{answers:s}]",
"restore_extracting": "Extracció dels fitxers necessaris de l'arxiu…",
"restore_failed": "No s'ha pogut restaurar el sistema",
"restore_hook_unavailable": "L'script de restauració «{part:s}» no està disponible en el sistema i tampoc és en l'arxiu",
"restore_may_be_not_enough_disk_space": "Sembla que no hi ha prou espai disponible en el disc (espai lliure: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)",
"restore_mounting_archive": "Muntatge de l'arxiu a «{path:s}»",
"restore_not_enough_disk_space": "No hi ha prou espai disponible en el disc (espai lliure: {free_space:d} B, espai necessari: {needed_space:d} B, marge de seguretat: {margin:d} B)",
"restore_nothings_done": "No s'ha restaurat res",
"restore_removing_tmp_dir_failed": "No s'ha pogut eliminar un directori temporal antic",
"restore_running_app_script": "Execució de l'script de restauració de l'aplicació «{app:s}»…",
"restore_running_hooks": "Execució dels hooks de restauració…",
"restore_system_part_failed": "No s'ha pogut restaurar la part «{part:s}» del sistema",
"root_password_desynchronized": "S'ha canviat la contrasenya d'administració, però YunoHost no ha pogut propagar-ho cap a la contrasenya root!",
"root_password_replaced_by_admin_password": "La contrasenya root s'ha substituït per la contrasenya d'administració.",
"server_shutdown": "S'aturarà el servidor",
"server_shutdown_confirm": "S'aturarà el servidor immediatament, n'esteu segur? [{answers:s}]",
"server_reboot": "Es reiniciarà el servidor",
"server_reboot_confirm": "Es reiniciarà el servidor immediatament, n'esteu segur? [{answers:s}]",
"service_add_failed": "No s'ha pogut afegir el servei «{service:s}»",
"service_added": "S'ha afegit el servei «{service:s}»",
"service_already_started": "Ja s'ha iniciat el servei «{service:s}»",
"service_already_stopped": "Ja s'ha aturat el servei «{service:s}»",
"service_cmd_exec_failed": "No s'ha pogut executar l'ordre «{command:s}»",
"service_description_avahi-daemon": "permet accedir al servidor via yunohost.local en la xarxa local",
"service_description_dnsmasq": "gestiona la resolució del nom de domini (DNS)",
"service_description_dovecot": "permet als clients de correu accedir/recuperar correus (via IMAP i POP3)",
"service_description_fail2ban": "protegeix contra els atacs de força bruta i a altres atacs provinents d'Internet",
"service_description_glances": "monitora la informació del sistema en el servidor",
"service_description_metronome": "gestiona els comptes de missatgeria instantània XMPP",
"service_description_mysql": "guarda les dades de les aplicacions (base de dades SQL)",
"service_description_nginx": "serveix o permet l'accés a totes les pàgines web allotjades en el servidor",
"service_description_nslcd": "gestiona les connexions shell dels usuaris YunoHost",
"service_description_php7.0-fpm": "executa les aplicacions escrites en PHP amb nginx",
"service_description_postfix": "utilitzat per enviar i rebre correus",
"service_description_redis-server": "una base de dades especialitzada per l'accés ràpid a dades, files d'espera i comunicació entre programes",
"service_description_rmilter": "verifica diferents paràmetres en els correus",
"service_description_rspamd": "filtra el correu brossa, i altres funcionalitats relacionades al correu",
"service_description_slapd": "guarda el usuaris, dominis i informació relacionada",
"service_description_ssh": "permet la connexió remota al servidor via terminal (protocol SSH)",
"service_description_yunohost-api": "gestiona les interaccions entre la interfície web de YunoHost i el sistema",
"service_description_yunohost-firewall": "gestiona els ports de connexió oberts i tancats als serveis",
"service_disable_failed": "No s'han pogut deshabilitar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_disabled": "S'ha deshabilitat el servei {service:s}",
"service_enable_failed": "No s'ha pogut activar el servei «{service:s}»\n\nRegistres recents: {log:s}",
"service_enabled": "S'ha activat el servei {service:s}",
"service_no_log": "No hi ha cap registre pel servei «{service:s}»",
"service_regen_conf_is_deprecated": "«yunohost service regen-conf» està desfasat! Utilitzeu «yunohost tools regen-conf» en el seu lloc.",
"service_remove_failed": "No s'ha pogut eliminar el servei «{service:s}»",
"service_removed": "S'ha eliminat el servei «{service:s}»",
"service_reload_failed": "No s'ha pogut tornar a carregar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_reloaded": "S'ha tornat a carregar el servei «{service:s}»",
"service_restart_failed": "No s'ha pogut reiniciar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_restarted": "S'ha reiniciat el servei «{service:s}»",
"service_reload_or_restart_failed": "No s'ha pogut tornar a carregar o reiniciar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_reloaded_or_restarted": "S'ha tornat a carregar o s'ha reiniciat el servei «{service:s}»",
"service_start_failed": "No s'ha pogut iniciar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_started": "S'ha iniciat el servei «{service:s}»",
"service_status_failed": "No s'ha pogut determinar l'estat del servei «{service:s}»",
"service_stop_failed": "No s'ha pogut aturar el servei «{service:s}»\n\nRegistres recents: {logs:s}",
"service_stopped": "S'ha aturat el servei «{service:s}»",
"service_unknown": "Servei «{service:s}» desconegut",
"ssowat_conf_generated": "S'ha generat la configuració SSOwat",
"ssowat_conf_updated": "S'ha actualitzat la configuració SSOwat",
"ssowat_persistent_conf_read_error": "Error en llegir la configuració persistent de SSOwat: {error:s}. Modifiqueu el fitxer /etc/ssowat/conf.json.persistent per arreglar la sintaxi JSON",
"ssowat_persistent_conf_write_error": "Error guardant la configuració persistent de SSOwat: {error:s}. Modifiqueu el fitxer /etc/ssowat/conf.json.persistent per arreglar la sintaxi JSON",
"system_upgraded": "S'ha actualitzat el sistema",
"system_username_exists": "El nom d'usuari ja existeix en els usuaris de sistema",
"this_action_broke_dpkg": "Aquesta acció a trencat dpkg/apt (els gestors de paquets del sistema)… Podeu intentar resoldre el problema connectant-vos amb SSH i executant «sudo dpkg --configure -a».",
"tools_upgrade_at_least_one": "Especifiqueu --apps O --system",
"tools_upgrade_cant_both": "No es poden actualitzar tant el sistema com les aplicacions al mateix temps",
"tools_upgrade_cant_hold_critical_packages": "No es poden mantenir els paquets crítics…",
"tools_upgrade_cant_unhold_critical_packages": "No es poden deixar de mantenir els paquets crítics…",
"tools_upgrade_regular_packages": "Actualitzant els paquets «normals» (no relacionats amb YunoHost)…",
"tools_upgrade_regular_packages_failed": "No s'han pogut actualitzar els paquets següents: {packages_list}",
"tools_upgrade_special_packages": "Actualitzant els paquets «especials» (relacionats amb YunoHost)…",
"tools_upgrade_special_packages_explanation": "Aquesta acció s'acabarà, però l'actualització especial continuarà en segon pla. No comenceu cap altra acció al servidor en els pròxims ~10 minuts (depèn de la velocitat del maquinari). Un cop acabat, pot ser que us hagueu de tornar a connectar a la interfície d'administració. Els registres de l'actualització estaran disponibles a Eines > Registres (a la interfície d'administració) o amb «yunohost log list» (a la línia d'ordres).",
"tools_upgrade_special_packages_completed": "Actualització dels paquets YunoHost acabada!\nPremeu [Enter] per tornar a la línia d'ordres",
"unbackup_app": "L'aplicació «{app:s}» no serà guardada",
"unexpected_error": "Hi ha hagut un error inesperat: {error}",
"unit_unknown": "Unitat desconeguda «{unit:s}»",
"unlimit": "Sense quota",
"unrestore_app": "L'aplicació «{app:s} no serà restaurada",
"update_apt_cache_failed": "No s'ha pogut actualitzar la memòria cau d'APT (el gestor de paquets de Debian). Aquí teniu les línies de sources.list que poden ajudar-vos a identificar les línies problemàtiques:\n{sourceslist}",
"update_apt_cache_warning": "Hi ha hagut errors al actualitzar la memòria cau d'APT (el gestor de paquets de Debian). Aquí teniu les línies de sources.list que poden ajudar-vos a identificar les línies problemàtiques:\n{sourceslist}",
"updating_apt_cache": "Obtenció de les actualitzacions disponibles per als paquets del sistema…",
"updating_app_lists": "Obtenció de les actualitzacions disponibles per a les aplicacions…",
"upgrade_complete": "Actualització acabada",
"upgrading_packages": "Actualitzant els paquets…",
"upnp_dev_not_found": "No s'ha trobat cap dispositiu UPnP",
"upnp_disabled": "S'ha desactivat UPnP",
"upnp_enabled": "S'ha activat UPnP",
"upnp_port_open_failed": "No s'han pogut obrir els ports UPnP",
"user_created": "S'ha creat l'usuari",
"user_creation_failed": "No s'ha pogut crear l'usuari",
"user_deleted": "S'ha suprimit l'usuari",
"user_deletion_failed": "No s'ha pogut suprimir l'usuari",
"user_home_creation_failed": "No s'ha pogut crear la carpeta personal («home») de l'usuari",
"user_info_failed": "No s'ha pogut obtenir la informació de l'usuari",
"user_unknown": "Usuari desconegut: {user:s}",
"user_update_failed": "No s'ha pogut actualitzar l'usuari",
"user_updated": "S'ha actualitzat l'usuari",
"users_available": "Usuaris disponibles:",
"yunohost_already_installed": "YunoHost ja està instal·lat",
"yunohost_ca_creation_failed": "No s'ha pogut crear l'autoritat de certificació",
"yunohost_ca_creation_success": "S'ha creat l'autoritat de certificació local.",
"yunohost_configured": "S'ha configurat YunoHost",
"yunohost_installing": "Instal·lació de YunoHost…",
"yunohost_not_installed": "YunoHost no està instal·lat o no està instal·lat correctament. Executeu «yunohost tools postinstall»",
"apps_permission_not_found": "No s'ha trobat cap permís per les aplicacions instal·lades",
"apps_permission_restoration_failed": "Ha fallat el permís «{permission:s}» per la restauració de l'aplicació {app:s}",
"backup_permission": "Permís de còpia de seguretat per l'aplicació {app:s}",
"edit_group_not_allowed": "No teniu autorització per modificar el grup {group:s}",
"edit_permission_with_group_all_users_not_allowed": "No podeu modificar els permisos del grup «all_users», s'ha d'utlilitzar «yunohost user permission clear APP» o «yunohost user permission add APP -u USER».",
"error_when_removing_sftpuser_group": "Error intentant eliminar el gruo sftpusers",
"group_already_allowed": "El grup «{group:s}» ja té el permís «{permission:s}» activat per l'aplicació «{app:s}»",
"group_already_disallowed": "El grup «{group:s}» ja té els permisos «{permission:s}» desactivats per l'aplicació «{app:s}»",
"group_name_already_exist": "El grup {name:s} ja existeix",
"group_created": "S'ha creat el grup «{group}»",
"group_creation_failed": "No s'ha pogut crear el grup «{group}»",
"group_deleted": "S'ha eliminat el grup «{group}»",
"group_deletion_failed": "No s'ha pogut eliminar el grup «{group}»",
"group_deletion_not_allowed": "El grup {group:s} no es pot eliminar manualment.",
"group_info_failed": "Ha fallat la informació del grup",
"group_unknown": "Grup {group:s} desconegut",
"group_updated": "S'ha actualitzat el grup «{group}»",
"group_update_failed": "No s'ha pogut actualitzat el grup «{group}»",
"log_permission_add": "Afegir el permís «{}» per l'aplicació «{}»",
"log_permission_remove": "Suprimir el permís «{}»",
"log_permission_update": "Actualitzar el permís «{}» per l'aplicació «{}»",
"log_user_group_add": "Afegir grup «{}»",
"log_user_group_delete": "Eliminar grup «{}»",
"log_user_group_update": "Actualitzar grup «{}»",
"log_user_permission_add": "Actualitzar el permís «{}»",
"log_user_permission_remove": "Actualitzar el permís «{}»",
"mailbox_disabled": "La bústia de correu està desactivada per als usuaris {user:s}",
"migration_description_0011_setup_group_permission": "Configurar el grup d'usuaris i els permisos per les aplicacions i els serveis",
"migration_0011_backup_before_migration": "Creant una còpia de seguretat de la base de dades LDAP i la configuració de les aplicacions abans d'efectuar la migració.",
"migration_0011_can_not_backup_before_migration": "No s'ha pogut fer la còpia de seguretat abans de la migració. No s'ha pogut fer la migració. Error: {error:s}",
"migration_0011_create_group": "Creant un grup per a cada usuari…",
"migration_0011_done": "Migració completa. Ja podeu gestionar grups d'usuaris.",
"migration_0011_LDAP_config_dirty": "Sembla que heu modificat manualment la configuració LDAP. Per fer aquesta migració s'ha d'actualitzar la configuració LDAP.\nGuardeu la configuració actual, reinicieu la configuració original amb l'ordre «yunohost tools regen-conf -f» i torneu a intentar la migració",
"migration_0011_LDAP_update_failed": "Ha fallat l'actualització de LDAP. Error: {error:s}",
"migration_0011_migrate_permission": "Fent la migració dels permisos de la configuració de les aplicacions a LDAP…",
"migration_0011_migration_failed_trying_to_rollback": "La migració ha fallat … s'intenta tornar el sistema a l'estat anterior.",
"migration_0011_rollback_success": "S'ha tornat el sistema a l'estat anterior.",
"migration_0011_update_LDAP_database": "Actualitzant la base de dades LDAP…",
"migration_0011_update_LDAP_schema": "Actualitzant l'esquema LDAP…",
"need_define_permission_before": "Heu de tornar a redefinir els permisos utilitzant «yunohost user permission add -u USER» abans d'eliminar un grup permès",
"permission_already_clear": "Ja s'ha donat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_already_exist": "El permís «{permission:s}» ja existeix per l'aplicació {app:s}",
"permission_created": "S'ha creat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_creation_failed": "La creació del permís ha fallat",
"permission_deleted": "S'ha eliminat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_deletion_failed": "L'eliminació del permís «{permission:s}» per l'aplicació {app:s} ha fallat",
"permission_not_found": "No s'ha trobat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_name_not_valid": "El nom del permís «{permission:s}» no és vàlid",
"permission_update_failed": "L'actualització del permís ha fallat",
"permission_generated": "S'ha actualitzat la base de dades del permís",
"permission_updated": "S'ha actualitzat el permís «{permission:s}» per l'aplicació {app:s}",
"permission_update_nothing_to_do": "No hi ha cap permís per actualitzar",
"remove_main_permission_not_allowed": "No es pot eliminar el permís principal",
"remove_user_of_group_not_allowed": "No es pot eliminar l'usuari {user:s} del grup {group:s}",
"system_groupname_exists": "El nom de grup ja existeix en el sistema de grups",
"tools_update_failed_to_app_fetchlist": "No s'ha pogut actualitzar la llista d'aplicacions de YunoHost a causa de: {error}",
"user_already_in_group": "L'usuari {user:s} ja és en el grup {group:s}",
"user_not_in_group": "L'usuari {user:s} no és en el grup {group:s}"
}

View file

@ -30,7 +30,7 @@
"app_no_upgrade": "No apps to upgrade",
"app_not_upgraded": "The following apps were not upgraded: {apps}",
"app_not_correctly_installed": "{app:s} seems to be incorrectly installed",
"app_not_installed": "{app:s} is not installed",
"app_not_installed": "The application '{app:s}' is not installed. Here is the list of all installed apps: {all_apps}",
"app_not_properly_removed": "{app:s} has not been properly removed",
"app_package_need_update": "The app {app} package needs to be updated to follow YunoHost changes",
"app_removed": "{app:s} has been removed",
@ -174,7 +174,7 @@
"domain_dyndns_invalid": "Invalid domain to use with DynDNS",
"domain_dyndns_root_unknown": "Unknown DynDNS root domain",
"domain_exists": "Domain already exists",
"domain_hostname_failed": "Failed to set new hostname",
"domain_hostname_failed": "Failed to set new hostname. This might cause issue later (not sure about it... it might be fine).",
"domain_uninstall_app_first": "One or more apps are installed on this domain. Please uninstall them before proceeding to domain removal",
"domain_unknown": "Unknown domain",
"domain_zone_exists": "DNS zone file already exists",
@ -185,7 +185,7 @@
"dyndns_could_not_check_provide": "Could not check if {provider:s} can provide {domain:s}.",
"dyndns_could_not_check_available": "Could not check if {domain:s} is available on {provider:s}.",
"dyndns_cron_installed": "The DynDNS cron job has been installed",
"dyndns_cron_remove_failed": "Unable to remove the DynDNS cron job",
"dyndns_cron_remove_failed": "Unable to remove the DynDNS cron job because: {error}",
"dyndns_cron_removed": "The DynDNS cron job has been removed",
"dyndns_ip_update_failed": "Unable to update IP address on DynDNS",
"dyndns_ip_updated": "Your IP address has been updated on DynDNS",
@ -285,7 +285,6 @@
"log_permission_update": "Update permission '{}' for app '{}'",
"log_selfsigned_cert_install": "Install self signed certificate on '{}' domain",
"log_letsencrypt_cert_renew": "Renew '{}' Let's encrypt certificate",
"log_service_enable": "Enable '{}' service",
"log_regen_conf": "Regenerate system configurations '{}'",
"log_user_create": "Add '{}' user",
"log_user_delete": "Delete '{}' user",
@ -331,6 +330,7 @@
"migration_description_0009_decouple_regenconf_from_services": "Decouple the regen-conf mechanism from services",
"migration_description_0010_migrate_to_apps_json": "Remove deprecated appslists and use the new unified 'apps.json' list instead",
"migration_description_0011_setup_group_permission": "Setup user group and setup permission for apps and services",
"migration_description_0012_postgresql_password_to_md5_authentication": "Force postgresql authentication to use md5 for local connections",
"migration_0003_start": "Starting migration to Stretch. The logs will be available in {logfile}.",
"migration_0003_patching_sources_list": "Patching the sources.lists…",
"migration_0003_main_upgrade": "Starting main upgrade…",

View file

@ -32,5 +32,12 @@
"service_description_yunohost-api": "mastrumas interagojn inter la YunoHost retinterfaco kaj la sistemo",
"service_description_yunohost-firewall": "mastrumas malfermitajn kaj fermitajn konektejojn al servoj",
"service_disable_failed": "Neebla malaktivigi servon '{service:s}'\n\nFreŝaj protokoloj de la servo : {logs:s}",
"service_disabled": "Servo '{service:s}' estas malaktivigita"
"service_disabled": "Servo '{service:s}' estas malaktivigita",
"action_invalid": "Nevalida ago « {action:s} »",
"admin_password": "Pasvorto de la estro",
"admin_password_too_long": "Bonvolu elekti pasvorton pli mallonga ol 127 signoj",
"already_up_to_date": "Neniu estas farenda! Ĉiu jam estas ĝisdata!",
"app_argument_choice_invalid": "Nevalida elekto por argumento « {name:s} », ĝi devas esti unu el {choices:s}",
"app_argument_invalid": "Nevalida valoro por argumento « {name:s} » : {error:s}",
"app_change_url_failed_nginx_reload": "Reŝargi nginx malsuksesis. Jen la eligo de « nginx -t » :\n{nginx_errors:s}"
}

View file

@ -17,7 +17,7 @@
"app_manifest_invalid": "Manifeste dapplication incorrect : {error}",
"app_no_upgrade": "Aucune application à mettre à jour",
"app_not_correctly_installed": "{app:s} semble être mal installé",
"app_not_installed": "{app:s} nest pas installé",
"app_not_installed": "L'application « {app:s} » nest pas installée. Voici la liste des applications installées: {all_apps}",
"app_not_properly_removed": "{app:s} na pas été supprimé correctement",
"app_package_need_update": "Le paquet de lapplication {app} doit être mis à jour pour être en adéquation avec les changements de YunoHost",
"app_recent_version_required": "{app:s} nécessite une version plus récente de YunoHost",
@ -120,7 +120,7 @@
"ldap_initialized": "Lannuaire LDAP a été initialisé",
"license_undefined": "indéfinie",
"mail_alias_remove_failed": "Impossible de supprimer lalias de courriel '{mail:s}'",
"mail_domain_unknown": "Le domaine « {domain:s} » du courriel est inconnu",
"mail_domain_unknown": "Le domaine '{domain:s}' pour l'adresse de courriel est inconnu",
"mail_forward_remove_failed": "Impossible de supprimer le courriel de transfert '{mail:s}'",
"maindomain_change_failed": "Impossible de modifier le domaine principal",
"maindomain_changed": "Le domaine principal a été modifié",
@ -281,7 +281,7 @@
"certmanager_http_check_timeout": "Expiration du délai lorsque le serveur a essayé de se contacter lui-même via HTTP en utilisant l'adresse IP public {ip:s} du domaine {domain:s}. Vous rencontrez peut-être un problème dhairpinning ou alors le pare-feu/routeur en amont de votre serveur est mal configuré.",
"certmanager_couldnt_fetch_intermediate_cert": "Expiration du délai lors de la tentative de récupération du certificat intermédiaire depuis Lets Encrypt. Linstallation ou le renouvellement du certificat a été annulé. Veuillez réessayer plus tard.",
"appslist_retrieve_bad_format": "Le fichier récupéré pour la liste dapplications {appslist:s} nest pas valide",
"domain_hostname_failed": "Échec de la création dun nouveau nom dhôte",
"domain_hostname_failed": "Échec de lutilisation dun nouveau nom dhôte. Cela pourrait causer des soucis plus tard (mais ce nest pas sûr… peut-être que ça nen causera pas).",
"yunohost_ca_creation_success": "Lautorité de certification locale a été créée.",
"appslist_name_already_tracked": "Il y a déjà une liste dapplications enregistrée avec le nom {name:s}.",
"appslist_url_already_tracked": "Il y a déjà une liste dapplications enregistrée avec lURL {url:s}.",
@ -370,7 +370,7 @@
"dyndns_domain_not_provided": "Le fournisseur DynDNS {provider:s} ne peut pas fournir le domaine {domain:s}.",
"app_make_default_location_already_used": "Impossible de configurer lapplication '{app}' par défaut pour le domaine {domain} car il est déjà utilisé par l'application '{other_app}'",
"app_upgrade_app_name": "Mise à jour de lapplication {app} …",
"backup_output_symlink_dir_broken": "Vous avez un lien symbolique cassé à la place de votre dossier darchives « {path:s} ». Vous pourriez avoir une configuration personnalisée pour sauvegarder vos données sur un autre système de fichiers, dans ce cas, vous avez probablement oublié de monter ou de connecter votre disque dur ou votre clé USB.",
"backup_output_symlink_dir_broken": "Vous avez un lien symbolique cassé à la place de votre dossier darchives « {path:s} ». Vous pourriez avoir une configuration personnalisée pour sauvegarder vos données sur un autre système de fichiers, dans ce cas vous avez probablement oublié de monter ou de connecter votre disque dur ou votre clé USB.",
"migrate_tsig_end": "La migration à hmac-sha512 est terminée",
"migrate_tsig_failed": "La migration du domaine DynDNS {domain} à hmac-sha512 a échoué. Annulation des modifications. Erreur : {error_code} - {error}",
"migrate_tsig_start": "Lalgorithme de génération des clefs nest pas suffisamment sécurisé pour la signature TSIG du domaine '{domain}', lancement de la migration vers hmac-sha512 qui est plus sécurisé",
@ -392,7 +392,7 @@
"migration_0003_yunohost_upgrade": "Démarrage de la mise à niveau du paquet YunoHost. La migration se terminera, mais la mise à jour réelle aura lieu immédiatement après. Une fois cette opération terminée, vous pourriez avoir à vous reconnecter à ladministration via le panel web.",
"migration_0003_not_jessie": "La distribution Debian actuelle nest pas Jessie !",
"migration_0003_system_not_fully_up_to_date": "Votre système nest pas complètement à jour. Veuillez mener une mise à jour classique avant de lancer à migration à Stretch.",
"migration_0003_still_on_jessie_after_main_upgrade": "Quelque chose sest mal passé pendant la mise à niveau principale : le système est toujours sur Jessie !? Pour investiguer sur problème, veuillez regarder les journaux {log}:s…",
"migration_0003_still_on_jessie_after_main_upgrade": "Quelque chose sest mal passé pendant la mise à niveau principale : le système est toujours sur Debian Jessie !? Pour investiguer sur le problème, veuillez regarder les journaux {log}:s …",
"migration_0003_general_warning": "Veuillez noter que cette migration est une opération délicate. Si léquipe YunoHost a fait de son mieux pour la relire et la tester, la migration pourrait tout de même casser des parties de votre système ou de vos applications.\n\nEn conséquence, nous vous recommandons :\n - de lancer une sauvegarde de vos données ou applications critiques. Plus dinformations sur https://yunohost.org/backup ;\n - dêtre patient après avoir lancé la migration : selon votre connexion internet et matériel, cela pourrait prendre jusquà quelques heures pour que tout soit à niveau.\n\nEn outre, le port SMTP utilisé par les clients de messagerie externes comme (Thunderbird ou K9-Mail) a été changé de 465 (SSL/TLS) à 587 (STARTTLS). Lancien port 465 sera automatiquement fermé et le nouveau port 587 sera ouvert dans le pare-feu. Vous et vos utilisateurs *devront* adapter la configuration de vos clients de messagerie en conséquence !",
"migration_0003_problematic_apps_warning": "Veuillez noter que des applications possiblement problématiques ont été détectées. Il semble quelles naient pas été installées depuis une liste dapplication ou quelles ne soit pas marquées comme « fonctionnelles ». En conséquence, nous ne pouvons pas garantir quelles fonctionneront après la mise à niveau : {problematic_apps}",
"migration_0003_modified_files": "Veuillez noter que les fichiers suivants ont été détectés comme modifiés manuellement et pourraient être écrasés à la fin de la mise à niveau : {manually_modified_files}",
@ -418,7 +418,7 @@
"service_description_yunohost-api": "permet les interactions entre linterface web de YunoHost et le système",
"service_description_yunohost-firewall": "gère l'ouverture et la fermeture des ports de connexion aux services",
"experimental_feature": "Attention : cette fonctionnalité est expérimentale et ne doit pas être considérée comme stable, vous ne devriez pas lutiliser à moins que vous ne sachiez ce que vous faites.",
"log_corrupted_md_file": "Le fichier yaml de metadata associé aux logs est corrompu : '{md_file}'",
"log_corrupted_md_file": "Le fichier yaml de métadonnées associé aux logs est corrompu : '{md_file}'\nErreur : {error}",
"log_category_404": "Le journal de la catégorie '{category}' nexiste pas",
"log_link_to_log": "Journal historisé complet de cette opération : '<a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\"> {desc} </a>'",
"log_help_to_get_log": "Pour voir le journal historisé de cette opération '{desc}', utilisez la commande 'yunohost log display {name}'",
@ -462,16 +462,16 @@
"log_tools_shutdown": "Éteindre votre serveur",
"log_tools_reboot": "Redémarrer votre serveur",
"mail_unavailable": "Cette adresse de courriel est réservée et doit être automatiquement attribuée au tout premier utilisateur",
"migration_description_0004_php5_to_php7_pools": "Reconfiguration des pools PHP pour utiliser PHP 7 au lieu de PHP 5",
"migration_description_0004_php5_to_php7_pools": "Reconfiguration des groupes PHP pour utiliser PHP 7 au lieu de PHP 5",
"migration_description_0005_postgresql_9p4_to_9p6": "Migration des bases de données de PostgreSQL 9.4 vers PostgreSQL 9.6",
"migration_0005_postgresql_94_not_installed": "PostgreSQL na pas été installé sur votre système. Rien à faire !",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 a été trouvé et installé, mais pas PostgreSQL 9.6 !? Quelque chose détrange a dû arriver à votre système :(",
"migration_0005_postgresql_96_not_installed": "PostgreSQL 9.4 a été trouvé et installé, mais pas PostgreSQL 9.6 !? Quelque chose détrange a dû arriver à votre système :(",
"migration_0005_not_enough_space": "Il ny a pas assez despace libre de disponible sur {path} pour lancer maintenant la migration :(.",
"recommend_to_add_first_user": "La post-installation est terminée mais YunoHost a besoin dau moins un utilisateur pour fonctionner correctement. Vous devez en ajouter un en utilisant 'yunohost user create $nomdutilisateur' ou bien via linterface dadministration web.",
"recommend_to_add_first_user": "La post-installation est terminée mais YunoHost a besoin dau moins un utilisateur pour fonctionner correctement. Vous devez en ajouter un en utilisant la commande 'yunohost user create $nomdutilisateur' ou bien via linterface dadministration web.",
"service_description_php7.0-fpm": "exécute des applications écrites en PHP avec Nginx",
"users_available": "Liste des utilisateurs disponibles :",
"good_practices_about_admin_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe dadministration. Le mot de passe doit comporter au moins 8 caractères bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).",
"good_practices_about_user_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe utilisateur. Le mot de passe doit comporter au moins 8 caractères bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).",
"good_practices_about_user_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe utilisateur. Le mot de passe doit comporter au moins 8 caractères - bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères tels que : majuscules, minuscules, chiffres et caractères spéciaux.",
"migration_description_0006_sync_admin_and_root_passwords": "Synchroniser les mots de passe admin et root",
"migration_0006_disclaimer": "YunoHost sattendra désormais à ce que les mots de passe admin et root soient synchronisés. En exécutant cette migration, votre mot de passe root sera remplacé par le mot de passe administrateur.",
"migration_0006_done": "Votre mot de passe root a été remplacé par celui de votre adminitrateur.",
@ -481,7 +481,7 @@
"password_too_simple_3": "Le mot de passe doit comporter au moins 8 caractères et contenir des chiffres, des majuscules, des minuscules et des caractères spéciaux",
"password_too_simple_4": "Le mot de passe doit comporter au moins 12 caractères et contenir des chiffres, des majuscules, des minuscules et des caractères spéciaux",
"root_password_desynchronized": "Le mot de passe administrateur a été changé, mais YunoHost na pas pu le propager au mot de passe root !",
"aborting": "Interruption.",
"aborting": "Opération annulée.",
"app_not_upgraded": "Les applications suivantes n'ont pas été mises à jour : {apps}",
"app_start_install": "Installation de l'application {app} …",
"app_start_remove": "Suppression de l'application {app} …",
@ -523,7 +523,7 @@
"service_reload_or_restart_failed": "Impossible de recharger ou de redémarrer le service '{service:s}'\n\nJournaux historisés récents de ce service : {logs:s}",
"service_reloaded_or_restarted": "Le service '{service:s}' a été rechargé ou redémarré",
"this_action_broke_dpkg": "Cette action a laissé des paquets non configurés par dpkg/apt (les gestionnaires de paquets système). Vous pouvez essayer de résoudre ce problème en vous connectant via SSH et en exécutant `sudo dpkg --configure -a`.",
"app_action_cannot_be_ran_because_required_services_down": "Cette application requiert certains services qui sont actuellement en pannes. Avant de continuer, vous devriez essayer de redémarrer les services suivant (et éventuellement rechercher pourquoi ils sont en panne) : {services}",
"app_action_cannot_be_ran_because_required_services_down": "Cette application requiert certains services qui sont actuellement arrêtés. Avant de continuer, vous devriez essayer de redémarrer les services suivants (et éventuellement rechercher pourquoi ils sont arrêtés) : {services}",
"admin_password_too_long": "Choisissez un mot de passe plus court que 127 caractères",
"log_regen_conf": "Régénérer les configurations du système '{}'",
"migration_0009_not_needed": "Cette migration semble avoir déjà été jouée ? On l'ignore.",
@ -535,26 +535,58 @@
"regenconf_file_removed": "Le fichier de configuration '{conf}' a été supprimé",
"regenconf_file_updated": "Le fichier de configuration '{conf}' a été mis à jour",
"regenconf_now_managed_by_yunohost": "Le fichier de configuration '{conf}' est maintenant géré par YunoHost (catégorie {category}).",
"regenconf_up_to_date": "La configuration est déjà à jour pour la catégorie « {catégorie} ».",
"regenconf_up_to_date": "La configuration est déjà à jour pour la catégorie '{category}'",
"already_up_to_date": "Il n'y a rien à faire ! Tout est déjà à jour !",
"global_settings_setting_security_nginx_compatibility": "Compatibilité vs. compromis sécuritaire pour le serveur web nginx. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
"global_settings_setting_security_ssh_compatibility": "Compatibilité vs. compromis sécuritaire pour le serveur SSH. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
"global_settings_setting_security_postfix_compatibility": "Compatibilité vs. compromis sécuritaire pour le serveur Postfix. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
"global_settings_setting_security_nginx_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur web nginx. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
"global_settings_setting_security_ssh_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur SSH. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
"global_settings_setting_security_postfix_compatibility": "Compatibilité versus compromis sécuritaire pour le serveur Postfix. Affecte les cryptogrammes (et d'autres aspects liés à la sécurité)",
"migration_description_0009_decouple_regenconf_from_services": "Dissocier le mécanisme « regen-conf » des services",
"migration_description_0010_migrate_to_apps_json": "Supprimer les listes d'applications obsolètes et utiliser la nouvelle liste unifiée « apps.json » à la place",
"regenconf_file_kept_back": "Le fichier de configuration « {conf} » s'attendait à être supprimé par « regen-conf » (catégorie {catégorie}) mais a été conservé.",
"regenconf_updated": "La configuration a été mise à jour pour la catégorie « {category} ».",
"regenconf_would_be_updated": "La configuration aurait dû être mise à jour pour la catégorie « {category} ».",
"regenconf_dry_pending_applying": "Vérification de la configuration en attente qui aurait été appliquée pour la catégorie « {category} ».",
"regenconf_failed": "Impossible de régénérer la configuration pour la ou les catégorie(s) : « {categories} ».",
"regenconf_pending_applying": "Appliquer la configuration en attente pour la catégorie « {catégorie} »…",
"service_regen_conf_is_deprecated": "« yunohost service regen-conf » est obsolète ! Veuillez plutôt utiliser « yunohost tools regen-conf ».",
"migration_description_0010_migrate_to_apps_json": "Supprimer les listes d'applications obsolètes et utiliser la nouvelle liste unifiée 'apps.json' à la place",
"regenconf_file_kept_back": "Le fichier de configuration '{conf}' devait être supprimé par « regen-conf » (catégorie {category}) mais a été conservé.",
"regenconf_updated": "La configuration a été mise à jour pour la catégorie '{category}'",
"regenconf_would_be_updated": "La configuration aurait dû être mise à jour pour la catégorie '{category}'",
"regenconf_dry_pending_applying": "Vérification de la configuration en attente qui aurait été appliquée pour la catégorie '{category}' …",
"regenconf_failed": "Impossible de régénérer la configuration pour la ou les catégorie(s) : '{categories}'",
"regenconf_pending_applying": "Applique la configuration en attente pour la catégorie '{category}' …",
"service_regen_conf_is_deprecated": "'yunohost service regen-conf' est obsolète ! Veuillez plutôt utiliser 'yunohost tools regen-conf' à la place.",
"tools_upgrade_at_least_one": "Veuillez spécifier --apps OU --system",
"tools_upgrade_cant_both": "Impossible de mettre à niveau le système et les applications en même temps",
"tools_upgrade_cant_hold_critical_packages": "Impossibilité de maintenir les paquets critiques...",
"tools_upgrade_regular_packages": "Mise à jour des paquets « normaux » (non liés a YunoHost) ...",
"tools_upgrade_regular_packages": "Mise à jour des paquets du système (non liés a YunoHost) ...",
"tools_upgrade_regular_packages_failed": "Impossible de mettre à jour les paquets suivants : {packages_list}",
"tools_upgrade_special_packages": "Mise à jour des paquets « spéciaux » (liés a YunoHost) ...",
"tools_upgrade_special_packages": "Mise à jour des paquets 'spécifiques' (liés a YunoHost) ...",
"tools_upgrade_special_packages_completed": "La mise à jour des paquets de YunoHost est finie!\nPressez [Entrée] pour revenir à la ligne de commande",
"updating_app_lists": "Récupération des mises à jour des applications disponibles…"
"updating_app_lists": "Récupération des mises à jour des applications disponibles…",
"dpkg_lock_not_available": "Cette commande ne peut être lancée maintenant car il semblerai qu'un autre programme utilise déjà le verrou dpkg du gestionnaire de paquets du système",
"tools_upgrade_cant_unhold_critical_packages": "Impossible de dé-marquer les paquets critiques ...",
"tools_upgrade_special_packages_explanation": "Cette opération prendra fin mais la mise à jour spécifique continuera en arrière-plan. Veuillez ne pas lancer d'autre action sur votre serveur dans les 10 prochaines minutes (en fonction de la vitesse de votre matériel). Une fois que c'est fait, vous devrez peut-être vous reconnecter sur le panel d'administration web. Le journal de la mise à jour sera disponible dans Outils > Log (dans le panel d'administration web) ou dans la liste des journaux YunoHost (en ligne de commande).",
"update_apt_cache_failed": "Impossible de mettre à jour le cache APT (gestionnaire de paquets Debian). Voici un extrait du fichier sources.list qui pourrait vous aider à identifier les lignes problématiques :\n{sourceslist}",
"update_apt_cache_warning": "Des erreurs se sont produites lors de la mise à jour du cache APT (gestionnaire de paquets Debian). Voici un extrait des lignes du fichier sources.list qui pourrait vous aider à identifier les lignes problématiques :\n{sourceslist}",
"apps_permission_not_found": "Aucune permission trouvée pour les applications installées",
"apps_permission_restoration_failed": "L'autorisation '{permission:s}' pour la restauration de l'application {app:s} a échoué",
"backup_permission": "Autorisation de sauvegarde pour l'application {app:s}",
"edit_group_not_allowed": "Vous n'êtes pas autorisé à modifier le groupe {group:s}",
"error_when_removing_sftpuser_group": "Erreur en essayant de supprimer le groupe sftpusers",
"group_created": "Le groupe '{group}' a créé avec succès",
"group_deleted": "Le groupe '{group}' a été supprimé",
"group_deletion_not_allowed": "Le groupe {group:s} ne peut pas être supprimé manuellement.",
"group_info_failed": "L'information sur le groupe a échoué",
"group_unknown": "Le groupe {group:s} est inconnu",
"group_updated": "Le groupe '{group}' a été mis à jour",
"group_update_failed": "La mise à jour du groupe '{group}' a échoué",
"group_already_allowed": "Le groupe '{group:s}' a déjà la permission '{permission:s}' activée pour l'application '{app:s}'",
"group_already_disallowed": "Le groupe '{group:s}' a déjà la permission '{permission:s}' désactivée pour l'application '{app:s}'",
"group_name_already_exist": "Le groupe {name:s} existe déjà",
"group_creation_failed": "Échec de la création du groupe '{group}'",
"group_deletion_failed": "Échec de la suppression du groupe '{group}'",
"edit_permission_with_group_all_users_not_allowed": "Vous n'êtes pas autorisé à modifier les permissions pour le groupe 'all_users', utilisez'yunohost user permission clear APP' ou 'yunohost user permission add APP -u USER'.",
"log_permission_add": "Ajouter l'autorisation '{}' pour l'application '{}'",
"log_permission_remove": "Supprimer l'autorisation '{}'",
"log_permission_update": "Mise à jour de l'autorisation '{}' pour l'application '{}'",
"log_user_group_add": "Ajouter '{}' au groupe",
"log_user_group_delete": "Supprimer le groupe '{}'",
"log_user_group_update": "Mettre à jour '{}' pour le groupe",
"log_user_permission_add": "Mettre à jour l'autorisation pour '{}'",
"log_user_permission_remove": "Mettre à jour l'autorisation pour '{}'",
"mailbox_disabled": "La boîte aux lettres est désactivée pour l'utilisateur {user:s}"
}

View file

@ -7,16 +7,16 @@
"installation_complete": "Installacion acabada",
"app_id_invalid": "Id daplicacion incorrècte",
"app_install_files_invalid": "Fichièrs dinstallacion incorrèctes",
"app_no_upgrade": "Pas cap daplicacion de metre a jorn",
"app_no_upgrade": "Pas cap daplicacion dactualizar",
"app_not_correctly_installed": "{app:s} sembla pas ben installat",
"app_not_installed": "{app:s} es pas installat",
"app_not_installed": "Laplicacion {app:s} es pas installat. Vaquí la lista de las aplicacions installadas: {all_apps}",
"app_not_properly_removed": "{app:s} es pas estat corrèctament suprimit",
"app_removed": "{app:s} es estat suprimit",
"app_unknown": "Aplicacion desconeguda",
"app_upgrade_app_name": "Mesa a jorn de laplicacion {app}…",
"app_upgrade_failed": "Impossible de metre a jorn {app:s}",
"app_upgrade_some_app_failed": "Daplicacions se pòdon pas metre a jorn",
"app_upgraded": "{app:s} es estat mes a jorn",
"app_upgrade_app_name": "Actualizacion de laplicacion {app}…",
"app_upgrade_failed": "Impossible dactualizar {app:s}",
"app_upgrade_some_app_failed": "Daplicacions se pòdon pas actualizar",
"app_upgraded": "{app:s} es estada actualizada",
"appslist_fetched": "Recuperacion de la lista daplicacions {appslist:s} corrèctament realizada",
"appslist_migrating": "Migracion de la lista daplicacion{appslist:s}…",
"appslist_name_already_tracked": "I a ja una lista daplicacion enregistrada amb lo nom {name:s}.",
@ -51,7 +51,7 @@
"app_incompatible": "Laplicacion {app} es pas compatibla amb vòstra version de YunoHost",
"app_location_already_used": "Laplicacion « {app}»es ja installada a aqueste emplaçament ({path})",
"app_manifest_invalid": "Manifest daplicacion incorrècte: {error}",
"app_package_need_update": "Lo paquet de laplicacion {app} deu èsser mes a jorn per seguir los cambiaments de YunoHost",
"app_package_need_update": "Lo paquet de laplicacion {app} deu èsser actualizat per poder seguir los cambiaments de YunoHost",
"app_requirements_checking": "Verificacion dels paquets requesits per {app}…",
"app_sources_fetch_failed": "Recuperacion dels fichièrs fonts impossibla, lURL es corrècta?",
"app_unsupported_remote_type": "Lo tipe alonhat utilizat per laplicacion es pas suportat",
@ -67,8 +67,8 @@
"backup_creating_archive": "Creacion de larchiu de salvagarda…",
"backup_creation_failed": "Impossible de crear la salvagarda",
"app_already_installed_cant_change_url": "Aquesta aplicacion es ja installada. Aquesta foncion pòt pas simplament cambiar lURL. Agachatz «app changeurl »ses disponible.",
"app_change_no_change_url_script": "Laplicacion {app_name:s} pren pas en compte lo cambiament dURL, poiretz aver de la metre a jorn.",
"app_change_url_no_script": "Laplicacion {app_name:s} pren pas en compte lo cambiament dURL, benlèu que vos cal la metre a jorn.",
"app_change_no_change_url_script": "Laplicacion {app_name:s} pren pas en compte lo cambiament dURL, poiretz aver de lactualizar.",
"app_change_url_no_script": "Laplicacion {app_name:s} pren pas en compte lo cambiament dURL, benlèu que vos cal lactualizar.",
"app_make_default_location_already_used": "Impossible de configurar laplicacion « {app} »per defaut pel domeni {domain} perque es ja utilizat per laplicacion {other_app}",
"app_location_install_failed": "Impossible dinstallar laplicacion a aqueste emplaçament per causa de conflicte amb laplicacion {other_app} ques ja installada sus {other_path}",
"app_location_unavailable": "Aquesta URL es pas disponibla o en conflicte amb una aplicacion existenta:\n{apps:s}",
@ -148,7 +148,7 @@
"domain_dyndns_invalid": "Domeni incorrècte per una utilizacion amb DynDNS",
"domain_dyndns_root_unknown": "Domeni DynDNS màger desconegut",
"domain_exists": "Lo domeni existís ja",
"domain_hostname_failed": "Fracàs de la creacion dun nòu nom dòst",
"domain_hostname_failed": "Fracàs de la creacion dun nòu nom dòst. Aquò poirà provocar de problèmas mai tard (mas es pas segur… benlèu que coparà pas res).",
"domain_unknown": "Domeni desconegut",
"domain_zone_exists": "Lo fichièr zòna DNS existís ja",
"domain_zone_not_found": "Fichèr de zòna DNS introbable pel domeni {:s}",
@ -264,7 +264,7 @@
"migrate_tsig_failed": "La migracion del domeni dyndns {domain} cap a hmac-sha512 a pas capitat, anullacion de las modificacions. Error: {error_code} - {error}",
"migrate_tsig_wait": "Esperem 3 minutas que lo servidor dyndns prenga en compte la novèla clau…",
"migrate_tsig_not_needed": "Sembla quutilizatz pas un domeni dyndns, donc cap de migracion es pas necessària!",
"migration_0003_yunohost_upgrade": "Aviada de la mesa a nivèl del paquet YunoHost… La migracion acabarà, mas la mesa a jorn reala se realizarà tot bèl aprèp. Un còp acabada, poiretz vos reconnectar a ladministracion web.",
"migration_0003_yunohost_upgrade": "Aviada de la mesa a nivèl del paquet YunoHost… La migracion acabarà, mas lactualizacion reala se realizarà tot bèl aprèp. Un còp acabada, poiretz vos reconnectar a ladministracion web.",
"migration_0003_system_not_fully_up_to_date": "Lo sistèma es pas complètament a jorn. Mercés de lançar una mesa a jorn classica abans de començar la migracion per Stretch.",
"migration_0003_modified_files": "Mercés de notar que los fichièrs seguents son estats detectats coma modificats manualament e poiràn èsser escafats a la fin de la mesa a nivèl: {manually_modified_files}",
"monitor_period_invalid": "Lo periòde de temps es incorrècte",
@ -404,7 +404,7 @@
"backup_no_uncompress_archive_dir": "Lo repertòri de larchiu descomprimit existís pas",
"pattern_username": "Deu èsser compausat solament de caractèrs alfanumerics en letras minusculas e de tirets basses",
"experimental_feature": "Atencion: aquesta foncionalitat es experimentala e deu pas èsser considerada coma establa, deuriatz pas lutilizar levat que sapiatz çò que fasètz.",
"log_corrupted_md_file": "Lo fichièr yaml de metadonada amb los jornals daudit es corromput: « {md_file} »",
"log_corrupted_md_file": "Lo fichièr yaml de metadonada amb los jornals daudit es corromput: « {md_file} »\nError: {error:s}",
"log_category_404": "La categoria de jornals daudit « {category} » existís pas",
"log_link_to_log": "Jornal complèt daquesta operacion: <a href=\"#/tools/logs/{name}\" style=\"text-decoration:underline\">{desc}</a>",
"log_help_to_get_log": "Per veire lo jornal daquesta operacion « {desc} », utilizatz la comanda «yunohost log display {name} »",
@ -421,7 +421,7 @@
"log_app_change_url": "Cambiar lURL de laplicacion « {} »",
"log_app_install": "Installar laplicacion « {} »",
"log_app_remove": "Levar laplicacion « {} »",
"log_app_upgrade": "Metre a jorn laplicacion « {} »",
"log_app_upgrade": "Actualizacion de laplicacion « {} »",
"log_app_makedefault": "Far venir « {} » laplicacion per defaut",
"log_available_on_yunopaste": "Lo jornal es ara disponible via {url}",
"log_backup_restore_system": "Restaurar lo sistèma a partir duna salvagarda",
@ -431,7 +431,7 @@
"log_domain_add": "Ajustar lo domeni « {} » dins la configuracion sistèma",
"log_domain_remove": "Tirar lo domeni « {} » da la configuracion sistèma",
"log_dyndns_subscribe": "Sabonar al subdomeni YunoHost « {} »",
"log_dyndns_update": "Metre a jorn ladreça IP ligada a vòstre jos-domeni YunoHost « {} »",
"log_dyndns_update": "Actualizar ladreça IP ligada a vòstre jos-domeni YunoHost « {} »",
"log_letsencrypt_cert_install": "Installar lo certificat Let's encrypt sul domeni « {} »",
"log_selfsigned_cert_install": "Installar lo certificat auto-signat sul domeni « {} »",
"log_letsencrypt_cert_renew": "Renovar lo certificat Let's encrypt de « {} »",
@ -439,12 +439,12 @@
"log_service_regen_conf": "Regenerar la configuracion sistèma de « {} »",
"log_user_create": "Ajustar lutilizaire « {} »",
"log_user_delete": "Levar lutilizaire « {} »",
"log_user_update": "Metre a jorn las informacions a lutilizaire « {} »",
"log_user_update": "Actualizar las informacions a lutilizaire « {} »",
"log_tools_maindomain": "Far venir « {} » lo domeni màger",
"log_tools_migrations_migrate_forward": "Migrar",
"log_tools_migrations_migrate_backward": "Tornar en arrièr",
"log_tools_postinstall": "Realizar la post installacion del servidor YunoHost",
"log_tools_upgrade": "Mesa a jorn dels paquets sistèma",
"log_tools_upgrade": "Actualizacion dels paquets sistèma",
"log_tools_shutdown": "Atudar lo servidor",
"log_tools_reboot": "Reaviar lo servidor",
"mail_unavailable": "Aquesta adreça electronica es reservada e deu èsser automaticament atribuida al tot bèl just primièr utilizaire",
@ -473,7 +473,7 @@
"app_start_remove": "Supression de laplicacion {app}…",
"app_start_backup": "Recuperacion dels fichièrs de salvagardar per {app}…",
"app_start_restore": "Restauracion de laplicacion {app}…",
"app_upgrade_several_apps": "Las aplicacions seguentas seràn mesas a jorn: {apps}",
"app_upgrade_several_apps": "Las aplicacions seguentas seràn actualizadas: {apps}",
"ask_new_domain": "Nòu domeni",
"ask_new_path": "Nòu camin",
"backup_actually_backuping": "Creacion dun archiu de seguretat a partir dels fichièrs recuperats…",
@ -525,5 +525,84 @@
"regenconf_failed": "Regeneracion impossibla de la configuracion per la(s) categoria(s) : {categories}",
"regenconf_pending_applying": "Aplicacion de la configuracion en espèra per la categoria « {category} »…",
"tools_upgrade_cant_both": "Actualizacion impossibla del sistèma e de las aplicacions a lencòp",
"tools_upgrade_cant_hold_critical_packages": "Manteniment impossible dels paquets critiques…"
"tools_upgrade_cant_hold_critical_packages": "Manteniment impossible dels paquets critiques…",
"global_settings_setting_security_nginx_compatibility": "Solucion de compromés entre compatibilitat e seguretat pel servidor web nginx. Afècta los criptografs (e dautres aspèctes ligats amb la seguretat)",
"global_settings_setting_security_ssh_compatibility": "Solucion de compromés entre compatibilitat e seguretat pel servidor SSH. Afècta los criptografs (e dautres aspèctes ligats amb la seguretat)",
"global_settings_setting_security_postfix_compatibility": "Solucion de compromés entre compatibilitat e seguretat pel servidor Postfix. Afècta los criptografs (e dautres aspèctes ligats amb la seguretat)",
"migration_description_0010_migrate_to_apps_json": "Levar las appslists despreciadas e utilizar la nòva lista unificada «apps.json» allòc",
"migration_0008_root": " - vos poiretz pas vos connectar coma root via SSH. Allòc auretz dutilizar lutilizaire admin;",
"migration_0008_warning": "Se comprenètz aquestes avertiments e quacceptatz de daissar YunoHost remplaçar la configuracion actuala, començatz la migracion. Autrament podètz tanben passar la migracion, encara que non siá pas recomandat.",
"service_regen_conf_is_deprecated": yunohost service regen-conf» es despreciat! Utilizatz «yunohost tools regen-conf» allòc.",
"service_reload_failed": "Impossible de recargar lo servici « {service:s} »\n\nJornal daudit recent: {logs:s}",
"service_restart_failed": "Impossible de reaviar lo servici « {service:s} »\n\nJornal daudit recent: {logs:s}",
"service_reload_or_restart_failed": "Impossible de recargar o reaviar lo servici « {service:s} »\n\nJornal daudit recent: {logs:s}",
"migration_description_0009_decouple_regenconf_from_services": "Desassociar lo mecanisme de regen-conf dels servicis",
"migration_0008_dsa": " - la clau DSA serà desactivada. En consequéncia, poiriatz aver dinvalidar un messatge espaurugant del client SSH, e tornar verificar lemprunta del servidor;",
"migration_0008_no_warning": "Cap de risc important es estat detectat per remplaçar e la configuracion SSH, mas podèm pas nèsser totalament segur ;) Se acceptatz que YunoHost remplace la configuracion actuala, començatz la migracion. Autrament, podètz passar la migracion, tot ben que non siá pas recomandat.",
"regenconf_file_kept_back": "Sespèra que lo fichièr de configuracion « {conf} » siá suprimit per regen-conf (categoria {category} mas es estat mantengut.",
"this_action_broke_dpkg": "Aquesta accion a copat dpkg/apt (los gestionaris de paquets del sistèma)… Podètz ensajar de resòlver aqueste problèma en vos connectant amb SSH e executant «sudo dpkg --configure -a».",
"tools_upgrade_at_least_one": "Especificatz --apps O --system",
"tools_upgrade_cant_unhold_critical_packages": "Se pòt pas quitar de manténer los paquets critics…",
"tools_upgrade_regular_packages": "Actualizacion dels paquets «normals» (pas ligats a YunoHost)…",
"tools_upgrade_special_packages": "Actualizacion dels paquets «especials» (ligats a YunoHost)…",
"tools_upgrade_special_packages_explanation": "Aquesta accion sacabarà mas lactualizacion especiala actuala contunharà en rèire-plan. Comencetz pas cap dautra accion sul servidor dins las ~ 10 minutas que venon (depend de la velocitat de la maquina). Un còp acabat, benlèu que vos calrà vos tornar connectar a linterfàcia dadministracion. Los jornals daudit de lactualizacion seràn disponibles a Aisinas > Jornals daudit (dins linterfàcia dadministracion) o amb «yunohost log list» (en linha de comanda).",
"update_apt_cache_failed": "I a agut derrors en actualizar la memòria cache dAPT (lo gestionari de paquets de Debian). Aquí avètz las linhas de sources.list que pòdon vos ajudar a identificar las linhas problematicas: \n{sourceslist}",
"update_apt_cache_warning": "I a agut derrors en actualizar la memòria cache dAPT (lo gestionari de paquets de Debian). Aquí avètz las linhas de sources.list que pòdon vos ajudar a identificar las linhas problematicas: \n{sourceslist}",
"apps_permission_not_found": "Cap dautorizacion pas trobada per las aplicacions installadas",
"backup_permission": "Autorizacion de salvagarda per laplicacion {app:s}",
"edit_group_not_allowed": "Sètz pas autorizat a cambiar lo grop {group:s}",
"error_when_removing_sftpuser_group": "Error en ensajar de suprimir lo grop sftpusers",
"group_name_already_exist": "Lo grop {name:s} existís ja",
"group_created": "Lo grop « {group} » es estat corrèctament creat",
"group_creation_failed": "Fracàs de la creacion del grop « {group} »",
"group_deleted": "Lo grop « {group} » es estat suprimit",
"group_deletion_failed": "Fracàs de la supression del grop « {group} »",
"group_deletion_not_allowed": "Lo grop « {group} » pòt pas èsser suprimir manualament.",
"group_info_failed": "Recuperacion de las informacions del grop « {group} » impossibla",
"group_unknown": "Lo grop « {group} » es desconegut",
"log_user_group_add": "Ajustar lo grop « {} »",
"log_user_group_delete": "Suprimir lo grop « {} »",
"migration_0011_backup_before_migration": "Creacion duna còpia de seguretat de la basa de donadas LDAP e de la configuracion de las aplicacions abans defectuar la migracion.",
"migration_0011_create_group": "Creacion dun grop per cada utilizaire…",
"migration_0011_done": "Migracion complèta. Ara podètz gerir de grops dutilizaires.",
"migration_0011_LDAP_update_failed": "Actualizacion impossibla de LDAP. Error: {error:s}",
"migration_0011_migration_failed_trying_to_rollback": "La migracion a fracassat… ensag de tornar lo sistèma a lestat anterio.",
"migration_0011_rollback_success": "Restauracion del sistèma reüssida.",
"apps_permission_restoration_failed": "Fracàs de la permission « {permission:s} » per la restauracion de laplicacion {app:s}",
"group_already_allowed": "Lo grop « {group:s} » a ja la permission « {permission:s} » activada per laplicacion « {app:s} »",
"group_already_disallowed": "Lo grop « {group:s} »a ja las permissions « {permission:s} » desactivadas per laplicacion « {app:s} »",
"group_updated": "Lo grop « {group} » es estat actualizat",
"group_update_failed": "Actualizacion impossibla del grop « {group} »",
"log_permission_add": "Ajustar la permission « {} » per laplicacion « {} »",
"log_permission_remove": "Suprimir la permission « {} »",
"log_permission_update": "Actualizacion de la permission « {} » per laplicacion « {} »",
"log_user_group_update": "Actualizar lo grop « {} »",
"log_user_permission_add": "Actualizar la permission « {} »",
"log_user_permission_remove": "Actualizar la permission « {} »",
"migration_description_0011_setup_group_permission": "Configurar lo grop dutilizaire e las permission de las aplicacions e dels servicis",
"migration_0011_can_not_backup_before_migration": "La salvagarda del sistèma abans la migracion a pas capitat. La migracion a fracassat. Error : {error:s}",
"migration_0011_migrate_permission": "Migracion de las permission dels paramètres daplicacion a LDAP…",
"migration_0011_update_LDAP_database": "Actualizacion de la basa de donadas LDAP…",
"migration_0011_update_LDAP_schema": "Actualizacion de lesquèma LDAP…",
"permission_already_exist": "La permission « {permission:s} » per laplicacion {app:s} existís ja",
"permission_created": "Permission creada « {permission:s} » per laplicacion{app:s}",
"permission_creation_failed": "Creacion impossibla de la permission",
"permission_deleted": "Permission « {permission:s} » per laplicacion {app:s} suprimida",
"permission_deletion_failed": "Fracàs de la supression de la permission « {permission:s} » per laplicacion {app:s}",
"permission_not_found": "Permission « {permission:s} » pas trobada per laplicacion {app:s}",
"permission_name_not_valid": "Lo nom de la permission « {permission:s} » es pas valid",
"permission_update_failed": "Fracàs de lactualizacion de la permission",
"permission_generated": "La basa de donadas de las permission es estada actualizada",
"permission_updated": "La permission « {permission:s} » per laplicacion {app:s} es estada actualizada",
"permission_update_nothing_to_do": "Cap de permission dactualizar",
"remove_main_permission_not_allowed": "Se pòt pas suprimir la permission màger",
"remove_user_of_group_not_allowed": "Sètz pas autorizat a suprimir {user:s} del grop {group:s}",
"system_groupname_exists": "Lo nom del grop existís ja dins lo sistèma de grops",
"tools_update_failed_to_app_fetchlist": "Fracàs de lactualizacion de la lista daplicacions de YunoHost a causa de : {error}",
"user_already_in_group": "Lutilizaire {user:} es ja dins lo grop {group:s}",
"user_not_in_group": "Lutilizaire {user:} es pas dins lo grop {group:s}",
"edit_permission_with_group_all_users_not_allowed": "Podètz pas modificar las permissions del grop « all_users », utilizatz « yunohost user permission clear APP » o « yunohost user permission add APP -u USER ».",
"mailbox_disabled": "La bóstia de las letras es desactivada per lutilizaire {user:s}",
"migration_0011_LDAP_config_dirty": "Sembla quavètz modificat manualament la configuracion LDAP. Per far aquesta migracion cal actualizar la configuracion LDAP.\nSalvagardatz la configuracion actuala, reïnicializatz la configuracion originala amb la comanda « yunohost tools regen-conf -f » e tornatz ensajar la migracion",
"need_define_permission_before": "Vos cal tornar definir las permission en utilizant « yunohost user permission add -u USER » abans de suprimir un grop permés"
}

View file

@ -41,7 +41,7 @@ from datetime import datetime
from moulinette import msignals, m18n, msettings
from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import read_json
from moulinette.utils.filesystem import read_json, read_toml
from yunohost.service import service_log, service_status, _run_service_command
from yunohost.utils import packages
@ -277,8 +277,8 @@ def app_list(filter=None, raw=False, installed=False, with_backup=False):
continue
# FIXME : What if it's not !?!?
with open(os.path.join(APPS_SETTING_PATH, app, 'manifest.json')) as json_manifest:
app_dict[app] = {"manifest": json.load(json_manifest)}
manifest = _get_manifest_of_app(os.path.join(APPS_SETTING_PATH, app))
app_dict[app] = {"manifest": manifest}
app_dict[app]['repository'] = None
@ -349,7 +349,7 @@ def app_info(app, show_status=False, raw=False):
"""
if not _is_installed(app):
raise YunohostError('app_not_installed', app=app)
raise YunohostError('app_not_installed', app=app, all_apps=_get_all_installed_apps_id())
app_setting_path = APPS_SETTING_PATH + app
@ -371,16 +371,14 @@ def app_info(app, show_status=False, raw=False):
ret['upgradable'] = upgradable
ret['change_url'] = os.path.exists(os.path.join(app_setting_path, "scripts", "change_url"))
with open(os.path.join(APPS_SETTING_PATH, app, 'manifest.json')) as json_manifest:
manifest = json.load(json_manifest)
manifest = _get_manifest_of_app(os.path.join(APPS_SETTING_PATH, app))
ret['version'] = manifest.get('version', '-')
return ret
# Retrieve manifest and status
with open(app_setting_path + '/manifest.json') as f:
manifest = json.loads(str(f.read()))
manifest = _get_manifest_of_app(app_setting_path)
status = _get_app_status(app, format_date=True)
info = {
@ -415,7 +413,7 @@ def app_map(app=None, raw=False, user=None):
if app is not None:
if not _is_installed(app):
raise YunohostError('app_not_installed', app=app)
raise YunohostError('app_not_installed', app=app, all_apps=_get_all_installed_apps_id())
apps = [app, ]
else:
apps = os.listdir(APPS_SETTING_PATH)
@ -471,7 +469,7 @@ def app_change_url(operation_logger, app, domain, path):
installed = _is_installed(app)
if not installed:
raise YunohostError('app_not_installed', app=app)
raise YunohostError('app_not_installed', app=app, all_apps=_get_all_installed_apps_id())
if not os.path.exists(os.path.join(APPS_SETTING_PATH, app, "scripts", "change_url")):
raise YunohostError("app_change_no_change_url_script", app_name=app)
@ -499,7 +497,7 @@ def app_change_url(operation_logger, app, domain, path):
))
raise YunohostError('app_location_unavailable', apps="\n".join(apps))
manifest = json.load(open(os.path.join(APPS_SETTING_PATH, app, "manifest.json")))
manifest = _get_manifest_of_app(os.path.join(APPS_SETTING_PATH, app))
# Retrieve arguments list for change_url script
# TODO: Allow to specify arguments
@ -616,7 +614,7 @@ def app_upgrade(app=[], url=None, file=None):
# Abort if any of those app is in fact not installed..
for app in [app for app in apps if not _is_installed(app)]:
raise YunohostError('app_not_installed', app=app)
raise YunohostError('app_not_installed', app=app, all_apps=_get_all_installed_apps_id())
if len(apps) == 0:
raise YunohostError('app_no_upgrade')
@ -697,8 +695,12 @@ def app_upgrade(app=[], url=None, file=None):
json.dump(status, f)
# Replace scripts and manifest and conf (if exists)
os.system('rm -rf "%s/scripts" "%s/manifest.json %s/conf"' % (app_setting_path, app_setting_path, app_setting_path))
os.system('mv "%s/manifest.json" "%s/scripts" %s' % (extracted_app_folder, extracted_app_folder, app_setting_path))
os.system('rm -rf "%s/scripts" "%s/manifest.toml %s/manifest.json %s/conf"' % (app_setting_path, app_setting_path, app_setting_path, app_setting_path))
if os.path.exists(os.path.join(extracted_app_folder, "manifest.json")):
os.system('mv "%s/manifest.json" "%s/scripts" %s' % (extracted_app_folder, extracted_app_folder, app_setting_path))
if os.path.exists(os.path.join(extracted_app_folder, "manifest.toml")):
os.system('mv "%s/manifest.toml" "%s/scripts" %s' % (extracted_app_folder, extracted_app_folder, app_setting_path))
for file_to_copy in ["actions.json", "actions.toml", "config_panel.json", "config_panel.toml", "conf"]:
if os.path.exists(os.path.join(extracted_app_folder, file_to_copy)):
@ -740,9 +742,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
ldap = _get_ldap_interface()
# Fetch or extract sources
try:
os.listdir(INSTALL_TMP)
except OSError:
if not os.path.exists(INSTALL_TMP):
os.makedirs(INSTALL_TMP)
status = {
@ -754,7 +754,6 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
}
def confirm_install(confirm):
# Ignore if there's nothing for confirm (good quality app), if --force is used
# or if request on the API (confirm already implemented on the API side)
if confirm is None or force or msettings.get('interface') == 'api':
@ -863,7 +862,10 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
# Execute App install script
os.system('chown -hR admin: %s' % INSTALL_TMP)
# Move scripts and manifest to the right place
os.system('cp %s/manifest.json %s' % (extracted_app_folder, app_setting_path))
if os.path.exists(os.path.join(extracted_app_folder, "manifest.json")):
os.system('cp %s/manifest.json %s' % (extracted_app_folder, app_setting_path))
if os.path.exists(os.path.join(extracted_app_folder, "manifest.toml")):
os.system('cp %s/manifest.toml %s' % (extracted_app_folder, app_setting_path))
os.system('cp -R %s/scripts %s' % (extracted_app_folder, app_setting_path))
for file_to_copy in ["actions.json", "actions.toml", "config_panel.json", "config_panel.toml", "conf"]:
@ -980,7 +982,7 @@ def app_remove(operation_logger, app):
from yunohost.hook import hook_exec, hook_remove, hook_callback
from yunohost.permission import permission_remove, permission_sync_to_user
if not _is_installed(app):
raise YunohostError('app_not_installed', app=app)
raise YunohostError('app_not_installed', app=app, all_apps=_get_all_installed_apps_id())
operation_logger.start()
@ -1099,8 +1101,7 @@ def app_debug(app):
Keyword argument:
app
"""
with open(APPS_SETTING_PATH + app + '/manifest.json') as f:
manifest = json.loads(f.read())
manifest = _get_manifest_of_app(os.path.join(APPS_SETTING_PATH, app))
return {
'name': manifest['id'],
@ -1452,7 +1453,7 @@ def app_ssowatconf():
def app_change_label(app, new_label):
installed = _is_installed(app)
if not installed:
raise YunohostError('app_not_installed', app=app)
raise YunohostError('app_not_installed', app=app, all_apps=_get_all_installed_apps_id())
app_setting(app, "label", value=new_label)
@ -1475,7 +1476,8 @@ def app_action_list(app):
}
def app_action_run(app, action, args=None):
@is_unit_operation()
def app_action_run(operation_logger, app, action, args=None):
logger.warning(m18n.n('experimental_feature'))
from yunohost.hook import hook_exec
@ -1488,6 +1490,8 @@ def app_action_run(app, action, args=None):
if action not in actions:
raise YunohostError("action '%s' not available for app '%s', available actions are: %s" % (action, app, ", ".join(actions.keys())), raw_msg=True)
operation_logger.start()
action_declaration = actions[action]
# Retrieve arguments list for install script
@ -1524,17 +1528,21 @@ def app_action_run(app, action, args=None):
)[0]
if retcode not in action_declaration.get("accepted_return_codes", [0]):
raise YunohostError("Error while executing action '%s' of app '%s': return code %s" % (action, app, retcode), raw_msg=True)
msg = "Error while executing action '%s' of app '%s': return code %s" % (action, app, retcode)
operation_logger.error(msg)
raise YunohostError(msg, raw_msg=True)
os.remove(path)
operation_logger.success()
return logger.success("Action successed!")
# Config panel todo list:
# * docstrings
# * merge translations on the json once the workflow is in place
def app_config_show_panel(app):
@is_unit_operation()
def app_config_show_panel(operation_logger, app):
logger.warning(m18n.n('experimental_feature'))
from yunohost.hook import hook_exec
@ -1542,6 +1550,7 @@ def app_config_show_panel(app):
# this will take care of checking if the app is installed
app_info_dict = app_info(app)
operation_logger.start()
config_panel = _get_app_config_panel(app)
config_script = os.path.join(APPS_SETTING_PATH, app, 'scripts', 'config')
@ -1605,17 +1614,19 @@ def app_config_show_panel(app):
"app": app,
"app_name": app_info_dict["name"],
"config_panel": config_panel,
"logs": operation_logger.success(),
}
def app_config_apply(app, args):
@is_unit_operation()
def app_config_apply(operation_logger, app, args):
logger.warning(m18n.n('experimental_feature'))
from yunohost.hook import hook_exec
installed = _is_installed(app)
if not installed:
raise YunohostError('app_not_installed', app=app)
raise YunohostError('app_not_installed', app=app, all_apps=_get_all_installed_apps_id())
config_panel = _get_app_config_panel(app)
config_script = os.path.join(APPS_SETTING_PATH, app, 'scripts', 'config')
@ -1624,6 +1635,7 @@ def app_config_apply(app, args):
# XXX real exception
raise Exception("Not config-panel.json nor scripts/config")
operation_logger.start()
app_id, app_instance_nb = _parse_app_instance_name(app)
env = {
"YNH_APP_ID": app_id,
@ -1657,9 +1669,31 @@ def app_config_apply(app, args):
)[0]
if return_code != 0:
raise Exception("'script/config apply' return value code: %s (considered as an error)", return_code)
msg = "'script/config apply' return value code: %s (considered as an error)" % return_code
operation_logger.error(msg)
raise Exception(msg)
logger.success("Config updated as expected")
return {
"logs": operation_logger.success(),
}
def _get_all_installed_apps_id():
"""
Return something like:
' * app1
* app2
* ...'
"""
all_apps_ids = [x["id"] for x in app_list(installed=True)["apps"]]
all_apps_ids = sorted(all_apps_ids)
all_apps_ids_formatted = "\n * ".join(all_apps_ids)
all_apps_ids_formatted = "\n * " + all_apps_ids_formatted
return all_apps_ids_formatted
def _get_app_actions(app_id):
@ -1882,7 +1916,7 @@ def _get_app_settings(app_id):
"""
if not _is_installed(app_id):
raise YunohostError('app_not_installed', app=app_id)
raise YunohostError('app_not_installed', app=app_id, all_apps=_get_all_installed_apps_id())
try:
with open(os.path.join(
APPS_SETTING_PATH, app_id, 'settings.yml')) as f:
@ -1998,9 +2032,8 @@ def _extract_app_from_file(path, remove=False):
if len(os.listdir(extracted_app_folder)) == 1:
for folder in os.listdir(extracted_app_folder):
extracted_app_folder = extracted_app_folder + '/' + folder
with open(extracted_app_folder + '/manifest.json') as json_manifest:
manifest = json.loads(str(json_manifest.read()))
manifest['lastUpdate'] = int(time.time())
manifest = _get_manifest_of_app(extracted_app_folder)
manifest['lastUpdate'] = int(time.time())
except IOError:
raise YunohostError('app_install_files_invalid')
except ValueError as e:
@ -2012,6 +2045,139 @@ def _extract_app_from_file(path, remove=False):
return manifest, extracted_app_folder
def _get_manifest_of_app(path):
"Get app manifest stored in json or in toml"
# sample data to get an idea of what is going on
# this toml extract:
#
# license = "free"
# url = "https://example.com"
# multi_instance = true
# version = "1.0~ynh1"
# packaging_format = 1
# services = ["nginx", "php7.0-fpm", "mysql"]
# id = "ynhexample"
# name = "YunoHost example app"
#
# [requirements]
# yunohost = ">= 3.5"
#
# [maintainer]
# url = "http://example.com"
# name = "John doe"
# email = "john.doe@example.com"
#
# [description]
# fr = "Exemple de package d'application pour YunoHost."
# en = "Example package for YunoHost application."
#
# [arguments]
# [arguments.install.domain]
# type = "domain"
# example = "example.com"
# [arguments.install.domain.ask]
# fr = "Choisissez un nom de domaine pour ynhexample"
# en = "Choose a domain name for ynhexample"
#
# will be parsed into this:
#
# OrderedDict([(u'license', u'free'),
# (u'url', u'https://example.com'),
# (u'multi_instance', True),
# (u'version', u'1.0~ynh1'),
# (u'packaging_format', 1),
# (u'services', [u'nginx', u'php7.0-fpm', u'mysql']),
# (u'id', u'ynhexample'),
# (u'name', u'YunoHost example app'),
# (u'requirements', OrderedDict([(u'yunohost', u'>= 3.5')])),
# (u'maintainer',
# OrderedDict([(u'url', u'http://example.com'),
# (u'name', u'John doe'),
# (u'email', u'john.doe@example.com')])),
# (u'description',
# OrderedDict([(u'fr',
# u"Exemple de package d'application pour YunoHost."),
# (u'en',
# u'Example package for YunoHost application.')])),
# (u'arguments',
# OrderedDict([(u'install',
# OrderedDict([(u'domain',
# OrderedDict([(u'type', u'domain'),
# (u'example',
# u'example.com'),
# (u'ask',
# OrderedDict([(u'fr',
# u'Choisissez un nom de domaine pour ynhexample'),
# (u'en',
# u'Choose a domain name for ynhexample')]))])),
#
# and needs to be converted into this:
#
# {
# "name": "YunoHost example app",
# "id": "ynhexample",
# "packaging_format": 1,
# "description": {
# ¦ "en": "Example package for YunoHost application.",
# ¦ "fr": "Exemple de package dapplication pour YunoHost."
# },
# "version": "1.0~ynh1",
# "url": "https://example.com",
# "license": "free",
# "maintainer": {
# ¦ "name": "John doe",
# ¦ "email": "john.doe@example.com",
# ¦ "url": "http://example.com"
# },
# "requirements": {
# ¦ "yunohost": ">= 3.5"
# },
# "multi_instance": true,
# "services": [
# ¦ "nginx",
# ¦ "php7.0-fpm",
# ¦ "mysql"
# ],
# "arguments": {
# ¦ "install" : [
# ¦ ¦ {
# ¦ ¦ ¦ "name": "domain",
# ¦ ¦ ¦ "type": "domain",
# ¦ ¦ ¦ "ask": {
# ¦ ¦ ¦ ¦ "en": "Choose a domain name for ynhexample",
# ¦ ¦ ¦ ¦ "fr": "Choisissez un nom de domaine pour ynhexample"
# ¦ ¦ ¦ },
# ¦ ¦ ¦ "example": "example.com"
# ¦ ¦ },
if os.path.exists(os.path.join(path, "manifest.toml")):
manifest_toml = read_toml(os.path.join(path, "manifest.toml"))
manifest = manifest_toml.copy()
if "arguments" not in manifest:
return manifest
if "install" not in manifest["arguments"]:
return manifest
install_arguments = []
for name, values in manifest_toml.get("arguments", {}).get("install", {}).items():
args = values.copy()
args["name"] = name
install_arguments.append(args)
manifest["arguments"]["install"] = install_arguments
return manifest
elif os.path.exists(os.path.join(path, "manifest.json")):
return read_json(os.path.join(path, "manifest.json"))
else:
return None
def _get_git_last_commit_hash(repository, reference='HEAD'):
"""
Attempt to retrieve the last commit hash of a git repository
@ -2092,8 +2258,7 @@ def _fetch_app_from_git(app):
subprocess.check_call([
'git', 'reset', '--hard', branch
], cwd=extracted_app_folder)
with open(extracted_app_folder + '/manifest.json') as f:
manifest = json.loads(str(f.read()))
manifest = _get_manifest_of_app(extracted_app_folder)
except subprocess.CalledProcessError:
raise YunohostError('app_sources_fetch_failed')
except ValueError as e:
@ -2145,8 +2310,7 @@ def _fetch_app_from_git(app):
'git', 'reset', '--hard',
str(app_info['git']['revision'])
], cwd=extracted_app_folder)
with open(extracted_app_folder + '/manifest.json') as f:
manifest = json.loads(str(f.read()))
manifest = _get_manifest_of_app(extracted_app_folder)
except subprocess.CalledProcessError:
raise YunohostError('app_sources_fetch_failed')
except ValueError as e:
@ -2774,6 +2938,7 @@ def _patch_php5(app_folder):
files_to_patch.extend(glob.glob("%s/scripts/*" % app_folder))
files_to_patch.extend(glob.glob("%s/scripts/.*" % app_folder))
files_to_patch.append("%s/manifest.json" % app_folder)
files_to_patch.append("%s/manifest.toml" % app_folder)
for filename in files_to_patch:

View file

@ -0,0 +1,21 @@
import glob
import re
from yunohost.tools import Migration
from moulinette.utils.filesystem import read_file, write_to_file
class MyMigration(Migration):
"Force authentication in md5 for local connexions"
all_hba_files = glob.glob("/etc/postgresql/*/*/pg_hba.conf")
def forward(self):
for filename in self.all_hba_files:
pg_hba_in = read_file(filename)
write_to_file(filename, re.sub(r"local(\s*)all(\s*)all(\s*)password", "local\\1all\\2all\\3md5", pg_hba_in))
def backward(self):
for filename in self.all_hba_files:
pg_hba_in = read_file(filename)
write_to_file(filename, re.sub(r"local(\s*)all(\s*)all(\s*)md5", "local\\1all\\2all\\3password", pg_hba_in))

View file

@ -33,7 +33,7 @@ import subprocess
from moulinette import m18n
from moulinette.core import MoulinetteError
from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import write_to_file
from moulinette.utils.filesystem import write_to_file, read_file
from moulinette.utils.network import download_json
from moulinette.utils.process import check_output
@ -176,7 +176,7 @@ def dyndns_subscribe(operation_logger, subscribe_host="dyndns.yunohost.org", dom
@is_unit_operation()
def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, key=None,
ipv4=None, ipv6=None):
ipv4=None, ipv6=None, force=False, dry_run=False):
"""
Update IP on DynDNS platform
@ -249,7 +249,7 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
logger.debug("Requested IPv4/v6 are (%s, %s)" % (ipv4, ipv6))
# no need to update
if old_ipv4 == ipv4 and old_ipv6 == ipv6:
if (not force and not dry_run) and (old_ipv4 == ipv4 and old_ipv6 == ipv6):
logger.info("No updated needed.")
return
else:
@ -279,7 +279,7 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
# should be muc.the.domain.tld. or the.domain.tld
if record["value"] == "@":
record["value"] = domain
record["value"] = record["value"].replace(";", "\;")
record["value"] = record["value"].replace(";", r"\;")
action = "update add {name}.{domain}. {ttl} {type} {value}".format(domain=domain, **record)
action = action.replace(" @.", " ")
@ -296,13 +296,18 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
logger.debug("Now pushing new conf to DynDNS host...")
try:
command = ["/usr/bin/nsupdate", "-k", key, DYNDNS_ZONE]
subprocess.check_call(command)
except subprocess.CalledProcessError:
raise YunohostError('dyndns_ip_update_failed')
if not dry_run:
try:
command = ["/usr/bin/nsupdate", "-k", key, DYNDNS_ZONE]
subprocess.check_call(command)
except subprocess.CalledProcessError:
raise YunohostError('dyndns_ip_update_failed')
logger.success(m18n.n('dyndns_ip_updated'))
logger.success(m18n.n('dyndns_ip_updated'))
else:
print(read_file(DYNDNS_ZONE))
print("")
print("Warning: dry run, this is only the generated config, it won't be applied")
def dyndns_installcron():
@ -325,8 +330,8 @@ def dyndns_removecron():
"""
try:
os.remove("/etc/cron.d/yunohost-dyndns")
except:
raise YunohostError('dyndns_cron_remove_failed')
except Exception as e:
raise YunohostError('dyndns_cron_remove_failed', error=e)
logger.success(m18n.n('dyndns_cron_removed'))

View file

@ -25,8 +25,11 @@
"""
import os
import re
import sys
import tempfile
import mimetypes
from glob import iglob
from importlib import import_module
from moulinette import m18n, msettings
from yunohost.utils.error import YunohostError
@ -179,7 +182,7 @@ 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] == '~':
if f[0] == '.' or f[-1] == '~' or f.endswith(".pyc"):
continue
path = '%s%s/%s' % (folder, action, f)
priority, name = _extract_filename_parts(f)
@ -311,7 +314,6 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
user -- User with which to run the command
"""
from moulinette.utils.process import call_async_output
# Validate hook path
if path[0] != '/':
@ -319,6 +321,38 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
if not os.path.isfile(path):
raise YunohostError('file_does_not_exist', path=path)
# Define output loggers and call command
loggers = (
lambda l: logger.debug(l.rstrip()+"\r"),
lambda l: logger.warning(l.rstrip()),
lambda l: logger.info(l.rstrip())
)
# Check the type of the hook (bash by default)
# For now we support only python and bash hooks.
hook_type = mimetypes.MimeTypes().guess_type(path)[0]
if hook_type == 'text/x-python':
returncode, returndata = _hook_exec_python(path, args, env, loggers)
else:
returncode, returndata = _hook_exec_bash(path, args, no_trace, chdir, env, user, return_format, loggers)
# Check and return process' return code
if returncode is None:
if raise_on_error:
raise YunohostError('hook_exec_not_terminated', path=path)
else:
logger.error(m18n.n('hook_exec_not_terminated', path=path))
return 1, {}
elif raise_on_error and returncode != 0:
raise YunohostError('hook_exec_failed', path=path)
return returncode, returndata
def _hook_exec_bash(path, args, no_trace, chdir, env, user, return_format, loggers):
from moulinette.utils.process import call_async_output
# Construct command variables
cmd_args = ''
if args and isinstance(args, list):
@ -369,33 +403,13 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
else:
logger.debug(m18n.n('executing_script', script=path))
# Define output callbacks and call command
callbacks = (
lambda l: logger.debug(l.rstrip()+"\r"),
lambda l: logger.warning(l.rstrip()),
)
if stdinfo:
callbacks = (callbacks[0], callbacks[1],
lambda l: logger.info(l.rstrip()))
logger.debug("About to run the command '%s'" % command)
returncode = call_async_output(
command, callbacks, shell=False, cwd=chdir,
command, loggers, shell=False, cwd=chdir,
stdinfo=stdinfo
)
# Check and return process' return code
if returncode is None:
if raise_on_error:
raise YunohostError('hook_exec_not_terminated', path=path)
else:
logger.error(m18n.n('hook_exec_not_terminated', path=path))
return 1, {}
elif raise_on_error and returncode != 0:
raise YunohostError('hook_exec_failed', path=path)
raw_content = None
try:
with open(stdreturn, 'r') as f:
@ -427,6 +441,25 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
return returncode, returncontent
def _hook_exec_python(path, args, env, loggers):
dir_ = os.path.dirname(path)
name = os.path.splitext(os.path.basename(path))[0]
if not dir_ in sys.path:
sys.path = [dir_] + sys.path
module = import_module(name)
ret = module.main(args, env, loggers)
# # Assert that the return is a (int, dict) tuple
assert isinstance(ret, tuple) \
and len(ret) == 2 \
and isinstance(ret[0],int) \
and isinstance(ret[1],dict), \
"Module %s did not return a (int, dict) tuple !" % module
return ret
def _extract_filename_parts(filename):
"""Extract hook parts from filename"""
if '-' in filename:
@ -434,6 +467,9 @@ def _extract_filename_parts(filename):
else:
priority = '50'
action = filename
# Remove extension if there's one
action = os.path.splitext(action)[0]
return priority, action

View file

@ -103,7 +103,12 @@ def log_list(category=[], limit=None, with_details=False):
entry["started_at"] = log_datetime
if with_details:
metadata = read_yaml(md_path)
try:
metadata = read_yaml(md_path)
except Exception as e:
# If we can't read the yaml for some reason, report an error and ignore this entry...
logger.error(m18n.n('log_corrupted_md_file', md_file=md_path, error=e))
continue
entry["success"] = metadata.get("success", "?") if metadata else "?"
result[category].append(entry)
@ -310,7 +315,7 @@ class RedactingFormatter(Formatter):
try:
# This matches stuff like db_pwd=the_secret or admin_password=other_secret
# (the secret part being at least 3 chars to avoid catching some lines like just "db_pwd=")
match = re.search(r'(pwd|pass|password|secret|key)=(\S{3,})$', record.strip())
match = re.search(r'(pwd|pass|password|secret|key|token)=(\S{3,})$', record.strip())
if match and match.group(2) not in self.data_to_redact:
self.data_to_redact.append(match.group(2))
except Exception as e:
@ -396,7 +401,8 @@ class OperationLogger(object):
dump = yaml.safe_dump(self.metadata, default_flow_style=False)
for data in self.data_to_redact:
dump = dump.replace(data, "**********")
# N.B. : we need quotes here, otherwise yaml isn't happy about loading the yml later
dump = dump.replace(data, "'**********'")
with open(self.md_path, 'w') as outfile:
outfile.write(dump)

View file

@ -35,8 +35,6 @@ from moulinette import m18n
from yunohost.utils.error import YunohostError
from moulinette.utils import log, filesystem
from yunohost.log import is_unit_operation
MOULINETTE_LOCK = "/var/run/moulinette_yunohost.lock"
logger = log.getActionLogger('yunohost.service')
@ -215,8 +213,7 @@ def service_reload_or_restart(names):
raise YunohostError('service_reload_or_restart_failed', service=name, logs=_get_journalctl_logs(name))
@is_unit_operation()
def service_enable(operation_logger, names):
def service_enable(names):
"""
Enable one or more services
@ -224,7 +221,6 @@ def service_enable(operation_logger, names):
names -- Services name to enable
"""
operation_logger.start()
if isinstance(names, str):
names = [names]
for name in names:

View file

@ -225,10 +225,6 @@ def _set_hostname(hostname, pretty_hostname=None):
Change the machine hostname using hostnamectl
"""
if _is_inside_container():
logger.warning("You are inside a container and hostname cannot easily be changed")
return
if not pretty_hostname:
pretty_hostname = "(YunoHost/%s)" % hostname
@ -252,26 +248,23 @@ def _set_hostname(hostname, pretty_hostname=None):
if p.returncode != 0:
logger.warning(command)
logger.warning(out)
raise YunohostError('domain_hostname_failed')
logger.error(m18n.n('domain_hostname_failed'))
else:
logger.debug(out)
def _is_inside_container():
def _detect_virt():
"""
Check if we're inside a container (i.e. LXC)
Returns True or False
Returns the output of systemd-detect-virt (so e.g. 'none' or 'lxc' or ...)
You can check the man of the command to have a list of possible outputs...
"""
# See https://www.2daygeek.com/check-linux-system-physical-virtual-machine-virtualization-technology/
p = subprocess.Popen("sudo systemd-detect-virt".split(),
p = subprocess.Popen("systemd-detect-virt".split(),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
out, _ = p.communicate()
container = ['lxc', 'lxd', 'docker']
return out.split()[0] in container
return out.split()[0]
@is_unit_operation()

View file

@ -48,9 +48,9 @@ def get_network_interfaces():
# Get network devices and their addresses (raw infos from 'ip addr')
devices_raw = {}
output = subprocess.check_output('ip addr show'.split())
for d in re.split('^(?:[0-9]+: )', output, flags=re.MULTILINE):
for d in re.split(r'^(?:[0-9]+: )', output, flags=re.MULTILINE):
# Extract device name (1) and its addresses (2)
m = re.match('([^\s@]+)(?:@[\S]+)?: (.*)', d, flags=re.DOTALL)
m = re.match(r'([^\s@]+)(?:@[\S]+)?: (.*)', d, flags=re.DOTALL)
if m:
devices_raw[m.group(1)] = m.group(2)
@ -63,7 +63,7 @@ def get_network_interfaces():
def get_gateway():
output = subprocess.check_output('ip route show'.split())
m = re.search('default via (.*) dev ([a-z]+[0-9]?)', output)
m = re.search(r'default via (.*) dev ([a-z]+[0-9]?)', output)
if not m:
return None
@ -71,9 +71,6 @@ def get_gateway():
return addr.popitem()[1] if len(addr) == 1 else None
#
def _extract_inet(string, skip_netmask=False, skip_loopback=True):
"""
Extract IP addresses (v4 and/or v6) from a string limited to one
@ -89,10 +86,10 @@ def _extract_inet(string, skip_netmask=False, skip_loopback=True):
A dict of {protocol: address} with protocol one of 'ipv4' or 'ipv6'
"""
ip4_pattern = '((25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'
ip6_pattern = '(((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)'
ip4_pattern += '/[0-9]{1,2})' if not skip_netmask else ')'
ip6_pattern += '/[0-9]{1,3})' if not skip_netmask else ')'
ip4_pattern = r'((25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'
ip6_pattern = r'(((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)'
ip4_pattern += r'/[0-9]{1,2})' if not skip_netmask else ')'
ip6_pattern += r'/[0-9]{1,3})' if not skip_netmask else ')'
result = {}
for m in re.finditer(ip4_pattern, string):