@@ -397,6 +397,87 @@ def test_set_hvdev_changed_stal(self):
397
397
self .assertEqual (len (self .tracker .stale ), 1 )
398
398
self .assertEqual (self .tracker .stale ['0000:00:00.2' ]['vendor_id' ], 'v2' )
399
399
400
+ def _get_device_by_address (self , address ):
401
+ devs = [dev for dev in self .tracker .pci_devs if dev .address == address ]
402
+ if len (devs ) == 1 :
403
+ return devs [0 ]
404
+ if devs :
405
+ raise ValueError ('ambiguous address' , devs )
406
+ else :
407
+ raise ValueError ('device not found' , address )
408
+
409
+ def test_set_hvdevs_unavailable_vf_removed (self ):
410
+ # We start with a PF parent and two VF children
411
+ self ._create_tracker ([fake_db_dev_3 , fake_db_dev_4 , fake_db_dev_5 ])
412
+ pci_requests_obj = self ._create_pci_requests_object (
413
+ [
414
+ {
415
+ 'count' : 1 ,
416
+ 'spec' : [{'dev_type' : fields .PciDeviceType .SRIOV_PF }]
417
+ }
418
+ ],
419
+ instance_uuid = uuidsentinel .instance1 ,
420
+ )
421
+ # then claim and allocate the PF that makes the VFs unavailable
422
+ self .tracker .claim_instance (
423
+ mock .sentinel .context , pci_requests_obj , None )
424
+ self .tracker .allocate_instance ({'uuid' : uuidsentinel .instance1 })
425
+
426
+ dev3_pf = self ._get_device_by_address (fake_db_dev_3 ['address' ])
427
+ self .assertEqual ('allocated' , dev3_pf .status )
428
+ self .assertEqual (uuidsentinel .instance1 , dev3_pf .instance_uuid )
429
+ dev4_vf = self ._get_device_by_address (fake_db_dev_4 ['address' ])
430
+ self .assertEqual ('unavailable' , dev4_vf .status )
431
+ dev5_vf = self ._get_device_by_address (fake_db_dev_5 ['address' ])
432
+ self .assertEqual ('unavailable' , dev5_vf .status )
433
+
434
+ # now simulate that one VF (dev_5) is removed from the hypervisor and
435
+ # the compute is restarted. As the VF is not claimed or allocated we
436
+ # are free to remove it from the tracker.
437
+ self .tracker ._set_hvdevs (copy .deepcopy ([fake_pci_3 , fake_pci_4 ]))
438
+
439
+ dev3_pf = self ._get_device_by_address (fake_db_dev_3 ['address' ])
440
+ self .assertEqual ('allocated' , dev3_pf .status )
441
+ self .assertEqual (uuidsentinel .instance1 , dev3_pf .instance_uuid )
442
+ dev4_vf = self ._get_device_by_address (fake_db_dev_4 ['address' ])
443
+ self .assertEqual ('unavailable' , dev4_vf .status )
444
+ dev5_vf = self ._get_device_by_address (fake_db_dev_5 ['address' ])
445
+ self .assertEqual ('removed' , dev5_vf .status )
446
+
447
+ def test_set_hvdevs_unavailable_pf_removed (self ):
448
+ # We start with one PF parent and one child VF
449
+ self ._create_tracker ([fake_db_dev_3 , fake_db_dev_4 ])
450
+ pci_requests_obj = self ._create_pci_requests_object (
451
+ [
452
+ {
453
+ 'count' : 1 ,
454
+ 'spec' : [{'dev_type' : fields .PciDeviceType .SRIOV_VF }]
455
+ }
456
+ ],
457
+ instance_uuid = uuidsentinel .instance1 ,
458
+ )
459
+ # Then we claim and allocate the VF that makes the PF unavailable
460
+ self .tracker .claim_instance (
461
+ mock .sentinel .context , pci_requests_obj , None )
462
+ self .tracker .allocate_instance ({'uuid' : uuidsentinel .instance1 })
463
+
464
+ dev3_pf = self ._get_device_by_address (fake_db_dev_3 ['address' ])
465
+ self .assertEqual ('unavailable' , dev3_pf .status )
466
+ dev4_vf = self ._get_device_by_address (fake_db_dev_4 ['address' ])
467
+ self .assertEqual ('allocated' , dev4_vf .status )
468
+ self .assertEqual (uuidsentinel .instance1 , dev4_vf .instance_uuid )
469
+
470
+ # now simulate that the parent PF is removed from the hypervisor and
471
+ # the compute is restarted. As the PF is not claimed or allocated we
472
+ # are free to remove it from the tracker.
473
+ self .tracker ._set_hvdevs (copy .deepcopy ([fake_pci_4 ]))
474
+
475
+ dev3_pf = self ._get_device_by_address (fake_db_dev_3 ['address' ])
476
+ self .assertEqual ('removed' , dev3_pf .status )
477
+ dev4_vf = self ._get_device_by_address (fake_db_dev_4 ['address' ])
478
+ self .assertEqual ('allocated' , dev4_vf .status )
479
+ self .assertEqual (uuidsentinel .instance1 , dev4_vf .instance_uuid )
480
+
400
481
def test_update_pci_for_instance_active (self ):
401
482
pci_requests_obj = self ._create_pci_requests_object (fake_pci_requests )
402
483
self .tracker .claim_instance (mock .sentinel .context ,
0 commit comments