)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90d77bf85f8c089f86bfaf6db8a8e5409d9819d8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"2ceeeda5_0a9e7101","updated":"2026-06-15 17:35:25.000000000","message":"there are some inline issues that woudl be nice to adress but nothing that could not be fixed in the followup patch.\n\ni agree that this is a vaild repoducer for the bug","commit_id":"7eb47edeaa40151af1fbcebc2e8da35c10fff05d"}],"nova/tests/functional/regressions/test_bug_2111320.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90d77bf85f8c089f86bfaf6db8a8e5409d9819d8","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2025, Red Hat, Inc. All Rights Reserved."},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":2,"id":"8dcefb7c_f57750ba","line":1,"range":{"start_line":1,"start_character":0,"end_line":1,"end_character":52},"updated":"2026-06-15 17:35:25.000000000","message":"nit: i woudl drop this line or use 2026\n\nthe liscense is requried the copyright statement is not","commit_id":"7eb47edeaa40151af1fbcebc2e8da35c10fff05d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90d77bf85f8c089f86bfaf6db8a8e5409d9819d8","unresolved":true,"context_lines":[{"line_number":30,"context_line":"    soft-deleted rows (missing ``Service.deleted \u003d\u003d 0`` in the primaryjoin),"},{"line_number":31,"context_line":"    so the ``check_instance_host`` decorator may pick up a stale service"},{"line_number":32,"context_line":"    record whose heartbeat is long expired, causing ``service_is_up()`` to"},{"line_number":33,"context_line":"    return False and the API to return a 409 ServiceUnavailable error."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    This is a duplicate of bug 2073365 (resize path) but manifests here on"},{"line_number":36,"context_line":"    the volume detach path."}],"source_content_type":"text/x-python","patch_set":2,"id":"41bc3926_cdaeff76","line":33,"updated":"2026-06-15 17:35:25.000000000","message":"that sounds plasusable but you shoudl not be able to delete a compute serivce that has instance on it without also deleting all the instance record\n\nalso we populate the comptue service_id int eh compute nodes table as of \nhttps://specs.openstack.org/openstack/nova-specs/specs/2023.2/implemented/compute-object-ids.html\n\nso we have a direct linkage form the isntance to compute node by compute_id adn from the compute ndoe to service by id.\n\nand that was doen so that we didnt need to rely on the host to find the serivce or filter by delete or not because we directly can use the service id if that is needed.\n\nhttps://specs.openstack.org/openstack/nova-specs/specs/2023.2/implemented/compute-object-ids.html covered migrtion and some other action but i guess it never coverd impcliaton for other operation like volume detach. however it fell liek we shoudl not need to rely on filtering out the soft deleted row as we shoudl have a more solid driectly id of the service when tha tis requried.","commit_id":"7eb47edeaa40151af1fbcebc2e8da35c10fff05d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90d77bf85f8c089f86bfaf6db8a8e5409d9819d8","unresolved":true,"context_lines":[{"line_number":49,"context_line":"        The bug manifests when the stale service record happens to be"},{"line_number":50,"context_line":"        returned first by the ORM (e.g. it has a lower database ID than"},{"line_number":51,"context_line":"        the active record, which is the typical production scenario)."},{"line_number":52,"context_line":"        The ``check_instance_host`` decorator then picks up this stale"},{"line_number":53,"context_line":"        service whose heartbeat is expired, causing operations like"},{"line_number":54,"context_line":"        volume detach or resize to fail with a 409 error."},{"line_number":55,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"9bf05870_9bd6eedc","line":52,"range":{"start_line":52,"start_character":14,"end_line":52,"end_character":33},"updated":"2026-06-15 17:35:25.000000000","message":"so thats https://github.com/openstack/nova/blob/380f657b5102707a3da676478e72fd96691e966b/nova/compute/api.py#L214-L242\n\nand it relying on this join\n\nhttps://github.com/openstack/nova/blob/master/nova/db/main/models.py#L463-L472\n\n\n    services \u003d orm.relationship(\n        \u0027Service\u0027,\n        back_populates\u003d\u0027instance\u0027,\n        primaryjoin\u003d(\n            \u0027and_(Instance.host \u003d\u003d Service.host,\u0027\n            \u0027Service.binary \u003d\u003d \"nova-compute\",\u0027\n            \u0027Instance.deleted \u003d\u003d 0)\u0027\n        ),\n        foreign_keys\u003d\u0027Service.host\u0027,\n    )\n    \nwhich is still relying on Instance.host \u003d\u003d Service.host, \n\nrather then using the service_id form the compute node.","commit_id":"7eb47edeaa40151af1fbcebc2e8da35c10fff05d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90d77bf85f8c089f86bfaf6db8a8e5409d9819d8","unresolved":true,"context_lines":[{"line_number":63,"context_line":"        # Create an instance on host1."},{"line_number":64,"context_line":"        server \u003d self._create_server(networks\u003d\u0027none\u0027, host\u003d\u0027host1\u0027)"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"        # Migrate the instance to host2 so we can safely delete the"},{"line_number":67,"context_line":"        # host1 service (a service hosting instances cannot be deleted)."},{"line_number":68,"context_line":"        self.api.post_server_action("},{"line_number":69,"context_line":"            server[\u0027id\u0027], {\u0027migrate\u0027: None})"},{"line_number":70,"context_line":"        server \u003d self._wait_for_state_change(server, \u0027VERIFY_RESIZE\u0027)"},{"line_number":71,"context_line":"        self.assertEqual(\u0027host2\u0027, server[\u0027OS-EXT-SRV-ATTR:host\u0027])"},{"line_number":72,"context_line":"        self.api.post_server_action("},{"line_number":73,"context_line":"            server[\u0027id\u0027], {\u0027confirmResize\u0027: None})"},{"line_number":74,"context_line":"        server \u003d self._wait_for_state_change(server, \u0027ACTIVE\u0027)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"        # Delete the host1 compute service.  This soft-deletes the service"}],"source_content_type":"text/x-python","patch_set":2,"id":"4669b17a_db1bc5bb","line":73,"range":{"start_line":66,"start_character":0,"end_line":73,"end_character":50},"updated":"2026-06-15 17:35:25.000000000","message":"by the way i belive you can just use self._resize_server and self._confirm_resize\n\nhttps://github.com/openstack/nova/blob/master/nova/tests/functional/integrated_helpers.py#L616-L630\n\n\nthis will work as well but you dont need to repati it since your inclduign the integrated helpers mixin","commit_id":"7eb47edeaa40151af1fbcebc2e8da35c10fff05d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90d77bf85f8c089f86bfaf6db8a8e5409d9819d8","unresolved":false,"context_lines":[{"line_number":79,"context_line":"        host1.stop()"},{"line_number":80,"context_line":"        host1_service \u003d self.api.get_services("},{"line_number":81,"context_line":"            binary\u003d\u0027nova-compute\u0027, host\u003d\u0027host1\u0027)[0]"},{"line_number":82,"context_line":"        self.api.api_delete(\u0027/os-services/%s\u0027 % host1_service[\u0027id\u0027])"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"        # Recreate host1 using restart_compute_service, which starts a"},{"line_number":85,"context_line":"        # brand new compute service on the same host.  This creates a"}],"source_content_type":"text/x-python","patch_set":2,"id":"5da0da75_bb963b63","line":82,"updated":"2026-06-15 17:35:25.000000000","message":"ok in thory the compute is empty so this is valid to do\n\nthis will remove the placement rp and clean up any stall allcoation as well as soft deleting the ocmpute node recored in the db as you noted.","commit_id":"7eb47edeaa40151af1fbcebc2e8da35c10fff05d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90d77bf85f8c089f86bfaf6db8a8e5409d9819d8","unresolved":true,"context_lines":[{"line_number":85,"context_line":"        # brand new compute service on the same host.  This creates a"},{"line_number":86,"context_line":"        # new active service row (higher ID) while the stale soft-deleted"},{"line_number":87,"context_line":"        # row remains."},{"line_number":88,"context_line":"        self.restart_compute_service(host1)"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"        # Sanity check: 3 total service rows (host1 deleted, host1 active,"},{"line_number":91,"context_line":"        # host2 active)."}],"source_content_type":"text/x-python","patch_set":2,"id":"cf807428_4f2d90ea","line":88,"updated":"2026-06-15 17:35:25.000000000","message":"form a nova presepctive we are now creat a new comptue node that happens to have the same host/hypervior hostname as a differnt one that existed perviously.","commit_id":"7eb47edeaa40151af1fbcebc2e8da35c10fff05d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90d77bf85f8c089f86bfaf6db8a8e5409d9819d8","unresolved":true,"context_lines":[{"line_number":121,"context_line":"        self.assertEqual(2, len(instance.services))"},{"line_number":122,"context_line":"        deleted_services \u003d ["},{"line_number":123,"context_line":"            svc for svc in instance.services if svc.deleted]"},{"line_number":124,"context_line":"        self.assertEqual(1, len(deleted_services))"}],"source_content_type":"text/x-python","patch_set":2,"id":"8c3138e4_26d911b9","line":124,"updated":"2026-06-15 17:35:25.000000000","message":"ack so yes this confirms the bug","commit_id":"7eb47edeaa40151af1fbcebc2e8da35c10fff05d"}]}
