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,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