Skip to content
This repository was archived by the owner on Jun 19, 2020. It is now read-only.

Commit 0bd51e7

Browse files
author
Oana Tanasoiu
committed
(FACT-2233) Add AIX partitons fact
1 parent 71e5d18 commit 0bd51e7

8 files changed

Lines changed: 219 additions & 4 deletions

File tree

lib/facts/aix/partitions.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
3+
module Facts
4+
module Aix
5+
class Partitions
6+
FACT_NAME = 'partitions'
7+
8+
def call_the_resolver
9+
partitions = Facter::Resolvers::Aix::Partitions.resolve(:partitions)
10+
11+
Facter::ResolvedFact.new(FACT_NAME, partitions.empty? ? nil : partitions)
12+
end
13+
end
14+
end
15+
end

lib/resolvers/aix/partitions.rb

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# frozen_string_literal: true
2+
3+
module Facter
4+
module Resolvers
5+
module Aix
6+
class Partitions < BaseResolver
7+
@log = Facter::Log.new(self)
8+
@semaphore = Mutex.new
9+
@fact_list ||= {}
10+
class << self
11+
private
12+
13+
MEGABYTES_EXPONENT = 1024**2
14+
GIGABYTES_EXPONENT = 1024**3
15+
16+
def post_resolve(fact_name)
17+
@fact_list.fetch(fact_name) { query_cudv(fact_name) }
18+
end
19+
20+
def query_cudv(fact_name)
21+
@fact_list[:partitions] = {}
22+
23+
odmquery = Facter::ODMQuery.new
24+
odmquery.equals('PdDvLn', 'logical_volume/lvsubclass/lvtype')
25+
26+
result = odmquery.execute
27+
28+
return unless result
29+
30+
result.each_line do |line|
31+
next unless line.include?('name')
32+
33+
part_name = line.split('=')[1].strip.delete('"')
34+
part = "/dev/#{part_name}"
35+
info = populate_from_lslv(part_name)
36+
@fact_list[:partitions][part] = info if info
37+
end
38+
39+
@fact_list[fact_name]
40+
end
41+
42+
def populate_from_lslv(name)
43+
stdout, stderr, _status = Open3.capture3("lslv -L #{name}")
44+
if stdout.empty?
45+
@log.debug(stderr)
46+
return
47+
end
48+
49+
info_hash = extract_info(stdout)
50+
size_bytes = compute_size(info_hash)
51+
52+
part_info = {
53+
filesystem: info_hash['TYPE'],
54+
size_bytes: size_bytes,
55+
size: Facter::BytesToHumanReadable.convert(size_bytes)
56+
}
57+
mount = info_hash['MOUNTPOINT']
58+
label = info_hash['LABEL']
59+
part_info[:mount] = mount unless %r{N/A} =~ mount
60+
part_info[:label] = label unless /None/ =~ label
61+
part_info
62+
end
63+
64+
def extract_info(lsl_content)
65+
lsl_content = lsl_content.strip.split("\n").map do |line|
66+
next unless /PPs:|PP SIZE|TYPE:|LABEL:|MOUNT/ =~ line
67+
68+
line.split(/:|\s\s/).reject(&:empty?)
69+
end
70+
71+
lsl_content.flatten!.select! { |elem| elem }.map! { |elem| elem.delete("\s") }
72+
73+
Hash[*lsl_content]
74+
end
75+
76+
def compute_size(info_hash)
77+
physical_partitions = info_hash['PPs'].to_i
78+
size_physical_partition = info_hash['PPSIZE']
79+
exp = size_physical_partition[/mega/] ? MEGABYTES_EXPONENT : GIGABYTES_EXPONENT
80+
size_physical_partition.to_i * physical_partitions * exp
81+
end
82+
end
83+
end
84+
end
85+
end
86+
end

lib/resolvers/aix/utils/odm_query.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ def like(field, value)
2727
def execute
2828
result = nil
2929
REPOS.each do |repo|
30-
break if result
30+
break if result && !result.empty?
3131

32-
result, _s = Open3.capture2("#{query} #{repo}")
32+
result, _stderr, _s = Open3.capture3("#{query} #{repo}")
3333
end
3434
result
3535
end
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# frozen_string_literal: true
2+
3+
describe Facts::Aix::Partitions do
4+
describe '#call_the_resolver' do
5+
subject(:fact) { Facts::Aix::Partitions.new }
6+
7+
let(:value) do
8+
{ '/dev/hd5' => { 'filesystem' => 'boot',
9+
'size_bytes' => 33_554_432,
10+
'size' => '32.00 MiB',
11+
'label' => 'primary_bootlv' } }
12+
end
13+
14+
before do
15+
allow(Facter::Resolvers::Aix::Partitions).to receive(:resolve).with(:partitions).and_return(value)
16+
end
17+
18+
it 'calls Facter::Resolvers::Aix::Partitions' do
19+
fact.call_the_resolver
20+
expect(Facter::Resolvers::Aix::Partitions).to have_received(:resolve).with(:partitions)
21+
end
22+
23+
it 'returns partitions fact' do
24+
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
25+
have_attributes(name: 'partitions', value: value)
26+
end
27+
end
28+
end
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# frozen_string_literal: true
2+
3+
describe Facter::Resolvers::Aix::Partitions do
4+
subject(:resolver) { Facter::Resolvers::Aix::Partitions }
5+
6+
let(:odm_query_spy) { instance_spy(Facter::ODMQuery) }
7+
let(:logger_spy) { instance_spy(Facter::Log) }
8+
9+
before do
10+
resolver.instance_variable_set(:@log, logger_spy)
11+
allow(Facter::ODMQuery).to receive(:new).and_return(odm_query_spy)
12+
allow(odm_query_spy).to receive(:equals).with('PdDvLn', 'logical_volume/lvsubclass/lvtype')
13+
allow(odm_query_spy).to receive(:execute).and_return(result)
14+
end
15+
16+
after do
17+
resolver.invalidate_cache
18+
end
19+
20+
context 'when retrieving partitions name fails' do
21+
let(:result) { nil }
22+
23+
before do
24+
allow(odm_query_spy).to receive(:execute).and_return(result)
25+
end
26+
27+
it 'returns nil' do
28+
expect(resolver.resolve(:partitions)).to be_nil
29+
end
30+
end
31+
32+
context 'when CuDv query succesful' do
33+
let(:result) { load_fixture('partitions_cudv_query').read }
34+
35+
let(:partitions) do
36+
{ '/dev/hd5' => { filesystem: 'boot', label: 'primary_bootlv', size: '32.00 MiB', size_bytes: 33_554_432 } }
37+
end
38+
39+
before do
40+
allow(Open3).to receive(:capture3).with('lslv -L hd5').and_return(load_fixture('lslv_output').read)
41+
allow(Open3).to receive(:capture3).with('lslv -L hd6').and_return(['', 'Error: something happened!', 1])
42+
end
43+
44+
it 'returns partitions informations' do
45+
expect(resolver.resolve(:partitions)).to eql(partitions)
46+
end
47+
48+
it 'logs stderr output in case lslv commands fails' do
49+
resolver.resolve(:partitions)
50+
51+
expect(logger_spy).to have_received(:debug).with('Error: something happened!')
52+
end
53+
end
54+
end

spec/facter/resolvers/utils/aix/odm_query_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
it 'creates a query' do
1111
odm_query.equals('name', '12345')
1212

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

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

20-
expect(Open3).to receive(:capture2)
20+
expect(Open3).to receive(:capture3)
2121
.with("odmget -q \"field1='value' AND field2 like 'value*'\" CuAt")
2222
odm_query.execute
2323
end

spec/fixtures/lslv_output

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
LOGICAL VOLUME: hd5 VOLUME GROUP: rootvg
2+
LV IDENTIFIER: 00fa684e00004c00000001715c6c0708.1 PERMISSION: read/write
3+
VG STATE: active/complete LV STATE: closed/syncd
4+
TYPE: boot WRITE VERIFY: off
5+
MAX LPs: 512 PP SIZE: 32 megabyte(s)
6+
COPIES: 1 SCHED POLICY: parallel
7+
LPs: 1 PPs: 1
8+
STALE PPs: 0 BB POLICY: non-relocatable
9+
INTER-POLICY: minimum RELOCATABLE: no
10+
INTRA-POLICY: edge UPPER BOUND: 32
11+
MOUNT POINT: N/A LABEL: primary_bootlv
12+
MIRROR WRITE CONSISTENCY: on/ACTIVE
13+
EACH LP COPY ON A SEPARATE PV ?: yes
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
CuDv:
2+
name = "hd5"
3+
status = 0
4+
chgstatus = 1
5+
ddins = ""
6+
location = ""
7+
parent = "rootvg"
8+
connwhere = ""
9+
PdDvLn = "logical_volume/lvsubclass/lvtype"
10+
11+
CuDv:
12+
name = "hd6"
13+
status = 0
14+
chgstatus = 1
15+
ddins = ""
16+
location = ""
17+
parent = "rootvg"
18+
connwhere = ""
19+
PdDvLn = "logical_volume/lvsubclass/lvtype"

0 commit comments

Comments
 (0)