@@ -1346,3 +1346,113 @@ def test_heal_partial_allocations_during_resize_change_dev_type(self):
1346
1346
del compute1_expected_placement_view ["allocations" ][server ["id" ]]
1347
1347
self .assert_placement_pci_view (
1348
1348
"compute1" , ** compute1_expected_placement_view )
1349
+
1350
+ def test_heal_allocation_during_same_host_resize (self ):
1351
+ self .flags (allow_resize_to_same_host = True )
1352
+ # The fake libvirt will emulate on the host:
1353
+ # * one type-PFs (slot 0) with 3 type-VFs
1354
+ compute1_pci_info = fakelibvirt .HostPCIDevicesInfo (
1355
+ num_pci = 0 , num_pfs = 1 , num_vfs = 3 )
1356
+ # the config matches just the VFs
1357
+ compute1_device_spec = self ._to_device_spec_conf (
1358
+ [
1359
+ {
1360
+ "vendor_id" : fakelibvirt .PCI_VEND_ID ,
1361
+ "product_id" : fakelibvirt .VF_PROD_ID ,
1362
+ "address" : "0000:81:00.*" ,
1363
+ },
1364
+ ]
1365
+ )
1366
+ self .flags (group = 'pci' , device_spec = compute1_device_spec )
1367
+ # Start a compute with PCI tracking in placement
1368
+ self .mock_pci_report_in_placement .return_value = True
1369
+ self .start_compute (hostname = "compute1" , pci_info = compute1_pci_info )
1370
+ self .assertPCIDeviceCounts ("compute1" , total = 3 , free = 3 )
1371
+ compute1_expected_placement_view = {
1372
+ "inventories" : {
1373
+ "0000:81:00.0" : {self .VF_RC : 3 },
1374
+ },
1375
+ "traits" : {
1376
+ "0000:81:00.0" : [],
1377
+ },
1378
+ "usages" : {
1379
+ "0000:81:00.0" : {self .VF_RC : 0 },
1380
+ },
1381
+ "allocations" : {},
1382
+ }
1383
+ self .assert_placement_pci_view (
1384
+ "compute1" , ** compute1_expected_placement_view )
1385
+ # Create an instance consuming one VFs
1386
+ extra_spec = {"pci_passthrough:alias" : "a-vf:1" }
1387
+ flavor_id = self ._create_flavor (extra_spec = extra_spec )
1388
+ server = self ._create_server (flavor_id = flavor_id , networks = [])
1389
+ self .assertPCIDeviceCounts ("compute1" , total = 3 , free = 2 )
1390
+ # As scheduling does not support PCI in placement yet no allocation
1391
+ # is created for the PCI consumption by the scheduler. BUT the resource
1392
+ # tracker in the compute will heal the missing PCI allocation
1393
+ compute1_expected_placement_view [
1394
+ "usages" ]["0000:81:00.0" ][self .VF_RC ] = 1
1395
+ compute1_expected_placement_view ["allocations" ][server ["id" ]] = {
1396
+ "0000:81:00.0" : {self .VF_RC : 1 }
1397
+ }
1398
+ self .assert_placement_pci_view (
1399
+ "compute1" , ** compute1_expected_placement_view )
1400
+ self ._run_periodics ()
1401
+ self .assert_placement_pci_view (
1402
+ "compute1" , ** compute1_expected_placement_view )
1403
+
1404
+ # resize the server to consume 2 VFs on the same host
1405
+ extra_spec = {"pci_passthrough:alias" : "a-vf:2" }
1406
+ flavor_id = self ._create_flavor (extra_spec = extra_spec )
1407
+ server = self ._resize_server (server , flavor_id )
1408
+ # during resize both the source and the dest allocation is kept
1409
+ # and in same host resize that means both consumed from the same host
1410
+ self .assertPCIDeviceCounts ("compute1" , total = 3 , free = 0 )
1411
+ # the source side of the allocation held by the migration
1412
+ self ._move_server_allocation (
1413
+ compute1_expected_placement_view ["allocations" ], server ['id' ])
1414
+ # NOTE(gibi): we intentionally don't heal allocation for the instance
1415
+ # while it is being resized. See the comment in the
1416
+ # pci_placement_translator about the reasoning.
1417
+ self .assert_placement_pci_view (
1418
+ "compute1" , ** compute1_expected_placement_view )
1419
+ self ._run_periodics ()
1420
+ self .assert_placement_pci_view (
1421
+ "compute1" , ** compute1_expected_placement_view )
1422
+
1423
+ # revert the resize
1424
+ self ._revert_resize (server )
1425
+ self .assertPCIDeviceCounts ("compute1" , total = 3 , free = 2 )
1426
+ # the original allocations are restored
1427
+ self ._move_server_allocation (
1428
+ compute1_expected_placement_view ["allocations" ],
1429
+ server ["id" ],
1430
+ revert = True ,
1431
+ )
1432
+ compute1_expected_placement_view [
1433
+ "usages" ]["0000:81:00.0" ][self .VF_RC ] = 1
1434
+ compute1_expected_placement_view ["allocations" ][server ["id" ]] = {
1435
+ "0000:81:00.0" : {self .VF_RC : 1 }
1436
+ }
1437
+ self .assert_placement_pci_view (
1438
+ "compute1" , ** compute1_expected_placement_view )
1439
+ self ._run_periodics ()
1440
+ self .assert_placement_pci_view (
1441
+ "compute1" , ** compute1_expected_placement_view )
1442
+
1443
+ # now resize and then confirm it
1444
+ self ._resize_server (server , flavor_id )
1445
+ self ._confirm_resize (server )
1446
+
1447
+ # we expect that the consumption is according to the new flavor
1448
+ self .assertPCIDeviceCounts ("compute1" , total = 3 , free = 1 )
1449
+ compute1_expected_placement_view [
1450
+ "usages" ]["0000:81:00.0" ][self .VF_RC ] = 2
1451
+ compute1_expected_placement_view ["allocations" ][server ["id" ]] = {
1452
+ "0000:81:00.0" : {self .VF_RC : 2 }
1453
+ }
1454
+ self .assert_placement_pci_view (
1455
+ "compute1" , ** compute1_expected_placement_view )
1456
+ self ._run_periodics ()
1457
+ self .assert_placement_pci_view (
1458
+ "compute1" , ** compute1_expected_placement_view )
0 commit comments