#!/usr/bin/ruby

# -------------------------------------------------------------------------- #
# 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.                                             #
#--------------------------------------------------------------------------- #

# %%RUBYGEMS_SETUP_BEGIN%%
require 'load_opennebula_paths'
# %%RUBYGEMS_SETUP_END%%

###############################################################################
# This script moves images/directories across system_ds in different Hosts. When
# used for the system datastore the script will receive the directory ARGUMENT.
# This script will be also called for the image TM for each disk to perform
# setup tasks on the target node.
#
# Called during stop/undeploy/resume (where src and dst are either a host or
# the frontend):
# - For each disk: <src_disk_path> <dst_disk_path> <vmid> <imgds_id>
# - Finally: <src_vmdir> <dst_vmdir> <vmid> <sysds_id>
###############################################################################
#
# ARGUMENTS:
#    <hostA:system_ds/disk.i|hostB:system_ds/disk.i> vmid imgds_id
#    OR
#    <hostA:system_ds/|hostB:system_ds/> vmid sysds_id
#   - hostX is the target host to deploy the VM
#   - system_ds is the path for the system datastore in the host
#   - vmid is the id of the VM
#   - dsid is the target datastore (0 is the system datastore)
# STDIN: -
# RETURNS: -
#
###############################################################################

require_relative '../../datastore/lvm'
require_relative '../lib/tm_action'

arg_src = ARGV[0]
arg_dst = ARGV[1]
arg_vmid = ARGV[2]
_arg_imgds_id = ARGV[3]

src = TransferManager::Action::Location.new(arg_src)
dst = TransferManager::Action::Location.new(arg_dst)

action = TransferManager::Action.new(:vm_id => arg_vmid, :action_name => 'mv')

if src.disk?
    lcm_state = action.vm.lcm_state

    src_lvmdisk = MAD::LVMVM.new(action.vm.to_xml).disk(src.disk_id)

    # This is a "projection" of the future disk; does not exist yet
    dst_lvmdisk = src_lvmdisk.dup
    dst_lvmdisk.path = dst.path

    # Deactivate LV at source, unless during `onevm resume` (after stop or undeploy)
    # 9(49)  = PROLOG_RESUME(+FAILURE)
    # 31(50) = PROLOG_UNDEPLOY(+FAILURE)
    # 60(61) = PROLOG_MIGRATE_UNKNOWN(+FAILURE)
    unless [9, 49, 31, 50, 60, 61].include?(lcm_state)
        MAD::LVMWrapper.with_lvm_lock(src_lvmdisk.lv.vgname) do
            MAD.run(src.host, MAD::LVMWrapper.lvmsync(src_lvmdisk.activate_sh(false)),
                    "Error deactivating disk #{src.path}")
        end
    end

    # Activate LV at destination, unless during `onevm stop` or `onevm undeploy`
    # 10(41) = EPILOG_STOP(+FAILURE)
    # 30(42) = EPILOG_UNDEPLOY(+FAILURE)
    unless [10, 41, 30, 42].include?(lcm_state)
        # Activate LV at destination
        MAD::LVMWrapper.with_lvm_lock(dst_lvmdisk.lv.vgname) do
            MAD.run(dst.host, MAD::LVMWrapper.lvmsync(dst_lvmdisk.activate_sh.strip),
                    "Error activating disk #{dst.path}")
        end
    end

    # In FT mode, we don't have access to source host and ssh/mv does nothing. Create symbolic
    # link manually in that case.
    # 60(61) = PROLOG_MIGRATE_UNKNOWN(+FAILURE)
    if [60, 61].include?(lcm_state)
        dst_lvmdisk.symlink
    end
else
    # After managing LV de/activation on different hosts, transfer normal files & symlinks
    action.tm_call('ssh')
end
