# Copyright 2019 VMware, Inc.
# All rights reserved. -- VMware Confidential

"""
    The purpose of this script is to run the specific NSX prechecks during
    patching. Due to the way NSX code is structure do not import and call
    functions except the 'performNsxPrechecks' which has the logic to start the
    NSX in new process to prevent messing the python path.
"""

import sys
import logging
import os
from queue import Empty
from multiprocessing import Process, Queue

from update_utils import DEPLOYMENT_ROOT
from vmware.update.json_utils import JsonSerializer
from vmware.update.specs import InternalError

logger = logging.getLogger(__name__)

def doNsxPrechecks(resultQueue, requirementsSpec):
    ''' THIS SHOULD ONLY BE CALLED VIA MULTIPROCESSING MODULE as there is clash
    in NSX and applmgmt packages, both have package "vmware"
    '''
    logger.info("Performing NSX checks")
    nsxFolder = os.path.join(DEPLOYMENT_ROOT, "scripts", "patches",
                             "payload", "components-script", "nsx")

    logger.info("Adding NSX path to Python path")
    sys.path.append(nsxFolder)

    skipPrechecksIds = []
    if hasattr(requirementsSpec, 'skipPrechecksIds'):
        skipPrechecksIds = requirementsSpec.skipPrechecksIds

    result = []  # List of Mismatches to be returned
    ex = None  # To hold exception if raised.
    try:
        sys.path.append(os.path.join(
            os.path.dirname(__file__),
            "patches",
            "payload",
            "components-script",
            "nsx"))
        import nsx_utils
        result = nsx_utils.precheck()
    except Exception as e:
        logger.exception("Exception raised while running NSX prechecks.")
        ex = e

    json_result = JsonSerializer().serialize([result, ex])
    resultQueue.put(json_result)
    logger.info("Done performing NSX checks")


def performNsxPrechecks(requirementsSpec):
    ''' This performNsxPrechecks create the process and execute the checks in a queue.
    It blocks the process until it completes.
    @param requirementsSpec: The requirements hook input
    @type requirementsSpec:

    @return: list of mismatches if any
    @rtype: list(Mismatch)
    '''
    logger.info("About to perform NSX checks")
    resultQueue = Queue()
    p = Process(target=doNsxPrechecks, args=(resultQueue, requirementsSpec))
    p.start()

    # Blocks until the process does not complete
    p.join()

    try:
        json_result = resultQueue.get_nowait()
        result, ex = JsonSerializer().deserialize(json_result)
        if ex:
            raise ex
    except Empty:
        # Thrown if the CPO hook_execution logic fail
        raise InternalError("Cannot execute NSX prechecks")
    logger.info("NSX checks finished")
    return result
