Skip to content
This repository was archived by the owner on Jun 19, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/facts/aix/partitions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module Facts
module Aix
class Partitions
FACT_NAME = 'partitions'

def call_the_resolver
partitions = Facter::Resolvers::Aix::Partitions.resolve(:partitions)

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

module Facter
module Resolvers
module Aix
class Partitions < BaseResolver
@log = Facter::Log.new(self)
@semaphore = Mutex.new
@fact_list ||= {}
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

def query_cudv(fact_name)
@fact_list[:partitions] = {}

odmquery = Facter::ODMQuery.new
odmquery.equals('PdDvLn', 'logical_volume/lvsubclass/lvtype')

result = odmquery.execute

return unless result

result.each_line do |line|
next unless line.include?('name')

part_name = line.split('=')[1].strip.delete('"')
part = "/dev/#{part_name}"
info = populate_from_lslv(part_name)
@fact_list[:partitions][part] = info if info
end

@fact_list[fact_name]
end

def populate_from_lslv(name)
stdout, stderr, _status = Open3.capture3("lslv -L #{name}")
if stdout.empty?
@log.debug(stderr)
return
end

info_hash = extract_info(stdout)
size_bytes = compute_size(info_hash)

part_info = {
filesystem: info_hash['TYPE'],
size_bytes: size_bytes,
size: Facter::BytesToHumanReadable.convert(size_bytes)
}
mount = info_hash['MOUNTPOINT']
label = info_hash['LABEL']
part_info[:mount] = mount unless %r{N/A} =~ mount
part_info[:label] = label 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.to_i * physical_partitions * exp
end
end
end
end
end
end
4 changes: 2 additions & 2 deletions lib/resolvers/aix/utils/odm_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ def like(field, value)
def execute
result = nil
REPOS.each do |repo|
break if result
break if result && !result.empty?

result, _s = Open3.capture2("#{query} #{repo}")
result, _stderr, _s = Open3.capture3("#{query} #{repo}")
Comment thread
sebastian-miclea marked this conversation as resolved.
end
result
end
Expand Down
28 changes: 28 additions & 0 deletions spec/facter/facts/aix/partitions_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

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

let(:value) do
{ '/dev/hd5' => { 'filesystem' => 'boot',
'size_bytes' => 33_554_432,
'size' => '32.00 MiB',
'label' => 'primary_bootlv' } }
end

before do
allow(Facter::Resolvers::Aix::Partitions).to receive(:resolve).with(:partitions).and_return(value)
end

it 'calls Facter::Resolvers::Aix::Partitions' do
fact.call_the_resolver
expect(Facter::Resolvers::Aix::Partitions).to have_received(:resolve).with(:partitions)
end

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

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

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

before do
resolver.instance_variable_set(:@log, logger_spy)
allow(Facter::ODMQuery).to receive(:new).and_return(odm_query_spy)
allow(odm_query_spy).to receive(:equals).with('PdDvLn', 'logical_volume/lvsubclass/lvtype')
allow(odm_query_spy).to receive(:execute).and_return(result)
end

after do
resolver.invalidate_cache
end

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

before do
allow(odm_query_spy).to receive(:execute).and_return(result)
end

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

context 'when CuDv query succesful' do
let(:result) { load_fixture('partitions_cudv_query').read }

let(:partitions) do
{ '/dev/hd5' => { filesystem: 'boot', label: 'primary_bootlv', size: '32.00 MiB', size_bytes: 33_554_432 } }
end

before do
allow(Open3).to receive(:capture3).with('lslv -L hd5').and_return(load_fixture('lslv_output').read)
allow(Open3).to receive(:capture3).with('lslv -L hd6').and_return(['', 'Error: something happened!', 1])
end

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

it 'logs stderr output in case lslv commands fails' do
resolver.resolve(:partitions)

expect(logger_spy).to have_received(:debug).with('Error: something happened!')
end
end
end
4 changes: 2 additions & 2 deletions spec/facter/resolvers/utils/aix/odm_query_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
it 'creates a query' do
odm_query.equals('name', '12345')

expect(Open3).to receive(:capture2).with("odmget -q \"name='12345'\" CuAt")
expect(Open3).to receive(:capture3).with("odmget -q \"name='12345'\" CuAt")
odm_query.execute
end

it 'can chain conditions' do
odm_query.equals('field1', 'value').like('field2', 'value*')

expect(Open3).to receive(:capture2)
expect(Open3).to receive(:capture3)
.with("odmget -q \"field1='value' AND field2 like 'value*'\" CuAt")
odm_query.execute
end
Expand Down
13 changes: 13 additions & 0 deletions spec/fixtures/lslv_output
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
LOGICAL VOLUME: hd5 VOLUME GROUP: rootvg
LV IDENTIFIER: 00fa684e00004c00000001715c6c0708.1 PERMISSION: read/write
VG STATE: active/complete LV STATE: closed/syncd
TYPE: boot WRITE VERIFY: off
MAX LPs: 512 PP SIZE: 32 megabyte(s)
COPIES: 1 SCHED POLICY: parallel
LPs: 1 PPs: 1
STALE PPs: 0 BB POLICY: non-relocatable
INTER-POLICY: minimum RELOCATABLE: no
INTRA-POLICY: edge UPPER BOUND: 32
MOUNT POINT: N/A LABEL: primary_bootlv
MIRROR WRITE CONSISTENCY: on/ACTIVE
EACH LP COPY ON A SEPARATE PV ?: yes
19 changes: 19 additions & 0 deletions spec/fixtures/partitions_cudv_query
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
CuDv:
name = "hd5"
status = 0
chgstatus = 1
ddins = ""
location = ""
parent = "rootvg"
connwhere = ""
PdDvLn = "logical_volume/lvsubclass/lvtype"

CuDv:
name = "hd6"
status = 0
chgstatus = 1
ddins = ""
location = ""
parent = "rootvg"
connwhere = ""
PdDvLn = "logical_volume/lvsubclass/lvtype"