|
21 | 21 |
|
22 | 22 | from nova.compute import vm_states
|
23 | 23 | from nova import context
|
| 24 | +from nova import exception |
24 | 25 | from nova import objects
|
25 | 26 | from nova.objects import fields
|
26 | 27 | from nova.pci import manager
|
@@ -478,6 +479,61 @@ def test_set_hvdevs_unavailable_pf_removed(self):
|
478 | 479 | self.assertEqual('allocated', dev4_vf.status)
|
479 | 480 | self.assertEqual(uuidsentinel.instance1, dev4_vf.instance_uuid)
|
480 | 481 |
|
| 482 | + def test_claim_available_pf_while_child_vf_is_unavailable(self): |
| 483 | + # NOTE(gibi): this is bug 1969496. The state created here is |
| 484 | + # inconsistent and should not happen. But it did happen in some cases |
| 485 | + # where we were not able to track down the way how it happened. |
| 486 | + |
| 487 | + # We start with a PF parent and a VF child. The PF is available and |
| 488 | + # the VF is unavailable. |
| 489 | + pf = copy.deepcopy(fake_db_dev_3) |
| 490 | + vf = copy.deepcopy(fake_db_dev_4) |
| 491 | + vf['status'] = fields.PciDeviceStatus.UNAVAILABLE |
| 492 | + self._create_tracker([pf, vf]) |
| 493 | + |
| 494 | + pf_dev = self._get_device_by_address(pf['address']) |
| 495 | + self.assertEqual('available', pf_dev.status) |
| 496 | + vf_dev = self._get_device_by_address(vf['address']) |
| 497 | + self.assertEqual('unavailable', vf_dev.status) |
| 498 | + |
| 499 | + pci_requests_obj = self._create_pci_requests_object( |
| 500 | + [ |
| 501 | + { |
| 502 | + 'count': 1, |
| 503 | + 'spec': [{'dev_type': fields.PciDeviceType.SRIOV_PF}] |
| 504 | + } |
| 505 | + ], |
| 506 | + instance_uuid=uuidsentinel.instance1, |
| 507 | + ) |
| 508 | + # now try to claim and allocate the PF. It should work as it is |
| 509 | + # available |
| 510 | + # This is bug 1969496 as the claim fails with exception |
| 511 | + ex = self.assertRaises( |
| 512 | + exception.PciDevicePoolEmpty, |
| 513 | + self.tracker.claim_instance, |
| 514 | + mock.sentinel.context, |
| 515 | + pci_requests_obj, |
| 516 | + None |
| 517 | + ) |
| 518 | + self.assertIn( |
| 519 | + 'Attempt to consume PCI device 1:0000:00:02.1 from empty pool', |
| 520 | + str(ex) |
| 521 | + ) |
| 522 | + pf_dev = self._get_device_by_address(pf['address']) |
| 523 | + self.assertEqual('available', pf_dev.status) |
| 524 | + vf_dev = self._get_device_by_address(vf['address']) |
| 525 | + self.assertEqual('unavailable', vf_dev.status) |
| 526 | + |
| 527 | + # This should work when the bug is fixed |
| 528 | + # self.tracker.claim_instance( |
| 529 | + # mock.sentinel.context, pci_requests_obj, None) |
| 530 | + # self.tracker.allocate_instance({'uuid': uuidsentinel.instance1}) |
| 531 | + |
| 532 | + # pf_dev = self._get_device_by_address(pf['address']) |
| 533 | + # self.assertEqual('allocated', pf_dev.status) |
| 534 | + # vf_dev = self._get_device_by_address(vf['address']) |
| 535 | + # self.assertEqual('unavailable', vf_dev.status) |
| 536 | + |
481 | 537 | def test_update_pci_for_instance_active(self):
|
482 | 538 | pci_requests_obj = self._create_pci_requests_object(fake_pci_requests)
|
483 | 539 | self.tracker.claim_instance(mock.sentinel.context,
|
|
0 commit comments