class Case
Case
class
-
initialize
-
export
-
filename
-
grade
-
members
-
skip
-
show
-
read_filename
???
Class Case#close
Class Case::Config
-
get
-
set
-
unset
-
missing_method
Case
class:
Class Case
-
run_local_cmd
-
run_remote_cmd
-
run_remote_cmd_ssh
-
run_remote_cmd_telnet
Attributes
Public Class Methods
Initialize case from specified config @param config (Hash)
# File lib/teuton/case_manager/case/case.rb, line 34 def initialize(config) app = Application.instance @config = Case::Config.new(local: config, global: app.global) @groups = app.groups @id = @@id @@id = @@id.next # Define Case Report @report = Report.new(@id) @report.output_dir = File.join('var', @config.global[:tt_testname]) ensure_dir @report.output_dir # Default configuration @skip = false @skip = get(:tt_skip) unless get(:tt_skip) == 'NODATA' unless app.options['case'].nil? @skip = true @skip = false if app.options['case'].include? @id.to_i end @conn_status = {} @tmpdir = File.join('var', @config.get(:tt_testname), 'tmp', @id.to_s) # ensure_dir @tmpdir # REVISE: When we will need this? Samba? @remote_tmpdir = File.join('/', 'tmp') @unique_values = {} @result = Result.new @debug = Application.instance.debug @verbose = Application.instance.verbose @action_counter = 0 @action = { id: 0, weight: 1.0, description: 'No description!', groupname: nil } @uniques = [] @sessions = {} # Store opened sessions for this case tempfile :default end
Public Instance Methods
# File lib/teuton/case_manager/case/close.rb, line 5 def close(uniques) fails = 0 @uniques.each do |key| next unless uniques[key].include?(id) && uniques[key].count > 1 fails += 1 log_unique_message(key, uniques[key]) end @report.tail[:unique_fault] = fails @report.close end
Close opened sessions for this case
# File lib/teuton/case_manager/case/play.rb, line 28 def close_opened_sessions @sessions.each_value do |s| s.close if s.class == Net::SSH::Connection::Session end end
Export Case
with specific output format @param format (Symbol)
# File lib/teuton/case_manager/case/case.rb, line 79 def export(format) return if skip? @report.export format end
Return case report filename @return String
# File lib/teuton/case_manager/case/case.rb, line 88 def filename @report.filename end
Return case grade @return grade
# File lib/teuton/case_manager/case/case.rb, line 95 def grade return 0.0 if skip @report.tail[:grade] end
# File lib/teuton/case_manager/case/builtin/main.rb, line 5 def host(host = 'localhost') TeutonHost.new(self, host) end
Return case members
@return members
# File lib/teuton/case_manager/case/case.rb, line 103 def members return '-' if skip @report.head[:tt_members] || 'noname' end
Execute “play” order on this case
# File lib/teuton/case_manager/case/play.rb, line 12 def play if skip? verbose "Skipping case <#{@config.get(:tt_members)}>\n" return false end # TODO: Delete old reports??? start_time = Time.now play_in_sequence if get(:tt_sequence) == true # Play in sequence play_in_parallel if get(:tt_sequence) != true # Play in parallel fill_report(start_time, Time.now) close_opened_sessions end
Show case report data on screen
# File lib/teuton/case_manager/case/case.rb, line 119 def show @report.show end
Return case skip value @return skip
# File lib/teuton/case_manager/case/case.rb, line 112 def skip @skip end
Private Instance Methods
Fill case report with time information
# File lib/teuton/case_manager/case/play.rb, line 61 def fill_report(start_time, finish_time) @report.head.merge! @config.global @report.head.merge! @config.local @report.head.merge! @config.running @report.tail[:case_id] = @id @report.tail[:start_time] = start_time @report.tail[:finish_time] = finish_time @report.tail[:duration] = finish_time - start_time end
# File lib/teuton/case_manager/case/close.rb, line 19 def log_unique_message(key, value) log('UNIQUE:', :error) begin log(" ├── Value => #{key}", :error) log(" └── Conflicts => #{value}", :error) rescue StandardError => e log(key, :error) log(e.to_s, :error) end end
Execute every play#group in parallel TO-DO: Under construction!
# File lib/teuton/case_manager/case/play.rb, line 39 def play_in_parallel @groups.each do |t| @action[:groupname] = t[:name] instance_eval(&t[:block]) end end
Execute every play#group in sequence
# File lib/teuton/case_manager/case/play.rb, line 48 def play_in_sequence verboseln "Starting case <#{@config.get(:tt_members)}>" @groups.each do |t| verbose "* Processing <#{t[:name]}> " @action[:groupname] = t[:name] instance_eval(&t[:block]) verbose "\n" end verboseln "\n" end
# File lib/teuton/case_manager/case/case.rb, line 125 def read_filename(filename) begin file = File.open(filename, 'r') item = file.readlines file.close item.map! { |i| i.sub(/\n/, '') } return item rescue StandardError return [] end end
Run command on local machine
# File lib/teuton/case_manager/case/runner.rb, line 37 def run_cmd_localhost() @action[:conn_type] = :local i = my_execute( @action[:command], @action[:encoding] ) @result.exitstatus = i[:exitstatus] @result.content = i[:content] end
# File lib/teuton/case_manager/case/runner.rb, line 16 def run_cmd_on(host) protocol = @config.get("#{host}_protocol".to_sym) ip = @config.get("#{host}_ip".to_sym) if (protocol.to_s.downcase == 'local' || host.to_s == 'localhost') run_cmd_localhost() # Protocol force => local elsif protocol.to_s.downcase == 'ssh' run_cmd_remote_ssh(host) # Protocol force => ssh elsif protocol.to_s.downcase == 'telnet' run_cmd_remote_telnet(host) # Protocol force => telnet elsif (ip.to_s.downcase == 'localhost' || ip.to_s.include?('127.0.0.')) run_cmd_localhost() elsif ip == 'NODATA' log("#{host} IP not found!", :error) else run_cmd_remote_ssh host end end
Run remote command @param input_hostname (Symbol or String)
# File lib/teuton/case_manager/case/runner.rb, line 47 def run_cmd_remote(input_hostname) hostname = input_hostname.to_s i = (hostname + '_protocol').to_sym protocol = @config.get(i) if @config.get(i) protocol = :ssh if protocol.nil? || protocol == 'NODATA' protocol = protocol.to_sym case protocol when :ssh run_cmd_remote_ssh(input_hostname) when :telnet run_cmd_remote_telnet(input_hostname) when :local run_cmd_localhost() else log("Protocol #{protocol} unknown! Use ssh or telnet.", :error) end end
# File lib/teuton/case_manager/case/runner.rb, line 65 def run_cmd_remote_ssh(input_hostname) @action[:conn_type] = :ssh hostname = input_hostname.to_s ip = @config.get((hostname + '_ip').to_sym) username = @config.get((hostname + '_username').to_sym).to_s password = @config.get((hostname + '_password').to_sym).to_s text = '' begin if @sessions[hostname].nil? @sessions[hostname] = Net::SSH.start(ip, username, password: password, keepalive: true, timeout: 30, non_interactive: true) end if @sessions[hostname].class == Net::SSH::Connection::Session text = @sessions[hostname].exec!(@action[:command].to_s) end rescue Errno::EHOSTUNREACH @sessions[hostname] = :nosession @conn_status[hostname] = :host_unreachable verbose Rainbow(Application.instance.letter[:error]).red.bright log("Host #{ip} unreachable!", :error) rescue Net::SSH::AuthenticationFailed @sessions[hostname] = :nosession @conn_status[hostname] = :error_authentication_failed verbose Rainbow(Application.instance.letter[:error]).red.bright log('SSH::AuthenticationFailed!', :error) rescue Net::SSH::HostKeyMismatch @sessions[hostname] = :nosession @conn_status[hostname] = :host_key_mismatch verbose Rainbow(Application.instance.letter[:error]).red.bright log('SSH::HostKeyMismatch!', :error) log("* The destination server's fingerprint is not matching " \ 'what is in your local known_hosts file.', :error) log('* Remove the existing entry in your local known_hosts file', :error) log("* Try this => ssh-keygen -f '/home/USERNAME/.ssh/known_hosts' " \ "-R #{ip}", :error) rescue StandardError => e @sessions[hostname] = :nosession @conn_status[hostname] = :error verbose Rainbow(Application.instance.letter[:error]).red.bright log("[#{e.class}] SSH on <#{username}@#{ip}>" \ " exec: #{@action[:command]}", :error) end output = encode_and_split(@action[:encoding], text) @result.content = output @result.content.compact! end
# File lib/teuton/case_manager/case/runner.rb, line 116 def run_cmd_remote_telnet(input_hostname) @action[:conn_type] = :telnet app = Application.instance hostname = input_hostname.to_s ip = @config.get((hostname + '_ip').to_sym) username = @config.get((hostname + '_username').to_sym).to_s password = @config.get((hostname + '_password').to_sym).to_s text = '' begin if @sessions[hostname].nil? || @sessions[hostname] == :ok h = Net::Telnet.new( 'Host' => ip, 'Timeout' => 30, 'Prompt' => /login|teuton|[$%#>]/ ) # 'Prompt' => Regexp.new(username[1, 40])) # 'Prompt' => /[$%#>] \z/n) h.login(username, password) text = '' h.cmd(@action[:command]) { |i| text << i } h.close @sessions[hostname] = :ok end rescue Net::OpenTimeout @sessions[hostname] = :nosession @conn_status[hostname] = :open_timeout verbose Rainbow(Application.instance.letter[:error]).red.bright log(" ExceptionType=<Net::OpenTimeout> doing <telnet #{ip}>", :error) log(' └── Revise host IP!', :warn) rescue Net::ReadTimeout @sessions[hostname] = :nosession @conn_status[hostname] = :read_timeout verbose Rainbow(Application.instance.letter[:error]).red.bright log(" ExceptionType=<Net::ReadTimeout> doing <telnet #{ip}>", :error) rescue StandardError => e @sessions[hostname] = :nosession @conn_status[hostname] = :error verbose Rainbow(Application.instance.letter[:error]).red.bright log(" ExceptionType=<#{e.class}> doing telnet on <#{username}@#{ip}>" \ " exec: #{@action[:command]}", :error) log(" └── username=<#{username}>, password=<#{password}>," \ " ip=<#{ip}>, HOSTID=<#{hostname}>", :warn) end output = encode_and_split(@action[:encoding], text) @result.content = output @result.content.compact! end