Bug #4498
ipaddress* facts do not include secondary IPs
| Status: | Duplicate | Start date: | 08/08/2010 | |
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | - | % Done: | 0% | |
| Category: | library | |||
| Target version: | - | |||
| Keywords: | Affected Facter version: | |||
| Branch: | ||||
Description
I can add as many IP addresses to an interface (at least on Linux), using iproute2. However, since facter uses the horrific ifconfig command to scan for and obtain interface information, it does not see those additional interfaces (ifconfig needed the interface alias hack).
I am going to start working on a patch to swap ifconfig for iproute2 on Linux.
Related issues
History
#1
Updated by Paul Nasrat almost 3 years ago
If you are doing this please post to list for design discussion as early as possible.
Note my preferred method to move to would be probably to read procfs/sysfs to enumerate the devices and support iproute2 and falling back to ifconfig.
I also want to completely rework how they are represented so we can provide richer objects to puppet for 2.0.
#2
Updated by Paul Nasrat almost 3 years ago
- Target version set to 1.6.0
#3
Updated by Paul Nasrat almost 3 years ago
- Status changed from Unreviewed to Duplicate
- Target version changed from 1.6.0 to 14
Duplicate of bug 1346
#4
Updated by martin krafft almost 3 years ago
- Assignee deleted (
martin krafft)
Here is my patch as a basis:
index 5ad9658..7682a04 100644
--- a/files/util/ip.rb
+++ b/files/util/ip.rb
@@ -5,9 +5,9 @@ module Facter::Util::IP
# a given platform or set of platforms.
REGEX_MAP = {
:linux => {
- :ipaddress => /inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
- :macaddress => /(?:ether|HWaddr)\s+(\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2})/,
- :netmask => /Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
+ :ipaddress => /\s+inet ((?:\d+\.){3}\d+)\/\d+(?: brd (?:\d+\.){3}\d+)? scope global/,
+ :macaddress => /\s+link\/\S+ ((?:[0-9a-f]{2}:){5}:[0-9a-f]{2}) brd (?:[0-9a-f]{2}:){5}:[0-9a-f]{2}/,
+ :netmask => /\s+inet (?:(?:\d+\.){3}\d+)\/(\d+)(?: brd (?:\d+\.){3}\d+)? scope global/
},
:bsd => {
:aliases => [:openbsd, :netbsd, :freebsd, :darwin],
@@ -32,6 +32,11 @@ module Facter::Util::IP
kernels_to_convert.include?(kernel)
end
+ def self.convert_from_prefixlen?(kernel)
+ kernels_to_convert = [:linux]
+ kernels_to_convert.include?(kernel)
+ end
+
def self.supported_platforms
REGEX_MAP.inject([]) do |result, tmp|
key, map = tmp
@@ -56,7 +61,9 @@ module Facter::Util::IP
def self.get_all_interface_output
case Facter.value(:kernel)
- when 'Linux', 'OpenBSD', 'NetBSD', 'FreeBSD', 'Darwin'
+ when 'Linux'
+ output = %x{/bin/ip addr list}.gsub(/^\d+:\s+/, '')
+ when 'OpenBSD', 'NetBSD', 'FreeBSD', 'Darwin'
output = %x{/sbin/ifconfig -a}
when 'SunOS'
output = %x{/usr/sbin/ifconfig -a}
@@ -67,7 +74,9 @@ module Facter::Util::IP
def self.get_single_interface_output(interface)
output = ""
case Facter.value(:kernel)
- when 'Linux', 'OpenBSD', 'NetBSD', 'FreeBSD', 'Darwin'
+ when 'Linux'
+ output = %x{/bin/ip addr list dev #{interface}}.gsub(/^\d+:\s+/, '')
+ when 'OpenBSD', 'NetBSD', 'FreeBSD', 'Darwin'
output = %x{/sbin/ifconfig #{interface}}
when 'SunOS'
output = %x{/usr/sbin/ifconfig #{interface}}
@@ -130,8 +139,17 @@ module Facter::Util::IP
output_int.each_line do |s|
if s =~ regex
value = $1
- if label == 'netmask' && convert_from_hex?(kernel)
- value = value.scan(/../).collect do |byte| byte.to_i(16) end.join('.')
+ if label == 'netmask'
+ convert_from_hex = convert_from_hex?(kernel)
+ if convert_from_prefixlen?(kernel)
+ hostmaxlen = 32-value.to_i
+ value = ((0xffffffff >> hostmaxlen) << hostmaxlen).to_s(16)
+ convert_from_hex = true
+ end
+
+ if convert_from_hex
+ value = value.scan(/../).collect do |byte| byte.to_i(16) end.join('.')
+ end
end
tmp1.push(value)
end
And then the one that actually implements multiple returns with a compatibility interface:
diff --git a/files/interfaces.rb b/files/interfaces.rb
index 1239215..67e6ead 100644
--- a/files/interfaces.rb
+++ b/files/interfaces.rb
@@ -25,7 +25,7 @@ Facter::Util::IP.get_interfaces.each do |interface|
%w{ipaddress macaddress netmask}.each do |label|
Facter.add(label + "_" + Facter::Util::IP.alphafy(interface)) do
setcode do
- Facter::Util::IP.get_interface_value(interface, label)
+ Facter::Util::IP.get_interface_values(interface, label).join(',')
end
end
end
diff --git a/files/network.rb b/files/network.rb
index df53ce4..02ee94c 100644
--- a/files/network.rb
+++ b/files/network.rb
@@ -3,7 +3,7 @@ require 'facter/util/ip'
Facter::Util::IP.get_interfaces.each do |interface|
Facter.add("network_" + Facter::Util::IP.alphafy(interface)) do
setcode do
- Facter::Util::IP.get_network_value(interface)
+ Facter::Util::IP.get_network_values(interface).join(',')
end
end
end
diff --git a/files/util/ip.rb b/files/util/ip.rb
index 7682a04..7b29afb 100644
--- a/files/util/ip.rb
+++ b/files/util/ip.rb
@@ -111,7 +111,7 @@ module Facter::Util::IP
end
- def self.get_interface_value(interface, label)
+ def self.get_interface_values(interface, label)
tmp1 = []
kernel = Facter.value(:kernel).downcase.to_sym
@@ -157,21 +157,35 @@ module Facter::Util::IP
end
if tmp1
- value = tmp1.shift
+ value = tmp1
end
end
end
+ def self.get_interface_value(interface, label)
+ # compatibility interface
+ self.get_interface_values(interface, label).shift
+ end
- def self.get_network_value(interface)
+ def self.get_network_values(interface)
require 'ipaddr'
- ipaddress = get_interface_value(interface, "ipaddress")
- netmask = get_interface_value(interface, "netmask")
-
- if ipaddress && netmask
- ip = IPAddr.new(ipaddress, Socket::AF_INET)
- subnet = IPAddr.new(netmask, Socket::AF_INET)
- network = ip.mask(subnet.to_s).to_s
+ ipaddresses = get_interface_values(interface, "ipaddress")
+ netmasks = get_interface_values(interface, "netmask")
+ ret = []
+ ipaddresses.zip(netmasks) { |pair|
+ if pair[0] && pair[1]
+ ip = IPAddr.new(pair[0], Socket::AF_INET)
+ subnet = IPAddr.new(pair[1], Socket::AF_INET)
+ network = ip.mask(subnet.to_s).to_s
+ ret.push(network)
+ end
+ }
+ if ret
+ value = ret
end
end
+ def self.get_network_value(interface)
+ # compatibility interface
+ self.get_network_values(interface).shift
+ end
end
Of course, having ifconfig would be good for fallback.
One issue not addressed in the above are bonded interfaces. Those show up with the @ sign in the iface name. This actually causes problems with now, e.g.:
4: sixxs@NONE:mtu 1480 qdisc noqueue state UNKNOWN link/sit 0.0.0.0 peer 213.144.148.74 inet6 2001:1620:f08::1/128 scope global valid_lft forever preferred_lft forever
#5
Updated by martin krafft almost 3 years ago
- Status changed from Duplicate to Re-opened
Please don’t delete, I’ll mark it a duplicate…
#6
Updated by martin krafft almost 3 years ago
- Status changed from Re-opened to Code Insufficient
#7
Updated by James Turnbull almost 2 years ago
- Category set to library
#8
Updated by Ken Barber over 1 year ago
- Target version changed from 14 to 186
#9
Updated by Daniel Pittman over 1 year ago
- Target version deleted (
186)
#10
Updated by Andrew Parker 11 months ago
- Status changed from Code Insufficient to Duplicate
This is being taken care of in #1346.