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
@@ -0,0 +1,174 @@
1
+ if Facter::Util::Resolution.which("zpool")
2
+ def sz_to_bytes(sz)
3
+ case sz[-1].chr
4
+ when 'K'
5
+ rv = sz[0..-2].to_f * (1024)
6
+ when 'M'
7
+ rv = sz[0..-2].to_f * (1024 ** 2)
8
+ when 'G'
9
+ rv = sz[0..-2].to_f * (1024 ** 3)
10
+ when 'T'
11
+ rv = sz[0..-2].to_f * (1024 ** 4)
12
+ when 'P'
13
+ rv = sz[0..-2].to_f * (1024 ** 5)
14
+ when 'E'
15
+ rv = sz[0..-2].to_f * (1024 ** 6)
16
+ when 'Z'
17
+ rv = sz[0..-2].to_f * (1024 ** 7)
18
+ when 'Y'
19
+ rv = sz[0..-2].to_f * (1024 ** 8)
20
+ else
21
+ rv = sz[0..-2].to_f
22
+ end
23
+
24
+ rv.to_i
25
+ end
26
+
27
+ zfs = {
28
+ :filesystems => [],
29
+ :pools => [],
30
+ :snapshots => []
31
+ }
32
+
33
+
34
+ # =============================================================================
35
+ # POOLS
36
+ Facter::Util::Resolution.exec("zpool list -H").to_s.lines.each do |line|
37
+ pool, size, allocated, free, used_perc, dedup, health, altroot = line.strip.split(/\s+/)
38
+ zfs_pool = {
39
+ :name => pool,
40
+ :status => health.downcase,
41
+ :size => {
42
+ :total => sz_to_bytes(size),
43
+ :allocated => sz_to_bytes(allocated),
44
+ :free => sz_to_bytes(free),
45
+ :used => (sz_to_bytes(size) - sz_to_bytes(free)),
46
+ :percent_used => used_perc.delete('%').to_f
47
+ },
48
+ :deduplication_factor => dedup.delete('x').to_f,
49
+ :virtual_devices => {}
50
+ }
51
+
52
+ zfs_pool[:mountpoint] = altroot if altroot != '-'
53
+ vdevs = {}
54
+ current_vdev = nil
55
+
56
+ # get vdevs/devices
57
+ Facter::Util::Resolution.exec("zpool status -v #{pool}").to_s.lines.each do |line|
58
+ if line =~ /^\s*([a-z]+):\s+(.*)$/
59
+ case $1
60
+ when 'scan'
61
+ # scrub output
62
+ if $2 =~ /scrub repaired ([0-9]+) in ((?:[0-9]+d)?(?:[0-9]+h)?(?:[0-9]+m)) with ([0-9]+) errors on (.*)$/
63
+ zfs_pool[:scrub] ||= {}
64
+ zfs_pool[:scrub][:repaired] = $1.to_i
65
+ zfs_pool[:scrub][:errors] = $3.to_i
66
+ zfs_pool[:scrub][:completed_at] = DateTime.parse($4).strftime("%Y-%m-%d %H:%M:%S %z")
67
+ end
68
+ end
69
+
70
+ # vdev line
71
+ elsif line =~ /^\t ([a-z0-9]+)(?:-([0-9]+))\s+([A-Z]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s*$/
72
+ current_vdev = "#{$1}-#{$2}"
73
+ vdevs[current_vdev] = {
74
+ :name => "#{$1}-#{$2}",
75
+ :type => $1.to_sym,
76
+ :number => $2.to_i,
77
+ :status => $3.downcase,
78
+ :errors => {
79
+ :read => $4.to_i,
80
+ :write => $5.to_i,
81
+ :checksum => $6.to_i
82
+ },
83
+ :devices => []
84
+ }
85
+
86
+ # device line
87
+ elsif line =~ /^\t ([a-zA-Z0-9\-\_]+)\s+([A-Z]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s*$/
88
+ if File.symlink?("/dev/disk/by-id/#{$1}")
89
+ dev = File.expand_path(File.readlink("/dev/disk/by-id/#{$1}"), "/dev/disk/by-id")
90
+ elsif File.exists?("/dev/#{$1}")
91
+ dev = "/dev/#{$1}"
92
+ end
93
+
94
+ vdevs[current_vdev][:devices] << {
95
+ :name => $1,
96
+ :device => dev,
97
+ :errors => {
98
+ :read => $2.to_i,
99
+ :write => $3.to_i,
100
+ :checksum => $4.to_i
101
+ }
102
+ }
103
+ end
104
+ end
105
+
106
+ vdevs.each do |name, devs|
107
+ zfs_pool[:virtual_devices][name.split('-').first.to_sym] ||= []
108
+ zfs_pool[:virtual_devices][name.split('-').first.to_sym] << devs
109
+ end
110
+
111
+ zfs[:pools] << zfs_pool
112
+ end
113
+
114
+
115
+
116
+
117
+ # =============================================================================
118
+ # FILESYSTEMS
119
+ Facter::Util::Resolution.exec("zfs list -H").to_s.lines.each do |line|
120
+ filesystem, used, available, referenced, mountpoint = line.strip.split(/\s+/)
121
+
122
+ zfs_filesystem = {
123
+ :name => filesystem,
124
+ :mountpoint => mountpoint,
125
+ :properties => {},
126
+ :snapshots => [],
127
+ :size => {
128
+ :used => sz_to_bytes(used),
129
+ :free => sz_to_bytes(available)
130
+ }
131
+ }
132
+
133
+ # get properties
134
+ Facter::Util::Resolution.exec("zfs get all -H #{filesystem}").to_s.lines.each do |line|
135
+ fs, property, value, source = line.strip.split(/\t/)
136
+
137
+ value = case value
138
+ when 'off' then false
139
+ when 'on' then true
140
+ when 'none' then nil
141
+ when /^[0-9]+(?:\.[0-9]+)?[KMGTPEZY]$/ then sz_to_bytes(value)
142
+ when /^[0-9]+$/ then value.to_i
143
+ when /^[0-9]+\.[0-9]+$/ then value.to_f
144
+ when /^[0-9]+\.[0-9]+x$/ then value.delete('x').to_f
145
+ else value
146
+ end
147
+
148
+ zfs_filesystem[:properties][property.to_sym] = value
149
+ end
150
+
151
+ zfs[:filesystems] << zfs_filesystem
152
+ end
153
+
154
+
155
+ # =============================================================================
156
+ # SNAPSHOTS
157
+ Facter::Util::Resolution.exec("zfs list -H -t snapshot").to_s.lines.each do |line|
158
+ name, used, available, referenced, mountpoint = line.strip.split(/\s+/)
159
+ mountpoint = nil if mountpoint == '-'
160
+
161
+ zfs[:snapshots] << {
162
+ :name => name,
163
+ :used => sz_to_bytes(used),
164
+ :available => sz_to_bytes(available),
165
+ :referenced => sz_to_bytes(referenced),
166
+ :mountpoint => mountpoint
167
+ }
168
+ end
169
+
170
+
171
+ Facter.add("zfs") do
172
+ setcode{ zfs }
173
+ end
174
+ end
@@ -0,0 +1,15 @@
1
+ # Onering Collector - Chef Properties plugin
2
+ # provides collection of Chef metadata
3
+ #
4
+ report do
5
+ chef = {
6
+ :name => Facter.value('chef_nodename'),
7
+ :environment => Facter.value('chef_environment'),
8
+ :@run_list => Facter.value('chef_runlist'),
9
+ :enabled => Facter.value('chef_enabled'),
10
+ :version => Facter.value('chef_version'),
11
+ :last_ran_at => (Time.at(Facter.value('chef_lastrun')).strftime('%Y-%m-%d %H:%M:%S %z') rescue nil)
12
+ }.reject{|k,v| v === nil }
13
+
14
+ property :chef, chef unless chef.empty?
15
+ end
@@ -0,0 +1,51 @@
1
+ # Onering Collector - Facter Properties plugin
2
+ # provides a configurable list of Facter facts that should be sent to the
3
+ # Onering API
4
+ #
5
+ # Properties defined in /etc/onering/facter.list
6
+ #
7
+
8
+ report do
9
+ def cleanup_dirty_values(k, v)
10
+ return case k
11
+ when 'mbserial' then v.to_s.gsub(/(^\.+|\.+$)/,'').gsub('.','-')
12
+ else (v.strip.chomp rescue v)
13
+ end
14
+ end
15
+
16
+ if defined?(Facter)
17
+ # get a list of Facter attributes to list
18
+ local_list = File.join(File.dirname(File.dirname(File.dirname(__FILE__))),'etc','facter.list')
19
+
20
+ facts = [
21
+ local_list,
22
+ "/etc/onering/facter.list"
23
+ ].collect{|file|
24
+ IO.readlines(file) if File.exists?(file)
25
+ }.flatten.compact.uniq
26
+
27
+
28
+ facts.each do |line|
29
+ Onering::Logger.debug3("-> Facter Line: #{line.inspect}", "Onering::Reporter")
30
+
31
+ # strip whitespace/kill newline
32
+ line.strip!
33
+ line.chomp!
34
+ next if line.empty?
35
+ line = line.downcase
36
+
37
+ unless line =~ /^#/
38
+ begin
39
+ line = line.split(':')
40
+ key = (line.length == 1 ? line.first : line.last)
41
+ val = cleanup_dirty_values(key, Facter.value(line.first))
42
+
43
+ property(key.to_sym, val)
44
+ rescue Exception => e
45
+ Onering::Logger.debug(e.message, "onering-report-plugins/properties_facter/#{e.class.name}")
46
+ next
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,8 @@
1
+ # Onering Collector - HAProxy
2
+ # provides data on HAProxy services
3
+ #
4
+
5
+ report do
6
+ haproxy = Facter.value('haproxy')
7
+ property :@haproxy, haproxy unless haproxy.nil?
8
+ end
@@ -0,0 +1,10 @@
1
+ # Onering Collector - IPMI plugin
2
+ # provides collection of IPMI data using vendor tools
3
+ #
4
+
5
+ report do
6
+ property :ipmi_ip, Facter.value('ipmi_ip')
7
+ property :ipmi_netmask, Facter.value('ipmi_netmask')
8
+ property :ipmi_gateway, Facter.value('ipmi_gateway')
9
+ property :ipmi_macaddress, Facter.value('ipmi_macaddress')
10
+ end
@@ -0,0 +1,63 @@
1
+ report do
2
+ interfaces = {}
3
+ ips = []
4
+
5
+ Facter.value('network_interfaces').each do |iface|
6
+ iface = iface.to_sym
7
+ next if [:dummy0, :lo, :sit0].include?(iface)
8
+ interfaces[iface] ||= {}
9
+
10
+ mac = (Facter.value("macaddress_#{iface}").upcase rescue nil)
11
+ mtu = (Integer(Facter.value("mtu_#{iface}")) rescue nil)
12
+
13
+ interfaces[iface][:name] = iface
14
+ interfaces[iface][:mac] = mac if mac
15
+ interfaces[iface][:mtu] = mtu if mtu
16
+
17
+ ips << Facter.value("ipaddress_#{iface}")
18
+
19
+ addresses = [{
20
+ :ip => Facter.value("ipaddress_#{iface}"),
21
+ :netmask => Facter.value("netmask_#{iface}")
22
+ }.reject{|k,v| v.nil? }]
23
+
24
+ interfaces[iface][:addresses] = addresses unless addresses.empty? or addresses.reject{|i| i.empty? }.empty?
25
+
26
+ # LLDP autodiscovery
27
+ switch = {
28
+ :name => Facter.value("lldp_switch_#{iface}"),
29
+ :port => Facter.value("lldp_port_#{iface}"),
30
+ :speed => Facter.value("lldp_speed_#{iface}"),
31
+ :duplex => Facter.value("lldp_duplex_#{iface}"),
32
+ :port_name => Facter.value("lldp_port_name_#{iface}"),
33
+ :port_mac => Facter.value("lldp_port_mac_#{iface}"),
34
+ :ip => Facter.value("lldp_management_ip_#{iface}"),
35
+ :chassis_mac => Facter.value("lldp_chassis_mac_#{iface}"),
36
+ :vlan => Facter.value("lldp_vlan_#{iface}"),
37
+ :tagged_vlans => Facter.value("lldp_tagged_vlans_#{iface}")
38
+ }.reject{|k,v| v.nil? }
39
+
40
+
41
+ # Bonding configuration
42
+
43
+ # slaves
44
+ master = Facter.value("bonding_master_#{iface}")
45
+ interfaces[iface][:master] = master if master
46
+
47
+ # masters
48
+ bond = {
49
+ :arp_ip_target => Facter.value("bonding_arp_ip_target_#{iface}")
50
+ }.reject {|k,v| v.nil? }
51
+
52
+
53
+ # conditionally add applicable subsections
54
+ interfaces[iface][:switch] = switch unless switch.empty?
55
+ interfaces[iface][:bonding] = bond unless bond.empty?
56
+ end
57
+
58
+ property :network, {
59
+ :@ip => ips,
60
+ :@interfaces => interfaces.values,
61
+ :@sockets => Facter.value('netstat')
62
+ }
63
+ end
@@ -0,0 +1,62 @@
1
+ # Onering Collector - Ohai Properties plugin
2
+ # provides a configurable list of Ohai attributes that should be sent to the
3
+ # Onering API
4
+ #
5
+ # Properties defined in /etc/onering/ohai.list
6
+ #
7
+
8
+ report do
9
+ if defined?(Ohai)
10
+ def cleanup_dirty_values(k, v)
11
+ return case k
12
+ when 'mbserial' then v.to_s.gsub(/(^\.+|\.+$)/,'').gsub('.','-')
13
+ else v
14
+ end
15
+ end
16
+
17
+ # get a list of ohai attributes to list
18
+ if File.exists?("/etc/onering/ohai.list")
19
+ IO.readlines("/etc/onering/ohai.list").each do |line|
20
+ # trip whitespace/kill newline
21
+ line.strip!
22
+ line.chomp!
23
+ next if line.empty?
24
+ line = line.downcase
25
+
26
+ unless line =~ /^#/
27
+ begin
28
+ parts = line.split(".")
29
+ root = @ohai
30
+
31
+ parts.each do |part|
32
+ part = part.split(':')
33
+ key = part.first
34
+ alt = part.last
35
+
36
+ if root[key]
37
+ if root[key].is_a?(Hash)
38
+ root = root[key]
39
+ next
40
+ else
41
+ val = [*root[key]].collect{|i| i.strip.chomp rescue i }
42
+ val = val.first if val.length == 1
43
+ val = cleanup_dirty_values(alt, val)
44
+ val.strip! if val.is_a?(String)
45
+
46
+ # set property value
47
+ property alt, val
48
+ break
49
+ end
50
+ else
51
+ break
52
+ end
53
+ end
54
+ rescue Exception => e
55
+ Onering::Logger.warn("Error occurred gathering Ohai facts: #{e.class.name} - #{e.message}", "onering-report-plugins/properties_ohai")
56
+ next
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,12 @@
1
+ # Onering Collector - OpenVZ Properties plugin
2
+ # provides collection of OpenVZ metadata
3
+ #
4
+ report do
5
+ vz_containers = Facter.value('openvz_containers')
6
+ vz = {}
7
+
8
+ # OpenVZ host
9
+ vz[:@guests] = vz_containers if vz_containers
10
+
11
+ property :openvz, vz unless vz.empty?
12
+ end
@@ -0,0 +1,10 @@
1
+ # Onering Collector - Physical Properties plugin
2
+ # provides collection of hardware location data using vendor tools
3
+ #
4
+
5
+ report do
6
+ property :site, Facter.value('site')
7
+ property :environment, Facter.value('environment')
8
+ property :slot, Facter.value('slot')
9
+ property :virtual, (Facter.value('is_virtual').to_s == 'true' ? true : false)
10
+ end
@@ -0,0 +1,6 @@
1
+ # Onering Collector - Service List
2
+ # provides list of certain services that are running on a machine
3
+ #
4
+ report do
5
+ property :@services, Facter.value('services')
6
+ end
@@ -0,0 +1,30 @@
1
+ report do
2
+ # ------------------------------------------------------------------------------
3
+ # cpu
4
+ #
5
+ stats_cpu = {
6
+ :count => 0,
7
+ :processors => []
8
+ }
9
+
10
+ current_cpu = nil
11
+
12
+ File.open("/proc/cpuinfo").each do |line|
13
+ case line
14
+ when /processor\s+:\s(.+)/
15
+ current_cpu = $1.to_i
16
+ stats_cpu[:count] += 1
17
+ stats_cpu[:processors][current_cpu] = {
18
+ :number => current_cpu
19
+ }
20
+ when /cpu MHz\s+:\s(.+)/
21
+ stats_cpu[:processors][current_cpu][:speed] = $1.to_f
22
+ end
23
+ end
24
+
25
+ stat :cpu, ({
26
+ 'count' => Facter.value('processorcount').to_i,
27
+ 'physical' => Facter.value('physicalprocessorcount').to_i,
28
+ 'speed' => stats_cpu[:processors].collect{|i| i[:speed] }.compact.uniq.sort{|a,b| a.to_f <=> b.to_f }.last.to_f
29
+ } rescue nil)
30
+ end
@@ -0,0 +1,35 @@
1
+ report do
2
+ # ------------------------------------------------------------------------------
3
+ # block devices
4
+ #
5
+ blocks = []
6
+
7
+ Facter.value('blockdevices').to_s.split(/\W+/).each do |dev|
8
+
9
+ block = {
10
+ :name => dev,
11
+ :device => (File.exists?("/dev/#{dev}") ? "/dev/#{dev}" : nil)
12
+ }
13
+
14
+ if File.directory?("/sys/block/#{dev}")
15
+ block[:vendor] = (%x{cat /sys/block/#{dev}/device/vendor 2> /dev/null}.to_s.strip.chomp rescue nil)
16
+ block[:model] = (%x{cat /sys/block/#{dev}/device/model 2> /dev/null}.to_s.strip.chomp rescue nil)
17
+ block[:size] = ((Integer(%x{cat /sys/block/#{dev}/size 2> /dev/null}.to_s.strip.chomp) * 512) rescue nil)
18
+ block[:removable] = (%x{cat /sys/block/#{dev}/removable 2> /dev/null}.to_s.chomp.strip == '1' rescue nil)
19
+ block[:readonly] = (%x{cat /sys/block/#{dev}/ro 2> /dev/null}.to_s.chomp.strip == '1' rescue nil)
20
+ block[:solidstate] = (%x{cat /sys/block/#{dev}/queue/rotational 2> /dev/null}.to_s.chomp.strip == '0' rescue nil)
21
+ block[:sectorsize] = {}
22
+
23
+ %w{
24
+ logical
25
+ physical
26
+ }.each do |s|
27
+ block[:sectorsize][s.to_sym] = (Integer(%x{cat /sys/block/#{dev}/queue/#{s}_block_size 2> /dev/null}.chomp.strip) rescue nil)
28
+ end
29
+ end
30
+
31
+ blocks << block.compact
32
+ end
33
+
34
+ stat 'disk.@block', blocks
35
+ end
@@ -0,0 +1,73 @@
1
+ report do
2
+ # ------------------------------------------------------------------------------
3
+ # LVM
4
+ #
5
+ vg = {}
6
+
7
+ # volume groups
8
+ Facter::Util::Resolution.exec("vgdisplay -c 2> /dev/null").to_s.lines.each do |line|
9
+ line = line.strip.chomp.split(':')
10
+
11
+ vg[line[0]] = {
12
+ :name => line[0],
13
+ :uuid => line[16],
14
+ :size => (line[11].to_i*1024),
15
+ :extents => {
16
+ :size => (line[12].to_i * 1024),
17
+ :total => line[13].to_i,
18
+ :allocated => line[14].to_i,
19
+ :free => line[15].to_i
20
+ },
21
+ :volumes => [],
22
+ :disks => []
23
+ }
24
+ end
25
+
26
+ # logical volumes
27
+ Facter::Util::Resolution.exec("lvdisplay -c 2> /dev/null").to_s.lines.each do |line|
28
+ line = line.strip.chomp.split(':')
29
+
30
+ unless vg[line[1]].nil?
31
+ vg[line[1]][:volumes] << {
32
+ :name => line[0],
33
+ :sectors => line[6].to_i,
34
+ :extents => line[7].to_i,
35
+ :size => (vg[line[1]][:extents][:size] * line[7].to_i)
36
+ }
37
+ end
38
+ end
39
+
40
+
41
+ # physical volumes
42
+ Facter::Util::Resolution.exec("pvdisplay -c 2> /dev/null").to_s.lines.each do |line|
43
+ line = line.strip.chomp.split(':')
44
+
45
+ unless vg[line[1]].nil?
46
+ vg[line[1]][:disks] << {
47
+ :name => line[0],
48
+ :uuid => line[11],
49
+ :size => (line[8].to_i * (line[7].to_i * 1024)), # See Note 1 below
50
+ :extents => {
51
+ :size => (line[7].to_i * 1024),
52
+ :total => line[8].to_i,
53
+ :allocated => line[10].to_i,
54
+ :free => line[9].to_i
55
+ }
56
+ }
57
+
58
+ # the output of certain versions of pvdisplay -c reports a blatantly incorrect
59
+ # physical volume total size. the workaround is to calculate the actual total size
60
+ # via (total extents * extent size)
61
+ #
62
+ # this may or may not be GPT related
63
+ #
64
+ end
65
+ end
66
+
67
+ lvm = {}
68
+ lvm = {
69
+ :groups => vg.values
70
+ } unless vg.values.empty?
71
+
72
+ stat 'disk.@lvm', lvm unless lvm.empty?
73
+ end
@@ -0,0 +1,46 @@
1
+ report do
2
+ # ------------------------------------------------------------------------------
3
+ # mounts
4
+ #
5
+ mounts = {}
6
+ current_dev = nil
7
+
8
+ uuids = Hash[Dir["/dev/disk/by-uuid/*"].collect{|i|
9
+ [File.expand_path(File.readlink(i), File.dirname(i)), File.basename(i)]
10
+ }]
11
+
12
+ File.read("/etc/mtab").lines.each do |line|
13
+ dev,mount,fstype,flags,dump,pass = line.split(/\s+/)
14
+
15
+ mounts[dev] = {
16
+ :mount => mount,
17
+ :device => dev,
18
+ :filesystem => fstype,
19
+ :flags => flags.split(/\s*,\s*/),
20
+ :uuid => uuids[dev]
21
+ }.compact
22
+ end
23
+
24
+ # logical space utilization
25
+ Facter::Util::Resolution.exec("df 2> /dev/null").to_s.lines.each do |line|
26
+ next if line =~ /^Filesystem/
27
+ parts = line.split(/\s+/)
28
+
29
+ if parts.length == 1
30
+ current_dev = parts.first
31
+ next
32
+
33
+ else
34
+ dev,kblk,used,free,percent,mount = parts
35
+ dev = current_dev if dev.empty?
36
+ next unless mounts[dev] and mounts[dev].is_a?(Hash)
37
+
38
+ mounts[dev][:used] = (used.to_i * 1024)
39
+ mounts[dev][:available] = (free.to_i * 1024)
40
+ mounts[dev][:total] = (mounts[dev][:available] + mounts[dev][:used])
41
+ mounts[dev][:percent_used] = percent.delete('%').to_i
42
+ end
43
+ end
44
+
45
+ stat 'disk.@mounts', (Hash[mounts.select{|k,v| k =~ /^\/dev\/((h|s|xv|v)d|mapper|vgc)/ }].values rescue nil)
46
+ end
@@ -0,0 +1,3 @@
1
+ report do
2
+ stat 'disk.@smart', Facter.value('smart')
3
+ end