# 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 Test, LinuxSSHMixIn
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(Test, LinuxSSHMixIn):

    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')
