onering-report 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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