Skip to content

Commit

Permalink
Ensure MAC addresses characters are in the same case
Browse files Browse the repository at this point in the history
Currently neutron can report ports to have MAC addresses
in upper case when they're created like that. In the meanwhile
libvirt configuration file always stores MAC in lower case
which leads to KeyError while trying to retrieve migrate_vif.

Closes-Bug: #1945646
Change-Id: Ie3129ee395427337e9abcef2f938012608f643e1
(cherry picked from commit 6a15169)
(cherry picked from commit 63a6388)
  • Loading branch information
Dmitriy Rabotyagov committed Dec 10, 2021
1 parent 1edabab commit 6c3d5de
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 3 deletions.
43 changes: 42 additions & 1 deletion nova/tests/unit/virt/libvirt/test_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,48 @@ def test_update_vif_xml_no_matching_vif(self):
doc = etree.fromstring(original_xml)
ex = self.assertRaises(KeyError, migration._update_vif_xml,
doc, data, get_vif_config)
self.assertIn("CA:FE:DE:AD:BE:EF", str(ex))
self.assertIn("ca:fe:de:ad:be:ef", str(ex))

def test_update_vif_xml_lower_case_mac(self):
"""Tests that the vif in the migrate data is not found in the existing
guest interfaces.
"""
conf = vconfig.LibvirtConfigGuestInterface()
conf.net_type = "bridge"
conf.source_dev = "qbra188171c-ea"
conf.target_dev = "tapa188171c-ea"
conf.mac_addr = "DE:AD:BE:EF:CA:FE"
conf.model = "virtio"
original_xml = """<domain>
<uuid>3de6550a-8596-4937-8046-9d862036bca5</uuid>
<devices>
<interface type="bridge">
<mac address="de:ad:be:ef:ca:fe"/>
<model type="virtio"/>
<source bridge="qbra188171c-ea"/>
<target dev="tapa188171c-ea"/>
<virtualport type="openvswitch">
<parameters interfaceid="%s"/>
</virtualport>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04'
function='0x0'/>
</interface>
</devices>
</domain>""" % uuids.ovs
expected_xml = """<domain>
<uuid>3de6550a-8596-4937-8046-9d862036bca5</uuid>
<devices>
<interface type="bridge">
<mac address="DE:AD:BE:EF:CA:FE"/>
<model type="virtio"/>
<source bridge="qbra188171c-ea"/>
<target dev="tapa188171c-ea"/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04'
function='0x0'/>
</interface>
</devices>
</domain>"""
self._test_update_vif_xml(conf, original_xml, expected_xml)


class MigrationMonitorTestCase(test.NoDBTestCase):
Expand Down
11 changes: 9 additions & 2 deletions nova/virt/libvirt/migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,14 +339,21 @@ def _update_vif_xml(xml_doc, migrate_data, get_vif_config):
instance_uuid = xml_doc.findtext('uuid')
parser = etree.XMLParser(remove_blank_text=True)
interface_nodes = xml_doc.findall('./devices/interface')
migrate_vif_by_mac = {vif.source_vif['address']: vif
# MAC address stored for port in neutron DB and in domain XML
# might be in different cases, so to harmonize that
# we convert MAC to lower case for dict key.
migrate_vif_by_mac = {vif.source_vif['address'].lower(): vif
for vif in migrate_data.vifs}
for interface_dev in interface_nodes:
mac = interface_dev.find('mac')
mac = mac if mac is not None else {}
mac_addr = mac.get('address')
if mac_addr:
migrate_vif = migrate_vif_by_mac[mac_addr]
# MAC address stored in libvirt should always be normalized
# and stored in lower case. But just to be extra safe here
# we still normalize MAC retrieved from XML to be absolutely
# sure it will be the same with the Neutron provided one.
migrate_vif = migrate_vif_by_mac[mac_addr.lower()]
vif = migrate_vif.get_dest_vif()
# get_vif_config is a partial function of
# nova.virt.libvirt.vif.LibvirtGenericVIFDriver.get_config
Expand Down

0 comments on commit 6c3d5de

Please sign in to comment.