diff --git a/app/models/conversion_host.rb b/app/models/conversion_host.rb index 0d2a53a74d6..7426e466f72 100644 --- a/app/models/conversion_host.rb +++ b/app/models/conversion_host.rb @@ -169,34 +169,43 @@ def get_conversion_log(path) raise "Could not get conversion log '#{path}' from '#{resource.name}' with [#{e.class}: #{e}" end - def check_conversion_host_role - playbook = "/usr/share/ovirt-ansible-v2v-conversion-host/playbooks/conversion_host_check.yml" - ansible_playbook(playbook) + def check_conversion_host_role(miq_task_id = nil) + playbook = "/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_check.yml" + extra_vars = { + :v2v_host_type => resource.ext_management_system.emstype, + :v2v_transport_method => source_transport_method + } + ansible_playbook(playbook, extra_vars, miq_task_id) tag_resource_as('enabled') rescue tag_resource_as('disabled') end - def enable_conversion_host_role(vmware_vddk_package_url = nil, vmware_ssh_private_key = nil) - raise "vddk_package_url is mandatory if transformation method is vddk" if vddk_transport_supported && vmware_vddk_package_url.nil? - raise "ssh_private_key is mandatory if transformation_method is ssh" if ssh_transport_supported && vmware_ssh_private_key.nil? - playbook = "/usr/share/ovirt-ansible-v2v-conversion-host/playbooks/conversion_host_enable.yml" + def enable_conversion_host_role(vmware_vddk_package_url = nil, vmware_ssh_private_key = nil, miq_task_id = nil) + raise "vmware_vddk_package_url is mandatory if transformation method is vddk" if vddk_transport_supported && vmware_vddk_package_url.nil? + raise "vmware_ssh_private_key is mandatory if transformation_method is ssh" if ssh_transport_supported && vmware_ssh_private_key.nil? + playbook = "/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_enable.yml" extra_vars = { - :v2v_transport_method => vddk_transport_supported ? 'vddk' : 'ssh', + :v2v_host_type => resource.ext_management_system.emstype, + :v2v_transport_method => source_transport_method, :v2v_vddk_package_url => vmware_vddk_package_url, :v2v_ssh_private_key => vmware_ssh_private_key, :v2v_ca_bundle => resource.ext_management_system.connection_configurations['default'].certificate_authority }.compact - ansible_playbook(playbook, extra_vars) + ansible_playbook(playbook, extra_vars, miq_task_id) ensure - check_conversion_host_role + check_conversion_host_role(miq_task_id) end - def disable_conversion_host_role - playbook = "/usr/share/ovirt-ansible-v2v-conversion-host/playbooks/conversion_host_disable.yml" - ansible_playbook(playbook) + def disable_conversion_host_role(miq_task_id = nil) + playbook = "/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_disable.yml" + extra_vars = { + :v2v_host_type => resource.ext_management_system.emstype, + :v2v_transport_method => source_transport_method + } + ansible_playbook(playbook, extra_vars, miq_task_id) ensure - check_conversion_host_role + check_conversion_host_role(miq_task_id) end private @@ -274,16 +283,38 @@ def miq_ssh_util_args_manageiq_providers_openstack_cloudmanager_vm # +extra_vars+ option should be a hash of key/value pairs which, if present, # will be passed to the '-e' flag. # - def ansible_playbook(playbook, extra_vars = {}) - command = "ansible-playbook #{playbook} -i #{ipaddress}" + def ansible_playbook(playbook, extra_vars = {}, miq_task_id = nil, auth_type = nil) + task = MiqTask.find(miq_task_id) if miq_task_id.present? - extra_vars[:v2v_host_type] = resource.ext_management_system.emstype - extra_vars.each { |k, v| command += " -e '#{k}=#{v}'" } + host = hostname || ipaddress - connect_ssh { |ssu| ssu.shell_exec(command) } - rescue => e - _log.error("Ansible playbook '#{playbook}' failed for '#{resource.name}' with [#{e.class}: #{e}]") - raise e + command = "ansible-playbook #{playbook} --inventory #{host}, --become --extra-vars=\"ansible_ssh_common_args='-o StrictHostKeyChecking=no'\"" + + auth = authentication_type(auth_type) || authentications.first + command << " --user #{auth.userid}" + + case auth + when AuthUseridPassword + extra_vars[:ansible_ssh_pass] = auth.password + when AuthPrivateKey + ssh_private_key_file = Tempfile.new('ansible_key') + begin + ssh_private_key_file.write(auth.auth_key) + ensure + ssh_private_key_file.close + end + command << " --private-key #{ssh_private_key_file.path}" + else + raise MiqException::MiqInvalidCredentialsError, _("Unknown auth type: #{auth.authtype}") + end + + extra_vars.each { |k, v| command << " --extra-vars '#{k}=#{v}'" } + + result = AwesomeSpawn.run(command) + raise unless result.exit_status.zero? + ensure + task&.update_context(task.context_data.merge!(File.basename(playbook, '.yml') => result.output)) unless result.nil? + ssh_private_key_file&.unlink end # Wrapper method for the various tag_resource_as_xxx methods. diff --git a/app/models/conversion_host/configurations.rb b/app/models/conversion_host/configurations.rb index 348c380f36c..a8b2b6246b4 100644 --- a/app/models/conversion_host/configurations.rb +++ b/app/models/conversion_host/configurations.rb @@ -55,7 +55,7 @@ def enable_queue(params, auth_user = nil) def enable(params, auth_user = nil) params = params.symbolize_keys - _log.info("Enabling a conversion_host with parameters: #{params}") + _log.debug("Enabling a conversion_host with parameters: #{params}") params.delete(:task_id) # In case this is being called through *_queue which will stick in a :task_id miq_task_id = params.delete(:miq_task_id) # The miq_queue.activate_miq_task will stick in a :miq_task_id @@ -78,7 +78,7 @@ def enable(params, auth_user = nil) ) end - conversion_host.enable_conversion_host_role(vmware_vddk_package_url, vmware_ssh_private_key) + conversion_host.enable_conversion_host_role(vmware_vddk_package_url, vmware_ssh_private_key, miq_task_id) conversion_host.save! if miq_task_id @@ -102,7 +102,7 @@ def disable_queue(auth_user = nil) def disable resource_info = "type=#{resource.class.name} id=#{resource.id}" - _log.info("Disabling a conversion_host #{resource_info}") + _log.debug("Disabling a conversion_host #{resource_info}") disable_conversion_host_role destroy! diff --git a/spec/models/conversion_host_spec.rb b/spec/models/conversion_host_spec.rb index 157a6b35de7..8078ecbbe54 100644 --- a/spec/models/conversion_host_spec.rb +++ b/spec/models/conversion_host_spec.rb @@ -163,12 +163,58 @@ it_behaves_like "#check_ssh_connection" end end + + context "#ansible_playbook" do + it "check_conversion_host_role calls ansible_playbook with extra_vars" do + check_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_check.yml' + check_extra_vars = { + :v2v_host_type => 'rhevm', + :v2v_transport_method => 'vddk' + } + expect(conversion_host).to receive(:ansible_playbook).with(check_playbook, check_extra_vars, 1) + conversion_host.check_conversion_host_role(1) + end + + it "disable_conversion_host_role calls ansible_playbook with extra_vars" do + disable_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_disable.yml' + check_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_check.yml' + disable_extra_vars = { + :v2v_host_type => 'rhevm', + :v2v_transport_method => 'vddk' + } + check_extra_vars = disable_extra_vars + expect(conversion_host).to receive(:ansible_playbook).once.ordered.with(disable_playbook, disable_extra_vars, 1) + expect(conversion_host).to receive(:ansible_playbook).once.ordered.with(check_playbook, check_extra_vars, 1) + conversion_host.disable_conversion_host_role(1) + end + + it "enable_conversion_host_role raises if vmware_vddk_package_url is nil" do + expect { conversion_host.enable_conversion_host_role }.to raise_error("vmware_vddk_package_url is mandatory if transformation method is vddk") + end + + it "enable_conversion_host_role calls ansible_playbook with extra_vars" do + enable_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_enable.yml' + check_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_check.yml' + enable_extra_vars = { + :v2v_host_type => 'rhevm', + :v2v_transport_method => 'vddk', + :v2v_vddk_package_url => 'http://file.example.com/vddk-stable.tar.gz' + } + check_extra_vars = { + :v2v_host_type => 'rhevm', + :v2v_transport_method => 'vddk' + } + expect(conversion_host).to receive(:ansible_playbook).once.ordered.with(enable_playbook, enable_extra_vars, nil) + expect(conversion_host).to receive(:ansible_playbook).once.ordered.with(check_playbook, check_extra_vars, nil) + conversion_host.enable_conversion_host_role('http://file.example.com/vddk-stable.tar.gz', nil) + end + end end context "resource provider is openstack" do let(:ems) { FactoryBot.create(:ems_openstack, :zone => FactoryBot.create(:zone)) } let(:vm) { FactoryBot.create(:vm_openstack, :ext_management_system => ems) } - let(:conversion_host) { FactoryBot.create(:conversion_host, :resource => vm, :vddk_transport_supported => true) } + let(:conversion_host) { FactoryBot.create(:conversion_host, :resource => vm, :ssh_transport_supported => true) } context "ems authentications is empty" do it { expect(conversion_host.check_ssh_connection).to be(false) } @@ -186,6 +232,52 @@ it_behaves_like "#check_ssh_connection" end + + context "#ansible_playbook" do + it "check_conversion_host_role calls ansible_playbook with extra_vars" do + check_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_check.yml' + check_extra_vars = { + :v2v_host_type => 'openstack', + :v2v_transport_method => 'ssh' + } + expect(conversion_host).to receive(:ansible_playbook).with(check_playbook, check_extra_vars, 1) + conversion_host.check_conversion_host_role(1) + end + + it "disable_conversion_host_role calls ansible_playbook with extra_vars" do + disable_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_disable.yml' + check_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_check.yml' + disable_extra_vars = { + :v2v_host_type => 'openstack', + :v2v_transport_method => 'ssh' + } + check_extra_vars = disable_extra_vars + expect(conversion_host).to receive(:ansible_playbook).once.ordered.with(disable_playbook, disable_extra_vars, 1) + expect(conversion_host).to receive(:ansible_playbook).once.ordered.with(check_playbook, check_extra_vars, 1) + conversion_host.disable_conversion_host_role(1) + end + + it "enable_conversion_host_role raises if vmware_ssh_private_key is nil" do + expect { conversion_host.enable_conversion_host_role }.to raise_error("vmware_ssh_private_key is mandatory if transformation_method is ssh") + end + + it "enable_conversion_host_role calls ansible_playbook with extra_vars" do + enable_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_enable.yml' + check_playbook = '/usr/share/v2v-conversion-host-ansible/playbooks/conversion_host_check.yml' + enable_extra_vars = { + :v2v_host_type => 'openstack', + :v2v_transport_method => 'ssh', + :v2v_ssh_private_key => 'fake ssh private key' + } + check_extra_vars = { + :v2v_host_type => 'openstack', + :v2v_transport_method => 'ssh' + } + expect(conversion_host).to receive(:ansible_playbook).once.ordered.with(enable_playbook, enable_extra_vars, nil) + expect(conversion_host).to receive(:ansible_playbook).once.ordered.with(check_playbook, check_extra_vars, nil) + conversion_host.enable_conversion_host_role(nil, 'fake ssh private key') + end + end end context "address validation" do