Skip to content

Commit 19b89a1

Browse files
(FACT-2721) Added ldom resolver
1 parent 835641d commit 19b89a1

5 files changed

Lines changed: 289 additions & 0 deletions

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# frozen_string_literal: true
2+
3+
module Facts
4+
module Solaris
5+
class Virtual
6+
FACT_NAME = 'virtual'
7+
8+
def initialize
9+
@log = Facter::Log.new(self)
10+
end
11+
12+
def call_the_resolver
13+
@log.debug('Solaris Virtual Resolver')
14+
15+
fact_value = check_ldom || check_zone || 'physical'
16+
17+
@log.debug("Fact value is: #{fact_value}")
18+
19+
Facter::ResolvedFact.new(FACT_NAME, fact_value)
20+
end
21+
22+
def check_ldom
23+
@log.debug('Checking LDoms')
24+
Facter::Resolvers::Solaris::Ldom.resolve(:role_impl)
25+
end
26+
27+
def check_zone
28+
@log.debug('Checking LDoms')
29+
zone_name = Facter::Resolvers::SolarisZoneName.resolve(:current_zone_name)
30+
31+
return if zone_name == 'global'
32+
33+
zone_name
34+
end
35+
end
36+
end
37+
end
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# frozen_string_literal: true
2+
3+
module Facter
4+
module Resolvers
5+
module Solaris
6+
class Ldom < BaseResolver
7+
# :chassis_serial
8+
# :control_domain
9+
# :domain_name
10+
# :domain_uuid
11+
# :role_control
12+
# :role_io
13+
# :role_root
14+
# :role_service
15+
# :role_impl
16+
17+
@semaphore = Mutex.new
18+
@fact_list ||= {}
19+
20+
VIRTINFO_MAPPING = {
21+
chassis_serial: %w[DOMAINCHASSIS serialno],
22+
control_domain: %w[DOMAINCONTROL name],
23+
domain_name: %w[DOMAINNAME name],
24+
domain_uuid: %w[DOMAINUUID uuid],
25+
role_control: %w[DOMAINROLE control],
26+
role_io: %w[DOMAINROLE io],
27+
role_root: %w[DOMAINROLE root],
28+
role_service: %w[DOMAINROLE service],
29+
role_impl: %w[DOMAINROLE impl]
30+
}.freeze
31+
32+
class << self
33+
private
34+
35+
def post_resolve(fact_name)
36+
@fact_list.fetch(fact_name) { call_virtinfo(fact_name) }
37+
end
38+
39+
def call_virtinfo(fact_name)
40+
# return unless File.executable?('/usr/sbin/virtinfo')
41+
42+
virtinfo_output = Facter::Core::Execution.execute('/usr/sbin/virtinfo -a -p', logger: log)
43+
return if virtinfo_output.empty?
44+
45+
output_hash = parse_output(virtinfo_output)
46+
return if output_hash.empty?
47+
48+
VIRTINFO_MAPPING.each do |key, value|
49+
@fact_list[key] = output_hash.dig(*value)&.strip
50+
end
51+
52+
@fact_list[fact_name]
53+
end
54+
55+
def parse_output(output)
56+
result = {}
57+
output.each_line do |line|
58+
next unless line.include? 'DOMAIN'
59+
60+
x = line.split('|')
61+
result[x.shift] = x.map { |f| f.split('=') }.to_h
62+
end
63+
64+
result
65+
end
66+
end
67+
end
68+
end
69+
end
70+
end
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# frozen_string_literal: true
2+
3+
describe Facts::Solaris::Virtual do
4+
describe '#call_the_resolver' do
5+
subject(:fact) { Facts::Solaris::Virtual.new }
6+
7+
context 'when no hypervisor is found' do
8+
let(:vm) { 'physical' }
9+
10+
before do
11+
allow(Facter::Resolvers::SolarisZoneName).to receive(:resolve).with(:current_zone_name).and_return(nil)
12+
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_impl).and_return(nil)
13+
end
14+
15+
it 'returns virtual fact as physical' do
16+
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
17+
have_attributes(name: 'virtual', value: vm)
18+
end
19+
end
20+
21+
context 'when ldom hypervisor is found' do
22+
let(:vm) { 'LDoms' }
23+
24+
before do
25+
allow(Facter::Resolvers::SolarisZoneName).to receive(:resolve).with(:current_zone_name).and_return(nil)
26+
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_impl).and_return(vm)
27+
end
28+
29+
it 'returns virtual fact as physical' do
30+
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
31+
have_attributes(name: 'virtual', value: vm)
32+
end
33+
end
34+
35+
context 'when zone hypervisor is found' do
36+
let(:vm) { 'my_zone' }
37+
38+
before do
39+
allow(Facter::Resolvers::SolarisZoneName).to receive(:resolve).with(:current_zone_name).and_return(vm)
40+
allow(Facter::Resolvers::Solaris::Ldom).to receive(:resolve).with(:role_impl).and_return(nil)
41+
end
42+
43+
it 'returns virtual fact as physical' do
44+
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
45+
have_attributes(name: 'virtual', value: vm)
46+
end
47+
end
48+
end
49+
end
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# frozen_string_literal: true
2+
3+
describe Facter::Resolvers::Solaris::Ldom do
4+
subject(:resolver) { Facter::Resolvers::Solaris::Ldom }
5+
6+
let(:log_spy) { instance_spy(Facter::Log) }
7+
8+
before do
9+
resolver.instance_variable_set(:@log, log_spy)
10+
allow(Facter::Core::Execution)
11+
.to receive(:execute)
12+
.with('/usr/sbin/virtinfo -a -p', logger: log_spy)
13+
.and_return(output)
14+
end
15+
16+
after do
17+
resolver.invalidate_cache
18+
end
19+
20+
context 'when syscall returns valid output' do
21+
let(:output) { load_fixture('virtinfo').read }
22+
23+
it 'parses chassis_serial' do
24+
expect(resolver.resolve(:chassis_serial)).to eq('AK00358110')
25+
end
26+
27+
it 'parses control_domain' do
28+
expect(resolver.resolve(:control_domain)).to eq('opdx-a0-sun2')
29+
end
30+
31+
it 'parses domain_name' do
32+
expect(resolver.resolve(:domain_name)).to eq('sol11-11')
33+
end
34+
35+
it 'parses domain_uuid' do
36+
expect(resolver.resolve(:domain_uuid)).to eq('415dfab4-c373-4ac0-9414-8bf00801fb72')
37+
end
38+
39+
it 'parses role_control' do
40+
expect(resolver.resolve(:role_control)).to eq('false')
41+
end
42+
43+
it 'parses role_io' do
44+
expect(resolver.resolve(:role_io)).to eq('false')
45+
end
46+
47+
it 'parses role_root' do
48+
expect(resolver.resolve(:role_root)).to eq('false')
49+
end
50+
51+
it 'parses role_service' do
52+
expect(resolver.resolve(:role_service)).to eq('false')
53+
end
54+
end
55+
56+
context 'when syscall returns invalid output' do
57+
let(:output) { 'iNvAlId OuTpUt' }
58+
59+
it 'parses chassis_serial to nil' do
60+
expect(resolver.resolve(:chassis_serial)).to be_nil
61+
end
62+
63+
it 'parses control_domain to nil' do
64+
expect(resolver.resolve(:control_domain)).to be_nil
65+
end
66+
67+
it 'parses domain_name to nil' do
68+
expect(resolver.resolve(:domain_name)).to be_nil
69+
end
70+
71+
it 'parses domain_uuid to nil' do
72+
expect(resolver.resolve(:domain_uuid)).to be_nil
73+
end
74+
75+
it 'parses role_control to nil' do
76+
expect(resolver.resolve(:role_control)).to be_nil
77+
end
78+
79+
it 'parses role_io to nil' do
80+
expect(resolver.resolve(:role_io)).to be_nil
81+
end
82+
83+
it 'parses role_root to nil' do
84+
expect(resolver.resolve(:role_root)).to be_nil
85+
end
86+
87+
it 'parses role_service to nil' do
88+
expect(resolver.resolve(:role_service)).to be_nil
89+
end
90+
end
91+
92+
context 'when syscall has no output' do
93+
let(:output) { '' }
94+
95+
it 'parses chassis_serial to nil' do
96+
expect(resolver.resolve(:chassis_serial)).to be_nil
97+
end
98+
99+
it 'parses control_domain to nil' do
100+
expect(resolver.resolve(:control_domain)).to be_nil
101+
end
102+
103+
it 'parses domain_name to nil' do
104+
expect(resolver.resolve(:domain_name)).to be_nil
105+
end
106+
107+
it 'parses domain_uuid to nil' do
108+
expect(resolver.resolve(:domain_uuid)).to be_nil
109+
end
110+
111+
it 'parses role_control to nil' do
112+
expect(resolver.resolve(:role_control)).to be_nil
113+
end
114+
115+
it 'parses role_io to nil' do
116+
expect(resolver.resolve(:role_io)).to be_nil
117+
end
118+
119+
it 'parses role_root to nil' do
120+
expect(resolver.resolve(:role_root)).to be_nil
121+
end
122+
123+
it 'parses role_service to nil' do
124+
expect(resolver.resolve(:role_service)).to be_nil
125+
end
126+
end
127+
end

spec/fixtures/virtinfo

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
VERSION 1.0
2+
DOMAINROLE|impl=LDoms|control=false|io=false|service=false|root=false
3+
DOMAINNAME|name=sol11-11
4+
DOMAINUUID|uuid=415dfab4-c373-4ac0-9414-8bf00801fb72
5+
DOMAINCONTROL|name=opdx-a0-sun2
6+
DOMAINCHASSIS|serialno=AK00358110

0 commit comments

Comments
 (0)