
from __future__ import absolute_import
from __future__ import division

import grp
import os
import pwd

from . import YES, NO, MAYBE, InvalidConfig
from vdsm.common import cmdutils
from vdsm.common import commands
from vdsm import constants

SANLOCK_GROUPS = (constants.QEMU_PROCESS_GROUP, constants.VDSM_GROUP)

services = ('sanlock',)


def configure():
    try:
        commands.run([
            '/usr/sbin/usermod',
            '-a',
            '-G',
            ','.join(SANLOCK_GROUPS),
            constants.SANLOCK_USER
        ])
    except cmdutils.Error as e:
        raise RuntimeError("Failed to perform sanlock config: {}".format(e))


def isconfigured():
    configured = NO
    groups = [g.gr_name for g in grp.getgrall()
              if constants.SANLOCK_USER in g.gr_mem]
    gid = pwd.getpwnam(constants.SANLOCK_USER).pw_gid
    groups.append(grp.getgrgid(gid).gr_name)
    if all(group in groups for group in SANLOCK_GROUPS):
        configured = MAYBE

    if configured == MAYBE:
        try:
            with open("/var/run/sanlock/sanlock.pid", "r") as f:
                sanlock_pid = f.readline().strip()
            with open(os.path.join('/proc', sanlock_pid, 'status'),
                      "r") as sanlock_status:
                proc_status_group_prefix = "Groups:\t"
                for status_line in sanlock_status:
                    if status_line.startswith(proc_status_group_prefix):
                        groups = [int(x) for x in status_line[
                            len(proc_status_group_prefix):]
                            .strip().split()]
                        break
                else:
                    raise InvalidConfig(
                        "Unable to find sanlock service groups"
                    )

            is_sanlock_groups_set = True
            for g in SANLOCK_GROUPS:
                if grp.getgrnam(g)[2] not in groups:
                    is_sanlock_groups_set = False
            if is_sanlock_groups_set:
                configured = YES

        except IOError as e:
            if e.errno == os.errno.ENOENT:
                configured = YES
            else:
                raise

    return configured
