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
@@ -0,0 +1,253 @@
1
+
2
+ def _format(key, value)
3
+ rv = []
4
+ value = nil if value =~ /Not received/i
5
+
6
+ begin
7
+ case key
8
+ when :autoneg
9
+ v0, v1 = value.split('/')
10
+ rv << [:autoneg_supported, (v0 == 'supported')]
11
+ rv << [:autoneg_enabled, (v1 == 'enabled')]
12
+
13
+ when :mgmt_ip
14
+ rv << [:management_ip, value]
15
+
16
+ when :mau_oper_type
17
+ rv << [:mau_type, value]
18
+
19
+ when :port_id
20
+ value = value.split(' ')
21
+ value = value.select{|i| i =~ /..:..:..:..:..:../ }.first
22
+
23
+ rv << [:port_mac, value.upcase]
24
+
25
+ when :chassis_id
26
+ value = value.split(' ')
27
+ value = value.select{|i| i =~ /..:..:..:..:..:../ }.first
28
+
29
+ rv << [:chassis_mac, value.upcase]
30
+
31
+ when :port_descr
32
+ port = value.split(/[^0-9]([0-9])/, 2)
33
+ port.shift
34
+ port = port.join('')
35
+
36
+ rv << [:port_name, value]
37
+ rv << [:port, port]
38
+
39
+ when :mfs
40
+ rv << [:mfs, (value.split(' ').first.to_i rescue nil)]
41
+
42
+ when :sys_name
43
+
44
+ rv << [:switch, value]
45
+
46
+ when :lldp_med_device_type,
47
+ :lldp_med_capabilities,
48
+ :caps,
49
+ :sys_descr
50
+ return []
51
+
52
+ else
53
+ rv << [key, value]
54
+ end
55
+ rescue
56
+ nil
57
+ end
58
+
59
+ return rv
60
+ end
61
+
62
+
63
+ # Typefix for interfaces fact
64
+ Facter.add('network_interfaces') do
65
+ setcode do
66
+ Facter.value("interfaces").split(',')
67
+ end
68
+ end
69
+
70
+ default_if = Facter::Util::Resolution.exec('ip route | grep "^default" | tr -s " " | cut -d " " -f5')
71
+
72
+ # attempt to use 'route -n' if 'ip route' failed somehow
73
+ if default_if.nil? or not Facter.value('interfaces').to_s.split(',').include?(default_if)
74
+ STDERR.puts("Falling back to 'route -n' for default interface detection")
75
+ default_if = Facter::Util::Resolution.exec('route -n | grep "^0.0.0.0" | tr -s " " | cut -d " " -f8')
76
+ end
77
+
78
+ Facter.add('default_gateway') do
79
+ setcode do
80
+ default_gw = Facter::Util::Resolution.exec('ip route | grep "^default" | tr -s " " | cut -d " " -f3')
81
+
82
+ # 'ip route' default gateway looks like an IP address, cool!
83
+ if default_gw.to_s =~ /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/
84
+ default_gw
85
+ else
86
+ STDERR.puts("Falling back to 'route -n' for default gateway detection")
87
+ Facter::Util::Resolution.exec('route -n | grep "UG" | tr -s " " | cut -d" " -f2')
88
+ end
89
+ end
90
+ end
91
+
92
+ if default_if
93
+ begin
94
+ default_if.strip!
95
+ default_if.chomp!
96
+
97
+ Facter.add('default_interface') do
98
+ setcode { default_if }
99
+ end
100
+
101
+ Facter.add('default_macaddress') do
102
+ setcode { Facter.value("macaddress_#{default_if}") }
103
+ end
104
+
105
+ Facter.add('default_ipaddress') do
106
+ setcode { Facter.value("ipaddress_#{default_if}") }
107
+ end
108
+ rescue
109
+ nil
110
+ end
111
+ else
112
+ # no default interface could be determined, fallback to sane defaults
113
+ #-
114
+ Facter.add('default_macaddress') do
115
+ setcode { Facter.value("macaddress") }
116
+ end
117
+
118
+ Facter.add('default_ipaddress') do
119
+ setcode { Facter.value("ipaddress") }
120
+ end
121
+ end
122
+
123
+ # LLDP
124
+ begin
125
+ require 'xmlsimple'
126
+ current_iface = nil
127
+ network_lldp = {}
128
+
129
+ output = Facter::Util::Resolution.exec('lldpctl -f xml')
130
+
131
+ if not output.nil?
132
+ # XML formatting worked, parse as such
133
+ if output[0..1] == '<?'
134
+ begin
135
+ output = XmlSimple.xml_in(output)
136
+
137
+ (output['interface'] || []).each do |i|
138
+ # only accept devices that advertise themselves as a router
139
+ next unless i['chassis'].first['capability'].select{|j| j['type'] == 'Router' }.first['enabled'] == 'on'
140
+
141
+ current_iface = i['name']
142
+ port = i['port'].first
143
+ vlan = i['vlan']
144
+ chassis = i['chassis'].first
145
+ speed, duplex = port['auto-negotiation'].first['current'].first['content'].split(' - ',2).first.split(/BaseT/i,2)
146
+
147
+ speed = (Integer(speed) * 1000000 rescue nil) # convert to bits
148
+ duplex = case duplex
149
+ when 'FD' then :full
150
+ when 'HD' then :half
151
+ else nil
152
+ end
153
+
154
+ # port settings
155
+ network_lldp[current_iface] = Hash[_format(:port_descr, port['descr'].first['content'])]
156
+
157
+ network_lldp[current_iface]['port_mac'] = (port['id'].first['content'] rescue nil)
158
+ network_lldp[current_iface]['mfs'] = (port['mfs'].first['content'].to_i rescue nil)
159
+ network_lldp[current_iface]['speed'] = speed
160
+ network_lldp[current_iface]['duplex'] = duplex
161
+
162
+ # switch settings
163
+ network_lldp[current_iface]['switch'] = (chassis['name'].first['content'] rescue nil)
164
+ network_lldp[current_iface]['management_ip'] = (chassis['mgmt-ip'].first['content'] rescue nil)
165
+ network_lldp[current_iface]['chassis_mac'] = (chassis['id'].first['content'] rescue nil)
166
+
167
+ # Layer 2 / VLAN details
168
+ network_lldp[current_iface]['vlan'] = (Integer(vlan.select{|i| i['pvid'] == 'yes' }.first['vlan-id']) rescue nil)
169
+ network_lldp[current_iface]['tagged_vlans'] = (vlan.select{|i| i['pvid'] != 'yes' }.collect{|i| Integer(i['vlan-id']) } rescue nil)
170
+ end
171
+ rescue
172
+ nil
173
+ end
174
+
175
+ else
176
+ output.gsub(/^\s+/,'').lines do |line|
177
+ key, value = line.strip.chomp.squeeze(' ').split(/:\s+/, 2)
178
+
179
+ if key and value
180
+ key.gsub!(/ID$/, '_id')
181
+ key.gsub!(/[\-\s]+/, '_')
182
+ key.gsub!(/([a-z])([A-Z])/, '\1_\2')
183
+ key = key.downcase.strip.to_sym
184
+ value.strip!
185
+ kvs = _format(key,value)
186
+
187
+ kvs.each do |k, v|
188
+ next unless k and v
189
+
190
+ if k == :interface
191
+ current_iface = v.split(',').first.to_sym
192
+ else
193
+ network_lldp[current_iface] = {} unless network_lldp[current_iface]
194
+ network_lldp[current_iface][k] = v
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
201
+
202
+ network_lldp.each do |iface, lldp|
203
+ lldp.each do |key, value|
204
+ next if value.respond_to?(:empty?) and value.empty?
205
+
206
+ Facter.add("lldp_#{key}_#{iface}") do
207
+ setcode { value }
208
+ end
209
+ end
210
+ end
211
+
212
+
213
+ # Bonding Configuration
214
+ if Facter.value("osfamily") == "RedHat"
215
+ interfaces = {}
216
+
217
+ Facter.value('network_interfaces').each do |iface|
218
+ if File.exists?("/etc/sysconfig/network-scripts/ifcfg-#{iface}")
219
+ sysconfig = Hash[File.read("/etc/sysconfig/network-scripts/ifcfg-#{iface}").lines.collect {|line|
220
+ key, value = line.split('=', 2)
221
+ next unless key and value
222
+ [key.downcase.to_sym, value.strip.chomp]
223
+ }]
224
+
225
+
226
+ if sysconfig[:master] and (sysconfig[:slave] == 'yes')
227
+ Facter.add("bonding_master_#{iface}") do
228
+ setcode { sysconfig[:master] }
229
+ end
230
+ elsif not (sysconfig[:slave] == 'yes')
231
+ if sysconfig[:bonding_opts]
232
+ opts = Hash[sysconfig[:bonding_opts].gsub(/(^\"|\"$)/,'').split(/\s+/).collect{ |pair|
233
+ pair.split('=')
234
+ }]
235
+
236
+ opts.each do |key, value|
237
+ Facter.add("bonding_#{key}_#{iface}") do
238
+ setcode { value }
239
+ end
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end
246
+
247
+ rescue Exception => e
248
+ STDERR.puts "#{e.name}: #{e.message}"
249
+
250
+ e.backtrace.each do |b|
251
+ STDERR.puts b
252
+ end
253
+ end
@@ -0,0 +1,17 @@
1
+ if Facter::Util::Resolution.which('onering')
2
+ onering = {}
3
+
4
+ if defined?(Gem)
5
+ if defined?(Gem::Specification)
6
+ if Gem::Specification.respond_to?(:find_by_name)
7
+ onering[:version] = Gem::Specification.find_by_name('onering-client').version.to_s
8
+ end
9
+ end
10
+ end
11
+
12
+ unless onering.empty?
13
+ Facter.add('onering') do
14
+ setcode { onering }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # Onering Facts - OpenVZ Properties
2
+ # provides collection of OpenVZ (host and guest) properties
3
+ #
4
+ require 'json'
5
+
6
+ # get list of OpenVZ container hostnames from the host
7
+ vzlist = Facter::Util::Resolution.exec("vzlist -o hostname | tail -n+2 2> /dev/null")
8
+
9
+ if vzlist
10
+ if not vzlist.empty?
11
+ Facter.add('openvz_containers') do
12
+ setcode do
13
+ vzlist.split("\n").collect{|i| i.strip.chomp }.reject{|i| i.empty? }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,87 @@
1
+ Facter.add('site') do
2
+ setcode do
3
+ if File.size?('/etc/onering/static/site')
4
+ site = File.read('/etc/onering/static/site').strip.chomp
5
+
6
+ else
7
+ if File.exists?('/proc/cmdline')
8
+ site = (File.read('/proc/cmdline').chomp.split(' ').select{|i| i =~ /^domain=/ }.first rescue nil)
9
+ site = site.split('=', 2).last if site
10
+ site = site.split('.').first if site
11
+ end
12
+ end
13
+
14
+ site = nil if ['test', 'hw', 'vm'].include?(site)
15
+
16
+ if site
17
+ site
18
+ else
19
+ Facter.value('fqdn').split('.')[-3].downcase rescue nil
20
+ end
21
+ end
22
+ end
23
+
24
+ Facter.add('environment') do
25
+ setcode do
26
+ env = (Facter.value('fqdn').split('.').first.split('-')[-2].downcase rescue nil)
27
+
28
+ case env
29
+ when 'dev'
30
+ 'development'
31
+ when /(stg|stage)/
32
+ 'staging'
33
+ when 'prod'
34
+ 'production'
35
+ else
36
+ nil
37
+ end
38
+ end
39
+ end
40
+
41
+ Facter.add('slot') do
42
+ setcode do
43
+ slot = Integer(Facter::Util::Resolution.exec("bmc node_number 2> /dev/null")) rescue nil
44
+ slot = nil if slot == 0
45
+ slot
46
+ end
47
+ end
48
+
49
+
50
+ ipmi_ok = (Facter::Util::Resolution.exec("ipmiutil health 2> /dev/null | tail -n1 | grep failed") === nil)
51
+
52
+ if ipmi_ok
53
+ ipmi_lan = Facter::Util::Resolution.exec("ipmitool lan print 1 2> /dev/null")
54
+
55
+ if ipmi_lan
56
+ ipmi_lan_data = {}
57
+
58
+ ipmi_lan.lines.each do |line|
59
+ key, value = line.split(/:/, 2)
60
+ value = value.strip.squeeze(' ').chomp
61
+
62
+ case key
63
+ when /^IP Address/i
64
+ ipmi_lan_data[:ip] = value
65
+
66
+ when /^Subnet Mask/i
67
+ ipmi_lan_data[:netmask] = value
68
+
69
+ when /^MAC Address/i
70
+ ipmi_lan_data[:macaddress] = value.upcase
71
+
72
+ when /^Default Gateway IP/i
73
+ ipmi_lan_data[:gateway] = value
74
+
75
+ when /^SNMP Community String/i
76
+ ipmi_lan_data[:snmp_community] = value
77
+
78
+ end
79
+ end
80
+
81
+ ipmi_lan_data.each do |key, value|
82
+ Facter.add("ipmi_#{key}") do
83
+ setcode { value }
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,25 @@
1
+ # Onering Facts - Service List
2
+ # provides list of certain services that are running on a machine
3
+ #
4
+
5
+
6
+ Facter.add('services') do
7
+ def get_service_list()
8
+ rv = []
9
+ case Facter.value('osfamily')
10
+ when 'Debian'
11
+ rv = IO.popen('find /etc/init.d -maxdepth 1 -type f -executable | cut -d"/" -f4 | sort | uniq').lines
12
+ when 'RedHat'
13
+ rv = IO.popen('chkconfig --list | grep "3:on" | tr "\t" " " | cut -d" " -f1 | sort | uniq').lines
14
+ end
15
+
16
+ rv.collect {|i| i.strip.chomp }.reject{|i| i.empty? }
17
+ end
18
+
19
+ setcode do
20
+ acceptable = (File.read('/etc/onering/services.list').lines.collect{|i| i.strip.chomp }.reject{|i| i.empty? } rescue [])
21
+ actual = get_service_list()
22
+
23
+ (acceptable & actual)
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ Facter.add('boottime') do
2
+ setcode do
3
+ Time.at(Time.now.to_i - Facter.value('uptime_seconds').to_i)
4
+ end
5
+ end
6
+
7
+ Facter.add('kernelarguments') do
8
+ setcode do
9
+ if File.readable?('/proc/cmdline')
10
+ Hash[File.read('/proc/cmdline').split(' ').collect{|i|
11
+ key, value = i.split('=', 2)
12
+ [key.gsub('.','_'), value]
13
+ }]
14
+ else
15
+ nil
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,93 @@
1
+ if Facter::Util::Resolution.which('vgc-monitor')
2
+ virident_cards = []
3
+
4
+ Facter::Util::Resolution.exec("vgc-monitor | grep '^/dev'").to_s.split("\n").each do |card|
5
+ name, partitions, model, status = card.strip.chomp.split(/\s+/)
6
+ card = {
7
+ :name => name,
8
+ :model => model.strip,
9
+ :status => status.downcase,
10
+ :driver => {},
11
+ :partitions => []
12
+ }
13
+
14
+ part = {}
15
+ part_name = nil
16
+ details = Facter::Util::Resolution.exec("vgc-monitor -d #{name}").to_s.split(/\n/).collect{|i| i.strip.split(/\s*:\s*/,2) }
17
+
18
+ details.each_index do |i|
19
+ begin
20
+ detail = details[i]
21
+
22
+ if detail.length == 2
23
+ case detail.first
24
+ when 'vgc-monitor'
25
+ card[:driver][:tool_version] = detail.last
26
+
27
+ # when 'Driver Uptime'
28
+ # card[:driver][:uptime] = detail.last
29
+
30
+ when 'Serial Number'
31
+ card[:serial] = detail.last
32
+
33
+ when 'Temperature'
34
+ card[:temperature] = detail.last.split(' ').first.to_i
35
+
36
+ when 'Rev'
37
+ card[:description] = detail.last
38
+
39
+ when 'Card State Details'
40
+ st = detail.last.downcase
41
+ next if st == 'normal'
42
+ card[:status_detail] = st
43
+
44
+ when 'Action Required'
45
+ action = detail.last.downcase
46
+ next if action == 'none'
47
+ card[:action_required] = action
48
+
49
+ # partitions
50
+ when 'Mode'
51
+ part[part_name][:mode] = detail.last
52
+
53
+ when 'Total Flash Bytes'
54
+ part[part_name][:throughput] ||= {}
55
+ part[part_name][:throughput][:read_bytes] = detail.last.split(' ').first.to_i
56
+ part[part_name][:throughput][:write_bytes] = details[i+1].first.split(' ').first.to_i
57
+
58
+ when 'Remaining Life'
59
+ part[part_name][:life_remaining] = detail.last.delete('%').to_f
60
+
61
+ when 'Partition State'
62
+ part[part_name][:state] = detail.last.downcase
63
+
64
+ when 'Flash Reserves Left'
65
+ part[part_name][:reserves_remaining] = detail.last.delete('%').to_f
66
+
67
+ end
68
+ else
69
+ if detail.first.to_s =~ /^\/dev\/(vgc[a-z]+[0-9]+)\s+([0-9]+) [KMGTPEZY]?i?B\s+([a-z]+)$/
70
+ card[:partitions] << part[part_name] unless part_name.nil?
71
+
72
+ part_name = $1
73
+ part[part_name] ||= {}
74
+ part[part_name][:name] = part_name
75
+ part[part_name][:size] = ($2.to_i * (1024 ** 3))
76
+ part[part_name][:raid_enabled] = ($3 == 'enabled')
77
+ end
78
+ end
79
+ rescue
80
+ next
81
+ end
82
+ end
83
+
84
+ card[:partitions] << part[part_name] unless part_name.nil?
85
+ virident_cards << card
86
+ end
87
+
88
+ Facter.add("virident") do
89
+ setcode do
90
+ virident_cards
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,32 @@
1
+ # Onering Facts - Xen Properties
2
+ # provides collection of Xen (host and guest) properties
3
+ #
4
+ require 'json'
5
+
6
+ # get list of xen guest UUIDs
7
+ xen = Facter::Util::Resolution.exec("xm list --long 2> /dev/null | grep uuid")
8
+
9
+ if xen
10
+ xen_uuid = []
11
+
12
+ xen.lines.each do |line|
13
+ xen_uuid << line.strip.chomp.split(/[\s+\)]/).last
14
+ end
15
+
16
+ if not xen_uuid.empty?
17
+ Facter.add('xen_guests') do
18
+ setcode { xen_uuid.reject{|i| i =~ /^0{8}/ } }
19
+ end
20
+ end
21
+ end
22
+
23
+ # current xen guest: uuid
24
+ if File.exists?("/sys/hypervisor/uuid")
25
+ uuid = (File.read("/sys/hypervisor/uuid").strip.chomp rescue nil)
26
+
27
+ if uuid and not uuid =~ /^0{8}/
28
+ Facter.add("xen_uuid") do
29
+ setcode { uuid }
30
+ end
31
+ end
32
+ end