Skip to content

Commit

Permalink
Merge pull request #2745 from mhashizume/gpt-guids
Browse files Browse the repository at this point in the history
Add type GUIDs to partitions resolver
  • Loading branch information
cthorn42 authored Aug 27, 2024
2 parents c9db47d + 82b980e commit b6cf607
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 26 deletions.
53 changes: 37 additions & 16 deletions lib/facter/resolvers/partitions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,14 @@ def populate_partitions(partition_name, block_path, blkid_and_lsblk, backing_fil
size: Facter::Util::Facts::UnitConverter.bytes_to_human_readable(size_bytes),
backing_file: backing_file }
info_hash.merge!(populate_from_syscalls(partition_name, blkid_and_lsblk))
@fact_list[:partitions][partition_name] = info_hash.reject { |_key, value| value.nil? }
@fact_list[:partitions][partition_name] = info_hash.compact
end

def populate_from_syscalls(partition_name, blkid_and_lsblk)
part_info = populate_from_blkid(partition_name, blkid_and_lsblk)
# Prefer lsblk over blkid since lsblk does not require root, returns more information, and is recommended by blkid
part_info = populate_from_lsblk(partition_name, blkid_and_lsblk)

return populate_from_lsblk(partition_name, blkid_and_lsblk) if part_info.empty?
return populate_from_blkid(partition_name, blkid_and_lsblk) if part_info.empty?

part_info
end
Expand Down Expand Up @@ -121,26 +122,46 @@ def execute_and_extract_blkid_info
def populate_from_lsblk(partition_name, blkid_and_lsblk)
return {} unless available?('lsblk', blkid_and_lsblk)

blkid_and_lsblk[:lsblk] ||= Facter::Core::Execution.execute('lsblk -fp', logger: log)
lsblk_version_raw = Facter::Core::Execution.execute('lsblk --version 2>&1', logger: log)
lsblk_version = lsblk_version_raw.match(/ \d\.\d+/)[0].to_f

part_info = blkid_and_lsblk[:lsblk].match(/#{partition_name}.*/).to_s.split(' ')
return {} if part_info.empty?
# The -p/--paths option was added in lsblk 2.23, return early and fall back to blkid with earlier versions
return {} if lsblk_version < 2.23

parse_part_info(part_info)
end
blkid_and_lsblk[:lsblk] ||= execute_and_extract_lsblk_info(lsblk_version)

def parse_part_info(part_info)
result = { filesystem: part_info[1] }
partition_data = blkid_and_lsblk[:lsblk][partition_name]
return {} unless partition_data

if part_info.count.eql?(5)
result[:label] = part_info[2]
result[:uuid] = part_info[3]
else
result[:uuid] = part_info[2]
end
filesys = partition_data['FSTYPE']
uuid = partition_data['UUID']
label = partition_data['LABEL']
part_uuid = partition_data['PARTUUID']
part_label = partition_data['PARTLABEL']
part_type = partition_data['PARTTYPE']

result = { filesystem: filesys, uuid: uuid, label: label, partuuid: part_uuid, partlabel: part_label }
result[:parttype] = part_type if part_type

result
end

def execute_and_extract_lsblk_info(lsblk_version)
# lsblk 2.25 added support for GPT partition type GUIDs
stdout = if lsblk_version >= 2.25
Facter::Core::Execution.execute('lsblk -p -P -o NAME,FSTYPE,UUID,LABEL,PARTUUID,PARTLABEL,PARTTYPE', logger: log)
else
Facter::Core::Execution.execute('lsblk -p -P -o NAME,FSTYPE,LABEL,UUID,PARTUUID,PARTLABEL', logger: log)
end

output_hash = Hash[*stdout.split(/^(NAME=\S+)/)[1..-1]]
output_hash.transform_keys! { |key| key.delete('NAME=')[1..-2] }
output_hash.each do |key, value|
output_hash[key] = Hash[*value.chomp.rstrip.split(/ ([^= ]+)=/)[1..-1].each { |x| x.delete!('"') }]
end
output_hash.each_value { |value_hash| value_hash.delete_if { |_k, v| v.empty? } }
output_hash.delete_if { |_k, v| v.empty? }
end
end
end
end
Expand Down
3 changes: 3 additions & 0 deletions lib/schema/facter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,9 @@ partitions:
backing_file:
type: string
description: The path to the file backing the partition.
parttype:
type: string
description: The partition type GUID.

path:
type: string
Expand Down
46 changes: 43 additions & 3 deletions spec/facter/resolvers/partitions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@
allow(Facter::Core::Execution).to receive(:which)
.with('lsblk').and_return('/usr/bin/lsblk')
allow(Facter::Core::Execution).to receive(:execute)
.with('lsblk -fp', logger: an_instance_of(Facter::Log)).and_return(load_fixture('lsblk_output').read)
.with('lsblk --version 2>&1', logger: an_instance_of(Facter::Log)).and_return('lsblk from util-linux 2.24')
allow(Facter::Core::Execution).to receive(:execute)
.with('lsblk -p -P -o NAME,FSTYPE,LABEL,UUID,PARTUUID,PARTLABEL', logger: an_instance_of(Facter::Log)).and_return(load_fixture('lsblk_output_old').read)
end

context 'when block has a device subdir' do
Expand All @@ -68,12 +70,12 @@
context 'when there is more than one partition' do
it 'checks for blkid only once' do
resolver.resolve(:partitions)
expect(Facter::Core::Execution).to have_received(:which).with('blkid').once
expect(Facter::Core::Execution).to have_received(:which).with('blkid').at_most(:once)
end

it 'checks for lsblk only once' do
resolver.resolve(:partitions)
expect(Facter::Core::Execution).to have_received(:which).with('lsblk').once
expect(Facter::Core::Execution).to have_received(:which).with('lsblk').at_most(:once)
end
end

Expand Down Expand Up @@ -189,5 +191,43 @@
end
end
end

context 'when lsblk can read partition types' do
let(:partitions) do
{ '/dev/sda1' => { filesystem: 'ext3', label: '/boot', parttype: '21686148-6449-6E6F-744E-656564454649', size: '117.00 KiB',
size_bytes: 119_808, uuid: '88077904-4fd4-476f-9af2-0f7a806ca25e',
partuuid: '00061fe0-01' },
'/dev/sda2' => { filesystem: 'LVM2_member', parttype: '0fc63daf-8483-4772-8e79-3d69d8477de4', size: '98.25 MiB',
size_bytes: 103_021_056, uuid: 'edi7s0-2WVa-ZBan' } }
end

let(:sda_subdirs) do
['/sys/block/sda/queue',
'/sys/block/sda/sda2',
'/sys/block/sda/sda2/stat',
'/sys/block/sda/sda2/dev',
'/sys/block/sda/sda2/uevent',
'/sys/block/sda/sda1']
end

before do
allow(File).to receive(:directory?).with("#{sys_block_path}/sda/device").and_return(true)
allow(Dir).to receive(:[]).with("#{sys_block_path}/sda/**/*").and_return(sda_subdirs)
sda_subdirs.each { |subdir| allow(File).to receive(:directory?).with(subdir).and_return(true) }
allow(Facter::Util::FileHelper).to receive(:safe_read)
.with("#{sys_block_path}/sda/sda2/size", '0').and_return('201213')
allow(Facter::Util::FileHelper).to receive(:safe_read)
.with("#{sys_block_path}/sda/sda1/size", '0').and_return('234')
end

it 'return partitions fact with part_type' do
allow(Facter::Core::Execution).to receive(:execute)
.with('lsblk --version 2>&1', logger: an_instance_of(Facter::Log)).and_return('lsblk from util-linux 2.25')
allow(Facter::Core::Execution).to receive(:execute)
.with('lsblk -p -P -o NAME,FSTYPE,UUID,LABEL,PARTUUID,PARTLABEL,PARTTYPE', logger: an_instance_of(Facter::Log)).and_return(load_fixture('lsblk_output_new').read)

expect(resolver.resolve(:partitions)).to eq(partitions)
end
end
end
end
7 changes: 0 additions & 7 deletions spec/fixtures/lsblk_output

This file was deleted.

3 changes: 3 additions & 0 deletions spec/fixtures/lsblk_output_new
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NAME="/dev/sda" FSTYPE="" UUID="" LABEL="" PARTUUID="" PARTLABEL="" PARTTYPE=""
NAME="/dev/sda1" FSTYPE="ext3" UUID="88077904-4fd4-476f-9af2-0f7a806ca25e" LABEL="/boot" PARTUUID="00061fe0-01" PARTLABEL="" PARTTYPE="21686148-6449-6E6F-744E-656564454649"
NAME="/dev/sda2" FSTYPE="LVM2_member" UUID="edi7s0-2WVa-ZBan" LABEL="" PARTUUID="" PARTLABEL="" PARTTYPE="0fc63daf-8483-4772-8e79-3d69d8477de4"
3 changes: 3 additions & 0 deletions spec/fixtures/lsblk_output_old
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NAME="/dev/sda" FSTYPE="" UUID="" LABEL="" PARTUUID="" PARTLABEL="" PARTTYPE=""
NAME="/dev/sda1" FSTYPE="ext3" UUID="88077904-4fd4-476f-9af2-0f7a806ca25e" LABEL="/boot" PARTUUID="00061fe0-01" PARTLABEL=""
NAME="/dev/sda2" FSTYPE="LVM2_member" UUID="edi7s0-2WVa-ZBan" LABEL="" PARTUUID="" PARTLABEL=""

0 comments on commit b6cf607

Please sign in to comment.