# Copyright (c) 2017 VMware, Inc.
# All rights reserved. -- VMware Confidential
"""
Integrate Rsyslog service with the B2B patching framework
"""
import os
import sys
import logging
import os_utils

from extensions import extend, Hook
from patch_specs import DiscoveryResult
from l10n import msgMetadata as _T, localizedString as _
from reporting import getProgressReporter

_PAYLOAD_DIR = os.path.dirname(os.path.realpath(__file__))
_PATCHES_DIR = os.path.join(_PAYLOAD_DIR, "patches")
sys.path.extend([_PAYLOAD_DIR, _PATCHES_DIR])
import utils

logger = logging.getLogger(__name__)

# List of patch tuples: [(patch_version, patch_module)]
# All the patch modules should use the same patch_version; eg.,
# patches = [("6.6.0.2", "tls_priority"), ("6.6.0.2", "reset_config"),]
# Thus with the update of any patch_module, patch_version need to be updated.
patches = [
    ("6.6.0.2", "tls_priority"),
    ("6.6.0.2", "syslog_levels"),
]


@extend(Hook.Discovery)
def discover(ctx):
    logger.info("Discovering Rsyslog service")
    return DiscoveryResult(displayName=_(_T("common.comp.displayName",
                                            "VMware Rsyslog")),
                           componentId="rsyslog")


def _doIncrementalPatching(ctx):
    curVersion = getCurrentVersion()
    patchCurrentVersion = curVersion is None
    patchApplied = False

    for ver, modulePath in patches:
        patchCurrentVersion |= (curVersion != ver)

        if patchCurrentVersion:
            logger.info("Applying patch {0} from version {1}".format(
                        modulePath, ver))
            mod = __import__(modulePath)
            mod.doPatching(ctx)
            patchApplied = True
            logger.info("Patch {0} applied".format(modulePath))

    utils.setSourceVersion(getLatestVersion())
    return patchApplied


def getCurrentVersion():
    return utils.getSourceVersion()


def getLatestVersion():
    return patches[-1][0]


def restartRsyslogService():
    restart_cmd = ['systemctl', 'restart', 'rsyslog']
    out, err, rc = os_utils.executeCommand(restart_cmd)
    if rc != 0:
        logger.error("Failed to restart Rsyslog after applying the patches."
                     " rc = %d, stdout: %s, stderr: %s" % (rc, out, err))
        raise ValueError("Failed during Rsyslog patching.")


@extend(Hook.Patch)
def patch(ctx):
    logger.info("Patching Rsyslog Service")
    progressReporter = getProgressReporter()

    progressReporter.updateProgress(0)
    needRestart = _doIncrementalPatching(ctx)
    if needRestart:
        progressReporter.updateProgress(50)
        restartRsyslogService()
    progressReporter.updateProgress(100)
