[Pkg-puppet-devel] [facter] 126/180: (FACT-234) Partitions Fact
Stig Sandbeck Mathisen
ssm at debian.org
Mon Jun 30 15:06:39 UTC 2014
This is an automated email from the git hooks/post-receive script.
ssm pushed a commit to branch master
in repository facter.
commit 67011ac03b005cfc233657c7e64d7edbfe12ac9b
Author: Chris Portman <chris.portman at optusnet.com.au>
Date: Thu Apr 24 11:19:51 2014 +1000
(FACT-234) Partitions Fact
This fact adds a structured fact that reveals details of the partitions on the machine including things like UUID, size, mount point and filesystem.
This PR supersedes PR #560
---
lib/facter/partitions.rb | 35 +++++++++++
lib/facter/util/partitions.rb | 41 +++++++++++++
lib/facter/util/partitions/linux.rb | 65 +++++++++++++++++++++
.../fixtures/unit/util/partitions/partitions/mount | 9 +++
spec/unit/partitions_spec.rb | 48 ++++++++++++++++
spec/unit/util/partitions/partitions_spec.rb | 67 ++++++++++++++++++++++
spec/unit/util/partitions_spec.rb | 19 ++++++
7 files changed, 284 insertions(+)
diff --git a/lib/facter/partitions.rb b/lib/facter/partitions.rb
new file mode 100644
index 0000000..6ef109a
--- /dev/null
+++ b/lib/facter/partitions.rb
@@ -0,0 +1,35 @@
+# Fact: partitions
+#
+# Purpose:
+# Return the details of the disk partitions
+#
+# Resolution:
+# Parse the contents of /sys/block/<device>/size to receive the size (multiplying by 512 to correct for blocks-to-bytes)
+#
+# Caveats:
+# Only supports Linux 2.6+ at this time, due to the reliance on sysfs
+#
+# Author: Chris Portman <chris at portman.net.au>
+
+require 'facter'
+require 'facter/util/partitions'
+
+Facter.add(:partitions) do
+ confine do
+ Facter::Util::Partitions.available? ? true : nil
+ end
+
+ setcode do
+ partitions = {}
+ Facter::Util::Partitions.list.each do |part|
+ details = {}
+ details['uuid'] = Facter::Util::Partitions.uuid(part)
+ details['size'] = Facter::Util::Partitions.size(part)
+ details['mount'] = Facter::Util::Partitions.mount(part)
+ details['filesystem'] = Facter::Util::Partitions.filesystem(part)
+ details.reject! {|k,v| v.nil? || v.to_s.empty? }
+ partitions[part] = details
+ end
+ partitions
+ end
+end
diff --git a/lib/facter/util/partitions.rb b/lib/facter/util/partitions.rb
new file mode 100644
index 0000000..fc96487
--- /dev/null
+++ b/lib/facter/util/partitions.rb
@@ -0,0 +1,41 @@
+require 'facter/util/partitions/linux'
+
+module Facter::Util::Partitions
+ IMPLEMENTATIONS = {
+ 'Linux' => Linux
+ }
+
+ module NoImplementation
+ def self.list
+ []
+ end
+ end
+
+ def self.implementation
+ IMPLEMENTATIONS[Facter.fact(:kernel).value] || NoImplementation
+ end
+
+ def self.list
+ implementation.list
+ end
+
+ def self.uuid(partition)
+ implementation.uuid(partition)
+ end
+
+ def self.size(partition)
+ implementation.size(partition)
+ end
+
+ def self.mount(partition)
+ implementation.mount(partition)
+ end
+
+ def self.filesystem(partition)
+ implementation.filesystem(partition)
+ end
+
+ def self.available?
+ !self.list.empty?
+ end
+end
diff --git a/lib/facter/util/partitions/linux.rb b/lib/facter/util/partitions/linux.rb
new file mode 100644
index 0000000..b56c6f2
--- /dev/null
+++ b/lib/facter/util/partitions/linux.rb
@@ -0,0 +1,65 @@
+module Facter::Util::Partitions
+ module Linux
+ # Only Linux 2.6+ kernels support sysfs which is required to easily get device details
+ SYSFS_BLOCK_DIRECTORY = '/sys/block/'
+ DEVDISK_BY_UUID_DIRECTORY = '/dev/disk/by-uuid/'
+
+ def self.list
+ if File.exist?(SYSFS_BLOCK_DIRECTORY)
+ devices = Dir.entries(SYSFS_BLOCK_DIRECTORY).select { |d| File.exist?( SYSFS_BLOCK_DIRECTORY + d + "/device" ) }
+
+ if devices.empty?
+ []
+ else
+ devices.collect do |device|
+ Dir.glob( SYSFS_BLOCK_DIRECTORY + device + "/#{device}*" ).collect do |d|
+ File.basename(d)
+ end
+ end.flatten
+ end
+ else
+ []
+ end
+ end
+
+ def self.uuid(partition)
+ uuid = nil
+ if File.exist?(DEVDISK_BY_UUID_DIRECTORY)
+ Dir.entries(DEVDISK_BY_UUID_DIRECTORY).each do |file|
+ qualified_file = File.join(DEVDISK_BY_UUID_DIRECTORY, file)
+
+ #A uuid is 16 octets long (RFC4122) which is 32hex chars + 4 '-'s
+ next unless file.length == 36
+ next unless File.symlink?(qualified_file)
+ next unless File.readlink(qualified_file).match(%r[(?:\.\./\.\./|/dev/)#{partition}$])
+
+ uuid = file
+ end
+ end
+ uuid
+ end
+
+ def self.size(partition)
+ read_size(partition)
+ end
+
+ def self.mount(partition)
+ if Facter::Core::Execution.which('mount')
+ Facter::Core::Execution.exec('mount').scan(/\/dev\/#{partition}\son\s(\S+)/).flatten.first
+ end
+ end
+
+ def self.filesystem(partition)
+ if Facter::Core::Execution.which('blkid')
+ Facter::Core::Execution.exec("blkid #{File.join('/dev', partition)}").scan(/TYPE="(.+)"/).flatten.first
+ end
+ end
+
+ private
+ def self.read_size(partition)
+ if device = partition.match(/(\D+)/)[1] and File.readable?(File.join(SYSFS_BLOCK_DIRECTORY, device, partition, 'size'))
+ File.read(File.join(SYSFS_BLOCK_DIRECTORY, device, partition, 'size')).chomp
+ end
+ end
+ end
+end
diff --git a/spec/fixtures/unit/util/partitions/partitions/mount b/spec/fixtures/unit/util/partitions/partitions/mount
new file mode 100644
index 0000000..6289df0
--- /dev/null
+++ b/spec/fixtures/unit/util/partitions/partitions/mount
@@ -0,0 +1,9 @@
+proc on /proc type proc (rw,noexec,nosuid,nodev)
+sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
+none on /sys/fs/cgroup type tmpfs (rw)
+udev on /dev type devtmpfs (rw,mode=0755)
+devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
+tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755)
+/dev/sda1 on /home type ext4 (rw)
+/dev/sdb2 on / type ext4 (rw,errors=remount-ro)
+/dev/sdc3 on /var type ext4 (rw,errors=remount-ro)
diff --git a/spec/unit/partitions_spec.rb b/spec/unit/partitions_spec.rb
new file mode 100644
index 0000000..1807c51
--- /dev/null
+++ b/spec/unit/partitions_spec.rb
@@ -0,0 +1,48 @@
+#!/usr/bin/env ruby
+
+require 'spec_helper'
+require 'facter'
+
+describe "Partition facts" do
+
+ describe "on non-Linux OS" do
+
+ it "should not exist when kernel isn't Linux" do
+ Facter.fact(:kernel).stubs(:value).returns("SunOS")
+ Facter.fact(:partitions).value.should == nil
+ end
+ end
+
+ describe "on Linux" do
+ it "should return a structured fact with uuid, size, mount point and filesytem for each partition" do
+ partitions = {
+ 'sda1' => {
+ 'uuid' => '13459663-22cc-47b4-a9e6-21dea9906e03',
+ 'size' => '1234',
+ 'mount' => '/',
+ 'filesystem' => 'ext4',
+ },
+ 'sdb2' => {
+ 'uuid' => '98043570-eb10-457f-9718-0b85a26e66bf',
+ 'size' => '5678',
+ 'mount' => '/home',
+ 'filesystem' => 'xfs',
+ },
+ }
+
+ Facter::Util::Partitions.stubs(:list).returns( partitions.keys )
+
+ partitions.each do |part,vals|
+ Facter::Util::Partitions.stubs(:uuid).with(part).returns(vals['uuid'])
+ Facter::Util::Partitions.stubs(:size).with(part).returns(vals['size'])
+ Facter::Util::Partitions.stubs(:mount).with(part).returns(vals['mount'])
+ Facter::Util::Partitions.stubs(:filesystem).with(part).returns(vals['filesystem'])
+ end
+
+ Facter.fact(:partitions).value.should == {
+ 'sda1' => { 'uuid' => '13459663-22cc-47b4-a9e6-21dea9906e03', 'size' => '1234', 'mount' => '/', 'filesystem' => 'ext4' },
+ 'sdb2' => { 'uuid' => '98043570-eb10-457f-9718-0b85a26e66bf', 'size' => '5678', 'mount' => '/home', 'filesystem' => 'xfs' },
+ }
+ end
+ end
+end
diff --git a/spec/unit/util/partitions/partitions_spec.rb b/spec/unit/util/partitions/partitions_spec.rb
new file mode 100644
index 0000000..c690540
--- /dev/null
+++ b/spec/unit/util/partitions/partitions_spec.rb
@@ -0,0 +1,67 @@
+require 'spec_helper'
+require 'facter'
+require 'facter/util/partitions/linux'
+
+describe 'Facter::Util::Partitions::Linux' do
+ describe 'on Linux OS' do
+ before :each do
+ Facter.fact(:kernel).stubs(:value).returns("Linux")
+
+ File.stubs(:exist?).with('/sys/block/').returns(true)
+ File.stubs(:exist?).with("/sys/block/./device").returns(false)
+ File.stubs(:exist?).with("/sys/block/../device").returns(false)
+ File.stubs(:exist?).with('/dev/disk/by-uuid/').returns(true)
+
+ devices = [".", "..", "sda", "sdb", "sdc"]
+ Dir.stubs(:entries).with('/sys/block/').returns(devices)
+
+ Facter::Core::Execution.stubs(:which).with('mount').returns(true)
+ Facter::Core::Execution.stubs(:which).with('blkid').returns(true)
+
+ test_parts = {
+ 'sda1' => '13459663-22cc-47b4-a9e6-21dea9906e03',
+ 'sdb2' => '98043570-eb10-457f-9718-0b85a26e66bf',
+ 'sdc3' => 'a35fb506-e831-4752-9899-dff6c601214b',
+ }
+
+ Dir.stubs(:entries).with('/dev/disk/by-uuid/').returns(test_parts.values)
+ test_parts.each do |part,uuid|
+ device = part.match(/(\D+)/)[1]
+ File.stubs(:exist?).with("/sys/block/#{device}/device").returns(true)
+ File.stubs(:symlink?).with("/dev/disk/by-uuid/#{uuid}").returns(true)
+ File.stubs(:readlink).with("/dev/disk/by-uuid/#{uuid}").returns("/dev/#{part}")
+ Dir.stubs(:glob).with("/sys/block/#{device}/#{device}*").returns(["/sys/block/#{device}/#{part}"])
+ Facter::Util::Partitions::Linux.stubs(:read_size).returns('12345')
+ Facter::Core::Execution.stubs(:exec).with("blkid /dev/#{part}").returns("/dev/#{part}: UUID=\"#{uuid}\" TYPE=\"ext4\"")
+ end
+
+ Facter::Core::Execution.stubs(:exec).with('mount').returns(my_fixture_read("mount"))
+ end
+
+ it '.list should return a list of partitions' do
+ Facter::Util::Partitions::Linux.list.should == ['sda1', 'sdb2', 'sdc3']
+ end
+
+ it '.uuid should return a string containing the uuid' do
+ Facter::Util::Partitions::Linux.uuid('sda1').should == '13459663-22cc-47b4-a9e6-21dea9906e03'
+ Facter::Util::Partitions::Linux.uuid('sdb2').should == '98043570-eb10-457f-9718-0b85a26e66bf'
+ Facter::Util::Partitions::Linux.uuid('sdc3').should == 'a35fb506-e831-4752-9899-dff6c601214b'
+ end
+
+ it '.size should return a string containing the size' do
+ Facter::Util::Partitions::Linux.size('sda1').should == '12345'
+ end
+
+ it '.mount should return a string containing the mount point of the partition' do
+ Facter::Util::Partitions::Linux.mount('sda1').should == '/home'
+ Facter::Util::Partitions::Linux.mount('sdb2').should == '/'
+ Facter::Util::Partitions::Linux.mount('sdc3').should == '/var'
+ end
+
+ it '.filesystem should return a string containing the filesystem on the partition' do
+ Facter::Util::Partitions::Linux.filesystem('sda1').should == 'ext4'
+ Facter::Util::Partitions::Linux.filesystem('sdb2').should == 'ext4'
+ Facter::Util::Partitions::Linux.filesystem('sdc3').should == 'ext4'
+ end
+ end
+end
diff --git a/spec/unit/util/partitions_spec.rb b/spec/unit/util/partitions_spec.rb
new file mode 100644
index 0000000..9fb79f0
--- /dev/null
+++ b/spec/unit/util/partitions_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+require 'facter'
+require 'facter/util/partitions'
+
+describe 'Facter::Util::Partitions' do
+ describe 'on unsupported OSs' do
+ before :each do
+ Facter.fact(:kernel).stubs(:value).returns("SunOS")
+ end
+
+ it 'list should return empty array' do
+ Facter::Util::Partitions.list.should == []
+ end
+
+ it 'available? should return false' do
+ Facter::Util::Partitions.available?.should == false
+ end
+ end
+end
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-puppet/facter.git
More information about the Pkg-puppet-devel
mailing list