Skip to content

Commit

Permalink
Merge pull request #301 from fdupont-redhat/v2v_gaprindashvili-3
Browse files Browse the repository at this point in the history
Add V2V for VMware to oVirt / RHV
(cherry picked from commit dc72f1f)
  • Loading branch information
gmcculloug authored and simaishi committed Jun 1, 2018
1 parent 1e6e732 commit 35ca01c
Show file tree
Hide file tree
Showing 50 changed files with 1,581 additions and 283 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ def on_entry(state_hash, _, _, state_weight, state_description)
end

def on_exit(state_hash, state_progress, state_name, _, _)
@handle.log(:info, "State Progress: #{state_progress.inspect}")
# If the state is retrying, we leave the status to 'active'.
if @handle.root['ae_result'] == 'retry'
# If the method provides progress info, it is merged, otherwise we set
Expand All @@ -68,12 +67,12 @@ def on_exit(state_hash, state_progress, state_name, _, _)
state_hash
end

def on_error(state_hash, state_progress, state_name, _, _)
def on_error(state_hash, state_progress, _, _, state_description)
# The state has failed, so we consider it as finished and 100%.
state_hash['status'] = 'failed'
state_hash['percent'] = 100.0
# We merge the potential message from method and set the update time.
state_hash['message'] = state_progress.nil? ? "#{state_name} has failed." : state_progress['message']
state_hash['message'] = state_progress.nil? ? "Failed to #{state_description}." : state_progress['message']
state_hash['updated_on'] = Time.now.utc
state_hash
end
Expand Down Expand Up @@ -106,7 +105,6 @@ def main

# We record the state hash in the task progress
progress['states']["#{state_ancestry}/#{state_name}"] = state_hash
@handle.log(:info, "Progress: #{progress}")
# If we enter the state, we update the task progress with current
# state and description.
if @handle.root['ae_status_state'] == 'on_entry'
Expand All @@ -121,7 +119,12 @@ def main
@handle.set_state_var('ae_state_progress', nil)
# We record the progress as a task option.
task.update_transformation_progress(progress)
@handle.log(:info, "Task: #{task.get_option(:progress)}")
# We set the task message.
if @handle.root['ae_state_step'] == 'on_error'
task.message = 'Failed'
else
task.message = @handle.inputs['task_message'] unless @handle.inputs['task_message'] == '_'
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,23 @@ object:
on_error:
max_retries:
max_time:
- field:
aetype:
name: task_message
display_name:
datatype:
priority: 3
owner:
default_value: _
substitute: false
message: create
visibility:
collect:
scope:
description:
condition:
on_entry:
on_exit:
on_error:
max_retries:
max_time:
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
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:
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module ManageIQ
module Automate
module Transformation
module Common
class AcquireTransformationHost
def initialize(handle = $evm)
@handle = handle
end

def main
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']
@handle.log(:info, "Task: #{task.inspect}")
source_vm = task.source
@handle.log(:info, "Source VM: #{source_vm.name}")
source_cluster = source_vm.ems_cluster
@handle.log(:info, "Source Cluster: #{source_cluster.name}")
@handle.log(:info, "Destination Cluster: #{task.transformation_destination(source_cluster).name}")
destination_ems = task.transformation_destination(source_cluster).ext_management_system
raise "Invalid destination EMS type: #{destination_ems.emstype}. Aborting." unless destination_ems.emstype == "rhevm"

transformation_host = ManageIQ::Automate::Transformation::TransformationHosts::Common::Utils.get_transformation_host(destination_ems, @handle.get_state_var(:transformation_method), factory_config)
if transformation_host.nil?
@handle.log(:info, "No transformation host available. Retrying.")
@handle.root['ae_result'] = 'retry'
@handle.root['ae_retry_server_affinity'] = true
@handle.root['ae_retry_interval'] = $evm.object['check_convert_interval'] || '1.minutes'
else
@handle.log(:info, "Transformation Host: #{transformation_host.name}.")
task.set_option(:transformation_host_id, transformation_host.id)
task.set_option(:transformation_host_name, transformation_host.name)
end
rescue => e
@handle.set_state_var(:ae_state_progress, 'message' => e.message)
raise
end
end
end
end
end
end

if $PROGRAM_NAME == __FILE__
ManageIQ::Automate::Transformation::Common::AcquireTransformationHost.new.main
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
object_type: method
version: 1.0
object:
attributes:
name: AcquireTransformationHost
display_name:
description:
scope: instance
language: ruby
location: inline
embedded_methods:
- "/Transformation/TransformationHosts/Common/Utils"
options: {}
inputs: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
module ManageIQ
module Automate
module Transformation
module Common
class AssessTransformation
SUPPORTED_SOURCE_EMS_TYPES = ['vmwarews'].freeze
SUPPORTED_DESTINATION_EMS_TYPES = ['rhevm'].freeze
REQUIRED_CUSTOM_ATTRIBUTES = {
'rhevm' => %i(rhv_export_domain_id rhv_cluster_id rhv_storage_domain_id)
}.freeze

def initialize(handle = $evm)
@handle = handle
end

def main
task = @handle.root['service_template_transformation_plan_task']
raise 'No task found. Exiting' if task.nil?
@handle.log(:info, "Task: #{task.inspect}") if @debug

source_vm ||= task.source
raise 'No VM found. Exiting' if source_vm.nil?

source_cluster = source_vm.ems_cluster
destination_cluster = task.transformation_destination(source_cluster)
raise "No destination cluster for '#{source_vm.name}'. Exiting." if destination_cluster.nil?

source_ems = source_vm.ext_management_system
destination_ems = destination_cluster.ext_management_system

virtv2v_networks = []
source_vm.hardware.nics.select { |n| n.device_type == 'ethernet' }.each 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?
virtv2v_networks << { :source => source_network.name, :destination => destination_network.name }
end
@handle.log(:info, "Network mappings: #{virtv2v_networks}")
task.set_option(:virtv2v_networks, virtv2v_networks)

virtv2v_disks = []
source_vm.hardware.disks.select { |d| d.device_type == 'disk' }.each 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?
virtv2v_disks << { :path => disk.filename, :size => disk.size, :percent => 0, :weight => disk.size.to_f / source_vm.allocated_disk_storage.to_f * 100 }
end
@handle.log(:info, "Source VM Disks #{virtv2v_disks}")
task.set_option(:virtv2v_disks, virtv2v_disks)

raise "Unsupported source EMS type: #{source_ems.emstype}." unless SUPPORTED_SOURCE_EMS_TYPES.include?(source_ems.emstype)
@handle.set_state_var(:source_ems_type, source_ems.emstype)

raise "Unsupported destination EMS type: #{destination_ems.emstype}." unless SUPPORTED_DESTINATION_EMS_TYPES.include?(destination_ems.emstype)
@handle.set_state_var(:destination_ems_type, destination_ems.emstype)

transformation_type = "#{source_ems.emstype}2#{destination_ems.emstype}"
@handle.set_state_var(:transformation_type, transformation_type)

transformation_method = "vddk"
@handle.set_state_var(:transformation_method, transformation_method)

transformation_host_type = "ovirt_host"
@handle.set_state_var(:transformation_host_type, transformation_host_type)

factory_config = {
'vmtransformation_check_interval' => @handle.object['vmtransformation_check_interval'] || '15.seconds',
'vmpoweroff_check_interval' => @handle.object['vmpoweroff_check_interval'] || '30.seconds'
}
@handle.set_state_var(:factory_config, factory_config)

# Force VM shutdown and snapshots collapse by default
task.set_option(:collapse_snapshots, true)
task.set_option(:power_off, true)
rescue => e
@handle.set_state_var(:ae_state_progress, 'message' => e.message)
raise
end
end
end
end
end
end

if $PROGRAM_NAME == __FILE__
ManageIQ::Automate::Transformation::Common::AssessTransformation.new.main
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
object_type: method
version: 1.0
object:
attributes:
name: AssessTransformation
display_name:
description:
scope: instance
language: ruby
location: inline
options: {}
inputs: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
object_type: instance
version: 1.0
object:
attributes:
display_name:
name: ".missing"
inherits:
description:
fields:
- execute:
value: "${#_missing_instance}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
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:
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module ManageIQ
module Automate
module Transformation
module Infrastructure
module VM
module Common
class PowerOff
def initialize(handle = $evm)
@handle = 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'
else
raise "VM '#{source_vm.name} is powered on, but we are not allowed to shut it down. Aborting."
end
rescue => e
@handle.set_state_var(:ae_state_progress, 'message' => e.message)
raise
end
end
end
end
end
end
end
end

if $PROGRAM_NAME == __FILE__
ManageIQ::Automate::Transformation::Infrastructure::VM::Common::PowerOff.new.main
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
object_type: method
version: 1.0
object:
attributes:
name: PowerOff
display_name:
description:
scope: instance
language: ruby
location: inline
options: {}
inputs: []
Loading

0 comments on commit 35ca01c

Please sign in to comment.