Recognize interface aliases in network facts, and add IP facts

This commit is contained in:
Ahmad Khayyat 2012-08-11 02:40:54 -04:00
parent 573616780b
commit 42fedcc810

157
setup
View file

@ -433,93 +433,88 @@ class LinuxNetwork(Network):
Network.__init__(self) Network.__init__(self)
def populate(self): def populate(self):
self.facts['interfaces'] = self.get_interfaces() interfaces, ips = self.parse_ip_addr()
self.get_interface_facts()
self.get_ipv4_facts() self.facts['interfaces'] = interfaces.keys()
self.get_ipv6_facts() for iface in interfaces:
self.facts[iface] = interfaces[iface]
self.facts['all_ipv4_addresses'] = ips['all_ipv4']
self.facts['all_ipv6_addresses'] = ips['all_ipv6']
self.facts['ipv4_address'] = ips['ipv4']
self.facts['ipv6_address'] = ips['ipv6']
return self.facts return self.facts
# get list of interfaces
def get_interfaces(self):
names = []
data = get_file_content('/proc/net/dev')
# Format of /proc/net/dev is:
# Inter-| Receive ...
# face |bytes ...
# lo: 595059
for line in data.split('\n'):
if ':' in line:
names.append(line.split(':')[0].strip())
return names
def get_iface_hwaddr(self, iface): def parse_ip_addr(self):
data = get_file_content('/sys/class/net/%s/address' % iface) interfaces = {}
if data is None: ips = {'all_ipv4': [], 'all_ipv6': [], 'ipv4': None, 'ipv6': None}
return 'unknown'
else:
return data.strip()
def get_interface_facts(self): output = subprocess.Popen(['ip','addr'], stdout=subprocess.PIPE).communicate()[0]
for iface in self.facts['interfaces']: for line in output.split('\n'):
if iface not in self.facts: if line:
self.facts[iface] = {} words = line.split()
self.facts[iface] = { 'macaddress': self.get_iface_hwaddr(iface) } if not line.startswith(' '):
if os.path.exists('/sys/class/net/%s/mtu' % iface): device = words[1][0:-1]
mtu = get_file_content('/sys/class/net/%s/mtu' % iface) mtu = words[4]
self.facts[iface]['mtu'] = mtu.strip() elif words[0].startswith('link/'):
iface_type = words[0].split('/')[1]
if iface_type == 'void':
macaddress = 'unknown'
else:
macaddress = words[1]
elif words[0] == 'inet':
address, netmask_length = words[1].split('/')
address_bin = struct.unpack('!L', socket.inet_aton(address))[0]
def get_ipv4_facts(self): netmask_bin = (1<<32) - (1<<32>>int(netmask_length))
for iface in self.facts['interfaces']: netmask = socket.inet_ntoa(struct.pack('!L', netmask_bin))
# This is lame, but there doesn't appear to be a good way
# to get all addresses for both IPv4 and IPv6.
cmd = subprocess.Popen("env LANG=\"\" /sbin/ifconfig %s" % iface, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = cmd.communicate()
for line in out.split('\n'):
is_ipv4 = False
data = line.split()
if 'inet addr' in line:
if 'ipv4' not in self.facts[iface]:
self.facts[iface]['ipv4'] = {}
is_ipv4 = True
self.facts[iface]['ipv4'] = { 'address': data[1].split(':')[1],
'netmask': data[-1].split(':')[1] }
# Slightly different output in net-tools-1.60-134.20120127git
# Looks like
# inet 192.168.1.2 netmask 255.255.255.0 broadcast 192.168.1.255
elif 'inet ' in line:
is_ipv4 = True
if 'ipv4' not in self.facts[iface]:
self.facts[iface]['ipv4'] = {}
self.facts[iface]['ipv4'] = { 'address': data[1],
'netmask': data[3] }
if is_ipv4:
ip = struct.unpack("!L", socket.inet_aton(self.facts[iface]['ipv4']['address']))[0]
mask = struct.unpack("!L", socket.inet_aton(self.facts[iface]['ipv4']['netmask']))[0]
self.facts[iface]['ipv4']['network'] = socket.inet_ntoa(struct.pack("!L", ip & mask))
def get_ipv6_facts(self): network = socket.inet_ntoa(struct.pack('!L', address_bin & netmask_bin))
if not socket.has_ipv6:
return iface = words[-1]
data = get_file_content('/proc/net/if_inet6') # If an interface has multiple IPv4 addresses, make up an
if data is None: # interface name for each address
return if iface in interfaces:
for line in data.split('\n'): i = 0
l = line.split() while '{0}:{1}'.format(iface, i) in interfaces:
iface = l[5] i += 1
if 'ipv6' not in self.facts[iface]: iface = '{0}:{1}'.format(iface, i)
self.facts[iface]['ipv6'] = []
scope = l[3] interfaces[iface] = {}
if Network.IPV6_SCOPE.has_key(l[3]): interfaces[iface]['macaddress'] = macaddress
scope = Network.IPV6_SCOPE[l[3]] interfaces[iface]['mtu'] = mtu
prefix = int(l[2], 16) interfaces[iface]['device'] = device
str_addr = ':'.join( [ l[0][i:i+4] for i in range(0, len(l[0]), 4) ] ) interfaces[iface]['ipv4'] = {'address': address,
# Normalize ipv6 address from format in /proc/net/if_inet6 'netmask': netmask,
addr = socket.inet_ntop(socket.AF_INET6, 'network': network}
socket.inet_pton(socket.AF_INET6, str_addr))
self.facts[iface]['ipv6'].append( { 'address': addr, ips['all_ipv4'].append(address)
'prefix': prefix, if not ips['ipv4'] or ips['ipv4'].startswith('127'):
'scope': scope } ) ips['ipv4'] = address
elif words[0] == 'inet6':
address, prefix = words[1].split('/')
scope = words[3]
iface = device
if iface not in interfaces:
interfaces[iface] = {}
interfaces[iface]['macaddress'] = macaddress
interfaces[iface]['mtu'] = mtu
interfaces[iface]['device'] = device
if 'ipv6' not in interfaces[iface]:
interfaces[iface]['ipv6'] = []
interfaces[iface]['ipv6'].append( {
'address': address,
'prefix': prefix,
'scope': scope} )
ips['all_ipv6'].append(address)
if not ips['ipv6'] or ips['ipv6'] == '::1':
ips['ipv6'] = address
return interfaces, ips
class Virtual(Facts): class Virtual(Facts):
""" """