#!/usr/bin/env python

# Copyright (c) 2014 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

# DESCRIPTION
# This script is used to test public autobuilder images on remote hardware.
# The script is called from a machine that is able download the images from the remote images repository and to connect to the test hardware.
#
# test-remote-image --image-type core-image-sato --repo-link http://192.168.10.2/images --required-packages rpm psplash
#
# Translation: Build the 'rpm' and 'pslash' packages and test a remote core-image-sato image using the http://192.168.10.2/images repository.
#
# You can also use the '-h' option to see some help information.

import os
import sys
import argparse
import logging
import shutil
from abc import ABCMeta, abstractmethod

# Add path to scripts/lib in sys.path;
scripts_path = os.path.abspath(os.path.dirname(os.path.abspath(sys.argv[0])))
lib_path = scripts_path + '/lib'
sys.path = sys.path + [lib_path]

import scriptpath

# Add meta/lib to sys.path
scriptpath.add_oe_lib_path()

import oeqa.utils.ftools as ftools
from oeqa.utils.commands import runCmd, bitbake, get_bb_var

# Add all lib paths relative to BBPATH to sys.path; this is used to find and import the target controllers.
for path in get_bb_var('BBPATH').split(":"):
    sys.path.insert(0, os.path.abspath(os.path.join(path, 'lib')))

# In order to import modules that contain target controllers, we need the bitbake libraries in sys.path .
bitbakepath = scriptpath.add_bitbake_lib_path()
if not bitbakepath:
    sys.stderr.write("Unable to find bitbake by searching parent directory of this script or PATH\n")
    sys.exit(1)

# create a logger
def logger_create():
    log = logging.getLogger('hwauto')
    log.setLevel(logging.DEBUG)

    fh = logging.FileHandler(filename='hwauto.log', mode='w')
    fh.setLevel(logging.DEBUG)

    ch = logging.StreamHandler(sys.stdout)
    ch.setLevel(logging.INFO)

    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)

    log.addHandler(fh)
    log.addHandler(ch)

    return log

# instantiate the logger
log = logger_create()


# Define and return the arguments parser for the script
def get_args_parser():
    description = "This script is used to run automated runtime tests using remotely published image files. You should prepare the build environment just like building local images and running the tests."
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('--image-types', required=True, action="store", nargs='*', dest="image_types", default=None, help='The image types to test(ex: core-image-minimal).')
    parser.add_argument('--repo-link', required=True, action="store", type=str, dest="repo_link", default=None, help='The link to the remote images repository.')
    parser.add_argument('--required-packages', required=False, action="store", nargs='*', dest="required_packages", default=None, help='Required packages for the tests. They will be built before the testing begins.')
    parser.add_argument('--targetprofile', required=False, action="store", nargs=1, dest="targetprofile", default='AutoTargetProfile', help='The target profile to be used.')
    parser.add_argument('--repoprofile', required=False, action="store", nargs=1, dest="repoprofile", default='PublicAB', help='The repo profile to be used.')
    parser.add_argument('--skip-download', required=False, action="store_true", dest="skip_download", default=False, help='Skip downloading the images completely. This needs the correct files to be present in the directory specified by the target profile.')
    return parser

class BaseTargetProfile(object):
    """
    This class defines the meta profile for a specific target (MACHINE type + image type).
    """

    __metaclass__ = ABCMeta

    def __init__(self, image_type):
        self.image_type = image_type

        self.kernel_file = None
        self.rootfs_file = None
        self.manifest_file = None
        self.extra_download_files = []          # Extra files (full name) to be downloaded. They should be situated in repo_link

    # This method is used as the standard interface with the target profile classes.
    # It returns a dictionary containing a list of files and their meaning/description.
    def get_files_dict(self):
        files_dict = {}

        if self.kernel_file:
            files_dict['kernel_file'] = self.kernel_file
        else:
            log.error('The target profile did not set a kernel file.')
            sys.exit(1)

        if self.rootfs_file:
            files_dict['rootfs_file'] = self.rootfs_file
        else:
            log.error('The target profile did not set a rootfs file.')
            sys.exit(1)

        if self.manifest_file:
            files_dict['manifest_file'] = self.manifest_file
        else:
            log.error('The target profile did not set a manifest file.')
            sys.exit(1)

        for idx, f in enumerate(self.extra_download_files):
            files_dict['extra_download_file' + str(idx)] = f

        return files_dict

class AutoTargetProfile(BaseTargetProfile):

    def __init__(self, image_type):
        super(AutoTargetProfile, self).__init__(image_type)
        self.image_name = get_bb_var('IMAGE_LINK_NAME', target=image_type)
        self.kernel_type = get_bb_var('KERNEL_IMAGETYPE', target=image_type)
        self.controller = self.get_controller()

        self.set_kernel_file()
        self.set_rootfs_file()
        self.set_manifest_file()
        self.set_extra_download_files()

    # Get the controller object that will be used by bitbake.
    def get_controller(self):
        from oeqa.controllers.testtargetloader import TestTargetLoader

        target_controller = get_bb_var('TEST_TARGET')
        bbpath = get_bb_var('BBPATH').split(':')

        if target_controller == "qemu":
            from oeqa.targetcontrol import QemuTarget
            controller = QemuTarget
        else:
            testtargetloader = TestTargetLoader()
            controller = testtargetloader.get_controller_module(target_controller, bbpath)
        return controller

    def set_kernel_file(self):
        postconfig = "QA_GET_MACHINE = \"${MACHINE}\""
        machine = get_bb_var('QA_GET_MACHINE', postconfig=postconfig)
        self.kernel_file = self.kernel_type + '-' + machine + '.bin'

    def set_rootfs_file(self):
        image_fstypes = get_bb_var('IMAGE_FSTYPES').split(' ')
        # Get a matching value between target's IMAGE_FSTYPES and the image fstypes suppoerted by the target controller.
        fstype = self.controller.match_image_fstype(d=None, image_fstypes=image_fstypes)
        if fstype:
            self.rootfs_file = self.image_name + '.' + fstype
        else:
            log.error("Could not get a compatible image fstype. Check that IMAGE_FSTYPES and the target controller's supported_image_fstypes fileds have common values.")
            sys.exit(1)

    def set_manifest_file(self):
        self.manifest_file = self.image_name + ".manifest"

    def set_extra_download_files(self):
        self.extra_download_files = self.get_controller_extra_files()
        if not self.extra_download_files:
            self.extra_download_files = []

    def get_controller_extra_files(self):
        controller = self.get_controller()
        return controller.get_extra_files()


class BaseRepoProfile(object):
    """
    This class defines the meta profile for an images repository.
    """

    __metaclass__ = ABCMeta

    def __init__(self, repolink, localdir):
        self.localdir = localdir
        self.repolink = repolink

    # The following abstract methods are the interfaces to the repository profile classes derived from this abstract class.

    # This method should check the file named 'file_name' if it is different than the upstream one.
    # Should return False if the image is the same as the upstream and True if it differs.
    @abstractmethod
    def check_old_file(self, file_name):
        pass

    # This method should fetch file_name and create a symlink to localname if set.
    @abstractmethod
    def fetch(self, file_name, localname=None):
        pass

class PublicAB(BaseRepoProfile):

    def __init__(self, repolink, localdir=None):
        super(PublicAB, self).__init__(repolink, localdir)
        if localdir is None:
            self.localdir = os.path.join(os.environ['BUILDDIR'], 'PublicABMirror')

    # Not yet implemented. Always returning True.
    def check_old_file(self, file_name):
        return True

    def get_repo_path(self):
        path = '/machines/'

        postconfig = "QA_GET_MACHINE = \"${MACHINE}\""
        machine = get_bb_var('QA_GET_MACHINE', postconfig=postconfig)
        if 'qemu' in machine:
            path += 'qemu/'

        postconfig = "QA_GET_DISTRO = \"${DISTRO}\""
        distro = get_bb_var('QA_GET_DISTRO', postconfig=postconfig)
        path += distro.replace('poky', machine) + '/'
        return path


    def fetch(self, file_name, localname=None):
        repo_path = self.get_repo_path()
        link = self.repolink + repo_path + file_name

        self.wget(link, self.localdir, localname)

    def wget(self, link, localdir, localname=None, extraargs=None):
        wget_cmd = '/usr/bin/env wget -t 2 -T 30 -nv --passive-ftp --no-check-certificate '

        if localname:
            wget_cmd += ' -O ' + localname + ' '

        if extraargs:
            wget_cmd += ' ' + extraargs + ' '

        wget_cmd += " -P %s '%s'" % (localdir, link)
        runCmd(wget_cmd)

class HwAuto():

    def __init__(self, image_types, repolink, required_packages, targetprofile, repoprofile, skip_download):
        log.info('Initializing..')
        self.image_types = image_types
        self.repolink = repolink
        self.required_packages = required_packages
        self.targetprofile = targetprofile
        self.repoprofile = repoprofile
        self.skip_download = skip_download
        self.repo = self.get_repo_profile(self.repolink)

    # Get the repository profile; for now we only look inside this module.
    def get_repo_profile(self, *args, **kwargs):
        repo = getattr(sys.modules[__name__], self.repoprofile)(*args, **kwargs)
        log.info("Using repo profile: %s" % repo.__class__.__name__)
        return repo

    # Get the target profile; for now we only look inside this module.
    def get_target_profile(self, *args, **kwargs):
        target = getattr(sys.modules[__name__], self.targetprofile)(*args, **kwargs)
        log.info("Using target profile: %s" % target.__class__.__name__)
        return target

    # Run the testimage task on a build while redirecting DEPLOY_DIR_IMAGE to repo.localdir, where the images are downloaded.
    def runTestimageBuild(self, image_type):
        log.info("Running the runtime tests for %s.." % image_type)
        postconfig = "DEPLOY_DIR_IMAGE = \"%s\"" % self.repo.localdir
        result = bitbake("%s -c testimage" % image_type, ignore_status=True, postconfig=postconfig)
        testimage_results = ftools.read_file(os.path.join(get_bb_var("T", image_type), "log.do_testimage"))
        log.info('Runtime tests results for %s:' % image_type)
        print testimage_results
        return result

    # Start the procedure!
    def run(self):
        if self.required_packages:
            # Build the required packages for the tests
            log.info("Building the required packages: %s ." % ', '.join(map(str, self.required_packages)))
            result = bitbake(self.required_packages, ignore_status=True)
            if result.status != 0:
                log.error("Could not build required packages: %s. Output: %s" % (self.required_packages, result.output))
                sys.exit(1)

            # Build the package repository meta data.
            log.info("Building the package index.")
            result = bitbake("package-index", ignore_status=True)
            if result.status != 0:
                log.error("Could not build 'package-index'. Output: %s" % result.output)
                sys.exit(1)

        # Create the directory structure for the images to be downloaded
        log.info("Creating directory structure %s" % self.repo.localdir)
        if not os.path.exists(self.repo.localdir):
            os.makedirs(self.repo.localdir)

        # For each image type, download the needed files and run the tests.
        noissuesfound = True
        for image_type in self.image_types:
            if self.skip_download:
                log.info("Skipping downloading the images..")
            else:
                target = self.get_target_profile(image_type)
                files_dict = target.get_files_dict()
                log.info("Downloading files for %s" % image_type)
                for f in files_dict:
                    if self.repo.check_old_file(files_dict[f]):
                        filepath = os.path.join(self.repo.localdir, files_dict[f])
                        if os.path.exists(filepath):
                            os.remove(filepath)
                        self.repo.fetch(files_dict[f])

            result = self.runTestimageBuild(image_type)
            if result.status != 0:
                noissuesfound = False

        if noissuesfound:
            log.info('Finished. No issues found.')
        else:
            log.error('Finished. Some runtime tests have failed. Returning non-0 status code.')
            sys.exit(1)



def main():

    parser = get_args_parser()
    args = parser.parse_args()

    hwauto = HwAuto(image_types=args.image_types, repolink=args.repo_link, required_packages=args.required_packages, targetprofile=args.targetprofile, repoprofile=args.repoprofile, skip_download=args.skip_download)

    hwauto.run()

if __name__ == "__main__":
    try:
        ret = main()
    except Exception:
        ret = 1
        import traceback
        traceback.print_exc(5)
    sys.exit(ret)
