291
291
return 'unknown-%d' % iftype
294
def annotate_with_driver_information(interfaces):
294
def _parse_proc_net_bonding(file):
295
"""Parse the given file, which must be a path to a file in the format
296
that is used for file in `/proc/net/bonding/<interface>`.
298
Returns a dictionary mapping each interface name found in the file to
299
its original MAC address.
303
with open(file) as f:
304
for line in f.readlines():
306
slave_iface = line.split("Slave Interface: ")
307
if len(slave_iface) == 2:
308
current_iface = slave_iface[1]
309
hw_addr = line.split("Permanent HW addr: ")
310
if len(hw_addr) == 2:
311
interfaces[current_iface] = hw_addr[1]
315
def annotate_with_proc_net_bonding_original_macs(
316
interfaces, proc_net="/proc/net"):
317
"""Repairs the MAC addresses of bond members in the specified structure.
319
Given the specified interfaces structure, uses the data in
320
`/proc/net/bonding/*` to determine if any of the interfaces
321
in the structure are bond members. If so, modifies their MAC address,
322
setting it back to the original hardware MAC. (When an interface is added
323
to a bond, its MAC address is set to the bond MAC, and subsequently
324
reported in commands like "ip addr".)
326
proc_net_bonding = os.path.join(proc_net, "bonding")
327
if os.path.isdir(proc_net_bonding):
328
bonds = os.listdir(proc_net_bonding)
330
parent_macs = _parse_proc_net_bonding(
331
os.path.join(proc_net_bonding, bond))
332
for interface in parent_macs:
333
if interface in interfaces:
334
interfaces[interface]['mac'] = parent_macs[interface]
338
def annotate_with_driver_information(
339
interfaces, sys_class_net="/sys/class/net", proc_net="/proc/net"):
295
340
"""Determines driver information for each of the given interfaces.
297
342
Annotates the given dictionary to update it with driver information
298
343
(if found) for each interface.
345
Deletes bond interfaces if they are not configured.
347
:param interfaces: interfaces dictionary from `parse_ip_addr()`.
348
:param proc_net: path to /proc/net
349
:param sys_class_net: path to /sys/class/net
351
interfaces = annotate_with_proc_net_bonding_original_macs(
352
interfaces, proc_net=proc_net)
353
bogus_interfaces = []
300
354
for name in interfaces:
301
355
iface = interfaces[name]
302
iftype = get_interface_type(name)
356
iftype = get_interface_type(
357
name, sys_class_net=sys_class_net, proc_net=proc_net)
303
358
interfaces[name]['type'] = iftype
304
359
if iftype == 'ethernet.bond':
305
iface['bonded_interfaces'] = get_bonded_interfaces(name)
360
bond_parents = get_bonded_interfaces(
361
name, sys_class_net=sys_class_net)
362
if len(bond_parents) > 0:
363
iface['bonded_interfaces'] = bond_parents
365
# If we found a bond interface with no parents, just pretend
366
# it doesn't exist. The MAAS model assumes bonds must have
367
# backing interfaces.
368
bogus_interfaces.append(name)
306
369
elif iftype == 'ethernet.vlan':
307
370
iface['vid'] = get_vid_from_ifname(name)
308
371
elif iftype == 'ethernet.bridge':
309
iface['bridged_interfaces'] = get_bridged_interfaces(name)
372
iface['bridged_interfaces'] = get_bridged_interfaces(
373
name, sys_class_net=sys_class_net)
374
for name in bogus_interfaces:
310
376
return interfaces