#!/usr/bin/env python3

import argparse
import subprocess
import sys
import time


def safe_umount(path):
    retry_count = 10
    not_mounted_str = 'umount: {}: not mounted'.format(path)

    last_code = 0
    while retry_count:
        proc = subprocess.Popen(['mountpoint', '-q', path])
        proc.wait()
        if proc.returncode:
            return 0

        proc = subprocess.Popen(['umount', path], stderr=subprocess.PIPE)
        (_stdout, stderr) = proc.communicate()
        if not proc.returncode:
            return 0

        error = stderr.strip()
        if error == not_mounted_str:
            return 0

        retry_count -= 1
        last_code = proc.returncode
        time.sleep(0.500)

    # Lazy attempt.
    # Unmounting can fail for example due to a network outage of a DRBD volume mounted
    # as `xcp-persistent-database` and which would be blocked in the kernel because of
    # ext4 commands that cannot complete.
    # In this kind of situation, it's necessary to force a umount call with lazy arg to
    # ensure that the mountpoint does not remain present.
    print(f'Failed to unmount `{path}`, trying with lazy option...', file=sys.stderr)
    proc = subprocess.Popen(['umount', '-l', path], stderr=subprocess.PIPE)
    (_stdout, stderr) = proc.communicate()
    if proc.returncode:
        print(f'Failed to unmount `{path}` with lazy option: `{stderr.strip()}`.', file=sys.stderr)
    else:
        print(f'Successfully unmounted `{path}`.', file=sys.stderr)

    return proc.returncode


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('path')
    args = parser.parse_args()
    sys.exit(safe_umount(args.path))
