# Functional test that boots a VM and run commands via a SSH session
#
# Copyright (c) Philippe Mathieu-Daudé <f4bug@amsat.org>
#
# This work is licensed under the terms of the GNU GPL, version 2 or
# later.  See the COPYING file in the top-level directory.

import os
import re
import base64
import logging
import time

from avocado import skipUnless
from avocado_qemu import LinuxSSHMixIn
from avocado_qemu import QemuSystemTest
from avocado_qemu import wait_for_console_pattern
from avocado.utils import process
from avocado.utils import archive
from avocado.utils import ssh


@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
@skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available')
class LinuxSSH(QemuSystemTest, LinuxSSHMixIn):
    """
    :avocado: tags=accel:tcg
    """

    timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg'

    KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
    VM_IP = '127.0.0.1'

    BASE_URL = 'https://people.debian.org/~aurel32/qemu/'
    IMAGE_INFO = {
        'be': {'base_url': 'mips',
               'image_name': 'debian_wheezy_mips_standard.qcow2',
               'image_hash': '8987a63270df67345b2135a6b7a4885a35e392d5',
               'kernel_hash': {
                   32: '592e384a4edc16dade52a6cd5c785c637bcbc9ad',
                   64: 'db6eea7de35d36c77d8c165b6bcb222e16eb91db'}
              },
        'le': {'base_url': 'mipsel',
               'image_name': 'debian_wheezy_mipsel_standard.qcow2',
               'image_hash': '7866764d9de3ef536ffca24c9fb9f04ffdb45802',
               'kernel_hash': {
                   32: 'a66bea5a8adaa2cb3d36a1d4e0ccdb01be8f6c2a',
                   64: '6a7f77245acf231415a0e8b725d91ed2f3487794'}
              }
        }
    CPU_INFO = {
        32: {'cpu': 'MIPS 24Kc', 'kernel_release': '3.2.0-4-4kc-malta'},
        64: {'cpu': 'MIPS 20Kc', 'kernel_release': '3.2.0-4-5kc-malta'}
        }

    def get_url(self, endianess, path=''):
        qkey = {'le': 'el', 'be': ''}
        return '%s/mips%s/%s' % (self.BASE_URL, qkey[endianess], path)

    def get_image_info(self, endianess):
        dinfo = self.IMAGE_INFO[endianess]
        image_url = self.get_url(endianess, dinfo['image_name'])
        image_hash = dinfo['image_hash']
        return (image_url, image_hash)

    def get_kernel_info(self, endianess, wordsize):
        minfo = self.CPU_INFO[wordsize]
        kernel_url = self.get_url(endianess,
                                  'vmlinux-%s' % minfo['kernel_release'])
        kernel_hash = self.IMAGE_INFO[endianess]['kernel_hash'][wordsize]
        return kernel_url, kernel_hash

    def ssh_disconnect_vm(self):
        self.ssh_session.quit()

    def boot_debian_wheezy_image_and_ssh_login(self, endianess, kernel_path):
        image_url, image_hash = self.get_image_info(endianess)
        image_path = self.fetch_asset(image_url, asset_hash=image_hash)

        self.vm.set_console()
        kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE
                               + 'console=ttyS0 root=/dev/sda1')
        self.vm.add_args('-no-reboot',
                         '-kernel', kernel_path,
                         '-append', kernel_command_line,
                         '-drive', 'file=%s,snapshot=on' % image_path,
                         '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22',
                         '-device', 'pcnet,netdev=vnet')
        self.vm.launch()

        self.log.info('VM launched, waiting for sshd')
        console_pattern = 'Starting OpenBSD Secure Shell server: sshd'
        wait_for_console_pattern(self, console_pattern, 'Oops')
        self.log.info('sshd ready')

        self.ssh_connect('root', 'root', False)

    def shutdown_via_ssh(self):
        self.ssh_command('poweroff')
        self.ssh_disconnect_vm()
        wait_for_console_pattern(self, 'Power down', 'Oops')

    def ssh_command_output_contains(self, cmd, exp):
        stdout, _ = self.ssh_command(cmd)
        for line in stdout:
            if exp in line:
                break
        else:
            self.fail('"%s" output does not contain "%s"' % (cmd, exp))

    def run_common_commands(self, wordsize):
        self.ssh_command_output_contains(
            'cat /proc/cpuinfo',
            self.CPU_INFO[wordsize]['cpu'])
        self.ssh_command_output_contains(
            'uname -m',
            'mips')
        self.ssh_command_output_contains(
            'uname -r',
            self.CPU_INFO[wordsize]['kernel_release'])
        self.ssh_command_output_contains(
            'cat /proc/interrupts',
            'XT-PIC  timer')
        self.ssh_command_output_contains(
            'cat /proc/interrupts',
            'XT-PIC  i8042')
        self.ssh_command_output_contains(
            'cat /proc/interrupts',
            'XT-PIC  serial')
        self.ssh_command_output_contains(
            'cat /proc/interrupts',
            'XT-PIC  ata_piix')
        self.ssh_command_output_contains(
            'cat /proc/interrupts',
            'XT-PIC  eth0')
        self.ssh_command_output_contains(
            'cat /proc/devices',
            'input')
        self.ssh_command_output_contains(
            'cat /proc/devices',
            'usb')
        self.ssh_command_output_contains(
            'cat /proc/devices',
            'fb')
        self.ssh_command_output_contains(
            'cat /proc/ioports',
            ' : serial')
        self.ssh_command_output_contains(
            'cat /proc/ioports',
            ' : ata_piix')
        self.ssh_command_output_contains(
            'cat /proc/ioports',
            ' : piix4_smbus')
        self.ssh_command_output_contains(
            'lspci -d 11ab:4620',
            'GT-64120')
        self.ssh_command_output_contains(
            'cat /sys/bus/i2c/devices/i2c-0/name',
            'SMBus PIIX4 adapter')
        self.ssh_command_output_contains(
            'cat /proc/mtd',
            'YAMON')
        # Empty 'Board Config' (64KB)
        self.ssh_command_output_contains(
            'md5sum /dev/mtd2ro',
            '0dfbe8aa4c20b52e1b8bf3cb6cbdf193')

    def check_mips_malta(self, uname_m, endianess):
        wordsize = 64 if '64' in uname_m else 32
        kernel_url, kernel_hash = self.get_kernel_info(endianess, wordsize)
        kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
        self.boot_debian_wheezy_image_and_ssh_login(endianess, kernel_path)

        stdout, _ = self.ssh_command('uname -a')
        self.assertIn(True, [uname_m + " GNU/Linux" in line for line in stdout])

        self.run_common_commands(wordsize)
        self.shutdown_via_ssh()
        # Wait for VM to shut down gracefully
        self.vm.wait()

    def test_mips_malta32eb_kernel3_2_0(self):
        """
        :avocado: tags=arch:mips
        :avocado: tags=endian:big
        :avocado: tags=device:pcnet32
        """
        self.check_mips_malta('mips', 'be')

    def test_mips_malta32el_kernel3_2_0(self):
        """
        :avocado: tags=arch:mipsel
        :avocado: tags=endian:little
        :avocado: tags=device:pcnet32
        """
        self.check_mips_malta('mips', 'le')

    def test_mips_malta64eb_kernel3_2_0(self):
        """
        :avocado: tags=arch:mips64
        :avocado: tags=endian:big
        :avocado: tags=device:pcnet32
        """
        self.check_mips_malta('mips64', 'be')

    def test_mips_malta64el_kernel3_2_0(self):
        """
        :avocado: tags=arch:mips64el
        :avocado: tags=endian:little
        :avocado: tags=device:pcnet32
        """
        self.check_mips_malta('mips64', 'le')
