Browse Source

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

changes/49/679449/1
Zuul 3 weeks ago
parent
commit
ee942b43cb
2 changed files with 44 additions and 35 deletions
  1. 5
    1
      nova/compute/resource_tracker.py
  2. 39
    34
      nova/tests/unit/compute/test_resource_tracker.py

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

@@ -580,8 +580,12 @@ class ResourceTracker(object):
580 580
         cn = objects.ComputeNode(context)
581 581
         cn.host = self.host
582 582
         self._copy_resources(cn, resources)
583
-        self.compute_nodes[nodename] = cn
584 583
         cn.create()
584
+        # Only map the ComputeNode into compute_nodes if create() was OK
585
+        # because if create() fails, on the next run through here nodename
586
+        # would be in compute_nodes and we won't try to create again (because
587
+        # of the logic above).
588
+        self.compute_nodes[nodename] = cn
585 589
         LOG.info('Compute node record created for '
586 590
                  '%(host)s:%(node)s with uuid: %(uuid)s',
587 591
                  {'host': self.host, 'node': nodename, 'uuid': cn.uuid})

+ 39
- 34
nova/tests/unit/compute/test_resource_tracker.py View File

@@ -1074,23 +1074,18 @@ class TestInitComputeNode(BaseTestCase):
1074 1074
         self.assertEqual(_HOSTNAME, self.rt.compute_nodes[_NODENAME].host)
1075 1075
 
1076 1076
     @mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
1077
-    @mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
1078
-                return_value=objects.PciDeviceList(objects=[]))
1079 1077
     @mock.patch('nova.objects.ComputeNode.create')
1080 1078
     @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')
1081 1079
     @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
1082 1080
                 '_update')
1083 1081
     def test_compute_node_created_on_empty(self, update_mock, get_mock,
1084
-                                           create_mock, pci_tracker_mock,
1082
+                                           create_mock,
1085 1083
                                            get_by_hypervisor_mock):
1086 1084
         get_by_hypervisor_mock.return_value = []
1087 1085
         self._test_compute_node_created(update_mock, get_mock, create_mock,
1088
-                                        pci_tracker_mock,
1089 1086
                                         get_by_hypervisor_mock)
1090 1087
 
1091 1088
     @mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
1092
-    @mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
1093
-                return_value=objects.PciDeviceList(objects=[]))
1094 1089
     @mock.patch('nova.objects.ComputeNode.create')
1095 1090
     @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')
1096 1091
     @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
@@ -1098,32 +1093,26 @@ class TestInitComputeNode(BaseTestCase):
1098 1093
     def test_compute_node_created_on_empty_rebalance(self, update_mock,
1099 1094
                                                      get_mock,
1100 1095
                                                      create_mock,
1101
-                                                     pci_tracker_mock,
1102 1096
                                                      get_by_hypervisor_mock):
1103 1097
         get_by_hypervisor_mock.return_value = []
1104 1098
         self._test_compute_node_created(update_mock, get_mock, create_mock,
1105
-                                        pci_tracker_mock,
1106 1099
                                         get_by_hypervisor_mock,
1107 1100
                                         rebalances_nodes=True)
1108 1101
 
1109 1102
     @mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
1110
-    @mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
1111
-                return_value=objects.PciDeviceList(objects=[]))
1112 1103
     @mock.patch('nova.objects.ComputeNode.create')
1113 1104
     @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')
1114 1105
     @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
1115 1106
                 '_update')
1116 1107
     def test_compute_node_created_too_many(self, update_mock, get_mock,
1117
-                                           create_mock, pci_tracker_mock,
1108
+                                           create_mock,
1118 1109
                                            get_by_hypervisor_mock):
1119 1110
         get_by_hypervisor_mock.return_value = ["fake_node_1", "fake_node_2"]
1120 1111
         self._test_compute_node_created(update_mock, get_mock, create_mock,
1121
-                                        pci_tracker_mock,
1122 1112
                                         get_by_hypervisor_mock,
1123 1113
                                         rebalances_nodes=True)
1124 1114
 
1125
-    def _test_compute_node_created(self, update_mock, get_mock,
1126
-                                   create_mock, pci_tracker_mock,
1115
+    def _test_compute_node_created(self, update_mock, get_mock, create_mock,
1127 1116
                                    get_by_hypervisor_mock,
1128 1117
                                    rebalances_nodes=False):
1129 1118
         self.flags(cpu_allocation_ratio=1.0, ram_allocation_ratio=1.0,
@@ -1152,12 +1141,12 @@ class TestInitComputeNode(BaseTestCase):
1152 1141
             'current_workload': 0,
1153 1142
             'vcpus': 4,
1154 1143
             'running_vms': 0,
1155
-            'pci_passthrough_devices': '[]'
1144
+            'pci_passthrough_devices': '[]',
1145
+            'uuid': uuids.compute_node_uuid
1156 1146
         }
1157 1147
         # The expected compute represents the initial values used
1158 1148
         # when creating a compute node.
1159 1149
         expected_compute = objects.ComputeNode(
1160
-            id=42,
1161 1150
             host_ip=resources['host_ip'],
1162 1151
             vcpus=resources['vcpus'],
1163 1152
             memory_mb=resources['memory_mb'],
@@ -1177,20 +1166,11 @@ class TestInitComputeNode(BaseTestCase):
1177 1166
             cpu_allocation_ratio=1.0,
1178 1167
             disk_allocation_ratio=1.0,
1179 1168
             stats={'failed_builds': 0},
1180
-            pci_device_pools=objects.PciDevicePoolList(objects=[]),
1181 1169
             uuid=uuids.compute_node_uuid
1182 1170
         )
1183 1171
 
1184
-        def set_cn_id():
1185
-            # The PCI tracker needs the compute node's ID when starting up, so
1186
-            # make sure that we set the ID value so we don't get a Cannot load
1187
-            # 'id' in base class error
1188
-            cn = self.rt.compute_nodes[_NODENAME]
1189
-            cn.id = 42  # Has to be a number, not a mock
1190
-            cn.uuid = uuids.compute_node_uuid
1191
-
1192
-        create_mock.side_effect = set_cn_id
1193
-        self.rt._init_compute_node(mock.sentinel.ctx, resources)
1172
+        with mock.patch.object(self.rt, '_setup_pci_tracker') as setup_pci:
1173
+            self.rt._init_compute_node(mock.sentinel.ctx, resources)
1194 1174
 
1195 1175
         cn = self.rt.compute_nodes[_NODENAME]
1196 1176
         get_mock.assert_called_once_with(mock.sentinel.ctx, _HOSTNAME,
@@ -1202,22 +1182,47 @@ class TestInitComputeNode(BaseTestCase):
1202 1182
             get_by_hypervisor_mock.assert_not_called()
1203 1183
         create_mock.assert_called_once_with()
1204 1184
         self.assertTrue(obj_base.obj_equal_prims(expected_compute, cn))
1205
-        pci_tracker_mock.assert_called_once_with(mock.sentinel.ctx,
1206
-                                                 42)
1185
+        setup_pci.assert_called_once_with(mock.sentinel.ctx, cn, resources)
1207 1186
         self.assertFalse(update_mock.called)
1208 1187
 
1188
+    @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
1189
+                '_setup_pci_tracker')
1190
+    @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename',
1191
+                side_effect=exc.ComputeHostNotFound(host=_HOSTNAME))
1192
+    @mock.patch('nova.objects.ComputeNode.create',
1193
+                side_effect=(test.TestingException, None))
1194
+    def test_compute_node_create_fail_retry_works(self, mock_create, mock_get,
1195
+                                                  mock_setup_pci):
1196
+        """Tests that _init_compute_node will not save the ComputeNode object
1197
+        in the compute_nodes dict if create() fails.
1198
+        """
1199
+        self._setup_rt()
1200
+        self.assertEqual({}, self.rt.compute_nodes)
1201
+        ctxt = context.get_context()
1202
+        # The first ComputeNode.create fails so rt.compute_nodes should
1203
+        # remain empty.
1204
+        resources = copy.deepcopy(_VIRT_DRIVER_AVAIL_RESOURCES)
1205
+        resources['uuid'] = uuids.cn_uuid  # for the LOG.info message
1206
+        self.assertRaises(test.TestingException,
1207
+                          self.rt._init_compute_node, ctxt, resources)
1208
+        self.assertEqual({}, self.rt.compute_nodes)
1209
+        # Second create works so compute_nodes should have a mapping.
1210
+        self.rt._init_compute_node(ctxt, resources)
1211
+        self.assertIn(_NODENAME, self.rt.compute_nodes)
1212
+        mock_get.assert_has_calls([mock.call(
1213
+            ctxt, _HOSTNAME, _NODENAME)] * 2)
1214
+        self.assertEqual(2, mock_create.call_count)
1215
+        mock_setup_pci.assert_called_once_with(
1216
+            ctxt, test.MatchType(objects.ComputeNode), resources)
1217
+
1209 1218
     @mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
1210
-    @mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
1211
-                return_value=objects.PciDeviceList(objects=[]))
1212 1219
     @mock.patch('nova.objects.ComputeNode.create')
1213 1220
     @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')
1214 1221
     @mock.patch('nova.compute.resource_tracker.ResourceTracker.'
1215 1222
                 '_update')
1216 1223
     def test_node_removed(self, update_mock, get_mock,
1217
-                          create_mock, pci_tracker_mock,
1218
-                          get_by_hypervisor_mock):
1224
+                          create_mock, get_by_hypervisor_mock):
1219 1225
         self._test_compute_node_created(update_mock, get_mock, create_mock,
1220
-                                        pci_tracker_mock,
1221 1226
                                         get_by_hypervisor_mock)
1222 1227
         self.rt.old_resources[_NODENAME] = mock.sentinel.foo
1223 1228
         self.assertIn(_NODENAME, self.rt.compute_nodes)

Loading…
Cancel
Save