#!/bin/bash

# -------------------------------------------------------------------------- #
# Copyright 2002-2025, OpenNebula Project, OpenNebula Systems                #
#                                                                            #
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
# not use this file except in compliance with the License. You may obtain    #
# a copy of the License at                                                   #
#                                                                            #
# http://www.apache.org/licenses/LICENSE-2.0                                 #
#                                                                            #
# Unless required by applicable law or agreed to in writing, software        #
# distributed under the License is distributed on an "AS IS" BASIS,          #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
# See the License for the specific language governing permissions and        #
# limitations under the License.                                             #
#--------------------------------------------------------------------------- #

DRIVER_PATH=$(dirname $0)
DOMAIN=$1

# Exit if no stdin data is available
if [ -t 0 ]; then
    exit 0
fi

# Read data from stdin data. Extracting the VCPU and MEMORY
XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin"

unset i XPATH_ELEMENTS

while IFS= read -r -d '' element; do
    XPATH_ELEMENTS[i++]="$element"
done < <($XPATH     /VMM_DRIVER_ACTION_DATA/VM/TEMPLATE/VCPU \
                    /VMM_DRIVER_ACTION_DATA/VM/TEMPLATE/MEMORY \
                    /VMM_DRIVER_ACTION_DATA/VM/TEMPLATE/MEMORY_RESIZE_MODE \
                    /VMM_DRIVER_ACTION_DATA/VM/TEMPLATE/RESIZE/VCPU \
                    /VMM_DRIVER_ACTION_DATA/VM/TEMPLATE/RESIZE/MEMORY)

unset i

VCPU="${XPATH_ELEMENTS[i++]}"
MEM="${XPATH_ELEMENTS[i++]}"
MEM_RESIZE_MODE="${XPATH_ELEMENTS[i++]}"
VCPU_OLD="${XPATH_ELEMENTS[i++]}"
MEM_OLD="${XPATH_ELEMENTS[i++]}"

source $(dirname $0)/../../etc/vmm/kvm/kvmrc
source $(dirname $0)/../../scripts_common.sh

# Resize mem
if [ ! -z "$MEM" -a "$MEM" -ne "$MEM_OLD" ]; then
    # Compact memory
    if [ "x$CLEANUP_MEMORY_ON_START" = "xyes" ]; then
        (sudo -l | grep -q sysctl) && sudo -n sysctl vm.drop_caches=3 vm.compact_memory=1 >/dev/null
    fi

    if [ "x$MEM_RESIZE_MODE" = "xHOTPLUG" ]; then
        # Hotplug

        # Extract node id from virsh dumpxml
        XML_INFO=$(virsh --connect ${LIBVIRT_URI} dumpxml ${DOMAIN})
        IFS= read -r -d '' NODE_ID < <(echo "$XML_INFO" | $XPATH --subtree /domain/cpu/numa/cell/@id)

        MEM_DIFF=$(expr $MEM - $MEM_OLD)

        case $MEM_DIFF in
        -*)
        ACTION="detach-device"
        MEM_DIFF=${MEM_DIFF#-}
        ;;
        *)
        ACTION="attach-device"
        ;;
        esac

        # Create tmp file with memory device specification
        TMPFILE=$(mktemp /tmp/resize.XXXXXX)
        echo -e "<memory model='dimm'>\n\t<target>\n\
                <size unit='MiB'>$MEM_DIFF</size>\n\
                <node>$NODE_ID</node>\n\t</target>\n</memory>" >$TMPFILE

        # Add memory to VM
        exec_and_log "virsh --connect ${LIBVIRT_URI} ${ACTION} ${DOMAIN} ${TMPFILE} --live"

        # Cleanup
        rm $TMPFILE
    else
        # Ballooning (default)
        exec_and_log "virsh --connect ${LIBVIRT_URI} setmem ${DOMAIN} $((${MEM}*1024))"
    fi

    # Compact memory
    if [ "x$CLEANUP_MEMORY_ON_STOP" = "xyes" ]; then
        (sudo -l | grep -q sysctl) && sudo -n sysctl vm.drop_caches=3 vm.compact_memory=1 &>/dev/null &
    fi
fi

# Resize VCPU
if [ ! -z "$VCPU" -a "$VCPU" -ne "$VCPU_OLD" ]; then
    exec_and_log "virsh --connect ${LIBVIRT_URI} setvcpus ${DOMAIN} ${VCPU} --live --hotpluggable" \
    "Failed to resize VCPU to ${VCPU} on ${DOMAIN}"
fi
