facter 4.0.40 → 4.0.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/facter.rb +72 -19
  3. data/lib/facter/config.rb +355 -0
  4. data/lib/facter/custom_facts/core/aggregate.rb +51 -17
  5. data/lib/facter/custom_facts/core/execution.rb +54 -38
  6. data/lib/facter/custom_facts/core/execution/base.rb +46 -40
  7. data/lib/facter/custom_facts/util/fact.rb +1 -1
  8. data/lib/facter/custom_facts/util/parser.rb +17 -3
  9. data/lib/facter/custom_facts/util/resolution.rb +40 -11
  10. data/lib/facter/facts/linux/ec2_metadata.rb +5 -30
  11. data/lib/facter/facts/linux/ec2_userdata.rb +5 -28
  12. data/lib/facter/facts/linux/is_virtual.rb +7 -46
  13. data/lib/facter/facts/linux/virtual.rb +3 -58
  14. data/lib/facter/facts/rhel/os/release.rb +1 -1
  15. data/lib/facter/facts/solaris/hypervisors/ldom.rb +3 -0
  16. data/lib/facter/facts/solaris/ldom.rb +4 -1
  17. data/lib/facter/facts/solaris/zones.rb +1 -1
  18. data/lib/facter/facts_utils/virtual_detector.rb +78 -0
  19. data/lib/facter/framework/benchmarking/timer.rb +4 -2
  20. data/lib/facter/framework/cli/cli.rb +19 -5
  21. data/lib/facter/framework/config/fact_groups.rb +10 -8
  22. data/lib/facter/framework/core/cache_manager.rb +78 -28
  23. data/lib/facter/framework/core/fact/internal/core_fact.rb +6 -1
  24. data/lib/facter/framework/core/fact/internal/internal_fact_manager.rb +38 -4
  25. data/lib/facter/framework/core/fact_augmenter.rb +1 -1
  26. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +1 -1
  27. data/lib/facter/framework/core/fact_manager.rb +1 -1
  28. data/lib/facter/framework/core/options/config_file_options.rb +16 -5
  29. data/lib/facter/framework/core/options/option_store.rb +40 -20
  30. data/lib/facter/framework/detector/os_hierarchy.rb +5 -9
  31. data/lib/facter/resolvers/aio_agent_version.rb +1 -1
  32. data/lib/facter/resolvers/aix/architecture_resolver.rb +17 -2
  33. data/lib/facter/resolvers/aix/disks.rb +2 -1
  34. data/lib/facter/resolvers/aix/filesystem_resolver.rb +1 -1
  35. data/lib/facter/resolvers/aix/hardware_resolver.rb +2 -1
  36. data/lib/facter/resolvers/aix/load_averages_resolver.rb +2 -1
  37. data/lib/facter/resolvers/aix/memory.rb +2 -1
  38. data/lib/facter/resolvers/aix/mountpoints.rb +2 -1
  39. data/lib/facter/resolvers/aix/networking_resolver.rb +1 -1
  40. data/lib/facter/resolvers/aix/nim.rb +1 -1
  41. data/lib/facter/resolvers/aix/os_level.rb +2 -2
  42. data/lib/facter/resolvers/aix/partitions.rb +2 -1
  43. data/lib/facter/resolvers/aix/processors.rb +2 -1
  44. data/lib/facter/resolvers/aix/serialnumber.rb +1 -1
  45. data/lib/facter/resolvers/augeas_resolver.rb +8 -2
  46. data/lib/facter/resolvers/base_resolver.rb +11 -4
  47. data/lib/facter/resolvers/bsd/processors.rb +13 -8
  48. data/lib/facter/resolvers/cloud.rb +1 -1
  49. data/lib/facter/resolvers/containers.rb +2 -1
  50. data/lib/facter/resolvers/debian_version.rb +1 -1
  51. data/lib/facter/resolvers/disk_resolver.rb +15 -4
  52. data/lib/facter/resolvers/dmi_decode.rb +2 -1
  53. data/lib/facter/resolvers/dmi_resolver.rb +4 -3
  54. data/lib/facter/resolvers/ec2.rb +2 -1
  55. data/lib/facter/resolvers/eos_release_resolver.rb +1 -1
  56. data/lib/facter/resolvers/facterversion_resolver.rb +1 -1
  57. data/lib/facter/resolvers/filesystems_resolver.rb +4 -1
  58. data/lib/facter/resolvers/fips_enabled_resolver.rb +4 -1
  59. data/lib/facter/resolvers/freebsd/dmi_resolver.rb +1 -1
  60. data/lib/facter/resolvers/freebsd/freebsd_version_resolver.rb +9 -7
  61. data/lib/facter/resolvers/freebsd/geom_resolver.rb +14 -21
  62. data/lib/facter/resolvers/freebsd/processors.rb +13 -8
  63. data/lib/facter/resolvers/freebsd/swap_memory_resolver.rb +2 -1
  64. data/lib/facter/resolvers/freebsd/system_memory_resolver.rb +2 -1
  65. data/lib/facter/resolvers/gce.rb +2 -1
  66. data/lib/facter/resolvers/hostname_resolver.rb +2 -1
  67. data/lib/facter/resolvers/identity_resolver.rb +2 -1
  68. data/lib/facter/resolvers/linux/docker_uptime.rb +2 -1
  69. data/lib/facter/resolvers/linux/load_averages.rb +2 -1
  70. data/lib/facter/resolvers/load_averages.rb +2 -1
  71. data/lib/facter/resolvers/lpar_resolver.rb +1 -1
  72. data/lib/facter/resolvers/lsb_release_resolver.rb +1 -1
  73. data/lib/facter/resolvers/lspci.rb +1 -1
  74. data/lib/facter/resolvers/macosx/dmi_resolver.rb +1 -1
  75. data/lib/facter/resolvers/macosx/filesystems_resolver.rb +1 -1
  76. data/lib/facter/resolvers/macosx/load_averages_resolver.rb +2 -1
  77. data/lib/facter/resolvers/macosx/mountpoints_resolver.rb +2 -1
  78. data/lib/facter/resolvers/macosx/processor_resolver.rb +2 -1
  79. data/lib/facter/resolvers/macosx/swap_memory_resolver.rb +2 -1
  80. data/lib/facter/resolvers/macosx/system_memory_resolver.rb +2 -1
  81. data/lib/facter/resolvers/macosx/system_profiler_resolver.rb +1 -3
  82. data/lib/facter/resolvers/memory_resolver.rb +15 -15
  83. data/lib/facter/resolvers/mountpoints_resolver.rb +54 -23
  84. data/lib/facter/resolvers/networking_linux_resolver.rb +15 -9
  85. data/lib/facter/resolvers/networking_resolver.rb +1 -1
  86. data/lib/facter/resolvers/open_vz.rb +1 -1
  87. data/lib/facter/resolvers/os_release_resolver.rb +1 -1
  88. data/lib/facter/resolvers/partitions.rb +62 -58
  89. data/lib/facter/resolvers/path_resolver.rb +1 -1
  90. data/lib/facter/resolvers/processors_resolver.rb +9 -2
  91. data/lib/facter/resolvers/puppet_version_resolver.rb +1 -1
  92. data/lib/facter/resolvers/redhat_release_resolver.rb +1 -1
  93. data/lib/facter/resolvers/ruby_resolver.rb +1 -1
  94. data/lib/facter/resolvers/selinux_resolver.rb +1 -1
  95. data/lib/facter/resolvers/solaris/disks.rb +1 -1
  96. data/lib/facter/resolvers/solaris/dmi.rb +3 -1
  97. data/lib/facter/resolvers/solaris/dmi_sparc.rb +1 -1
  98. data/lib/facter/resolvers/solaris/filesystems.rb +1 -1
  99. data/lib/facter/resolvers/solaris/ipaddress.rb +2 -1
  100. data/lib/facter/resolvers/solaris/ldom.rb +1 -3
  101. data/lib/facter/resolvers/solaris/memory.rb +2 -1
  102. data/lib/facter/resolvers/solaris/mountpoints.rb +60 -0
  103. data/lib/facter/resolvers/solaris/networking.rb +2 -3
  104. data/lib/facter/resolvers/solaris/os_release.rb +6 -4
  105. data/lib/facter/resolvers/solaris/processors.rb +2 -1
  106. data/lib/facter/resolvers/solaris/zone.rb +1 -1
  107. data/lib/facter/resolvers/solaris/zone_name.rb +1 -1
  108. data/lib/facter/resolvers/ssh_resolver.rb +8 -5
  109. data/lib/facter/resolvers/suse_release_resolver.rb +1 -1
  110. data/lib/facter/resolvers/sw_vers_resolver.rb +2 -2
  111. data/lib/facter/resolvers/timezone_resolver.rb +1 -1
  112. data/lib/facter/resolvers/uname_resolver.rb +1 -1
  113. data/lib/facter/resolvers/uptime_resolver.rb +1 -1
  114. data/lib/facter/resolvers/utils/networking.rb +2 -0
  115. data/lib/facter/resolvers/virt_what.rb +1 -1
  116. data/lib/facter/resolvers/vmware.rb +1 -1
  117. data/lib/facter/resolvers/windows/aio_agent_version.rb +1 -1
  118. data/lib/facter/resolvers/windows/dmi_bios_resolver.rb +1 -1
  119. data/lib/facter/resolvers/windows/dmi_computersystem_resolver.rb +1 -1
  120. data/lib/facter/resolvers/windows/fips_resolver.rb +2 -1
  121. data/lib/facter/resolvers/windows/hardware_architecture_resolver.rb +2 -1
  122. data/lib/facter/resolvers/windows/identity_resolver.rb +2 -1
  123. data/lib/facter/resolvers/windows/kernel_resolver.rb +3 -1
  124. data/lib/facter/resolvers/windows/memory_resolver.rb +3 -1
  125. data/lib/facter/resolvers/windows/netkvm_resolver.rb +2 -1
  126. data/lib/facter/resolvers/windows/networking_resolver.rb +2 -1
  127. data/lib/facter/resolvers/windows/processors_resolver.rb +2 -1
  128. data/lib/facter/resolvers/windows/product_release_resolver.rb +2 -1
  129. data/lib/facter/resolvers/windows/ssh.rb +3 -1
  130. data/lib/facter/resolvers/windows/system32_resolver.rb +3 -1
  131. data/lib/facter/resolvers/windows/uptime_resolver.rb +2 -1
  132. data/lib/facter/resolvers/windows/virtualization_resolver.rb +2 -1
  133. data/lib/facter/resolvers/windows/win_os_description_resolver.rb +3 -1
  134. data/lib/facter/resolvers/wpar_resolver.rb +1 -1
  135. data/lib/facter/resolvers/xen.rb +1 -1
  136. data/lib/facter/resolvers/zfs.rb +2 -1
  137. data/lib/facter/resolvers/zpool.rb +2 -1
  138. data/lib/facter/version.rb +1 -1
  139. metadata +7 -5
  140. data/lib/facter/fact_groups.conf +0 -308
  141. data/lib/facter/os_hierarchy.json +0 -36
@@ -4,7 +4,8 @@ module Facter
4
4
  module Resolvers
5
5
  module Macosx
6
6
  class Processors < BaseResolver
7
- @fact_list = {}
7
+ init_resolver
8
+
8
9
  ITEMS = { logical_count: 'hw.logicalcpu_max',
9
10
  physical_count: 'hw.physicalcpu_max',
10
11
  brand: 'machdep.cpu.brand_string',
@@ -4,7 +4,8 @@ module Facter
4
4
  module Resolvers
5
5
  module Macosx
6
6
  class SwapMemory < BaseResolver
7
- @fact_list ||= {}
7
+ init_resolver
8
+
8
9
  class << self
9
10
  private
10
11
 
@@ -4,7 +4,8 @@ module Facter
4
4
  module Resolvers
5
5
  module Macosx
6
6
  class SystemMemory < BaseResolver
7
- @fact_list ||= {}
7
+ init_resolver
8
+
8
9
  class << self
9
10
  private
10
11
 
@@ -15,7 +15,7 @@ module Facter
15
15
  SP_ETHERNET_DATA_TYPE = %i[type bus vendor_id device_id subsystem_vendor_id
16
16
  subsystem_id revision_id bsd_name kext_name location version].freeze
17
17
 
18
- @fact_list = {}
18
+ init_resolver
19
19
 
20
20
  class << self
21
21
  private
@@ -25,8 +25,6 @@ module Facter
25
25
  end
26
26
 
27
27
  def retrieve_system_profiler(fact_name)
28
- @fact_list ||= {}
29
-
30
28
  case fact_name
31
29
  when *SP_HARDWARE_DATA_TYPE
32
30
  @fact_list.merge!(SystemProfileExecutor.execute('SPHardwareDataType'))
@@ -4,8 +4,10 @@ module Facter
4
4
  module Resolvers
5
5
  module Linux
6
6
  class Memory < BaseResolver
7
- @fact_list ||= {}
7
+ init_resolver
8
+
8
9
  @log = Facter::Log.new(self)
10
+
9
11
  class << self
10
12
  private
11
13
 
@@ -25,11 +27,21 @@ module Facter
25
27
 
26
28
  def read_system(output)
27
29
  @fact_list[:total] = kilobytes_to_bytes(output.match(/MemTotal:\s+(\d+)\s/)[1])
28
- @fact_list[:memfree] = kilobytes_to_bytes(output.match(/MemFree:\s+(\d+)\s/)[1])
29
- @fact_list[:used_bytes] = compute_used(@fact_list[:total], reclaimable_memory(output))
30
+ @fact_list[:memfree] = memfree(output)
31
+ @fact_list[:used_bytes] = compute_used(@fact_list[:total], @fact_list[:memfree])
30
32
  @fact_list[:capacity] = compute_capacity(@fact_list[:used_bytes], @fact_list[:total])
31
33
  end
32
34
 
35
+ def memfree(output)
36
+ available = output.match(/MemAvailable:\s+(\d+)\s/)
37
+ return kilobytes_to_bytes(available[1]) if available
38
+
39
+ buffers = kilobytes_to_bytes(output.match(/Buffers:\s+(\d+)\s/)[1])
40
+ cached = kilobytes_to_bytes(output.match(/Cached:\s+(\d+)\s/)[1])
41
+ memfree = kilobytes_to_bytes(output.match(/MemFree:\s+(\d+)\s/)[1])
42
+ memfree + buffers + cached
43
+ end
44
+
33
45
  def read_swap(output)
34
46
  total = output.match(/SwapTotal:\s+(\d+)\s/)[1]
35
47
  return if total.to_i.zero?
@@ -44,18 +56,6 @@ module Facter
44
56
  quantity.to_i * 1024
45
57
  end
46
58
 
47
- def reclaimable_memory(output)
48
- buffers = kilobytes_to_bytes(output.match(/Buffers:\s+(\d+)\s/)[1])
49
- cached = kilobytes_to_bytes(output.match(/Cached:\s+(\d+)\s/)[1])
50
- s_reclaimable = output.match(/SReclaimable:\s+(\d+)\s/)
51
- s_reclaimable = if s_reclaimable
52
- kilobytes_to_bytes(s_reclaimable[1])
53
- else
54
- 0
55
- end
56
- @fact_list[:memfree] + buffers + cached + s_reclaimable
57
- end
58
-
59
59
  def compute_capacity(used, total)
60
60
  format('%<computed_capacity>.2f', computed_capacity: (used / total.to_f * 100)) + '%'
61
61
  end
@@ -4,19 +4,36 @@ module Facter
4
4
  module Resolvers
5
5
  class Mountpoints < BaseResolver
6
6
  include Facter::FilesystemHelper
7
- @fact_list ||= {}
7
+
8
+ init_resolver
9
+
8
10
  @log = Facter::Log.new(self)
11
+
9
12
  class << self
10
13
  private
11
14
 
12
15
  def post_resolve(fact_name)
13
- @fact_list.fetch(fact_name) { read_mounts }
16
+ @fact_list.fetch(fact_name) { read_mounts(fact_name) }
14
17
  end
15
18
 
16
19
  def root_device
17
20
  cmdline = Util::FileHelper.safe_read('/proc/cmdline')
18
21
  match = cmdline.match(/root=([^\s]+)/)
19
- match&.captures&.first
22
+ root = match&.captures&.first
23
+
24
+ if !root.nil? && root.include?('=')
25
+ # We are dealing with the PARTUUID of the partition. Need to extract partition path.
26
+ root_partition_path = convert_partuuid_to_path(root)
27
+ root = root_partition_path unless root_partition_path.nil?
28
+ end
29
+ root
30
+ end
31
+
32
+ def convert_partuuid_to_path(root)
33
+ blkid_content = Facter::Core::Execution.execute('blkid', logger: log)
34
+ partuuid = root.split('=').last
35
+ match = blkid_content.match(/(.+)#{partuuid}/)
36
+ match&.captures&.first&.split(':')&.first
20
37
  end
21
38
 
22
39
  def compute_device(device)
@@ -26,32 +43,46 @@ module Facter
26
43
  device
27
44
  end
28
45
 
29
- def read_mounts # rubocop:disable Metrics/AbcSize
46
+ def read_mounts(fact_name)
30
47
  mounts = []
31
- FilesystemHelper.read_mountpoints.each do |fs|
32
- device = compute_device(fs.name)
33
- filesystem = fs.mount_type
34
- path = fs.mount_point
35
- options = fs.options.split(',').map(&:strip)
48
+ FilesystemHelper.read_mountpoints.each do |file_system|
49
+ mount = {}
50
+ get_mount_data(file_system, mount)
51
+
52
+ next if mount[:path] =~ %r{^/(proc|sys)} && mount[:filesystem] != 'tmpfs' || mount[:filesystem] == 'autofs'
53
+
54
+ get_mount_sizes(mount)
55
+ mounts << mount
56
+ end
36
57
 
37
- next if path =~ %r{^/(proc|sys)} && filesystem != 'tmpfs' || filesystem == 'autofs'
58
+ @fact_list[:mountpoints] = mounts
59
+ @fact_list[fact_name]
60
+ end
38
61
 
39
- stats = FilesystemHelper.read_mountpoint_stats(path)
40
- size_bytes = stats.bytes_total.abs
41
- available_bytes = stats.bytes_available.abs
62
+ def get_mount_data(file_system, mount)
63
+ mount[:device] = compute_device(file_system.name)
64
+ mount[:filesystem] = file_system.mount_type
65
+ mount[:path] = file_system.mount_point
66
+ mount[:options] = file_system.options.split(',').map(&:strip)
67
+ end
42
68
 
43
- used_bytes = stats.bytes_used.abs
44
- total_bytes = used_bytes + available_bytes
45
- capacity = FilesystemHelper.compute_capacity(used_bytes, total_bytes)
69
+ def get_mount_sizes(mount)
70
+ stats = FilesystemHelper.read_mountpoint_stats(mount[:path])
46
71
 
47
- size = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(size_bytes)
48
- available = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(available_bytes)
49
- used = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(used_bytes)
72
+ get_bytes_data(mount, stats)
50
73
 
51
- mounts << Hash[FilesystemHelper::MOUNT_KEYS.zip(FilesystemHelper::MOUNT_KEYS
52
- .map { |v| binding.local_variable_get(v) })]
53
- end
54
- @fact_list[:mountpoints] = mounts
74
+ total_bytes = mount[:used_bytes] + mount[:available_bytes]
75
+ mount[:capacity] = FilesystemHelper.compute_capacity(mount[:used_bytes], total_bytes)
76
+
77
+ mount[:size] = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(mount[:size_bytes])
78
+ mount[:available] = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(mount[:available_bytes])
79
+ mount[:used] = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(mount[:used_bytes])
80
+ end
81
+
82
+ def get_bytes_data(mount, stats)
83
+ mount[:size_bytes] = stats.bytes_total.abs
84
+ mount[:available_bytes] = stats.bytes_available.abs
85
+ mount[:used_bytes] = stats.bytes_used.abs
55
86
  end
56
87
  end
57
88
  end
@@ -3,22 +3,20 @@
3
3
  module Facter
4
4
  module Resolvers
5
5
  class NetworkingLinux < BaseResolver
6
- @fact_list = {}
6
+ init_resolver
7
+
7
8
  DIRS = ['/var/lib/dhclient/', '/var/lib/dhcp/', '/var/lib/dhcp3/', '/var/lib/NetworkManager/', '/var/db/'].freeze
8
9
 
9
10
  class << self
10
11
  private
11
12
 
12
13
  def post_resolve(fact_name)
13
- log.debug('in networking_linux_resolver')
14
14
  @fact_list.fetch(fact_name) { retrieve_network_info(fact_name) }
15
15
 
16
16
  @fact_list[fact_name]
17
17
  end
18
18
 
19
19
  def retrieve_network_info(fact_name)
20
- @fact_list ||= {}
21
-
22
20
  retrieve_interface_info
23
21
  retrieve_interfaces_mac_and_mtu
24
22
  retrieve_default_interface
@@ -60,9 +58,14 @@ module Facter
60
58
  return if !network_info[interface_name] || network_info[interface_name][:dhcp]
61
59
 
62
60
  index = tokens[0].delete(':')
63
- dhcp = Util::FileHelper.safe_read("/run/systemd/netif/leases/#{index}", nil)
64
- network_info[interface_name][:dhcp] = dhcp.match(/SERVER_ADDRESS=(.*)/)[1] if dhcp
65
- network_info[interface_name][:dhcp] ||= retrieve_from_other_directories(interface_name)
61
+ file_content = Util::FileHelper.safe_read("/run/systemd/netif/leases/#{index}", nil)
62
+ dhcp = file_content.match(/SERVER_ADDRESS=(.*)/) if file_content
63
+ if dhcp
64
+ network_info[interface_name][:dhcp] = dhcp[1]
65
+ else
66
+ alternate_dhcp = retrieve_from_other_directories(interface_name)
67
+ network_info[interface_name][:dhcp] = alternate_dhcp if alternate_dhcp
68
+ end
66
69
  end
67
70
 
68
71
  def retrieve_from_other_directories(interface_name)
@@ -76,7 +79,8 @@ module Facter
76
79
  content = Util::FileHelper.safe_read("#{dir}#{file}", nil)
77
80
  next unless content =~ /interface.*#{interface_name}/
78
81
 
79
- return content.match(/dhcp-server-identifier ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/)[1]
82
+ dhcp = content.match(/dhcp-server-identifier ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/)
83
+ return dhcp[1] if dhcp
80
84
  end
81
85
  end
82
86
  return unless File.readable?('/var/lib/NetworkManager/')
@@ -108,6 +112,8 @@ module Facter
108
112
  "ip4_mask_length = #{ip4_mask_length}")
109
113
 
110
114
  binding = ::Resolvers::Utils::Networking.build_binding(ip4_address, ip4_mask_length)
115
+ return unless binding
116
+
111
117
  build_network_info_structure!(network_info, interface_name, :bindings)
112
118
 
113
119
  network_info[interface_name][:bindings] << binding
@@ -115,7 +121,7 @@ module Facter
115
121
 
116
122
  def retrieve_name_and_ip_info(tokens)
117
123
  interface_name = tokens[1]
118
- ip_info = tokens[3].split('/')
124
+ ip_info = tokens[4] =~ /peer/ ? tokens[5].split('/') : tokens[3].split('/')
119
125
  ip_address = ip_info[0]
120
126
  ip_mask_length = ip_info[1]
121
127
 
@@ -3,7 +3,7 @@
3
3
  module Facter
4
4
  module Resolvers
5
5
  class Networking < BaseResolver
6
- @fact_list ||= {}
6
+ init_resolver
7
7
 
8
8
  class << self
9
9
  private
@@ -5,7 +5,7 @@ module Facter
5
5
  class OpenVz < BaseResolver
6
6
  # build
7
7
 
8
- @fact_list ||= {}
8
+ init_resolver
9
9
 
10
10
  class << self
11
11
  private
@@ -14,7 +14,7 @@ module Facter
14
14
  # :support_url
15
15
  # :bug_report_url
16
16
 
17
- @fact_list ||= {}
17
+ init_resolver
18
18
 
19
19
  class << self
20
20
  private
@@ -3,7 +3,8 @@
3
3
  module Facter
4
4
  module Resolvers
5
5
  class Partitions < BaseResolver
6
- @fact_list ||= {}
6
+ init_resolver
7
+
7
8
  BLOCK_PATH = '/sys/block'
8
9
  BLOCK_SIZE = 512
9
10
 
@@ -15,98 +16,122 @@ module Facter
15
16
  end
16
17
 
17
18
  def read_partitions(fact_name)
18
- @fact_list[:partitions] = {}
19
- return {} unless File.readable?(BLOCK_PATH)
19
+ return unless File.readable?(BLOCK_PATH)
20
20
 
21
21
  block_devices = Dir.entries(BLOCK_PATH).reject { |dir| dir =~ /^\.+/ }
22
+ @fact_list[:partitions] = {} unless block_devices.empty?
23
+ blkid_and_lsblk = {}
24
+
22
25
  block_devices.each do |block_device|
23
26
  block_path = "#{BLOCK_PATH}/#{block_device}"
24
27
  if File.directory?("#{block_path}/device")
25
- extract_from_device(block_path)
28
+ extract_from_device(block_path, blkid_and_lsblk)
26
29
  elsif File.directory?("#{block_path}/dm")
27
- extract_from_dm(block_path)
30
+ extract_from_dm(block_path, block_device, blkid_and_lsblk)
28
31
  elsif File.directory?("#{block_path}/loop")
29
- extract_from_loop(block_path)
32
+ extract_from_loop(block_path, block_device, blkid_and_lsblk)
30
33
  end
31
34
  end
35
+
32
36
  @fact_list[fact_name]
33
37
  end
34
38
 
35
- def extract_from_device(block_path)
39
+ def extract_from_device(block_path, blkid_and_lsblk)
36
40
  subdirs = browse_subdirectories(block_path)
37
41
  subdirs.each do |subdir|
38
42
  name = "/dev/#{subdir.split('/').last}"
39
- populate_partitions(name, subdir)
43
+ populate_partitions(name, subdir, blkid_and_lsblk)
40
44
  end
41
45
  end
42
46
 
43
- def extract_from_dm(block_path)
47
+ def extract_from_dm(block_path, block_device, blkid_and_lsblk)
44
48
  map_name = Util::FileHelper.safe_read("#{block_path}/dm/name").chomp
45
49
  if map_name.empty?
46
- populate_partitions("/dev#{block_path}", block_path)
50
+ populate_partitions("/dev/#{block_device}", block_path, blkid_and_lsblk)
47
51
  else
48
- populate_partitions("/dev/mapper/#{map_name}", block_path)
52
+ populate_partitions("/dev/mapper/#{map_name}", block_path, blkid_and_lsblk)
49
53
  end
50
54
  end
51
55
 
52
- def extract_from_loop(block_path)
56
+ def extract_from_loop(block_path, block_device, blkid_and_lsblk)
53
57
  backing_file = Util::FileHelper.safe_read("#{block_path}/loop/backing_file").chomp
54
58
  if backing_file.empty?
55
- populate_partitions("/dev#{block_path}", block_path)
59
+ populate_partitions("/dev/#{block_device}", block_path, blkid_and_lsblk)
56
60
  else
57
- populate_partitions("/dev#{block_path}", block_path, backing_file)
61
+ populate_partitions("/dev/#{block_device}", block_path, blkid_and_lsblk, backing_file)
58
62
  end
59
63
  end
60
64
 
61
- def populate_partitions(partition_name, block_path, backing_file = nil)
62
- @fact_list[:partitions][partition_name] = {}
65
+ def populate_partitions(partition_name, block_path, blkid_and_lsblk, backing_file = nil)
63
66
  size_bytes = Util::FileHelper.safe_read("#{block_path}/size", '0')
64
67
  .chomp.to_i * BLOCK_SIZE
65
68
  info_hash = { size_bytes: size_bytes,
66
69
  size: Facter::FactsUtils::UnitConverter.bytes_to_human_readable(size_bytes),
67
70
  backing_file: backing_file }
68
- info_hash.merge!(populate_from_syscalls(partition_name))
71
+ info_hash.merge!(populate_from_syscalls(partition_name, blkid_and_lsblk))
69
72
  @fact_list[:partitions][partition_name] = info_hash.reject { |_key, value| value.nil? }
70
73
  end
71
74
 
72
- def populate_from_syscalls(partition_name)
73
- part_info = populate_from_blkid(partition_name)
75
+ def populate_from_syscalls(partition_name, blkid_and_lsblk)
76
+ part_info = populate_from_blkid(partition_name, blkid_and_lsblk)
74
77
 
75
- return pupulate_from_lsblk(partition_name) if part_info.empty?
78
+ return populate_from_lsblk(partition_name, blkid_and_lsblk) if part_info.empty?
76
79
 
77
80
  part_info
78
81
  end
79
82
 
80
- def populate_from_blkid(partition_name)
81
- return {} unless blkid_command?
83
+ def browse_subdirectories(path)
84
+ dirs = Dir[File.join(path, '**', '*')].select { |p| File.directory? p }
85
+ dirs.select { |subdir| subdir.split('/').last.include?(path.split('/').last) }.reject(&:nil?)
86
+ end
87
+
88
+ def populate_from_blkid(partition_name, blkid_and_lsblk)
89
+ return {} unless available?('blkid', blkid_and_lsblk)
90
+
91
+ blkid_and_lsblk[:blkid] ||= execute_and_extract_blkid_info
92
+
93
+ partition_data = blkid_and_lsblk[:blkid][partition_name]
94
+ return {} unless partition_data
82
95
 
83
- @blkid_content ||= execute_and_extract_blkid_info
84
- return {} unless @blkid_content[partition_name]
96
+ filesys = partition_data['TYPE']
97
+ uuid = partition_data['UUID']
98
+ label = partition_data['LABEL']
99
+ part_uuid = partition_data['PARTUUID']
100
+ part_label = partition_data['PARTLABEL']
85
101
 
86
- filesys = @blkid_content[partition_name]['TYPE']
87
- uuid = @blkid_content[partition_name]['UUID']
88
- label = @blkid_content[partition_name]['LABEL']
89
- part_uuid = @blkid_content[partition_name]['PARTUUID']
90
- part_label = @blkid_content[partition_name]['PARTLABEL']
91
102
  { filesystem: filesys, uuid: uuid, label: label, partuuid: part_uuid, partlabel: part_label }
92
103
  end
93
104
 
94
- def blkid_command?
95
- return @blkid_exists unless @blkid_exists.nil?
105
+ def available?(command, blkid_and_lsblk)
106
+ command_exists_key = command == 'blkid' ? :blkid_exists : :lsblk_exists
96
107
 
97
- output = Facter::Core::Execution.execute('which blkid', logger: log)
108
+ return blkid_and_lsblk[command_exists_key] unless blkid_and_lsblk[command_exists_key].nil?
98
109
 
99
- @blkid_exists = !output.empty?
110
+ output = Facter::Core::Execution.execute("which #{command}", logger: log)
111
+
112
+ blkid_and_lsblk[:command_exists_key] = !output.empty?
113
+ end
114
+
115
+ def execute_and_extract_blkid_info
116
+ stdout = Facter::Core::Execution.execute('blkid', logger: log)
117
+ output_hash = Hash[*stdout.split(/^([^:]+):/)[1..-1]]
118
+ output_hash.each do |key, value|
119
+ output_hash[key] = Hash[*value.delete('"').chomp.rstrip.split(/ ([^= ]+)=/)[1..-1]]
120
+ end
100
121
  end
101
122
 
102
- def pupulate_from_lsblk(partition_name)
103
- return {} unless lsblk_command?
123
+ def populate_from_lsblk(partition_name, blkid_and_lsblk)
124
+ return {} unless available?('lsblk', blkid_and_lsblk)
104
125
 
105
- @lsblk_content ||= Facter::Core::Execution.execute('lsblk -fp', logger: log)
126
+ blkid_and_lsblk[:lsblk] ||= Facter::Core::Execution.execute('lsblk -fp', logger: log)
106
127
 
107
- part_info = @lsblk_content.match(/#{partition_name}.*/).to_s.split(' ')
128
+ part_info = blkid_and_lsblk[:lsblk].match(/#{partition_name}.*/).to_s.split(' ')
108
129
  return {} if part_info.empty?
109
130
 
131
+ parse_part_info(part_info)
132
+ end
133
+
134
+ def parse_part_info(part_info)
110
135
  result = { filesystem: part_info[1] }
111
136
 
112
137
  if part_info.count.eql?(5)
@@ -118,27 +143,6 @@ module Facter
118
143
 
119
144
  result
120
145
  end
121
-
122
- def lsblk_command?
123
- return @lsblk_exists unless @lsblk_exists.nil?
124
-
125
- output = Facter::Core::Execution.execute('which lsblk', logger: log)
126
-
127
- @lsblk_exists = !output.empty?
128
- end
129
-
130
- def execute_and_extract_blkid_info
131
- stdout = Facter::Core::Execution.execute('blkid', logger: log)
132
- output_hash = Hash[*stdout.split(/^([^:]+):/)[1..-1]]
133
- output_hash.each do |key, value|
134
- output_hash[key] = Hash[*value.delete('"').chomp.rstrip.split(/ ([^= ]+)=/)[1..-1]]
135
- end
136
- end
137
-
138
- def browse_subdirectories(path)
139
- dirs = Dir[File.join(path, '**', '*')].select { |p| File.directory? p }
140
- dirs.select { |subdir| subdir.split('/').last.include?(path.split('/').last) }.reject(&:nil?)
141
- end
142
146
  end
143
147
  end
144
148
  end