Skip to content

Issue-406: Added changes for command timeouts (NDA-34) - #486

Open
jeetugangwar11 wants to merge 4 commits into
CiscoDevNet:developfrom
jeetugangwar11:issue_406_04082026
Open

Issue-406: Added changes for command timeouts (NDA-34)#486
jeetugangwar11 wants to merge 4 commits into
CiscoDevNet:developfrom
jeetugangwar11:issue_406_04082026

Conversation

@jeetugangwar11

@jeetugangwar11 jeetugangwar11 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Related Issue(s)

Fixes #406

Proposed Changes

  1. Remove timeout from nd_argument_spec() in nd_argument_specs.py.
  2. Remove the persistent_command_timeout assignment from nd.py
  3. Remove timeout and ND_TIMEOUT from the shared documentation fragment.

Now we can use timeout by providing below ways:

  1. By setting in playbook facts:
  • name: set facts
    ansible.builtin.set_fact:
    ansible_command_timeout: 100
  1. By playbook vars:
    vars:
    ansible_command_timeout: 300
  2. By adding below props in inventory:
    ansible_command_timeout=100
  3. By exporting variable:
    export ANSIBLE_PERSISTENT_COMMAND_TIMEOUT=300

NOTE:

Variable precedence order - module reads from:

  1. Playbook facts
  2. Playbook vars
  3. Inventory
  4. Env varialble ANSIBLE_PERSISTENT_COMMAND_TIMEOUT

Test Notes

I have added test case for the same.
I tested above precedence order in local by adding logs.

Cisco Nexus Dashboard Version

4.3.1

Related ND API Resource Category

NA

Checklist

  • Latest commit is rebased from develop with merge conflicts resolved
  • New or updates to documentation has been made accordingly
  • Assigned the proper reviewers

@mtarking mtarking changed the title [Jeet | issue-406] Added changes for command timeouts with ansible_co… Issue-406: Added changes for command timeouts Aug 6, 2026

@mtarking mtarking left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this — the core fix is exactly right and minimal: dropping the argspec timeout default that unconditionally clobbered persistent_command_timeout, and stopping the httpapi plugin from writing that option at all. test_nd_argument_specs.py ("timeout" not in spec) and the doc-fragment removal are good regression guards, and verify.timeout / persistent_connect_timeout are correctly left untouched.

Requesting changes on a few items before merge (details inline):

  1. set_fact: ansible_command_timeout may not reconfigure an already-open persistent socket — it's a connection var resolved at connection setup. The old timeout: applied per-request dynamically; this doesn't. Please verify the migrated targets still get the extended window, or move to play-level vars: / inventory [nd:vars] (as the interface and maintenance-mode targets do). Affects nd_backup, nd_backup_restore, nd_service, nd_service_instance, nd_rest/*, nd_vpc_pair/*.
  2. Scope regressionset_fact is play-lifetime and per-host; prefer block-scoped vars: to match the original module_defaults scoping. Also confirm the nd_vpc_pair change from nd_vpc_pair_module_timeout | default(600) to a hardcoded 90 is intended.
  3. Verify no residual timeout / ND_TIMEOUT readers#406 named nd.py/nd_v2.py; please grep to confirm nothing else (e.g. nd_v2.py, sender_nd.set_params(), action plugins) still reads the removed param.

Non-blocking:
4. The vrf_attachment_manager._delete_wait_timeout removal drops a user override of an internal wait ceiling — confirm the adaptive formula covers the large-delete cases it existed for.
5. test_httpapi.py has a tautological assertion and is missing a license/copyright header (sanity may flag it).

Once 1–3 are addressed this looks ready. Nice, well-scoped change overall.

# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
- name: Set vars
ansible.builtin.set_fact:
ansible_command_timeout: 90 # Backup tasks commonly require 10-15 minutes or more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: ansible_command_timeout is a connection variable read by ansible-connection when the persistent socket is initialized. Setting it via set_fact after an ND task has already opened the persistent connection may not reconfigure the already-running socket, so the effective persistent_command_timeout can stay at the default 30s.

The old timeout: 90 worked because the httpapi plugin called connection.set_option("persistent_command_timeout", ...) on every request (dynamic). That path is now gone, so timing here depends entirely on native connection-var resolution.

Please confirm empirically that a >30s operation in this target still gets the extended window. If not, move this to play-level vars: / inventory [nd:vars] (as the maintenance-mode and interface targets already do), which is resolved at connection setup and is reliable. Same concern applies to the other set_fact: ansible_command_timeout targets: nd_backup_restore, nd_service, nd_service_instance, nd_rest/*, and nd_vpc_pair/*.


- name: DELETE - Set nd_info defaults
ansible.builtin.set_fact:
ansible_command_timeout: 90

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scope regression: set_fact persists for the remainder of the play and is per-host, whereas the replaced module_defaults:/inline timeout: was scoped to this specific task file. The block-scoped vars: conversions elsewhere in this PR (e.g. nd_interface_port_channel_*, nd_maintenance_mode) preserve the original scoping and are the better pattern.

Recommend converting these set_fact cases to block/task-scoped vars: for consistency and to avoid leaking a long timeout into unrelated later tasks. Also note this previously honored nd_vpc_pair_module_timeout | default(600) — the new hardcoded 90 drops that override knob and lowers the ceiling from 600→90; confirm that's intended.


httpapi.send_request("GET", "/api/v1/test")

assert connection.get_option("persistent_command_timeout") == 1000

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion is tautological: connection.get_option is wired to options.get via side_effect, so it returns 1000 regardless of the plugin's behavior — it doesn't prove anything. The meaningful check is the next line (that set_option was never called with persistent_command_timeout). Suggest dropping this line or replacing it with something that verifies the plugin left the option untouched.

Also: this new file has no GPL/copyright header, unlike the other test files — ansible-test sanity will likely flag a missing license/copyright header. Please add one at the top.

time.sleep(self.delete_wait_delay)

def _delete_wait_timeout(self, module_args: dict, item_count: int) -> int:
explicit_timeout = module_args.get("timeout")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes a real user override, not just a connection timeout: previously an explicit module timeout raised the internal delete-wait ceiling. That's internal query/retry behavior — arguably the same category as verify.timeout, which #406 said to leave unchanged. Removing the argspec key forces this branch to change (it'd always be None), so the edit is justified, but please confirm the adaptive formula min(900, 30 + extra_chunks * delete_wait_delay) actually covers the large-VRF-delete cases this override existed for. The new unit test asserts the formula but not the dropped-override intent.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @AKDRG

@AKDRG AKDRG Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removal of explicit_timeout is acceptable. However, the adaptive formula needs more tuning and seems insufficient when scale increases. I have opened #492 for tracking and fixing it.

"username": {"type": "str", "fallback": (env_fallback, ["ND_USERNAME", "ANSIBLE_NET_USERNAME"])},
"password": {"type": "str", "required": False, "no_log": True, "fallback": (env_fallback, ["ND_PASSWORD", "ANSIBLE_NET_PASSWORD"])},
"output_level": {"type": "str", "default": "normal", "choices": ["debug", "info", "normal"], "fallback": (env_fallback, ["ND_OUTPUT_LEVEL"])},
"timeout": {"type": "int", "default": 30, "fallback": (env_fallback, ["ND_TIMEOUT"])},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the argspec key is the right fix. One verification request: issue #406 explicitly named plugins/module_utils/nd.py and nd_v2.py. This PR changes nd_argument_specs.py (the current shared source) but I don't see those files touched. Please grep the tree for timeout and ND_TIMEOUT to confirm nothing else still reads the removed param — e.g. nd_v2.py, action plugins, or sender_nd.set_params() — so it can't silently resolve to None/absent at runtime.

@allenrobel allenrobel left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review

One docstring-consistency finding, inline below.

🤖 Generated with Claude Code

@@ -33,7 +33,7 @@ def test_nd_argument_specs_00000() -> None:

- The key set matches the historical spec from nd.py exactly

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bullet ("The key set matches the historical spec from nd.py exactly") is now stale: with timeout removed from the asserted key set (and the bullet two lines below updated to say the option is absent), the key set intentionally no longer matches the historical nd.py spec exactly. Suggest rewording, e.g. "The key set matches the historical spec from nd.py, minus the removed timeout option".

@mtarking mtarking added 2.0.0 Release 2.0.0 ready for review Submitter is requesting a PR review nac01 NaC ND release 0.0.1 jira-sync Sync this issue to Jira nda-project Move this issue to the NDA project labels Aug 7, 2026
@github-actions github-actions Bot changed the title Issue-406: Added changes for command timeouts Issue-406: Added changes for command timeouts (DCNE-883) Aug 7, 2026
@dcne-automation dcne-automation changed the title Issue-406: Added changes for command timeouts (DCNE-883) Issue-406: Added changes for command timeouts (NDA-34) Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.0.0 Release 2.0.0 jira-sync Sync this issue to Jira nac01 NaC ND release 0.0.1 nda-project Move this issue to the NDA project ready for review Submitter is requesting a PR review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove ND_TIMEOUT/module timeout override and use ANSIBLE_PERSISTENT_COMMAND_TIMEOUT

6 participants