)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":30002,"name":"Douglas Viroel","email":"viroel@gmail.com","username":"dviroel"},"change_message_id":"a792ea43b1a20a8596ea83cac194c634db4f4ffc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"b592e556_398ec1a3","updated":"2026-11-09 21:42:12.000000000","message":"needs depends-on nova change + tempest tests","commit_id":"7c9e0861a95dc6f0758205370b6bfc211be353e2"}],"doc/source/actions/migrate.rst":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"b2f8f3e26cffcab4008a8651530f75b1837b7fef","unresolved":false,"context_lines":[{"line_number":23,"context_line":""},{"line_number":24,"context_line":".. note::"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    Nova API version must be 2.56 or above if ``destination_node`` parameter"},{"line_number":27,"context_line":"    is given, and 2.105 or above if ``destination_az`` is given."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Configuration"}],"source_content_type":"text/x-rst","patch_set":1,"id":"7fcf0e8c_fcb82089","line":26,"updated":"2026-11-09 22:19:54.000000000","message":"pre_condition() fails the action when repin_availability_zone is set and the configured Nova API version is below 2.104, and the method docstring lists this failing condition, but the operator documentation never states the 2.104 requirement: the introductory note lists only 2.56 for destination_node and 2.105 for destination_az, the failing-conditions list omits the repin microversion case, and the release note documents only the destination requirement for the new parameter.\n\n**Severity**: SUGGESTION | **Confidence**: 0.85\n\n**Impact**: Operators running Nova below 2.104 who enable repin_availability_zone together with destination_node (the only destination type that does not already require 2.105) find no documented microversion requirement; their action plans fail in pre_condition with a runtime error message naming 2.104. Impact is limited because the failure message itself is self-explanatory.\n\n**Recommendation**:\nExtend the note in migrate.rst to cover repin_availability_zone (e.g. \u0027and 2.104 or above if repin_availability_zone is given\u0027), add a failing-condition bullet for repin below 2.104, and mention the 2.104 requirement next to the destination requirement in the release note entry.","commit_id":"7c9e0861a95dc6f0758205370b6bfc211be353e2"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"67936c218bf3fb1a36ab09fdc77a4396456d2ce7","unresolved":false,"context_lines":[{"line_number":64,"context_line":"original pin is restored. Servers that are unpinned, or already pinned to"},{"line_number":65,"context_line":"the destination zone, migrate unchanged."},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"``repin_availability_zone`` requires either ``destination_node`` or"},{"line_number":68,"context_line":"``destination_az``, since otherwise there is no zone to repin to. It"},{"line_number":69,"context_line":"defaults to false."},{"line_number":70,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"beb98a47_8cc66278","line":67,"updated":"2026-11-10 12:37:19.000000000","message":"pre_condition fails when repin_availability_zone is set and the configured Nova API is below the unpin microversion 2.104 (migration.py:392-402; listed in the docstring at migration.py:370). The new documentation states only the 2.105 requirement for destination_az (migrate.rst:88-89) and, in the pinned-zones section, only that repin requires a destination (migrate.rst:67-69); the failing-conditions list (migrate.rst:84-90) has no entry for the 2.104 case. The release note likewise omits the microversion.\n\n**Severity**: SUGGESTION | **Confidence**: 0.85\n\n**Impact**: Operators running a cloud below Nova microversion 2.104 cannot determine from the documentation why repin_availability_zone actions fail in pre_condition, nor which [nova]/api_version to configure; the release note ships the same gap to upgrade consumers.\n\n**Recommendation**:\nState in the \u0027Pinned availability zones\u0027 section and the failing-conditions list of doc/source/actions/migrate.rst, and in the release note entry, that repin_availability_zone requires Nova API microversion 2.104 or above.","commit_id":"25a07230beee24f3d2ef2af8f2a1fb2b31b2f147"}],"watcher/applier/actions/migration.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"b2f8f3e26cffcab4008a8651530f75b1837b7fef","unresolved":false,"context_lines":[{"line_number":312,"context_line":""},{"line_number":313,"context_line":"        result \u003d self._move()"},{"line_number":314,"context_line":""},{"line_number":315,"context_line":"        if result is None:"},{"line_number":316,"context_line":"            # migrate() signals failure by returning None; restore the pin."},{"line_number":317,"context_line":"            LOG.warning("},{"line_number":318,"context_line":"                \"Migration failed; restoring AZ pin \u0027%s\u0027 for instance %s\","}],"source_content_type":"text/x-python","patch_set":1,"id":"7152f631_0c71e6f9","line":315,"updated":"2026-11-09 22:19:54.000000000","message":"In _execute_with_repin(), the failure branch is selected with \u0027if result is None:\u0027, backed by the comment \u0027migrate() signals failure by returning None\u0027. However, NovaHelper.live_migrate_instance() and NovaHelper.watcher_non_live_migrate_instance() report their common, non-exception failure paths by returning False (retry timeout without a host change, instance entering ERROR, instance vanishing, cold migration failing). When a repin migration fails this way, the pin has already been cleared, the code falls through to the success branch, and it pins the server to the destination zone it never reached.\n\n**Severity**: HIGH | **Confidence**: 0.92\n\n**Impact**: On any migration that fails by returning False (a retry timeout, an instance ending in ERROR, or a cold migration that never completes), the server is left with pinned_availability_zone set to the destination zone while still running in its source zone. The promised rollback never runs, Nova holds incorrect placement state for that server, and later moves of it are constrained against the wrong zone. The state is recoverable only by a manual unpin, so the change incorrectly completes a supported operation and leaves recoverably incorrect state.\n\n**Priority**: Before merge\n**Recommendation**:\nTreat any falsy migration result as failure: replace \u0027if result is None:\u0027 with \u0027if not result:\u0027 in _execute_with_repin() and correct the accompanying comment. Add a regression test where live_migrate_instance (or watcher_non_live_migrate_instance) returns False after the unpin and assert the original pin is restored and no destination-zone pin is set.","commit_id":"7c9e0861a95dc6f0758205370b6bfc211be353e2"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"67936c218bf3fb1a36ab09fdc77a4396456d2ce7","unresolved":false,"context_lines":[{"line_number":312,"context_line":""},{"line_number":313,"context_line":"        result \u003d self._move()"},{"line_number":314,"context_line":""},{"line_number":315,"context_line":"        if result is None:"},{"line_number":316,"context_line":"            # migrate() signals failure by returning None; restore the pin."},{"line_number":317,"context_line":"            LOG.warning("},{"line_number":318,"context_line":"                \"Migration failed; restoring AZ pin \u0027%s\u0027 for instance %s\","}],"source_content_type":"text/x-python","patch_set":2,"id":"70896848_909dc288","line":315,"updated":"2026-11-10 12:37:19.000000000","message":"_execute_with_repin restores the original pin only when _move() returns None (migration.py:315-316; the comment says migrate() signals failure by returning None). The migration helpers return False, not None, when Nova accepted the request but the migration did not complete: live_migrate_instance returns False when the instance never reaches the destination host (nova_helper.py:1081-1089 for a scheduler-chosen host, :1108 for a named host), and watcher_non_live_migrate_instance returns False when cold migration fails (nova_helper.py:922-923). With result False the flow skips the restore and executes migration.py:339, pinning the server to destination_az while it is still on the source host.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Impact**: When a migration is accepted but fails afterwards - the normal outcome for a failed cold migration or a live migration that fails mid-move, which is expected while draining to a zone with no viable host - the action pins the server to the zone it never reached, contradicting the documented restore guarantee. The applier then marks the action failed (workflow_engine/default.py:164-173) and taskflow reverts it; revert() migrates back toward source_node, which Nova rejects because the server is pinned to the destination zone, so the rollback fails too and the wrong pin persists until manually removed.\n\n**Priority**: Before merge\n**Recommendation**:\nRestore the original pin whenever the migration did not succeed: use a truthiness check (\u0027if not result:\u0027) instead of \u0027result is None\u0027 so both False and None restore the pin, restore it also when _move() raises, and guard the post-migration pin update like the failure-path restore at migration.py:322-331. Extend test_execute_repin_migration_failure_restores_pin with a case where the helper returns False.","commit_id":"25a07230beee24f3d2ef2af8f2a1fb2b31b2f147"}]}
