diff --git a/plugins/modules/virt.py b/plugins/modules/virt.py index 5a43aeb..9e68cff 100644 --- a/plugins/modules/virt.py +++ b/plugins/modules/virt.py @@ -620,24 +620,36 @@ def handle_define(module, v): # if fuzzy_match is False, we only match on aliases fuzzy_match = flag == 'ADD_MAC_ADDRESSES_FUZZY' + # this set of nodes gets manipulated (elements removed), so be + # careful if using using `existing_xml` later existing_devices = existing_xml.find('./devices') - for interface in incoming_xml.findall('./devices/interface'): - mac = interface.find('mac') - if mac is None: - # incoming interface is missing MAC address, so we will add it - # from the existing domain if it has a matching interface - matched_interface = _match_interface(interface, - existing_devices.findall('./interface'), - fuzzy_match) - - if matched_interface is not None: - # Remove matched_interface from possible candidates to prevent duplicate - # MAC address assignments (which is possible when fuzzy_match = True) - existing_devices.remove(matched_interface) - - etree.SubElement(interface, 'mac', { - 'address': matched_interface.find('./mac').get('address'), - }) + + # iterate user-defined elements + for mac in incoming_xml.findall('./devices/interface/mac'): + # remove from existing_devices any interfaces containing a + # MAC contained in incoming_xml, so we don't later match + # against one of these interfaces if a user provides MAC + # addresses for some but not all interfaces + for existing_interface in \ + existing_devices.xpath('./interface[mac[@address="%s"]]' % mac.get('address')): + existing_devices.remove(existing_interface) + + # iterate user-defined interfaces _without_ a mac element + for interface in incoming_xml.xpath('./devices/interface[not(mac)]'): + # incoming interface is missing MAC address, so we will add it + # from the existing domain if it has a matching interface + matched_interface = _match_interface(interface, + existing_devices.findall('./interface'), + fuzzy_match) + + if matched_interface is not None: + # Remove matched_interface from possible candidates to prevent duplicate + # MAC address assignments (which is possible when fuzzy_match = True) + existing_devices.remove(matched_interface) + + etree.SubElement(interface, 'mac', { + 'address': matched_interface.find('./mac').get('address'), + }) try: domain_xml = etree.tostring(incoming_xml).decode()