#!/usr/bin/python
# Copyright 2019-2020 VMware, Inc.  All rights reserved. -- VMware Confidential
#
"""
Script that adds memory to a given VM that is managed by the server
"""
import sys
import os
import logging
import traceback
sys.path.append(os.environ['VMWARE_PYTHON_PATH'])
sys.path.append(os.path.dirname(__file__))
from pyVim import task # pylint: disable=E0401
from pyVmomi import vim  # pylint: disable=E0401,E0611
from l10n import msgMetadata as _T, localizedString as _
from patch_errors import UserError


logger = logging.getLogger(__name__)


def _prepare_update_spec(memory):
    """
    This method creates the spec for addition of memory
    :param memory: required memory size
    :type memory: int

    :return:spec file with new memory set
    """
    try:
        configSpec = vim.VirtualMachineConfigSpec()
        logger.info("Memory is set to %s", memory)
        configSpec.memoryMB = memory
        return configSpec
    except Exception:
        cause = _(_T('memory.spec.preparation.failed',
                     'Memory specification preparation failed due to %s.'),
                     traceback.format_exc())
        raise UserError(cause=cause)


def add_memory(vm_obj, memory):
    """
    This method increases the memory to the specified size
    :param vm_obj: VM Object
    :param memory: size of the memory to be set
    :return: None
    """
    try:
        logger.info("Current VM memory is %s", vm_obj.config.hardware.memoryMB)
        if vm_obj.summary.runtime.maxMemoryUsage >= memory:
            logger.info("Current memory allocation is satisfied. "
                        "Skipping memory addition task.")
            return

        configSpec = _prepare_update_spec(memory)
        logger.info("Updating VM memory.")
        state = task.WaitForTask(task=vm_obj.ReconfigVM_Task(configSpec))
        if state == "success":
            logger.info("Memory update is complete.")
        else:
            cause = _(_T('memory.update.failed',
                         'Cannot update memory due to %s.'), state)
            raise UserError(cause=cause)
    except vim.fault.AlreadyUpgraded as e:
        logger.info("VM is already upgraded to %s.", e)
    except UserError as userError:
        raise userError
    except Exception:
        cause = _(_T('Add.memory.failed.error',
                     'Memory addition failed due to %s.'),
                  traceback.format_exc())
        raise UserError(cause=cause)