Skip to content

Commit 4eb32cb

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Optimize SchedulerReportClient.delete_resource_provider"
2 parents d29d1d1 + 4adface commit 4eb32cb

File tree

4 files changed

+36
-21
lines changed

4 files changed

+36
-21
lines changed

nova/objects/instance.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,8 @@ class InstanceList(base.ObjectListBase, base.NovaObject):
12191219
# Version 2.2: Pagination for get_active_by_window_joined()
12201220
# Version 2.3: Add get_count_by_vm_state()
12211221
# Version 2.4: Add get_counts()
1222-
VERSION = '2.4'
1222+
# Version 2.5: Add get_uuids_by_host_and_node()
1223+
VERSION = '2.5'
12231224

12241225
fields = {
12251226
'objects': fields.ListOfObjectsField('Instance'),
@@ -1282,6 +1283,24 @@ def get_by_host_and_node(cls, context, host, node, expected_attrs=None):
12821283
return _make_instance_list(context, cls(), db_inst_list,
12831284
expected_attrs)
12841285

1286+
@staticmethod
1287+
@db_api.pick_context_manager_reader
1288+
def _get_uuids_by_host_and_node(context, host, node):
1289+
return context.session.query(
1290+
models.Instance.uuid).filter_by(
1291+
host=host).filter_by(node=node).filter_by(deleted=0).all()
1292+
1293+
@base.remotable_classmethod
1294+
def get_uuids_by_host_and_node(cls, context, host, node):
1295+
"""Return non-deleted instance UUIDs for the given host and node.
1296+
1297+
:param context: nova auth request context
1298+
:param host: Filter instances on this host.
1299+
:param node: Filter instances on this node.
1300+
:returns: list of non-deleted instance UUIDs on the given host and node
1301+
"""
1302+
return cls._get_uuids_by_host_and_node(context, host, node)
1303+
12851304
@base.remotable_classmethod
12861305
def get_by_host_and_not_type(cls, context, host, type_id=None,
12871306
expected_attrs=None):

nova/scheduler/client/report.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2150,14 +2150,16 @@ def delete_resource_provider(self, context, compute_node, cascade=False):
21502150
# Delete any allocations for this resource provider.
21512151
# Since allocations are by consumer, we get the consumers on this
21522152
# host, which are its instances.
2153-
# TODO(mriedem): Optimize this up by adding an
2154-
# InstanceList.get_uuids_by_host_and_node method.
2155-
# Pass expected_attrs=[] to avoid joining on extra columns we
2156-
# don't use.
2157-
instances = objects.InstanceList.get_by_host_and_node(
2158-
context, host, nodename, expected_attrs=[])
2159-
for instance in instances:
2160-
self.delete_allocation_for_instance(context, instance.uuid)
2153+
# NOTE(mriedem): This assumes the only allocations on this node
2154+
# are instances, but there could be migration consumers if the
2155+
# node is deleted during a migration or allocations from an
2156+
# evacuated host (bug 1829479). Obviously an admin shouldn't
2157+
# do that but...you know. I guess the provider deletion should fail
2158+
# in that case which is what we'd want to happen.
2159+
instance_uuids = objects.InstanceList.get_uuids_by_host_and_node(
2160+
context, host, nodename)
2161+
for instance_uuid in instance_uuids:
2162+
self.delete_allocation_for_instance(context, instance_uuid)
21612163
try:
21622164
self._delete_provider(rp_uuid, global_request_id=context.global_id)
21632165
except (exception.ResourceProviderInUse,

nova/tests/unit/objects/test_objects.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,7 @@ def obj_name(cls):
10841084
'InstanceGroup': '1.11-852ac511d30913ee88f3c3a869a8f30a',
10851085
'InstanceGroupList': '1.8-90f8f1a445552bb3bbc9fa1ae7da27d4',
10861086
'InstanceInfoCache': '1.5-cd8b96fefe0fc8d4d337243ba0bf0e1e',
1087-
'InstanceList': '2.4-d2c5723da8c1d08e07cb00160edfd292',
1087+
'InstanceList': '2.5-43b5e7d8c4ebde52f2c2da22a1739e95',
10881088
'InstanceMapping': '1.2-3bd375e65c8eb9c45498d2f87b882e03',
10891089
'InstanceMappingList': '1.3-d34b6ebb076d542ae0f8b440534118da',
10901090
'InstanceNUMACell': '1.4-7c1eb9a198dee076b4de0840e45f4f55',

nova/tests/unit/scheduler/client/test_report.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3219,21 +3219,18 @@ def test_instance_to_allocations_dict_zero_disk(self, mock_vbi):
32193219
"delete")
32203220
@mock.patch("nova.scheduler.client.report.SchedulerReportClient."
32213221
"delete_allocation_for_instance")
3222-
@mock.patch("nova.objects.InstanceList.get_by_host_and_node")
3222+
@mock.patch("nova.objects.InstanceList.get_uuids_by_host_and_node")
32233223
def test_delete_resource_provider_cascade(self, mock_by_host,
32243224
mock_del_alloc, mock_delete):
32253225
self.client._provider_tree.new_root(uuids.cn, uuids.cn, generation=1)
32263226
cn = objects.ComputeNode(uuid=uuids.cn, host="fake_host",
32273227
hypervisor_hostname="fake_hostname", )
3228-
inst1 = objects.Instance(uuid=uuids.inst1)
3229-
inst2 = objects.Instance(uuid=uuids.inst2)
3230-
mock_by_host.return_value = objects.InstanceList(
3231-
objects=[inst1, inst2])
3228+
mock_by_host.return_value = [uuids.inst1, uuids.inst2]
32323229
resp_mock = mock.Mock(status_code=204)
32333230
mock_delete.return_value = resp_mock
32343231
self.client.delete_resource_provider(self.context, cn, cascade=True)
32353232
mock_by_host.assert_called_once_with(
3236-
self.context, cn.host, cn.hypervisor_hostname, expected_attrs=[])
3233+
self.context, cn.host, cn.hypervisor_hostname)
32373234
self.assertEqual(2, mock_del_alloc.call_count)
32383235
exp_url = "/resource_providers/%s" % uuids.cn
32393236
mock_delete.assert_called_once_with(
@@ -3244,17 +3241,14 @@ def test_delete_resource_provider_cascade(self, mock_by_host,
32443241
"delete")
32453242
@mock.patch("nova.scheduler.client.report.SchedulerReportClient."
32463243
"delete_allocation_for_instance")
3247-
@mock.patch("nova.objects.InstanceList.get_by_host_and_node")
3244+
@mock.patch("nova.objects.InstanceList.get_uuids_by_host_and_node")
32483245
def test_delete_resource_provider_no_cascade(self, mock_by_host,
32493246
mock_del_alloc, mock_delete):
32503247
self.client._provider_tree.new_root(uuids.cn, uuids.cn, generation=1)
32513248
self.client._association_refresh_time[uuids.cn] = mock.Mock()
32523249
cn = objects.ComputeNode(uuid=uuids.cn, host="fake_host",
32533250
hypervisor_hostname="fake_hostname", )
3254-
inst1 = objects.Instance(uuid=uuids.inst1)
3255-
inst2 = objects.Instance(uuid=uuids.inst2)
3256-
mock_by_host.return_value = objects.InstanceList(
3257-
objects=[inst1, inst2])
3251+
mock_by_host.return_value = [uuids.inst1, uuids.inst2]
32583252
resp_mock = mock.Mock(status_code=204)
32593253
mock_delete.return_value = resp_mock
32603254
self.client.delete_resource_provider(self.context, cn)

0 commit comments

Comments
 (0)