# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import avahi_utils
from autotest_lib.client.common_lib.cros import virtual_ethernet_pair
from autotest_lib.client.common_lib.cros.network import netblock
from autotest_lib.client.cros import network_chroot
from autotest_lib.client.cros import service_stopper
from autotest_lib.client.cros import tcpdump


class ChrootedAvahi(object):
    """Helper object to start up avahi in a network chroot.

    Creates a virtual ethernet pair to enable communication with avahi.
    Does the necessary work to make avahi appear on DBus and allow it
    to claim its canonical service name.

    """

    SERVICES_TO_STOP = ['avahi']
    # This side has to be called something special to avoid shill touching it.
    MONITOR_IF_IP = netblock.from_addr('10.9.8.1/24')
    # We'll drop the Avahi side into our network namespace.
    AVAHI_IF_IP = netblock.from_addr('10.9.8.2/24')
    AVAHI_IF_NAME = 'pseudoethernet0'
    TCPDUMP_FILE_PATH = '/var/log/peerd_dump.pcap'
    AVAHI_CONFIG_FILE = 'etc/avahi/avahi-daemon.conf'
    AVAHI_CONFIGS = {
        AVAHI_CONFIG_FILE :
            '[server]\n'
                'host-name-from-machine-id=yes\n'
                'browse-domains=\n'
                'use-ipv4=yes\n'
                'use-ipv6=no\n'
                'ratelimit-interval-usec=1000000\n'
                'ratelimit-burst=1000\n'
            '[wide-area]\n'
                'enable-wide-area=no\n'
            '[publish]\n'
                'publish-hinfo=no\n'
                'publish-workstation=no\n'
                'publish-aaaa-on-ipv4=no\n'
                'publish-a-on-ipv6=no\n'
            '[rlimits]\n'
                'rlimit-core=0\n'
                'rlimit-data=4194304\n'
                'rlimit-fsize=1024\n'
                'rlimit-nofile=768\n'
                'rlimit-stack=4194304\n'
                'rlimit-nproc=10\n',

        'etc/passwd' :
            'root:x:0:0:root:/root:/bin/bash\n'
            'avahi:*:238:238::/dev/null:/bin/false\n',

        'etc/group' :
            'avahi:x:238:\n',
    }
    AVAHI_LOG_FILE = '/var/log/avahi.log'
    AVAHI_PID_FILE = 'run/avahi-daemon/pid'
    AVAHI_UP_TIMEOUT_SECONDS = 10


    def __init__(self, unchrooted_interface_name='pseudoethernet1'):
        """Construct a chrooted instance of Avahi.

        @param unchrooted_interface_name: string name of interface to leave
                outside the network chroot.  This interface will be connected
                to the end Avahi is listening on.

        """
        self._unchrooted_interface_name = unchrooted_interface_name
        self._services = None
        self._vif = None
        self._tcpdump = None
        self._chroot = None


    @property
    def unchrooted_interface_name(self):
        """Get the name of the end of the VirtualEthernetPair not in the chroot.

        The network chroot works by isolating avahi inside with one end of a
        virtual ethernet pair.  The outside world needs to interact with the
        other end in order to talk to avahi.

        @return name of interface not inside the chroot.

        """
        return self._unchrooted_interface_name


    @property
    def avahi_interface_addr(self):
        """@return string ip address of interface belonging to avahi."""
        return self.AVAHI_IF_IP.addr


    @property
    def hostname(self):
        """@return string hostname claimed by avahi on |self.dns_domain|."""
        return avahi_utils.avahi_get_hostname()


    @property
    def dns_domain(self):
        """@return string DNS domain in use by avahi (e.g. 'local')."""
        return avahi_utils.avahi_get_domain_name()


    def start(self):
        """Start up the chrooted Avahi instance."""
        # Prevent weird interactions between services which talk to Avahi.
        # TODO(wiley) Does Chrome need to die here as well?
        self._services = service_stopper.ServiceStopper(
                self.SERVICES_TO_STOP)
        self._services.stop_services()
        # We don't want Avahi talking to the real world, so give it a nice
        # fake interface to use.  We'll watch the other half of the pair.
        self._vif = virtual_ethernet_pair.VirtualEthernetPair(
                interface_name=self.unchrooted_interface_name,
                peer_interface_name=self.AVAHI_IF_NAME,
                interface_ip=self.MONITOR_IF_IP.netblock,
                peer_interface_ip=self.AVAHI_IF_IP.netblock,
                # Moving one end into the chroot causes errors.
                ignore_shutdown_errors=True)
        self._vif.setup()
        if not self._vif.is_healthy:
            raise error.TestError('Failed to setup virtual ethernet pair.')
        # By default, take a packet capture of everything Avahi sends out.
        self._tcpdump = tcpdump.Tcpdump(self.unchrooted_interface_name,
                                        self.TCPDUMP_FILE_PATH)
        # We're going to run Avahi in a network namespace to avoid interactions
        # with the outside world.
        self._chroot = network_chroot.NetworkChroot(self.AVAHI_IF_NAME,
                                                    self.AVAHI_IF_IP.addr,
                                                    self.AVAHI_IF_IP.prefix_len)
        self._chroot.add_config_templates(self.AVAHI_CONFIGS)
        self._chroot.add_root_directories(['etc/avahi', 'etc/avahi/services'])
        self._chroot.add_copied_config_files(['etc/resolv.conf',
                                              'etc/avahi/hosts'])
        self._chroot.add_startup_command(
                '/usr/sbin/avahi-daemon --file=/%s >%s 2>&1' %
                (self.AVAHI_CONFIG_FILE, self.AVAHI_LOG_FILE))
        self._chroot.bridge_dbus_namespaces()
        self._chroot.startup()
        # Wait for Avahi to come up, claim its DBus name, settle on a hostname.
        start_time = time.time()
        while time.time() - start_time < self.AVAHI_UP_TIMEOUT_SECONDS:
            if avahi_utils.avahi_ping():
                break
            time.sleep(0.2)
        else:
            raise error.TestFail('Avahi did not come up in time.')


    def close(self):
        """Clean up the chrooted Avahi instance."""
        if self._chroot:
            # TODO(wiley) This is sloppy.  Add a helper to move the logs over.
            for line in self._chroot.get_log_contents().splitlines():
                logging.debug(line)
            self._chroot.kill_pid_file(self.AVAHI_PID_FILE)
            self._chroot.shutdown()
        if self._tcpdump:
            self._tcpdump.stop()
        if self._vif:
            self._vif.teardown()
        if self._services:
            self._services.restore_services()
