diff --git a/app/models/service_template_transformation_plan_task.rb b/app/models/service_template_transformation_plan_task.rb index a649375f5b67..b10ff366791a 100644 --- a/app/models/service_template_transformation_plan_task.rb +++ b/app/models/service_template_transformation_plan_task.rb @@ -34,9 +34,74 @@ def task_active vm_resource.update_attributes(:status => ServiceResource::STATUS_ACTIVE) end + def conversion_host + Host.find_by(:id => options["transformation_host_id"]) + 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." + _log.error(msg) + raise MiqException::Error, msg + end + + userid, password = host.auth_user_pwd(:remote) + if userid.blank? || password.blank? + msg = "Host credential is required: userid [#{userid}], password [#{password}]. Download of transformation log aborted." + _log.error(msg) + raise MiqException::Error, msg + end + + logfile = options.fetch_path("virtv2v_wrapper", "v2v_log") + if logfile.blank? + msg = "The location of transformation log was not set. Download of transformation log aborted." + _log.error(msg) + raise MiqException::Error, msg + end + + begin + require 'net/scp' + Net::SCP::download!(host.ipaddress, userid, logfile, nil, :ssh => {:password => password}) + rescue => scp_err + _log.error("Download of transformation log for #{description} with ID [#{id}] failed with error: #{scp_err.message}") + raise scp_err + end + end + + # Intend to be called by UI to display transformation log. The log is stored in MiqTask#task_results + # Since the task_results may contain a large block of data, it is desired to remove the task upon receiving the data + def transformation_log_queue(userid) + host = conversion_host + if host.nil? + msg = "Conversion host was not found: ID [#{options["transformation_host_id"]}]. Cannot queue the download of transformation log." + return create_error_status_task(userid, msg).id + end + + _log.info("Queuing the download of transformation log for #{description} with ID [#{id}]") + options = {:userid => userid || 'system', :action => 'transformation_log'} + queue_options = {:class_name => self.class, + :method_name => 'transformation_log', + :instance_id => id, + :priority => MiqQueue::HIGH_PRIORITY, + :args => [], + :zone => host.my_zone} + MiqTask.generic_action_with_callback(options, queue_options) + end + private def vm_resource miq_request.vm_resources.find_by(:resource => source) end + + def create_error_status_task(userid, msg) + MiqTask.create( + :name => "Download transformation log with ID: #{id}", + :userid => userid || 'system', + :state => MiqTask::STATE_FINISHED, + :status => MiqTask::STATUS_ERROR, + :message => msg + ) + end end diff --git a/spec/models/service_template_transformation_plan_task_spec.rb b/spec/models/service_template_transformation_plan_task_spec.rb index edfb208c85a5..873121671eb3 100644 --- a/spec/models/service_template_transformation_plan_task_spec.rb +++ b/spec/models/service_template_transformation_plan_task_spec.rb @@ -82,5 +82,94 @@ expect(described_class.get_description(request)).to eq(plan.name) end end + + describe '#transformation_log_queue' do + let(:host_id) { 22 } + + before do + task.options["transformation_host_id"] = host_id + task.save! + end + + context 'when conversion host exists' do + before do + FactoryGirl.create(:host, :id => host_id, :ext_management_system => FactoryGirl.create(:ext_management_system, :zone => FactoryGirl.create(:zone))) + + allow(described_class).to receive(:find).and_return(task) + + allow(MiqTask).to receive(:wait_for_taskid) do + request = MiqQueue.find_by(:class_name => described_class.name) + request.update_attributes(:state => MiqQueue::STATE_DEQUEUE) + request.delivered(*request.deliver) + end + end + + it 'gets the transformation log from conversion host' do + expect(task).to receive(:transformation_log).and_return('transformation migration log content') + taskid = task.transformation_log_queue('user') + MiqTask.wait_for_taskid(taskid) + expect(MiqTask.find(taskid)).to have_attributes( + :task_results => 'transformation migration log content', + :status => 'Ok' + ) + end + + it 'returns the error message' do + msg = 'Failed to get transformation migration log for some reason' + expect(task).to receive(:transformation_log).and_raise(msg) + taskid = task.transformation_log_queue('user') + MiqTask.wait_for_taskid(taskid) + expect(MiqTask.find(taskid).message).to include(msg) + expect(MiqTask.find(taskid).status).to eq('Error') + end + end + + context 'when conversion host does not exist' do + it 'returns an error message' do + taskid = task.transformation_log_queue('user') + expect(MiqTask.find(taskid)).to have_attributes( + :message => "Conversion host was not found: ID [#{host_id}]. Cannot queue the download of transformation log.", + :status => 'Error' + ) + end + end + end + + describe '#transformation_log' do + let(:host) { FactoryGirl.create(:host, :id => 9) } + + before do + EvmSpecHelper.create_guid_miq_server_zone + task.options["transformation_host_id"] = host.id + task.options.store_path("virtv2v_wrapper", "v2v_log", "/path/to/log.file") + task.save! + + host.update_authentication(:default => {:userid => 'root', :password => 'v2v'}) + allow(described_class).to receive(:find).and_return(task) + + require 'net/scp' + end + + it 'requires host credential' do + host.update_authentication(:default => {:userid => 'root', :password => ''}) + expect { task.transformation_log }.to raise_error(MiqException::Error) + end + + it 'requires transformation log location in options' do + task.options.store_path("virtv2v_wrapper", "v2v_log", "") + expect { task.transformation_log }.to raise_error(MiqException::Error) + end + + it 'catches errors from net/scp' do + expect(Net::SCP).to receive(:download!).and_raise('something is wrong') + expect { task.transformation_log }.to raise_error(RuntimeError) + end + + it 'gets the transformation log content' do + msg = 'my transformation migration log' + expect(Net::SCP).to receive(:download!).and_return(msg) + expect(task.transformation_log).to eq(msg) + end + end end end