[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