require 'shellwords' module ForemanVirtWhoConfigure class OutputGenerator class ConfigurationResult attr_reader :code, :identifier, :message def initialize(code, identifier, message) @code, @message, @identifier = code, message, identifier end end MINIMUM_VIRT_WHO_VERSION = '0.24.2' LIBVIRT_FAKE_PASSWORD = 'libvirt_fake_password' KUBEVIRT_FAKE_PASSWORD = 'kubevirt_fake_password' CONFIGURATION_RESULTS = [ ConfigurationResult.new(0, 'success', N_('Success')), ConfigurationResult.new(1, 'virt_who_too_old', N_('Newer version of virt-who is required, minimum version is %s') % MINIMUM_VIRT_WHO_VERSION), ConfigurationResult.new(2, 'virt_who_config_file_issue', N_('Unable to create virt-who config file')), ConfigurationResult.new(4, 'virt_who_sysconfig_file_issue', N_('Unable to create sysconfig file')), ConfigurationResult.new(8, 'virt_who_chkconfig_issue', N_('Unable to enable virt-who service using chkconfig')), ConfigurationResult.new(16, 'virt_who_service_issue', N_('Unable to start virt-who service, please see virt-who logs for more details')), ConfigurationResult.new(32, 'virt_who_installation', N_('Unable to install virt-who package, make sure the host is properly subscribed and has access to satellite-tools repository')), ] attr_reader :config def initialize(config) @config = config end def error_code(error_name) result = CONFIGURATION_RESULTS.find { |result| result.identifier == error_name.to_s } result.try(:code) end def ready_for_virt_who_output? missing_virt_who_input_messages.empty? end def missing_virt_who_input_messages messages = [] messages.push _('Owner was not provided') unless config.organization_id? messages.push _('Interval was not provided') unless config.interval.present? # messages.push _('Cofiguration not stored') unless config.persisted? # messages.push _('Service user was not provided') unless config.service_user_id.present? messages end def virt_who_output(format = nil) kubeconfig = config.hypervisor_type == 'kubevirt' ? "\nkubeconfig=#{config.kubeconfig_path}" : '' result = '' result += "#!/bin/bash\n" if format == :bash_script result += < /dev/null`; then compose_install_command satellite-maintain elif `rpm -q rubygem-foreman_maintain > /dev/null`; then compose_install_command foreman-maintain else yum install -y virt-who || result_code=$(($result_code|#{error_code(:virt_who_installation)})) fi } step 1 "Installing virt-who" install_virt_who if verify_minimal_version; then step 2 "Encrypting password" cr_password=`virt-who-password --password '#{cr_password}' 2> /dev/null` user_password=`virt-who-password --password '#{service_user_password}' 2> /dev/null` step 3 "Creating virt-who configuration" cat > #{config_file_path} << EOF ### This configuration file is managed via the virt-who configure plugin ### manual edits will be deleted. [#{identifier}] type=#{type} hypervisor_id=#{hypervisor_id} owner=#{owner} env=Library#{connection_details}#{filtering} rhsm_hostname=#{satellite_url} rhsm_username=#{service_user_username} rhsm_encrypted_password=$user_password rhsm_prefix=/rhsm#{kubeconfig} EOF if [ $? -ne 0 ]; then result_code=$(($result_code|#{error_code(:virt_who_config_file_issue)})); fi step 4 "Creating sysconfig virt-who configuration" cat > #{sysconfig_file_path} << EOF ### This configuration file is managed via the virt-who configure plugin ### manual edits will be deleted. VIRTWHO_DEBUG=#{config.debug? ? 1 : 0} VIRTWHO_INTERVAL=#{config.interval * 60}#{proxy_strings} EOF if [ $? -ne 0 ]; then result_code=$(($result_code|#{error_code(:virt_who_sysconfig_file_issue)})); fi step 5 "Enabling and restarting the virt-who service" chkconfig virt-who on || result_code=$(($result_code|#{error_code(:virt_who_chkconfig_issue)})) service virt-who restart || result_code=$(($result_code|#{error_code(:virt_who_service_issue)})) else result_code=$(($result_code|#{error_code(:virt_who_too_old)})) fi heading "Finished" if [ $result_code -ne 0 ]; then echo "There were some errors during configuration:" #{error_handling} else echo "Finished successfully" fi EOS result += "exit $result_code\n" if format == :bash_script result end def connection_details if config.hypervisor_type == 'kubevirt' "" else "\nserver=#{cr_server} username=#{cr_username} encrypted_password=$cr_password" end end def error_handling CONFIGURATION_RESULTS.map do |result| "[ $(($result_code&#{result.code})) -ge 1 ] && echo '#{result.message}'" end.join("\n ") end def filtering case config.listing_mode.to_i when ForemanVirtWhoConfigure::Config::UNLIMITED '' when ForemanVirtWhoConfigure::Config::WHITELIST enabled_filters({'filter_hosts' => config.whitelist, 'filter_host_parents' => config.filter_host_parents}) when ForemanVirtWhoConfigure::Config::BLACKLIST enabled_filters({'exclude_hosts' => config.blacklist, 'exclude_host_parents' => config.exclude_host_parents}) end end def enabled_filters(filter) filter.reject { |_, list| list.blank? }.map { |filter,list| filtering_line_sanitized(filter, list) }.join end def filtering_line_sanitized(filter, list) "\n" + filter + '=' + sanitize_filter(list.to_s) end def sanitize_filter(list) sanitize(list) end def config_file_path "/etc/virt-who.d/#{identifier}.conf" end def sysconfig_file_path '/etc/sysconfig/virt-who' end def identifier "virt-who-config-#{config.id}" end def hypervisor_id config.hypervisor_id end def owner config.organization.label end def type config.hypervisor_type end # returns nil if url could not be parsed or is invalid, e.g. qemu:///system def cr_server config.hypervisor_server end def cr_username Shellwords.escape(config.hypervisor_username) end def cr_password case config.hypervisor_type when 'libvirt' config.hypervisor_password.blank? ? LIBVIRT_FAKE_PASSWORD : config.hypervisor_password when 'kubevirt' config.hypervisor_password.blank? ? KUBEVIRT_FAKE_PASSWORD : config.hypervisor_password else config.hypervisor_password end end def satellite_url config.satellite_url end def service_user_username config.service_user.username end def service_user_password config.service_user.encrypted_password end def cr config.compute_resource end def proxy config.http_proxy end def no_proxy config.no_proxy end def sanitize_proxy(string) sanitize(string) end def proxy_type "#{URI(proxy.url).scheme}_proxy" end def proxy_strings output = '' output << "\n#{proxy_type}=#{sanitize_proxy(proxy.full_url)}" if proxy.present? output << "\nNO_PROXY=#{sanitize_proxy(no_proxy)}" if no_proxy.present? output << "\nNO_PROXY=*" if !proxy.present? && !no_proxy.present? output end def sanitize(string) string.tr("\r\n", '').strip.chomp(",") end end end