class Case

Case class

Class Case#close

Class Case::Config

Case class:

Class Case

Attributes

action[RW]
config[R]
conn_status[R]
id[R]
result[RW]
uniques[R]

Public Class Methods

new(config) click to toggle source

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

close(uniques) click to toggle source
# 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() click to toggle source

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(format) click to toggle source

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
filename() click to toggle source

Return case report filename @return String

# File lib/teuton/case_manager/case/case.rb, line 88
def filename
  @report.filename
end
grade() click to toggle source

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
host(host = 'localhost') click to toggle source
# File lib/teuton/case_manager/case/builtin/main.rb, line 5
def host(host = 'localhost')
  TeutonHost.new(self, host)
end
members() click to toggle source
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
play() click to toggle source

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
Also aliased as: start
show() click to toggle source

Show case report data on screen

# File lib/teuton/case_manager/case/case.rb, line 119
def show
  @report.show
end
skip() click to toggle source

Return case skip value @return skip

# File lib/teuton/case_manager/case/case.rb, line 112
def skip
  @skip
end
Also aliased as: skip?
skip?()
Alias for: skip
start()
Alias for: play

Private Instance Methods

fill_report(start_time, finish_time) click to toggle source

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
log_unique_message(key, value) click to toggle source
# 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
play_in_parallel() click to toggle source

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
play_in_sequence() click to toggle source

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
read_filename(filename) click to toggle source
# 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_cmd_localhost() click to toggle source

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
run_cmd_on(host) click to toggle source
# 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_cmd_remote(input_hostname) click to toggle source

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
run_cmd_remote_ssh(input_hostname) click to toggle source
# 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
run_cmd_remote_telnet(input_hostname) click to toggle source
# 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