Skip to content

Commit

Permalink
Merge pull request #1987 from oanatmaria/FACT-2220
Browse files Browse the repository at this point in the history
(FACT-2220) Add Aix disks fact
  • Loading branch information
Bogdan Irimie authored Jul 23, 2020
2 parents a9957d4 + 5d11188 commit 95112e7
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 20 deletions.
17 changes: 17 additions & 0 deletions lib/facter/facts/aix/disks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

module Facts
module Aix
class Disks
FACT_NAME = 'disks'

def call_the_resolver
disks = Facter::Resolvers::Aix::Disks.resolve(:disks)

disks = disks&.empty? ? nil : disks

Facter::ResolvedFact.new(FACT_NAME, disks)
end
end
end
end
63 changes: 63 additions & 0 deletions lib/facter/resolvers/aix/disks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# frozen_string_literal: true

module Facter
module Resolvers
module Aix
class Disks < BaseResolver
@semaphore = Mutex.new
@fact_list ||= {}
class << self
private

def post_resolve(fact_name)
@fact_list.fetch(fact_name) { execute_lspv(fact_name) }
end

def execute_lspv(fact_name)
@fact_list[:disks] = {}

result = Facter::Core::Execution.execute('lspv', logger: log)

return if result.empty?

result.each_line do |line|
disk_name = line.split(' ')[0].strip
size = find_size(disk_name)
@fact_list[:disks][disk_name] = size if size
end

@fact_list[fact_name]
end

def find_size(name)
stdout = Facter::Core::Execution.execute("lspv #{name}", logger: log)

return if stdout.empty?

info_size = InfoExtractor.extract(stdout, /PP SIZE:|TOTAL PPs:|FREE PPs:|PV STATE:/)

return unless info_size['PV STATE']

size_bytes = compute_size(info_size)

{
size_bytes: size_bytes,
size: Facter::FactsUtils::UnitConverter.bytes_to_human_readable(size_bytes)
}
end

def compute_size(size_hash)
physical_partitions = size_hash['TOTAL PPs'].to_i + size_hash['FREE PPs'].to_i
size_physical_partition = size_hash['PP SIZE']
exp = if size_physical_partition[/mega/]
InfoExtractor::MEGABYTES_EXPONENT
else
InfoExtractor::GIGABYTES_EXPONENT
end
size_physical_partition.to_i * physical_partitions * exp
end
end
end
end
end
end
29 changes: 9 additions & 20 deletions lib/facter/resolvers/aix/partitions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ class Partitions < BaseResolver
class << self
private

MEGABYTES_EXPONENT = 1024**2
GIGABYTES_EXPONENT = 1024**3

def post_resolve(fact_name)
@fact_list.fetch(fact_name) { query_cudv(fact_name) }
end
Expand Down Expand Up @@ -43,37 +40,29 @@ def populate_from_lslv(name)

return if stdout.empty?

info_hash = extract_info(stdout)
info_hash = InfoExtractor.extract(stdout, /PPs:|PP SIZE|TYPE:|LABEL:|MOUNT/)
size_bytes = compute_size(info_hash)

part_info = {
filesystem: info_hash['TYPE'],
size_bytes: size_bytes,
size: Facter::FactsUtils::UnitConverter.bytes_to_human_readable(size_bytes)
}
mount = info_hash['MOUNTPOINT']
mount = info_hash['MOUNT POINT']
label = info_hash['LABEL']
part_info[:mount] = mount unless %r{N/A} =~ mount
part_info[:label] = label unless /None/ =~ label
part_info[:label] = label.strip unless /None/ =~ label
part_info
end

def extract_info(lsl_content)
lsl_content = lsl_content.strip.split("\n").map do |line|
next unless /PPs:|PP SIZE|TYPE:|LABEL:|MOUNT/ =~ line

line.split(/:|\s\s/).reject(&:empty?)
end

lsl_content.flatten!.select! { |elem| elem }.map! { |elem| elem.delete("\s") }

Hash[*lsl_content]
end

def compute_size(info_hash)
physical_partitions = info_hash['PPs'].to_i
size_physical_partition = info_hash['PPSIZE']
exp = size_physical_partition[/mega/] ? MEGABYTES_EXPONENT : GIGABYTES_EXPONENT
size_physical_partition = info_hash['PP SIZE']
exp = if size_physical_partition[/mega/]
InfoExtractor::MEGABYTES_EXPONENT
else
InfoExtractor::GIGABYTES_EXPONENT
end
size_physical_partition.to_i * physical_partitions * exp
end
end
Expand Down
20 changes: 20 additions & 0 deletions lib/facter/resolvers/aix/utils/info_extractor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

module Facter
module InfoExtractor
MEGABYTES_EXPONENT = 1024**2
GIGABYTES_EXPONENT = 1024**3

def self.extract(content, regex)
content = content.each_line.map do |line|
next unless regex =~ line

line.split(/:\s*|\s{2,}/)
end

content.flatten!.reject!(&:nil?)

Hash[*content]
end
end
end
53 changes: 53 additions & 0 deletions spec/facter/facts/aix/disks_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

describe Facts::Aix::Disks do
describe '#call_the_resolver' do
subject(:fact) { Facts::Aix::Disks.new }

let(:disk) do
{
'disks' => {
'hdisk0' => {
'size' => '20.00 GiB',
'size_bytes' => 21_474_836_480
}
}
}
end

before do
allow(Facter::Resolvers::Aix::Disks).to receive(:resolve).with(:disks).and_return(disk)
end

it 'calls Facter::Resolvers::Aix::Disk' do
fact.call_the_resolver
expect(Facter::Resolvers::Aix::Disks).to have_received(:resolve).with(:disks)
end

it 'returns resolved fact with name disk and value' do
expect(fact.call_the_resolver)
.to be_an_instance_of(Facter::ResolvedFact)
.and have_attributes(name: 'disks', value: disk)
end

context 'when resolver returns empty hash' do
let(:disk) { {} }

it 'returns nil fact' do
expect(fact.call_the_resolver)
.to be_an_instance_of(Facter::ResolvedFact)
.and have_attributes(name: 'disks', value: nil)
end
end

context 'when resolver returns nil' do
let(:disk) { nil }

it 'returns nil fact' do
expect(fact.call_the_resolver)
.to be_an_instance_of(Facter::ResolvedFact)
.and have_attributes(name: 'disks', value: nil)
end
end
end
end
53 changes: 53 additions & 0 deletions spec/facter/resolvers/aix/disks_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

describe Facter::Resolvers::Aix::Disks do
subject(:resolver) { Facter::Resolvers::Aix::Disks }

let(:logger_spy) { instance_spy(Facter::Log) }

before do
resolver.instance_variable_set(:@log, logger_spy)
allow(Facter::Core::Execution).to receive(:execute).with('lspv', logger: logger_spy)
.and_return(result)
end

after do
resolver.invalidate_cache
end

context 'when retrieving disks name fails' do
let(:result) { '' }

it 'returns nil' do
expect(resolver.resolve(:disks)).to be_nil
end
end

context 'when lspv is successful' do
let(:result) { load_fixture('lspv_output').read }

let(:disks) do
{ 'hdisk0' => { size: '30.00 GiB', size_bytes: 32_212_254_720 } }
end

before do
allow(Facter::Core::Execution).to receive(:execute).with('lspv hdisk0', logger: logger_spy)
.and_return(load_fixture('lspv_disk_output').read)
end

it 'returns disks informations' do
expect(resolver.resolve(:disks)).to eql(disks)
end

context 'when second lspv call fails' do
before do
allow(Facter::Core::Execution).to receive(:execute).with('lspv hdisk0', logger: logger_spy)
.and_return('')
end

it 'returns disks informations' do
expect(resolver.resolve(:disks)).to eq({})
end
end
end
end
11 changes: 11 additions & 0 deletions spec/fixtures/lspv_disk_output
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
PHYSICAL VOLUME: hdisk0 VOLUME GROUP: rootvg
PV IDENTIFIER: 00f9280c31fc0ae6 VG IDENTIFIER 00f9280c00004c00000001737084c416
PV STATE: active
STALE PARTITIONS: 0 ALLOCATABLE: yes
PP SIZE: 32 megabyte(s) LOGICAL VOLUMES: 12
TOTAL PPs: 959 (30688 megabytes) VG DESCRIPTORS: 2
FREE PPs: 1 (32 megabytes) HOT SPARE: no
USED PPs: 958 (30656 megabytes) MAX REQUEST: 256 kilobytes
FREE DISTRIBUTION: 00..00..00..00..01
USED DISTRIBUTION: 192..192..191..192..191
MIRROR POOL: None
1 change: 1 addition & 0 deletions spec/fixtures/lspv_output
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hdisk0 testid0998 rootvg active

0 comments on commit 95112e7

Please sign in to comment.