diff --git a/nova/pci/manager.py b/nova/pci/manager.py index 1c9790aa9e67..499117edc867 100644 --- a/nova/pci/manager.py +++ b/nova/pci/manager.py @@ -261,10 +261,27 @@ class PciDevTracker(object): is allocated to """ for pci_dev in self.pci_devs: - # find the matching pci device in the pci resource tracker - # pci device. Once found one free it. + # Find the matching pci device in the pci resource tracker. + # Once found, free it. if dev.id == pci_dev.id and dev.instance_uuid == instance['uuid']: + self._remove_device_from_pci_mapping( + instance['uuid'], pci_dev, self.allocations) + self._remove_device_from_pci_mapping( + instance['uuid'], pci_dev, self.claims) self._free_device(pci_dev) + break + + def _remove_device_from_pci_mapping( + self, instance_uuid, pci_device, pci_mapping): + """Remove a PCI device from allocations or claims. + + If there are no more PCI devices, pop the uuid. + """ + pci_devices = pci_mapping.get(instance_uuid, []) + if pci_device in pci_devices: + pci_devices.remove(pci_device) + if len(pci_devices) == 0: + pci_mapping.pop(instance_uuid, None) def _free_device(self, dev, instance=None): freed_devs = dev.free(instance) diff --git a/nova/tests/unit/pci/test_manager.py b/nova/tests/unit/pci/test_manager.py index ecfecfe7f365..96b6fe623c0e 100644 --- a/nova/tests/unit/pci/test_manager.py +++ b/nova/tests/unit/pci/test_manager.py @@ -474,24 +474,24 @@ class PciDevTrackerTestCase(test.NoDBTestCase): def test_free_device(self): pci_requests_obj = self._create_pci_requests_object( - [{'count': 2, 'spec': [{'vendor_id': 'v'}]}]) + [{'count': 1, 'spec': [{'vendor_id': 'v'}]}]) self.tracker.claim_instance(mock.sentinel.context, pci_requests_obj, None) self.tracker.update_pci_for_instance(None, self.inst, sign=1) free_pci_device_ids = ( [dev.id for dev in self.tracker.pci_stats.get_free_devs()]) - self.assertEqual(1, len(free_pci_device_ids)) + self.assertEqual(2, len(free_pci_device_ids)) allocated_devs = manager.get_instance_pci_devs(self.inst) - pci_device_a = allocated_devs[0] - pci_device_b = copy.deepcopy(allocated_devs[1]) - self.assertNotIn(pci_device_a.id, free_pci_device_ids) - self.assertNotIn(pci_device_b.id, free_pci_device_ids) - for pci_device in (pci_device_a, pci_device_b): - self.tracker.free_device(pci_device, self.inst) - free_pci_device_ids = ( - [dev.id for dev in self.tracker.pci_stats.get_free_devs()]) - self.assertIn(pci_device.id, free_pci_device_ids) + pci_device = allocated_devs[0] + self.assertNotIn(pci_device.id, free_pci_device_ids) + instance_uuid = self.inst['uuid'] + self.assertIn(pci_device, self.tracker.allocations[instance_uuid]) + self.tracker.free_device(pci_device, self.inst) + free_pci_device_ids = ( + [dev.id for dev in self.tracker.pci_stats.get_free_devs()]) self.assertEqual(3, len(free_pci_device_ids)) + self.assertIn(pci_device.id, free_pci_device_ids) + self.assertIsNone(self.tracker.allocations.get(instance_uuid)) class PciGetInstanceDevs(test.NoDBTestCase):