Class: Beaker::Perf

Inherits:
Object
  • Object
show all
Defined in:
lib/beaker/perf.rb

Overview

The Beaker Perf class. A single instance is created per Beaker run.

Constant Summary collapse

PERF_PACKAGES =
['sysstat']
PERF_SUPPORTED_PLATFORMS =

SLES does not treat sysstat as a service that can be started

/amazon|debian|ubuntu|redhat|centos|oracle|scientific|fedora|el|opensuse|sles/
PERF_START_PLATFORMS =
/amazon|debian|ubuntu|redhat|centos|oracle|scientific|fedora|el/

Instance Method Summary collapse

Constructor Details

#initialize(hosts, options) ⇒ void

Create the Perf instance and runs setup_perf_on_host on all hosts if –collect-perf-data was used as an option on the Baker command line invocation. Instances of this class do not hold state and its methods are helpers for remotely executing tasks for performance data gathering with sysstat/sar

Parameters:

  • hosts (Array<Host>)

    All from the configuration

  • options (Hash)

    Options to alter execution



17
18
19
20
21
22
23
# File 'lib/beaker/perf.rb', line 17

def initialize(hosts, options)
  @hosts = hosts
  @options = options
  @logger = options[:logger]
  @perf_timestamp = Time.now
  @hosts.map { |h| setup_perf_on_host(h) }
end

Instance Method Details

#export_perf_data_to_graphite(host) ⇒ void

This method returns an undefined value.

Send performance report numbers to an external Graphite instance

Parameters:

  • host (Host)

    The host we are working with



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/beaker/perf.rb', line 87

def export_perf_data_to_graphite(host)
  @logger.perf_output("Sending data to Graphite server: " + @options[:graphite_server])

  data = JSON.parse(host.exec(Command.new("sadf -j -- -A"), :silent => true).stdout)
  hostname = host['vmhostname'].split('.')[0]

  data['sysstat']['hosts'].each do |host|
    host['statistics'].each do |poll|
      timestamp = DateTime.parse(poll['timestamp']['date'] + ' ' + poll['timestamp']['time']).to_time.to_i

      poll.keys.each do |stat|
        case stat
        when 'cpu-load-all'
          poll[stat].each do |s|
            s.keys.each do |k|
              next if k == 'cpu'

              socket = TCPSocket.new(@options[:graphite_server], 2003)
              socket.puts "#{@options[:graphite_perf_data]}.#{hostname}.cpu.#{s['cpu']}.#{k} #{s[k]} #{timestamp}"
              socket.close
            end
          end

        when 'memory'
          poll[stat].keys.each do |s|
            socket = TCPSocket.new(@options[:graphite_server], 2003)
            socket.puts "#{@options[:graphite_perf_data]}.#{hostname}.memory.#{s} #{poll[stat][s]} #{timestamp}"
            socket.close
          end
        end
      end
    end
  end
end

#get_perf_data(host, perf_start, perf_end) ⇒ void

This method returns an undefined value.

If host is a supported (ie linux) platform, generate a performance report

Parameters:

  • host (Host)

    The host we are working with

  • perf_start (Time)

    The beginning time for the SAR report

  • perf_end (Time)

    The ending time for the SAR report



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/beaker/perf.rb', line 71

def get_perf_data(host, perf_start, perf_end)
  @logger.perf_output("Getting perf data for host: " + host)
  if PERF_SUPPORTED_PLATFORMS.match?(host['platform']) # All flavours of Linux
    host.exec(Command.new("sar -A -s #{perf_start.strftime('%H:%M:%S')} -e #{perf_end.strftime('%H:%M:%S')}"), :acceptable_exit_codes => [0, 1, 2]) if not @options[:collect_perf_data]&.include?('aggressive')
    if (defined? @options[:graphite_server] and not @options[:graphite_server].nil?) and
       (defined? @options[:graphite_perf_data] and not @options[:graphite_perf_data].nil?)
      export_perf_data_to_graphite(host)
    end
  else
    @logger.perf_output("Perf (sysstat) not supported on host: " + host)
  end
end

This method returns an undefined value.

Iterate over all hosts, calling get_perf_data



61
62
63
64
# File 'lib/beaker/perf.rb', line 61

def print_perf_info
  @perf_end_timestamp = Time.now
  @hosts.map { |h| get_perf_data(h, @perf_timestamp, @perf_end_timestamp) }
end

#setup_perf_on_host(host) ⇒ void

This method returns an undefined value.

Install sysstat if required and perform any modifications needed to make sysstat work.

Parameters:

  • host (Host)

    The host we are working with



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/beaker/perf.rb', line 28

def setup_perf_on_host(host)
  @logger.perf_output("Setup perf on host: " + host)
  # Install sysstat if required
  if PERF_SUPPORTED_PLATFORMS.match?(host['platform'])
    PERF_PACKAGES.each do |pkg|
      host.install_package pkg if not host.check_for_package pkg
    end
  else
    @logger.perf_output("Perf (sysstat) not supported on host: " + host)
  end

  if /debian|ubuntu/.match?(host['platform'])
    @logger.perf_output("Modify /etc/default/sysstat on Debian and Ubuntu platforms")
    host.exec(Command.new('sed -i s/ENABLED=\"false\"/ENABLED=\"true\"/ /etc/default/sysstat'))
  elsif /opensuse|sles/.match?(host['platform'])
    @logger.perf_output("Creating symlink from /etc/sysstat/sysstat.cron to /etc/cron.d")
    host.exec(Command.new('ln -s /etc/sysstat/sysstat.cron /etc/cron.d'), :acceptable_exit_codes => [0, 1])
  end
  if @options[:collect_perf_data]&.include?('aggressive')
    @logger.perf_output("Enabling aggressive sysstat polling")
    if /debian|ubuntu/.match?(host['platform'])
      host.exec(Command.new('sed -i s/5-55\\\/10/*/ /etc/cron.d/sysstat'))
    elsif /amazon|centos|el|fedora|oracle|redhat|scientific/.match?(host['platform'])
      host.exec(Command.new('sed -i s/*\\\/10/*/ /etc/cron.d/sysstat'))
    end
  end
  return unless PERF_START_PLATFORMS.match?(host['platform']) # SLES doesn't need this step

  host.exec(Command.new('service sysstat start'))
end