summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Dibowitz <phil@ipom.com>2015-06-24 01:03:29 +0100
committerPhil Dibowitz <phil@ipom.com>2015-06-24 01:03:29 +0100
commitb864a44aba4dea946667983e774ac37155fe3c26 (patch)
tree672f44931d265a04a32b779016ed7ec61bed818d
parent5c166cf3fa4b2af541ee54855aae73c809044b3d (diff)
parentd6811b7257a0f35d2e38e3e18505365e3a268a39 (diff)
downloadohai-b864a44aba4dea946667983e774ac37155fe3c26.tar.gz
Merge pull request #559 from jaymzh/filesystem2
Provide a new and improved linux filesystem plugin
-rw-r--r--CHANGELOG.md3
-rw-r--r--RELEASE_NOTES.md36
-rw-r--r--lib/ohai/plugins/linux/filesystem2.rb218
-rw-r--r--spec/unit/plugins/linux/filesystem2_spec.rb337
4 files changed, 594 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 298c1a52..4de106eb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@
* [PR #548](https://github.com/chef/ohai/548):
Coerce non-UTF8 strings to UTF8 in output to suppress UTF8 encoding exceptions
+* [**Phil Dibowitz**](https://github.com/jymzh):
+ Provide a new and improved filesystem plugin for Linux (filesystem2), to
+ support CentOS7, multiple virtual filesystes, etc.
* [PR #544](https://github.com/chef/ohai/pull/544)
add support for Wind River Linux and Cisco's Nexus platforms
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 115a759e..137685d6 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -24,6 +24,42 @@ node[:virtualization][:systems][:vmware] = "guest"
Due to the requirements for being an LXC host being easily fulfilled, we only
populate the old system (role & system) with LXC if there are no other virtualization systems detected.
+
+### Filesystem2
+
+There is a new plugin for filesystems in Linux. It solves several problems:
+* Can handle multiple virtual FSes with the same "device" (eg, 'none')
+* Can handle a device mounted multiple places
+* Is resilient to mtab being a symlink to /proc/mounts
+* Provides multiple views for ease of use
+* Provides a mechanism that has gauranteed lack of overwritten data
+* Forks far fewer times than it's predecessor
+
+Unlike the 'filesystem' plugin, it provides 3 views into the data:
+
+* `by_pair` is the primary one and what most users are expected to use. It
+ gaurantees no loss of data from conflict and has an entry in the hash for each
+ pair of $device,$mountpoint (or "$device," for unmounted devices).
+* `by_device` a similar layout to the original filesystem plugin which is
+ indexed by device, except that 'mount' entry is now 'mounts' and is an array.
+ While this solves many of the problems users can encounter by having /etc/mtab
+ be a symlink to /proc/mounts it can still have data loss due to different
+ mount options, or multiple virtualfs mounts with the same fake device name.
+* `by_mount` similar to the above but indexed by mountpoint. Won't include
+ unmounted filesystems, of course.
+
+It is recommended to always use `by_pair` when iterating or wanting a full view
+of storage devices. The other two are provided for convenient lookup. Other
+notes:
+
+* The `by_mount` view handles conflicts in a last-wins manner. Other than that,
+ fields should be the same except for the lack of a "mount" key inside entries
+ (since that's the key to the structure)
+* The `by_device` mount changes the structure slightly to replace 'mount' key in
+ each structure with 'mounts' - an array of mountpoints instead of overwriting
+ values. For other conflicts last one wins. 'devices' is not a key inside
+ entries since it's the key to the structure.
+
### Miscellaneous
* Ohai now collects mdadm RAID information.
diff --git a/lib/ohai/plugins/linux/filesystem2.rb b/lib/ohai/plugins/linux/filesystem2.rb
new file mode 100644
index 00000000..bad4277a
--- /dev/null
+++ b/lib/ohai/plugins/linux/filesystem2.rb
@@ -0,0 +1,218 @@
+#
+# Author:: Phil Dibowitz <phil@ipom.com>
+# Author:: Adam Jacob <adam@chef.io>
+# Copyright:: Copyright (c) 2008 Opscode, Inc.
+# Copyright:: Copyright (c) 2015 Facebook, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+Ohai.plugin(:Filesystem2) do
+ provides "filesystem2"
+
+ def find_device(name)
+ %w{/dev /dev/mapper}.each do |dir|
+ path = File.join(dir, name)
+ return path if File.exist?(path)
+ end
+ name
+ end
+
+ def parse_line(line, have_lsblk)
+ if have_lsblk
+ regex = /NAME="(\S+)" UUID="(\S*)" LABEL="(\S*)" FSTYPE="(\S*)"/
+ if line =~ regex
+ dev = $1
+ dev = find_device(dev) unless dev.start_with?('/')
+ uuid = $2
+ label = $3
+ fs_type = $4
+ return {:dev => dev, :uuid => uuid, :label => label, :fs_type => fs_type}
+ end
+ else
+ bits = line.split
+ dev = bits.shift.split(':')[0]
+ f = {:dev => dev}
+ bits.each do |keyval|
+ if keyval =~ /(\S+)="(\S+)"/
+ key = $1.downcase.to_sym
+ key = :fs_type if key == :type
+ f[key] = $2
+ end
+ end
+ return f
+ end
+ return nil
+ end
+
+ def generate_device_view(fs)
+ view = {}
+ fs.each_value do |entry|
+ view[entry[:device]] = Mash.new unless view[entry[:device]]
+ entry.each do |key, val|
+ next if ['device', 'mount'].include?(key)
+ view[entry[:device]][key] = val
+ end
+ if entry[:mount]
+ view[entry[:device]][:mounts] = [] unless view[entry[:device]][:mounts]
+ view[entry[:device]][:mounts] << entry[:mount]
+ end
+ end
+ view
+ end
+
+ def generate_mountpoint_view(fs)
+ view = {}
+ fs.each_value do |entry|
+ next unless entry[:mount]
+ view[entry[:mount]] = Mash.new unless view[entry[:mount]]
+ entry.each do |key, val|
+ next if key == 'mount'
+ view[entry[:mount]][key] = val
+ end
+ end
+ view
+ end
+
+ collect_data(:linux) do
+ fs = Mash.new
+
+ # Grab filesystem data from df
+ so = shell_out("df -P")
+ so.stdout.each_line do |line|
+ case line
+ when /^Filesystem\s+1024-blocks/
+ next
+ when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(.+)$/
+ key = "#{$1},#{$6}"
+ fs[key] = Mash.new
+ fs[key][:device] = $1
+ fs[key][:kb_size] = $2
+ fs[key][:kb_used] = $3
+ fs[key][:kb_available] = $4
+ fs[key][:percent_used] = $5
+ fs[key][:mount] = $6
+ end
+ end
+
+ # Grab filesystem inode data from df
+ so = shell_out("df -iP")
+ so.stdout.each_line do |line|
+ case line
+ when /^Filesystem\s+Inodes/
+ next
+ when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(.+)$/
+ key = "#{$1},#{$6}"
+ fs[key] ||= Mash.new
+ fs[key][:device] = $1
+ fs[key][:total_inodes] = $2
+ fs[key][:inodes_used] = $3
+ fs[key][:inodes_available] = $4
+ fs[key][:inodes_percent_used] = $5
+ fs[key][:mount] = $6
+ end
+ end
+
+ # Grab mount information from /bin/mount
+ so = shell_out("mount")
+ so.stdout.each_line do |line|
+ if line =~ /^(.+?) on (.+?) type (.+?) \((.+?)\)$/
+ key = "#{$1},#{$2}"
+ fs[key] = Mash.new unless fs.has_key?(key)
+ fs[key][:device] = $1
+ fs[key][:mount] = $2
+ fs[key][:fs_type] = $3
+ fs[key][:mount_options] = $4.split(",")
+ end
+ end
+
+ have_lsblk = File.exist?('/bin/lsblk')
+ if have_lsblk
+ cmd = 'lsblk -n -P -o NAME,UUID,LABEL,FSTYPE'
+ else
+ # CentOS5 and other platforms don't have lsblk
+ cmd = 'blkid'
+ end
+
+ so = shell_out(cmd)
+ so.stdout.each_line do |line|
+ parsed = parse_line(line, have_lsblk)
+ next if parsed.nil?
+ # lsblk lists each device once, so we need to update all entries
+ # in the hash that are related to this device
+ keys_to_update = []
+ fs.each_key do |key|
+ keys_to_update << key if key.start_with?("#{parsed[:dev]},")
+ end
+
+ if keys_to_update.empty?
+ key = "#{parsed[:dev]},"
+ fs[key] = Mash.new
+ fs[key][:device] = parsed[:dev]
+ keys_to_update << key
+ end
+
+ keys_to_update.each do |key|
+ [:fs_type, :uuid, :label].each do |subkey|
+ if parsed[subkey] && !parsed[subkey].empty?
+ fs[key][subkey] = parsed[subkey]
+ end
+ end
+ end
+ end
+
+ # Grab any missing mount information from /proc/mounts
+ if File.exist?('/proc/mounts')
+ mounts = ''
+ # Due to https://tickets.opscode.com/browse/OHAI-196
+ # we have to non-block read dev files. Ew.
+ f = File.open('/proc/mounts')
+ loop do
+ begin
+ data = f.read_nonblock(4096)
+ mounts << data
+ # We should just catch EOFError, but the kernel had a period of
+ # bugginess with reading virtual files, so we're being extra
+ # cautious here, catching all exceptions, and then we'll read
+ # whatever data we might have
+ rescue Exception
+ break
+ end
+ end
+ f.close
+ mounts.each_line do |line|
+ if line =~ /^(\S+) (\S+) (\S+) (\S+) \S+ \S+$/
+ key = "#{$1},#{$2}"
+ next if fs.has_key?(key)
+ fs[key] = Mash.new
+ fs[key][:mount] = $2
+ fs[key][:fs_type] = $3
+ fs[key][:mount_options] = $4.split(",")
+ end
+ end
+ end
+
+ by_pair = fs
+ by_device = generate_device_view(fs)
+ by_mountpoint = generate_mountpoint_view(fs)
+
+ fs2 = Mash.new
+ fs2['by_device'] = by_device
+ fs2['by_mountpoint'] = by_mountpoint
+ fs2['by_pair'] = by_pair
+
+ # Set the filesystem data
+ filesystem2 fs2
+ end
+end
diff --git a/spec/unit/plugins/linux/filesystem2_spec.rb b/spec/unit/plugins/linux/filesystem2_spec.rb
new file mode 100644
index 00000000..de14225c
--- /dev/null
+++ b/spec/unit/plugins/linux/filesystem2_spec.rb
@@ -0,0 +1,337 @@
+#
+# Author:: Matthew Kent (<mkent@magoazul.com>)
+# Copyright:: Copyright (c) 2011 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper.rb')
+
+describe Ohai::System, "Linux filesystem plugin" do
+ before(:each) do
+ @plugin = get_plugin("linux/filesystem2")
+ allow(@plugin).to receive(:collect_os).and_return(:linux)
+
+ allow(@plugin).to receive(:shell_out).with("df -P").and_return(mock_shell_out(0, "", ""))
+ allow(@plugin).to receive(:shell_out).with("df -iP").and_return(mock_shell_out(0, "", ""))
+ allow(@plugin).to receive(:shell_out).with("mount").and_return(mock_shell_out(0, "", ""))
+ allow(File).to receive(:exist?).with("/bin/lsblk").and_return(false)
+ allow(@plugin).to receive(:shell_out).with("blkid").and_return(mock_shell_out(0, "", ""))
+
+ allow(@plugin).to receive(:shell_out).
+ with("lsblk -n -P -o NAME,UUID,LABEL,FSTYPE").
+ and_return(mock_shell_out(0, "", ""))
+
+ allow(File).to receive(:exist?).with("/proc/mounts").and_return(false)
+
+ %w{sdb1 sdb2 sda1 sda2 md0 md1 md2}.each do |name|
+ allow(File).to receive(:exist?).with("/dev/#{name}").and_return(true)
+ end
+ %w{
+ sys.vg-root.lv
+ sys.vg-swap.lv
+ sys.vg-tmp.lv
+ sys.vg-usr.lv
+ sys.vg-var.lv
+ sys.vg-home.lv
+ }.each do |name|
+ allow(File).to receive(:exist?).with("/dev/#{name}").and_return(false)
+ allow(File).to receive(:exist?).with("/dev/mapper/#{name}").and_return(true)
+ end
+ end
+
+ describe "when gathering filesystem usage data from df" do
+ before(:each) do
+ @stdout = <<-DF
+Filesystem 1024-blocks Used Available Capacity Mounted on
+/dev/mapper/sys.vg-root.lv 4805760 378716 4182924 9% /
+tmpfs 2030944 0 2030944 0% /lib/init/rw
+udev 2025576 228 2025348 1% /dev
+tmpfs 2030944 2960 2027984 1% /dev/shm
+/dev/mapper/sys.vg-home.lv 97605056 53563252 44041804 55% /home
+/dev/mapper/sys.vg-special.lv 97605057 53563253 44041805 56% /special
+/dev/mapper/sys.vg-tmp.lv 1919048 46588 1774976 3% /tmp
+/dev/mapper/sys.vg-usr.lv 19223252 5479072 12767696 31% /usr
+/dev/mapper/sys.vg-var.lv 19223252 3436556 14810212 19% /var
+/dev/md0 960492 36388 875312 4% /boot
+DF
+ allow(@plugin).to receive(:shell_out).with("df -P").and_return(mock_shell_out(0, @stdout, ""))
+
+ @inode_stdout = <<-DFi
+Filesystem Inodes IUsed IFree IUse% Mounted on
+/dev/xvda1 1310720 107407 1203313 9% /
+/dev/mapper/sys.vg-special.lv 124865 380 124485 1% /special
+tmpfs 126922 273 126649 1% /run
+none 126922 1 126921 1% /run/lock
+none 126922 1 126921 1% /run/shm
+DFi
+ allow(@plugin).to receive(:shell_out).with("df -iP").and_return(mock_shell_out(0, @inode_stdout, ""))
+ end
+
+ it "should run df -P and df -iP" do
+ expect(@plugin).to receive(:shell_out).ordered.with("df -P").and_return(mock_shell_out(0, @stdout, ""))
+ expect(@plugin).to receive(:shell_out).ordered.with("df -iP").and_return(mock_shell_out(0, @inode_stdout, ""))
+ @plugin.run
+ end
+
+ it "should set kb_size to value from df -P" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:kb_size]).to eq("97605057")
+ end
+
+ it "should set kb_used to value from df -P" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:kb_used]).to eq("53563253")
+ end
+
+ it "should set kb_available to value from df -P" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:kb_available]).to eq("44041805")
+ end
+
+ it "should set percent_used to value from df -P" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:percent_used]).to eq("56%")
+ end
+
+ it "should set mount to value from df -P" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:mount]).to eq("/special")
+ end
+
+ it "should set total_inodes to value from df -iP" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:total_inodes]).to eq("124865")
+ end
+
+ it "should set inodes_used to value from df -iP" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:inodes_used]).to eq("380")
+ end
+
+ it "should set inodes_available to value from df -iP" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:inodes_available]).to eq("124485")
+ end
+ end
+
+ describe "when gathering mounted filesystem data from mount" do
+ before(:each) do
+ @stdout = <<-MOUNT
+/dev/mapper/sys.vg-root.lv on / type ext4 (rw,noatime,errors=remount-ro)
+tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
+proc on /proc type proc (rw,noexec,nosuid,nodev)
+sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
+udev on /dev type tmpfs (rw,mode=0755)
+tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
+devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)
+/dev/mapper/sys.vg-home.lv on /home type xfs (rw,noatime)
+/dev/mapper/sys.vg-special.lv on /special type xfs (ro,noatime)
+/dev/mapper/sys.vg-tmp.lv on /tmp type ext4 (rw,noatime)
+/dev/mapper/sys.vg-usr.lv on /usr type ext4 (rw,noatime)
+/dev/mapper/sys.vg-var.lv on /var type ext4 (rw,noatime)
+/dev/md0 on /boot type ext3 (rw,noatime,errors=remount-ro)
+fusectl on /sys/fs/fuse/connections type fusectl (rw)
+binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev)
+MOUNT
+ allow(@plugin).to receive(:shell_out).with("mount").and_return(mock_shell_out(0, @stdout, ""))
+ end
+
+ it "should run mount" do
+ expect(@plugin).to receive(:shell_out).with("mount").and_return(mock_shell_out(0, @stdout, ""))
+ @plugin.run
+ end
+
+ it "should set mount to value from mount" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:mount]).to eq("/special")
+ end
+
+ it "should set fs_type to value from mount" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:fs_type]).to eq("xfs")
+ end
+
+ it "should set mount_options to an array of values from mount" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:mount_options]).to eq([ "ro", "noatime" ])
+ end
+ end
+
+ describe "when gathering filesystem type data from blkid" do
+ before(:each) do
+ # blkid and lsblk output are coorelated with df/mount output, so the
+ # most full test of them actually requires we have both
+ @dfstdout = <<-DF
+Filesystem 1024-blocks Used Available Capacity Mounted on
+/dev/mapper/sys.vg-root.lv 4805760 378716 4182924 9% /
+tmpfs 2030944 0 2030944 0% /lib/init/rw
+udev 2025576 228 2025348 1% /dev
+tmpfs 2030944 2960 2027984 1% /dev/shm
+/dev/mapper/sys.vg-home.lv 97605056 53563252 44041804 55% /home
+/dev/mapper/sys.vg-special.lv 97605057 53563253 44041805 56% /special
+/dev/mapper/sys.vg-tmp.lv 1919048 46588 1774976 3% /tmp
+/dev/mapper/sys.vg-usr.lv 19223252 5479072 12767696 31% /usr
+/dev/mapper/sys.vg-var.lv 19223252 3436556 14810212 19% /var
+/dev/md0 960492 36388 875312 4% /boot
+DF
+ allow(@plugin).to receive(:shell_out).with("df -P").and_return(mock_shell_out(0, @dfstdout, ""))
+
+ @inode_stdout = <<-DFi
+Filesystem Inodes IUsed IFree IUse% Mounted on
+/dev/xvda1 1310720 107407 1203313 9% /
+/dev/mapper/sys.vg-special.lv 124865 380 124485 1% /special
+tmpfs 126922 273 126649 1% /run
+none 126922 1 126921 1% /run/lock
+none 126922 1 126921 1% /run/shm
+DFi
+ allow(@plugin).to receive(:shell_out).with("df -iP").and_return(mock_shell_out(0, @inode_stdout, ""))
+
+ @stdout = <<-BLKID_TYPE
+/dev/sdb1: LABEL=\"fuego:0\" UUID=\"bd1197e0-6997-1f3a-e27e-7801388308b5\" TYPE=\"linux_raid_member\"
+/dev/sdb2: LABEL=\"fuego:1\" UUID=\"e36d933e-e5b9-cfe5-6845-1f84d0f7fbfa\" TYPE=\"linux_raid_member\"
+/dev/sda1: LABEL=\"fuego:0\" UUID=\"bd1197e0-6997-1f3a-e27e-7801388308b5\" TYPE=\"linux_raid_member\"
+/dev/sda2: LABEL=\"fuego:1\" UUID=\"e36d933e-e5b9-cfe5-6845-1f84d0f7fbfa\" TYPE=\"linux_raid_member\"
+/dev/md0: LABEL=\"/boot\" UUID=\"37b8de8e-0fe3-4b5a-b9b4-dde33e19bb32\" TYPE=\"ext3\"
+/dev/md1: UUID=\"YsIe0R-fj1y-LXTd-imla-opKo-OuIe-TBoxSK\" TYPE=\"LVM2_member\"
+/dev/mapper/sys.vg-root.lv: LABEL=\"/\" UUID=\"7742d14b-80a3-4e97-9a32-478be9ea9aea\" TYPE=\"ext4\"
+/dev/mapper/sys.vg-swap.lv: UUID=\"9bc2e515-8ddc-41c3-9f63-4eaebde9ce96\" TYPE=\"swap\"
+/dev/mapper/sys.vg-tmp.lv: LABEL=\"/tmp\" UUID=\"74cf7eb9-428f-479e-9a4a-9943401e81e5\" TYPE=\"ext4\"
+/dev/mapper/sys.vg-usr.lv: LABEL=\"/usr\" UUID=\"26ec33c5-d00b-4f88-a550-492def013bbc\" TYPE=\"ext4\"
+/dev/mapper/sys.vg-var.lv: LABEL=\"/var\" UUID=\"6b559c35-7847-4ae2-b512-c99012d3f5b3\" TYPE=\"ext4\"
+/dev/mapper/sys.vg-home.lv: LABEL=\"/home\" UUID=\"d6efda02-1b73-453c-8c74-7d8dee78fa5e\" TYPE=\"xfs\"
+BLKID_TYPE
+ allow(@plugin).to receive(:shell_out).with("blkid").and_return(mock_shell_out(0, @stdout, ""))
+ end
+
+ it "should run blkid" do
+ @plugin.run
+ end
+
+ it "should set kb_size to value from blkid" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/md1,"][:fs_type]).to eq("LVM2_member")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/sda2,"][:uuid]).to eq("e36d933e-e5b9-cfe5-6845-1f84d0f7fbfa")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/md0,/boot"][:label]).to eq("/boot")
+ end
+ end
+
+ describe "when gathering filesystem type data from lsblk" do
+ before(:each) do
+ @dfstdout = <<-DF
+Filesystem 1024-blocks Used Available Capacity Mounted on
+/dev/mapper/sys.vg-root.lv 4805760 378716 4182924 9% /
+tmpfs 2030944 0 2030944 0% /lib/init/rw
+udev 2025576 228 2025348 1% /dev
+tmpfs 2030944 2960 2027984 1% /dev/shm
+/dev/mapper/sys.vg-home.lv 97605056 53563252 44041804 55% /home
+/dev/mapper/sys.vg-special.lv 97605057 53563253 44041805 56% /special
+/dev/mapper/sys.vg-tmp.lv 1919048 46588 1774976 3% /tmp
+/dev/mapper/sys.vg-usr.lv 19223252 5479072 12767696 31% /usr
+/dev/mapper/sys.vg-var.lv 19223252 3436556 14810212 19% /var
+/dev/md0 960492 36388 875312 4% /boot
+DF
+ allow(@plugin).to receive(:shell_out).with("df -P").and_return(mock_shell_out(0, @dfstdout, ""))
+
+ @inode_stdout = <<-DFi
+Filesystem Inodes IUsed IFree IUse% Mounted on
+/dev/xvda1 1310720 107407 1203313 9% /
+/dev/mapper/sys.vg-special.lv 124865 380 124485 1% /special
+tmpfs 126922 273 126649 1% /run
+none 126922 1 126921 1% /run/lock
+none 126922 1 126921 1% /run/shm
+DFi
+ allow(@plugin).to receive(:shell_out).with("df -iP").and_return(mock_shell_out(0, @inode_stdout, ""))
+
+ allow(File).to receive(:exist?).with("/bin/lsblk").and_return(true)
+ @stdout = <<-BLKID_TYPE
+NAME=\"/dev/sdb1\" UUID=\"bd1197e0-6997-1f3a-e27e-7801388308b5\" LABEL=\"fuego:0\" FSTYPE=\"LVM2_member\"
+NAME=\"/dev/sdb2\" UUID=\"e36d933e-e5b9-cfe5-6845-1f84d0f7fbfa\" LABEL=\"fuego:1\" FSTYPE=\"LVM2_member\"
+NAME=\"/dev/sda1\" UUID=\"bd1197e0-6997-1f3a-e27e-7801388308b5\" LABEL=\"fuego:0\" FSTYPE=\"LVM2_member\"
+NAME=\"/dev/sda2\" UUID=\"e36d933e-e5b9-cfe5-6845-1f84d0f7fbfa\" LABEL=\"fuego:1\" FSTYPE=\"LVM2_member\"
+NAME=\"/dev/md0\" UUID=\"37b8de8e-0fe3-4b5a-b9b4-dde33e19bb32\" LABEL=\"/boot\" FSTYPE=\"ext3\"
+NAME=\"/dev/md1\" UUID=\"YsIe0R-fj1y-LXTd-imla-opKo-OuIe-TBoxSK\" LABEL=\"\" FSTYPE=\"LVM2_member\"
+NAME=\"/dev/mapper/sys.vg-root.lv\" UUID=\"7742d14b-80a3-4e97-9a32-478be9ea9aea\" LABEL=\"/\" FSTYPE=\"ext4\"
+NAME=\"/dev/mapper/sys.vg-swap.lv\" UUID=\"9bc2e515-8ddc-41c3-9f63-4eaebde9ce96\" LABEL=\"\" FSTYPE=\"swap\"
+NAME=\"/dev/mapper/sys.vg-tmp.lv\" UUID=\"74cf7eb9-428f-479e-9a4a-9943401e81e5\" LABEL=\"/tmp\" FSTYPE=\"ext4\"
+NAME=\"/dev/mapper/sys.vg-usr.lv\" UUID=\"26ec33c5-d00b-4f88-a550-492def013bbc\" LABEL=\"/usr\" FSTYPE=\"ext4\"
+NAME=\"/dev/mapper/sys.vg-var.lv\" UUID=\"6b559c35-7847-4ae2-b512-c99012d3f5b3\" LABEL=\"/var\" FSTYPE=\"ext4\"
+NAME=\"/dev/mapper/sys.vg-home.lv\" UUID=\"d6efda02-1b73-453c-8c74-7d8dee78fa5e\" LABEL=\"/home\" FSTYPE=\"xfs\"
+BLKID_TYPE
+ allow(@plugin).to receive(:shell_out).
+ with("lsblk -n -P -o NAME,UUID,LABEL,FSTYPE").
+ and_return(mock_shell_out(0, @stdout, ""))
+ end
+
+ it "should run lsblk -n -P -o NAME,UUID,LABEL,FSTYPE" do
+ @plugin.run
+ end
+
+ it "should set kb_size to value from lsblk -n -P -o NAME,UUID,LABEL,FSTYPE" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/md1,"][:fs_type]).to eq("LVM2_member")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/sda2,"][:uuid]).to eq("e36d933e-e5b9-cfe5-6845-1f84d0f7fbfa")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/md0,/boot"][:label]).to eq("/boot")
+ end
+ end
+
+ describe "when gathering data from /proc/mounts" do
+ before(:each) do
+ allow(File).to receive(:exist?).with("/proc/mounts").and_return(true)
+ @double_file = double("/proc/mounts")
+ @mounts = <<-MOUNTS
+rootfs / rootfs rw 0 0
+none /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
+none /proc proc rw,nosuid,nodev,noexec,relatime 0 0
+none /dev devtmpfs rw,relatime,size=2025576k,nr_inodes=506394,mode=755 0 0
+none /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0
+/dev/mapper/sys.vg-root.lv / ext4 rw,noatime,errors=remount-ro,barrier=1,data=ordered 0 0
+tmpfs /lib/init/rw tmpfs rw,nosuid,relatime,mode=755 0 0
+tmpfs /dev/shm tmpfs rw,nosuid,nodev,relatime 0 0
+/dev/mapper/sys.vg-home.lv /home xfs rw,noatime,attr2,noquota 0 0
+/dev/mapper/sys.vg-special.lv /special xfs ro,noatime,attr2,noquota 0 0
+/dev/mapper/sys.vg-tmp.lv /tmp ext4 rw,noatime,barrier=1,data=ordered 0 0
+/dev/mapper/sys.vg-usr.lv /usr ext4 rw,noatime,barrier=1,data=ordered 0 0
+/dev/mapper/sys.vg-var.lv /var ext4 rw,noatime,barrier=1,data=ordered 0 0
+/dev/md0 /boot ext3 rw,noatime,errors=remount-ro,data=ordered 0 0
+fusectl /sys/fs/fuse/connections fusectl rw,relatime 0 0
+binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,nosuid,nodev,noexec,relatime 0 0
+MOUNTS
+ @counter = 0
+ allow(@double_file).to receive(:read_nonblock) do
+ @counter += 1
+ raise EOFError if @counter == 2
+ @mounts
+ end
+ allow(@double_file).to receive(:close)
+ allow(File).to receive(:open).with("/proc/mounts").and_return(@double_file)
+ end
+
+ it "should set mount to value from /proc/mounts" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:mount]).to eq("/special")
+ end
+
+ it "should set fs_type to value from /proc/mounts" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:fs_type]).to eq("xfs")
+ end
+
+ it "should set mount_options to an array of values from /proc/mounts" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/mapper/sys.vg-special.lv,/special"][:mount_options]).to eq([ "ro", "noatime", "attr2", "noquota" ])
+ end
+ end
+
+end