# Copyright (c) 2012 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.

"""
Base class for DHCP tests.  This class just sets up a little bit of plumbing,
like a virtual ethernet device with one end that looks like a real ethernet
device to shill and a DHCP test server on the end that doesn't look like a real
ethernet interface to shill.  Child classes should override test_body() with the
logic of their test.  The plumbing of DhcpTestBase is accessible via properties.
"""

import logging
import socket
import struct
import time
import traceback

from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import dhcp_handling_rule
from autotest_lib.client.cros import dhcp_packet
from autotest_lib.client.cros import dhcp_test_server
from autotest_lib.client.cros import virtual_ethernet_pair
from autotest_lib.client.cros.networking import shill_proxy


# These are keys that may be used with the DBus dictionary returned from
# DhcpTestBase.get_interface_ipconfig().
DHCPCD_KEY_NAMESERVERS = 'NameServers'
DHCPCD_KEY_GATEWAY = 'Gateway'
DHCPCD_KEY_BROADCAST_ADDR = 'Broadcast'
DHCPCD_KEY_ADDRESS = 'Address'
DHCPCD_KEY_PREFIX_LENGTH = 'Prefixlen'
DHCPCD_KEY_DOMAIN_NAME = 'DomainName'
DHCPCD_KEY_SEARCH_DOMAIN_LIST = 'SearchDomains'

# We should be able to complete a DHCP negotiation in this amount of time.
DHCP_NEGOTIATION_TIMEOUT_SECONDS = 10

class DhcpTestBase(test.test):
    """Parent class for tests that work verify DHCP behavior."""
    version = 1

    @staticmethod
    def rewrite_ip_suffix(subnet_mask, ip_in_subnet, ip_suffix):
        """
        Create a new IPv4 address in a subnet by bitwise and'ing an existing
        address |ip_in_subnet| with |subnet_mask| and bitwise or'ing in
        |ip_suffix|.  For safety, bitwise or the suffix with the complement of
        the subnet mask.

        Usage: rewrite_ip_suffix("255.255.255.0", "192.168.1.1", "0.0.0.105")

        The example usage will return "192.168.1.105".

        @param subnet_mask string subnet mask, e.g. "255.255.255.0"
        @param ip_in_subnet string an IP address in the desired subnet
        @param ip_suffix string suffix desired for new address, e.g. "0.0.0.105"

        @return string IP address on in the same subnet with specified suffix.

        """
        mask = struct.unpack('!I', socket.inet_aton(subnet_mask))[0]
        subnet = mask & struct.unpack('!I', socket.inet_aton(ip_in_subnet))[0]
        suffix = ~mask & struct.unpack('!I', socket.inet_aton(ip_suffix))[0]
        return socket.inet_ntoa(struct.pack('!I', (subnet | suffix)))


    def get_device(self, interface_name):
        """Finds the corresponding Device object for an interface with
        the name |interface_name|.

        @param interface_name string The name of the interface to check.

        @return DBus interface object representing the associated device.

        """
        return self.shill_proxy.find_object('Device',
                                            {'Name': interface_name})


    def find_ethernet_service(self, interface_name):
        """Finds the corresponding service object for an Ethernet interface.

        @param interface_name string The name of the associated interface

        @return Service object representing the associated service.

        """
        device = self.get_device(interface_name)
        device_path = shill_proxy.ShillProxy.dbus2primitive(device.object_path)
        return self.shill_proxy.find_object('Service', {'Device': device_path})


    def get_interface_ipconfig_objects(self, interface_name):
        """
        Returns a list of dbus object proxies for |interface_name|.
        Returns an empty list if no such interface exists.

        @param interface_name string name of the device to query (e.g., "eth0").

        @return list of objects representing DBus IPConfig RPC endpoints.

        """
        device = self.get_device(interface_name)
        if device is None:
            return []

        device_properties = device.GetProperties(utf8_strings=True)
        proxy = self.shill_proxy

        ipconfig_object = proxy.DBUS_TYPE_IPCONFIG
        return filter(bool,
                      [ proxy.get_dbus_object(ipconfig_object, property_path)
                        for property_path in device_properties['IPConfigs'] ])


    def get_interface_ipconfig(self, interface_name):
        """
        Returns a dictionary containing settings for an |interface_name| set
        via DHCP.  Returns None if no such interface or setting bundle on
        that interface can be found in shill.

        @param interface_name string name of the device to query (e.g., "eth0").

        @return dict containing the the properties of the IPConfig stripped
            of DBus meta-data or None.

        """
        dhcp_properties = None
        for ipconfig in self.get_interface_ipconfig_objects(interface_name):
          logging.info('Looking at ipconfig %r', ipconfig)
          ipconfig_properties = ipconfig.GetProperties(utf8_strings=True)
          if 'Method' not in ipconfig_properties:
              logging.info('Found ipconfig object with no method field')
              continue
          if ipconfig_properties['Method'] != 'dhcp':
              logging.info('Found ipconfig object with method != dhcp')
              continue
          if dhcp_properties != None:
              raise error.TestFail('Found multiple ipconfig objects '
                                   'with method == dhcp')
          dhcp_properties = ipconfig_properties
        if dhcp_properties is None:
            logging.info('Did not find IPConfig object with method == dhcp')
            return None
        logging.info('Got raw dhcp config dbus object: %s.', dhcp_properties)
        return shill_proxy.ShillProxy.dbus2primitive(dhcp_properties)


    def run_once(self):
        self._server = None
        self._server_ip = None
        self._ethernet_pair = None
        self._server = None
        self._shill_proxy = shill_proxy.ShillProxy()
        try:
            self._ethernet_pair = virtual_ethernet_pair.VirtualEthernetPair(
                    peer_interface_name='pseudoethernet0',
                    peer_interface_ip=None)
            self._ethernet_pair.setup()
            if not self._ethernet_pair.is_healthy:
                raise error.TestFail('Could not create virtual ethernet pair.')
            self._server_ip = self._ethernet_pair.interface_ip
            self._server = dhcp_test_server.DhcpTestServer(
                    self._ethernet_pair.interface_name)
            self._server.start()
            if not self._server.is_healthy:
                raise error.TestFail('Could not start DHCP test server.')
            self._subnet_mask = self._ethernet_pair.interface_subnet_mask
            self.test_body()
        except error.TestFail:
            # Pass these through without modification.
            raise
        except Exception as e:
            logging.error('Caught exception: %s.', str(e))
            logging.error('Trace: %s', traceback.format_exc())
            raise error.TestFail('Caught exception: %s.' % str(e))
        finally:
            if self._server is not None:
                self._server.stop()
            if self._ethernet_pair is not None:
                self._ethernet_pair.teardown()

    def test_body(self):
        """
        Override this method with the body of your test.  You may safely assume
        that the the properties exposed by DhcpTestBase correctly return
        references to the test apparatus.
        """
        raise error.TestFail('No test body implemented')

    @property
    def server_ip(self):
        """
        Return the IP address of the side of the interface that the DHCP test
        server is bound to.  The server itself is bound the the broadcast
        address on the interface.
        """
        return self._server_ip

    @property
    def server(self):
        """
        Returns a reference to the DHCP test server.  Use this to add handlers
        and run tests.
        """
        return self._server

    @property
    def ethernet_pair(self):
        """
        Returns a reference to the virtual ethernet pair created to run DHCP
        tests on.
        """
        return self._ethernet_pair

    @property
    def shill_proxy(self):
        """
        Returns a the shill proxy instance.
        """
        return self._shill_proxy

    def negotiate_and_check_lease(self,
                                  dhcp_options,
                                  custom_fields={},
                                  disable_check=False):
        """
        Perform DHCP lease negotiation, and ensure that the resulting
        ipconfig matches the DHCP options provided to the server.

        @param dhcp_options dict of properties the DHCP server should provide.
        @param custom_fields dict of custom DHCP parameters to add to server.
        @param disable_check bool whether to perform IPConfig parameter
             checking.

        """
        if dhcp_packet.OPTION_REQUESTED_IP not in dhcp_options:
            raise error.TestFail('You must specify OPTION_REQUESTED_IP to '
                                 'negotiate a DHCP lease')
        intended_ip = dhcp_options[dhcp_packet.OPTION_REQUESTED_IP]
        # Build up the handling rules for the server and start the test.
        rules = []
        rules.append(dhcp_handling_rule.DhcpHandlingRule_RespondToDiscovery(
                intended_ip,
                self.server_ip,
                dhcp_options,
                custom_fields))
        rules.append(dhcp_handling_rule.DhcpHandlingRule_RespondToRequest(
                intended_ip,
                self.server_ip,
                dhcp_options,
                custom_fields))
        rules[-1].is_final_handler = True
        self.server.start_test(rules, DHCP_NEGOTIATION_TIMEOUT_SECONDS)
        logging.info('Server is negotiating new lease with options: %s',
                     dhcp_options)
        self.server.wait_for_test_to_finish()
        if not self.server.last_test_passed:
            raise error.TestFail(
                'Test failed: active rule is %s' % self.server.current_rule)

        if disable_check:
            logging.info('Skipping check of negotiated DHCP lease parameters.')
        else:
            # Wait for configuration to propagate over dbus to shill.
            # TODO(wiley) Make this event based.  This is pretty sloppy.
            time.sleep(0.1)
            self.check_dhcp_config(dhcp_options)


    def check_dhcp_config(self, dhcp_options):
        """
        Compare the DHCP ipconfig with DHCP lease parameters to ensure
        that the DUT attained the correct values.

        @param dhcp_options dict of properties the DHCP server provided.

        """
        # The config is what the interface was actually configured with, as
        # opposed to dhcp_options, which is what the server expected it be
        # configured with.
        dhcp_config = self.get_interface_ipconfig(
                self.ethernet_pair.peer_interface_name)
        if dhcp_config is None:
            raise error.TestFail('Failed to retrieve DHCP ipconfig object '
                                 'from shill.')

        logging.debug('Got DHCP config: %s', str(dhcp_config))
        expected_address = dhcp_options.get(dhcp_packet.OPTION_REQUESTED_IP)
        configured_address = dhcp_config.get(DHCPCD_KEY_ADDRESS)
        if expected_address != configured_address:
            raise error.TestFail('Interface configured with IP address not '
                                 'granted by the DHCP server after DHCP '
                                 'negotiation.  Expected %s but got %s.' %
                                 (expected_address, configured_address))

        # While DNS related settings only propagate to the system when the
        # service is marked as the default service, we can still check the
        # IP address on the interface, since that is set immediately.
        interface_address = self.ethernet_pair.peer_interface_ip
        if expected_address != interface_address:
            raise error.TestFail('shill somehow knew about the proper DHCP '
                                 'assigned address: %s, but configured the '
                                 'interface with something completely '
                                 'different: %s.' %
                                 (expected_address, interface_address))

        expected_dns_servers = dhcp_options.get(dhcp_packet.OPTION_DNS_SERVERS)
        configured_dns_servers = dhcp_config.get(DHCPCD_KEY_NAMESERVERS)
        if expected_dns_servers != configured_dns_servers:
            raise error.TestFail('Expected to be configured with DNS server '
                                 'list %s, but was configured with %s '
                                 'instead.' % (expected_dns_servers,
                                               configured_dns_servers))

        expected_domain_name = dhcp_options.get(dhcp_packet.OPTION_DOMAIN_NAME)
        configured_domain_name = dhcp_config.get(DHCPCD_KEY_DOMAIN_NAME)
        if expected_domain_name != configured_domain_name:
            raise error.TestFail('Expected to be configured with domain '
                                 'name %s, but got %s instead.' %
                                 (expected_domain_name, configured_domain_name))

        expected_search_list = dhcp_options.get(
                dhcp_packet.OPTION_DNS_DOMAIN_SEARCH_LIST)
        configured_search_list = dhcp_config.get(DHCPCD_KEY_SEARCH_DOMAIN_LIST)
        if expected_search_list != configured_search_list:
            raise error.TestFail('Expected to be configured with domain '
                                 'search list %s, but got %s instead.' %
                                 (expected_search_list, configured_search_list))

        expected_routers = dhcp_options.get(dhcp_packet.OPTION_ROUTERS)
        if (not expected_routers and
            dhcp_options.get(dhcp_packet.OPTION_CLASSLESS_STATIC_ROUTES)):
            classless_static_routes = dhcp_options[
                dhcp_packet.OPTION_CLASSLESS_STATIC_ROUTES]
            for prefix, destination, gateway in classless_static_routes:
                if not prefix:
                    logging.info('Using %s as the default gateway', gateway)
                    expected_routers = [ gateway ]
                    break
        configured_router = dhcp_config.get(DHCPCD_KEY_GATEWAY)
        if expected_routers and expected_routers[0] != configured_router:
            raise error.TestFail('Expected to be configured with gateway %s, '
                                 'but got %s instead.' %
                                 (expected_routers[0], configured_router))

        self.server.wait_for_test_to_finish()
        if not self.server.last_test_passed:
            raise error.TestFail('Test server didn\'t get all the messages it '
                                 'was told to expect for renewal.')
