#!/usr/bin/python3
"""Restauration du controleur ADDC"""
import sys
from os.path import isdir, isfile
from os import unlink
from creole.client import CreoleClient
from pyeole.process import system_code
from pyeole.service import manage_services
from pyeole.bareosrestore import exit_if_running_jobs, bareos_restore_several_paths

client = CreoleClient()
if client.get_creole('openldap_installed', 'oui') == 'oui':
    if isdir('/var/lib/lxc/addc/rootfs'):
        BACKUP_DIR = '/var/lib/lxc/addc/rootfs'
        SYSVOL_DIR = '/var/lib/lxc/addc/rootfs'
        MODE = 'scribe'
    else:
        # Seth pas education
        BACKUP_DIR = ''
        SYSVOL_DIR = ''
        MODE = 'seth'
elif client.get_creole('mode_conteneur_actif') == 'oui':
    BACKUP_DIR = ''
    SYSVOL_DIR = client.get_creole('container_path_domaine')
    MODE = 'amonecole'
else:
    # Seth education
    BACKUP_DIR = ''
    SYSVOL_DIR = ''
    MODE = 'seth'
BACKUP_DIR += '/home/backup/samba/'
SYSVOL_DIR = SYSVOL_DIR + '/home/sysvol'


def run_addc_command(cmd):
    """Execute une commande dans l'environnement du controleur ADDC."""
    if MODE == 'scribe':
        cmd = ['lxc-attach', '-n', 'addc', '--'] + cmd
    return system_code(cmd, container='domaine')


def fix_samba_private_rights():
    """Normalise les droits de /var/lib/samba/private apres restauration."""
    private_dir = '/var/lib/samba/private'

    print("Correction des droits de {0}".format(private_dir))

    script = r'''
set -eu

private_dir="/var/lib/samba/private"
bind_files="$(mktemp)"
trap 'rm -f "$bind_files"' EXIT

if [ ! -d "$private_dir" ]; then
    echo "Il manque le repertoire $private_dir" >&2
    exit 1
fi

# Memoriser les fichiers utilises par Bind avant de corriger les proprietaires.
find "$private_dir" -type f -group bind -print0 > "$bind_files"

# Etat securise par defaut. Les sockets sont volontairement ignores.
find "$private_dir" -type d -exec chown root:root {} +
find "$private_dir" -type f -exec chown root:root {} +
find "$private_dir" -type d -exec chmod 0700 {} +
find "$private_dir" -type f -exec chmod 0600 {} +

# Repertoire racine et repertoires particuliers observes sur un Seth sain.
chmod 0755 "$private_dir"

[ ! -d "$private_dir/ldap_priv" ] || chmod 0750 "$private_dir/ldap_priv"

for path in \
    "$private_dir/managed_account" \
    "$private_dir/smbd.tmp" \
    "$private_dir/tls" \
    "$private_dir/tls/certs"
do
    [ ! -d "$path" ] || chmod 0755 "$path"
done

for path in \
    "$private_dir/sam.ldb.d" \
    "$private_dir/tls/private"
do
    [ ! -d "$path" ] || chmod 0700 "$path"
done

# Fichiers volontairement lisibles.
for path in \
    "$private_dir/krb5.conf" \
    "$private_dir/dns_update_list" \
    "$private_dir/spn_update_list"
do
    [ ! -f "$path" ] || chmod 0644 "$path"
done

# Certificats publics.
if [ -d "$private_dir/tls/certs" ]; then
    find "$private_dir/tls/certs" -type f -exec chmod 0644 {} +
fi

# Restaurer les proprietaires et droits necessaires a Bind DLZ.
# La liste memorisee preserve les autres exceptions eventuelles.
while IFS= read -r -d '' path; do
    chown root:bind "$path"
    case "$path" in
        "$private_dir/dns.keytab")
            chmod 0640 "$path"
            ;;
        "$private_dir/sam.ldb.d/"*)
            chmod 0660 "$path"
            ;;
    esac
done < "$bind_files"

# Les sauvegardes affectees peuvent avoir perdu le groupe bind.
if [ -f "$private_dir/dns.keytab" ]; then
    chown root:bind "$private_dir/dns.keytab"
    chmod 0640 "$private_dir/dns.keytab"
fi

if [ -d "$private_dir/sam.ldb.d" ]; then
    find "$private_dir/sam.ldb.d" -maxdepth 1 -type f \
        \( -name 'DC%3DDOMAINDNSZONES*.ldb' \
        -o -name 'DC%3DFORESTDNSZONES*.ldb' \
        -o -name 'metadata.tdb' \) \
        -exec chown root:bind {} + \
        -exec chmod 0660 {} +
fi
'''

    return run_addc_command(['/bin/bash', '-c', script])


def execute(option, opt_str, value, parser, jobid, test_jobs=True):
    """ADDC helper"""
    if len(parser.rargs) > 0:
        option = parser.rargs[0]
        if option == 'pre':
            pre()
        elif option == 'post':
            post()
    else:
        if test_jobs:
            exit_if_running_jobs()
        job(jobid)

def pre():
    print("pre ADDC")

def post():
    print("post ADDC")
    if not isdir(BACKUP_DIR):
        print("Il manque le repertoire {0}".format(BACKUP_DIR))
        sys.exit(1)
    old_style_backup = isfile(BACKUP_DIR + '/bareos/sysvol.tar.gz')
    if old_style_backup:
        cmd = ['/usr/bin/online_addc_restore']
    else:
        cmd = ['/usr/bin/addc_restore']

    code = run_addc_command(cmd)
    if code != 0:
        sys.exit(code)

    code = fix_samba_private_rights()
    if code != 0:
        sys.exit(code)

    if MODE == 'scribe':
        # reintegration au domaine
        code = system_code(['/usr/share/eole/postservice/05-eolead-join-and-sync-ldap'])
    if MODE == 'amonecole':
        # reintegration au domaine
        system_code(['cp', client.get_creole('container_path_domaine') + '/etc/eole/private/eole-seth-education.password', client.get_creole('container_path_fichier') + '/etc/eole/private/eole-seth-education.password'])
        system_code(['cp', client.get_creole('container_path_domaine') + '/etc/eole/private/eole-seth-education.password', client.get_creole('container_path_web') + '/etc/eole/private/eole-seth-education.password'])
        unlink(client.get_creole('container_path_fichier') + '/var/lib/samba/.instance_ok')
        system_code(['/usr/share/eole/postservice/26-manage-samba-master', 'instance'])
        system_code(['/usr/share/eole/postservice/26-manage-samba-member', 'instance'])
        code = system_code(['/usr/share/eole/postservice/30-proxy', 'instance', 'restauration'])
    sys.exit(code)

def job(jobid):
    print("Restauration des fichiers Samba")
    path_list = [BACKUP_DIR, SYSVOL_DIR]
    if MODE == 'scribe':
        path_list.append('/root/.eolead')
    if MODE == 'amonecole':
        path_list.append(client.get_creole('container_path_domaine') + '/etc/eole/private/eole-seth-education.password')
    bareos_restore_several_paths(path_list, jobid)

priority = 21

if __name__ == '__main__':
    if sys.argv[-1] == '--force_post':
        post()