#
# Copyright 2017 VMware, Inc.  All rights reserved. -- VMware Confidential
#
"""PatchRunner integration hook for Hybrid vCenter Service

This module integrates Hybrid vCenter Service (HVC) patching scripts with the
PatchRunner Framework.

"""
__author__ = 'VMware, Inc.'
__copyright__ = 'Copyright 2017 VMware, Inc. All rights reserved.'

import logging
import os
import sys

from extensions import extend, Hook
from l10n import msgMetadata as _T, localizedString as _
from patch_specs import ValidationResult, Question, Mismatch, Requirements, \
    PatchInfo, RequirementsResult
from reporting import getProgressReporter
import vcsa_utils
import fss_utils

vmware_python_path = os.getenv('VMWARE_PYTHON_PATH')
if vmware_python_path and os.path.exists(vmware_python_path):
    sys.path.append(vmware_python_path)
sys.path.append(os.path.join(os.path.dirname(__file__), "patches"))
patches = [
    # no patches post M10
]

COMPONENT_NAME = "hvc"

logger = logging.getLogger(__name__)


@extend(Hook.Discovery)
def discover(patch_context):
    logger.info("Executing Discovery Hook for Hybric vCenter Service")

    if not is_embedded():
        logger.info("hvc.patch: HVC not run on non-embedded nodes")
        return None

    if not is_hvc_enabled():
        logger.info("hvc.patch: HVC not enabled on source build")
        return None

    if not is_patch_needed():
        logger.info("hvc.patch: Patch version up-to-date.")
        return None

    if fss_utils.getTargetFSS("NDU_Limited_Downtime") \
            and not vcsa_utils.isDisruptiveUpgrade(patch_context):
        # Remove version specific backup restore
        replicationConfig = {
            # exclude version specific files
            "/usr/lib/vmware-hvc/config/log4j.properties": None,
        }
        return vcsa_utils.getComponentDiscoveryResult(
            COMPONENT_NAME,
            displayName=_(
                _T("hvc.displayName",
                   "Hybrid vCenter Service")),
            replicationConfig=replicationConfig)
    return vcsa_utils.getComponentDiscoveryResult(COMPONENT_NAME,
                                                  displayName=_(
                                                   _T("hvc.displayName",
                                                   "Hybrid vCenter Service")))


@extend(Hook.Patch)
def execute_patch(patch_context):
    #This hook is invoked after the rpms are installed.
    if fss_utils.getTargetFSS("NDU_Limited_Downtime") \
            and not vcsa_utils.isDisruptiveUpgrade(patch_context):
        logger.info("For NDU, patching will happen using expand/contract hook.")
        return None

    logger.info("Executing Patch Hook for Hybrid vCenter Service")
    progressReporter = getProgressReporter()
    progressReporter.updateProgress(0, _(_T("hvc.patch.begin",
                                            "Start hvc patching")))
    _do_incremental_patching(patch_context)
    progressReporter.updateProgress(100, _(_T("hvc.patch.complete",
                                              "patching hvc completed")))


@extend(Hook.Expand)
def expand(context):
    ''' needed for NDU'''
    pass

@extend(Hook.Contract)
def contract(ctx):
    '''needed for NDU'''
    pass

@extend(Hook.Revert)
def revert(ctx):
    '''needed for NDU'''
    pass



def _do_incremental_patching(ctx):
    for ver, modulePath in patches:
        logger.info("Checking if need patch %s on version %s"
                     % (ver, modulePath))
        mod = __import__(modulePath)

        if mod.is_patch_needed(isDiscovery=False):
            logger.info("Patch %s needed" % (modulePath))
            mod.doPatching(ctx)
            logger.info('Patch %s applied' % (modulePath))


def is_patch_needed():
    for ver, modulePath in patches:
        logger.info("Checking if need patch %s on version %s"
                     % (ver, modulePath))
        mod = __import__(modulePath)
        if hasattr(mod, 'is_patch_needed'):
            if mod.is_patch_needed():
                return True
    return False


def is_hvc_enabled():
    try:
        sys.path.append(os.environ['VMWARE_PYTHON_PATH'])
        import featureState
        featureState.init()
        if hasattr(featureState, 'getHybridVC'):
            return (featureState.getHybridVC() and
                   os.path.exists('/usr/lib/vmware-hvc'))
    except Exception as e:
        logger.warning('Failed to getHybridVC: %s' % str(e))
        if os.path.exists('/usr/lib/vmware-hvc'):
            logger.info('hvc lib exists, so assume source enabled')
            return True
    return False


def is_embedded():
    try:
        sys.path.append(os.environ['VMWARE_PYTHON_PATH'])
        from cis.utils import get_deployment_nodetype
        node_type = get_deployment_nodetype()
        logger.info('Node type is %s' % node_type)
        return node_type == 'embedded'
    except Exception as e:
        logger.warning('Failed to get_deployment_nodetype: %s' % str(e))
        return False
