diff --git a/content/automate/ManageIQ/Transformation/Common.class/__methods__/acquiretransformationhost.rb b/content/automate/ManageIQ/Transformation/Common.class/__methods__/acquiretransformationhost.rb index eb7f3143b..44c5daa45 100644 --- a/content/automate/ManageIQ/Transformation/Common.class/__methods__/acquiretransformationhost.rb +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/acquiretransformationhost.rb @@ -9,7 +9,7 @@ def initialize(handle = $evm) end def main - if @task.get_option(:transformation_host_id).nil? + if @task.conversion_host.nil? @handle.root['ae_result'] = 'retry' @handle.root['ae_retry_server_affinity'] = true @handle.root['ae_retry_interval'] = 15.seconds diff --git a/content/automate/ManageIQ/Transformation/Common.class/__methods__/assesstransformation.rb b/content/automate/ManageIQ/Transformation/Common.class/__methods__/assesstransformation.rb index 771459f77..bb94ac168 100644 --- a/content/automate/ManageIQ/Transformation/Common.class/__methods__/assesstransformation.rb +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/assesstransformation.rb @@ -3,80 +3,13 @@ module Automate module Transformation module Common class AssessTransformation - SUPPORTED_SOURCE_EMS_TYPES = ['vmwarews'].freeze - SUPPORTED_DESTINATION_EMS_TYPES = ['rhevm'].freeze - def initialize(handle = $evm) @handle = handle @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) @source_vm = ManageIQ::Automate::Transformation::Common::Utils.source_vm(@handle) end - def virtv2v_networks - @source_vm.hardware.nics.select { |n| n.device_type == 'ethernet' }.collect do |nic| - source_network = nic.lan - destination_network = @task.transformation_destination(source_network) - raise "[#{@source_vm.name}] NIC #{nic.device_name} [#{source_network.name}] has no mapping. Aborting." if destination_network.nil? - { - :source => source_network.name, - :destination => destination_network.name, - :mac_address => nic.address - } - end - end - - def virtv2v_disks - @source_vm.hardware.disks.select { |d| d.device_type == 'disk' }.collect do |disk| - source_storage = disk.storage - destination_storage = @task.transformation_destination(disk.storage) - raise "[#{@source_vm.name}] Disk #{disk.device_name} [#{source_storage.name}] has no mapping. Aborting." if destination_storage.nil? - { - :path => disk.filename, - :size => disk.size, - :percent => 0, - :weight => disk.size.to_f / @source_vm.allocated_disk_storage.to_f * 100 - } - end - end - - def source_cluster - @source_cluster ||= @source_vm.ems_cluster.tap do |cluster| - raise "No source cluster" if cluster.nil? - end - end - - def source_ems - @source_ems ||= @source_vm.ext_management_system.tap do |ems| - raise "No source EMS" if ems.nil? - end - end - - def destination_cluster - @destination_cluster ||= @task.transformation_destination(source_cluster).tap do |cluster| - raise "No destination cluster" if cluster.nil? - end - end - - def destination_ems - @destination_ems ||= destination_cluster.ext_management_system.tap do |ems| - raise "No destination EMS" if ems.nil? - end - end - - def transformation_type - raise "Unsupported source EMS type: #{source_ems.emstype}." unless SUPPORTED_SOURCE_EMS_TYPES.include?(source_ems.emstype) - raise "Unsupported destination EMS type: #{destination_ems.emstype}." unless SUPPORTED_DESTINATION_EMS_TYPES.include?(destination_ems.emstype) - @handle.set_state_var(:source_ems_type, source_ems.emstype) - @handle.set_state_var(:destination_ems_type, destination_ems.emstype) - "#{source_ems.emstype}2#{destination_ems.emstype}" - end - def populate_task_options - @task.set_option(:source_ems_id, source_ems.id) - @task.set_option(:destination_ems_id, destination_ems.id) - @task.set_option(:virtv2v_networks, virtv2v_networks) - @task.set_option(:virtv2v_disks, virtv2v_disks) - @task.set_option(:transformation_type, transformation_type) @task.set_option(:source_vm_power_state, @source_vm.power_state) @task.set_option(:collapse_snapshots, true) @task.set_option(:power_off, true) @@ -91,6 +24,7 @@ def populate_factory_config end def main + @task.set_option('cancel_requested', true) unless @task.preflight_check %w(task_options factory_config).each { |ci| send("populate_#{ci}") } rescue => e @handle.set_state_var(:ae_state_progress, 'message' => e.message) diff --git a/content/automate/ManageIQ/Transformation/Common.class/__methods__/killvirtv2v.rb b/content/automate/ManageIQ/Transformation/Common.class/__methods__/killvirtv2v.rb new file mode 100644 index 000000000..490384b24 --- /dev/null +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/killvirtv2v.rb @@ -0,0 +1,39 @@ +module ManageIQ + module Automate + module Transformation + module Common + class KillVirtV2V + def initialize(handle = $evm) + @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + end + + def task_virtv2v_state + return if @task.get_option(:virtv2v_started_on).blank? || @task.get_option(:virtv2v_finished_on).present? || @task.get_option(:virtv2v_wrapper).blank? + @task.get_conversion_state + end + + def kill_signal + if @handle.get_state_var('virtv2v_graceful_kill') + 'KILL' + else + @handle.set_state_var('virtv2v_graceful_kill', true) + @handle.root['ae_result'] = 'retry' + @handle.root['ae_retry_interval'] = '30.seconds' + 'TERM' + end + end + + def main + @task.kill_virtv2v(kill_signal) unless task_virtv2v_state.nil? + rescue => e + @handle.set_state_var(:ae_state_progress, 'message' => e.message) + raise + end + end + end + end + end +end + +ManageIQ::Automate::Transformation::Common::KillVirtV2V.new.main diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/utils.yaml b/content/automate/ManageIQ/Transformation/Common.class/__methods__/killvirtv2v.yaml similarity index 69% rename from content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/utils.yaml rename to content/automate/ManageIQ/Transformation/Common.class/__methods__/killvirtv2v.yaml index 94612ce92..ec5a33d54 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/utils.yaml +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/killvirtv2v.yaml @@ -3,11 +3,13 @@ object_type: method version: 1.0 object: attributes: - name: Utils + name: KillVirtV2V display_name: description: scope: instance language: ruby location: inline + embedded_methods: + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Common.class/__methods__/setmigrated.rb b/content/automate/ManageIQ/Transformation/Common.class/__methods__/setmigrated.rb new file mode 100644 index 000000000..c92dd60e6 --- /dev/null +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/setmigrated.rb @@ -0,0 +1,23 @@ +module ManageIQ + module Automate + module Transformation + module Common + class SetMigrated + def initialize(handle = $evm) + @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + end + + def main + @task.mark_vm_migrated + rescue => e + @handle.set_state_var(:ae_state_progress, 'message' => e.message) + raise + end + end + end + end + end +end + +ManageIQ::Automate::Transformation::Common::SetMigrated.new.main diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/setmigrated.yaml b/content/automate/ManageIQ/Transformation/Common.class/__methods__/setmigrated.yaml similarity index 80% rename from content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/setmigrated.yaml rename to content/automate/ManageIQ/Transformation/Common.class/__methods__/setmigrated.yaml index 51ff96a32..e7c229ef7 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/setmigrated.yaml +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/setmigrated.yaml @@ -10,6 +10,6 @@ object: language: ruby location: inline embedded_methods: - - "/Transformation/Infrastructure/VM/vmwarews/Utils" + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmchecktransformed.rb b/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmchecktransformed.rb new file mode 100644 index 000000000..48340a028 --- /dev/null +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmchecktransformed.rb @@ -0,0 +1,56 @@ +module ManageIQ + module Automate + module Transformation + module Common + class VMCheckTransformed + def initialize(handle = $evm) + @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + end + + def set_retry + @handle.root['ae_result'] = 'retry' + @handle.root['ae_retry_server_affinity'] = true + @handle.log(:info, "Disk transformation is not finished. Checking in #{@handle.root['ae_retry_interval']}") + end + + def update_total_percentage + virtv2v_disks = @task[:options][:virtv2v_disks] + converted_disks = virtv2v_disks.reject { |d| d[:percent].zero? } + message, percent = nil, nil + if converted_disks.empty? + percent = 1 + message = 'Disks transformation is initializing.' + else + percent = 0 + converted_disks.each { |disk| percent += (disk[:percent].to_f * disk[:weight].to_f / 100.0) } + message = "Converting disk #{converted_disks.length} / #{virtv2v_disks.length} [#{percent.round(2)}%]." + end + [message, percent] + end + + def main + @task.get_conversion_state + + case @task.get_option(:virtv2v_status) + when 'active' + message, percent = update_total_percentage + @handle.set_state_var(:ae_state_progress, 'message' => message, 'percent' => percent.round(2)) + set_retry + when 'failed' + @handle.set_state_var(:ae_state_progress, 'message' => 'Disks transformation failed.') + raise "Disks transformation failed." + when 'succeeded' + @handle.set_state_var(:ae_state_progress, 'message' => 'Disks transformation succeeded.', 'percent' => 100) + end + rescue => e + @handle.set_state_var(:ae_state_progress, 'message' => e.message) + raise + end + end + end + end + end +end + +ManageIQ::Automate::Transformation::Common::VMCheckTransformed.new.main diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmchecktransformed.yaml b/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmchecktransformed.yaml similarity index 66% rename from content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmchecktransformed.yaml rename to content/automate/ManageIQ/Transformation/Common.class/__methods__/vmchecktransformed.yaml index 1a990a161..b30cceda2 100644 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmchecktransformed.yaml +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmchecktransformed.yaml @@ -10,7 +10,6 @@ object: language: ruby location: inline embedded_methods: - - "/Transformation/TransformationHosts/Common/Utils" - - "/Transformation/TransformationHosts/ovirt_host/Utils" + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmtransform.rb b/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmtransform.rb new file mode 100644 index 000000000..25a5287d5 --- /dev/null +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmtransform.rb @@ -0,0 +1,27 @@ +module ManageIQ + module Automate + module Transformation + module Common + class VMTransform + def initialize(handle = $evm) + @debug = false + @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + end + + def main + # WARNING: Enable at your own risk, as it may lead to sensitive data leak + # @handle.log(:info, "JSON Input:\n#{JSON.pretty_generate(@task.conversion_options)}") if @debug + + @task.run_conversion + rescue => e + @handle.set_state_var(:ae_state_progress, 'message' => e.message) + raise + end + end + end + end + end +end + +ManageIQ::Automate::Transformation::Common::VMTransform.new.main diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/ovirt_host.class/__methods__/utils.yaml b/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmtransform.yaml similarity index 69% rename from content/automate/ManageIQ/Transformation/TransformationHosts/ovirt_host.class/__methods__/utils.yaml rename to content/automate/ManageIQ/Transformation/Common.class/__methods__/vmtransform.yaml index 94612ce92..a6cf1ff64 100644 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/ovirt_host.class/__methods__/utils.yaml +++ b/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmtransform.yaml @@ -3,11 +3,13 @@ object_type: method version: 1.0 object: attributes: - name: Utils + name: VMTransform display_name: description: scope: instance language: ruby location: inline + embedded_methods: + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon.rb index e2b3fe02f..6ce8a74a3 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon.rb +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon.rb @@ -7,20 +7,20 @@ module Common class CheckPoweredOn def initialize(handle = $evm) @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + transformation_phase = ManageIQ::Automate::Transformation::Common::Utils.transformation_phase(@handle) + case transformation_phase + when 'transformation' + @vm = ManageIQ::Automate::Transformation::Common::Utils.destination_vm(@handle) + when 'cleanup' + @vm = ManageIQ::Automate::Transformation::Common::Utils.source_vm(@handle) + end end def main - if @handle.root['service_template_transformation_plan_task'].blank? - task = @handle.vmdb(:service_template_transformation_plan_task).find_by(:id => @handle.root['service_template_transformation_plan_task_id']) - vm = task.source if task.present? - else - task = @handle.root['service_template_transformation_plan_task'] - vm = @handle.vmdb(:vm).find_by(:id => task.get_option(:destination_vm_id)) if task.present? - end - return if vm.blank? - @handle.log(:info, "Target VM: #{vm.name} [#{vm.vendor}]") - return if task.get_option(:source_vm_power_state) != 'on' - if vm.power_state != 'on' + return if @vm.blank? + return if @task.get_option(:source_vm_power_state) != 'on' + if @vm.power_state != 'on' @handle.root["ae_result"] = "retry" @handle.root["ae_retry_interval"] = "15.seconds" end diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon.yaml b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon.yaml index bbb581ca3..80f7e8b0e 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon.yaml +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon.yaml @@ -9,5 +9,7 @@ object: scope: instance language: ruby location: inline + embedded_methods: + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory.rb index 2e4185436..89ca8cf37 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory.rb +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory.rb @@ -7,41 +7,17 @@ module Common class CheckVmInInventory def initialize(handle = $evm) @handle = handle - end - - def log_and_raise(message) - @handle.log(:error, message) - raise "ERROR - #{message}" - end - - def task - @task ||= @handle.root["service_template_transformation_plan_task"].tap do |task| - log_and_raise('A service_template_transformation_plan_task is needed for this method to continue') if task.nil? - end - end - - def source_vm - @source_vm ||= task.source.tap do |vm| - log_and_raise('Source VM has not been defined in the task') if vm.nil? - end - end - - def destination_vm - destination_ems = task.transformation_destination(source_vm.ems_cluster).ext_management_system - @destination_vm ||= @handle.vmdb(:vm).find_by(:name => source_vm.name, :ems_id => destination_ems.id) - end - - def set_retry(message = nil, interval = '1.minutes') - @handle.log(:info, message) if message.present? - @handle.root['ae_result'] = 'retry' - @handle.root['ae_retry_interval'] = interval + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + @source_vm = ManageIQ::Automate::Transformation::Common::Utils.source_vm(@handle) end def main - if destination_vm.blank? - set_retry('VM is not yet in the destination provider inventory', '15.seconds') + destination_vm = @handle.vmdb(:vm).find_by(:name => @source_vm.name, :ems_id => @task.destination_ems.id) + if destination_vm.nil? + @handle.root['ae_result'] = 'retry' + @handle.root['ae_retry_interval'] = '15.seconds' else - task.set_option(:destination_vm_id, destination_vm.id) + @task.set_option(:destination_vm_id, destination_vm.id) end rescue => e @handle.set_state_var(:ae_state_progress, 'message' => e.message) diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory.yaml b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory.yaml index ddb9c49e9..61b536792 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory.yaml +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory.yaml @@ -9,5 +9,7 @@ object: scope: instance language: ruby location: inline + embedded_methods: + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/collapsesnapshots.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/collapsesnapshots.rb new file mode 100644 index 000000000..3b7b1dfd8 --- /dev/null +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/collapsesnapshots.rb @@ -0,0 +1,31 @@ +module ManageIQ + module Automate + module Transformation + module Infrastructure + module VM + module VMware + class CollapseSnapshots + def initialize(handle = $evm) + @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + @source_vm = ManageIQ::Automate::Transformation::Common::Utils.source_vm(@handle) + end + + def main + return unless @source_vm.vendor == 'vmware' + return if @source_vm.snapshots.empty? + raise "VM '#{@source_vm.name}' has snapshots, but we are not allowed to collapse them. Exiting." unless @task.get_option(:collapse_snapshots) + @source_vm.remove_all_snapshots + rescue => e + @handle.set_state_var(:ae_state_progress, 'message' => e.message) + raise + end + end + end + end + end + end + end +end + +ManageIQ::Automate::Transformation::Infrastructure::VM::VMware::CollapseSnapshots.new.main diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/collapsesnapshots.yaml b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/collapsesnapshots.yaml similarity index 80% rename from content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/collapsesnapshots.yaml rename to content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/collapsesnapshots.yaml index 098568861..5a977d87d 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/collapsesnapshots.yaml +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/collapsesnapshots.yaml @@ -10,6 +10,6 @@ object: language: ruby location: inline embedded_methods: - - "/Transformation/Infrastructure/VM/vmwarews/Utils" + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweroff.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweroff.rb index ec0dad827..3ee601b53 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweroff.rb +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweroff.rb @@ -7,26 +7,20 @@ module Common class PowerOff def initialize(handle = $evm) @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + @source_vm = ManageIQ::Automate::Transformation::Common::Utils.source_vm(@handle) end def main - task = @handle.root['service_template_transformation_plan_task'] - source_vm = task.source - - if source_vm.power_state == 'off' - @handle.log(:info, "VM '#{source_vm.name}' is already off. Nothing to do.") - elsif task.get_option(:power_off) - @handle.log(:info, "VM '#{source_vm.name} is powered on. Let's shut it down.") - if @handle.state_var_exist?(:vm_shutdown_in_progress) - source_vm.stop if @handle.root['ae_state_retries'].to_i > 10 - else - source_vm.shutdown_guest - @handle.set_state_var(:vm_shutdown_in_progress, true) - end - @handle.root['ae_result'] = 'retry' + return if @source_vm.power_state == 'off' + raise "VM '#{@source_vm.name} is powered on, but we are not allowed to shut it down. Aborting." unless @task.get_option(:power_off) + if @handle.state_var_exist?(:vm_shutdown_in_progress) + @source_vm.stop if @handle.root['ae_state_retries'].to_i > 10 else - raise "VM '#{source_vm.name} is powered on, but we are not allowed to shut it down. Aborting." + @source_vm.shutdown_guest + @handle.set_state_var(:vm_shutdown_in_progress, true) end + @handle.root['ae_result'] = 'retry' rescue => e @handle.set_state_var(:ae_state_progress, 'message' => e.message) raise diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweroff.yaml b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweroff.yaml index 57c96587a..19d592eeb 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweroff.yaml +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweroff.yaml @@ -9,5 +9,7 @@ object: scope: instance language: ruby location: inline + embedded_methods: + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweron.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweron.rb index 205306f76..61e609c6f 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweron.rb +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweron.rb @@ -7,18 +7,19 @@ module Common class PowerOn def initialize(handle = $evm) @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + transformation_phase = ManageIQ::Automate::Transformation::Common::Utils.transformation_phase(@handle) + case transformation_phase + when 'transformation' + @vm = ManageIQ::Automate::Transformation::Common::Utils.destination_vm(@handle) + when 'cleanup' + @vm = ManageIQ::Automate::Transformation::Common::Utils.source_vm(@handle) + end end def main - if @handle.root['service_template_transformation_plan_task'].blank? - task = @handle.vmdb(:service_template_transformation_plan_task).find_by(:id => @handle.root['service_template_transformation_plan_task_id']) - vm = task.source if task.present? - else - task = @handle.root['service_template_transformation_plan_task'] - vm = @handle.vmdb(:vm).find_by(:id => task.get_option(:destination_vm_id)) if task.present? - end - return if vm.blank? - vm.start if task.get_option(:source_vm_power_state) == 'on' + return if @vm.blank? + @vm.start if @task.get_option(:source_vm_power_state) == 'on' rescue => e @handle.set_state_var(:ae_state_progress, 'message' => e.message) raise diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweron.yaml b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweron.yaml index aa10bf7bb..1ff4c3e6f 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweron.yaml +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/poweron.yaml @@ -9,5 +9,7 @@ object: scope: instance language: ruby location: inline + embedded_methods: + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes.rb index a90f0e4d3..23d6383da 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes.rb +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes.rb @@ -9,67 +9,46 @@ class RestoreVmAttributes def initialize(handle = $evm) @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + @source_vm = ManageIQ::Automate::Transformation::Common::Utils.source_vm(@handle) + @destination_vm = ManageIQ::Automate::Transformation::Common::Utils.destination_vm(@handle) end - def log_and_raise(message) - @handle.log(:error, message) - raise "ERROR - #{message}" - end - - def task - @task ||= @handle.root["service_template_transformation_plan_task"].tap do |task| - log_and_raise('A service_template_transformation_plan_task is needed for this method to continue') if task.nil? - end - end - - def source_vm - @vm ||= task.source.tap do |vm| - log_and_raise('Source VM has not been defined in the task') if vm.nil? - end - end - - def destination_vm - log_and_raise('destination_vm_id is blank') if task.get_option(:destination_vm_id).blank? - @destination_vm ||= @handle.vmdb(:vm).find_by(:id => task.get_option(:destination_vm_id)).tap do |vm| - log_and_raise('Destination VM not found in the database after migration') if vm.nil? - end - end - - def vm_restore_service(source_vm, destination_vm) - if source_vm.service - destination_vm.add_to_service(source_vm.service) - source_vm.remove_from_service + def vm_restore_service + if @source_vm.service + @destination_vm.add_to_service(@source_vm.service) + @source_vm.remove_from_service end end - def vm_restore_tags(source_vm, destination_vm) - source_vm.tags.each do |tag| - destination_vm.tag_assign(tag) unless tag =~ /^folder_path_/ + def vm_restore_tags + @source_vm.tags.each do |tag| + @destination_vm.tag_assign(tag) unless tag =~ /^folder_path_/ end end - def vm_restore_custom_attributes(source_vm, destination_vm) - source_vm.custom_keys.each do |ca| - destination_vm.custom_set(ca, source_vm.custom_get(ca)) + def vm_restore_custom_attributes + @source_vm.custom_keys.each do |ca| + @destination_vm.custom_set(ca, @source_vm.custom_get(ca)) end end - def vm_restore_ownership(source_vm, destination_vm) - owner = source_vm.owner - miq_group = @handle.vmdb(:miq_group).find_by(:id => source_vm.miq_group_id) - destination_vm.owner = owner if owner.present? - destination_vm.group = miq_group if miq_group.present? + def vm_restore_ownership + owner = @source_vm.owner + miq_group = @handle.vmdb(:miq_group).find_by(:id => @source_vm.miq_group_id) + @destination_vm.owner = owner if owner.present? + @destination_vm.group = miq_group if miq_group.present? end - def vm_restore_retirement(source_vm, destination_vm) - retirement_datetime = source_vm.retires_on - retirement_warn = source_vm.retirement_warn - destination_vm.retires_on = retirement_datetime if retirement_datetime.present? - destination_vm.retirement_warn = retirement_warn if retirement_warn.present? + def vm_restore_retirement + retirement_datetime = @source_vm.retires_on + retirement_warn = @source_vm.retirement_warn + @destination_vm.retires_on = retirement_datetime if retirement_datetime.present? + @destination_vm.retirement_warn = retirement_warn if retirement_warn.present? end def main - IDENTITY_ITEMS.each { |item| send("vm_restore_#{item}", source_vm, destination_vm) } + IDENTITY_ITEMS.each { |item| send("vm_restore_#{item}") } rescue => e @handle.set_state_var(:ae_state_progress, 'message' => e.message) raise diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes.yaml b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes.yaml index 3b146b42e..48c2a9df5 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes.yaml +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes.yaml @@ -9,5 +9,7 @@ object: scope: instance language: ruby location: inline + embedded_methods: + - "/Transformation/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/setdescription.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/setdescription.rb similarity index 67% rename from content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/setdescription.rb rename to content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/setdescription.rb index 7460f6486..fe172a664 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/setdescription.rb +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/setdescription.rb @@ -7,15 +7,14 @@ module RedHat class SetDescription def initialize(handle = $evm) @handle = handle + @task = ManageIQ::Automate::Transformation::Common::Utils.task(@handle) + @destination_vm = ManageIQ::Automate::Transformation::Common::Utils.destination_vm(@handle) end def main - task = @handle.root['service_template_transformation_plan_task'] - destination_vm = @handle.vmdb(:vm).find_by(:id => task.get_option(:destination_vm_id)) - destination_ems = destination_vm.ext_management_system - + return unless @destination_vm.vendor == 'redhat' description = "Migrated by Cloudforms on #{Time.now.utc}." - ManageIQ::Automate::Transformation::Infrastructure::VM::RedHat::Utils.new(destination_ems).vm_set_description(destination_vm, description) + ManageIQ::Automate::Transformation::Infrastructure::VM::RedHat::Utils.new(@task.destination_ems).vm_set_description(@destination_vm, description) rescue => e @handle.set_state_var(:ae_state_progress, 'message' => e.message) raise diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/setdescription.yaml b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/setdescription.yaml similarity index 88% rename from content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/setdescription.yaml rename to content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/setdescription.yaml index 095fa0e43..c9d717c62 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/setdescription.yaml +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/setdescription.yaml @@ -10,6 +10,7 @@ object: language: ruby location: inline embedded_methods: + - "/Transformation/Common/Utils" - "/Transformation/Infrastructure/VM/rhevm/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/utils.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/utils.rb index 3b0a8a96f..5d1f2163d 100644 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/utils.rb +++ b/content/automate/ManageIQ/Transformation/Infrastructure/VM/rhevm.class/__methods__/utils.rb @@ -17,84 +17,17 @@ def initialize(ems, handle = $evm) @connection = connection(@ems) end - def ems_get_export_domain - storage_domains_service.list.select { |domain_service| domain_service.type == OvirtSDK4::StorageDomainType::EXPORT }.first - end - - def vm_import(vm_name, cluster, storage_domain) - target_domain = storage_domains_service.list(:search => "name=#{storage_domain}").first - raise "Can't find storage domain #{storage_domain}" if target_domain.blank? - target_cluster = clusters_service.list(:search => "name=#{cluster}").first - raise "Can't find cluster #{cluster}" if target_cluster.blank? - vm = vm_find_in_export_domain(vm_name) - raise "Can't find VM #{vm_name} on export domain" if vm.blank? - export_domain_vm_service(vm.id).import( - :storage_domain => OvirtSDK4::StorageDomain.new(:id => target_domain.id), - :cluster => OvirtSDK4::Cluster.new(:id => target_cluster.id), - :vm => OvirtSDK4::Vm.new(:id => vm.id) - ) - end - - def vm_delete_from_export_domain(vm_name) - vm = vm_find_in_export_domain(vm_name) - raise "Can't find VM #{vm_name} on export domain" if vm.blank? - @handle.log(:info, "About to remove VM: #{vm_name}") - export_domain_vm_service(vm.id).remove - end - def vm_find_by_name(vm_name) vms_service.list(:search => "name=#{vm_name}").first end def vm_set_description(vm, description) vm_sdk = vm_find_by_name(vm.name) - raise "Can't find VM #{vm_name} in RHV provider" if vm_sdk.blank? + raise "Can't find VM #{vm.name} in RHV provider" if vm_sdk.blank? vm_service(vm_sdk.id).update(:description => description) true end - def vm_get_description(vm) - vm_sdk = vm_find_by_name(vm.name) - raise "Can't find VM #{vm_name} in RHV provider" if vm_sdk.blank? - vm_sdk.description - end - - def vm_enable_virtio_scsi(vm) - vm_sdk = vm_find_by_name(vm.name) - raise "Can't find VM #{vm_name}" if vm_sdk.blank? - # Enable virtio_scsi in the VM - vm_service(vm_sdk.id).update(:virtio_scsi => { :enabled => true }) - if vm_sdk.status == OvirtSDK4::VmStatus::DOWN - attachments_service = disk_attachments_service(vm_sdk.id) - attachments_service.list.each do |attachment| - attachments_service.attachment_service(attachment.id).update(:interface => OvirtSDK4::DiskInterface::VIRTIO_SCSI) - end - else - raise "VM must be down to enable virtio_scsi" - end - end - - def vm_set_nic_network(vm, nic, lan) - vm_sdk = vm_find_by_name(vm.name) - raise "Can't find VM #{vm_name} in RHV provider" if vm_sdk.blank? - target_network = vnic_profiles_service.list.select { |vnic_profile| vnic_profile.network.id == lan.uid_ems }.first - raise "Can't find network #{lan.name} in RHV provider" if target_network.blank? - nics_service = vm_nics_service(vm_sdk.id) - target_nic = nics_service.list.select { |nic_sdk| nic_sdk.name == nic.device_name }.first - raise "Can't find nic #{nic.name} for VM #{vm_name}" if target_nic.blank? - nics_service.nic_service(target_nic.id).update(:vnic_profile => target_network) - end - - def vm_get_disk_interfaces(vm) - disks = [] - vm_sdk = vm_find_by_name(vm.name) - raise "Can't find VM #{vm.name} in RHV provider" if vm_sdk.blank? - disk_attachments_service(vm_sdk.id).list.each do |attachment| - disks << attachment.interface - end - disks - end - private def ems_to_service_model(ems) @@ -108,52 +41,14 @@ def ems_to_service_model(ems) ems end - def vm_find_in_export_domain(vm_name) - export_domain_vms_service.list.select { |export_vm| export_vm.name == vm_name }.first - end - - def storage_domains_service - @connection.system_service.storage_domains_service - end - - def clusters_service - @connection.system_service.clusters_service - end - - def export_domain_vms_service - export_domain = ems_get_export_domain - raise "No export domain found!" if export_domain.blank? - storage_domains_service.storage_domain_service(export_domain.id).vms_service - end - - def export_domain_vm_service(id) - export_domain_vms_service.vm_service(id) - end - def vms_service @connection.system_service.vms_service end - def networks_service - @connection.system_service.networks_service - end - - def vnic_profiles_service - @connection.system_service.vnic_profiles_service - end - - def vm_nics_service(id) - vm_service(id).nics_service - end - def vm_service(id) vms_service.vm_service(id) end - def disk_attachments_service(id) - vm_service(id).disk_attachments_service - end - def connection(ems) connection = OvirtSDK4::Connection.new( :url => "https://#{ems.hostname}/ovirt-engine/api", diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__class__.yaml b/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__class__.yaml deleted file mode 100644 index 6d886911f..000000000 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__class__.yaml +++ /dev/null @@ -1,33 +0,0 @@ ---- -object_type: class -version: 1.0 -object: - attributes: - description: - display_name: VMware - name: vmwarews - type: - inherits: - visibility: - owner: - schema: - - field: - aetype: method - name: execute - display_name: - datatype: - priority: 1 - owner: - default_value: - substitute: true - message: create - visibility: - collect: - scope: - description: - condition: - on_entry: - on_exit: - on_error: - max_retries: - max_time: diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/collapsesnapshots.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/collapsesnapshots.rb deleted file mode 100644 index 0810983e3..000000000 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/collapsesnapshots.rb +++ /dev/null @@ -1,37 +0,0 @@ -module ManageIQ - module Automate - module Transformation - module Infrastructure - module VM - module VMware - class CollapseSnapshots - def initialize(handle = $evm) - @handle = handle - end - - def main - task = @handle.root['service_template_transformation_plan_task'] - source_vm = task.source - - if source_vm.snapshots.empty? - @handle.log(:info, "VM '#{source_vm.name}' has no snapshot. Nothing to do.") - elsif task.get_option(:collapse_snapshots) - @handle.log(:info, "VM '#{source_vm.name}' has snapshots and we need to collapse them.") - @handle.log(:info, "Collapsing snapshots for #{source_vm.name}") - source_vm.remove_all_snapshots - else - raise "VM '#{source_vm.name}' has snapshots, but we are not allowed to collapse them. Exiting." - end - rescue => e - @handle.set_state_var(:ae_state_progress, 'message' => e.message) - raise - end - end - end - end - end - end - end -end - -ManageIQ::Automate::Transformation::Infrastructure::VM::VMware::CollapseSnapshots.new.main diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/setmigrated.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/setmigrated.rb deleted file mode 100644 index 75cfb67cf..000000000 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/setmigrated.rb +++ /dev/null @@ -1,55 +0,0 @@ -module ManageIQ - module Automate - module Transformation - module Infrastructure - module VM - module VMware - class SetMigrated - def initialize(handle = $evm) - @handle = handle - end - - # Taken from / Service / Provisioning / StateMachines / Methods / configure_vm_hostname. - def check_name_collisions(new_name) - name_collisions = Hash.new(0) - @handle.vmdb(:vm).where("name = '#{new_name}'").each do |vm| - name_collisions[:active] += 1 if vm.active - name_collisions[:template] += 1 if vm.template - name_collisions[:retired] += 1 if vm.retired? - name_collisions[:archived] += 1 if vm.archived - name_collisions[:orphaned] += 1 if vm.orphaned - end - name_collisions_summary = "" - name_collisions.each { |k, v| name_collisions_summary += " - #{k}: #{v}" } - name_collisions_summary - end - - def rename_migrated_vm - task = @handle.root['service_template_transformation_plan_task'] - source_vm = task.source - new_name = "#{source_vm.name}_migrated" - - name_collisions = check_name_collisions(new_name) - raise "ERROR: #{new_name} already exists #{name_collisions}." if name_collisions.present? - - @handle.log(:info, "Renaming VM #{source_vm.name} to #{new_name}") - result = ManageIQ::Automate::Transformation::Infrastructure::VM::VMware::Utils.vm_rename(source_vm, new_name) - raise "VM rename for #{source_vm.name} to #{new_name} failed" unless result - end - - def main - task = @handle.root['service_template_transformation_plan_task'] - task.mark_vm_migrated - rescue => e - @handle.set_state_var(:ae_state_progress, 'message' => e.message) - raise - end - end - end - end - end - end - end -end - -ManageIQ::Automate::Transformation::Infrastructure::VM::VMware::SetMigrated.new.main diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/utils.rb b/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/utils.rb deleted file mode 100644 index e7c7dfe21..000000000 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/utils.rb +++ /dev/null @@ -1,30 +0,0 @@ -module ManageIQ - module Automate - module Transformation - module Infrastructure - module VM - module VMware - class Utils - require 'rbvmomi' - - def self.host_fingerprint(host) - require 'socket' - require 'openssl' - - tcp_client = TCPSocket.new(host.ipaddress, 443) - ssl_context = OpenSSL::SSL::SSLContext('SSLv23_client') - ssl_content.verify_mode = OpenSSL::SSL::VERIFY_NONE - ssl_client = OpenSSL::SSL::SSLSocker.new(tcp_client, ssl_context) - cert = OpenSSL::X509::Certificate.new(ssl_client.peer_cert) - ssl_client.sysclose - tcp_client.close - - Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":") - end - end - end - end - end - end - end -end diff --git a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/_missing.yaml b/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/_missing.yaml deleted file mode 100644 index 31e5fff8b..000000000 --- a/content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/_missing.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -object_type: instance -version: 1.0 -object: - attributes: - display_name: - name: ".missing" - inherits: - description: - fields: - - execute: - value: "${#_missing_instance}" diff --git a/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/posttransform.yaml b/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/posttransform.yaml index 59ac9f62d..72ea76f30 100644 --- a/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/posttransform.yaml +++ b/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/posttransform.yaml @@ -17,7 +17,7 @@ object: on_error: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 5, description => "Apply Right-Size Recommendation", task_message => "Migrating") - State5: - value: "/Transformation/Infrastructure/VM/${state_var#destination_ems_type}/SetDescription" + value: "/Transformation/Infrastructure/VM/Common/SetDescription" on_entry: /Transformation/TransformationThrottler.Watch ; /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 5, description => "Update description of VM", task_message => "Migrating") on_exit: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 5, description @@ -58,7 +58,7 @@ object: on_error: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 5, description => "Restore VM Attributes", task_message => "Migrating") - State20: - value: "/Transformation/Infrastructure/VM/${state_var#source_ems_type}/SetMigrated" + value: "/Transformation/Common/SetMigrated" on_entry: /Transformation/TransformationThrottler.Watch ; /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 5, description => "Mark source as migrated", task_message => "Migrating") on_exit: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 5, description diff --git a/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/pretransform.yaml b/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/pretransform.yaml index add631509..856178c4b 100644 --- a/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/pretransform.yaml +++ b/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/pretransform.yaml @@ -26,7 +26,7 @@ object: => "Power off", task_message => "Pre-migration") max_retries: '20' - State8: - value: "/Transformation/Infrastructure/VM/${state_var#source_ems_type}/CollapseSnapshots" + value: "/Transformation/Infrastructure/VM/Common/CollapseSnapshots" on_entry: /Transformation/TransformationThrottler.Watch ; /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 40, description => "Collapse Snapshots", task_message => "Pre-migration") on_exit: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 40, description diff --git a/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/transform.yaml b/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/transform.yaml index 9dd4580eb..37d167263 100644 --- a/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/transform.yaml +++ b/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/transform.yaml @@ -9,7 +9,7 @@ object: description: fields: - State2: - value: "/Transformation/TransformationHosts/Common/VMTransform" + value: "/Transformation/Common/VMTransform" on_entry: /Transformation/TransformationThrottler.Watch ; /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 5, description => "Convert disks", task_message => "Migrating") on_exit: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 5, description @@ -17,7 +17,7 @@ object: on_error: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 5, description => "Convert disks", task_message => "Migrating") - State5: - value: "/Transformation/TransformationHosts/Common/VMCheckTransformed" + value: "/Transformation/Common/VMCheckTransformed" on_entry: /Transformation/TransformationThrottler.Watch ; /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 80, description => "Convert disks", task_message => "Migrating") on_exit: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 80, description diff --git a/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/transformationcleanup.yaml b/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/transformationcleanup.yaml index 2cb917fc2..6d188ef3a 100644 --- a/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/transformationcleanup.yaml +++ b/content/automate/ManageIQ/Transformation/StateMachines/VMTransformation.class/transformationcleanup.yaml @@ -11,7 +11,7 @@ object: - state_machine_phase: value: cleanup - State2: - value: "/Transformation/TransformationHosts/Common/KillVirtV2V" + value: "/Transformation/Common/KillVirtV2V" on_entry: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 40, description => "Interrupt virt-v2v", task_message => "Cleanup") on_exit: /System/CommonMethods/MiqAe.WeightedUpdateStatus(weight => 40, description diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__class__.yaml b/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__class__.yaml deleted file mode 100644 index b7fe6fdbf..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__class__.yaml +++ /dev/null @@ -1,33 +0,0 @@ ---- -object_type: class -version: 1.0 -object: - attributes: - description: - display_name: - name: Common - type: - inherits: - visibility: - owner: - schema: - - field: - aetype: method - name: execute - display_name: - datatype: - priority: 1 - owner: - default_value: - substitute: true - message: create - visibility: - collect: - scope: - description: - condition: - on_entry: - on_exit: - on_error: - max_retries: - max_time: diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/killvirtv2v.rb b/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/killvirtv2v.rb deleted file mode 100644 index aea1b87a8..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/killvirtv2v.rb +++ /dev/null @@ -1,37 +0,0 @@ -module ManageIQ - module Automate - module Transformation - module TransformationHost - module Common - class KillVirtV2V - def initialize(handle = $evm) - @handle = handle - end - - def task_virtv2v_state(task, transformation_host) - require 'json' - return if task.get_option(:virtv2v_started_on).blank? || task.get_option(:virtv2v_finished_on).present? - return if task.get_option(:virtv2v_wrapper).blank? - result = Transformation::TransformationHosts::Common::Utils.remote_command(task, transformation_host, "cat '#{task.get_option(:virtv2v_wrapper)['state_file']}'") - return if !result[:success] || result[:stdout].empty? - JSON.parse(result[:stdout]) - end - - def main - task = @handle.vmdb(:service_template_transformation_plan_task).find_by(:id => @handle.root['service_template_transformation_plan_task_id']) - transformation_host = @handle.vmdb(:host).find_by(:id => task.get_option(:transformation_host_id)) - virtv2v_state = task_virtv2v_state(task, transformation_host) - @handle.log(:info, "VirtV2V State: #{virtv2v_state.inspect}") - Transformation::TransformationHosts::Common::Utils.remote_command(task, transformation_host, "kill -9 #{virtv2v_state['pid']}") if virtv2v_state.present? - rescue => e - @handle.set_state_var(:ae_state_progress, 'message' => e.message) - raise - end - end - end - end - end - end -end - -ManageIQ::Automate::Transformation::TransformationHost::Common::KillVirtV2V.new.main diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/killvirtv2v.yaml b/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/killvirtv2v.yaml deleted file mode 100644 index 205cb2af0..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/killvirtv2v.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -object_type: method -version: 1.0 -object: - attributes: - name: KillVirtV2V - display_name: - description: - scope: instance - language: ruby - location: inline - embedded_methods: - - "/Transformation/TransformationHosts/Common/Utils" - - "/Transformation/TransformationHosts/ovirt_host/Utils" - options: {} - inputs: [] diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils.rb b/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils.rb deleted file mode 100644 index 70a5bd1a0..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils.rb +++ /dev/null @@ -1,163 +0,0 @@ -module ManageIQ - module Automate - module Transformation - module TransformationHosts - module Common - class Utils - DEFAULT_EMS_MAX_RUNNERS = 10 - DEFAULT_HOST_MAX_RUNNERS = 10 - - def self.get_runners_count_by_host(host, handle = $evm) - handle.vmdb(:service_template_transformation_plan_task).where(:state => 'active').select { |task| task.get_option(:transformation_host_id) == host.id }.size - end - - def self.host_max_runners(host, factory_config, max_runners = DEFAULT_HOST_MAX_RUNNERS) - if host.custom_get('Max Transformation Runners') - host.custom_get('Max Transformation Runners').to_i - elsif factory_config['transformation_host_max_runners'] - factory_config['transformation_host_max_runners'].to_i - else - max_runners - end - end - - def self.transformation_hosts(ems, factory_config, handle = $evm) - thosts = [] - ems.hosts.each do |host| - next unless host.tagged_with?('v2v_transformation_host', 'true') - thosts << { - :type => 'OVirtHost', - :transformation_method => host.tags('v2v_transformation_method'), - :host => host, - :runners => { - :current => get_runners_count_by_host(host, handle), - :maximum => host_max_runners(host, factory_config) - } - } - end - thosts.sort_by! { |th| th[:runners][:current] } - end - - def self.eligible_transformation_hosts(ems, factory_config, handle = $evm) - transformation_hosts(ems, factory_config, handle).select { |thost| thost[:runners][:current] < thost[:runners][:maximum] } - end - - def self.get_runners_count_by_ems(ems, factory_config, handle = $evm) - transformation_hosts(ems, factory_config, handle).inject(0) { |sum, thost| sum + thost[:runners][:current] } - end - - def self.ems_max_runners(ems, factory_config, max_runners = DEFAULT_EMS_MAX_RUNNERS) - if ems.custom_get('Max Transformation Runners') - ems.custom_get('Max Transformation Runners').to_i - elsif factory_config['ems_max_runners'] - factory_config['ems_max_runners'].to_i - else - max_runners - end - end - - def self.get_transformation_host(task, factory_config, handle = $evm) - ems = handle.vmdb(:ext_management_system).find_by(:id => task.get_option(:destination_ems_id)) - ems_cur_runners = get_runners_count_by_ems(ems, factory_config, handle) - return unless ems_cur_runners < ems_max_runners(ems, factory_config) - thosts = eligible_transformation_hosts(ems, factory_config, handle) - return if thosts.size.zero? - [thosts.first[:type], thosts.first[:host], thosts.first[:transformation_method]] - end - - def self.virtv2vwrapper_options(task) - send("virtv2vwrapper_options_#{task.get_option(:transformation_type)}_#{task.get_option(:transformation_method)}", task) - end - - def self.vmware_uri_vddk(vm) - URI::Generic.build( - :scheme => 'esx', - :userinfo => CGI.escape(vm.host.authentication_userid), - :host => vm.host.ipaddress, - :path => '/', - :query => { :no_verify => 1 }.to_query - ).to_s - end - private_class_method :vmware_uri_vddk - - # We can't put the whole storage and VM location bits in the URI - # build, as is contains _invalid_ characters, such as space and [. - def self.vmware_uri_ssh(vm, storage) - url = URI::Generic.build( - :scheme => 'ssh', - :userinfo => 'root', - :host => vm.host.ipaddress, - :path => "/vmfs/volumes" - ).to_s - url + "/#{storage.name}/#{vm.location}" - end - private_class_method :vmware_uri_ssh - - def self.rhv_url(ems) - URI::Generic.build( - :scheme => 'https', - :host => ems.hostname, - :path => '/ovirt-engine/api' - ).to_s - end - private_class_method :rhv_url - - def self.virtv2vwrapper_options_vmwarews2rhevm_vddk(task) - source_vm = task.source - source_cluster = source_vm.ems_cluster - - destination_cluster = task.transformation_destination(source_cluster) - destination_ems = destination_cluster.ext_management_system - destination_storage = task.transformation_destination(source_vm.hardware.disks.select { |d| d.device_type == 'disk' }.first.storage) - - { - :vm_name => source_vm.name, - :transport_method => 'vddk', - :vmware_fingerprint => ManageIQ::Automate::Transformation::Infrastructure::VM::VMware::Utils.host_fingerprint(source_vm.host), - :vmware_uri => vmware_uri_vddk(source_vm), - :vmware_password => source_vm.host.authentication_password, - :rhv_url => rhv_url(destination_ems), - :rhv_cluster => destination_cluster.name, - :rhv_storage => destination_storage.name, - :rhv_password => destination_ems.authentication_password, - :source_disks => task[:options][:virtv2v_disks].map { |disk| disk[:path] }, - :network_mappings => task[:options][:virtv2v_networks], - :install_drivers => true, - :insecure_connection => true - } - end - private_class_method :virtv2vwrapper_options_vmwarews2rhevm_vddk - - def self.virtv2vwrapper_options_vmwarews2rhevm_ssh(task) - source_vm = task.source - source_cluster = source_vm.ems_cluster - source_storage = source_vm.hardware.disks.select { |d| d.device_type == 'disk' }.first.storage - - destination_cluster = task.transformation_destination(source_cluster) - destination_ems = destination_cluster.ext_management_system - destination_storage = task.transformation_destination(source_vm.hardware.disks.select { |d| d.device_type == 'disk' }.first.storage) - - { - :vm_name => vmware_uri_ssh(source_vm, source_storage), - :transport_method => 'ssh', - :rhv_url => rhv_url(destination_ems), - :rhv_cluster => destination_cluster.name, - :rhv_storage => destination_storage.name, - :rhv_password => destination_ems.authentication_password, - :source_disks => task[:options][:virtv2v_disks].map { |disk| disk[:path] }, - :network_mappings => task[:options][:virtv2v_networks], - :install_drivers => true, - :insecure_connection => true - } - end - private_class_method :virtv2vwrapper_options_vmwarews2rhevm_ssh - - def self.remote_command(task, transformation_host, command, stdin = nil, run_as = nil) - "ManageIQ::Automate::Transformation::TransformationHosts::#{task.get_option(:transformation_host_type)}::Utils".constantize.remote_command(transformation_host, command, stdin, run_as) - end - end - end - end - end - end -end diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils.yaml b/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils.yaml deleted file mode 100644 index 5b5c40d1c..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -object_type: method -version: 1.0 -object: - attributes: - name: Utils - display_name: - description: - scope: instance - language: ruby - location: inline - embedded_methods: - - "/Transformation/Infrastructure/VM/vmwarews/Utils" - - "/Transformation/TransformationHosts/ovirt_host/Utils" - options: {} - inputs: [] diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmchecktransformed.rb b/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmchecktransformed.rb deleted file mode 100644 index 6479f3172..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmchecktransformed.rb +++ /dev/null @@ -1,81 +0,0 @@ -module ManageIQ - module Automate - module Transformation - module TransformationHost - module Common - class VMCheckTransformed - def initialize(handle = $evm) - @debug = true - @handle = handle - end - - def main - require 'json' - - factory_config = @handle.get_state_var(:factory_config) - raise "No factory config found. Aborting." if factory_config.nil? - - task = @handle.root['service_template_transformation_plan_task'] - - # Retrieve transformation host - transformation_host = @handle.vmdb(:host).find_by(:id => task.get_option(:transformation_host_id)) - - # Retrieve state of virt-v2v - result = Transformation::TransformationHosts::Common::Utils.remote_command(task, transformation_host, "cat '#{task.get_option(:virtv2v_wrapper)['state_file']}'") - raise result[:stderr] unless result[:success] && !result[:stdout].empty? - virtv2v_state = JSON.parse(result[:stdout]) - @handle.log(:info, "VirtV2V State: #{virtv2v_state.inspect}") - - # Retrieve disks array - virtv2v_disks = task[:options][:virtv2v_disks] - @handle.log(:info, "Disks: #{virtv2v_disks.inspect}") - - if virtv2v_state['finished'].nil? - # Update the progress of each disk - virtv2v_disks.each do |disk| - matching_disks = virtv2v_state['disks'].select { |d| d['path'] == disk[:path] } - raise "No disk matches '#{disk[:path]}'. Aborting." if matching_disks.length.zero? - raise "More than one disk matches '#{disk[:path]}'. Aborting." if matching_disks.length > 1 - disk[:percent] = matching_disks.first['progress'] - end - converted_disks = virtv2v_disks.reject { |d| d[:percent].zero? } - @handle.log(:info, "Converted disks: #{converted_disks.inspect}") - if converted_disks.empty? - @handle.set_state_var(:ae_state_progress, 'message' => "Disks transformation is initializing.", 'percent' => 1) - else - percent = 0 - converted_disks.each { |disk| percent += (disk[:percent].to_f * disk[:weight].to_f / 100.0) } - message = "Converting disk #{converted_disks.length} / #{virtv2v_disks.length} [#{percent.round(2)}%]." - @handle.set_state_var(:ae_state_progress, 'message' => message, 'percent' => percent.round(2)) - end - else - task.set_option(:virtv2v_finished_on, Time.now.utc.strftime('%Y%m%d_%H%M')) - if virtv2v_state['failed'] - @handle.set_state_var(:ae_state_progress, 'message' => 'Disks transformation failed.') - raise "Disks transformation failed." - else - virtv2v_disks.each { |d| d[:percent] = 100 } - @handle.set_state_var(:ae_state_progress, 'message' => 'Disks transformation succeeded.', 'percent' => 100) - end - end - - task.set_option(:virtv2v_disks, virtv2v_disks) - - if task.get_option(:virtv2v_finished_on).nil? - @handle.root['ae_result'] = 'retry' - @handle.root['ae_retry_server_affinity'] = true - @handle.root['ae_retry_interval'] = factory_config['vmtransformation_check_interval'] || '15.seconds' - @handle.log(:info, "Disk transformation is not finished. Checking in #{@handle.root['ae_retry_interval']}") - end - rescue => e - @handle.set_state_var(:ae_state_progress, 'message' => e.message) - raise - end - end - end - end - end - end -end - -ManageIQ::Automate::Transformation::TransformationHost::Common::VMCheckTransformed.new.main diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmtransform.rb b/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmtransform.rb deleted file mode 100644 index c2ff7a91d..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmtransform.rb +++ /dev/null @@ -1,56 +0,0 @@ -module ManageIQ - module Automate - module Transformation - module TransformationHost - module Common - class VMTransform - def initialize(handle = $evm) - @debug = false - @handle = handle - end - - def main - require 'json' - - factory_config = @handle.get_state_var(:factory_config) - raise "No factory config found. Aborting." if factory_config.nil? - - task = @handle.root['service_template_transformation_plan_task'] - - # Get or create the virt-v2v start timestamp - start_timestamp = task.get_option(:virtv2v_started_on) || Time.now.utc.strftime('%Y-%m-%d %H:%M:%S') - - # Retrieve transformation host - transformation_host = @handle.vmdb(:host).find_by(:id => task.get_option(:transformation_host_id)) - - @handle.log(:info, "Transformation - Started On: #{start_timestamp}") - - wrapper_options = ManageIQ::Automate::Transformation::TransformationHosts::Common::Utils.virtv2vwrapper_options(task) - - # WARNING: Enable at your own risk, as it may lead to sensitive data leak - # @handle.log(:info, "JSON Input:\n#{JSON.pretty_generate(wrapper_options)}") if @debug - - @handle.log(:info, "Connecting to #{transformation_host.name} as #{transformation_host.authentication_userid}") if @debug - @handle.log(:info, "Executing '/usr/bin/virt-v2v-wrapper.py'") - result = Transformation::TransformationHosts::Common::Utils.remote_command(task, transformation_host, "/usr/bin/virt-v2v-wrapper.py", wrapper_options.to_json) - raise result[:stderr] unless result[:rc].zero? - - # Record the wrapper files path - @handle.log(:info, "Command stdout: #{result[:stdout]}") if @debug - task.set_option(:virtv2v_wrapper, JSON.parse(result[:stdout])) - - # Record the status in the task object - task.set_option(:virtv2v_started_on, start_timestamp) - task.set_option(:virtv2v_status, 'active') - rescue => e - @handle.set_state_var(:ae_state_progress, 'message' => e.message) - raise - end - end - end - end - end - end -end - -ManageIQ::Automate::Transformation::TransformationHost::Common::VMTransform.new.main diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmtransform.yaml b/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmtransform.yaml deleted file mode 100644 index b5a7e7fe8..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/vmtransform.yaml +++ /dev/null @@ -1,17 +0,0 @@ ---- -object_type: method -version: 1.0 -object: - attributes: - name: VMTransform - display_name: - description: - scope: instance - language: ruby - location: inline - embedded_methods: - - "/Transformation/TransformationHosts/Common/Utils" - - "/Transformation/Infrastructure/VM/vmwarews/Utils" - - "/Transformation/TransformationHosts/ovirt_host/Utils" - options: {} - inputs: [] diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/_missing.yaml b/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/_missing.yaml deleted file mode 100644 index 31e5fff8b..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/_missing.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -object_type: instance -version: 1.0 -object: - attributes: - display_name: - name: ".missing" - inherits: - description: - fields: - - execute: - value: "${#_missing_instance}" diff --git a/content/automate/ManageIQ/Transformation/TransformationHosts/ovirt_host.class/__methods__/utils.rb b/content/automate/ManageIQ/Transformation/TransformationHosts/ovirt_host.class/__methods__/utils.rb deleted file mode 100644 index b7fad90ca..000000000 --- a/content/automate/ManageIQ/Transformation/TransformationHosts/ovirt_host.class/__methods__/utils.rb +++ /dev/null @@ -1,77 +0,0 @@ -module ManageIQ - module Automate - module Transformation - module TransformationHosts - module OVirtHost - class Utils - def initialize(handle = $evm) - @handle = handle - end - - def self.remote_command(host, command, stdin = nil, run_as = nil) - require "net/ssh" - command = "sudo -u #{run_as} #{command}" unless run_as.nil? - success, stdout, stderr, exit_code = true, '', '', nil - Net::SSH.start(host.name, host.authentication_userid, :password => host.authentication_password) do |ssh| - channel = ssh.open_channel do |chan| - chan.request_pty unless run_as.nil? - chan.exec(command) do |ch, exec_success| - if exec_success - ch.on_data do |_, data| - stdout += data.to_s - end - ch.on_extended_data do |_, data| - stderr += data.to_s - end - ch.on_request("exit-status") do |_, data| - exit_code = data.read_long - end - unless stdin.nil? - ch.send_data(stdin) - ch.eof! - end - else - success = false - stderr = "Could not execute command." - end - end - end - channel.wait - end - { :success => success, :stdout => stdout, :stderr => stderr, :rc => exit_code } - end - - def self.ansible_playbook(host, playbook, extra_vars) - require "net/ssh" - command = "ansible-playbook -i #{host.name}, #{playbook}" - extra_vars.each { |k, v| command += " -e '#{k}=#{v}'" } - success, stdout, stderr, exit_code = true, '', '', nil - Net::SSH.start(host.ext_management_system.hostname, 'root') do |ssh| - channel = ssh.open_channel do |chan| - chan.exec(command) do |ch, exec_success| - if exec_success - ch.on_data do |_, data| - stdout += data.to_s - end - ch.on_extended_data do |_, data| - stderr += data.to_s - end - ch.on_request("exit-status") do |_, data| - exit_code = data.read_long - end - else - success = false - stderr = "Could not execute command." - end - end - end - channel.wait - end - { :success => success, :stdout => stdout, :stderr => stderr, :rc => exit_code } - end - end - end - end - end - end -end diff --git a/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/throttle.yaml b/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/throttle.yaml index 30b29cf3b..074bbe022 100644 --- a/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/throttle.yaml +++ b/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/throttle.yaml @@ -11,6 +11,5 @@ object: location: inline embedded_methods: - "/Transformation/TransformationThrottler/Utils" - - "/Transformation/TransformationHosts/Common/Utils" options: {} inputs: [] diff --git a/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils.rb b/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils.rb index bd2dcb889..357f54b1c 100644 --- a/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils.rb +++ b/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils.rb @@ -10,6 +10,7 @@ class Utils DEFAULT_THROTTLER_TTL = 3600 DEFAULT_TASKS_SCHEDULING_POLICY = 'fifo'.freeze DEFAULT_LIMITS_ADJUSTMENT_POLICY = 'skip'.freeze + DEFAULT_EMS_MAX_RUNNERS = 10 def self.log_and_raise(message, handle = $evm) handle.log(:error, message) @@ -82,7 +83,7 @@ def self.retry_or_die(handle = $evm) end def self.tasks_scheduling_policy(handle = $evm) - @tasks_scheduling_policy ||= handle.root['tasks_scheduling_policy'] || DEFAULT_TASKS_SCHEDULING_POLICY + handle.root['tasks_scheduling_policy'] || DEFAULT_TASKS_SCHEDULING_POLICY end def self.schedule_tasks(handle = $evm) @@ -91,17 +92,14 @@ def self.schedule_tasks(handle = $evm) def self.schedule_tasks_fifo(handle = $evm) unassigned_transformation_tasks(handle).sort_by(&:created_on).each do |transformation_task| - transformation_host_type, transformation_host, transformation_method = ManageIQ::Automate::Transformation::TransformationHosts::Common::Utils.get_transformation_host(transformation_task, {}) + transformation_host = get_transformation_host(transformation_task, {}, handle) break if transformation_host.nil? - transformation_task.set_option(:transformation_host_id, transformation_host.id) - transformation_task.set_option(:transformation_host_name, transformation_host.name) - transformation_task.set_option(:transformation_host_type, transformation_host_type) - transformation_task.set_option(:transformation_method, transformation_method) + transformation_task.conversion_host = transformation_host end end def self.limits_adjustment_policy(handle = $evm) - @limits_adjustment_policy ||= handle.root['limits_adjustment_policy'] || DEFAULT_LIMITS_ADJUSTMENT_POLICY + handle.root['limits_adjustment_policy'] || DEFAULT_LIMITS_ADJUSTMENT_POLICY end def self.adjust_limits(handle = $evm) @@ -111,12 +109,43 @@ def self.adjust_limits(handle = $evm) def self.adjust_limits_skip(handle = $evm) end - def self.active_transformation_tasks(handle) - @active_transformation_tasks ||= handle.vmdb(:service_template_transformation_plan_task).where(:state => 'active') + def self.active_transformation_tasks(handle = $evm) + handle.vmdb(:service_template_transformation_plan_task).where(:state => 'active') end - def self.unassigned_transformation_tasks(handle) - active_transformation_tasks(handle).select { |transformation_task| transformation_task.get_option(:transformation_host_id).nil? } + def self.unassigned_transformation_tasks(handle = $evm) + active_transformation_tasks(handle).select { |transformation_task| transformation_task.conversion_host.nil? } + end + + def self.transformation_hosts(ems, handle = $evm) + handle.vmdb(:conversion_host).all.select { |ch| ch.ext_management_system.id == ems.id } + end + + def self.eligible_transformation_hosts(ems, handle = $evm) + transformation_hosts(ems, handle).select(&:eligible?).sort_by { |ch| ch.active_tasks.size } + end + + def self.get_runners_count_by_ems(ems, handle = $evm) + transformation_hosts(ems, handle).inject(0) { |sum, ch| sum + ch.active_tasks.size } + end + + def self.ems_max_runners(ems, factory_config, max_runners = DEFAULT_EMS_MAX_RUNNERS) + if ems.custom_get('Max Transformation Runners') + ems.custom_get('Max Transformation Runners').to_i + elsif factory_config['ems_max_runners'] + factory_config['ems_max_runners'].to_i + else + max_runners + end + end + + def self.get_transformation_host(task, factory_config, handle = $evm) + ems = task.destination_ems + ems_cur_runners = get_runners_count_by_ems(ems, handle) + return unless ems_cur_runners < ems_max_runners(ems, factory_config) + thosts = eligible_transformation_hosts(ems, handle) + return if thosts.size.zero? + thosts.first end end end diff --git a/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils.yaml b/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils.yaml index e4bddee09..94612ce92 100644 --- a/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils.yaml +++ b/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils.yaml @@ -9,7 +9,5 @@ object: scope: instance language: ruby location: inline - embedded_methods: - - "/Transformation/TransformationHosts/Common/Utils" options: {} inputs: [] diff --git a/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/acquiretransformationhost_spec.rb b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/acquiretransformationhost_spec.rb index 4c9ee0567..ba2c3c44d 100644 --- a/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/acquiretransformationhost_spec.rb +++ b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/acquiretransformationhost_spec.rb @@ -4,11 +4,11 @@ describe ManageIQ::Automate::Transformation::Common::AcquireTransformationHost do let(:user) { FactoryGirl.create(:user_with_email_and_group) } let(:task) { FactoryGirl.create(:service_template_transformation_plan_task) } - let(:host) { FactoryGirl.create(:host) } + let(:conversion_host) { FactoryGirl.create(:conversion_host) } let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } let(:svc_model_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task.id) } - let(:svc_model_host) { MiqAeMethodService::MiqAeServiceHost.find(host.id) } + let(:svc_model_conversion_host) { MiqAeMethodService::MiqAeServiceConversionHost.find(conversion_host.id) } let(:root) do Spec::Support::MiqAeMockObject.new( @@ -33,7 +33,7 @@ context "#main" do it "without transformation host" do - allow(svc_model_task).to receive(:get_option).with(:transformation_host_id).and_return(nil) + allow(svc_model_task).to receive(:conversion_host).and_return(nil) described_class.new(ae_service).main expect(ae_service.root['ae_result']).to eq('retry') expect(ae_service.root['ae_retry_server_affinity']).to eq(true) @@ -41,7 +41,7 @@ end it "with transformation host" do - allow(svc_model_task).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_host.id) + allow(svc_model_task).to receive(:conversion_host).and_return(svc_model_conversion_host) described_class.new(ae_service).main expect(ae_service.root['ae_result']).to be_nil expect(ae_service.root['ae_retry_server_affinity']).to be_nil @@ -53,7 +53,7 @@ let(:svc_model_src_vm) { svc_model_src_vm_vmware } before do - allow(svc_model_task).to receive(:get_option).with(:transformation_host_id).and_raise(StandardError, 'kaboom') + allow(svc_model_task).to receive(:conversion_host).and_raise(StandardError, 'kaboom') end it "forcefully raise" do diff --git a/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/assesstransformation_spec.rb b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/assesstransformation_spec.rb index 7b1544676..10b2b2737 100644 --- a/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/assesstransformation_spec.rb +++ b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/assesstransformation_spec.rb @@ -5,19 +5,13 @@ let(:user) { FactoryGirl.create(:user_with_email_and_group) } let(:group) { FactoryGirl.create(:miq_group) } let(:task) { FactoryGirl.create(:service_template_transformation_plan_task) } - let(:src_vm_vmware) { FactoryGirl.create(:vm_vmware) } - let(:src_cluster) { FactoryGirl.create(:ems_cluster) } let(:src_ems_vmware) { FactoryGirl.create(:ems_vmware) } - let(:dst_cluster) { FactoryGirl.create(:ems_cluster) } - let(:dst_ems_redhat) { FactoryGirl.create(:ems_redhat) } - let(:dst_ems_openstack) { FactoryGirl.create(:ems_openstack_infra) } + let(:src_cluster_vmware) { FactoryGirl.create(:ems_cluster, :ext_management_system => src_ems_vmware) } + let(:src_vm_vmware) { FactoryGirl.create(:vm_vmware, :ext_management_system => src_ems_vmware, :ems_cluster => src_cluster_vmware) } let(:src_storage_1) { FactoryGirl.create(:storage) } let(:src_storage_2) { FactoryGirl.create(:storage) } - let(:dst_storage) { FactoryGirl.create(:storage) } let(:src_lan_1) { FactoryGirl.create(:lan) } let(:src_lan_2) { FactoryGirl.create(:lan) } - let(:dst_lan_1) { FactoryGirl.create(:lan) } - let(:dst_lan_2) { FactoryGirl.create(:lan) } let(:hardware) { FactoryGirl.create(:hardware) } let(:nic_1) { FactoryGirl.create(:guest_device_nic) } let(:nic_2) { FactoryGirl.create(:guest_device_nic) } @@ -25,19 +19,13 @@ let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } let(:svc_model_group) { MiqAeMethodService::MiqAeServiceMiqGroup.find(group.id) } let(:svc_model_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task.id) } - let(:svc_model_src_vm_vmware) { MiqAeMethodService::MiqAeServiceManageIQ_Providers_Vmware_InfraManager_Vm.find(src_vm_vmware.id) } - let(:svc_model_src_cluster) { MiqAeMethodService::MiqAeServiceEmsCluster.find(src_cluster) } let(:svc_model_src_ems_vmware) { MiqAeMethodService::MiqAeServiceExtManagementSystem.find(src_ems_vmware) } - let(:svc_model_dst_cluster) { MiqAeMethodService::MiqAeServiceEmsCluster.find(dst_cluster) } - let(:svc_model_dst_ems_redhat) { MiqAeMethodService::MiqAeServiceExtManagementSystem.find(dst_ems_redhat) } - let(:svc_model_dst_ems_openstack) { MiqAeMethodService::MiqAeServiceExtManagementSystem.find(dst_ems_openstack) } + let(:svc_model_src_cluster_vmware) { MiqAeMethodService::MiqAeServiceEmsCluster.find(src_cluster_vmware) } + let(:svc_model_src_vm_vmware) { MiqAeMethodService::MiqAeServiceManageIQ_Providers_Vmware_InfraManager_Vm.find(src_vm_vmware.id) } let(:svc_model_src_storage_1) { MiqAeMethodService::MiqAeServiceStorage.find(src_storage_1) } let(:svc_model_src_storage_2) { MiqAeMethodService::MiqAeServiceStorage.find(src_storage_2) } - let(:svc_model_dst_storage) { MiqAeMethodService::MiqAeServiceStorage.find(dst_storage) } let(:svc_model_src_lan_1) { MiqAeMethodService::MiqAeServiceLan.find(src_lan_1) } let(:svc_model_src_lan_2) { MiqAeMethodService::MiqAeServiceLan.find(src_lan_2) } - let(:svc_model_dst_lan_1) { MiqAeMethodService::MiqAeServiceLan.find(dst_lan_1) } - let(:svc_model_dst_lan_2) { MiqAeMethodService::MiqAeServiceLan.find(dst_lan_2) } let(:svc_model_hardware) { MiqAeMethodService::MiqAeServiceHardware.find(hardware) } let(:svc_model_guest_device_1) { MiqAeMethodService::MiqAeServiceGuestDevice.find(guest_device_1) } let(:svc_model_guest_device_2) { MiqAeMethodService::MiqAeServiceGuestDevice.find(guest_device_2) } @@ -96,183 +84,6 @@ ManageIQ::Automate::Transformation::Common::AssessTransformation.instance_variable_set(:@destination_ems, nil) end - shared_examples_for "source and destination items" do - it "source_cluster without cluster" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(nil) - errormsg = "No source cluster" - expect { described_class.new(ae_service).source_cluster }.to raise_error(errormsg) - end - - it "source_cluster with cluster" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - expect(described_class.new(ae_service).source_cluster.id).to eq(svc_model_src_cluster.id) - end - - it "source_ems without ems" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_src_cluster).to receive(:ext_management_system).and_return(nil) - errormsg = "No source EMS" - expect { described_class.new(ae_service).source_ems }.to raise_error(errormsg) - end - - it "source_ems with ems" do - allow(svc_model_src_vm).to receive(:ext_management_system).and_return(svc_model_src_ems) - expect(described_class.new(ae_service).source_ems.id).to eq(svc_model_src_ems.id) - end - - it "destination_cluster without cluster" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(nil) - errormsg = "No destination cluster" - expect { described_class.new(ae_service).destination_cluster }.to raise_error(errormsg) - end - - it "destination_cluster with cluster" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(svc_model_dst_cluster) - expect(described_class.new(ae_service).destination_cluster.id).to eq(svc_model_dst_cluster.id) - end - - it "destination_ems without ems" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(svc_model_dst_cluster) - allow(svc_model_dst_cluster).to receive(:ext_management_system).and_return(nil) - errormsg = "No destination EMS" - expect { described_class.new(ae_service).destination_ems }.to raise_error(errormsg) - end - - it "destination_ems with ems" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(svc_model_dst_cluster) - allow(svc_model_dst_cluster).to receive(:ext_management_system).and_return(svc_model_dst_ems) - expect(described_class.new(ae_service).destination_ems.id).to eq(svc_model_dst_ems.id) - end - end - - context "source and destination items source vmware and destination redhat" do - let(:svc_model_src_vm) { svc_model_src_vm_vmware } - let(:svc_model_src_ems) { svc_model_src_ems_vmware } - let(:svc_model_dst_ems) { svc_model_dst_ems_redhat } - - it_behaves_like "source and destination items" - end - - context "source and destination items source vmware and destination openstack" do - let(:svc_model_src_vm) { svc_model_src_vm_vmware } - let(:svc_model_src_ems) { svc_model_src_ems_vmware } - let(:svc_model_dst_ems) { svc_model_dst_ems_openstack } - - it_behaves_like "source and destination items" - end - - context "transformation_type" do - let(:svc_model_src_vm) { svc_model_src_vm_vmware } - - it "transformation_type with invalid source ems" do - allow(svc_model_src_vm).to receive(:ext_management_system).and_return(svc_model_dst_ems_redhat) - errormsg = "Unsupported source EMS type: #{svc_model_dst_ems_redhat.emstype}." - expect { described_class.new(ae_service).transformation_type }.to raise_error(errormsg) - end - - it "transformation_type with invalid destination ems" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_src_vm).to receive(:ext_management_system).and_return(svc_model_src_ems_vmware) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(svc_model_dst_cluster) - allow(svc_model_dst_cluster).to receive(:ext_management_system).and_return(svc_model_src_ems_vmware) - errormsg = "Unsupported destination EMS type: #{svc_model_src_ems_vmware.emstype}." - expect { described_class.new(ae_service).transformation_type }.to raise_error(errormsg) - end - - it "transformation_type with valid source and destination ems" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_src_vm).to receive(:ext_management_system).and_return(svc_model_src_ems_vmware) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(svc_model_dst_cluster) - allow(svc_model_dst_cluster).to receive(:ext_management_system).and_return(svc_model_dst_ems_redhat) - expect(described_class.new(ae_service).transformation_type).to eq("#{svc_model_src_ems_vmware.emstype}2#{svc_model_dst_ems_redhat.emstype}") - end - end - - shared_examples_for "virtv2v hardware" do - it "source_vm has no disk" do - allow(svc_model_src_vm.hardware).to receive(:disks).and_return([]) - expect(described_class.new(ae_service).virtv2v_disks).to eq([]) - end - - it "source_vm has disks, but src_storage_1 has no mapping" do - allow(svc_model_hardware).to receive(:disks).and_return([disk_1, disk_2]) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_storage_1).and_return(nil) - errormsg = "[#{svc_model_src_vm.name}] Disk #{disk_1.device_name} [#{svc_model_src_storage_1.name}] has no mapping. Aborting." - expect { described_class.new(ae_service).virtv2v_disks }.to raise_error(errormsg) - end - - it "source_vm has disks and storages have mapping" do - allow(svc_model_hardware).to receive(:disks).and_return([disk_1, disk_2]) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_storage_1).and_return(svc_model_dst_storage) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_storage_2).and_return(svc_model_dst_storage) - allow(svc_model_src_vm).to receive(:allocated_disk_storage).and_return(disk_1.size + disk_2.size) - expect(described_class.new(ae_service).virtv2v_disks).to eq(virtv2v_disks) - end - - it "source_vm has no nic" do - allow(svc_model_src_vm.hardware).to receive(:nics).and_return([]) - expect(described_class.new(ae_service).virtv2v_networks).to eq([]) - end - - it "source_vm has nics, but src_lan_1 has no mapping" do - allow(svc_model_hardware).to receive(:nics).and_return([svc_model_nic_1, svc_model_nic_2]) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_lan_1).and_return(nil) - errormsg = "[#{svc_model_src_vm.name}] NIC #{svc_model_nic_1.device_name} [#{svc_model_src_lan_1.name}] has no mapping. Aborting." - expect { described_class.new(ae_service).virtv2v_networks }.to raise_error(errormsg) - end - - it "source_vm has nicss and lans have mapping" do - allow(svc_model_hardware).to receive(:nics).and_return([svc_model_nic_1, svc_model_nic_2]) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_lan_1).and_return(svc_model_dst_lan_1) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_lan_2).and_return(svc_model_dst_lan_2) - expect(described_class.new(ae_service).virtv2v_networks).to eq(virtv2v_networks) - end - end - - context "source vm is vmware" do - let(:svc_model_src_vm) { svc_model_src_vm_vmware } - - it_behaves_like "virtv2v hardware" - end - - shared_examples_for "populate task options" do - it "task options" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_src_vm).to receive(:ext_management_system).and_return(svc_model_src_ems) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(svc_model_dst_cluster) - allow(svc_model_dst_cluster).to receive(:ext_management_system).and_return(svc_model_dst_ems) - allow(svc_model_hardware).to receive(:disks).and_return([disk_1, disk_2]) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_storage_1).and_return(svc_model_dst_storage) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_storage_2).and_return(svc_model_dst_storage) - allow(svc_model_src_vm).to receive(:allocated_disk_storage).and_return(disk_1.size + disk_2.size) - allow(svc_model_hardware).to receive(:nics).and_return([svc_model_nic_1, svc_model_nic_2]) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_lan_1).and_return(svc_model_dst_lan_1) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_lan_2).and_return(svc_model_dst_lan_2) - allow(svc_model_src_vm).to receive(:power_state).and_return("on") - described_class.new(ae_service).populate_task_options - expect(svc_model_task.get_option(:source_ems_id)).to eq(svc_model_src_ems.id) - expect(svc_model_task.get_option(:destination_ems_id)).to eq(svc_model_dst_ems.id) - expect(svc_model_task[:options][:virtv2v_networks]).to eq(virtv2v_networks) - expect(svc_model_task[:options][:virtv2v_disks]).to eq(virtv2v_disks) - expect(svc_model_task.get_option(:transformation_type)).to eq("#{svc_model_src_ems.emstype}2#{svc_model_dst_ems.emstype}") - expect(svc_model_task.get_option(:source_vm_power_state)).to eq("on") - expect(svc_model_task.get_option(:collapse_snapshots)).to be true - expect(svc_model_task.get_option(:power_off)).to be true - end - end - - context "source is vmware and destination is redhat" do - let(:svc_model_src_vm) { svc_model_src_vm_vmware } - let(:svc_model_src_ems) { svc_model_src_ems_vmware } - let(:svc_model_dst_ems) { svc_model_dst_ems_redhat } - - it_behaves_like "populate task options" - end - context "populate factory config" do let(:svc_model_src_vm) { svc_model_src_vm_vmware } @@ -299,26 +110,20 @@ end end + shared_examples_for "#populate_task_options" do + it "task options" do + allow(svc_model_src_vm).to receive(:power_state).and_return("on") + described_class.new(ae_service).populate_task_options + expect(svc_model_task.get_option(:source_vm_power_state)).to eq("on") + expect(svc_model_task.get_option(:collapse_snapshots)).to be true + expect(svc_model_task.get_option(:power_off)).to be true + end + end + shared_examples_for "main" do it "global summary test" do - allow(svc_model_src_vm).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_src_vm).to receive(:ext_management_system).and_return(svc_model_src_ems) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(svc_model_dst_cluster) - allow(svc_model_dst_cluster).to receive(:ext_management_system).and_return(svc_model_dst_ems) - allow(svc_model_hardware).to receive(:disks).and_return([disk_1, disk_2]) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_storage_1).and_return(svc_model_dst_storage) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_storage_2).and_return(svc_model_dst_storage) - allow(svc_model_src_vm).to receive(:allocated_disk_storage).and_return(disk_1.size + disk_2.size) - allow(svc_model_hardware).to receive(:nics).and_return([svc_model_nic_1, svc_model_nic_2]) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_lan_1).and_return(svc_model_dst_lan_1) - allow(svc_model_task).to receive(:transformation_destination).with(svc_model_src_lan_2).and_return(svc_model_dst_lan_2) allow(svc_model_src_vm).to receive(:power_state).and_return("on") described_class.new(ae_service).main - expect(svc_model_task.get_option(:source_ems_id)).to eq(svc_model_src_ems.id) - expect(svc_model_task.get_option(:destination_ems_id)).to eq(svc_model_dst_ems.id) - expect(svc_model_task[:options][:virtv2v_networks]).to eq(virtv2v_networks) - expect(svc_model_task[:options][:virtv2v_disks]).to eq(virtv2v_disks) - expect(svc_model_task.get_option(:transformation_type)).to eq("#{svc_model_src_ems.emstype}2#{svc_model_dst_ems.emstype}") expect(svc_model_task.get_option(:source_vm_power_state)).to eq("on") expect(svc_model_task.get_option(:collapse_snapshots)).to be true expect(svc_model_task.get_option(:power_off)).to be true @@ -328,18 +133,117 @@ end context "source is vmware and destination is redhat" do + let(:src_vm) { src_vm_vmware } let(:svc_model_src_vm) { svc_model_src_vm_vmware } let(:svc_model_src_ems) { svc_model_src_ems_vmware } - let(:svc_model_dst_ems) { svc_model_dst_ems_redhat } + let(:dst_ems) { FactoryGirl.create(:ems_redhat) } + let(:svc_model_dst_ems) { MiqAeMethodService::MiqAeServiceExtManagementSystem.find(dst_ems.id) } + let(:dst_cluster) { FactoryGirl.create(:ems_cluster, :ext_management_system => dst_ems) } + let(:svc_model_dst_cluster) { MiqAeMethodService::MiqAeServiceEmsCluster.find(dst_cluster.id) } + let(:dst_storage) { FactoryGirl.create(:storage) } + let(:svc_model_dst_storage) { MiqAeMethodService::MiqAeServiceStorage.find(dst_storage.id) } + let(:dst_lan_1) { FactoryGirl.create(:lan) } + let(:svc_model_dst_lan_1) { MiqAeMethodService::MiqAeServiceLan.find(dst_lan_1.id) } + let(:dst_lan_2) { FactoryGirl.create(:lan) } + let(:svc_model_dst_lan_2) { MiqAeMethodService::MiqAeServiceLan.find(dst_lan_2.id) } + + let(:mapping) do + FactoryGirl.create( + :transformation_mapping, + :transformation_mapping_items => [ + FactoryGirl.create(:transformation_mapping_item, :source => src_cluster_vmware, :destination => dst_cluster), + FactoryGirl.create(:transformation_mapping_item, :source => src_storage_1, :destination => dst_storage), + FactoryGirl.create(:transformation_mapping_item, :source => src_storage_2, :destination => dst_storage), + FactoryGirl.create(:transformation_mapping_item, :source => src_lan_1, :destination => dst_lan_1), + FactoryGirl.create(:transformation_mapping_item, :source => src_lan_2, :destination => dst_lan_2) + ] + ) + end + + let(:catalog_item_options) do + { + :name => 'Transformation Plan', + :description => 'a description', + :config_info => { + :transformation_mapping_id => mapping.id, + :actions => [ + {:vm_id => src_vm.id.to_s, :pre_service => false, :post_service => false} + ], + } + } + end + + let(:plan) { ServiceTemplateTransformationPlan.create_catalog_item(catalog_item_options) } + let(:request) { FactoryGirl.create(:service_template_transformation_plan_request, :source => plan) } + let(:task) { FactoryGirl.create(:service_template_transformation_plan_task, :miq_request => request, :request_type => 'transformation_plan', :source => src_vm_vmware) } + + it_behaves_like "#populate_task_options" it_behaves_like "main" end - context "catchall exception rescue" do + context "source is vmware and destination is openstack" do + let(:src_vm) { src_vm_vmware } let(:svc_model_src_vm) { svc_model_src_vm_vmware } + let(:svc_model_src_ems) { svc_model_src_ems_vmware } + + let(:dst_ems) { FactoryGirl.create(:ems_openstack_infra) } + let(:svc_model_dst_ems) { MiqAeMethodService::MiqAeServiceExtManagementSystem.find(dst_ems.id) } + let(:dst_cloud_tenant) { FactoryGirl.create(:cloud_tenant, :ext_management_system => dst_ems) } + let(:svc_model_dst_cloud_tenant) { MiqAeMethodService::MiqAeServiceCloudTenant.find(dst_cluster.id) } + let(:dst_cloud_volume_type) { FactoryGirl.create(:cloud_volume_type) } + let(:svc_model_dst_cloud_volume_type) { MiqAeMethodService::MiqAeServiceCloudVolumeType.find(dst_cloud_volume_type.id) } + let(:dst_cloud_network_1) { FactoryGirl.create(:cloud_network) } + let(:svc_model_cloud_network_1) { MiqAeMethodService::MiqAeServiceCloudNetwork.find(dst_cloud_network_1.id) } + let(:dst_cloud_network_2) { FactoryGirl.create(:cloud_network) } + let(:svc_model_cloud_network_1) { MiqAeMethodService::MiqAeServiceCloudNetwork.find(dst_cloud_network_2.id) } + + let(:mapping) do + FactoryGirl.create( + :transformation_mapping, + :transformation_mapping_items => [ + FactoryGirl.create(:transformation_mapping_item, :source => src_cluster_vmware, :destination => dst_cloud_tenant), + FactoryGirl.create(:transformation_mapping_item, :source => src_storage_1, :destination => dst_cloud_volume_type), + FactoryGirl.create(:transformation_mapping_item, :source => src_storage_2, :destination => dst_cloud_volume_type), + FactoryGirl.create(:transformation_mapping_item, :source => src_lan_1, :destination => dst_cloud_network_1), + FactoryGirl.create(:transformation_mapping_item, :source => src_lan_2, :destination => dst_cloud_network_2) + ] + ) + end + + let(:catalog_item_options) do + { + :name => 'Transformation Plan', + :description => 'a description', + :config_info => { + :transformation_mapping_id => mapping.id, + :actions => [ + {:vm_id => src_vm.id.to_s, :pre_service => false, :post_service => false} + ], + } + } + end + + let(:plan) { ServiceTemplateTransformationPlan.create_catalog_item(catalog_item_options) } + let(:request) { FactoryGirl.create(:service_template_transformation_plan_request, :source => plan) } + let(:task) { FactoryGirl.create(:service_template_transformation_plan_task, :miq_request => request, :request_type => 'transformation_plan', :source => src_vm_vmware) } + + it_behaves_like "#populate_task_options" + it_behaves_like "main" + end + + context "handle errors" do + let(:svc_model_src_vm) { svc_model_src_vm_vmware } + + it "sets cancel_requested option if preflight check returns false" do + allow(svc_model_task).to receive(:preflight_check).and_return(false) + described_class.new(ae_service).main + expect(svc_model_task.get_option('cancel_requested')).to eq(true) + end - it "forcefully raise" do - errormsg = 'No source EMS' + it "raises if task preflight check raises" do + errormsg = 'Unexpected error' + allow(svc_model_task).to receive(:preflight_check).and_raise(errormsg) expect { described_class.new(ae_service).main }.to raise_error(errormsg) expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => errormsg) end diff --git a/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/killvirtv2v_spec.rb b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/killvirtv2v_spec.rb new file mode 100644 index 000000000..81c3c5bc9 --- /dev/null +++ b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/killvirtv2v_spec.rb @@ -0,0 +1,109 @@ +require_domain_file +require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/Common.class/__methods__/utils.rb') + +describe ManageIQ::Automate::Transformation::Common::KillVirtV2V do + let(:user) { FactoryGirl.create(:user_with_email_and_group) } + let(:group) { FactoryGirl.create(:miq_group) } + let(:task) { FactoryGirl.create(:service_template_transformation_plan_task) } + + let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } + let(:svc_model_group) { MiqAeMethodService::MiqAeServiceMiqGroup.find(group.id) } + let(:svc_model_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task.id) } + + let(:conversion_state) do + { + "started" => true, + "disks" => [{ "path" => "[datastore] test_vm/test_vm.vmdk", "progress" => 25 }], + "pid" => 141_350, + "disk_count" => 1 + } + end + + let(:time_now) { Time.now.utc } + + let(:root) do + Spec::Support::MiqAeMockObject.new( + 'current' => current_object, + 'user' => svc_model_user, + 'state_machine_phase' => 'cleanup' + ) + end + + let(:current_object) { Spec::Support::MiqAeMockObject.new } + let(:ae_service) do + Spec::Support::MiqAeMockService.new(root).tap do |service| + current_object = Spec::Support::MiqAeMockObject.new + current_object.parent = root + service.object = current_object + end + end + + before do + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:task).and_return(svc_model_task) + allow(svc_model_task).to receive(:get_conversion_state).and_return(conversion_state) + end + + describe "#task_virtv2v_state" do + it "returns nil if virt_v2v has not started" do + allow(svc_model_task).to receive(:get_option).with(:virtv2v_started_on).and_return(nil) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_finished_on).and_return(nil) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_wrapper).and_return(nil) + expect(described_class.new(ae_service).task_virtv2v_state).to be_nil + end + + it "returns nil if virt_v2v has finished" do + allow(svc_model_task).to receive(:get_option).with(:virtv2v_started_on).and_return(time_now) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_finished_on).and_return(time_now + 1200) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_wrapper).and_return(nil) + expect(described_class.new(ae_service).task_virtv2v_state).to be_nil + end + + it "returns nil if virt_v2v_wrapper has no information" do + allow(svc_model_task).to receive(:get_option).with(:virtv2v_started_on).and_return(time_now) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_finished_on).and_return(nil) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_wrapper).and_return(nil) + expect(described_class.new(ae_service).task_virtv2v_state).to be_nil + end + + it "returns a hash if virt_v2v is still running" do + allow(svc_model_task).to receive(:get_option).with(:virtv2v_started_on).and_return(time_now) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_finished_on).and_return(nil) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_wrapper).and_return('fake_key' => 'fave_value') + expect(described_class.new(ae_service).task_virtv2v_state).to eq(conversion_state) + end + end + + describe "#kill_signal" do + it "returns KILL if gracefull kill has already been sent" do + allow(ae_service).to receive(:get_state_var).with('virtv2v_graceful_kill').and_return(true) + expect(described_class.new(ae_service).kill_signal).to eq('KILL') + end + + it "returns TERM and retries if gracefull kill has not been sent" do + allow(ae_service).to receive(:get_state_var).with('virtv2v_graceful_kill').and_return(false) + expect(described_class.new(ae_service).kill_signal).to eq('TERM') + expect(ae_service.root['ae_result']).to eq('retry') + expect(ae_service.root['ae_retry_interval']).to eq('30.seconds') + end + end + + describe "#main" do + before do + allow(svc_model_task).to receive(:get_option).with(:virtv2v_started_on).and_return(time_now) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_finished_on).and_return(nil) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_wrapper).and_return('fake_key' => 'fave_value') + end + + it "returns true if kill succeeds" do + allow(svc_model_task).to receive(:kill_virtv2v).and_return(true) + expect(described_class.new(ae_service).main).to eq(true) + end + + it "raises if kill_virtv2v fails" do + errormsg = 'Unexpected error' + allow(svc_model_task).to receive(:kill_virtv2v).and_raise(errormsg) + expect { described_class.new(ae_service).main }.to raise_error(errormsg) + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => errormsg) + end + end +end diff --git a/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/setmigrated_spec.rb b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/setmigrated_spec.rb new file mode 100644 index 000000000..4ab392c86 --- /dev/null +++ b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/setmigrated_spec.rb @@ -0,0 +1,50 @@ +require_domain_file +require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/Common.class/__methods__/utils.rb') + +describe ManageIQ::Automate::Transformation::Common::SetMigrated do + let(:user) { FactoryGirl.create(:user_with_email_and_group) } + let(:group) { FactoryGirl.create(:miq_group) } + let(:src_vm) { FactoryGirl.create(:vm) } + let(:task) { FactoryGirl.create(:service_template_transformation_plan_task, :source => src_vm) } + + let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } + let(:svc_model_group) { MiqAeMethodService::MiqAeServiceMiqGroup.find(group.id) } + let(:svc_model_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task.id) } + let(:svc_model_src_vm) { MiqAeMethodService::MiqAeServiceVm.find(src_vm.id) } + + let(:root) do + Spec::Support::MiqAeMockObject.new( + 'current' => current_object, + 'user' => svc_model_user, + 'state_machine_phase' => 'transformation' + ) + end + + let(:current_object) { Spec::Support::MiqAeMockObject.new } + let(:ae_service) do + Spec::Support::MiqAeMockService.new(root).tap do |service| + current_object = Spec::Support::MiqAeMockObject.new + current_object.parent = root + service.object = current_object + end + end + + before do + ManageIQ::Automate::Transformation::Common::SetMigrated.instance_variable_set(:@task, nil) + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:task).and_return(svc_model_task) + end + + describe "#main" do + it "sets tag on source vm" do + described_class.new(ae_service).main + expect(svc_model_src_vm.tagged_with?('transformation_status', 'migrated')).to eq(true) + end + + it "raises if task preflight check raises" do + errormsg = 'Unexpected error' + allow(svc_model_task).to receive(:mark_vm_migrated).and_raise(errormsg) + expect { described_class.new(ae_service).main }.to raise_error(errormsg) + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => errormsg) + end + end +end diff --git a/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmchecktransformed_spec.rb b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmchecktransformed_spec.rb new file mode 100644 index 000000000..cbee973a0 --- /dev/null +++ b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmchecktransformed_spec.rb @@ -0,0 +1,95 @@ +require_domain_file +require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/Common.class/__methods__/utils.rb') + +describe ManageIQ::Automate::Transformation::Common::VMCheckTransformed do + let(:user) { FactoryGirl.create(:user_with_email_and_group) } + let(:group) { FactoryGirl.create(:miq_group) } + let(:task) { FactoryGirl.create(:service_template_transformation_plan_task) } + + let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } + let(:svc_model_group) { MiqAeMethodService::MiqAeServiceMiqGroup.find(group.id) } + let(:svc_model_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task.id) } + + let(:root) do + Spec::Support::MiqAeMockObject.new( + 'current' => current_object, + 'user' => svc_model_user, + 'state_machine_phase' => 'transformation' + ) + end + + let(:current_object) { Spec::Support::MiqAeMockObject.new } + let(:ae_service) do + Spec::Support::MiqAeMockService.new(root).tap do |service| + current_object = Spec::Support::MiqAeMockObject.new + current_object.parent = root + service.object = current_object + end + end + + before do + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:task).and_return(svc_model_task) + end + + describe "#main" do + context "virtv2v has not started conversion" do + let(:virtv2v_disks) do + [ + { :path => '[datastore] test_vm/test_vm.vmdk', :size => 1_234_567, :percent => 0, :weight => 25 }, + { :path => '[datastore] test_vm/test_vm-2.vmdk', :size => 3_703_701, :percent => 0, :weight => 75 } + ] + end + + it "returns a message stating conversion has not started" do + svc_model_task[:options][:virtv2v_disks] = virtv2v_disks + allow(svc_model_task).to receive(:get_conversion_state).and_return(true) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_status).and_return('active') + described_class.new(ae_service).main + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => 'Disks transformation is initializing.', 'percent' => 1.0) + end + end + + context "conversion is still running" do + let(:virtv2v_disks) do + [ + { :path => '[datastore] test_vm/test_vm.vmdk', :size => 1_234_567, :percent => 100, :weight => 25 }, + { :path => '[datastore] test_vm/test_vm-2.vmdk', :size => 3_703_701, :percent => 25, :weight => 75 } + ] + end + + it "returns a message stating conversion has not started" do + svc_model_task[:options][:virtv2v_disks] = virtv2v_disks + allow(svc_model_task).to receive(:get_conversion_state).and_return(true) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_status).and_return('active') + described_class.new(ae_service).main + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => 'Converting disk 2 / 2 [43.75%].', 'percent' => 43.75) + end + end + + context "conversion has failed" do + it "raises with a message stating conversion has failed" do + allow(svc_model_task).to receive(:get_conversion_state).and_return(true) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_status).and_return('failed') + errormsg = 'Disks transformation failed.' + expect { described_class.new(ae_service).main }.to raise_error(errormsg) + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => errormsg) + end + end + + context "conversion has successfuly finished" do + it "returns a message stating conversion succeeded" do + allow(svc_model_task).to receive(:get_conversion_state).and_return(true) + allow(svc_model_task).to receive(:get_option).with(:virtv2v_status).and_return('succeeded') + described_class.new(ae_service).main + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => 'Disks transformation succeeded.', 'percent' => 100) + end + end + + it "raises if get_conversion_state fails" do + errormsg = 'Unexpected error' + allow(svc_model_task).to receive(:get_conversion_state).and_raise(errormsg) + expect { described_class.new(ae_service).main }.to raise_error(errormsg) + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => errormsg) + end + end +end diff --git a/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmtransform_spec.rb b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmtransform_spec.rb new file mode 100644 index 000000000..139f5942b --- /dev/null +++ b/spec/content/automate/ManageIQ/Transformation/Common.class/__methods__/vmtransform_spec.rb @@ -0,0 +1,45 @@ +require_domain_file +require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/Common.class/__methods__/utils.rb') + +describe ManageIQ::Automate::Transformation::Common::VMTransform do + let(:user) { FactoryGirl.create(:user_with_email_and_group) } + let(:group) { FactoryGirl.create(:miq_group) } + let(:task) { FactoryGirl.create(:service_template_transformation_plan_task) } + + let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } + let(:svc_model_group) { MiqAeMethodService::MiqAeServiceMiqGroup.find(group.id) } + let(:svc_model_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task.id) } + + let(:root) do + Spec::Support::MiqAeMockObject.new( + 'current' => current_object, + 'user' => svc_model_user, + 'state_machine_phase' => 'transformation' + ) + end + + let(:current_object) { Spec::Support::MiqAeMockObject.new } + let(:ae_service) do + Spec::Support::MiqAeMockService.new(root).tap do |service| + current_object = Spec::Support::MiqAeMockObject.new + current_object.parent = root + service.object = current_object + end + end + + before do + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:task).and_return(svc_model_task) + end + + it "returns 'active' if run_conversion succeeds " do + allow(svc_model_task).to receive(:run_conversion).and_return('active') + expect(described_class.new(ae_service).main).to eq('active') + end + + it "raises if run_conversion fails" do + errormsg = 'Unexpected error' + allow(svc_model_task).to receive(:run_conversion).and_raise(errormsg) + expect { described_class.new(ae_service).main }.to raise_error(errormsg) + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => errormsg) + end +end diff --git a/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon_spec.rb b/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon_spec.rb new file mode 100644 index 000000000..411c7ba49 --- /dev/null +++ b/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkpoweredon_spec.rb @@ -0,0 +1,68 @@ +require_domain_file +require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/Common.class/__methods__/utils.rb') + +describe ManageIQ::Automate::Transformation::Infrastructure::VM::Common::CheckPoweredOn do + let(:user) { FactoryGirl.create(:user_with_email_and_group) } + let(:group) { FactoryGirl.create(:miq_group) } + let(:vm) { FactoryGirl.create(:vm) } + let(:task) { FactoryGirl.create(:service_template_transformation_plan_task) } + + let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } + let(:svc_model_group) { MiqAeMethodService::MiqAeServiceMiqGroup.find(group.id) } + let(:svc_model_vm) { MiqAeMethodService::MiqAeServiceVm.find(vm.id) } + let(:svc_model_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task.id) } + + let(:root) do + Spec::Support::MiqAeMockObject.new( + 'current' => current_object, + 'user' => svc_model_user, + 'state_machine_phase' => 'transformation' + ) + end + + let(:current_object) { Spec::Support::MiqAeMockObject.new } + let(:ae_service) do + Spec::Support::MiqAeMockService.new(root).tap do |service| + current_object = Spec::Support::MiqAeMockObject.new + current_object.parent = root + service.object = current_object + end + end + + before do + ManageIQ::Automate::Transformation::Infrastructure::VM::Common::CheckPoweredOn.instance_variable_set(:@task, nil) + ManageIQ::Automate::Transformation::Infrastructure::VM::Common::CheckPoweredOn.instance_variable_set(:@vm, nil) + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:task).and_return(svc_model_task) + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:source_vm).and_return(svc_model_vm) + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:destination_vm).and_return(svc_model_vm) + allow(svc_model_task).to receive(:get_option).with(:source_vm_power_state).and_return('on') + allow(svc_model_vm).to receive(:power_state).and_return('off') + end + + shared_examples_for "#main" do + it "retries if VM is not powered on" do + described_class.new(ae_service).main + expect(ae_service.root['ae_result']).to eq('retry') + expect(ae_service.root['ae_retry_interval']).to eq('15.seconds') + end + end + + describe "#main" do + context "handling source vm" do + before { ae_service.root['state_machine_phase'] = 'transformation' } + it_behaves_like "#main" + end + + context "handling destination vm" do + before { ae_service.root['state_machine_phase'] = 'cleanup' } + it_behaves_like "#main" + end + + it "raises if task preflight check raises" do + errormsg = 'Unexpected error' + allow(svc_model_task).to receive(:get_option).with(:source_vm_power_state).and_raise(errormsg) + expect { described_class.new(ae_service).main }.to raise_error(errormsg) + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => errormsg) + end + end +end diff --git a/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory_spec.rb b/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory_spec.rb index d12232182..b8dcc5646 100644 --- a/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory_spec.rb +++ b/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/checkvmininventory_spec.rb @@ -1,14 +1,41 @@ require_domain_file +require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/Common.class/__methods__/utils.rb') describe ManageIQ::Automate::Transformation::Infrastructure::VM::Common::CheckVmInInventory do let(:user) { FactoryGirl.create(:user_with_email_and_group) } - let(:task) { FactoryGirl.create(:service_template_transformation_plan_task) } - let(:src_vm_vmware) { FactoryGirl.create(:vm_vmware) } - let(:dst_vm_redhat) { FactoryGirl.create(:vm_redhat) } - let(:dst_vm_openstack) { FactoryGirl.create(:vm_openstack) } - let(:src_cluster) { FactoryGirl.create(:ems_cluster) } - let(:dst_cluster) { FactoryGirl.create(:ems_cluster) } + let(:src_vm_vmware) { FactoryGirl.create(:vm_vmware, :ext_management_system => src_ems, :ems_cluster => src_cluster) } + let(:dst_vm_redhat) { FactoryGirl.create(:vm_redhat, :ext_management_system => dst_ems) } + let(:dst_vm_openstack) { FactoryGirl.create(:vm_openstack, :ext_management_system => dst_ems) } + let(:src_ems) { FactoryGirl.create(:ext_management_system) } + let(:src_cluster) { FactoryGirl.create(:ems_cluster, :ext_management_system => src_ems) } let(:dst_ems) { FactoryGirl.create(:ext_management_system) } + let(:dst_cluster) { FactoryGirl.create(:ems_cluster, :ext_management_system => dst_ems) } + + let(:mapping) do + FactoryGirl.create( + :transformation_mapping, + :transformation_mapping_items => [ + FactoryGirl.create(:transformation_mapping_item, :source => src_cluster, :destination => dst_cluster) + ] + ) + end + + let(:catalog_item_options) do + { + :name => 'Transformation Plan', + :description => 'a description', + :config_info => { + :transformation_mapping_id => mapping.id, + :actions => [ + {:vm_id => src_vm.id.to_s, :pre_service => false, :post_service => false} + ], + } + } + end + + let(:plan) { ServiceTemplateTransformationPlan.create_catalog_item(catalog_item_options) } + let(:request) { FactoryGirl.create(:service_template_transformation_plan_request, :source => plan) } + let(:task) { FactoryGirl.create(:service_template_transformation_plan_task, :miq_request => request, :request_type => 'transformation_plan', :source => src_vm_vmware) } let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } let(:svc_model_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task.id) } @@ -23,6 +50,7 @@ Spec::Support::MiqAeMockObject.new( 'current' => current_object, 'user' => svc_model_user, + 'state_machine_phase' => 'transformation' ) end @@ -34,60 +62,39 @@ end end - context "validate task" do - it "when task is nil" do - errormsg = 'ERROR - A service_template_transformation_plan_task is needed for this method to continue' - expect { described_class.new(ae_service).task }.to raise_error(errormsg) - end + let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceVm } - it "when task is present" do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - expect(described_class.new(ae_service).task.id).to eq(svc_model_task.id) - end - end + before do + ManageIQ::Automate::Transformation::Infrastructure::VM::Common::CheckVmInInventory.instance_variable_set(:@task, nil) + ManageIQ::Automate::Transformation::Infrastructure::VM::Common::CheckVmInInventory.instance_variable_set(:@source_vm, nil) - shared_examples_for "validate source and destination vms" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceVm } + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:task).and_return(svc_model_task) + allow(ae_service).to receive(:vmdb).with(:vm).and_return(svc_vmdb_handle) + end + shared_examples_for "#main" do before do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - end - - it "when task.source vm is nil" do - errormsg = 'ERROR - Source VM has not been defined in the task' - expect { described_class.new(ae_service).source_vm }.to raise_error(errormsg) + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:source_vm).and_return(svc_model_src_vm) end - it "when task.source is present" do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - allow(svc_model_task).to receive(:source) { svc_model_src_vm } - expect(described_class.new(ae_service).source_vm.id).to eq(svc_model_src_vm.id) - end - - it "when destination_vm is nil" do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - allow(svc_model_task).to receive(:source) { svc_model_src_vm } - allow(svc_model_task).to receive(:transformation_destination).and_return(svc_model_dst_cluster) - allow(svc_model_dst_cluster).to receive(:ext_management_system).and_return(svc_model_dst_ems) - allow(ae_service).to receive(:vmdb).with(:vm).and_return(svc_vmdb_handle) + it "retries if destination_vm is nil" do allow(svc_vmdb_handle).to receive(:find_by).with(:name => svc_model_src_vm.name, :ems_id => svc_model_dst_ems.id).and_return(nil) - expect(described_class.new(ae_service).destination_vm).to be_nil described_class.new(ae_service).main expect(ae_service.root['ae_result']).to eq('retry') expect(ae_service.root['ae_retry_interval']).to eq('15.seconds') end - it "when destination_vm is present" do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - allow(svc_model_task).to receive(:source) { svc_model_src_vm } - allow(svc_model_task).to receive(:transformation_destination).and_return(svc_model_dst_cluster) - allow(svc_model_dst_cluster).to receive(:ext_management_system).and_return(svc_model_dst_ems) - allow(ae_service).to receive(:vmdb).with(:vm).and_return(svc_vmdb_handle) + it "sets task options if destination_vm exists" do allow(svc_vmdb_handle).to receive(:find_by).with(:name => svc_model_src_vm.name, :ems_id => svc_model_dst_ems.id).and_return(svc_model_dst_vm) - expect(described_class.new(ae_service).destination_vm.id).to eq(svc_model_dst_vm.id) described_class.new(ae_service).main expect(svc_model_task.get_option(:destination_vm_id)).to eq(svc_model_dst_vm.id) end + + it "raises if VMDB find raises" do + allow(svc_vmdb_handle).to receive(:find_by).with(:name => svc_model_src_vm.name, :ems_id => svc_model_dst_ems.id).and_raise('Unexpected error') + expect { described_class.new(ae_service).main }.to raise_error('Unexpected error') + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => 'Unexpected error') + end end context "validate when source is vmware and destination redhat" do @@ -96,7 +103,7 @@ let(:svc_model_src_vm) { svc_model_src_vm_vmware } let(:svc_model_dst_vm) { svc_model_dst_vm_redhat } - it_behaves_like "validate source and destination vms" + it_behaves_like "#main" end context "validate when source is vmware and destination openstack" do @@ -105,18 +112,6 @@ let(:svc_model_src_vm) { svc_model_src_vm_vmware } let(:svc_model_dst_vm) { svc_model_dst_vm_openstack } - it_behaves_like "validate source and destination vms" - end - - context "catchall exception rescue" do - before do - allow(svc_model_task).to receive(:source).and_raise(StandardError.new('kaboom')) - end - - it "forcefully raise" do - errormsg = 'ERROR - A service_template_transformation_plan_task is needed for this method to continue' - expect { described_class.new(ae_service).main }.to raise_error(errormsg) - expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => errormsg) - end + it_behaves_like "#main" end end diff --git a/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes_spec.rb b/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes_spec.rb index 552aaaf90..ee005bfa4 100644 --- a/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes_spec.rb +++ b/spec/content/automate/ManageIQ/Transformation/Infrastructure/VM/Common.class/__methods__/restorevmattributes_spec.rb @@ -1,4 +1,5 @@ require_domain_file +require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/Common.class/__methods__/utils.rb') describe ManageIQ::Automate::Transformation::Infrastructure::VM::Common::RestoreVmAttributes do let(:user) { FactoryGirl.create(:user_with_email_and_group) } @@ -46,114 +47,42 @@ def set_vm_identity svc_model_src_vm.retirement_warn = 7 end - context "validate task" do - it "when task is nil" do - errormsg = 'ERROR - A service_template_transformation_plan_task is needed for this method to continue' - expect { described_class.new(ae_service).task }.to raise_error(errormsg) - end - - it "when task is present" do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - expect(described_class.new(ae_service).task.id).to eq(svc_model_task.id) - end - end - - shared_examples_for "validate source and destination vms" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceVm } - - before do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - end - - it "when task.source is nil" do - errormsg = 'ERROR - Source VM has not been defined in the task' - expect { described_class.new(ae_service).source_vm }.to raise_error(errormsg) - end - - it "when task.source is present" do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - allow(svc_model_task).to receive(:source) { svc_model_src_vm } - expect(described_class.new(ae_service).source_vm.id).to eq(svc_model_src_vm.id) - end - - it "when destination_vm_id option is absent" do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - errormsg = "ERROR - destination_vm_id is blank" - expect { described_class.new(ae_service).destination_vm }.to raise_error(errormsg) - end - - it "when destination_vm is nil" do - allow(svc_model_task).to receive(:get_option).with(:destination_vm_id).and_return(svc_model_dst_vm.id) - allow(ae_service).to receive(:vmdb).with(:vm).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:find_by).with(:id => svc_model_dst_vm.id).and_return(nil) - errormsg = 'ERROR - Destination VM not found in the database after migration' - expect { described_class.new(ae_service).destination_vm }.to raise_error(errormsg) - end - - it "when destination_vm present" do - allow(svc_model_task).to receive(:get_option).with(:destination_vm_id).and_return(svc_model_dst_vm.id) - allow(ae_service).to receive(:vmdb).with(:vm).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:find_by).with(:id => svc_model_dst_vm.id).and_return(svc_model_dst_vm) - expect(described_class.new(ae_service).destination_vm.id).to eq(svc_model_dst_vm.id) - end - end - - context "validate when source is vmware and destination redhat" do - let(:src_vm) { src_vm_vmware } - let(:dst_vm) { dst_vm_redhat } - let(:svc_model_src_vm) { svc_model_src_vm_vmware } - let(:svc_model_dst_vm) { svc_model_dst_vm_redhat } - - it_behaves_like "validate source and destination vms" - end - - context "validate when source is vmware and destination openstack" do - let(:src_vm) { src_vm_vmware } - let(:dst_vm) { dst_vm_openstack } - let(:svc_model_src_vm) { svc_model_src_vm_vmware } - let(:svc_model_dst_vm) { svc_model_dst_vm_openstack } - - it_behaves_like "validate source and destination vms" - end - shared_examples_for "restore identity" do let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceMiqGroup } before do - ae_service.root['service_template_transformation_plan_task'] = svc_model_task - allow(svc_model_task).to receive(:source) { svc_model_src_vm } - allow(svc_model_task).to receive(:get_option).with(:destination_vm_id).and_return(svc_model_dst_vm.id) - allow(ae_service).to receive(:vmdb).with(:vm).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:find_by).with(:id => svc_model_dst_vm.id).and_return(svc_model_dst_vm) + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:task).and_return(svc_model_task) + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:source_vm).and_return(svc_model_src_vm) + allow(ManageIQ::Automate::Transformation::Common::Utils).to receive(:destination_vm).and_return(svc_model_dst_vm) set_vm_identity end it "restore service" do - described_class.new(ae_service).vm_restore_service(svc_model_src_vm, svc_model_dst_vm) + described_class.new(ae_service).vm_restore_service expect(svc_model_src_vm.service).to be_nil expect(svc_model_dst_vm.service.id).to eq(svc_model_service.id) end it "restore tags" do - described_class.new(ae_service).vm_restore_tags(svc_model_src_vm, svc_model_dst_vm) + described_class.new(ae_service).vm_restore_tags expect(svc_model_dst_vm.tags).to eq(["environment/prod"]) end it "restore customer attributes" do - described_class.new(ae_service).vm_restore_custom_attributes(svc_model_src_vm, svc_model_dst_vm) + described_class.new(ae_service).vm_restore_custom_attributes expect(svc_model_dst_vm.custom_get('attr')).to eq('value') end it "restore ownership" do allow(ae_service).to receive(:vmdb).with(:miq_group).and_return(svc_vmdb_handle) allow(svc_vmdb_handle).to receive(:find_by).with(:id => svc_model_group.id).and_return(svc_model_group) - described_class.new(ae_service).vm_restore_ownership(svc_model_src_vm, svc_model_dst_vm) + described_class.new(ae_service).vm_restore_ownership expect(svc_model_dst_vm.owner.id).to eq(svc_model_user.id) expect(svc_model_dst_vm.miq_group_id).to eq(svc_model_group.id) end it "restore retirement" do - described_class.new(ae_service).vm_restore_retirement(svc_model_src_vm, svc_model_dst_vm) + described_class.new(ae_service).vm_restore_retirement expect(svc_model_dst_vm.retires_on.to_i).to be(retirement_date.to_i) expect(svc_model_dst_vm.retirement_warn).to eq(7) end @@ -171,6 +100,12 @@ def set_vm_identity expect(svc_model_dst_vm.retires_on.to_i).to be(retirement_date.to_i) expect(svc_model_dst_vm.retirement_warn).to eq(7) end + + it "forcefully raise" do + allow(svc_model_src_vm).to receive(:service).and_raise('Unexpected error') + expect { described_class.new(ae_service).main }.to raise_error('Unexpected error') + expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => 'Unexpected error') + end end context "restore when source is vmware and destination redhat" do @@ -190,16 +125,4 @@ def set_vm_identity it_behaves_like "restore identity" end - - context "catchall exception rescue" do - before do - allow(svc_model_task).to receive(:source).and_raise(StandardError.new('kaboom')) - end - - it "forcefully raise" do - errormsg = 'ERROR - A service_template_transformation_plan_task is needed for this method to continue' - expect { described_class.new(ae_service).main }.to raise_error(errormsg) - expect(ae_service.get_state_var(:ae_state_progress)).to eq('message' => errormsg) - end - end end diff --git a/spec/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils_spec.rb b/spec/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils_spec.rb deleted file mode 100644 index 64f25442e..000000000 --- a/spec/content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils_spec.rb +++ /dev/null @@ -1,314 +0,0 @@ -require_domain_file -require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils.rb') -require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/Infrastructure/VM/vmwarews.class/__methods__/utils.rb') -require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/TransformationHosts/ovirt_host.class/__methods__/utils.rb') - -describe ManageIQ::Automate::Transformation::TransformationHosts::Common::Utils do - let(:user) { FactoryGirl.create(:user_with_email_and_group) } - let(:task_1) { FactoryGirl.create(:service_template_transformation_plan_task) } - let(:task_2) { FactoryGirl.create(:service_template_transformation_plan_task) } - let(:task_3) { FactoryGirl.create(:service_template_transformation_plan_task) } - let(:dst_ems_redhat) { FactoryGirl.create(:ems_redhat) } - let(:src_host) { FactoryGirl.create(:host) } - let(:dst_host_1) { FactoryGirl.create(:host) } - let(:dst_host_2) { FactoryGirl.create(:host) } - let(:dst_host_3) { FactoryGirl.create(:host) } - let(:src_vm_vmware) { FactoryGirl.create(:vm_vmware) } - let(:src_cluster) { FactoryGirl.create(:ems_cluster) } - let(:dst_cluster) { FactoryGirl.create(:ems_cluster) } - let(:src_storage) { FactoryGirl.create(:storage) } - let(:dst_storage) { FactoryGirl.create(:storage) } - let(:src_lan_1) { FactoryGirl.create(:lan) } - let(:src_lan_2) { FactoryGirl.create(:lan) } - let(:dst_lan_1) { FactoryGirl.create(:lan) } - let(:dst_lan_2) { FactoryGirl.create(:lan) } - let(:hardware) { FactoryGirl.create(:hardware) } - let(:nic_1) { FactoryGirl.create(:guest_device_nic) } - let(:nic_2) { FactoryGirl.create(:guest_device_nic) } - - let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } - let(:svc_model_task_1) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task_1.id) } - let(:svc_model_task_2) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task_2.id) } - let(:svc_model_task_3) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(task_3.id) } - let(:svc_model_dst_ems_redhat) { MiqAeMethodService::MiqAeServiceExtManagementSystem.find(dst_ems_redhat.id) } - let(:svc_model_src_host) { MiqAeMethodService::MiqAeServiceHost.find(src_host.id) } - let(:svc_model_dst_host_1) { MiqAeMethodService::MiqAeServiceHost.find(dst_host_1.id) } - let(:svc_model_dst_host_2) { MiqAeMethodService::MiqAeServiceHost.find(dst_host_2.id) } - let(:svc_model_dst_host_3) { MiqAeMethodService::MiqAeServiceHost.find(dst_host_3.id) } - let(:svc_model_src_vm_vmware) { MiqAeMethodService::MiqAeServiceManageIQ_Providers_Vmware_InfraManager_Vm.find(src_vm_vmware.id) } - let(:svc_model_src_cluster) { MiqAeMethodService::MiqAeServiceEmsCluster.find(src_cluster.id) } - let(:svc_model_dst_cluster) { MiqAeMethodService::MiqAeServiceEmsCluster.find(dst_cluster.id) } - let(:svc_model_src_storage) { MiqAeMethodService::MiqAeServiceStorage.find(src_storage) } - let(:svc_model_dst_storage) { MiqAeMethodService::MiqAeServiceStorage.find(dst_storage) } - let(:svc_model_src_lan_1) { MiqAeMethodService::MiqAeServiceLan.find(src_lan_1) } - let(:svc_model_src_lan_2) { MiqAeMethodService::MiqAeServiceLan.find(src_lan_2) } - let(:svc_model_dst_lan_1) { MiqAeMethodService::MiqAeServiceLan.find(dst_lan_1) } - let(:svc_model_dst_lan_2) { MiqAeMethodService::MiqAeServiceLan.find(dst_lan_2) } - let(:svc_model_hardware) { MiqAeMethodService::MiqAeServiceHardware.find(hardware) } - let(:svc_model_guest_device_1) { MiqAeMethodService::MiqAeServiceGuestDevice.find(guest_device_1) } - let(:svc_model_guest_device_2) { MiqAeMethodService::MiqAeServiceGuestDevice.find(guest_device_2) } - let(:svc_model_nic_1) { MiqAeMethodService::MiqAeServiceGuestDevice.find(nic_1) } - let(:svc_model_nic_2) { MiqAeMethodService::MiqAeServiceGuestDevice.find(nic_2) } - - let(:disk_1) { instance_double("disk", :device_name => "Hard disk 1", :device_type => "disk", :filename => "[datastore12] test_vm/test_vm.vmdk", :size => 17_179_869_184) } - let(:disk_2) { instance_double("disk", :device_name => "Hard disk 2", :device_type => "disk", :filename => "[datastore12] test_vm/test_vm-2.vmdk", :size => 17_179_869_184) } - - let(:virtv2v_networks) do - [ - { :source => svc_model_src_lan_1.name, :destination => svc_model_dst_lan_1.name, :mac_address => svc_model_nic_1.address }, - { :source => svc_model_src_lan_2.name, :destination => svc_model_dst_lan_2.name, :mac_address => svc_model_nic_2.address }, - ] - end - - let(:virtv2v_disks) do - [ - { :path => disk_1.filename, :size => disk_1.size, :percent => 0, :weight => 50.0 }, - { :path => disk_2.filename, :size => disk_2.size, :percent => 0, :weight => 50.0 } - ] - end - - let(:root) do - Spec::Support::MiqAeMockObject.new( - 'current' => current_object, - 'user' => svc_model_user, - ) - end - - let(:current_object) { Spec::Support::MiqAeMockObject.new } - let(:ae_service) do - Spec::Support::MiqAeMockService.new(root).tap do |service| - current_object.parent = root - service.current_object = current_object - end - end - - before do - allow(svc_model_dst_ems_redhat).to receive(:hosts).and_return([svc_model_dst_host_1, svc_model_dst_host_2, svc_model_dst_host_3]) - allow(svc_model_dst_host_1).to receive(:tagged_with?).with('v2v_transformation_host', 'true').and_return(true) - allow(svc_model_dst_host_2).to receive(:tagged_with?).with('v2v_transformation_host', 'true').and_return(true) - allow(svc_model_dst_host_1).to receive(:tags).with('v2v_transformation_method').and_return('vddk') - allow(svc_model_dst_host_2).to receive(:tags).with('v2v_transformation_method').and_return('vddk') - end - - context "#get_runners_count_by_host" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } - - it "without only one task" do - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([svc_model_task_1, svc_model_task_2]) - allow(svc_model_task_1).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_1.id) - expect(described_class.get_runners_count_by_host(svc_model_dst_host_1, ae_service)).to eq(1) - end - end - - context "#host_max_runners" do - it "with custom attribute" do - allow(svc_model_dst_host_1).to receive(:custom_get).with('Max Transformation Runners').and_return('2') - expect(described_class.host_max_runners(svc_model_dst_host_1, {})).to eq(2) - end - - it "with factory_config key" do - expect(described_class.host_max_runners(svc_model_dst_host_1, {'transformation_host_max_runners' => 2}, ae_service)).to eq(2) - end - - it "with overridden max_runners" do - expect(described_class.host_max_runners(svc_model_dst_host_1, {}, 2)).to eq(2) - end - - it "with default" do - expect(described_class.host_max_runners(svc_model_dst_host_1, {})).to eq(10) - end - end - - context "#transformation_hosts" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } - - it "filter out untagged hosts and order tagged hosts" do - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([svc_model_task_1, svc_model_task_2, svc_model_task_3]) - allow(svc_model_task_1).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_1.id) - allow(svc_model_task_2).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_1.id) - allow(svc_model_task_3).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_2.id) - - expect(described_class.transformation_hosts(svc_model_dst_ems_redhat, {}, ae_service)).to eq( - [ - { - :type => 'OVirtHost', - :transformation_method => 'vddk', - :host => svc_model_dst_host_2, - :runners => { - :current => 1, - :maximum => 10 - } - }, - { - :type => 'OVirtHost', - :transformation_method => 'vddk', - :host => svc_model_dst_host_1, - :runners => { - :current => 2, - :maximum => 10 - } - } - ] - ) - end - end - - context "#eligible_transformation_hosts" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } - - it "filter out hosts that reached their max runners" do - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([svc_model_task_1, svc_model_task_2, svc_model_task_3]) - allow(svc_model_task_1).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_1.id) - allow(svc_model_task_2).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_1.id) - allow(svc_model_task_3).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_2.id) - allow(svc_model_dst_host_1).to receive(:custom_get).with('Max Transformation Runners').and_return('2') - - expect(described_class.eligible_transformation_hosts(svc_model_dst_ems_redhat, {}, ae_service)).to eq( - [ - { - :type => 'OVirtHost', - :transformation_method => 'vddk', - :host => svc_model_dst_host_2, - :runners => { - :current => 1, - :maximum => 10 - } - } - ] - ) - end - end - - context "#get_runners_count_by_ems" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } - - it "mixed hosts configurations" do - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([svc_model_task_1, svc_model_task_2, svc_model_task_3]) - allow(svc_model_task_1).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_1.id) - allow(svc_model_task_2).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_1.id) - allow(svc_model_task_3).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_2.id) - expect(described_class.get_runners_count_by_ems(svc_model_dst_ems_redhat, {}, ae_service)).to eq(3) - end - end - - context "#ems_max_runners" do - it "with custom attribute" do - allow(svc_model_dst_ems_redhat).to receive(:custom_get).with('Max Transformation Runners').and_return('2') - expect(described_class.ems_max_runners(svc_model_dst_ems_redhat, {})).to eq(2) - end - - it "with factory_config key" do - expect(described_class.ems_max_runners(svc_model_dst_ems_redhat, {'ems_max_runners' => 2}, ae_service)).to eq(2) - end - - it "with overridden max_runners" do - expect(described_class.ems_max_runners(svc_model_dst_ems_redhat, {}, 2)).to eq(2) - end - - it "with default" do - expect(described_class.ems_max_runners(svc_model_dst_ems_redhat, {})).to eq(10) - end - end - - context "#get_transformation_host" do - let(:svc_vmdb_handle_ems) { MiqAeMethodService::MiqAeServiceExtManagementSystem } - let(:svc_vmdb_handle_transformation_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } - - before do - allow(ae_service).to receive(:vmdb).with(:ext_management_system).and_return(svc_vmdb_handle_ems) - allow(svc_vmdb_handle_ems).to receive(:find_by).with(:id => svc_model_dst_ems_redhat.id).and_return(svc_model_dst_ems_redhat) - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle_transformation_task) - allow(svc_vmdb_handle_transformation_task).to receive(:where).with(:state => 'active').and_return([svc_model_task_1, svc_model_task_2, svc_model_task_3]) - allow(svc_model_task_3).to receive(:get_option).with(:destination_ems_id).and_return(svc_model_dst_ems_redhat.id) - allow(svc_model_task_1).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_1.id) - allow(svc_model_task_2).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_dst_host_2.id) - allow(svc_model_task_3).to receive(:get_option).with(:transformation_host_id).and_return(nil) - end - - it "when ems max runners is reached" do - expect(described_class.get_transformation_host(svc_model_task_3, { 'ems_max_runners' => 2 }, ae_service)).to be_nil - end - - it "without an eligible host" do - expect(described_class.get_transformation_host(svc_model_task_3, { 'transformation_host_max_runners' => 1 }, ae_service)).to be_nil - end - - it "with an eligible host" do - allow(svc_model_dst_host_1).to receive(:custom_get).with('Max Transformation Runners').and_return('1') - expect(described_class.get_transformation_host(svc_model_task_3, {}, ae_service)).to eq(['OVirtHost', svc_model_dst_host_2, 'vddk']) - end - end - - context "#virtv2vwrapper_options as when transformation type is vmwarews2rhevm" do - before do - allow(svc_model_task_1).to receive(:get_option).with(:transformation_type).and_return('vmwarews2rhevm') - svc_model_task_1[:options][:virtv2v_disks] = virtv2v_disks - svc_model_task_1[:options][:virtv2v_networks] = virtv2v_networks - allow(svc_model_task_1).to receive(:source).and_return(svc_model_src_vm_vmware) - allow(svc_model_src_vm_vmware).to receive(:ems_cluster).and_return(svc_model_src_cluster) - allow(svc_model_task_1).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(svc_model_dst_cluster) - allow(svc_model_dst_cluster).to receive(:ext_management_system).and_return(svc_model_dst_ems_redhat) - allow(svc_model_dst_ems_redhat).to receive(:authentication_password).and_return('rhv_passwd') - allow(svc_model_src_vm_vmware).to receive(:hardware).and_return(svc_model_hardware) - allow(svc_model_hardware).to receive(:disks).and_return([disk_1, disk_2]) - allow(disk_1).to receive(:storage).and_return(svc_model_src_storage) - allow(svc_model_task_1).to receive(:transformation_destination).with(svc_model_src_storage).and_return(svc_model_dst_storage) - allow(svc_model_hardware).to receive(:nics).and_return([svc_model_nic_1, svc_model_nic_2]) - allow(svc_model_task_1).to receive(:transformation_destination).with(svc_model_src_lan_1).and_return(svc_model_dst_lan_1) - allow(svc_model_task_1).to receive(:transformation_destination).with(svc_model_src_lan_2).and_return(svc_model_dst_lan_2) - allow(svc_model_src_vm_vmware).to receive(:host).and_return(svc_model_src_host) - allow(svc_model_src_host).to receive(:ipaddress).and_return('10.0.0.1') - allow(svc_model_src_host).to receive(:authentication_userid).and_return('esx_user') - allow(svc_model_src_host).to receive(:authentication_password).and_return('esx_passwd') - allow(ManageIQ::Automate::Transformation::Infrastructure::VM::VMware::Utils).to receive(:host_fingerprint).with(svc_model_src_host).and_return('01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67') - end - - it "when transformation method is vddk" do - allow(svc_model_task_1).to receive(:get_option).with(:transformation_method).and_return('vddk') - expect(described_class.virtv2vwrapper_options(svc_model_task_1)).to eq( - :vm_name => svc_model_src_vm_vmware.name, - :transport_method => 'vddk', - :vmware_fingerprint => '01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67', - :vmware_uri => "esx://esx_user@10.0.0.1/?no_verify=1", - :vmware_password => 'esx_passwd', - :rhv_url => "https://#{svc_model_dst_ems_redhat.hostname}/ovirt-engine/api", - :rhv_cluster => svc_model_dst_cluster.name, - :rhv_storage => svc_model_dst_storage.name, - :rhv_password => 'rhv_passwd', - :source_disks => [disk_1.filename, disk_2.filename], - :network_mappings => virtv2v_networks, - :install_drivers => true, - :insecure_connection => true - ) - end - - it "when transformation method is ssh" do - allow(svc_model_task_1).to receive(:get_option).with(:transformation_method).and_return('ssh') - expect(described_class.virtv2vwrapper_options(svc_model_task_1)).to eq( - :vm_name => "ssh://root@10.0.0.1/vmfs/volumes/#{svc_model_src_storage.name}/#{svc_model_src_vm_vmware.location}", - :transport_method => 'ssh', - :rhv_url => "https://#{svc_model_dst_ems_redhat.hostname}/ovirt-engine/api", - :rhv_cluster => svc_model_dst_cluster.name, - :rhv_storage => svc_model_dst_storage.name, - :rhv_password => 'rhv_passwd', - :source_disks => [disk_1.filename, disk_2.filename], - :network_mappings => virtv2v_networks, - :install_drivers => true, - :insecure_connection => true - ) - end - end - - context "#remote_command" do - it "check constantize with ovirt host" do - allow(svc_model_task_1).to receive(:get_option).with(:transformation_host_type).and_return('OVirtHost') - allow(ManageIQ::Automate::Transformation::TransformationHosts::OVirtHost::Utils).to receive(:remote_command).with(svc_model_dst_host_1, 'my_command', 'test stdin').and_return(:success => true, :stdout => 'test stdout', :rc => 0) - expect(ManageIQ::Automate::Transformation::TransformationHosts::OVirtHost::Utils).to receive(:remote_command).with(svc_model_dst_host_1, 'my_command', 'test stdin', nil) - described_class.remote_command(svc_model_task_1, svc_model_dst_host_1, 'my_command', 'test stdin') - end - end -end diff --git a/spec/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils_spec.rb b/spec/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils_spec.rb index 3130899ec..1a03bf753 100644 --- a/spec/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils_spec.rb +++ b/spec/content/automate/ManageIQ/Transformation/TransformationThrottler.class/__methods__/utils_spec.rb @@ -1,5 +1,4 @@ require_domain_file -require File.join(ManageIQ::Content::Engine.root, 'content/automate/ManageIQ/Transformation/TransformationHosts/Common.class/__methods__/utils.rb') describe ManageIQ::Automate::Transformation::TransformationThrottler::Utils do let(:user) { FactoryGirl.create(:user_with_email_and_group) } @@ -7,18 +6,68 @@ let(:automation_request_1) { FactoryGirl.create(:automation_request) } let(:automation_request_2) { FactoryGirl.create(:automation_request) } let(:automation_request_3) { FactoryGirl.create(:automation_request) } - let(:transformation_task_1) { FactoryGirl.create(:service_template_transformation_plan_task) } - let(:transformation_task_2) { FactoryGirl.create(:service_template_transformation_plan_task) } - let(:host) { FactoryGirl.create(:host) } + let(:src_cluster) { FactoryGirl.create(:ems_cluster) } + let(:src_vm_1) { FactoryGirl.create(:vm_or_template, :ems_cluster => src_cluster) } + let(:src_vm_2) { FactoryGirl.create(:vm_or_template, :ems_cluster => src_cluster) } + let(:src_vm_3) { FactoryGirl.create(:vm_or_template, :ems_cluster => src_cluster) } + let(:dst_ems_1) { FactoryGirl.create(:ext_management_system) } + let(:dst_ems_2) { FactoryGirl.create(:ext_management_system) } + let(:dst_cluster) { FactoryGirl.create(:ems_cluster, :ext_management_system => dst_ems_1) } + let(:dst_host_1) { FactoryGirl.create(:host, :ext_management_system => dst_ems_1) } + let(:dst_host_2) { FactoryGirl.create(:host, :ext_management_system => dst_ems_1) } + let(:dst_host_3) { FactoryGirl.create(:host, :ext_management_system => dst_ems_2) } + let(:conversion_host_1) { FactoryGirl.create(:conversion_host, :resource => dst_host_1) } + let(:conversion_host_2) { FactoryGirl.create(:conversion_host, :resource => dst_host_2) } + let(:conversion_host_3) { FactoryGirl.create(:conversion_host, :resource => dst_host_3) } let(:svc_model_user) { MiqAeMethodService::MiqAeServiceUser.find(user.id) } let(:svc_model_automation_task) { MiqAeMethodService::MiqAeServiceAutomationTask.find(automation_task.id) } let(:svc_model_automation_request_1) { MiqAeMethodService::MiqAeServiceAutomationRequest.find(automation_request_1.id) } let(:svc_model_automation_request_2) { MiqAeMethodService::MiqAeServiceAutomationRequest.find(automation_request_2.id) } let(:svc_model_automation_request_3) { MiqAeMethodService::MiqAeServiceAutomationRequest.find(automation_request_3.id) } + let(:svc_model_src_cluster) { MiqAeMethodService::MiqAeServiceEmsCluster.find(src_cluster.id) } + let(:svc_model_src_vm_1) { MiqAeMethodService::MiqAeServiceEmsCluster.find(src_vm_1.id) } + let(:svc_model_src_vm_2) { MiqAeMethodService::MiqAeServiceEmsCluster.find(src_vm_2.id) } + let(:svc_model_src_vm_3) { MiqAeMethodService::MiqAeServiceEmsCluster.find(src_vm_3.id) } + let(:svc_model_dst_ems_1) { MiqAeMethodService::MiqAeServiceExtManagementSystem.find(dst_ems_1.id) } + let(:svc_model_dst_ems_2) { MiqAeMethodService::MiqAeServiceExtManagementSystem.find(dst_ems_2.id) } + let(:svc_model_dst_cluster) { MiqAeMethodService::MiqAeServiceEmsCluster.find(dst_cluster.id) } let(:svc_model_transformation_task_1) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(transformation_task_1.id) } let(:svc_model_transformation_task_2) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(transformation_task_2.id) } - let(:svc_model_host) { MiqAeMethodService::MiqAeServiceHost.find(host.id) } + let(:svc_model_transformation_task_3) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask.find(transformation_task_3.id) } + let(:svc_model_conversion_host_1) { MiqAeMethodService::MiqAeServiceConversionHost.find(conversion_host_1.id) } + let(:svc_model_conversion_host_2) { MiqAeMethodService::MiqAeServiceConversionHost.find(conversion_host_2.id) } + let(:svc_model_conversion_host_3) { MiqAeMethodService::MiqAeServiceConversionHost.find(conversion_host_3.id) } + + let(:mapping) do + FactoryGirl.create( + :transformation_mapping, + :transformation_mapping_items => [ + FactoryGirl.create(:transformation_mapping_item, :source => src_cluster, :destination => dst_cluster), + ] + ) + end + + let(:catalog_item_options) do + { + :name => 'Transformation Plan', + :description => 'a description', + :config_info => { + :transformation_mapping_id => mapping.id, + :actions => [ + {:vm_id => src_vm_1.id.to_s, :pre_service => false, :post_service => false}, + {:vm_id => src_vm_2.id.to_s, :pre_service => false, :post_service => false}, + {:vm_id => src_vm_3.id.to_s, :pre_service => false, :post_service => false} + ], + } + } + end + + let(:plan) { ServiceTemplateTransformationPlan.create_catalog_item(catalog_item_options) } + let(:request) { FactoryGirl.create(:service_template_transformation_plan_request, :source => plan) } + let(:transformation_task_1) { FactoryGirl.create(:service_template_transformation_plan_task, :miq_request => request, :request_type => 'transformation_plan', :source => src_vm_1) } + let(:transformation_task_2) { FactoryGirl.create(:service_template_transformation_plan_task, :miq_request => request, :request_type => 'transformation_plan', :source => src_vm_2) } + let(:transformation_task_3) { FactoryGirl.create(:service_template_transformation_plan_task, :miq_request => request, :request_type => 'transformation_plan', :source => src_vm_3) } let(:root) do Spec::Support::MiqAeMockObject.new( @@ -35,6 +84,11 @@ end end + let(:svc_vmdb_handle_user) { MiqAeMethodService::MiqAeServiceUser } + let(:svc_vmdb_handle_request) { MiqAeMethodService::MiqAeServiceAutomationRequest } + let(:svc_vmdb_handle_conversion_host) { MiqAeMethodService::MiqAeServiceConversionHost } + let(:svc_vmdb_handle_transformation_task) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } + before(:each) do ManageIQ::Automate::Transformation::TransformationThrottler::Utils.instance_variable_set(:@task, nil) ManageIQ::Automate::Transformation::TransformationThrottler::Utils.instance_variable_set(:@current_throttler, nil) @@ -57,6 +111,17 @@ svc_model_automation_request_3.set_option(:namespace, 'Transformation/StateMachines') svc_model_automation_request_3.set_option(:class_name, 'TransformationThrottler') svc_model_automation_request_3.set_option(:instance_name, 'Invalid') + + allow(ae_service).to receive(:vmdb).with(:user).and_return(svc_vmdb_handle_user) + allow(ae_service).to receive(:vmdb).with(:miq_request).and_return(svc_vmdb_handle_request) + allow(ae_service).to receive(:vmdb).with(:conversion_host).and_return(svc_vmdb_handle_conversion_host) + allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle_transformation_task) + + allow(svc_vmdb_handle_conversion_host).to receive(:all).and_return([svc_model_conversion_host_1, svc_model_conversion_host_2, svc_model_conversion_host_3]) + allow(svc_model_transformation_task_1).to receive(:transformation_destination).with(svc_model_src_cluster).and_return(svc_model_dst_cluster) + allow(svc_model_conversion_host_1).to receive(:ext_management_system).and_return(svc_model_dst_ems_1) + allow(svc_model_conversion_host_2).to receive(:ext_management_system).and_return(svc_model_dst_ems_1) + allow(svc_model_conversion_host_3).to receive(:ext_management_system).and_return(svc_model_dst_ems_2) end context "#task" do @@ -87,11 +152,8 @@ end context "#active_throttlers" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceAutomationRequest } - it "filter out invalid request" do - allow(ae_service).to receive(:vmdb).with(:miq_request).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:request_state => 'active', :type => 'AutomationRequest').and_return([svc_model_automation_request_1, svc_model_automation_request_3]) + allow(svc_vmdb_handle_request).to receive(:where).with(:request_state => 'active', :type => 'AutomationRequest').and_return([svc_model_automation_request_1, svc_model_automation_request_3]) expect(described_class.active_throttlers(ae_service).length).to eq(1) expect(described_class.active_throttlers(ae_service).first.id).to eq(svc_model_automation_request_1.id) end @@ -116,12 +178,9 @@ end context "#eldest_active_throttler?" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceAutomationRequest } - before do ae_service.root['automation_task'] = svc_model_automation_task - allow(ae_service).to receive(:vmdb).with(:miq_request).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:request_state => 'active', :type => 'AutomationRequest').and_return([svc_model_automation_request_1, svc_model_automation_request_2]) + allow(svc_vmdb_handle_request).to receive(:where).with(:request_state => 'active', :type => 'AutomationRequest').and_return([svc_model_automation_request_1, svc_model_automation_request_2]) end it "is not eldest active throttler" do @@ -177,8 +236,6 @@ end context "#retry_or_die" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } - before do ae_service.root['automation_task'] = svc_model_automation_task allow(svc_model_automation_task).to receive(:miq_request).and_return(svc_model_automation_request_1) @@ -191,16 +248,14 @@ end it "without active transformation task" do - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([]) + allow(svc_vmdb_handle_transformation_task).to receive(:where).with(:state => 'active').and_return([]) described_class.retry_or_die(ae_service) expect(ae_service.root['ae_result']).to be_nil end it "with active transformation task" do ae_service.root['ae_state_max_retries'] = 60 - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([svc_model_transformation_task_1]) + allow(svc_vmdb_handle_transformation_task).to receive(:where).with(:state => 'active').and_return([svc_model_transformation_task_1]) described_class.retry_or_die(ae_service) expect(ae_service.root['ae_result']).to eq('retry') expect(ae_service.root['ae_retry_interval']).to eq(60.seconds) @@ -219,28 +274,26 @@ end context "#schedule_tasks" do - it "check send correct method" do + it "calls the correct method" do expect(described_class).to receive(:schedule_tasks_fifo).with(ae_service) described_class.schedule_tasks(ae_service) end end context "#schedule_tasks_fifo" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } + before do + allow(svc_vmdb_handle_transformation_task).to receive(:where).with(:state => 'active').and_return([svc_model_transformation_task_1]) + end + + it "doesn't assign host when none is eligible" do + described_class.schedule_tasks_fifo(ae_service) + expect(svc_model_transformation_task_1.conversion_host).to be_nil + end - it "only one slot available" do - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([svc_model_transformation_task_1, svc_model_transformation_task_2]) - allow(ManageIQ::Automate::Transformation::TransformationHosts::Common::Utils).to receive(:get_transformation_host).and_return(['OVirtHost', svc_model_host, 'vddk'], [nil, nil, nil]) + it "assigns the only one slot available" do + allow(svc_model_conversion_host_1).to receive(:eligible?).and_return(true) described_class.schedule_tasks_fifo(ae_service) - expect(svc_model_transformation_task_1.get_option(:transformation_host_id)).to eq(svc_model_host.id) - expect(svc_model_transformation_task_1.get_option(:transformation_host_name)).to eq(svc_model_host.name) - expect(svc_model_transformation_task_1.get_option(:transformation_host_type)).to eq('OVirtHost') - expect(svc_model_transformation_task_1.get_option(:transformation_method)).to eq('vddk') - expect(svc_model_transformation_task_2.get_option(:transformation_host_id)).to be_nil - expect(svc_model_transformation_task_2.get_option(:transformation_host_name)).to be_nil - expect(svc_model_transformation_task_2.get_option(:transformation_host_type)).to be_nil - expect(svc_model_transformation_task_2.get_option(:transformation_method)).to be_nil + expect(svc_model_transformation_task_1.conversion_host.id).to eq(svc_model_conversion_host_1.id) end end @@ -263,30 +316,98 @@ end context "#active_transformation_tasks" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } - it "without active transformation task" do - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([]) + allow(svc_vmdb_handle_transformation_task).to receive(:where).with(:state => 'active').and_return([]) expect(described_class.active_transformation_tasks(ae_service)).to eq([]) end it "with active transformation task" do - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([svc_model_transformation_task_1]) + allow(svc_vmdb_handle_transformation_task).to receive(:where).with(:state => 'active').and_return([svc_model_transformation_task_1]) expect(described_class.active_transformation_tasks(ae_service).first.id).to eq(svc_model_transformation_task_1.id) end end context "#unassigned_transformation_tasks" do - let(:svc_vmdb_handle) { MiqAeMethodService::MiqAeServiceServiceTemplateTransformationPlanTask } - it "filter out assigned transformation task" do - allow(ae_service).to receive(:vmdb).with(:service_template_transformation_plan_task).and_return(svc_vmdb_handle) - allow(svc_vmdb_handle).to receive(:where).with(:state => 'active').and_return([svc_model_transformation_task_1, svc_model_transformation_task_2]) - allow(svc_model_transformation_task_1).to receive(:get_option).with(:transformation_host_id).and_return(svc_model_host.id) + allow(svc_vmdb_handle_transformation_task).to receive(:where).with(:state => 'active').and_return([svc_model_transformation_task_1, svc_model_transformation_task_2]) + allow(svc_model_transformation_task_1).to receive(:conversion_host).and_return(svc_model_conversion_host_1) expect(described_class.unassigned_transformation_tasks(ae_service).length).to eq(1) expect(described_class.unassigned_transformation_tasks(ae_service).first.id).to eq(svc_model_transformation_task_2.id) end end + + describe "#transformation_hosts" do + before do + allow(svc_model_transformation_task_1).to receive(:conversion_host).and_return(svc_model_conversion_host_1) + allow(svc_model_transformation_task_2).to receive(:conversion_host).and_return(svc_model_conversion_host_2) + allow(svc_model_transformation_task_3).to receive(:conversion_host).and_return(nil) + end + + it "returns the conversion hosts for the EMS" do + expect(described_class.transformation_hosts(svc_model_dst_ems_1, ae_service)).to eq([svc_model_conversion_host_1, svc_model_conversion_host_2]) + end + end + + describe "#eligible_transformation_hosts" do + it "returns the eligble hosts" do + allow(svc_model_conversion_host_1).to receive(:eligible?).and_return(true) + allow(svc_model_conversion_host_2).to receive(:eligible?).and_return(true) + allow(svc_model_conversion_host_1).to receive(:active_tasks).and_return([svc_model_transformation_task_1, svc_model_transformation_task_2]) + allow(svc_model_conversion_host_2).to receive(:active_tasks).and_return([svc_model_transformation_task_3]) + expect(described_class.eligible_transformation_hosts(svc_model_dst_ems_1, ae_service)).to eq([svc_model_conversion_host_2, svc_model_conversion_host_1]) + end + end + + describe "#get_runners_count_by_ems" do + it "returns the number of runners" do + allow(svc_model_conversion_host_1).to receive(:active_tasks).and_return([svc_model_transformation_task_1, svc_model_transformation_task_2]) + allow(svc_model_conversion_host_2).to receive(:active_tasks).and_return([svc_model_transformation_task_3]) + expect(described_class.get_runners_count_by_ems(svc_model_dst_ems_1, ae_service)).to eq(3) + end + end + + describe "#ems_max_runners" do + it "with custom attribute" do + allow(svc_model_dst_ems_1).to receive(:custom_get).with('Max Transformation Runners').and_return('2') + expect(described_class.ems_max_runners(svc_model_dst_ems_1, {})).to eq(2) + end + + it "with factory_config key" do + expect(described_class.ems_max_runners(svc_model_dst_ems_1, {'ems_max_runners' => 2}, ae_service)).to eq(2) + end + + it "with overridden max_runners" do + expect(described_class.ems_max_runners(svc_model_dst_ems_1, {}, 2)).to eq(2) + end + + it "with default" do + expect(described_class.ems_max_runners(svc_model_dst_ems_1, {})).to eq(10) + end + end + + describe "#get_transformation_host" do + before do + allow(svc_model_conversion_host_1).to receive(:active_tasks).and_return([svc_model_transformation_task_1, svc_model_transformation_task_2]) + allow(svc_model_conversion_host_2).to receive(:active_tasks).and_return([svc_model_transformation_task_3]) + allow(svc_model_transformation_task_1).to receive(:conversion_host).and_return(svc_model_conversion_host_1) + allow(svc_model_transformation_task_2).to receive(:conversion_host).and_return(svc_model_conversion_host_2) + allow(svc_model_transformation_task_3).to receive(:conversion_host).and_return(nil) + end + + it "when ems max runners is reached" do + expect(described_class.get_transformation_host(svc_model_transformation_task_3, { 'ems_max_runners' => 2 }, ae_service)).to be_nil + end + + it "without an eligible host" do + allow(svc_model_conversion_host_1).to receive(:eligible?).and_return(false) + allow(svc_model_conversion_host_2).to receive(:eligible?).and_return(false) + expect(described_class.get_transformation_host(svc_model_transformation_task_3, {}, ae_service)).to be_nil + end + + it "with an eligible host" do + allow(svc_model_conversion_host_1).to receive(:eligible?).and_return(true) + allow(svc_model_conversion_host_2).to receive(:eligible?).and_return(true) + expect(described_class.get_transformation_host(svc_model_transformation_task_3, {}, ae_service)).to eq(svc_model_conversion_host_2) + end + end end