#!/bin/bash

#
# Copyright (C) 2022 Nethesis S.r.l.
# http://www.nethesis.it - nethserver@nethesis.it
#
# This script is part of NethServer.
#
# NethServer is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License,
# or any later version.
#
# NethServer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with NethServer.  If not, see COPYING.
#

set -e

function has_subdirs ()
{
    [[ -d "$1" ]] && [[ -n "$(find "$1" -mindepth 1 -maxdepth 1 -type d -print -quit)" ]]
    return $?
}

# Rsync command wrapper that ignores some specific exit codes
function rsync_forced ()
{
    local exit_code=0
    rsync "${@}" || exit_code=$?
    if [[ ${exit_code} == 23 ]]; then
        echo "[WARNING] rsync exit code 23 is ignored: Partial transfer due to error"
        return 0
    elif [[ ${exit_code} == 24 ]]; then
        echo "[WARNING] rsync exit code 24 is ignored: Partial transfer due to vanished source files"
        return 0
    fi
    return ${exit_code}
}

# Migrate shared folder contents if app nethserver-samba is not skipped
if [[ ! -f "${AGENT_STATE_DIR:?}/nethserver-samba/skip" ]]; then
    migrate_shared_folders=1
fi

# Read nsdc props
IFS=$'\t' read -r provision_type cur_ipaddress < <( /sbin/e-smith/config printjson nsdc | \
    jq -r '.props | [.ProvisionType, .IpAddress] | join("\t") ' )
ipaddress=${SAMBA_IPADDRESS:-$cur_ipaddress}

# Read sssd props
IFS=$'\t' read -r nbdomain realm svcuser svcpass < <( /sbin/e-smith/config printjson sssd | \
    jq -r '.props | [.Workgroup, .Realm, .BindDN, .BindPassword] | join("\t") ' )

# Trim @realm suffix from svcuser
svcuser="${svcuser%%@*}"

# Generate import.env
cat - >import.env <<EOF
HOSTNAME=$(< /var/lib/machines/nsdc/etc/hostname)
IPADDRESS=${ipaddress:?}
PROVISION_TYPE=${provision_type:-unknown}
NBDOMAIN=${nbdomain:?}
REALM=${realm:?}
SVCUSER=${svcuser}
SVCPASS=${svcpass}
EOF

# Send import.env
rsync -i import.env "${RSYNC_ENDPOINT:?}"/data/state/import.env

# Send sysvol contents
rsync -rlptDi /var/lib/machines/nsdc/var/lib/samba/sysvol/ "${RSYNC_ENDPOINT}"/data/volumes/data/sysvol/

# Generate .export files, like the pre-backup event handler of NSDC does
# shellcheck disable=SC2016
nsdc-run -e -- sh -c 'tdbbackup -s .export $(find /var/lib/samba/ -name "*.[t,l]db" -not -name netlogon_creds_cli.tdb)'

# Send .export, *.pem files, secrets encryption key, dns list...
rsync -mtri \
    --exclude="sysvol/" \
    --exclude="*.tdb" \
    --exclude="*.ldb" \
    --exclude="*.bak" \
    /var/lib/machines/nsdc/var/lib/samba/ "${RSYNC_ENDPOINT}"/data/volumes/data/

# Clean up .export files
nsdc-run -e -- find /var/lib/samba/ -name "*.export" -delete

if [[ -n "${migrate_shared_folders}" ]]; then
    # If /srv/shares/accounts.json exists on the remote side, the
    # NS8 module assumes we want to migrate the share dirs:
    /sbin/e-smith/db accounts printjson > accounts.json
    hostname -s > nbalias.txt # Alias name for NetBIOS and DNS resolution
    rsync -i accounts.json nbalias.txt "${RSYNC_ENDPOINT:?}"/data/state/
    if [[ "${MIGRATE_ACTION}" != "finish" ]]; then
        # non-finish pass: send home/ and ibay/ data
        rsync -i --recursive --times --links --perms --delete /var/lib/nethserver/home/ "${RSYNC_ENDPOINT}"/data/volumes/homes/
        if has_subdirs /var/lib/nethserver/ibay ; then
            rsync -i --recursive --times --links --delete /var/lib/nethserver/ibay/* "${RSYNC_ENDPOINT}"/data/volumes/shares/
        fi
    fi
fi

if [[ "${MIGRATE_ACTION}" != "finish" ]]; then
    exit 0
fi

# Remove temporary external user domain
ns8-action --attach cluster remove-external-domain "$(printf '{"domain":"%s"}' "${realm,,}")" || :

# Commit DC migration
rsync -v "${RSYNC_ENDPOINT}"/terminate

if [[ -n "${migrate_shared_folders}" ]]; then
    # Wait until the second rsyncd server with ACLs support is up:
    while sleep 2 ; do
        if rsync -v "${RSYNC_ENDPOINT:?}"/ &>/dev/null ; then
            break
        fi
    done

    # Reconfigure sssd to strip @domain suffix in NSS user and group names
    # resolution. This is necessary to
    sed -i -e '/^default_domain_suffix = / d' -e '/^use_fully_qualified_names =/ d' /etc/sssd/sssd.conf
    systemctl restart sssd.service
    # Avoid racing against rsync: wait until the new configuration is effective
    while sleep 1; do
        { getent passwd administrator | grep -q '@' ; } || break
    done

    # last pass: send shared folders and homedirs, including ACLs, owners,
    # permissions, and the user.DOSATTRIB extended attribute.
    rsync_forced -i --recursive --times --links --acls --owner --group --perms --xattrs --delete /var/lib/nethserver/home/ "${RSYNC_ENDPOINT}"/homes/
    if has_subdirs /var/lib/nethserver/ibay ; then
        rsync_forced -i --recursive --times --links --acls --owner --group --perms --xattrs --delete /var/lib/nethserver/ibay/ "${RSYNC_ENDPOINT}"/shares/
    fi

    # Restore the original sssd.conf contents. Now that all modules are
    # migrated we just want to allow people to log on this system with the sssd cached values
    /sbin/e-smith/expand-template /etc/sssd/sssd.conf
    systemctl restart sssd.service || :

    # Stop the Samba file server services
    systemctl disable --now smb.service nmb.service winbind.service || :
    /sbin/e-smith/config setprop smb status disabled
    /sbin/e-smith/config setprop smb nmb disabled
    /sbin/e-smith/config setprop smb winbind disabled

    # Commit file-server migration
    rsync -v "${RSYNC_ENDPOINT}"/terminate
fi

# Wait until the import-module task has completed
ns8-action --attach wait "${IMPORT_TASK_ID}"

# Stop local AD provider (nsdc) and disable it permanently
/sbin/e-smith/config setprop nsdc status disabled
systemctl disable --now nsdc || :
