Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods to conversion_host to build virt-v2v wrapper options #18033

Merged
Merged
100 changes: 100 additions & 0 deletions app/models/conversion_host.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,104 @@ class ConversionHost < ApplicationRecord
acts_as_miq_taggable

belongs_to :resource, :polymorphic => true
has_many :service_template_transformation_plan_tasks, :dependent => :nullify

def active_tasks
service_template_transformation_plan_tasks { active }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to define the scope in miq_request_task:

scope :active, -> { where(:state => "active") }

Then here it will look like:

has_many :active_tasks, -> { active }, :class_name => ServiceTemplateTransformationPlanTask

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried it but it fails during tests.

end

def eligible?
return true if concurrent_transformation_limit.nil?
active_tasks.size < concurrent_transformation_limit.to_i
end

def source_transport_method
return 'vddk' if vddk_transport_supported
return 'ssh' if ssh_transport_supported
end

def conversion_options(task)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do change the task to a true relationship, then this method could probably be replaced with a number of delegate methods.

See comment to create relationship.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely. What release are we targeting there ? Hammer or I-release ? Given that we're past code freeze for Hammer, I'd say, we're aiming I-release, unless we've got a derogation 😜

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the relationship is made so task belongs to conversion_host. Then, I'm not sure how I can delegate from conversion_host to task, as it has many tasks. That would require that the task is passed to the conversion. Is there a way to do it ? I'm a delegation newbie.

source_vm = task.source
source_ems = source_vm.ext_management_system
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_storage = task.transformation_destination(source_storage)
destination_ems = destination_cluster.ext_management_system

source_provider_options = send(
"conversion_options_source_provider_#{source_ems.emstype}_#{source_transport_method}",
source_vm,
source_storage
)
destination_provider_options = send(
"conversion_options_destination_provider_#{destination_ems.emstype}",
task,
destination_ems,
destination_cluster,
destination_storage
)
options = {
:source_disks => task.source_disks.map { |disk| disk[:path] },
:network_mappings => task.network_mappings
}
options.merge(source_provider_options).merge(destination_provider_options)
end

def conversion_options_source_provider_vmwarews_vddk(vm, _storage)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fdupont-redhat should these below methods be on the conversion_task model? What from the conversion_host do they use?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, they should be in the task... And that also answers #18033 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 awesome, if there is anything that the task needs from the conversion_host we can delegate those to the conversion_host as @blomquisg said above

{
:vm_name => vm.name,
:transport_method => 'vddk',
:vmware_fingerprint => vm.host.fingerprint,
:vmware_uri => 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,
:vmware_password => vm.host.authentication_password
}
end

def conversion_options_source_provider_vmwarews_ssh(vm, storage)
{
:vm_name => URI::Generic.build(:scheme => 'ssh', :userinfo => 'root', :host => vm.host.ipaddress, :path => "/vmfs/volumes").to_s + "/#{storage.name}/#{vm.location}",
:transport_method => 'ssh'
}
end

def conversion_options_destination_provider_rhevm(_task, ems, cluster, storage)
{
:rhv_url => URI::Generic.build(:scheme => 'https', :host => ems.hostname, :path => '/ovirt-engine/api').to_s,
:rhv_cluster => cluster.name,
:rhv_storage => storage.name,
:rhv_password => ems.authentication_password,
:install_drivers => true,
:insecure_connection => true
}
end

def conversion_options_destination_provider_openstack(task, ems, cluster, storage)
{
:osp_environment => {
:os_no_cache => true,
:os_auth_url => URI::Generic.build(
:scheme => ems.security_protocol == 'non-ssl' ? 'http' : 'https',
:host => ems.hostname,
:port => ems.port,
:path => ems.api_version
),
:os_user_domain_name => ems.uid_ems,
:os_username => ems.authentication_userid,
:os_password => ems.authentication_password,
:os_project_name => cluster.name
},
:osp_destination_project_id => cluster.ems_ref,
:osp_volume_type_id => storage.ems_ref,
:osp_flavor_id => task.destination_flavor.ems_ref,
:osp_security_groups_ids => [task.destination_security_group.ems_ref]
}
end
end
71 changes: 63 additions & 8 deletions app/models/service_template_transformation_plan_task.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class ServiceTemplateTransformationPlanTask < ServiceTemplateProvisionTask
belongs_to :conversion_host

def self.base_model
ServiceTemplateTransformationPlanTask
end
Expand Down Expand Up @@ -46,21 +48,74 @@ def task_active
vm_resource.update_attributes(:status => ServiceResource::STATUS_ACTIVE)
end

def conversion_host
Host.find_by(:id => options[:transformation_host_id])
def source_ems
options[:source_ems_id] ||= source.ext_management_system.id
source.ext_management_system
end
agrare marked this conversation as resolved.
Show resolved Hide resolved

def destination_ems
options[:destination_ems_id] ||= transformation_destination(source.ems_cluster).ext_management_system.id
transformation_destination(source.ems_cluster).ext_management_system
end

def source_disks
options[:source_disks] ||= source.hardware.disks.select { |d| d.device_type == 'disk' }.collect do |disk|
source_storage = disk.storage
destination_storage = transformation_destination(disk.storage)
raise "[#{source.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.allocated_disk_storage.to_f * 100
}
end
end

def network_mappings
options[:network_mappings] ||= source.hardware.nics.select { |n| n.device_type == 'ethernet' }.collect do |nic|
source_network = nic.lan
destination_network = transformation_destination(source_network)
raise "[#{source.name}] NIC #{nic.device_name} [#{source_network.name}] has no mapping. Aborting." if destination_network.nil?
{
:source => source_network.name,
:destination => destination_network_ref(destination_network),
:mac_address => nic.address
}
end
end

def destination_network_ref(network)
send("destination_network_ref_#{destination_ems.emstype}", network)
end

def destination_network_ref_rhevm(network)
network.name
end

def destination_network_ref_openstack(network)
network.ems_ref
end

def destination_flavor
Flavor.find_by(:id => miq_request.source.options[:config_info][:osp_flavor])
end

def destination_security_group
SecurityGroup.find_by(:id => miq_request.source.options[:config_info][:osp_security_group])
end

def transformation_log
host = conversion_host
if host.nil?
msg = "Conversion host was not found: ID [#{options[:transformation_host_id]}]. Download of transformation log aborted."
msg = "Conversion host was not found. Download of transformation log aborted."
_log.error(msg)
raise MiqException::Error, msg
end

userid, password = host.auth_user_pwd(:remote)
userid, password = host.resource.auth_user_pwd(:remote)
if userid.blank? || password.blank?
msg = "Credential was not found for host #{host.name}. Download of transformation log aborted."
msg = "Credential was not found for host #{host.resource.name}. Download of transformation log aborted."
_log.error(msg)
raise MiqException::Error, msg
end
Expand All @@ -74,7 +129,7 @@ def transformation_log

begin
require 'net/scp'
Net::SCP.download!(host.ipaddress, userid, logfile, nil, :ssh => {:password => password})
Net::SCP.download!(host.resource.ipaddress, userid, logfile, nil, :ssh => {:password => password})
rescue Net::SCP::Error => scp_err
_log.error("Download of transformation log for #{description} with ID [#{id}] failed with error: #{scp_err.message}")
raise scp_err
Expand All @@ -87,7 +142,7 @@ def transformation_log_queue(userid = nil)
userid ||= User.current_userid || 'system'
host = conversion_host
if host.nil?
msg = "Conversion host was not found: ID [#{options[:transformation_host_id]}]. Cannot queue the download of transformation log."
msg = "Conversion host was not found. Cannot queue the download of transformation log."
return create_error_status_task(userid, msg).id
end

Expand All @@ -98,7 +153,7 @@ def transformation_log_queue(userid = nil)
:instance_id => id,
:priority => MiqQueue::HIGH_PRIORITY,
:args => [],
:zone => host.my_zone}
:zone => host.resource.my_zone}
MiqTask.generic_action_with_callback(options, queue_options)
end

Expand Down
Loading