facter 4.0.50 → 4.2.0
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.
- checksums.yaml +4 -4
- data/lib/docs/generate_cli.rb +7 -0
- data/lib/facter.rb +90 -56
- data/lib/facter/config.rb +2 -0
- data/lib/facter/custom_facts/core/aggregate.rb +9 -0
- data/lib/facter/custom_facts/core/execution/base.rb +7 -3
- data/lib/facter/custom_facts/core/execution/popen3.rb +13 -1
- data/lib/facter/custom_facts/core/execution/posix.rb +2 -2
- data/lib/facter/custom_facts/core/execution/windows.rb +1 -1
- data/lib/facter/custom_facts/core/resolvable.rb +11 -0
- data/lib/facter/custom_facts/util/collection.rb +5 -0
- data/lib/facter/custom_facts/util/directory_loader.rb +1 -1
- data/lib/facter/custom_facts/util/normalization.rb +7 -2
- data/lib/facter/custom_facts/util/resolution.rb +2 -0
- data/lib/facter/custom_facts/util/windows_root.rb +2 -1
- data/lib/facter/facts/aix/processors/cores.rb +16 -0
- data/lib/facter/facts/aix/processors/threads.rb +16 -0
- data/lib/facter/facts/amzn/lsbdistcodename.rb +16 -0
- data/lib/facter/facts/amzn/lsbdistdescription.rb +16 -0
- data/lib/facter/facts/amzn/lsbdistid.rb +16 -0
- data/lib/facter/facts/amzn/os/distro/codename.rb +24 -0
- data/lib/facter/facts/amzn/os/distro/description.rb +21 -0
- data/lib/facter/facts/amzn/os/distro/id.rb +21 -0
- data/lib/facter/facts/amzn/os/distro/release.rb +32 -0
- data/lib/facter/facts/freebsd/is_virtual.rb +1 -5
- data/lib/facter/facts/freebsd/virtual.rb +1 -2
- data/lib/facter/facts/linux/az_metadata.rb +23 -0
- data/lib/facter/facts/linux/cloud/provider.rb +20 -0
- data/lib/facter/facts/linux/dhcp_servers.rb +2 -2
- data/lib/facter/facts/linux/ec2_metadata.rb +1 -5
- data/lib/facter/facts/linux/ec2_userdata.rb +1 -5
- data/lib/facter/facts/linux/hypervisors/xen.rb +1 -4
- data/lib/facter/facts/linux/interfaces.rb +1 -1
- data/lib/facter/facts/linux/ipaddress6_interfaces.rb +1 -1
- data/lib/facter/facts/linux/ipaddress_interfaces.rb +1 -1
- data/lib/facter/facts/linux/is_virtual.rb +1 -5
- data/lib/facter/facts/linux/macaddress_interfaces.rb +1 -1
- data/lib/facter/facts/linux/mtu_interfaces.rb +1 -1
- data/lib/facter/facts/linux/netmask6_interfaces.rb +1 -1
- data/lib/facter/facts/linux/netmask_interfaces.rb +1 -1
- data/lib/facter/facts/linux/network6_interfaces.rb +1 -1
- data/lib/facter/facts/linux/network_interfaces.rb +1 -1
- data/lib/facter/facts/linux/networking/dhcp.rb +1 -1
- data/lib/facter/facts/linux/networking/domain.rb +1 -1
- data/lib/facter/facts/linux/networking/fqdn.rb +1 -1
- data/lib/facter/facts/linux/networking/hostname.rb +1 -1
- data/lib/facter/facts/linux/networking/interfaces.rb +1 -1
- data/lib/facter/facts/linux/networking/ip.rb +1 -1
- data/lib/facter/facts/linux/networking/ip6.rb +1 -1
- data/lib/facter/facts/linux/networking/mac.rb +1 -1
- data/lib/facter/facts/linux/networking/mtu.rb +1 -1
- data/lib/facter/facts/linux/networking/netmask.rb +1 -1
- data/lib/facter/facts/linux/networking/netmask6.rb +1 -1
- data/lib/facter/facts/linux/networking/network.rb +1 -1
- data/lib/facter/facts/linux/networking/network6.rb +1 -1
- data/lib/facter/facts/linux/networking/primary.rb +1 -1
- data/lib/facter/facts/linux/networking/scope6.rb +1 -1
- data/lib/facter/facts/linux/processors/cores.rb +16 -0
- data/lib/facter/facts/linux/processors/threads.rb +16 -0
- data/lib/facter/facts/linux/scope6_interfaces.rb +1 -1
- data/lib/facter/facts/linux/virtual.rb +1 -2
- data/lib/facter/facts/macosx/os/macosx/version.rb +15 -4
- data/lib/facter/facts/macosx/processors/cores.rb +16 -0
- data/lib/facter/facts/macosx/processors/threads.rb +16 -0
- data/lib/facter/facts/rhel/lsbdistcodename.rb +16 -0
- data/lib/facter/facts/rhel/lsbdistdescription.rb +16 -0
- data/lib/facter/facts/rhel/lsbdistid.rb +16 -0
- data/lib/facter/facts/rhel/os/distro/codename.rb +2 -4
- data/lib/facter/facts/rhel/os/distro/description.rb +2 -4
- data/lib/facter/facts/rhel/os/distro/id.rb +2 -4
- data/lib/facter/facts/rhel/os/distro/release.rb +13 -12
- data/lib/facter/facts/sles/lsbdistcodename.rb +16 -0
- data/lib/facter/facts/sles/lsbdistdescription.rb +16 -0
- data/lib/facter/facts/sles/lsbdistid.rb +16 -0
- data/lib/facter/facts/sles/os/distro/codename.rb +3 -4
- data/lib/facter/facts/sles/os/distro/description.rb +2 -5
- data/lib/facter/facts/sles/os/distro/id.rb +6 -5
- data/lib/facter/facts/sles/os/distro/release.rb +17 -12
- data/lib/facter/facts/solaris/hypervisors/ldom.rb +1 -1
- data/lib/facter/facts/solaris/hypervisors/zone.rb +1 -1
- data/lib/facter/facts/solaris/mountpoints.rb +1 -1
- data/lib/facter/facts/solaris/processors/cores.rb +16 -0
- data/lib/facter/facts/solaris/processors/threads.rb +16 -0
- data/lib/facter/facts/ubuntu/lsbdistrelease.rb +2 -2
- data/lib/facter/facts/windows/az_metadata.rb +23 -0
- data/lib/facter/facts/windows/cloud/provider.rb +21 -0
- data/lib/facter/facts/windows/ec2_metadata.rb +1 -1
- data/lib/facter/facts/windows/ec2_userdata.rb +1 -1
- data/lib/facter/facts/windows/gce.rb +1 -1
- data/lib/facter/facts/windows/hypervisors/hyperv.rb +1 -1
- data/lib/facter/facts/windows/hypervisors/kvm.rb +2 -1
- data/lib/facter/facts/windows/hypervisors/virtualbox.rb +2 -2
- data/lib/facter/facts/windows/hypervisors/vmware.rb +1 -1
- data/lib/facter/facts/windows/hypervisors/xen.rb +3 -1
- data/lib/facter/facts/windows/is_virtual.rb +15 -0
- data/lib/facter/facts/windows/{virtualization/is_virtual.rb → processors/cores.rb} +4 -4
- data/lib/facter/facts/windows/{virtualization/virtual.rb → processors/threads.rb} +4 -4
- data/lib/facter/facts/windows/virtual.rb +15 -0
- data/lib/facter/framework/cli/cli.rb +6 -8
- data/lib/facter/framework/config/config_reader.rb +2 -0
- data/lib/facter/framework/config/fact_groups.rb +25 -2
- data/lib/facter/framework/core/cache_manager.rb +7 -3
- data/lib/facter/framework/core/fact/external/external_fact_manager.rb +0 -1
- data/lib/facter/framework/core/fact/internal/internal_fact_manager.rb +41 -39
- data/lib/facter/framework/core/fact_filter.rb +5 -15
- data/lib/facter/framework/core/fact_loaders/external_fact_loader.rb +9 -6
- data/lib/facter/framework/core/fact_loaders/fact_loader.rb +39 -37
- data/lib/facter/framework/core/fact_manager.rb +84 -14
- data/lib/facter/framework/core/file_loader.rb +1 -1
- data/lib/facter/framework/core/options.rb +1 -2
- data/lib/facter/framework/core/options/config_file_options.rb +7 -0
- data/lib/facter/framework/core/options/option_store.rb +12 -6
- data/lib/facter/framework/formatters/formatter_helper.rb +3 -5
- data/lib/facter/framework/logging/logger.rb +4 -4
- data/lib/facter/framework/parsers/query_parser.rb +5 -12
- data/lib/facter/models/fact_collection.rb +48 -5
- data/lib/facter/models/resolved_fact.rb +2 -3
- data/lib/facter/models/searched_fact.rb +2 -3
- data/lib/facter/resolvers/aix/ffi/ffi_helper.rb +1 -1
- data/lib/facter/resolvers/aix/processors.rb +4 -0
- data/lib/facter/resolvers/az.rb +39 -0
- data/lib/facter/resolvers/base_resolver.rb +2 -2
- data/lib/facter/resolvers/dmi_decode.rb +0 -1
- data/lib/facter/resolvers/linux/hostname.rb +126 -0
- data/lib/facter/resolvers/linux/networking.rb +124 -0
- data/lib/facter/resolvers/macosx/mountpoints.rb +14 -1
- data/lib/facter/resolvers/macosx/processor.rb +16 -1
- data/lib/facter/resolvers/mountpoints.rb +16 -8
- data/lib/facter/resolvers/networking.rb +3 -2
- data/lib/facter/resolvers/partitions.rb +1 -1
- data/lib/facter/resolvers/processors_lscpu.rb +44 -0
- data/lib/facter/resolvers/redhat_release.rb +28 -12
- data/lib/facter/resolvers/ruby.rb +1 -1
- data/lib/facter/resolvers/selinux.rb +5 -7
- data/lib/facter/resolvers/solaris/ffi/functions.rb +1 -1
- data/lib/facter/resolvers/solaris/ffi/structs.rb +12 -0
- data/lib/facter/resolvers/solaris/mountpoints.rb +22 -16
- data/lib/facter/resolvers/solaris/networking.rb +20 -5
- data/lib/facter/resolvers/solaris/processors.rb +7 -0
- data/lib/facter/resolvers/solaris/zone.rb +0 -1
- data/lib/facter/resolvers/windows/ffi/identity_ffi.rb +5 -0
- data/lib/facter/resolvers/windows/identity.rb +1 -6
- data/lib/facter/resolvers/windows/processors.rb +41 -4
- data/lib/facter/resolvers/windows/uptime.rb +3 -22
- data/lib/facter/resolvers/windows/virtualization.rb +46 -44
- data/lib/facter/resolvers/xen.rb +6 -1
- data/lib/facter/templates/man.erb +13 -5
- data/lib/facter/util/facts/posix/virtual_detector.rb +74 -0
- data/lib/facter/util/facts/unit_converter.rb +2 -2
- data/lib/facter/util/linux/dhcp.rb +86 -0
- data/lib/facter/util/linux/if_inet6.rb +73 -0
- data/lib/facter/util/linux/routing_table.rb +60 -0
- data/lib/facter/util/linux/socket_parser.rb +114 -0
- data/lib/facter/util/resolvers/ffi/hostname.rb +70 -0
- data/lib/facter/util/resolvers/http.rb +7 -1
- data/lib/facter/util/resolvers/networking/primary_interface.rb +11 -5
- data/lib/facter/util/utils.rb +18 -1
- data/lib/facter/version.rb +1 -1
- metadata +63 -13
- data/lib/facter/facts/linux/cloud.rb +0 -15
- data/lib/facter/framework/core/fact_augmenter.rb +0 -37
- data/lib/facter/resolvers/cloud.rb +0 -39
- data/lib/facter/resolvers/networking_linux.rb +0 -296
- data/lib/facter/util/facts/virtual_detector.rb +0 -90
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Facter
|
|
4
|
+
module Util
|
|
5
|
+
module Facts
|
|
6
|
+
module Posix
|
|
7
|
+
module VirtualDetector
|
|
8
|
+
class << self
|
|
9
|
+
def platform
|
|
10
|
+
@@fact_value ||= check_docker_lxc || check_freebsd || check_gce || retrieve_from_virt_what
|
|
11
|
+
@@fact_value ||= check_vmware || check_open_vz || check_vserver || check_xen || check_other_facts
|
|
12
|
+
@@fact_value ||= check_lspci || 'physical'
|
|
13
|
+
|
|
14
|
+
@@fact_value
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def check_docker_lxc
|
|
20
|
+
Facter::Resolvers::Containers.resolve(:vm)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def check_gce
|
|
24
|
+
bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor)
|
|
25
|
+
'gce' if bios_vendor&.include?('Google')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def check_vmware
|
|
29
|
+
Facter::Resolvers::Vmware.resolve(:vm)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def retrieve_from_virt_what
|
|
33
|
+
Facter::Resolvers::VirtWhat.resolve(:vm)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def check_open_vz
|
|
37
|
+
Facter::Resolvers::OpenVz.resolve(:vm)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def check_vserver
|
|
41
|
+
Facter::Resolvers::VirtWhat.resolve(:vserver)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def check_xen
|
|
45
|
+
Facter::Resolvers::Xen.resolve(:vm)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def check_freebsd
|
|
49
|
+
return unless Object.const_defined?('Facter::Resolvers::Freebsd::Virtual')
|
|
50
|
+
|
|
51
|
+
Facter::Resolvers::Freebsd::Virtual.resolve(:vm)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def check_other_facts
|
|
55
|
+
bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor)
|
|
56
|
+
return 'kvm' if bios_vendor&.include?('Amazon EC2')
|
|
57
|
+
|
|
58
|
+
product_name = Facter::Resolvers::Linux::DmiBios.resolve(:product_name)
|
|
59
|
+
return unless product_name
|
|
60
|
+
|
|
61
|
+
Facter::Util::Facts::HYPERVISORS_HASH.each { |key, value| return value if product_name.include?(key) }
|
|
62
|
+
|
|
63
|
+
nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def check_lspci
|
|
67
|
+
Facter::Resolvers::Lspci.resolve(:vm)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -10,7 +10,7 @@ module Facter
|
|
|
10
10
|
|
|
11
11
|
value_in_bytes = value_in_bytes.to_i
|
|
12
12
|
|
|
13
|
-
(value_in_bytes / (1024.0 * 1024.0))
|
|
13
|
+
(value_in_bytes / (1024.0 * 1024.0))
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def hertz_to_human_readable(speed)
|
|
@@ -19,7 +19,7 @@ module Facter
|
|
|
19
19
|
|
|
20
20
|
validated_speed, metric_prefix = determine_metric_prefix(speed)
|
|
21
21
|
|
|
22
|
-
format('%<displayed_speed>.2f', displayed_speed: validated_speed).to_s + ' ' + metric_prefix + 'Hz'
|
|
22
|
+
format('%<displayed_speed>.2f', displayed_speed: validated_speed.round(2)).to_s + ' ' + metric_prefix + 'Hz'
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def bytes_to_human_readable(bytes)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Facter
|
|
4
|
+
module Util
|
|
5
|
+
module Linux
|
|
6
|
+
class Dhcp
|
|
7
|
+
class << self
|
|
8
|
+
DIRS = %w[/var/lib/dhclient/
|
|
9
|
+
/var/lib/dhcp/
|
|
10
|
+
/var/lib/dhcp3/
|
|
11
|
+
/var/lib/NetworkManager/
|
|
12
|
+
/var/db/].freeze
|
|
13
|
+
|
|
14
|
+
def dhcp(interface_name, interface_index, logger)
|
|
15
|
+
@log = logger
|
|
16
|
+
@log.debug("Get DHCP for interface #{interface_name}")
|
|
17
|
+
|
|
18
|
+
dhcp = search_systemd_netif_leases(interface_index, interface_name)
|
|
19
|
+
dhcp ||= search_dhclient_leases(interface_name)
|
|
20
|
+
dhcp ||= search_internal_leases(interface_name)
|
|
21
|
+
dhcp ||= search_with_dhcpcd_command(interface_name)
|
|
22
|
+
dhcp
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def search_systemd_netif_leases(index, interface_name)
|
|
28
|
+
return if index.nil?
|
|
29
|
+
|
|
30
|
+
@log.debug("Attempt to get DHCP for interface #{interface_name}, from systemd/netif/leases")
|
|
31
|
+
|
|
32
|
+
file_content = Facter::Util::FileHelper.safe_read("/run/systemd/netif/leases/#{index}", nil)
|
|
33
|
+
dhcp = file_content.match(/SERVER_ADDRESS=(.*)/) if file_content
|
|
34
|
+
dhcp[1] if dhcp
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def search_dhclient_leases(interface_name)
|
|
38
|
+
@log.debug("Attempt to get DHCP for interface #{interface_name}, from dhclient leases")
|
|
39
|
+
|
|
40
|
+
DIRS.each do |dir|
|
|
41
|
+
next unless File.readable?(dir)
|
|
42
|
+
|
|
43
|
+
lease_files = Dir.entries(dir).select { |file| file =~ /dhclient.*\.lease/ }
|
|
44
|
+
next if lease_files.empty?
|
|
45
|
+
|
|
46
|
+
lease_files.select do |file|
|
|
47
|
+
content = Facter::Util::FileHelper.safe_read("#{dir}#{file}", nil)
|
|
48
|
+
next unless content =~ /interface.*#{interface_name}/
|
|
49
|
+
|
|
50
|
+
dhcp = content.match(/dhcp-server-identifier ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/)
|
|
51
|
+
return dhcp[1] if dhcp
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def search_internal_leases(interface_name)
|
|
59
|
+
return unless File.readable?('/var/lib/NetworkManager/')
|
|
60
|
+
|
|
61
|
+
@log.debug("Attempt to get DHCP for interface #{interface_name}, from NetworkManager leases")
|
|
62
|
+
|
|
63
|
+
files = Dir.entries('/var/lib/NetworkManager/').reject { |dir| dir =~ /^\.+$/ }
|
|
64
|
+
lease_file = files.find { |file| file =~ /internal.*#{interface_name}\.lease/ }
|
|
65
|
+
return unless lease_file
|
|
66
|
+
|
|
67
|
+
dhcp = Facter::Util::FileHelper.safe_read("/var/lib/NetworkManager/#{lease_file}", nil)
|
|
68
|
+
|
|
69
|
+
return unless dhcp
|
|
70
|
+
|
|
71
|
+
dhcp = dhcp.match(/SERVER_ADDRESS=(.*)/)
|
|
72
|
+
dhcp[1] if dhcp
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def search_with_dhcpcd_command(interface_name)
|
|
76
|
+
@log.debug("Attempt to get DHCP for interface #{interface_name}, from dhcpcd command")
|
|
77
|
+
|
|
78
|
+
output = Facter::Core::Execution.execute("dhcpcd -U #{interface_name}", logger: @log)
|
|
79
|
+
dhcp = output.match(/dhcp_server_identifier='(.*)'/)
|
|
80
|
+
dhcp[1] if dhcp
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ipaddr'
|
|
4
|
+
|
|
5
|
+
module Facter
|
|
6
|
+
module Util
|
|
7
|
+
module Linux
|
|
8
|
+
class IfInet6
|
|
9
|
+
class << self
|
|
10
|
+
IFA_FLAGS = {
|
|
11
|
+
'temporary' => 0x01,
|
|
12
|
+
'noad' => 0x02,
|
|
13
|
+
'optimistic' => 0x04,
|
|
14
|
+
'dadfailed' => 0x08,
|
|
15
|
+
'homeaddress' => 0x10,
|
|
16
|
+
'deprecated' => 0x20,
|
|
17
|
+
'tentative' => 0x40,
|
|
18
|
+
'permanent' => 0x80
|
|
19
|
+
# /proc/net/if_inet6 only supports the old 8bit flags
|
|
20
|
+
# I have been unable to find a simple solution to accesses
|
|
21
|
+
# the full 32bit flags. netlink is all I can could find but
|
|
22
|
+
# that will likely be ugly
|
|
23
|
+
# 'managetempaddr' => 0x100,
|
|
24
|
+
# 'noprefixroute' => 0x200,
|
|
25
|
+
# 'mcautojoin' => 0x400,
|
|
26
|
+
# 'stableprivacy' => 0x800
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
def read_flags
|
|
30
|
+
return read_flags_from_proc if File.exist?('/proc/net/if_inet6')
|
|
31
|
+
|
|
32
|
+
{}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def read_flags_from_proc
|
|
38
|
+
flags = init_flags
|
|
39
|
+
Facter::Util::FileHelper.safe_read('/proc/net/if_inet6', nil).each_line do |line|
|
|
40
|
+
iface = line.split
|
|
41
|
+
next unless iface.size == 6
|
|
42
|
+
|
|
43
|
+
ip = parse_ip(iface[0])
|
|
44
|
+
flags[iface[5]][ip] = parse_ifa_flags(iface[4])
|
|
45
|
+
end
|
|
46
|
+
flags
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def init_flags
|
|
50
|
+
Hash.new { |h1, k1| h1[k1] = Hash.new { |h2, k2| h2[k2] = [] } }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def parse_ifa_flags(flag)
|
|
54
|
+
flag = flag.hex
|
|
55
|
+
flags = []
|
|
56
|
+
IFA_FLAGS.each_pair do |name, value|
|
|
57
|
+
next if (flag & value).zero?
|
|
58
|
+
|
|
59
|
+
flags << name
|
|
60
|
+
end
|
|
61
|
+
flags
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def parse_ip(ip)
|
|
65
|
+
# The ip address in if_net6 is a long string wit no colons
|
|
66
|
+
ip = ip.scan(/(\h{4})/).join(':')
|
|
67
|
+
IPAddr.new(ip).to_s
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Facter
|
|
4
|
+
module Util
|
|
5
|
+
module Linux
|
|
6
|
+
class RoutingTable
|
|
7
|
+
class << self
|
|
8
|
+
ROUTE_TYPES = %w[anycast
|
|
9
|
+
unicast
|
|
10
|
+
broadcast
|
|
11
|
+
local
|
|
12
|
+
nat
|
|
13
|
+
unreachable
|
|
14
|
+
prohibit
|
|
15
|
+
blackhole
|
|
16
|
+
throw].freeze
|
|
17
|
+
|
|
18
|
+
def read_routing_table(logger)
|
|
19
|
+
ipv4_output = Facter::Core::Execution.execute('ip route show', logger: logger)
|
|
20
|
+
ipv6_output = Facter::Core::Execution.execute('ip -6 route show', logger: logger)
|
|
21
|
+
routes4 = parse_routes(ipv4_output, true)
|
|
22
|
+
routes6 = parse_routes(ipv6_output, false)
|
|
23
|
+
[routes4, routes6]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def parse_routes(output, ipv4_type)
|
|
29
|
+
routes = []
|
|
30
|
+
output.each_line do |line|
|
|
31
|
+
parts = line.split(' ').compact
|
|
32
|
+
next if parts.include?('linkdown')
|
|
33
|
+
|
|
34
|
+
delete_invalid_route_type(parts)
|
|
35
|
+
next if !ipv4_type && !parts[0].include?(':')
|
|
36
|
+
|
|
37
|
+
route = construct_route(parts)
|
|
38
|
+
routes << route unless route[:ip].nil?
|
|
39
|
+
end
|
|
40
|
+
routes.uniq
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def delete_invalid_route_type(parts)
|
|
44
|
+
route_type = parts[0]
|
|
45
|
+
parts.delete_at(0) if ROUTE_TYPES.include?(route_type)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def construct_route(parts)
|
|
49
|
+
route = {}
|
|
50
|
+
dev_index = parts.find_index { |elem| elem == 'dev' }
|
|
51
|
+
src_index = parts.find_index { |elem| elem == 'src' }
|
|
52
|
+
route[:interface] = parts[dev_index + 1] if dev_index
|
|
53
|
+
route[:ip] = parts[src_index + 1] if src_index
|
|
54
|
+
route
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Facter
|
|
4
|
+
module Util
|
|
5
|
+
module Linux
|
|
6
|
+
class SocketParser
|
|
7
|
+
class << self
|
|
8
|
+
def retrieve_interfaces(logger)
|
|
9
|
+
require 'socket'
|
|
10
|
+
@interfaces = {}
|
|
11
|
+
@log = logger
|
|
12
|
+
Socket.getifaddrs.each do |ifaddr|
|
|
13
|
+
populate_interface_info(ifaddr)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
@interfaces
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def populate_interface_info(ifaddr)
|
|
22
|
+
interface_name = ifaddr.name
|
|
23
|
+
@interfaces[interface_name] = {} if @interfaces[interface_name].nil?
|
|
24
|
+
|
|
25
|
+
mac(ifaddr)
|
|
26
|
+
ip_info_of(ifaddr)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def mac(ifaddr)
|
|
30
|
+
return unless @interfaces[ifaddr.name][:mac].nil?
|
|
31
|
+
|
|
32
|
+
mac = search_for_mac(ifaddr)
|
|
33
|
+
@interfaces[ifaddr.name][:mac] = mac if mac
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def search_for_mac(ifaddr)
|
|
37
|
+
mac = mac_from_bonded_interface(ifaddr.name)
|
|
38
|
+
mac ||= mac_from(ifaddr)
|
|
39
|
+
mac if !mac.nil? && mac != '00:00:00:00:00:00' && mac =~ /^([0-9A-Fa-f]{2}[:-]){5,19}([0-9A-Fa-f]{2})$/
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def mac_from_bonded_interface(interface_name)
|
|
43
|
+
master = bond_master_of(interface_name)
|
|
44
|
+
return unless master
|
|
45
|
+
|
|
46
|
+
output = Facter::Util::FileHelper.safe_read("/proc/net/bonding/#{master}", nil)
|
|
47
|
+
return unless output
|
|
48
|
+
|
|
49
|
+
found_match = false
|
|
50
|
+
output.each_line do |line|
|
|
51
|
+
if line.strip == "Slave Interface: #{interface_name}"
|
|
52
|
+
found_match = true
|
|
53
|
+
elsif line.include? 'Slave Interface'
|
|
54
|
+
# if we reached the data block of another interface belonging to the bonded interface
|
|
55
|
+
found_match = false
|
|
56
|
+
end
|
|
57
|
+
return Regexp.last_match(1) if found_match && line =~ /Permanent HW addr: (\S*)/
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def bond_master_of(interface_name)
|
|
62
|
+
content = Facter::Core::Execution.execute("ip link show #{interface_name}", logger: @log)
|
|
63
|
+
content.match(/master (\S*) /)&.captures&.first
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def mac_from(ifaddr)
|
|
67
|
+
if Socket.const_defined? :PF_LINK
|
|
68
|
+
ifaddr.addr&.getnameinfo&.first # sometimes it returns localhost or ip
|
|
69
|
+
elsif Socket.const_defined? :PF_PACKET
|
|
70
|
+
return if ifaddr.addr.nil?
|
|
71
|
+
|
|
72
|
+
mac_from_sockaddr_of(ifaddr)
|
|
73
|
+
end
|
|
74
|
+
rescue StandardError => e
|
|
75
|
+
@log.debug("Could not read mac for interface #{ifaddr.name}, got #{e}")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def mac_from_sockaddr_of(ifaddr)
|
|
79
|
+
result = ifaddr.addr.inspect_sockaddr
|
|
80
|
+
result&.match(/hwaddr=([\h:]+)/)&.captures&.first
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def ip_info_of(ifaddr)
|
|
84
|
+
return if ifaddr.addr.nil? || ifaddr.netmask.nil?
|
|
85
|
+
|
|
86
|
+
add_binding(ifaddr.name, ifaddr)
|
|
87
|
+
rescue StandardError => e
|
|
88
|
+
@log.debug("Could not read binding data, got #{e}")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def add_binding(interface_name, ifaddr)
|
|
92
|
+
ip, netmask, binding_key = binding_data(ifaddr)
|
|
93
|
+
binding = Facter::Util::Resolvers::Networking.build_binding(ip, netmask)
|
|
94
|
+
return if binding.nil?
|
|
95
|
+
|
|
96
|
+
@interfaces[interface_name][binding_key] = [] if @interfaces[interface_name][binding_key].nil?
|
|
97
|
+
@interfaces[interface_name][binding_key] << binding
|
|
98
|
+
|
|
99
|
+
@log.debug("Adding to interface #{interface_name}, binding:\n#{binding}")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def binding_data(ifaddr)
|
|
103
|
+
# ipv6 ips are retrieved as <ip>%<interface_name>
|
|
104
|
+
ip = ifaddr.addr.ip_address.split('%').first
|
|
105
|
+
netmask = ifaddr.netmask.ip_address
|
|
106
|
+
binding_key = ifaddr.addr.ipv4? ? :bindings : :bindings6
|
|
107
|
+
|
|
108
|
+
[ip, netmask, binding_key]
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ffi'
|
|
4
|
+
|
|
5
|
+
module Facter
|
|
6
|
+
module Util
|
|
7
|
+
module Resolvers
|
|
8
|
+
module Ffi
|
|
9
|
+
class AddrInfo < ::FFI::Struct
|
|
10
|
+
layout :ai_flags, :int,
|
|
11
|
+
:ai_family, :int,
|
|
12
|
+
:ai_socketype, :int,
|
|
13
|
+
:ai_protocol, :int,
|
|
14
|
+
:ai_addrlen, :uint,
|
|
15
|
+
:ai_addr, :pointer,
|
|
16
|
+
:ai_canonname, :string,
|
|
17
|
+
:ai_next, :pointer
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
module Hostname
|
|
21
|
+
HOST_NAME_MAX = 64
|
|
22
|
+
|
|
23
|
+
extend ::FFI::Library
|
|
24
|
+
ffi_lib ::FFI::Library::LIBC
|
|
25
|
+
|
|
26
|
+
attach_function :getaddrinfo, %i[string string pointer pointer], :int
|
|
27
|
+
attach_function :gethostname, %i[pointer int], :int
|
|
28
|
+
attach_function :freeaddrinfo, [:pointer], :void
|
|
29
|
+
|
|
30
|
+
def self.getffihostname
|
|
31
|
+
raw_hostname = ::FFI::MemoryPointer.new(:char, HOST_NAME_MAX)
|
|
32
|
+
|
|
33
|
+
res = Hostname.gethostname(raw_hostname, HOST_NAME_MAX)
|
|
34
|
+
return unless res.zero?
|
|
35
|
+
|
|
36
|
+
raw_hostname.read_string
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.getffiaddrinfo(hostname) # rubocop:disable Metrics/AbcSize
|
|
40
|
+
ret = FFI::MemoryPointer.new(:pointer)
|
|
41
|
+
|
|
42
|
+
hints = Facter::Util::Resolvers::Ffi::AddrInfo.new
|
|
43
|
+
hints[:ai_family] = Socket::AF_UNSPEC
|
|
44
|
+
hints[:ai_socketype] = Socket::SOCK_STREAM
|
|
45
|
+
hints[:ai_flags] = Socket::AI_CANONNAME
|
|
46
|
+
|
|
47
|
+
res = Hostname.getaddrinfo(hostname, '', hints.to_ptr, ret)
|
|
48
|
+
log = Log.new(self)
|
|
49
|
+
log.debug("FFI Getaddrinfo finished with exit status: #{res}")
|
|
50
|
+
log.debug("FFI Getaddrinfo returned an AddrInfo struct at address: #{ret}")
|
|
51
|
+
return unless res.zero?
|
|
52
|
+
|
|
53
|
+
return if ret == FFI::Pointer::NULL || ret.read_pointer == FFI::Pointer::NULL
|
|
54
|
+
|
|
55
|
+
begin
|
|
56
|
+
addr = Facter::Util::Resolvers::Ffi::AddrInfo.new(ret.read_pointer)
|
|
57
|
+
name = addr[:ai_canonname]
|
|
58
|
+
log.debug("FFI AddrInfo struct has the fqdn: #{name}")
|
|
59
|
+
return if !name || hostname == name
|
|
60
|
+
|
|
61
|
+
name
|
|
62
|
+
ensure
|
|
63
|
+
Hostname.freeaddrinfo(ret.read_pointer)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|