onering-report 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/Gemfile.lock +57 -0
  7. data/Makefile +2 -0
  8. data/Rakefile +8 -0
  9. data/lib/etc/facter.list +19 -0
  10. data/lib/facter/onering_disk_smart.rb +38 -0
  11. data/lib/facter/onering_properties_chef.rb +41 -0
  12. data/lib/facter/onering_properties_haproxy.rb +155 -0
  13. data/lib/facter/onering_properties_id.rb +69 -0
  14. data/lib/facter/onering_properties_netstat.rb +94 -0
  15. data/lib/facter/onering_properties_network.rb +253 -0
  16. data/lib/facter/onering_properties_onering.rb +17 -0
  17. data/lib/facter/onering_properties_openvz.rb +17 -0
  18. data/lib/facter/onering_properties_physical.rb +87 -0
  19. data/lib/facter/onering_properties_services.rb +25 -0
  20. data/lib/facter/onering_properties_system.rb +18 -0
  21. data/lib/facter/onering_properties_virident.rb +93 -0
  22. data/lib/facter/onering_properties_xen.rb +32 -0
  23. data/lib/facter/onering_properties_zfs.rb +174 -0
  24. data/lib/reporter/default/properties_chef.rb +15 -0
  25. data/lib/reporter/default/properties_facter.rb +51 -0
  26. data/lib/reporter/default/properties_haproxy.rb +8 -0
  27. data/lib/reporter/default/properties_ipmi.rb +10 -0
  28. data/lib/reporter/default/properties_network.rb +63 -0
  29. data/lib/reporter/default/properties_ohai.rb +62 -0
  30. data/lib/reporter/default/properties_openvz.rb +12 -0
  31. data/lib/reporter/default/properties_physical.rb +10 -0
  32. data/lib/reporter/default/properties_services.rb +6 -0
  33. data/lib/reporter/default/properties_system_cpu.rb +30 -0
  34. data/lib/reporter/default/properties_system_disk_block.rb +35 -0
  35. data/lib/reporter/default/properties_system_disk_lvm.rb +73 -0
  36. data/lib/reporter/default/properties_system_disk_mounts.rb +46 -0
  37. data/lib/reporter/default/properties_system_disk_smart.rb +3 -0
  38. data/lib/reporter/default/properties_system_memory.rb +111 -0
  39. data/lib/reporter/default/properties_xen.rb +16 -0
  40. data/lib/reporter/default/stats_virident.rb +8 -0
  41. data/lib/reporter/default/stats_zfs.rb +8 -0
  42. data/onering-report.gemspec +18 -0
  43. metadata +126 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ec8274d268a961e2138cb05c7371610982db522
4
+ data.tar.gz: 0faf9d2467b487596783743c9485940149016d89
5
+ SHA512:
6
+ metadata.gz: 73c92ee34a7b60620f9c9d232a1ee11ea72d53dd5f23e32c29e3baeb74b995f1a3aee9eb2397181971a9fc2f755bea98f5cade44ce5bc9be3471c768b6a51d2e
7
+ data.tar.gz: 9a79363d52c99399801d87206bf9171708f5930b698d5e2dea9174ab2468495329d9ffd2a2ecab3b53c60eb6418c531e7c2f132111498a9057d271a6e40eb664
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ onering-report
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ onering-report (0.6.5)
5
+ onering-client
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ CFPropertyList (2.2.8)
11
+ addressable (2.3.5)
12
+ coderay (1.1.0)
13
+ deep_merge (1.0.0)
14
+ facter (2.1.0)
15
+ CFPropertyList (~> 2.2.6)
16
+ hashlib (0.0.35)
17
+ hiera (1.3.4)
18
+ json_pure
19
+ httparty (0.11.0)
20
+ multi_json (~> 1.0)
21
+ multi_xml (>= 0.5.2)
22
+ json_pure (1.8.1)
23
+ method_source (0.8.2)
24
+ multi_json (1.7.9)
25
+ multi_xml (0.5.5)
26
+ onering-client (0.4.3)
27
+ addressable (= 2.3.5)
28
+ deep_merge (= 1.0.0)
29
+ facter (>= 1.7.2)
30
+ hashlib (>= 0.0.35)
31
+ httparty (= 0.11.0)
32
+ multi_json (= 1.7.9)
33
+ rainbow (<= 1.1.4)
34
+ trollop (= 2.0)
35
+ xml-simple (= 1.1.2)
36
+ pry (0.10.0)
37
+ coderay (~> 1.1.0)
38
+ method_source (~> 0.8.1)
39
+ slop (~> 3.4)
40
+ puppet (3.6.2)
41
+ facter (> 1.6, < 3)
42
+ hiera (~> 1.0)
43
+ json_pure
44
+ rgen (~> 0.6.5)
45
+ rainbow (1.1.4)
46
+ rgen (0.6.6)
47
+ slop (3.6.0)
48
+ trollop (2.0)
49
+ xml-simple (1.1.2)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ onering-report!
56
+ pry
57
+ puppet
data/Makefile ADDED
@@ -0,0 +1,2 @@
1
+ all:
2
+ gem build *.gemspec
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.pattern = "test/*_test.rb"
7
+ t.verbose = true
8
+ end
@@ -0,0 +1,19 @@
1
+ serialnumber:serial
2
+ manufacturer:make
3
+ productname:model
4
+ boardmanufacturer:mbmake
5
+ boardproductname:mbmodel
6
+ boardserialnumber:mbserial
7
+ hostname
8
+ fqdn
9
+ default_ipaddress:ip
10
+ default_macaddress:mac
11
+ default_gateway:gateway
12
+ kernelrelease:kernel
13
+ kernelarguments:@kernelarguments
14
+ architecture:arch
15
+ operatingsystem:distro
16
+ operatingsystemrelease:version
17
+ signature
18
+ boottime:booted_at
19
+ onering:@onering
@@ -0,0 +1,38 @@
1
+ if Facter::Util::Resolution.which('smartctl')
2
+ disks = []
3
+ letters = (('a'..'z').to_a + ('a'..'z').to_a.collect{|i| ('a'..'z').to_a.collect{|j| i+j }}.flatten)
4
+
5
+ letters.each do |i|
6
+ if File.exists?("/dev/sd#{i}")
7
+ smart = {}
8
+
9
+ Facter::Util::Resolution.exec("smartctl -A /dev/sd#{i}").to_s.lines.each do |line|
10
+ next unless line =~ /^\s*[0-9]+/
11
+ id, name, flag, value, worst, threshold, type, updated, failed, raw = line.strip.chomp.split(/\s+/)
12
+
13
+ smart[:attributes] ||= []
14
+ smart[:attributes] << {
15
+ :id => id.to_i,
16
+ :name => name.downcase.gsub(/[\s\-]+/, '_'),
17
+ :value => value.to_i,
18
+ :worst => worst.to_i,
19
+ :threshold => threshold.to_i,
20
+ :type => type.downcase,
21
+ :raw => raw
22
+ }
23
+ end
24
+
25
+ smart[:name] = "/dev/sd#{i}"
26
+
27
+ disks << smart
28
+ end
29
+ end
30
+
31
+ disks = disks.reject{|i| (i[:attributes] || {}).empty? }
32
+
33
+ unless disks.empty?
34
+ Facter.add('smart') do
35
+ setcode { disks }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,41 @@
1
+ # Onering Facts - Chef Properties
2
+ # provides collection of Chef metadata
3
+ #
4
+ require 'json'
5
+
6
+ chef = Facter::Util::Resolution.exec("knife node show $(hostname -f) -c /etc/chef/client.rb -k /etc/chef/client.pem -u $(hostname -f) -F json 2> /dev/null | grep -v 'json_class' 2> /dev/null")
7
+
8
+
9
+ if chef
10
+ begin
11
+ chef = (JSON.load(chef) rescue {})
12
+
13
+ unless chef.empty?
14
+ Facter.add('chef_nodename') do
15
+ setcode { chef['name'].to_s.strip.chomp.downcase rescue nil }
16
+ end
17
+
18
+ Facter.add('chef_version') do
19
+ setcode { %x{chef-client --version}.chomp.split(' ').last.strip rescue nil }
20
+ end
21
+
22
+ Facter.add('chef_environment') do
23
+ setcode { chef['environment'].to_s.strip.chomp.downcase rescue nil }
24
+ end
25
+
26
+ Facter.add('chef_runlist') do
27
+ setcode { chef['run_list'].collect{|i| i.gsub('[','-').gsub(']','').gsub('::','-') } rescue nil }
28
+ end
29
+
30
+ Facter.add('chef_enabled') do
31
+ setcode { !File.exists?('/outbrain/no_chef_run') }
32
+ end
33
+
34
+ Facter.add('chef_lastrun') do
35
+ setcode { File.mtime('/etc/chef/last_ran_at').to_i rescue nil }
36
+ end
37
+ end
38
+ rescue Exception => e
39
+ STDERR.puts "#{e.name}: #{e.message}"
40
+ end
41
+ end
@@ -0,0 +1,155 @@
1
+ # Onering Facts - HAProxy Stats
2
+ # provides collection of statistics from HAProxy
3
+ #
4
+ require 'set'
5
+ require 'socket'
6
+
7
+ haproxy = nil
8
+ sockets_seen = Set.new()
9
+
10
+ # find all haproxy configs, ensuring haproxy.cfg is always front of the line
11
+ Dir["/etc/haproxy/*.cfg"].sort{|a,b| (b == 'haproxy.cfg' ? 1 : a<=>b) }.each do |cfg|
12
+ haproxy ||= []
13
+ pools = {}
14
+ cfg_data = (File.read(cfg).lines rescue [])
15
+
16
+ description = (cfg_data.select{|i| i =~ /^\s* description / }.first.strip.split(' ',2).last.gsub('"','') rescue nil)
17
+ socket = (cfg_data.select{|i| i =~ /^\s* stats socket / }.first.strip.split(' ')[2] rescue nil)
18
+
19
+ # stats socket must be present in the config, a real file, and not have been seen before
20
+ if not socket.nil? and File.exists?(socket) and not sockets_seen.include?(socket)
21
+ sockets_seen << socket
22
+ stats = UNIXSocket.new(socket)
23
+ stats.puts("show stat")
24
+
25
+ instance = {
26
+ :name => File.basename(cfg, '.cfg'),
27
+ :socket => socket,
28
+ :path => cfg,
29
+ :description => description,
30
+ :pools => []
31
+ }
32
+
33
+ stats.read.lines.each do |line|
34
+ next if line[0].chr == '#'
35
+ line = line.strip.chomp
36
+ next if line.empty?
37
+ line = line.split(',')
38
+
39
+ begin
40
+ pools[line[0]] ||= {
41
+ :name => line[0],
42
+ :services => []
43
+ }
44
+
45
+ pools[line[0]][:services] << ({
46
+ :name => line[1],
47
+ :queue => {
48
+ :current => line[2].to_i,
49
+ :maximum => line[3].to_i,
50
+ :limit => line[25].to_i
51
+ },
52
+ :sessions => {
53
+ :rate => line[33].to_i,
54
+ :rate_limit => line[34].to_i,
55
+ :rate_maximum => line[35].to_i,
56
+ :current => line[4].to_i,
57
+ :maximum => line[5].to_i,
58
+ :limit => line[6].to_i,
59
+ :total => line[7].to_i
60
+ },
61
+ :bytes => {
62
+ :in => line[8].to_i,
63
+ :out => line[9].to_i
64
+ },
65
+ :denied => {
66
+ :request => line[10].to_i,
67
+ :response => line[11].to_i
68
+ },
69
+ :errors => {
70
+ :request => line[12].to_i,
71
+ :connection => line[13].to_i,
72
+ :response => line[14].to_i
73
+ },
74
+ :warnings => {
75
+ :retry => line[15].to_i,
76
+ :redispatch => line[16].to_i
77
+ },
78
+ :status => line[17].downcase,
79
+ :online => (line[17].downcase == 'up'),
80
+ :weight => line[18].to_i,
81
+ :checks => {
82
+ :status => (case line[36].upcase.to_sym
83
+ when :UNK then :unknown
84
+ when :INI then :initializing
85
+ when :SOCKERR then :socket_error
86
+ when :L4OK then :layer4_ok
87
+ when :L4TMOUT then :layer4_timeout
88
+ when :L4CON then :layer4_connection_failed
89
+ when :L6OK then :layer6_ok
90
+ when :L6TOUT then :layer6_ssl_timeout
91
+ when :L6RSP then :layer6_ssl_protocol_error
92
+ when :L7OK then :layer7_ok
93
+ when :L7OKC then :layer7_ok
94
+ when :L7TOUT then :layer7_timeout
95
+ when :L7RSP then :layer7_protocol_error
96
+ when :L7STS then :layer7_server_error
97
+ else nil
98
+ end
99
+ ),
100
+ :response_code => line[37].to_i,
101
+ :duration => line[38].to_i,
102
+ :fail_details => line[45],
103
+ :failed => line[21].to_i,
104
+ :downs => line[22].to_i
105
+ },
106
+ :http => {
107
+ :request => {
108
+ :rate => line[46].to_i,
109
+ :rate_maximum => line[47].to_i,
110
+ :total => line[48].to_i,
111
+ :client_abort => line[49].to_i,
112
+ :server_abort => line[50].to_i
113
+ },
114
+ :response => {
115
+ '100' => line[39].to_i,
116
+ '200' => line[40].to_i,
117
+ '300' => line[41].to_i,
118
+ '400' => line[42].to_i,
119
+ '500' => line[43].to_i,
120
+ 'other' => line[44].to_i
121
+ }
122
+ },
123
+ :last_changed_at => Time.at(Time.now.to_i - line[23].to_i).strftime('%Y-%m-%d %H:%M:%S %z'),
124
+ :downtime => line[24].to_i,
125
+ :pid => line[26].to_i,
126
+ :proxy_id => line[27].to_i,
127
+ :service_id => line[28].to_i,
128
+ :throttle => line[29],
129
+ :selected => line[30].to_i,
130
+ :tracked => line[31],
131
+ :type => (case line[32].to_i
132
+ when 0 then :frontend
133
+ when 1 then :backend
134
+ when 2 then :server
135
+ when 3 then :socket
136
+ else nil
137
+ end
138
+ )
139
+ })
140
+ rescue
141
+ next
142
+ end
143
+ end
144
+
145
+ instance[:pools] = pools.values()
146
+ haproxy << instance
147
+ end
148
+ end
149
+
150
+
151
+ if not haproxy.nil?
152
+ Facter.add('haproxy') do
153
+ setcode { haproxy }
154
+ end
155
+ end
@@ -0,0 +1,69 @@
1
+ Facter.add('uuid') do
2
+ setcode do
3
+ if not Facter.value('uuid').nil?
4
+ Facter.value('uuid')
5
+ elsif Facter::Util::Resolution.which('dmidecode')
6
+ Facter::Util::Resolution.exec('dmidecode -s system-uuid').strip.chomp
7
+ elsif File.exists?('/sys/hypervisor/uuid')
8
+ File.read('/sys/hypervisor/uuid').lines.first.strip.chomp
9
+ else
10
+ nil
11
+ end
12
+ end
13
+ end
14
+
15
+ Facter.add('signature') do
16
+ setcode do
17
+ parts = []
18
+
19
+ if Facter.value('uuid')
20
+ parts << Facter.value('uuid').gsub(/[\W\_]+/,'').upcase
21
+ end
22
+
23
+ if Facter.value('macaddress')
24
+ parts << Facter.value('macaddress').gsub(/[\W\_]+/,'').upcase
25
+ end
26
+
27
+ # still empty, now we really have to grasp at straws
28
+ if parts.empty?
29
+ if Facter.value('ipaddress')
30
+ parts << Facter.value('ipaddress').split(',').first.strip.chomp.delete('.')
31
+ end
32
+ end
33
+
34
+
35
+ # final pruning
36
+ parts = parts.reject{|i| i.nil? || i.empty? }
37
+
38
+ # still empty?
39
+ if parts.empty?
40
+ nil
41
+ else
42
+ parts.join('-')
43
+ end
44
+ end
45
+ end
46
+
47
+ Facter.add('hardwareid') do
48
+ setcode do
49
+ # 1. contents of /etc/hardware.id takes absolute precedence
50
+ if File.size?('/etc/hardware.id')
51
+ File.read('/etc/hardware.id').strip.chomp rescue nil
52
+
53
+ # 2. value of kernel boot argument 'hardwareid' is checked
54
+ elsif Facter.value('kernelarguments').is_a?(Hash) and
55
+ not Facter.value('kernelarguments')['hardwareid'].nil? and
56
+ not Facter.value('kernelarguments')['hardwareid'].to_s.strip.empty?
57
+ Facter.value('kernelarguments')['hardwareid'].to_s.strip
58
+
59
+ # 3. calculate a new hardwareid from the system signature
60
+ elsif Facter.value('signature')
61
+ require 'digest'
62
+ Digest::SHA256.new.update(Facter.value('signature')).hexdigest[0..5]
63
+
64
+ # 4. i got nothing...
65
+ else
66
+ nil
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,94 @@
1
+ require 'resolv'
2
+
3
+ protocols = %w{tcp tcp6 udp udp6}
4
+
5
+ flags = "--numeric-hosts --numeric-ports --programs --tcp --udp -ee"
6
+
7
+ case Facter.value('osfamily').to_s.downcase
8
+ when 'debian' then flags += " -W"
9
+ when 'redhat' then flags += " -T"
10
+ end
11
+
12
+ listening = Facter::Util::Resolution.exec("nice -n 19 netstat #{flags} -l | tr -s ' ' | sed 's/ LISTEN//g'")
13
+ #nonlistening = Facter::Util::Resolution.exec("nice -n 19 netstat #{flags} | tr -s ' '")
14
+
15
+ # netstat = {
16
+ # 'listening' => [],
17
+ # 'connections' => []
18
+ # }
19
+
20
+ netstat = {
21
+ 'listening' => []
22
+ }
23
+
24
+ def getcommandline(pid)
25
+ return nil unless pid.to_i > 0
26
+ (File.read("/proc/#{pid}/cmdline").to_s.strip.chomp.squeeze("\u0000").squeeze("\0").gsub("\u0000", ' ').gsub("\0", ' '))
27
+ end
28
+
29
+ [*listening.to_s.lines.to_a[2..-1]].each do |line|
30
+ protocol, recvq, sendq, local, foreign, user, inode, program = line.split(' ', 8)
31
+
32
+ next unless protocols.include?(protocol)
33
+
34
+ local = local.split(':')
35
+ foreign = foreign.split(':')
36
+ local_host = local[-2]
37
+ local_port = local[-1]
38
+ foreign_host = foreign[-2]
39
+ foreign_port = foreign[-1]
40
+ pid = program.split('/').first
41
+
42
+ command = getcommandline(pid)
43
+ next if command.nil?
44
+
45
+ netstat['listening'] << {
46
+ "protocol" => protocol,
47
+ "address" => local_host,
48
+ "fqdn" => (Resolv.getname(local_host) rescue nil),
49
+ "port" => local_port.to_i,
50
+ "user" => user,
51
+ "program" => {
52
+ "pid" => pid.to_i,
53
+ "command" => getcommandline(pid)
54
+ }
55
+ }
56
+ end
57
+
58
+ # nonlistening.lines.to_a[2..-1].each do |line|
59
+ # protocol, recvq, sendq, local, foreign, state, user, inode, program = line.split(' ', 9)
60
+ # next unless protocols.include?(protocol)
61
+
62
+ # local = local.split(':')
63
+ # foreign = foreign.split(':')
64
+ # local_host = local[-2]
65
+ # local_port = local[-1]
66
+ # foreign_host = foreign[-2]
67
+ # foreign_port = foreign[-1]
68
+ # pid = program.split('/').first
69
+
70
+ # netstat['connections'] << {
71
+ # "protocol" => protocol,
72
+ # "from" => {
73
+ # "address" => local_host,
74
+ # "port" => local_port.to_i
75
+ # },
76
+ # "to" => {
77
+ # "address" => foreign_host,
78
+ # "fqdn" => (Resolv.getname(foreign_host) rescue nil),
79
+ # "port" => foreign_port.to_i
80
+ # },
81
+ # "user" => user,
82
+ # "state" => state.downcase,
83
+ # "program" => {
84
+ # "pid" => pid.to_i,
85
+ # "command" => getcommandline(pid)
86
+ # }
87
+ # }
88
+ # end
89
+
90
+ Facter.add("netstat") do
91
+ setcode do
92
+ netstat
93
+ end
94
+ end