From 666625a397338eebe9b7d7e8e10f64d0adf7cba3 Mon Sep 17 00:00:00 2001 From: Jakob Pfeiffer Date: Mon, 9 Dec 2024 18:36:26 +0100 Subject: [PATCH] Support use of symlinks for device paths This change improves the mounted? check. Symlinks are now resolved to their canonical path. Checks if the device is mounted at a specific mount point Signed-off-by: Jakob Pfeiffer --- CHANGELOG.md | 2 ++ libraries/fs.rb | 30 +++++++++++++++++++++++++++--- resources/default.rb | 6 ++---- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfe0ada..253533b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## Unreleased +- Support use of symlinks for device paths + ## 4.1.0 - *2024-12-09* - Add validation to the filesystem label property, limiting to a maximum length of 12 characters diff --git a/libraries/fs.rb b/libraries/fs.rb index 9b59097..4b6de41 100644 --- a/libraries/fs.rb +++ b/libraries/fs.rb @@ -9,9 +9,33 @@ module FilesystemMod NET_FS_TYPES = %w(nfs nfs4 cifs smp nbd).freeze unless const_defined?(:NET_FS_TYPES) NFS_TYPES = %w(nfs nfs4).freeze unless const_defined?(:NFS_TYPES) - # Check to determine if the device is mounted. - def mounted?(device) - shell_out("grep -q '#{device}' /proc/mounts").exitstatus != 0 ? nil : shell_out("grep -q '#{device}' /proc/mounts").exitstatus + def canonical_path(path) + File.exist?(path) && File.realpath(path) || path + end + + # Check to determine if a device is mounted. + def mounted?(params = {}) + params.is_a?(String) && params = { device: params } # backward compatibility + + mounts = File.readlines('/proc/mounts').map(&:split).map do |field| + { + device: field[0].start_with?('/dev/') && canonical_path(field[0]) || field[0], + mountpoint: field[1], + } + end + + if params.key?(:device) && params.key?(:mountpoint) + mounts.select do |mount| + mount[:device] == canonical_path(params[:device]) && + mount[:mountpoint] == params[:mountpoint].chomp('/') + end.any? + elsif params.key?(:device) + mounts.select { |mount| mount[:device] == canonical_path(params[:device]) }.any? + elsif params.key?(:mountpoint) + mounts.select { |mount| mount[:mountpoint] == params[:mountpoint].chomp('/') }.any? + else + raise 'Invalid parameters passed to method "mounted?"' + end end # Check to determine if the mount is frozen. diff --git a/resources/default.rb b/resources/default.rb index 6501b81..8880d3c 100644 --- a/resources/default.rb +++ b/resources/default.rb @@ -153,7 +153,7 @@ def mount_point(mount_location) wait_for_device unless ::File.exist?(device) || netfs?(fstype) # We only try and create a filesystem if the device exists and is unmounted - unless mounted?(device) + unless mounted?(device: device) # Install the filesystem's default package and recipes as configured in default attributes. fs_tools = node['filesystem_tools'].fetch(fstype, nil) @@ -259,9 +259,7 @@ def mount_point(mount_location) fstype fstype options options action :mount - # Pathname.new(mount).mountpoint? would be a better check but might - # cause different behavior - not_if "mount | grep #{device}\" \" | grep #{mount}\" \"" + not_if { mounted?(device: device, mountpoint: mount) } end # set directory attributes within the mounted file system