From 6689c96cdfaa148037dc5df2baa058b09a075ec7 Mon Sep 17 00:00:00 2001 From: Moshe Levi Date: Tue, 13 Sep 2016 09:30:59 +0300 Subject: [PATCH] pci: remove pci device from claims and allocations when freeing it In drop_move_claim we call free pci device when we need to drop a specific device from the src/dest node. This is done by calling pci manager free_device. The current code just update the device status to available in database but doesn't remove it from the pci manager claims and allocations lists. This patch adds the removal as well. Closes-Bug: #1622854 Change-Id: If1cd6f3a635759cd55d116a34ca164630c61e085 --- nova/pci/manager.py | 21 +++++++++++++++++++-- nova/tests/unit/pci/test_manager.py | 22 +++++++++++----------- 2 files changed, 30 insertions(+), 13 deletions(-) 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):