Browse Source

Merge "rt: only map compute node if we created it" into stable/stein

changes/19/679519/1
Zuul 3 weeks ago
parent
commit
87fd2383b8
2 changed files with 45 additions and 36 deletions
  1. 5
    1
      nova/compute/resource_tracker.py
  2. 40
    35
      nova/tests/unit/compute/test_resource_tracker.py

+ 5
- 1
nova/compute/resource_tracker.py View File

@@ -600,8 +600,12 @@ class ResourceTracker(object):
600 600
         cn = objects.ComputeNode(context)
601 601
         cn.host = self.host
602 602
         self._copy_resources(cn, resources, initial=True)
603
-        self.compute_nodes[nodename] = cn
604 603
         cn.create()
604
+        # Only map the ComputeNode into compute_nodes if create() was OK
605
+        # because if create() fails, on the next run through here nodename
606
+        # would be in compute_nodes and we won't try to create again (because
607
+        # of the logic above).
608
+        self.compute_nodes[nodename] = cn
605 609
         LOG.info('Compute node record created for '
606 610
                  '%(host)s:%(node)s with uuid: %(uuid)s',
607 611
                  {'host': self.host, 'node': nodename, 'uuid': cn.uuid})

+ 40
- 35
nova/tests/unit/compute/test_resource_tracker.py View File

@@ -1165,23 +1165,18 @@ class TestInitComputeNode(BaseTestCase):
1165 1165
         self.assertEqual(_HOSTNAME, self.rt.compute_nodes[_NODENAME].host)
1166 1166
 
1167 1167
     @mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
1168
-    @mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
1169
-                return_value=objects.PciDeviceList(objects=[]))
1170 1168
     @mock.patch('nova.objects.ComputeNode.create')
1171 1169
     @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')
1172 1170
     @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
1173 1171
                 '_update')
1174 1172
     def test_compute_node_created_on_empty(self, update_mock, get_mock,
1175
-                                           create_mock, pci_tracker_mock,
1173
+                                           create_mock,
1176 1174
                                            get_by_hypervisor_mock):
1177 1175
         get_by_hypervisor_mock.return_value = []
1178 1176
         self._test_compute_node_created(update_mock, get_mock, create_mock,
1179
-                                        pci_tracker_mock,
1180 1177
                                         get_by_hypervisor_mock)
1181 1178
 
1182 1179
     @mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
1183
-    @mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
1184
-                return_value=objects.PciDeviceList(objects=[]))
1185 1180
     @mock.patch('nova.objects.ComputeNode.create')
1186 1181
     @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')
1187 1182
     @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
@@ -1189,32 +1184,26 @@ class TestInitComputeNode(BaseTestCase):
1189 1184
     def test_compute_node_created_on_empty_rebalance(self, update_mock,
1190 1185
                                                      get_mock,
1191 1186
                                                      create_mock,
1192
-                                                     pci_tracker_mock,
1193 1187
                                                      get_by_hypervisor_mock):
1194 1188
         get_by_hypervisor_mock.return_value = []
1195 1189
         self._test_compute_node_created(update_mock, get_mock, create_mock,
1196
-                                        pci_tracker_mock,
1197 1190
                                         get_by_hypervisor_mock,
1198 1191
                                         rebalances_nodes=True)
1199 1192
 
1200 1193
     @mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
1201
-    @mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
1202
-                return_value=objects.PciDeviceList(objects=[]))
1203 1194
     @mock.patch('nova.objects.ComputeNode.create')
1204 1195
     @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')
1205 1196
     @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
1206 1197
                 '_update')
1207 1198
     def test_compute_node_created_too_many(self, update_mock, get_mock,
1208
-                                           create_mock, pci_tracker_mock,
1199
+                                           create_mock,
1209 1200
                                            get_by_hypervisor_mock):
1210 1201
         get_by_hypervisor_mock.return_value = ["fake_node_1", "fake_node_2"]
1211 1202
         self._test_compute_node_created(update_mock, get_mock, create_mock,
1212
-                                        pci_tracker_mock,
1213 1203
                                         get_by_hypervisor_mock,
1214 1204
                                         rebalances_nodes=True)
1215 1205
 
1216
-    def _test_compute_node_created(self, update_mock, get_mock,
1217
-                                   create_mock, pci_tracker_mock,
1206
+    def _test_compute_node_created(self, update_mock, get_mock, create_mock,
1218 1207
                                    get_by_hypervisor_mock,
1219 1208
                                    rebalances_nodes=False):
1220 1209
         self.flags(cpu_allocation_ratio=1.0, ram_allocation_ratio=1.0,
@@ -1243,12 +1232,12 @@ class TestInitComputeNode(BaseTestCase):
1243 1232
             'current_workload': 0,
1244 1233
             'vcpus': 4,
1245 1234
             'running_vms': 0,
1246
-            'pci_passthrough_devices': '[]'
1235
+            'pci_passthrough_devices': '[]',
1236
+            'uuid': uuids.compute_node_uuid
1247 1237
         }
1248 1238
         # The expected compute represents the initial values used
1249 1239
         # when creating a compute node.
1250 1240
         expected_compute = objects.ComputeNode(
1251
-            id=42,
1252 1241
             host_ip=resources['host_ip'],
1253 1242
             vcpus=resources['vcpus'],
1254 1243
             memory_mb=resources['memory_mb'],
@@ -1268,21 +1257,12 @@ class TestInitComputeNode(BaseTestCase):
1268 1257
             cpu_allocation_ratio=CONF.initial_cpu_allocation_ratio,
1269 1258
             disk_allocation_ratio=CONF.initial_disk_allocation_ratio,
1270 1259
             stats={'failed_builds': 0},
1271
-            pci_device_pools=objects.PciDevicePoolList(objects=[]),
1272 1260
             uuid=uuids.compute_node_uuid
1273 1261
         )
1274 1262
 
1275
-        def set_cn_id():
1276
-            # The PCI tracker needs the compute node's ID when starting up, so
1277
-            # make sure that we set the ID value so we don't get a Cannot load
1278
-            # 'id' in base class error
1279
-            cn = self.rt.compute_nodes[_NODENAME]
1280
-            cn.id = 42  # Has to be a number, not a mock
1281
-            cn.uuid = uuids.compute_node_uuid
1282
-
1283
-        create_mock.side_effect = set_cn_id
1284
-        self.assertTrue(
1285
-            self.rt._init_compute_node(mock.sentinel.ctx, resources))
1263
+        with mock.patch.object(self.rt, '_setup_pci_tracker') as setup_pci:
1264
+            self.assertTrue(
1265
+                self.rt._init_compute_node(mock.sentinel.ctx, resources))
1286 1266
 
1287 1267
         cn = self.rt.compute_nodes[_NODENAME]
1288 1268
         get_mock.assert_called_once_with(mock.sentinel.ctx, _HOSTNAME,
@@ -1294,22 +1274,47 @@ class TestInitComputeNode(BaseTestCase):
1294 1274
             get_by_hypervisor_mock.assert_not_called()
1295 1275
         create_mock.assert_called_once_with()
1296 1276
         self.assertTrue(obj_base.obj_equal_prims(expected_compute, cn))
1297
-        pci_tracker_mock.assert_called_once_with(mock.sentinel.ctx,
1298
-                                                 42)
1277
+        setup_pci.assert_called_once_with(mock.sentinel.ctx, cn, resources)
1299 1278
         self.assertFalse(update_mock.called)
1300 1279
 
1280
+    @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
1281
+                '_setup_pci_tracker')
1282
+    @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename',
1283
+                side_effect=exc.ComputeHostNotFound(host=_HOSTNAME))
1284
+    @mock.patch('nova.objects.ComputeNode.create',
1285
+                side_effect=(test.TestingException, None))
1286
+    def test_compute_node_create_fail_retry_works(self, mock_create, mock_get,
1287
+                                                  mock_setup_pci):
1288
+        """Tests that _init_compute_node will not save the ComputeNode object
1289
+        in the compute_nodes dict if create() fails.
1290
+        """
1291
+        self._setup_rt()
1292
+        self.assertEqual({}, self.rt.compute_nodes)
1293
+        ctxt = context.get_context()
1294
+        # The first ComputeNode.create fails so rt.compute_nodes should
1295
+        # remain empty.
1296
+        resources = copy.deepcopy(_VIRT_DRIVER_AVAIL_RESOURCES)
1297
+        resources['uuid'] = uuids.cn_uuid  # for the LOG.info message
1298
+        self.assertRaises(test.TestingException,
1299
+                          self.rt._init_compute_node, ctxt, resources)
1300
+        self.assertEqual({}, self.rt.compute_nodes)
1301
+        # Second create works so compute_nodes should have a mapping.
1302
+        self.assertTrue(self.rt._init_compute_node(ctxt, resources))
1303
+        self.assertIn(_NODENAME, self.rt.compute_nodes)
1304
+        mock_get.assert_has_calls([mock.call(
1305
+            ctxt, _HOSTNAME, _NODENAME)] * 2)
1306
+        self.assertEqual(2, mock_create.call_count)
1307
+        mock_setup_pci.assert_called_once_with(
1308
+            ctxt, test.MatchType(objects.ComputeNode), resources)
1309
+
1301 1310
     @mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
1302
-    @mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
1303
-                return_value=objects.PciDeviceList(objects=[]))
1304 1311
     @mock.patch('nova.objects.ComputeNode.create')
1305 1312
     @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')
1306 1313
     @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
1307 1314
                 '_update')
1308 1315
     def test_node_removed(self, update_mock, get_mock,
1309
-                          create_mock, pci_tracker_mock,
1310
-                          get_by_hypervisor_mock):
1316
+                          create_mock, get_by_hypervisor_mock):
1311 1317
         self._test_compute_node_created(update_mock, get_mock, create_mock,
1312
-                                        pci_tracker_mock,
1313 1318
                                         get_by_hypervisor_mock)
1314 1319
         self.rt.old_resources[_NODENAME] = mock.sentinel.foo
1315 1320
         self.assertIn(_NODENAME, self.rt.compute_nodes)

Loading…
Cancel
Save