r"""
.. attention:: **wheezy or older builds on amd64**: Re-enable linux' vsyscall

  In Debian kernel packages since ``4.8.4-1~exp1``::

    [ Ben Hutchings ]
    * [amd64] Enable LEGACY_VSYSCALL_NONE instead of LEGACY_VSYSCALL_EMULATE.
      This breaks (e)glibc 2.13 and earlier, and can be reverted using the kernel
      parameter: vsyscall=emulate

  I.e.: When running the Debian standard kernel and your mini-buildd instance needs to support ``wheezy`` or earlier, you
  need to re-enable this (in ``/etc/default/grub``).

  You may use ``local-vsyscall-emulate.cfg`` in ``examples`` (a symlink should do) for this purpose.

  On any running kernel, this is a poor man's check to see if vsyscall is still enabled on your system:

  .. code:: bash

    grep "\[vsyscall\]" /proc/self/maps

  .. seealso:: :debbug:`847154`, linux package's ``NEWS`` file.

.. note:: **schroot**: Verbosely logs commands ("Running command ...") explicitly via syslog (journalctl)

  schroot seems to verbosely log any executed root-user command via syslog (user/notice). This will
  clutter journalctl's (standard) log output via unit::

    journalctl --unit mini-buildd.service --follow

  As a workaround, specifying the (syslog compatibility) identifier like so helps to unclutter::

    journalctl --identifier mini-buildd --follow
"""

import logging

from mini_buildd import call

LOG = logging.getLogger(__name__)

COMMAND = "/usr/bin/schroot"


class Session():
    def __init__(self, name, namespace="chroot"):
        self.chroot = f"{namespace}:{name}"
        self.session = "session:" + call.Call([COMMAND,
                                               "--begin-session",
                                               "--chroot", self.chroot]).check().stdout.strip()
        LOG.debug("%s: Schroot session started ({self.chroot})", self)

    def close(self):
        """
        Close session (including retries on failure)

        .. attention:: **schroot**: 'target is busy' on session close (stale schroot sessions)

           Occasionally, a schroot session can't be closed
           properly, leaving stale sessions around. Presumably,
           external programs (like 'desktop mount scanners') can cause
           this.

           This internal close does try hard to avoid this -- however,
           if disaster strikes anyway, ``mini-buildd-cruft``
           may help to remove these stale sessions manually (i.e., as
           ``mini-buildd`` user from the shell).
        """
        call.call_with_retry([COMMAND,
                              "--end-session",
                              "--chroot", self.session,
                              ],
                             retry_max_tries=10,
                             retry_sleep=1)
        LOG.debug("%s: Schroot session closed (%s)", self, self.chroot)

    def call(self, _call, user="root"):
        return call.Call([COMMAND,
                          "--run-session",
                          "--chroot", self.session,
                          "--user", user] + _call)

    def run(self, _call, user="root"):
        return self.call(_call, user=user).check().stdout

    def info(self):
        return call.Call([COMMAND,
                          "--info",
                          "--chroot", self.session]).check().stdout

    def __str__(self):
        return f"{self.session}"

    def update_file(self, file_path, content):
        """Write content to file"""
        self.run(["--", "/bin/sh", "-c", f"echo '{content}' >{file_path}"])
        LOG.debug("%s: Updated file '%s': %s", self, file_path, content)

    def set_debconf(self, key, value):
        """Set arbitrary debconf value"""
        self.run(["--", "/bin/sh", "-c", f"export DEBIAN_FRONTEND=noninteractive && echo 'set {key} {value}' | debconf-communicate"])
        LOG.debug("%s: Debconf value set: %s=%s", self, key, value)
