summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Dibowitz <phild@fb.com>2015-06-24 04:56:40 -0700
committerPhil Dibowitz <phild@fb.com>2015-06-24 04:57:40 -0700
commit27efdab791d59d239007f1dea9cbd4a75c27dfda (patch)
treee4ad18836280b138f40a6898d35719d4999066a1
parent132eef525ccf62bbd639e89d9e44094d0e13a2bc (diff)
downloadohai-27efdab791d59d239007f1dea9cbd4a75c27dfda.tar.gz
Port new filesystem2 plugin to darwin.
This is just a port of #559 to Darwin. See that PR for the details.
-rw-r--r--CHANGELOG.md2
-rw-r--r--RELEASE_NOTES.md3
-rw-r--r--lib/ohai/plugins/darwin/filesystem2.rb103
-rw-r--r--spec/unit/plugins/darwin/filesystem2_spec.rb96
4 files changed, 202 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac7e68c6..96c6acd4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@
## Unreleased
* [**Phil Dibowitz**](https://github.com/jymzh):
- Provide a new and improved filesystem plugin for Linux (filesystem2), to
+ Provide a new and improved filesystem plugin for Linux & Mac (filesystem2), to
support CentOS7, multiple virtual filesystes, etc.
* [**Jonathan Amiez**](https://github.com/josqu4red):
Linux filesystems plugin report wrong fs-type for logical volumes
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 137685d6..70008289 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -27,7 +27,8 @@ populate the old system (role & system) with LXC if there are no other virtualiz
### Filesystem2
-There is a new plugin for filesystems in Linux. It solves several problems:
+There is a new plugin for filesystems in Linux & Darwin. 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
diff --git a/lib/ohai/plugins/darwin/filesystem2.rb b/lib/ohai/plugins/darwin/filesystem2.rb
new file mode 100644
index 00000000..040e8c4d
--- /dev/null
+++ b/lib/ohai/plugins/darwin/filesystem2.rb
@@ -0,0 +1,103 @@
+#
+# Author:: Benjamin Black (<bb@opscode.com>)
+# Copyright:: Copyright (c) 2009 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.
+#
+
+Ohai.plugin(:Filesystem2) do
+ provides "filesystem2"
+
+ 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(:darwin) do
+ fs = Mash.new
+
+
+ block_size = 0
+ # on new versions of OSX, -i is default, on old versions it's not, so
+ # specifying it gets consistent output
+ so = shell_out("df -i")
+ so.stdout.each_line do |line|
+ case line
+ when /^Filesystem\s+(\d+)-/
+ block_size = $1.to_i
+ next
+ when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(\d+)\s+(\d+)\s+(\d+%)\s+(.+)$/
+ key = "#{$1},#{$9}"
+ fs[key] = Mash.new
+ fs[key][:block_size] = block_size
+ fs[key][:device] = $1
+ fs[key][:kb_size] = ($2.to_i / (1024 / block_size)).to_s
+ fs[key][:kb_used] = ($3.to_i / (1024 / block_size)).to_s
+ fs[key][:kb_available] = ($4.to_i / (1024 / block_size)).to_s
+ fs[key][:percent_used] = $5
+ fs[key][:inodes_used] = $6
+ fs[key][:inodes_available] = $7
+ fs[key][:total_inodes] = ($6.to_i + $7.to_i).to_s
+ fs[key][:inodes_percent_used] = $8
+ fs[key][:mount] = $9
+ end
+ end
+
+ so = shell_out("mount")
+ so.stdout.lines do |line|
+ if line =~ /^(.+?) on (.+?) \((.+?), (.+?)\)$/
+ key = "#{$1},#{$2}"
+ fs[key] = Mash.new unless fs.has_key?(key)
+ fs[key][:mount] = $2
+ fs[key][:fs_type] = $3
+ fs[key][:mount_options] = $4.split(/,\s*/)
+ 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
+
+ filesystem2 fs2
+ end
+end
diff --git a/spec/unit/plugins/darwin/filesystem2_spec.rb b/spec/unit/plugins/darwin/filesystem2_spec.rb
new file mode 100644
index 00000000..85e44de1
--- /dev/null
+++ b/spec/unit/plugins/darwin/filesystem2_spec.rb
@@ -0,0 +1,96 @@
+#
+# Author:: Phil Dibowitz (<phil@ipom.com>)
+# 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.
+#
+
+require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper.rb')
+
+describe Ohai::System, "darwin filesystem2 plugin" do
+ before(:each) do
+ @plugin = get_plugin("darwin/filesystem2")
+ allow(@plugin).to receive(:collect_os).and_return(:darwin)
+
+ allow(@plugin).to receive(:shell_out).with("df -i").and_return(mock_shell_out(0, "", ""))
+ allow(@plugin).to receive(:shell_out).with("mount").and_return(mock_shell_out(0, "", ""))
+ end
+
+ describe "when gathering filesystem usage data from df" do
+ before(:each) do
+ @stdout = <<-DF
+Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
+/dev/disk0s2 488555536 313696448 174347088 65% 39276054 21793386 64% /
+devfs 385 385 0 100% 666 0 100% /dev
+map /etc/auto.direct 0 0 0 100% 0 0 100% /mnt/vol
+map -hosts 0 0 0 100% 0 0 100% /net
+map -static 0 0 0 100% 0 0 100% /mobile_symbol
+deweyfs@osxfuse0 0 0 0 100% 0 0 100% /mnt/dewey
+DF
+ allow(@plugin).to receive(:shell_out).with("df -i").and_return(mock_shell_out(0, @stdout, ""))
+ end
+
+ it "should run df -i" do
+ expect(@plugin).to receive(:shell_out).ordered.with("df -i").and_return(mock_shell_out(0, @stdout, ""))
+ @plugin.run
+ end
+
+ it "should set size to value from df -i" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:kb_size]).to eq("244277768")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:kb_used]).to eq("156848224")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:kb_available]).to eq("87173544")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:percent_used]).to eq("65%")
+ end
+
+ it "should set device and mount to value from df -i" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:mount]).to eq("/")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:device]).to eq("/dev/disk0s2")
+ end
+
+ it "should set inode info to value from df -i" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:total_inodes]).to eq("61069440")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:inodes_used]).to eq("39276054")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:inodes_available]).to eq("21793386")
+ end
+ end
+
+ describe "when gathering mounted filesystem data from mount" do
+ before(:each) do
+ @stdout = <<-MOUNT
+/dev/disk0s2 on / (hfs, local, journaled)
+devfs on /dev (devfs, local, nobrowse)
+map /etc/auto.direct on /mnt/vol (autofs, automounted, nobrowse)
+map -hosts on /net (autofs, nosuid, automounted, nobrowse)
+map -static on /mobile_symbol (autofs, automounted, nobrowse)
+deweyfs@osxfuse0 on /mnt/dewey (osxfusefs, synchronous, nobrowse)
+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 values from mount" do
+ @plugin.run
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:mount]).to eq("/")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:fs_type]).to eq("hfs")
+ expect(@plugin[:filesystem2]["by_pair"]["/dev/disk0s2,/"][:mount_options]).to eq([ "local", "journaled" ])
+ end
+ end
+end