ohai 18.2.6 → 19.0.3
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.
- checksums.yaml +4 -4
- data/Gemfile +28 -28
- data/LICENSE +201 -201
- data/bin/ohai +25 -25
- data/lib/ohai/application.rb +189 -189
- data/lib/ohai/common/dmi.rb +167 -167
- data/lib/ohai/config.rb +51 -51
- data/lib/ohai/dsl/plugin/versionvii.rb +203 -203
- data/lib/ohai/dsl/plugin.rb +232 -232
- data/lib/ohai/dsl.rb +22 -22
- data/lib/ohai/exception.rb +36 -36
- data/lib/ohai/hints.rb +68 -68
- data/lib/ohai/loader.rb +178 -178
- data/lib/ohai/log.rb +34 -34
- data/lib/ohai/mash.rb +22 -22
- data/lib/ohai/mixin/alibaba_metadata.rb +83 -83
- data/lib/ohai/mixin/azure_metadata.rb +105 -105
- data/lib/ohai/mixin/chef_utils_wiring.rb +52 -52
- data/lib/ohai/mixin/command.rb +4 -4
- data/lib/ohai/mixin/constant_helper.rb +55 -55
- data/lib/ohai/mixin/dmi_decode.rb +54 -54
- data/lib/ohai/mixin/do_metadata.rb +48 -48
- data/lib/ohai/mixin/ec2_metadata.rb +264 -270
- data/lib/ohai/mixin/gce_metadata.rb +79 -79
- data/lib/ohai/mixin/http_helper.rb +64 -64
- data/lib/ohai/mixin/json_helper.rb +36 -36
- data/lib/ohai/mixin/network_helper.rb +92 -92
- data/lib/ohai/mixin/oci_metadata.rb +60 -60
- data/lib/ohai/mixin/os.rb +128 -128
- data/lib/ohai/mixin/scaleway_metadata.rb +51 -51
- data/lib/ohai/mixin/seconds_to_human.rb +52 -52
- data/lib/ohai/mixin/shell_out.rb +51 -51
- data/lib/ohai/mixin/softlayer_metadata.rb +74 -74
- data/lib/ohai/mixin/string.rb +31 -31
- data/lib/ohai/mixin/train_helpers.rb +36 -36
- data/lib/ohai/mixin/which.rb +39 -39
- data/lib/ohai/plugin_config.rb +47 -47
- data/lib/ohai/plugins/aix/kernel.rb +50 -50
- data/lib/ohai/plugins/aix/memory.rb +37 -37
- data/lib/ohai/plugins/aix/network.rb +142 -142
- data/lib/ohai/plugins/aix/platform.rb +30 -30
- data/lib/ohai/plugins/aix/uptime.rb +54 -54
- data/lib/ohai/plugins/aix/virtualization.rb +154 -154
- data/lib/ohai/plugins/alibaba.rb +72 -72
- data/lib/ohai/plugins/azure.rb +154 -154
- data/lib/ohai/plugins/bsd/virtualization.rb +121 -121
- data/lib/ohai/plugins/c.rb +178 -178
- data/lib/ohai/plugins/chef.rb +50 -50
- data/lib/ohai/plugins/cloud.rb +379 -379
- data/lib/ohai/plugins/command.rb +26 -26
- data/lib/ohai/plugins/cpu.rb +642 -642
- data/lib/ohai/plugins/darwin/hardware.rb +99 -99
- data/lib/ohai/plugins/darwin/memory.rb +62 -62
- data/lib/ohai/plugins/darwin/network.rb +207 -207
- data/lib/ohai/plugins/darwin/platform.rb +40 -40
- data/lib/ohai/plugins/darwin/virtualization.rb +104 -104
- data/lib/ohai/plugins/digital_ocean.rb +67 -67
- data/lib/ohai/plugins/dmi.rb +134 -134
- data/lib/ohai/plugins/docker.rb +58 -58
- data/lib/ohai/plugins/dragonflybsd/memory.rb +60 -60
- data/lib/ohai/plugins/dragonflybsd/network.rb +128 -128
- data/lib/ohai/plugins/dragonflybsd/platform.rb +28 -28
- data/lib/ohai/plugins/ec2.rb +148 -148
- data/lib/ohai/plugins/elixir.rb +36 -36
- data/lib/ohai/plugins/erlang.rb +60 -60
- data/lib/ohai/plugins/eucalyptus.rb +86 -86
- data/lib/ohai/plugins/filesystem.rb +753 -753
- data/lib/ohai/plugins/fips.rb +36 -36
- data/lib/ohai/plugins/freebsd/memory.rb +60 -60
- data/lib/ohai/plugins/freebsd/network.rb +128 -128
- data/lib/ohai/plugins/freebsd/platform.rb +28 -28
- data/lib/ohai/plugins/gce.rb +89 -89
- data/lib/ohai/plugins/go.rb +34 -34
- data/lib/ohai/plugins/groovy.rb +38 -38
- data/lib/ohai/plugins/grub2.rb +40 -40
- data/lib/ohai/plugins/habitat.rb +73 -73
- data/lib/ohai/plugins/haskell.rb +96 -96
- data/lib/ohai/plugins/hostname.rb +133 -133
- data/lib/ohai/plugins/init_package.rb +26 -26
- data/lib/ohai/plugins/java.rb +78 -78
- data/lib/ohai/plugins/kernel.rb +292 -292
- data/lib/ohai/plugins/keys.rb +27 -27
- data/lib/ohai/plugins/languages.rb +26 -26
- data/lib/ohai/plugins/libvirt.rb +114 -114
- data/lib/ohai/plugins/linode.rb +73 -73
- data/lib/ohai/plugins/linux/block_device.rb +48 -48
- data/lib/ohai/plugins/linux/hostnamectl.rb +34 -34
- data/lib/ohai/plugins/linux/interrupts.rb +84 -83
- data/lib/ohai/plugins/linux/ipc.rb +52 -52
- data/lib/ohai/plugins/linux/livepatch.rb +38 -38
- data/lib/ohai/plugins/linux/lsb.rb +46 -46
- data/lib/ohai/plugins/linux/lspci.rb +80 -80
- data/lib/ohai/plugins/linux/machineid.rb +36 -36
- data/lib/ohai/plugins/linux/mdadm.rb +120 -120
- data/lib/ohai/plugins/linux/memory.rb +106 -106
- data/lib/ohai/plugins/linux/network.rb +879 -879
- data/lib/ohai/plugins/linux/os_release.rb +38 -38
- data/lib/ohai/plugins/linux/platform.rb +314 -314
- data/lib/ohai/plugins/linux/selinux.rb +69 -69
- data/lib/ohai/plugins/linux/sessions.rb +54 -54
- data/lib/ohai/plugins/linux/sysctl.rb +39 -39
- data/lib/ohai/plugins/linux/systemd_paths.rb +36 -36
- data/lib/ohai/plugins/linux/tc.rb +61 -61
- data/lib/ohai/plugins/linux/virtualization.rb +300 -300
- data/lib/ohai/plugins/lua.rb +39 -39
- data/lib/ohai/plugins/mono.rb +50 -50
- data/lib/ohai/plugins/netbsd/memory.rb +99 -99
- data/lib/ohai/plugins/netbsd/network.rb +122 -122
- data/lib/ohai/plugins/netbsd/platform.rb +28 -28
- data/lib/ohai/plugins/network.rb +186 -186
- data/lib/ohai/plugins/nodejs.rb +40 -40
- data/lib/ohai/plugins/oci.rb +94 -94
- data/lib/ohai/plugins/ohai.rb +29 -29
- data/lib/ohai/plugins/ohai_time.rb +26 -26
- data/lib/ohai/plugins/openbsd/memory.rb +99 -99
- data/lib/ohai/plugins/openbsd/network.rb +122 -122
- data/lib/ohai/plugins/openbsd/platform.rb +28 -28
- data/lib/ohai/plugins/openstack.rb +84 -84
- data/lib/ohai/plugins/os.rb +55 -55
- data/lib/ohai/plugins/packages.rb +234 -234
- data/lib/ohai/plugins/passwd.rb +104 -104
- data/lib/ohai/plugins/perl.rb +45 -45
- data/lib/ohai/plugins/php.rb +52 -52
- data/lib/ohai/plugins/platform.rb +41 -41
- data/lib/ohai/plugins/powershell.rb +82 -82
- data/lib/ohai/plugins/ps.rb +35 -35
- data/lib/ohai/plugins/python.rb +43 -43
- data/lib/ohai/plugins/rackspace.rb +177 -177
- data/lib/ohai/plugins/root_group.rb +41 -41
- data/lib/ohai/plugins/rpm.rb +121 -121
- data/lib/ohai/plugins/ruby.rb +66 -66
- data/lib/ohai/plugins/rust.rb +34 -34
- data/lib/ohai/plugins/scala.rb +38 -38
- data/lib/ohai/plugins/scaleway.rb +58 -58
- data/lib/ohai/plugins/scsi.rb +52 -52
- data/lib/ohai/plugins/shard.rb +142 -142
- data/lib/ohai/plugins/shells.rb +32 -32
- data/lib/ohai/plugins/softlayer.rb +48 -48
- data/lib/ohai/plugins/solaris2/dmi.rb +191 -191
- data/lib/ohai/plugins/solaris2/memory.rb +32 -32
- data/lib/ohai/plugins/solaris2/network.rb +192 -192
- data/lib/ohai/plugins/solaris2/platform.rb +58 -58
- data/lib/ohai/plugins/solaris2/virtualization.rb +90 -90
- data/lib/ohai/plugins/ssh_host_key.rb +84 -84
- data/lib/ohai/plugins/sysconf.rb +46 -46
- data/lib/ohai/plugins/timezone.rb +45 -45
- data/lib/ohai/plugins/train.rb +35 -35
- data/lib/ohai/plugins/uptime.rb +95 -95
- data/lib/ohai/plugins/virtualbox.rb +197 -197
- data/lib/ohai/plugins/vmware.rb +109 -109
- data/lib/ohai/plugins/windows/dmi.rb +95 -95
- data/lib/ohai/plugins/windows/drivers.rb +52 -52
- data/lib/ohai/plugins/windows/memory.rb +39 -39
- data/lib/ohai/plugins/windows/network.rb +222 -222
- data/lib/ohai/plugins/windows/platform.rb +34 -34
- data/lib/ohai/plugins/windows/system_enclosure.rb +29 -29
- data/lib/ohai/plugins/windows/virtualization.rb +45 -45
- data/lib/ohai/plugins/zpools.rb +94 -94
- data/lib/ohai/provides_map.rb +208 -208
- data/lib/ohai/runner.rb +128 -126
- data/lib/ohai/system.rb +258 -258
- data/lib/ohai/train_transport.rb +29 -29
- data/lib/ohai/util/file_helper.rb +6 -6
- data/lib/ohai/util/ip_helper.rb +56 -56
- data/lib/ohai/util/win32.rb +47 -47
- data/lib/ohai/version.rb +23 -23
- data/lib/ohai.rb +23 -23
- data/ohai.gemspec +35 -35
- metadata +9 -15
@@ -1,753 +1,753 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Phil Dibowitz <phil@ipom.com>
|
3
|
-
# Author:: Adam Jacob <adam@chef.io>
|
4
|
-
# Author:: Kurt Yoder (ktyopscode@yoderhome.com)
|
5
|
-
# Author:: Deepali Jagtap (<deepali.jagtap@clogeny.com>)
|
6
|
-
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
7
|
-
# Author:: Isa Farnik (<isa@chef.io>)
|
8
|
-
# Author:: James Gartrell (<jgartrel@gmail.com>)
|
9
|
-
# Copyright:: Copyright (c) Chef Software Inc.
|
10
|
-
# Copyright:: Copyright (c) 2015 Facebook, Inc.
|
11
|
-
# License:: Apache License, Version 2.0
|
12
|
-
#
|
13
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
14
|
-
# you may not use this file except in compliance with the License.
|
15
|
-
# You may obtain a copy of the License at
|
16
|
-
#
|
17
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
18
|
-
#
|
19
|
-
# Unless required by applicable law or agreed to in writing, software
|
20
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
21
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22
|
-
# See the License for the specific language governing permissions and
|
23
|
-
# limitations under the License.
|
24
|
-
#
|
25
|
-
|
26
|
-
Ohai.plugin(:Filesystem) do
|
27
|
-
provides "filesystem".freeze
|
28
|
-
|
29
|
-
def find_device(name)
|
30
|
-
%w{/dev /dev/mapper}.each do |dir|
|
31
|
-
path = File.join(dir, name)
|
32
|
-
return path if file_exist?(path)
|
33
|
-
end
|
34
|
-
name
|
35
|
-
end
|
36
|
-
|
37
|
-
def parse_line(line, cmdtype)
|
38
|
-
case cmdtype
|
39
|
-
when "lsblk"
|
40
|
-
regex = /NAME="(\S+).*?" UUID="(\S*)" LABEL="(\S*)" FSTYPE="(\S*)"/
|
41
|
-
if line =~ regex
|
42
|
-
dev = $1
|
43
|
-
dev = find_device(dev) unless dev.start_with?("/")
|
44
|
-
uuid = $2
|
45
|
-
label = $3
|
46
|
-
fs_type = $4
|
47
|
-
return { dev: dev, uuid: uuid, label: label, fs_type: fs_type }
|
48
|
-
end
|
49
|
-
when "blkid"
|
50
|
-
bits = line.split
|
51
|
-
dev = bits.shift.split(":")[0]
|
52
|
-
f = { dev: dev }
|
53
|
-
bits.each do |keyval|
|
54
|
-
if keyval =~ /(\S+)="(\S+)"/
|
55
|
-
key = $1.downcase.to_sym
|
56
|
-
key = :fs_type if key == :type
|
57
|
-
f[key] = $2
|
58
|
-
end
|
59
|
-
end
|
60
|
-
return f
|
61
|
-
end
|
62
|
-
nil
|
63
|
-
end
|
64
|
-
|
65
|
-
def generate_device_view(fs)
|
66
|
-
view = {}
|
67
|
-
fs.each_value do |entry|
|
68
|
-
view[entry[:device]] ||= Mash.new
|
69
|
-
entry.each do |key, val|
|
70
|
-
next if %w{device mount}.include?(key)
|
71
|
-
|
72
|
-
view[entry[:device]][key] = val
|
73
|
-
end
|
74
|
-
view[entry[:device]][:mounts] ||= []
|
75
|
-
if entry[:mount]
|
76
|
-
view[entry[:device]][:mounts] << entry[:mount]
|
77
|
-
end
|
78
|
-
end
|
79
|
-
view
|
80
|
-
end
|
81
|
-
|
82
|
-
def generate_mountpoint_view(fs)
|
83
|
-
view = {}
|
84
|
-
fs.each_value do |entry|
|
85
|
-
next unless entry[:mount]
|
86
|
-
|
87
|
-
view[entry[:mount]] ||= Mash.new
|
88
|
-
entry.each do |key, val|
|
89
|
-
next if %w{mount device}.include?(key)
|
90
|
-
|
91
|
-
view[entry[:mount]][key] = val
|
92
|
-
end
|
93
|
-
view[entry[:mount]][:devices] ||= []
|
94
|
-
if entry[:device]
|
95
|
-
view[entry[:mount]][:devices] << entry[:device]
|
96
|
-
end
|
97
|
-
end
|
98
|
-
view
|
99
|
-
end
|
100
|
-
|
101
|
-
def parse_common_df(out)
|
102
|
-
fs = {}
|
103
|
-
out.each_line do |line|
|
104
|
-
case line
|
105
|
-
when /^Filesystem\s+1024-blocks/
|
106
|
-
next
|
107
|
-
when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(.+)$/
|
108
|
-
key = "#{$1},#{$6}"
|
109
|
-
fs[key] = Mash.new
|
110
|
-
fs[key][:device] = $1
|
111
|
-
fs[key][:kb_size] = $2
|
112
|
-
fs[key][:kb_used] = $3
|
113
|
-
fs[key][:kb_available] = $4
|
114
|
-
fs[key][:percent_used] = $5
|
115
|
-
fs[key][:mount] = $6
|
116
|
-
end
|
117
|
-
end
|
118
|
-
fs
|
119
|
-
end
|
120
|
-
|
121
|
-
def run_with_check(bin, &block)
|
122
|
-
yield
|
123
|
-
rescue Ohai::Exceptions::Exec => e
|
124
|
-
unless Ohai.config[:plugin][:filesystem][:allow_partial_data]
|
125
|
-
raise e
|
126
|
-
end
|
127
|
-
|
128
|
-
logger.warn("Plugin Filesystem: #{bin} binary is not available. Some data will not be available.")
|
129
|
-
end
|
130
|
-
|
131
|
-
### Windows specific methods BEGINS
|
132
|
-
# Drive types
|
133
|
-
DRIVE_TYPE ||= %w{unknown no_root_dir removable local network cd ram}.freeze
|
134
|
-
|
135
|
-
# Volume encryption or decryption status
|
136
|
-
#
|
137
|
-
# @see https://docs.microsoft.com/en-us/windows/desktop/SecProv/getconversionstatus-win32-encryptablevolume#parameters
|
138
|
-
#
|
139
|
-
CONVERSION_STATUS ||= %w{
|
140
|
-
FullyDecrypted FullyEncrypted EncryptionInProgress
|
141
|
-
DecryptionInProgress EncryptionPaused DecryptionPaused
|
142
|
-
}.freeze
|
143
|
-
|
144
|
-
# Returns a Mash loaded with logical details
|
145
|
-
#
|
146
|
-
# Uses Win32_LogicalDisk and logical_properties to return general details of volumes.
|
147
|
-
#
|
148
|
-
# Returns an empty Mash in case of any WMI exception.
|
149
|
-
#
|
150
|
-
# @see https://docs.microsoft.com/en-us/windows/desktop/CIMWin32Prov/win32-logicaldisk
|
151
|
-
#
|
152
|
-
# @return [Mash]
|
153
|
-
#
|
154
|
-
def logical_info
|
155
|
-
wmi = WmiLite::Wmi.new("Root\\CIMV2")
|
156
|
-
|
157
|
-
# TODO: We should really be parsing Win32_Volume and Win32_MountPoint.
|
158
|
-
disks = wmi.instances_of("Win32_LogicalDisk")
|
159
|
-
logical_properties(disks)
|
160
|
-
rescue WmiLite::WmiException
|
161
|
-
Ohai::Log.debug("Unable to access Win32_LogicalDisk. Skipping logical details")
|
162
|
-
Mash.new
|
163
|
-
end
|
164
|
-
|
165
|
-
# Returns a Mash loaded with encryption details
|
166
|
-
#
|
167
|
-
# Uses Win32_EncryptableVolume and encryption_properties to return encryption details of volumes.
|
168
|
-
#
|
169
|
-
# Returns an empty Mash in case of any WMI exception.
|
170
|
-
#
|
171
|
-
# @note We are fetching Encryption Status only as of now
|
172
|
-
#
|
173
|
-
# @see https://msdn.microsoft.com/en-us/library/windows/desktop/aa376483(v=vs.85).aspx
|
174
|
-
#
|
175
|
-
# @return [Mash]
|
176
|
-
#
|
177
|
-
def encryptable_info
|
178
|
-
wmi = WmiLite::Wmi.new("Root\\CIMV2\\Security\\MicrosoftVolumeEncryption")
|
179
|
-
disks = wmi.instances_of("Win32_EncryptableVolume")
|
180
|
-
encryption_properties(disks)
|
181
|
-
rescue WmiLite::WmiException
|
182
|
-
Ohai::Log.debug("Unable to access Win32_EncryptableVolume. Skipping encryptable details")
|
183
|
-
Mash.new
|
184
|
-
end
|
185
|
-
|
186
|
-
# Refines and calculates logical properties out of given instances.
|
187
|
-
#
|
188
|
-
# Note that :device here is the same as Volume name and there for compatibility with other OSes.
|
189
|
-
#
|
190
|
-
# @param [WmiLite::Wmi::Instance] disks
|
191
|
-
#
|
192
|
-
# @return [Mash] Each drive containing following properties:
|
193
|
-
#
|
194
|
-
# * :kb_size (Integer)
|
195
|
-
# * :kb_available (Integer)
|
196
|
-
# * :kb_used (Integer)
|
197
|
-
# * :percent_used (Integer)
|
198
|
-
# * :mount (String)
|
199
|
-
# * :fs_type (String)
|
200
|
-
# * :volume_name (String)
|
201
|
-
# * :device (String)
|
202
|
-
#
|
203
|
-
def logical_properties(disks)
|
204
|
-
properties = Mash.new
|
205
|
-
disks.each do |disk|
|
206
|
-
property = Mash.new
|
207
|
-
# In windows the closest thing we have to a device is the volume name
|
208
|
-
# and the "mountpoint" is the drive letter...
|
209
|
-
device = disk["volumename"].to_s.downcase
|
210
|
-
mount = disk["deviceid"]
|
211
|
-
property[:kb_size] = disk["size"] ? disk["size"].to_i / 1000 : 0
|
212
|
-
property[:kb_available] = disk["freespace"].to_i / 1000
|
213
|
-
property[:kb_used] = property[:kb_size] - property[:kb_available]
|
214
|
-
property[:percent_used] = (property[:kb_size] == 0 ? 0 : (property[:kb_used] * 100 / property[:kb_size]))
|
215
|
-
property[:mount] = mount
|
216
|
-
property[:fs_type] = disk["filesystem"].to_s.downcase
|
217
|
-
property[:drive_type] = disk["drivetype"].to_i
|
218
|
-
property[:drive_type_string] = DRIVE_TYPE[disk["drivetype"].to_i]
|
219
|
-
property[:drive_type_human] = disk["description"].to_s
|
220
|
-
property[:volume_name] = disk["volumename"].to_s
|
221
|
-
property[:device] = device
|
222
|
-
|
223
|
-
key = "#{device},#{mount}"
|
224
|
-
properties[key] = property
|
225
|
-
end
|
226
|
-
properties
|
227
|
-
end
|
228
|
-
|
229
|
-
# Refines and calculates encryption properties out of given instances
|
230
|
-
#
|
231
|
-
# @param [WmiLite::Wmi::Instance] disks
|
232
|
-
#
|
233
|
-
# @return [Mash] Each drive containing following properties:
|
234
|
-
#
|
235
|
-
# * :encryption_status (String)
|
236
|
-
#
|
237
|
-
def encryption_properties(disks)
|
238
|
-
properties = Mash.new
|
239
|
-
disks.each do |disk|
|
240
|
-
property = Mash.new
|
241
|
-
property[:encryption_status] = disk["conversionstatus"] ? CONVERSION_STATUS[disk["conversionstatus"]] : ""
|
242
|
-
key = disk["driveletter"]
|
243
|
-
properties[key] = property
|
244
|
-
end
|
245
|
-
properties
|
246
|
-
end
|
247
|
-
|
248
|
-
# Merges all the various properties of filesystems
|
249
|
-
#
|
250
|
-
# @param [Array<Mash>] disks_info
|
251
|
-
# Array of the Mashes containing disk properties
|
252
|
-
#
|
253
|
-
# @return [Mash]
|
254
|
-
#
|
255
|
-
def merge_info(logical_info, encryption_info)
|
256
|
-
fs = Mash.new
|
257
|
-
|
258
|
-
encryption_keys_used = Set.new
|
259
|
-
logical_info.each do |key, info|
|
260
|
-
if encryption_info[info["mount"]]
|
261
|
-
encryption_keys_used.add(info["mount"])
|
262
|
-
fs[key] = info.merge(encryption_info[info["mount"]])
|
263
|
-
else
|
264
|
-
fs[key] = info.dup
|
265
|
-
end
|
266
|
-
end
|
267
|
-
left_enc = encryption_info.reject { |x| encryption_keys_used.include?(x) }
|
268
|
-
left_enc.each do |key, info|
|
269
|
-
fs[",#{key}"] = info
|
270
|
-
end
|
271
|
-
fs
|
272
|
-
end
|
273
|
-
|
274
|
-
def collect_btrfs_data(entry)
|
275
|
-
btrfs = Mash.new
|
276
|
-
if entry[:fs_type] == "btrfs" && entry["uuid"]
|
277
|
-
uuid = entry["uuid"]
|
278
|
-
alloc = "/sys/fs/btrfs/#{uuid}/allocation"
|
279
|
-
if Dir.exist?(alloc)
|
280
|
-
%w{data metadata system}.each do |bg_type|
|
281
|
-
dir = "#{alloc}/#{bg_type}"
|
282
|
-
%w{single dup}.each do |raid|
|
283
|
-
if file_exist?("#{dir}/#{raid}")
|
284
|
-
btrfs["raid"] = raid
|
285
|
-
end
|
286
|
-
end
|
287
|
-
logger.trace("Plugin Filesystem: reading btrfs allocation files at #{dir}")
|
288
|
-
btrfs["allocation"] ||= Mash.new
|
289
|
-
btrfs["allocation"][bg_type] ||= Mash.new
|
290
|
-
%w{total_bytes bytes_used}.each do |field|
|
291
|
-
bytes = file_read("#{dir}/#{field}").chomp.to_i
|
292
|
-
btrfs["allocation"][bg_type][field] = "#{bytes}"
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
end
|
297
|
-
btrfs
|
298
|
-
end
|
299
|
-
|
300
|
-
collect_data(:linux) do
|
301
|
-
fs = Mash.new
|
302
|
-
|
303
|
-
# Grab filesystem data from df
|
304
|
-
run_with_check("df") do
|
305
|
-
fs.merge!(parse_common_df(shell_out("df -P").stdout))
|
306
|
-
|
307
|
-
# Grab filesystem inode data from df
|
308
|
-
shell_out("df -iP").stdout.each_line do |line|
|
309
|
-
case line
|
310
|
-
when /^Filesystem\s+Inodes/
|
311
|
-
next
|
312
|
-
when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(.+)$/
|
313
|
-
key = "#{$1},#{$6}"
|
314
|
-
fs[key] ||= Mash.new
|
315
|
-
fs[key][:device] = $1
|
316
|
-
fs[key][:total_inodes] = $2
|
317
|
-
fs[key][:inodes_used] = $3
|
318
|
-
fs[key][:inodes_available] = $4
|
319
|
-
fs[key][:inodes_percent_used] = $5
|
320
|
-
fs[key][:mount] = $6
|
321
|
-
end
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
# Grab mount information from /bin/mount
|
326
|
-
run_with_check("mount") do
|
327
|
-
shell_out("mount").stdout.each_line do |line|
|
328
|
-
if line =~ /^(.+?) on (.+?) type (.+?) \((.+?)\)$/
|
329
|
-
key = "#{$1},#{$2}"
|
330
|
-
fs[key] ||= Mash.new
|
331
|
-
fs[key][:device] = $1
|
332
|
-
fs[key][:mount] = $2
|
333
|
-
fs[key][:fs_type] = $3
|
334
|
-
fs[key][:mount_options] = $4.split(",")
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
# We used to try to decide if we wanted to run lsblk or blkid
|
340
|
-
# but they each have a variety of cases were they fail to report
|
341
|
-
# data. For example, there are a variety of cases where lsblk won't
|
342
|
-
# report unmounted filesystems, but blkid will. And vise-versa. Sweet.
|
343
|
-
# So for reliability, we'll run both, if we have them.
|
344
|
-
|
345
|
-
lsblk = which("lsblk")
|
346
|
-
blkid = which("blkid")
|
347
|
-
cmds = []
|
348
|
-
# These should be in order of preference... first writer wins.
|
349
|
-
if lsblk
|
350
|
-
cmds << "#{lsblk} -n -P -o NAME,UUID,LABEL,FSTYPE"
|
351
|
-
end
|
352
|
-
if blkid
|
353
|
-
cmds << blkid
|
354
|
-
end
|
355
|
-
|
356
|
-
cmds.each do |cmd|
|
357
|
-
cmdtype = File.basename(cmd.split.first)
|
358
|
-
# setting the timeout here for `lsblk` and `blkid` commands to 60
|
359
|
-
# this is to allow machines with large amounts of attached LUNs
|
360
|
-
# to respond back to the command successfully
|
361
|
-
run_with_check(cmdtype) do
|
362
|
-
shell_out(cmd, timeout: 60).stdout.each_line do |line|
|
363
|
-
parsed = parse_line(line, cmdtype)
|
364
|
-
next if parsed.nil?
|
365
|
-
|
366
|
-
# lsblk lists each device once, so we need to update all entries
|
367
|
-
# in the hash that are related to this device
|
368
|
-
keys_to_update = []
|
369
|
-
fs.each_key do |key|
|
370
|
-
keys_to_update << key if key.start_with?("#{parsed[:dev]},")
|
371
|
-
end
|
372
|
-
|
373
|
-
if keys_to_update.empty?
|
374
|
-
key = "#{parsed[:dev]},"
|
375
|
-
fs[key] = Mash.new
|
376
|
-
fs[key][:device] = parsed[:dev]
|
377
|
-
keys_to_update << key
|
378
|
-
end
|
379
|
-
|
380
|
-
keys_to_update.each do |k|
|
381
|
-
%i{fs_type uuid label}.each do |subkey|
|
382
|
-
if parsed[subkey] && !parsed[subkey].empty?
|
383
|
-
fs[k][subkey] = parsed[subkey]
|
384
|
-
end
|
385
|
-
end
|
386
|
-
end
|
387
|
-
end
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
# Grab any missing mount information from /proc/mounts
|
392
|
-
if file_exist?("/proc/mounts")
|
393
|
-
mounts = ""
|
394
|
-
# Due to https://tickets.opscode.com/browse/OHAI-196
|
395
|
-
# we have to non-block read dev files. Ew.
|
396
|
-
f = file_open("/proc/mounts")
|
397
|
-
loop do
|
398
|
-
data = f.read_nonblock(4096)
|
399
|
-
mounts << data
|
400
|
-
# We should just catch EOFError, but the kernel had a period of
|
401
|
-
# bugginess with reading virtual files, so we're being extra
|
402
|
-
# cautious here, catching all exceptions, and then we'll read
|
403
|
-
# whatever data we might have
|
404
|
-
rescue Exception
|
405
|
-
break
|
406
|
-
end
|
407
|
-
f.close
|
408
|
-
|
409
|
-
mounts.each_line do |line|
|
410
|
-
if line =~ /^(\S+) (\S+) (\S+) (\S+) \S+ \S+$/
|
411
|
-
key = "#{$1},#{$2}"
|
412
|
-
next if fs.key?(key)
|
413
|
-
|
414
|
-
fs[key] = Mash.new
|
415
|
-
fs[key][:device] = $1
|
416
|
-
fs[key][:mount] = $2
|
417
|
-
fs[key][:fs_type] = $3
|
418
|
-
fs[key][:mount_options] = $4.split(",")
|
419
|
-
end
|
420
|
-
end
|
421
|
-
end
|
422
|
-
|
423
|
-
fs.each do |key, entry|
|
424
|
-
if entry[:fs_type] == "btrfs"
|
425
|
-
fs[key][:btrfs] = collect_btrfs_data(entry)
|
426
|
-
end
|
427
|
-
end
|
428
|
-
|
429
|
-
by_pair = fs
|
430
|
-
by_device = generate_device_view(fs)
|
431
|
-
by_mountpoint = generate_mountpoint_view(fs)
|
432
|
-
|
433
|
-
fs_data = Mash.new
|
434
|
-
fs_data["by_device"] = by_device
|
435
|
-
fs_data["by_mountpoint"] = by_mountpoint
|
436
|
-
fs_data["by_pair"] = by_pair
|
437
|
-
|
438
|
-
# Set the filesystem data
|
439
|
-
filesystem fs_data
|
440
|
-
end
|
441
|
-
|
442
|
-
collect_data(:freebsd, :openbsd, :netbsd, :dragonflybsd) do
|
443
|
-
fs = Mash.new
|
444
|
-
|
445
|
-
# Grab filesystem data from df
|
446
|
-
run_with_check("df") do
|
447
|
-
so = shell_out("df")
|
448
|
-
fs.merge!(parse_common_df(so.stdout))
|
449
|
-
|
450
|
-
so = shell_out("df -iP")
|
451
|
-
so.stdout.lines do |line|
|
452
|
-
case line
|
453
|
-
when /^Filesystem/ # skip the header
|
454
|
-
next
|
455
|
-
when /^(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\%\s+(\d+)\s+(\d+)\s+(\d+)%\s+(\S+)$/
|
456
|
-
key = "#{$1},#{$9}"
|
457
|
-
fs[key] ||= Mash.new
|
458
|
-
fs[key][:device] = $1
|
459
|
-
fs[key][:inodes_used] = $6
|
460
|
-
fs[key][:inodes_available] = $7
|
461
|
-
fs[key][:total_inodes] = ($6.to_i + $7.to_i).to_s
|
462
|
-
fs[key][:inodes_percent_used] = $8
|
463
|
-
fs[key][:mount] = $9
|
464
|
-
end
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
# Grab mount information from mount
|
469
|
-
run_with_check("mount") do
|
470
|
-
so = shell_out("mount -l")
|
471
|
-
so.stdout.lines do |line|
|
472
|
-
if line =~ /^(.+?) on (.+?) \((.+?), (.+?)\)$/
|
473
|
-
key = "#{$1},#{$2}"
|
474
|
-
fs[key] ||= Mash.new
|
475
|
-
fs[key][:device] = $1
|
476
|
-
fs[key][:mount] = $2
|
477
|
-
fs[key][:fs_type] = $3
|
478
|
-
fs[key][:mount_options] = $4.split(/,\s*/)
|
479
|
-
end
|
480
|
-
end
|
481
|
-
end
|
482
|
-
|
483
|
-
# create views
|
484
|
-
by_pair = fs
|
485
|
-
by_device = generate_device_view(fs)
|
486
|
-
by_mountpoint = generate_mountpoint_view(fs)
|
487
|
-
|
488
|
-
fs_data = Mash.new
|
489
|
-
fs_data["by_device"] = by_device
|
490
|
-
fs_data["by_mountpoint"] = by_mountpoint
|
491
|
-
fs_data["by_pair"] = by_pair
|
492
|
-
|
493
|
-
filesystem fs_data
|
494
|
-
end
|
495
|
-
|
496
|
-
collect_data(:darwin) do
|
497
|
-
fs = Mash.new
|
498
|
-
block_size = 0
|
499
|
-
# on new versions of OSX, -i is default, on old versions it's not, so
|
500
|
-
# specifying it gets consistent output
|
501
|
-
run_with_check("df") do
|
502
|
-
so = shell_out("df -i")
|
503
|
-
so.stdout.each_line do |line|
|
504
|
-
case line
|
505
|
-
when /^Filesystem\s+(\d+)-/
|
506
|
-
block_size = $1.to_i
|
507
|
-
next
|
508
|
-
when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(\d+)\s+(\d+)\s+(\d+%)\s+(.+)$/
|
509
|
-
key = "#{$1},#{$9}"
|
510
|
-
fs[key] = Mash.new
|
511
|
-
fs[key][:block_size] = block_size
|
512
|
-
fs[key][:device] = $1
|
513
|
-
fs[key][:kb_size] = ($2.to_i / (1024 / block_size)).to_s
|
514
|
-
fs[key][:kb_used] = ($3.to_i / (1024 / block_size)).to_s
|
515
|
-
fs[key][:kb_available] = ($4.to_i / (1024 / block_size)).to_s
|
516
|
-
fs[key][:percent_used] = $5
|
517
|
-
fs[key][:inodes_used] = $6
|
518
|
-
fs[key][:inodes_available] = $7
|
519
|
-
fs[key][:total_inodes] = ($6.to_i + $7.to_i).to_s
|
520
|
-
fs[key][:inodes_percent_used] = $8
|
521
|
-
fs[key][:mount] = $9
|
522
|
-
end
|
523
|
-
end
|
524
|
-
end
|
525
|
-
|
526
|
-
run_with_check("mount") do
|
527
|
-
so = shell_out("mount")
|
528
|
-
so.stdout.lines do |line|
|
529
|
-
if line =~ /^(.+?) on (.+?) \((.+?), (.+?)\)$/
|
530
|
-
key = "#{$1},#{$2}"
|
531
|
-
fs[key] ||= Mash.new
|
532
|
-
fs[key][:mount] = $2
|
533
|
-
fs[key][:fs_type] = $3
|
534
|
-
fs[key][:mount_options] = $4.split(/,\s*/)
|
535
|
-
end
|
536
|
-
end
|
537
|
-
end
|
538
|
-
|
539
|
-
by_pair = fs
|
540
|
-
by_device = generate_device_view(fs)
|
541
|
-
by_mountpoint = generate_mountpoint_view(fs)
|
542
|
-
|
543
|
-
fs_data = Mash.new
|
544
|
-
fs_data["by_device"] = by_device
|
545
|
-
fs_data["by_mountpoint"] = by_mountpoint
|
546
|
-
fs_data["by_pair"] = by_pair
|
547
|
-
|
548
|
-
filesystem fs_data
|
549
|
-
end
|
550
|
-
|
551
|
-
collect_data(:solaris2) do
|
552
|
-
fs = Mash.new
|
553
|
-
|
554
|
-
# Grab filesystem data from df
|
555
|
-
run_with_check("df") do
|
556
|
-
so = shell_out("df -Pka")
|
557
|
-
fs.merge!(parse_common_df(so.stdout))
|
558
|
-
|
559
|
-
# Grab file system type from df (must be done separately)
|
560
|
-
so = shell_out("df -na")
|
561
|
-
so.stdout.lines do |line|
|
562
|
-
next unless line =~ /^(.+?)\s*: (\S+)\s*$/
|
563
|
-
|
564
|
-
mount = $1
|
565
|
-
fs.each do |key, fs_attributes|
|
566
|
-
next unless fs_attributes[:mount] == mount
|
567
|
-
|
568
|
-
fs[key][:fs_type] = $2
|
569
|
-
end
|
570
|
-
end
|
571
|
-
end
|
572
|
-
|
573
|
-
# Grab mount information from /bin/mount
|
574
|
-
run_with_check("mount") do
|
575
|
-
so = shell_out("mount")
|
576
|
-
so.stdout.lines do |line|
|
577
|
-
next unless line =~ /^(.+?) on (.+?) (.+?) on (.+?)$/
|
578
|
-
|
579
|
-
key = "#{$2},#{$1}"
|
580
|
-
fs[key] ||= Mash.new
|
581
|
-
fs[key][:mount] = $1
|
582
|
-
fs[key][:mount_time] = $4 # $4 must come before "split", else it becomes nil
|
583
|
-
fs[key][:mount_options] = $3.split("/")
|
584
|
-
end
|
585
|
-
end
|
586
|
-
|
587
|
-
# Grab any zfs data from "zfs get"
|
588
|
-
zfs = Mash.new
|
589
|
-
zfs_get = "zfs get -p -H all"
|
590
|
-
run_with_check("zfs") do
|
591
|
-
so = shell_out(zfs_get)
|
592
|
-
so.stdout.lines do |line|
|
593
|
-
next unless line =~ /^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)$/
|
594
|
-
|
595
|
-
filesystem = $1
|
596
|
-
property = $2
|
597
|
-
value = $3
|
598
|
-
source = $4.chomp
|
599
|
-
zfs[filesystem] ||= Mash.new
|
600
|
-
# if this fs doesn't exist, put in the bare minimum
|
601
|
-
zfs[filesystem][property] = {
|
602
|
-
value: value,
|
603
|
-
source: source,
|
604
|
-
}
|
605
|
-
end
|
606
|
-
end
|
607
|
-
|
608
|
-
zfs.each do |fs_name, attributes|
|
609
|
-
mountpoint = attributes[:mountpoint][:value] if attributes[:mountpoint]
|
610
|
-
key = "#{fs_name},#{mountpoint}"
|
611
|
-
fs[key] ||= Mash.new
|
612
|
-
fs[key][:fs_type] = "zfs"
|
613
|
-
fs[key][:mount] = mountpoint if mountpoint
|
614
|
-
fs[key][:device] = fs_name
|
615
|
-
fs[key][:zfs_properties] = attributes
|
616
|
-
# find all zfs parents
|
617
|
-
parents = fs_name.split("/")
|
618
|
-
zfs_parents = []
|
619
|
-
(0..parents.length - 1).to_a.each do |parent_index|
|
620
|
-
next_parent = parents[0..parent_index].join("/")
|
621
|
-
zfs_parents.push(next_parent)
|
622
|
-
end
|
623
|
-
zfs_parents.pop
|
624
|
-
fs[key][:zfs_parents] = zfs_parents
|
625
|
-
fs[key][:zfs_zpool] = (zfs_parents.length == 0)
|
626
|
-
end
|
627
|
-
|
628
|
-
# create views
|
629
|
-
by_pair = fs
|
630
|
-
by_device = generate_device_view(fs)
|
631
|
-
by_mountpoint = generate_mountpoint_view(fs)
|
632
|
-
|
633
|
-
fs_data = Mash.new
|
634
|
-
fs_data["by_device"] = by_device
|
635
|
-
fs_data["by_mountpoint"] = by_mountpoint
|
636
|
-
fs_data["by_pair"] = by_pair
|
637
|
-
|
638
|
-
filesystem fs_data
|
639
|
-
end
|
640
|
-
|
641
|
-
collect_data(:aix) do
|
642
|
-
def parse_df_or_mount(shell_out)
|
643
|
-
oldie = Mash.new
|
644
|
-
|
645
|
-
shell_out.lines.each do |line|
|
646
|
-
fields = line.split
|
647
|
-
case line
|
648
|
-
# headers and horizontal rules to skip
|
649
|
-
when /^\s*(node|---|^Filesystem\s+1024-blocks)/
|
650
|
-
next
|
651
|
-
# strictly a df entry
|
652
|
-
when /^(.+?)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+\%*)\s+(.+)$/
|
653
|
-
if $1 == "Global"
|
654
|
-
dev = "#{$1}:#{$6}"
|
655
|
-
else
|
656
|
-
dev = $1
|
657
|
-
end
|
658
|
-
mountpoint = $6
|
659
|
-
key = "#{dev},#{mountpoint}"
|
660
|
-
oldie[key] ||= Mash.new
|
661
|
-
oldie[key][:kb_size] = $2
|
662
|
-
oldie[key][:kb_used] = $3
|
663
|
-
oldie[key][:kb_available] = $4
|
664
|
-
oldie[key][:percent_used] = $5
|
665
|
-
oldie[key][:mount] = mountpoint
|
666
|
-
oldie[key][:device] = dev
|
667
|
-
# an entry starting with 'G' or / (E.G. /tmp or /var)
|
668
|
-
when %r{^\s*(G.*?|/\w)}
|
669
|
-
if fields[0] == "Global"
|
670
|
-
dev = fields[0] + ":" + fields[1]
|
671
|
-
else
|
672
|
-
dev = fields[0]
|
673
|
-
end
|
674
|
-
mountpoint = fields[1]
|
675
|
-
key = "#{dev},#{mountpoint}"
|
676
|
-
oldie[key] ||= Mash.new
|
677
|
-
oldie[key][:mount] = mountpoint
|
678
|
-
oldie[key][:fs_type] = fields[2]
|
679
|
-
oldie[key][:mount_options] = fields[6].split(",")
|
680
|
-
oldie[key][:device] = dev
|
681
|
-
# entries occupying the 'Node' column parsed here
|
682
|
-
else
|
683
|
-
dev = fields[0] + ":" + fields[1]
|
684
|
-
mountpoint = fields[2]
|
685
|
-
key = "#{dev},#{mountpoint}"
|
686
|
-
oldie[key] ||= Mash.new
|
687
|
-
oldie[key][:mount] = mountpoint
|
688
|
-
oldie[key][:device] = dev
|
689
|
-
oldie[key][:fs_type] = fields[3]
|
690
|
-
oldie[key][:mount_options] = fields[7].split(",")
|
691
|
-
end
|
692
|
-
end
|
693
|
-
oldie
|
694
|
-
end
|
695
|
-
|
696
|
-
def collect_old_version(shell_outs)
|
697
|
-
mount_hash = parse_df_or_mount shell_outs[:mount]
|
698
|
-
df_hash = parse_df_or_mount shell_outs[:df_Pk]
|
699
|
-
|
700
|
-
mount_hash.each do |key, hash|
|
701
|
-
df_hash[key].merge!(hash) if df_hash.key?(key)
|
702
|
-
end
|
703
|
-
|
704
|
-
mount_hash.merge(df_hash)
|
705
|
-
end
|
706
|
-
|
707
|
-
# Cache the command output
|
708
|
-
shell_outs = Mash.new
|
709
|
-
|
710
|
-
run_with_check("mount") do
|
711
|
-
shell_outs[:mount] = shell_out("mount").stdout
|
712
|
-
end
|
713
|
-
|
714
|
-
run_with_check("df") do
|
715
|
-
shell_outs[:df_Pk] = shell_out("df -Pk").stdout
|
716
|
-
end
|
717
|
-
|
718
|
-
fs = collect_old_version(shell_outs)
|
719
|
-
by_pair = fs
|
720
|
-
by_device = generate_device_view(fs)
|
721
|
-
by_mountpoint = generate_mountpoint_view(fs)
|
722
|
-
|
723
|
-
fs_data = Mash.new
|
724
|
-
fs_data["by_device"] = by_device
|
725
|
-
fs_data["by_mountpoint"] = by_mountpoint
|
726
|
-
fs_data["by_pair"] = by_pair
|
727
|
-
|
728
|
-
filesystem fs_data
|
729
|
-
end
|
730
|
-
|
731
|
-
collect_data(:windows) do
|
732
|
-
require "set" unless defined?(Set)
|
733
|
-
require "wmi-lite/wmi" unless defined?(WmiLite::Wmi)
|
734
|
-
require_relative "../mash"
|
735
|
-
|
736
|
-
fs = merge_info(logical_info, encryptable_info)
|
737
|
-
|
738
|
-
by_pair = fs
|
739
|
-
by_device = generate_device_view(fs)
|
740
|
-
by_mountpoint = generate_mountpoint_view(fs)
|
741
|
-
|
742
|
-
fs_data = Mash.new
|
743
|
-
fs_data["by_device"] = by_device
|
744
|
-
fs_data["by_mountpoint"] = by_mountpoint
|
745
|
-
fs_data["by_pair"] = by_pair
|
746
|
-
|
747
|
-
# Chef 16 added 'filesystem2'
|
748
|
-
# In Chef 17 we made 'filesystem' and 'filesystem2' match (both new-style)
|
749
|
-
# In Chef 18 we will drop 'filesystem2'
|
750
|
-
filesystem fs_data
|
751
|
-
filesystem2 fs_data
|
752
|
-
end
|
753
|
-
end
|
1
|
+
#
|
2
|
+
# Author:: Phil Dibowitz <phil@ipom.com>
|
3
|
+
# Author:: Adam Jacob <adam@chef.io>
|
4
|
+
# Author:: Kurt Yoder (ktyopscode@yoderhome.com)
|
5
|
+
# Author:: Deepali Jagtap (<deepali.jagtap@clogeny.com>)
|
6
|
+
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
|
7
|
+
# Author:: Isa Farnik (<isa@chef.io>)
|
8
|
+
# Author:: James Gartrell (<jgartrel@gmail.com>)
|
9
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
10
|
+
# Copyright:: Copyright (c) 2015 Facebook, Inc.
|
11
|
+
# License:: Apache License, Version 2.0
|
12
|
+
#
|
13
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
14
|
+
# you may not use this file except in compliance with the License.
|
15
|
+
# You may obtain a copy of the License at
|
16
|
+
#
|
17
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
18
|
+
#
|
19
|
+
# Unless required by applicable law or agreed to in writing, software
|
20
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
21
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22
|
+
# See the License for the specific language governing permissions and
|
23
|
+
# limitations under the License.
|
24
|
+
#
|
25
|
+
|
26
|
+
Ohai.plugin(:Filesystem) do
|
27
|
+
provides "filesystem".freeze
|
28
|
+
|
29
|
+
def find_device(name)
|
30
|
+
%w{/dev /dev/mapper}.each do |dir|
|
31
|
+
path = File.join(dir, name)
|
32
|
+
return path if file_exist?(path)
|
33
|
+
end
|
34
|
+
name
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_line(line, cmdtype)
|
38
|
+
case cmdtype
|
39
|
+
when "lsblk"
|
40
|
+
regex = /NAME="(\S+).*?" UUID="(\S*)" LABEL="(\S*)" FSTYPE="(\S*)"/
|
41
|
+
if line =~ regex
|
42
|
+
dev = $1
|
43
|
+
dev = find_device(dev) unless dev.start_with?("/")
|
44
|
+
uuid = $2
|
45
|
+
label = $3
|
46
|
+
fs_type = $4
|
47
|
+
return { dev: dev, uuid: uuid, label: label, fs_type: fs_type }
|
48
|
+
end
|
49
|
+
when "blkid"
|
50
|
+
bits = line.split
|
51
|
+
dev = bits.shift.split(":")[0]
|
52
|
+
f = { dev: dev }
|
53
|
+
bits.each do |keyval|
|
54
|
+
if keyval =~ /(\S+)="(\S+)"/
|
55
|
+
key = $1.downcase.to_sym
|
56
|
+
key = :fs_type if key == :type
|
57
|
+
f[key] = $2
|
58
|
+
end
|
59
|
+
end
|
60
|
+
return f
|
61
|
+
end
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def generate_device_view(fs)
|
66
|
+
view = {}
|
67
|
+
fs.each_value do |entry|
|
68
|
+
view[entry[:device]] ||= Mash.new
|
69
|
+
entry.each do |key, val|
|
70
|
+
next if %w{device mount}.include?(key)
|
71
|
+
|
72
|
+
view[entry[:device]][key] = val
|
73
|
+
end
|
74
|
+
view[entry[:device]][:mounts] ||= []
|
75
|
+
if entry[:mount]
|
76
|
+
view[entry[:device]][:mounts] << entry[:mount]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
view
|
80
|
+
end
|
81
|
+
|
82
|
+
def generate_mountpoint_view(fs)
|
83
|
+
view = {}
|
84
|
+
fs.each_value do |entry|
|
85
|
+
next unless entry[:mount]
|
86
|
+
|
87
|
+
view[entry[:mount]] ||= Mash.new
|
88
|
+
entry.each do |key, val|
|
89
|
+
next if %w{mount device}.include?(key)
|
90
|
+
|
91
|
+
view[entry[:mount]][key] = val
|
92
|
+
end
|
93
|
+
view[entry[:mount]][:devices] ||= []
|
94
|
+
if entry[:device]
|
95
|
+
view[entry[:mount]][:devices] << entry[:device]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
view
|
99
|
+
end
|
100
|
+
|
101
|
+
def parse_common_df(out)
|
102
|
+
fs = {}
|
103
|
+
out.each_line do |line|
|
104
|
+
case line
|
105
|
+
when /^Filesystem\s+1024-blocks/
|
106
|
+
next
|
107
|
+
when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(.+)$/
|
108
|
+
key = "#{$1},#{$6}"
|
109
|
+
fs[key] = Mash.new
|
110
|
+
fs[key][:device] = $1
|
111
|
+
fs[key][:kb_size] = $2
|
112
|
+
fs[key][:kb_used] = $3
|
113
|
+
fs[key][:kb_available] = $4
|
114
|
+
fs[key][:percent_used] = $5
|
115
|
+
fs[key][:mount] = $6
|
116
|
+
end
|
117
|
+
end
|
118
|
+
fs
|
119
|
+
end
|
120
|
+
|
121
|
+
def run_with_check(bin, &block)
|
122
|
+
yield
|
123
|
+
rescue Ohai::Exceptions::Exec => e
|
124
|
+
unless Ohai.config[:plugin][:filesystem][:allow_partial_data]
|
125
|
+
raise e
|
126
|
+
end
|
127
|
+
|
128
|
+
logger.warn("Plugin Filesystem: #{bin} binary is not available. Some data will not be available.")
|
129
|
+
end
|
130
|
+
|
131
|
+
### Windows specific methods BEGINS
|
132
|
+
# Drive types
|
133
|
+
DRIVE_TYPE ||= %w{unknown no_root_dir removable local network cd ram}.freeze
|
134
|
+
|
135
|
+
# Volume encryption or decryption status
|
136
|
+
#
|
137
|
+
# @see https://docs.microsoft.com/en-us/windows/desktop/SecProv/getconversionstatus-win32-encryptablevolume#parameters
|
138
|
+
#
|
139
|
+
CONVERSION_STATUS ||= %w{
|
140
|
+
FullyDecrypted FullyEncrypted EncryptionInProgress
|
141
|
+
DecryptionInProgress EncryptionPaused DecryptionPaused
|
142
|
+
}.freeze
|
143
|
+
|
144
|
+
# Returns a Mash loaded with logical details
|
145
|
+
#
|
146
|
+
# Uses Win32_LogicalDisk and logical_properties to return general details of volumes.
|
147
|
+
#
|
148
|
+
# Returns an empty Mash in case of any WMI exception.
|
149
|
+
#
|
150
|
+
# @see https://docs.microsoft.com/en-us/windows/desktop/CIMWin32Prov/win32-logicaldisk
|
151
|
+
#
|
152
|
+
# @return [Mash]
|
153
|
+
#
|
154
|
+
def logical_info
|
155
|
+
wmi = WmiLite::Wmi.new("Root\\CIMV2")
|
156
|
+
|
157
|
+
# TODO: We should really be parsing Win32_Volume and Win32_MountPoint.
|
158
|
+
disks = wmi.instances_of("Win32_LogicalDisk")
|
159
|
+
logical_properties(disks)
|
160
|
+
rescue WmiLite::WmiException
|
161
|
+
Ohai::Log.debug("Unable to access Win32_LogicalDisk. Skipping logical details")
|
162
|
+
Mash.new
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns a Mash loaded with encryption details
|
166
|
+
#
|
167
|
+
# Uses Win32_EncryptableVolume and encryption_properties to return encryption details of volumes.
|
168
|
+
#
|
169
|
+
# Returns an empty Mash in case of any WMI exception.
|
170
|
+
#
|
171
|
+
# @note We are fetching Encryption Status only as of now
|
172
|
+
#
|
173
|
+
# @see https://msdn.microsoft.com/en-us/library/windows/desktop/aa376483(v=vs.85).aspx
|
174
|
+
#
|
175
|
+
# @return [Mash]
|
176
|
+
#
|
177
|
+
def encryptable_info
|
178
|
+
wmi = WmiLite::Wmi.new("Root\\CIMV2\\Security\\MicrosoftVolumeEncryption")
|
179
|
+
disks = wmi.instances_of("Win32_EncryptableVolume")
|
180
|
+
encryption_properties(disks)
|
181
|
+
rescue WmiLite::WmiException
|
182
|
+
Ohai::Log.debug("Unable to access Win32_EncryptableVolume. Skipping encryptable details")
|
183
|
+
Mash.new
|
184
|
+
end
|
185
|
+
|
186
|
+
# Refines and calculates logical properties out of given instances.
|
187
|
+
#
|
188
|
+
# Note that :device here is the same as Volume name and there for compatibility with other OSes.
|
189
|
+
#
|
190
|
+
# @param [WmiLite::Wmi::Instance] disks
|
191
|
+
#
|
192
|
+
# @return [Mash] Each drive containing following properties:
|
193
|
+
#
|
194
|
+
# * :kb_size (Integer)
|
195
|
+
# * :kb_available (Integer)
|
196
|
+
# * :kb_used (Integer)
|
197
|
+
# * :percent_used (Integer)
|
198
|
+
# * :mount (String)
|
199
|
+
# * :fs_type (String)
|
200
|
+
# * :volume_name (String)
|
201
|
+
# * :device (String)
|
202
|
+
#
|
203
|
+
def logical_properties(disks)
|
204
|
+
properties = Mash.new
|
205
|
+
disks.each do |disk|
|
206
|
+
property = Mash.new
|
207
|
+
# In windows the closest thing we have to a device is the volume name
|
208
|
+
# and the "mountpoint" is the drive letter...
|
209
|
+
device = disk["volumename"].to_s.downcase
|
210
|
+
mount = disk["deviceid"]
|
211
|
+
property[:kb_size] = disk["size"] ? disk["size"].to_i / 1000 : 0
|
212
|
+
property[:kb_available] = disk["freespace"].to_i / 1000
|
213
|
+
property[:kb_used] = property[:kb_size] - property[:kb_available]
|
214
|
+
property[:percent_used] = (property[:kb_size] == 0 ? 0 : (property[:kb_used] * 100 / property[:kb_size]))
|
215
|
+
property[:mount] = mount
|
216
|
+
property[:fs_type] = disk["filesystem"].to_s.downcase
|
217
|
+
property[:drive_type] = disk["drivetype"].to_i
|
218
|
+
property[:drive_type_string] = DRIVE_TYPE[disk["drivetype"].to_i]
|
219
|
+
property[:drive_type_human] = disk["description"].to_s
|
220
|
+
property[:volume_name] = disk["volumename"].to_s
|
221
|
+
property[:device] = device
|
222
|
+
|
223
|
+
key = "#{device},#{mount}"
|
224
|
+
properties[key] = property
|
225
|
+
end
|
226
|
+
properties
|
227
|
+
end
|
228
|
+
|
229
|
+
# Refines and calculates encryption properties out of given instances
|
230
|
+
#
|
231
|
+
# @param [WmiLite::Wmi::Instance] disks
|
232
|
+
#
|
233
|
+
# @return [Mash] Each drive containing following properties:
|
234
|
+
#
|
235
|
+
# * :encryption_status (String)
|
236
|
+
#
|
237
|
+
def encryption_properties(disks)
|
238
|
+
properties = Mash.new
|
239
|
+
disks.each do |disk|
|
240
|
+
property = Mash.new
|
241
|
+
property[:encryption_status] = disk["conversionstatus"] ? CONVERSION_STATUS[disk["conversionstatus"]] : ""
|
242
|
+
key = disk["driveletter"]
|
243
|
+
properties[key] = property
|
244
|
+
end
|
245
|
+
properties
|
246
|
+
end
|
247
|
+
|
248
|
+
# Merges all the various properties of filesystems
|
249
|
+
#
|
250
|
+
# @param [Array<Mash>] disks_info
|
251
|
+
# Array of the Mashes containing disk properties
|
252
|
+
#
|
253
|
+
# @return [Mash]
|
254
|
+
#
|
255
|
+
def merge_info(logical_info, encryption_info)
|
256
|
+
fs = Mash.new
|
257
|
+
|
258
|
+
encryption_keys_used = Set.new
|
259
|
+
logical_info.each do |key, info|
|
260
|
+
if encryption_info[info["mount"]]
|
261
|
+
encryption_keys_used.add(info["mount"])
|
262
|
+
fs[key] = info.merge(encryption_info[info["mount"]])
|
263
|
+
else
|
264
|
+
fs[key] = info.dup
|
265
|
+
end
|
266
|
+
end
|
267
|
+
left_enc = encryption_info.reject { |x| encryption_keys_used.include?(x) }
|
268
|
+
left_enc.each do |key, info|
|
269
|
+
fs[",#{key}"] = info
|
270
|
+
end
|
271
|
+
fs
|
272
|
+
end
|
273
|
+
|
274
|
+
def collect_btrfs_data(entry)
|
275
|
+
btrfs = Mash.new
|
276
|
+
if entry[:fs_type] == "btrfs" && entry["uuid"]
|
277
|
+
uuid = entry["uuid"]
|
278
|
+
alloc = "/sys/fs/btrfs/#{uuid}/allocation"
|
279
|
+
if Dir.exist?(alloc)
|
280
|
+
%w{data metadata system}.each do |bg_type|
|
281
|
+
dir = "#{alloc}/#{bg_type}"
|
282
|
+
%w{single dup}.each do |raid|
|
283
|
+
if file_exist?("#{dir}/#{raid}")
|
284
|
+
btrfs["raid"] = raid
|
285
|
+
end
|
286
|
+
end
|
287
|
+
logger.trace("Plugin Filesystem: reading btrfs allocation files at #{dir}")
|
288
|
+
btrfs["allocation"] ||= Mash.new
|
289
|
+
btrfs["allocation"][bg_type] ||= Mash.new
|
290
|
+
%w{total_bytes bytes_used}.each do |field|
|
291
|
+
bytes = file_read("#{dir}/#{field}").chomp.to_i
|
292
|
+
btrfs["allocation"][bg_type][field] = "#{bytes}"
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
btrfs
|
298
|
+
end
|
299
|
+
|
300
|
+
collect_data(:linux) do
|
301
|
+
fs = Mash.new
|
302
|
+
|
303
|
+
# Grab filesystem data from df
|
304
|
+
run_with_check("df") do
|
305
|
+
fs.merge!(parse_common_df(shell_out("df -P").stdout))
|
306
|
+
|
307
|
+
# Grab filesystem inode data from df
|
308
|
+
shell_out("df -iP").stdout.each_line do |line|
|
309
|
+
case line
|
310
|
+
when /^Filesystem\s+Inodes/
|
311
|
+
next
|
312
|
+
when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(.+)$/
|
313
|
+
key = "#{$1},#{$6}"
|
314
|
+
fs[key] ||= Mash.new
|
315
|
+
fs[key][:device] = $1
|
316
|
+
fs[key][:total_inodes] = $2
|
317
|
+
fs[key][:inodes_used] = $3
|
318
|
+
fs[key][:inodes_available] = $4
|
319
|
+
fs[key][:inodes_percent_used] = $5
|
320
|
+
fs[key][:mount] = $6
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Grab mount information from /bin/mount
|
326
|
+
run_with_check("mount") do
|
327
|
+
shell_out("mount").stdout.each_line do |line|
|
328
|
+
if line =~ /^(.+?) on (.+?) type (.+?) \((.+?)\)$/
|
329
|
+
key = "#{$1},#{$2}"
|
330
|
+
fs[key] ||= Mash.new
|
331
|
+
fs[key][:device] = $1
|
332
|
+
fs[key][:mount] = $2
|
333
|
+
fs[key][:fs_type] = $3
|
334
|
+
fs[key][:mount_options] = $4.split(",")
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
# We used to try to decide if we wanted to run lsblk or blkid
|
340
|
+
# but they each have a variety of cases were they fail to report
|
341
|
+
# data. For example, there are a variety of cases where lsblk won't
|
342
|
+
# report unmounted filesystems, but blkid will. And vise-versa. Sweet.
|
343
|
+
# So for reliability, we'll run both, if we have them.
|
344
|
+
|
345
|
+
lsblk = which("lsblk")
|
346
|
+
blkid = which("blkid")
|
347
|
+
cmds = []
|
348
|
+
# These should be in order of preference... first writer wins.
|
349
|
+
if lsblk
|
350
|
+
cmds << "#{lsblk} -n -P -o NAME,UUID,LABEL,FSTYPE"
|
351
|
+
end
|
352
|
+
if blkid
|
353
|
+
cmds << blkid
|
354
|
+
end
|
355
|
+
|
356
|
+
cmds.each do |cmd|
|
357
|
+
cmdtype = File.basename(cmd.split.first)
|
358
|
+
# setting the timeout here for `lsblk` and `blkid` commands to 60
|
359
|
+
# this is to allow machines with large amounts of attached LUNs
|
360
|
+
# to respond back to the command successfully
|
361
|
+
run_with_check(cmdtype) do
|
362
|
+
shell_out(cmd, timeout: 60).stdout.each_line do |line|
|
363
|
+
parsed = parse_line(line, cmdtype)
|
364
|
+
next if parsed.nil?
|
365
|
+
|
366
|
+
# lsblk lists each device once, so we need to update all entries
|
367
|
+
# in the hash that are related to this device
|
368
|
+
keys_to_update = []
|
369
|
+
fs.each_key do |key|
|
370
|
+
keys_to_update << key if key.start_with?("#{parsed[:dev]},")
|
371
|
+
end
|
372
|
+
|
373
|
+
if keys_to_update.empty?
|
374
|
+
key = "#{parsed[:dev]},"
|
375
|
+
fs[key] = Mash.new
|
376
|
+
fs[key][:device] = parsed[:dev]
|
377
|
+
keys_to_update << key
|
378
|
+
end
|
379
|
+
|
380
|
+
keys_to_update.each do |k|
|
381
|
+
%i{fs_type uuid label}.each do |subkey|
|
382
|
+
if parsed[subkey] && !parsed[subkey].empty?
|
383
|
+
fs[k][subkey] = parsed[subkey]
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
# Grab any missing mount information from /proc/mounts
|
392
|
+
if file_exist?("/proc/mounts")
|
393
|
+
mounts = ""
|
394
|
+
# Due to https://tickets.opscode.com/browse/OHAI-196
|
395
|
+
# we have to non-block read dev files. Ew.
|
396
|
+
f = file_open("/proc/mounts")
|
397
|
+
loop do
|
398
|
+
data = f.read_nonblock(4096)
|
399
|
+
mounts << data
|
400
|
+
# We should just catch EOFError, but the kernel had a period of
|
401
|
+
# bugginess with reading virtual files, so we're being extra
|
402
|
+
# cautious here, catching all exceptions, and then we'll read
|
403
|
+
# whatever data we might have
|
404
|
+
rescue Exception
|
405
|
+
break
|
406
|
+
end
|
407
|
+
f.close
|
408
|
+
|
409
|
+
mounts.each_line do |line|
|
410
|
+
if line =~ /^(\S+) (\S+) (\S+) (\S+) \S+ \S+$/
|
411
|
+
key = "#{$1},#{$2}"
|
412
|
+
next if fs.key?(key)
|
413
|
+
|
414
|
+
fs[key] = Mash.new
|
415
|
+
fs[key][:device] = $1
|
416
|
+
fs[key][:mount] = $2
|
417
|
+
fs[key][:fs_type] = $3
|
418
|
+
fs[key][:mount_options] = $4.split(",")
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
fs.each do |key, entry|
|
424
|
+
if entry[:fs_type] == "btrfs"
|
425
|
+
fs[key][:btrfs] = collect_btrfs_data(entry)
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
by_pair = fs
|
430
|
+
by_device = generate_device_view(fs)
|
431
|
+
by_mountpoint = generate_mountpoint_view(fs)
|
432
|
+
|
433
|
+
fs_data = Mash.new
|
434
|
+
fs_data["by_device"] = by_device
|
435
|
+
fs_data["by_mountpoint"] = by_mountpoint
|
436
|
+
fs_data["by_pair"] = by_pair
|
437
|
+
|
438
|
+
# Set the filesystem data
|
439
|
+
filesystem fs_data
|
440
|
+
end
|
441
|
+
|
442
|
+
collect_data(:freebsd, :openbsd, :netbsd, :dragonflybsd) do
|
443
|
+
fs = Mash.new
|
444
|
+
|
445
|
+
# Grab filesystem data from df
|
446
|
+
run_with_check("df") do
|
447
|
+
so = shell_out("df")
|
448
|
+
fs.merge!(parse_common_df(so.stdout))
|
449
|
+
|
450
|
+
so = shell_out("df -iP")
|
451
|
+
so.stdout.lines do |line|
|
452
|
+
case line
|
453
|
+
when /^Filesystem/ # skip the header
|
454
|
+
next
|
455
|
+
when /^(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\%\s+(\d+)\s+(\d+)\s+(\d+)%\s+(\S+)$/
|
456
|
+
key = "#{$1},#{$9}"
|
457
|
+
fs[key] ||= Mash.new
|
458
|
+
fs[key][:device] = $1
|
459
|
+
fs[key][:inodes_used] = $6
|
460
|
+
fs[key][:inodes_available] = $7
|
461
|
+
fs[key][:total_inodes] = ($6.to_i + $7.to_i).to_s
|
462
|
+
fs[key][:inodes_percent_used] = $8
|
463
|
+
fs[key][:mount] = $9
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
# Grab mount information from mount
|
469
|
+
run_with_check("mount") do
|
470
|
+
so = shell_out("mount -l")
|
471
|
+
so.stdout.lines do |line|
|
472
|
+
if line =~ /^(.+?) on (.+?) \((.+?), (.+?)\)$/
|
473
|
+
key = "#{$1},#{$2}"
|
474
|
+
fs[key] ||= Mash.new
|
475
|
+
fs[key][:device] = $1
|
476
|
+
fs[key][:mount] = $2
|
477
|
+
fs[key][:fs_type] = $3
|
478
|
+
fs[key][:mount_options] = $4.split(/,\s*/)
|
479
|
+
end
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
# create views
|
484
|
+
by_pair = fs
|
485
|
+
by_device = generate_device_view(fs)
|
486
|
+
by_mountpoint = generate_mountpoint_view(fs)
|
487
|
+
|
488
|
+
fs_data = Mash.new
|
489
|
+
fs_data["by_device"] = by_device
|
490
|
+
fs_data["by_mountpoint"] = by_mountpoint
|
491
|
+
fs_data["by_pair"] = by_pair
|
492
|
+
|
493
|
+
filesystem fs_data
|
494
|
+
end
|
495
|
+
|
496
|
+
collect_data(:darwin) do
|
497
|
+
fs = Mash.new
|
498
|
+
block_size = 0
|
499
|
+
# on new versions of OSX, -i is default, on old versions it's not, so
|
500
|
+
# specifying it gets consistent output
|
501
|
+
run_with_check("df") do
|
502
|
+
so = shell_out("df -i")
|
503
|
+
so.stdout.each_line do |line|
|
504
|
+
case line
|
505
|
+
when /^Filesystem\s+(\d+)-/
|
506
|
+
block_size = $1.to_i
|
507
|
+
next
|
508
|
+
when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(\d+)\s+(\d+)\s+(\d+%)\s+(.+)$/
|
509
|
+
key = "#{$1},#{$9}"
|
510
|
+
fs[key] = Mash.new
|
511
|
+
fs[key][:block_size] = block_size
|
512
|
+
fs[key][:device] = $1
|
513
|
+
fs[key][:kb_size] = ($2.to_i / (1024 / block_size)).to_s
|
514
|
+
fs[key][:kb_used] = ($3.to_i / (1024 / block_size)).to_s
|
515
|
+
fs[key][:kb_available] = ($4.to_i / (1024 / block_size)).to_s
|
516
|
+
fs[key][:percent_used] = $5
|
517
|
+
fs[key][:inodes_used] = $6
|
518
|
+
fs[key][:inodes_available] = $7
|
519
|
+
fs[key][:total_inodes] = ($6.to_i + $7.to_i).to_s
|
520
|
+
fs[key][:inodes_percent_used] = $8
|
521
|
+
fs[key][:mount] = $9
|
522
|
+
end
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
run_with_check("mount") do
|
527
|
+
so = shell_out("mount")
|
528
|
+
so.stdout.lines do |line|
|
529
|
+
if line =~ /^(.+?) on (.+?) \((.+?), (.+?)\)$/
|
530
|
+
key = "#{$1},#{$2}"
|
531
|
+
fs[key] ||= Mash.new
|
532
|
+
fs[key][:mount] = $2
|
533
|
+
fs[key][:fs_type] = $3
|
534
|
+
fs[key][:mount_options] = $4.split(/,\s*/)
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
by_pair = fs
|
540
|
+
by_device = generate_device_view(fs)
|
541
|
+
by_mountpoint = generate_mountpoint_view(fs)
|
542
|
+
|
543
|
+
fs_data = Mash.new
|
544
|
+
fs_data["by_device"] = by_device
|
545
|
+
fs_data["by_mountpoint"] = by_mountpoint
|
546
|
+
fs_data["by_pair"] = by_pair
|
547
|
+
|
548
|
+
filesystem fs_data
|
549
|
+
end
|
550
|
+
|
551
|
+
collect_data(:solaris2) do
|
552
|
+
fs = Mash.new
|
553
|
+
|
554
|
+
# Grab filesystem data from df
|
555
|
+
run_with_check("df") do
|
556
|
+
so = shell_out("df -Pka")
|
557
|
+
fs.merge!(parse_common_df(so.stdout))
|
558
|
+
|
559
|
+
# Grab file system type from df (must be done separately)
|
560
|
+
so = shell_out("df -na")
|
561
|
+
so.stdout.lines do |line|
|
562
|
+
next unless line =~ /^(.+?)\s*: (\S+)\s*$/
|
563
|
+
|
564
|
+
mount = $1
|
565
|
+
fs.each do |key, fs_attributes|
|
566
|
+
next unless fs_attributes[:mount] == mount
|
567
|
+
|
568
|
+
fs[key][:fs_type] = $2
|
569
|
+
end
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
# Grab mount information from /bin/mount
|
574
|
+
run_with_check("mount") do
|
575
|
+
so = shell_out("mount")
|
576
|
+
so.stdout.lines do |line|
|
577
|
+
next unless line =~ /^(.+?) on (.+?) (.+?) on (.+?)$/
|
578
|
+
|
579
|
+
key = "#{$2},#{$1}"
|
580
|
+
fs[key] ||= Mash.new
|
581
|
+
fs[key][:mount] = $1
|
582
|
+
fs[key][:mount_time] = $4 # $4 must come before "split", else it becomes nil
|
583
|
+
fs[key][:mount_options] = $3.split("/")
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
# Grab any zfs data from "zfs get"
|
588
|
+
zfs = Mash.new
|
589
|
+
zfs_get = "zfs get -p -H all"
|
590
|
+
run_with_check("zfs") do
|
591
|
+
so = shell_out(zfs_get)
|
592
|
+
so.stdout.lines do |line|
|
593
|
+
next unless line =~ /^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)$/
|
594
|
+
|
595
|
+
filesystem = $1
|
596
|
+
property = $2
|
597
|
+
value = $3
|
598
|
+
source = $4.chomp
|
599
|
+
zfs[filesystem] ||= Mash.new
|
600
|
+
# if this fs doesn't exist, put in the bare minimum
|
601
|
+
zfs[filesystem][property] = {
|
602
|
+
value: value,
|
603
|
+
source: source,
|
604
|
+
}
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
zfs.each do |fs_name, attributes|
|
609
|
+
mountpoint = attributes[:mountpoint][:value] if attributes[:mountpoint]
|
610
|
+
key = "#{fs_name},#{mountpoint}"
|
611
|
+
fs[key] ||= Mash.new
|
612
|
+
fs[key][:fs_type] = "zfs"
|
613
|
+
fs[key][:mount] = mountpoint if mountpoint
|
614
|
+
fs[key][:device] = fs_name
|
615
|
+
fs[key][:zfs_properties] = attributes
|
616
|
+
# find all zfs parents
|
617
|
+
parents = fs_name.split("/")
|
618
|
+
zfs_parents = []
|
619
|
+
(0..parents.length - 1).to_a.each do |parent_index|
|
620
|
+
next_parent = parents[0..parent_index].join("/")
|
621
|
+
zfs_parents.push(next_parent)
|
622
|
+
end
|
623
|
+
zfs_parents.pop
|
624
|
+
fs[key][:zfs_parents] = zfs_parents
|
625
|
+
fs[key][:zfs_zpool] = (zfs_parents.length == 0)
|
626
|
+
end
|
627
|
+
|
628
|
+
# create views
|
629
|
+
by_pair = fs
|
630
|
+
by_device = generate_device_view(fs)
|
631
|
+
by_mountpoint = generate_mountpoint_view(fs)
|
632
|
+
|
633
|
+
fs_data = Mash.new
|
634
|
+
fs_data["by_device"] = by_device
|
635
|
+
fs_data["by_mountpoint"] = by_mountpoint
|
636
|
+
fs_data["by_pair"] = by_pair
|
637
|
+
|
638
|
+
filesystem fs_data
|
639
|
+
end
|
640
|
+
|
641
|
+
collect_data(:aix) do
|
642
|
+
def parse_df_or_mount(shell_out)
|
643
|
+
oldie = Mash.new
|
644
|
+
|
645
|
+
shell_out.lines.each do |line|
|
646
|
+
fields = line.split
|
647
|
+
case line
|
648
|
+
# headers and horizontal rules to skip
|
649
|
+
when /^\s*(node|---|^Filesystem\s+1024-blocks)/
|
650
|
+
next
|
651
|
+
# strictly a df entry
|
652
|
+
when /^(.+?)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+\%*)\s+(.+)$/
|
653
|
+
if $1 == "Global"
|
654
|
+
dev = "#{$1}:#{$6}"
|
655
|
+
else
|
656
|
+
dev = $1
|
657
|
+
end
|
658
|
+
mountpoint = $6
|
659
|
+
key = "#{dev},#{mountpoint}"
|
660
|
+
oldie[key] ||= Mash.new
|
661
|
+
oldie[key][:kb_size] = $2
|
662
|
+
oldie[key][:kb_used] = $3
|
663
|
+
oldie[key][:kb_available] = $4
|
664
|
+
oldie[key][:percent_used] = $5
|
665
|
+
oldie[key][:mount] = mountpoint
|
666
|
+
oldie[key][:device] = dev
|
667
|
+
# an entry starting with 'G' or / (E.G. /tmp or /var)
|
668
|
+
when %r{^\s*(G.*?|/\w)}
|
669
|
+
if fields[0] == "Global"
|
670
|
+
dev = fields[0] + ":" + fields[1]
|
671
|
+
else
|
672
|
+
dev = fields[0]
|
673
|
+
end
|
674
|
+
mountpoint = fields[1]
|
675
|
+
key = "#{dev},#{mountpoint}"
|
676
|
+
oldie[key] ||= Mash.new
|
677
|
+
oldie[key][:mount] = mountpoint
|
678
|
+
oldie[key][:fs_type] = fields[2]
|
679
|
+
oldie[key][:mount_options] = fields[6].split(",")
|
680
|
+
oldie[key][:device] = dev
|
681
|
+
# entries occupying the 'Node' column parsed here
|
682
|
+
else
|
683
|
+
dev = fields[0] + ":" + fields[1]
|
684
|
+
mountpoint = fields[2]
|
685
|
+
key = "#{dev},#{mountpoint}"
|
686
|
+
oldie[key] ||= Mash.new
|
687
|
+
oldie[key][:mount] = mountpoint
|
688
|
+
oldie[key][:device] = dev
|
689
|
+
oldie[key][:fs_type] = fields[3]
|
690
|
+
oldie[key][:mount_options] = fields[7].split(",")
|
691
|
+
end
|
692
|
+
end
|
693
|
+
oldie
|
694
|
+
end
|
695
|
+
|
696
|
+
def collect_old_version(shell_outs)
|
697
|
+
mount_hash = parse_df_or_mount shell_outs[:mount]
|
698
|
+
df_hash = parse_df_or_mount shell_outs[:df_Pk]
|
699
|
+
|
700
|
+
mount_hash.each do |key, hash|
|
701
|
+
df_hash[key].merge!(hash) if df_hash.key?(key)
|
702
|
+
end
|
703
|
+
|
704
|
+
mount_hash.merge(df_hash)
|
705
|
+
end
|
706
|
+
|
707
|
+
# Cache the command output
|
708
|
+
shell_outs = Mash.new
|
709
|
+
|
710
|
+
run_with_check("mount") do
|
711
|
+
shell_outs[:mount] = shell_out("mount").stdout
|
712
|
+
end
|
713
|
+
|
714
|
+
run_with_check("df") do
|
715
|
+
shell_outs[:df_Pk] = shell_out("df -Pk").stdout
|
716
|
+
end
|
717
|
+
|
718
|
+
fs = collect_old_version(shell_outs)
|
719
|
+
by_pair = fs
|
720
|
+
by_device = generate_device_view(fs)
|
721
|
+
by_mountpoint = generate_mountpoint_view(fs)
|
722
|
+
|
723
|
+
fs_data = Mash.new
|
724
|
+
fs_data["by_device"] = by_device
|
725
|
+
fs_data["by_mountpoint"] = by_mountpoint
|
726
|
+
fs_data["by_pair"] = by_pair
|
727
|
+
|
728
|
+
filesystem fs_data
|
729
|
+
end
|
730
|
+
|
731
|
+
collect_data(:windows) do
|
732
|
+
require "set" unless defined?(Set)
|
733
|
+
require "wmi-lite/wmi" unless defined?(WmiLite::Wmi)
|
734
|
+
require_relative "../mash"
|
735
|
+
|
736
|
+
fs = merge_info(logical_info, encryptable_info)
|
737
|
+
|
738
|
+
by_pair = fs
|
739
|
+
by_device = generate_device_view(fs)
|
740
|
+
by_mountpoint = generate_mountpoint_view(fs)
|
741
|
+
|
742
|
+
fs_data = Mash.new
|
743
|
+
fs_data["by_device"] = by_device
|
744
|
+
fs_data["by_mountpoint"] = by_mountpoint
|
745
|
+
fs_data["by_pair"] = by_pair
|
746
|
+
|
747
|
+
# Chef 16 added 'filesystem2'
|
748
|
+
# In Chef 17 we made 'filesystem' and 'filesystem2' match (both new-style)
|
749
|
+
# In Chef 18 we will drop 'filesystem2'
|
750
|
+
filesystem fs_data
|
751
|
+
filesystem2 fs_data
|
752
|
+
end
|
753
|
+
end
|