#!/usr/bin/env ruby

# ---------------------------------------------------------------------------- #
# Copyright 2002-2017, 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.                                               #
# ---------------------------------------------------------------------------- #

ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)

if !ONE_LOCATION
    RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
    VAR_LOCATION="/var/lib/one" if !defined?(VAR_LOCATION)
else
    RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
    VAR_LOCATION=ONE_LOCATION+"/var" if !defined?(VAR_LOCATION)
end

$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)

require 'vcenter_driver'

drv_action_enc = ARGV[0]
id             = ARGV[1]

drv_action = OpenNebula::XMLElement.new
drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA')

img_path     = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/PATH"]
host_id      = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_ONE_HOST_ID"]
ds_ref       = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_REF"]
ds_image_dir = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_IMAGE_DIR"] || "one"
md5          = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/MD5"]
sha1         = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/SHA1"]
nodecomp     = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/NO_DECOMPRESS"]
limit_bw     = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LIMIT_TRANSFER_BW"]

check_valid img_path, "img_path"

# if image is already in a vCenter datastore return the path
if img_path.start_with? "vcenter://"
    puts img_path.sub("vcenter://","")
    exit(0)
end

temp_file = nil
filename = File.basename(img_path)
target_path = "#{ds_image_dir}/#{id}"

# If image is in a remote http location it has to be downloaded
# or if is a zipped file it has to be unzipped in a temp folder

if VCenterDriver::FileHelper.is_remote_or_needs_unpack?(img_path)
    temp_folder = File.join(VAR_LOCATION, "vcenter/#{target_path}")
    temp_file = File.join(temp_folder, File.basename(img_path))

    # Create tmp directory
    FileUtils.mkdir_p(temp_folder)

    # Specify downloader args
    downsh_args = " "
    downsh_args << "--md5 #{md5} " if md5 && !md5.empty? && !md5.eql?("-")
    downsh_args << "--sha1 #{sha1} " if sha1 && !sha1.empty?
    downsh_args << "--nodecomp " if nodecomp && !nodecomp.empty?
    downsh_args << "--limit #{limit_bw} " if limit_bw && !limit_bw.empty?

    downloader = "#{File.dirname(__FILE__)}/../downloader.sh #{downsh_args}"

    rc = system("#{downloader} #{img_path} #{temp_file}")

    if !rc
        STDERR.puts "Error downloading #{img_path}"
        FileUtils.rm_rf(temp_file)
        exit -1
    end

    img_path = temp_file
end

# Time to upload files to vCenter
files_to_upload = []

info = VCenterDriver::FileHelper.vcenter_file_info(img_path)
extension = info[:extension] || ''

case info[:type]
when :standalone
    files_to_upload << info[:file]
when :flat
    files_to_upload = info[:flat_files]
    files_to_upload << info[:file]
end

files_to_upload.each_with_index do |f, index|

    path = "#{target_path}/#{File.basename(f)}"

    # Change path for gzipped standalone file
    if(target_path == File.basename(f))
        path = "#{target_path}/#{filename}"

        # remove gz or bz2 if part of filename
        if path.end_with?("gz") && VCenterDriver::FileHelper.is_vmdk?(f)
            path.gsub!(/gz$/,'')
        end

        if path.end_with?("bz2") && VCenterDriver::FileHelper.is_vmdk?(f)
            path.gsub!(/bz2$/,'')
        end
    end

    # Change path if vmdk is part of filename but it's not the extension
    if /[^.]+vmdk$/.match(path) && VCenterDriver::FileHelper.is_vmdk?(f)
        path.gsub!(/vmdk$/,'')
        extension = '.vmdk'
    end

    # Add iso extension if file is an ISO file
    if VCenterDriver::FileHelper.is_iso?(f)
        path = "#{File.dirname(path)}/#{File.basename(path,".*")}"
        extension = '.iso'
    end

    if index == files_to_upload.size - 1
        uploader_args = host_id + " " + ds_ref + " " +
            "#{path}#{extension}" + " " + f
    else
        uploader_args = host_id + " " + ds_ref + " " +
                        path + " " + f + " &> /dev/null"
    end

    cmd = "#{File.dirname(__FILE__)}/../vcenter_uploader.rb #{uploader_args}"
    rc = system(cmd)

    if !rc
        STDERR.puts "Cannot upload file #{f}"
        FileUtils.rm_rf(temp_file) if temp_file
        exit(-1)
    end
end

FileUtils.rm_rf(temp_file) if temp_file

