# Copyright (c) 2016-2021 VMware, Inc.  All rights reserved.
# All rights reserved. -- VMware Confidential

import logging
import os
import json
import shutil
import sys
import re

from fss_utils import getTargetFSS
from vcsa_utils import isDisruptiveUpgrade

# Import netdumperUtils.py from the parent directory
scriptDir = os.path.dirname(os.path.realpath(__file__))
sys.path.insert(0, os.path.dirname(scriptDir))
import netdumperUtils as utils

_logger = logging.getLogger(__name__)

_NETDUMPER_SYSCONFIG_FILE = '/etc/sysconfig/netdumper'
_NETDUMPER_FIREWALL_FILE = '/etc/vmware/appliance/firewall/vmware-netdumper'
_NETDUMPER_PROPERTIES_FILE = '/etc/vmware-netdump/firstboot/netdump.properties'
_RHTTPPROXY_ENDPOINT_DIR = '/etc/vmware-rhttpproxy/endpoints.conf.d/'

_NETDUMPER_SYSCONFIG_REPLICATE_FILE = '/etc/sysconfig/netdumper.replicate'
_NETDUMPER_FIREWALL_REPLICATE_FILE = '/etc/vmware/appliance/firewall/vmware-netdumper.replicate'
# Below are files that needs special attention.
# Each element consist of tuple of full file path
# and list of the keys that needs to be preserved
# REMARK: json file is working only with root level properties
_cfgFiles = [(_NETDUMPER_SYSCONFIG_FILE, ['NETDUMPER_HOST', 'NETDUMPER_PORT']),
             ('/usr/lib/vmware-sca/scripts/configuration/netdump-config.attr', [])]
_jsonFiles = [(_NETDUMPER_FIREWALL_FILE, ['firewall'])]


_cfgFiles_replicate = [(_NETDUMPER_SYSCONFIG_REPLICATE_FILE, ['NETDUMPER_HOST', 'NETDUMPER_PORT']),
                       ('/usr/lib/vmware-sca/scripts/configuration/netdump-config.attr', [])]
_jsonFiles_replicate = [(_NETDUMPER_FIREWALL_REPLICATE_FILE, ['firewall'])]

def doPatching(ctx):
    if not getTargetFSS("NDU_Limited_Downtime") or isDisruptiveUpgrade(ctx):
        for (fileName, props) in _cfgFiles:
            utils.mergeCfgFile(fileName, props, ctx)

        for (fileName, props) in _jsonFiles:
            utils.mergeJsonFile(fileName, props)

        # Get web port from _NETDUMPER_FIREWALL_FILE
        webPort = utils.getValueFromJsonFile(_NETDUMPER_FIREWALL_FILE,
                                            'internal-ports.rules.0.port')
        assert(webPort)

        # Substitute webPort in _NETDUMPER_SYSCONFIG_FILE
        utils.updateCfgFile(_NETDUMPER_SYSCONFIG_FILE, [
                        ("NETDUMPER_WEBPORT", webPort)])

        # Set port and hostname to default values
        # if it is not fetched from old config file
        propListToChange = []

        netdumperPort = utils.getPropFromCfgFile(_NETDUMPER_SYSCONFIG_FILE,
                                                 "NETDUMPER_PORT")
        if (not netdumperPort is None and
                                  re.search("^@@[A-Z_]*@@", netdumperPort)):
            propListToChange.append(("NETDUMPER_PORT", "6500"))

        netdumperHost = utils.getPropFromCfgFile(_NETDUMPER_SYSCONFIG_FILE,
                                                 "NETDUMPER_HOST")
        if (not netdumperHost is None and
                                  re.search("^@@[A-Z_]*@@", netdumperHost)):
            pnid = getPNIDfromFile()
            propListToChange.append(("NETDUMPER_HOST", pnid))

        utils.updateCfgFile(_NETDUMPER_SYSCONFIG_FILE, propListToChange)

    elif getTargetFSS("NDU_Limited_Downtime"):
        shutil.copyfile(_NETDUMPER_SYSCONFIG_FILE, _NETDUMPER_SYSCONFIG_REPLICATE_FILE)
        shutil.copyfile(_NETDUMPER_FIREWALL_FILE, _NETDUMPER_FIREWALL_REPLICATE_FILE)
        for (fileName, props) in _cfgFiles_replicate:
            utils.mergeCfgFile(fileName, props, ctx)

        for (fileName, props) in _jsonFiles_replicate:
            utils.mergeJsonFile(fileName, props)

        # Get web port from _NETDUMPER_FIREWALL_FILE
        webPort = utils.getValueFromJsonFile(_NETDUMPER_FIREWALL_REPLICATE_FILE,
                                            'internal-ports.rules.0.port')
        assert(webPort)

        # Substitute webPort in _NETDUMPER_SYSCONFIG_FILE
        utils.updateCfgFile(_NETDUMPER_SYSCONFIG_REPLICATE_FILE, [
                        ("NETDUMPER_WEBPORT", webPort)])

    # Register global urls with rhttpproxy from _NETDUMPER_PROPERTIES_FILE
    # and set the new webPort
    _RegenerateRhttpproxyConfiguration(webPort)


def getPNIDfromFile():
    ''' get PNID from systemname_info file
    @return PNID
    '''
    pnidData = {'PNID': ''}
    pnidFilePath = '/etc/vmware/systemname_info.json'
    try:
        with open(pnidFilePath) as f:
            pnidData = json.load(f)
    except Exception as e:
        print("Exception in getPNIDfromFile : " +e.message)
        pass
    return pnidData.get('PNID', '')


def _RegenerateRhttpproxyConfiguration(webPort):
    ''' Regenerate the netdumper configuration for the Rhttpproxy and change
    also the webPort(internal port).
    @param webPort: webport string for the netdumper service
    '''
    NETDUMPER_FILE_KEY = 'rhttpproxy.file'
    NETDUMPER_WEBPORT_KEY = 'rhttpproxy.endpoint0.address'

    props = _getPropsByRegExFromNetdumperCfgFile('^rhttpproxy')
    assert(props)

    # Generate the text to be written to the file
    strToWrite = ""
    for (key, value) in props:
        if (key != NETDUMPER_FILE_KEY):
            strToWrite += ("%s " %
                           (value if key != NETDUMPER_WEBPORT_KEY else webPort))

    # Write to the file
    fullFileName = _RHTTPPROXY_ENDPOINT_DIR + dict(props)[NETDUMPER_FILE_KEY]
    with open(fullFileName, 'w') as f:
        f.write(strToWrite.strip())


def _getPropsByRegExFromNetdumperCfgFile(regEx):
    ''' Get the properties that mach the @regex from the
        _NETDUMPER_PROPERTIES_FILE file.
    @param regEx: regex to search for
    @return list of tuples of key/value
    '''
    props = []
    with open(_NETDUMPER_PROPERTIES_FILE, 'r') as f:
        for line in f:
            if re.search(regEx, line):
                index = line.find('=')
                if index > 0:
                    key = line[:index].strip()
                    value = line[index + 1:].strip()
                    props.append((key, value))
    return props
