Adds IPv6 support for interface_for_ip function

Proper interface matching when an IPv6 address is provided.

If Facter version used is < 3 then it adds the netmask6 facts as custom facts.

Fix bugs https://bugzilla.redhat.com/show_bug.cgi?id=1280523

Change-Id: Ide26ca1740dc12ea5f47a28f4cecacd6ef0b18f9
This commit is contained in:
Gilles Dubreuil 2015-11-16 16:55:28 +11:00
parent b94e93d8c8
commit 11a0619a29
2 changed files with 66 additions and 13 deletions

View File

@ -0,0 +1,47 @@
require 'ipaddr'
def netmask6(value)
if value
ip = IPAddr.new('::0').mask(value)
ip.inspect.split('/')[1].gsub('>', '')
end
end
if Facter.value('facterversion')[0].to_i < 3
Facter::Util::IP.get_interfaces.each do |interface|
Facter.add('netmask6_' + Facter::Util::IP.alphafy(interface)) do
setcode do
tmp = []
regex = %r{inet6\s+.*\s+(?:prefixlen)\s+(\d+)}x
output_int = Facter::Util::IP.get_output_for_interface_and_label(interface, 'netmask6')
output_int.each_line do |line|
prefixlen = nil
matches = line.match(regex)
prefixlen = matches[1] if matches
if prefixlen
value = netmask6(prefixlen)
tmp.push(value)
end
end
tmp.shift if tmp
end
end
end
Facter.add('netmask6') do
setcode do
prefixlen = nil
regex = %r{#{Facter.value(:ipaddress6)}.*?(?:prefixlen)\s*(\d+)}x
String(Facter::Util::IP.exec_ifconfig(['2>/dev/null'])).split(/\n/).collect do |line|
matches = line.match(regex)
prefixlen = matches[1] if matches
end
netmask6(prefixlen) if prefixlen
end
end
end

View File

@ -8,25 +8,31 @@ module Puppet::Parser::Functions
newfunction(:interface_for_ip, :type => :rvalue, :doc => "Find the bind IP address for the provided subnet.") do |arg|
if arg[0].class == String
begin
ip_to_find = arg[0]
ip1 = IPAddr.new(arg[0])
Dir.foreach('/sys/class/net/') do |interface|
next if interface == '.' or interface == '..'
next if interface == '.' || interface == '..'
iface_no_dash = interface.gsub('-', '_')
interface_ip = lookupvar("ipaddress_#{iface_no_dash}")
netmask = lookupvar("netmask_#{iface_no_dash}")
if not interface_ip.nil? then
ip1=IPAddr.new(interface_ip)
ip2=IPAddr.new(ip_to_find)
if ip1.mask(netmask) == ip2.mask(netmask) then
return interface
end
if ip1.ipv4?
ipaddress_name = "ipaddress_#{iface_no_dash}"
netmask_name = "netmask_#{iface_no_dash}"
else
ipaddress_name = "ipaddress6_#{iface_no_dash}"
netmask_name = "netmask6_#{iface_no_dash}"
end
interface_ip = lookupvar(ipaddress_name)
netmask = lookupvar(netmask_name)
unless interface_ip.nil? then
ip2 = IPAddr.new(interface_ip)
return interface if ip1.mask(netmask) == ip2.mask(netmask)
end
end
rescue JSON::ParserError
raise Puppet::ParseError, "Syntax error: #{arg[0]} is invalid"
rescue IPAddr::InvalidAddressError => e
raise Puppet::ParseError, "#{e}: #{arg[0]}"
end
else
raise Puppet::ParseError, "Syntax error: #{arg[0]} is not a String"
raise Puppet::ParseError, "Syntax error: #{arg[0]} must be a String"
end
return ''
end