Skip to content

Migrating the Cumulus provider from NCLU to NVUE.#76

Open
ybettan wants to merge 1 commit into
ansible-network:develfrom
ybettan:devel
Open

Migrating the Cumulus provider from NCLU to NVUE.#76
ybettan wants to merge 1 commit into
ansible-network:develfrom
ybettan:devel

Conversation

@ybettan

@ybettan ybettan commented Jun 7, 2026

Copy link
Copy Markdown

Cumulus Linux 5.x replaced NCLU (net add/del) with NVUE (nv set/unset) as the primary CLI. The nclu Ansible module used by the existing provider is deprecated and fails with deserialization errors on ansible-core 2.20+.

This commit updates all Cumulus provider task files to use NVUE commands via the raw module:

  • create_vlan: nv set bridge domain br_default vlan
  • delete_vlan: nv unset bridge domain br_default vlan
  • conf_access_port: nv set interface ... bridge domain br_default access
  • conf_trunk_port: nv set interface ... bridge domain br_default
  • delete_port: nv unset interface ... bridge domain + link state down

Additionally, add_trunk_vlan and delete_trunk_vlan which were previously unimplemented ("not implimented") are now functional using NVUE.

Tested against Cumulus VX 5.3.0 in a Containerlab environment.

Cumulus Linux 5.x replaced NCLU (`net add/del`) with NVUE (`nv set/unset`)
as the primary CLI. The `nclu` Ansible module used by the existing provider
is deprecated and fails with deserialization errors on ansible-core 2.20+.

This commit updates all Cumulus provider task files to use NVUE commands
via the `raw` module:
- create_vlan: `nv set bridge domain br_default vlan`
- delete_vlan: `nv unset bridge domain br_default vlan`
- conf_access_port: `nv set interface ... bridge domain br_default access`
- conf_trunk_port: `nv set interface ... bridge domain br_default`
- delete_port: `nv unset interface ... bridge domain` + link state down

Additionally, `add_trunk_vlan` and `delete_trunk_vlan` which were previously
unimplemented ("not implimented") are now functional using NVUE.

Tested against Cumulus VX 5.3.0 in a Containerlab environment.

Signed-off-by: Yoni Bettan <yonibettan@gmail.com>
@centosinfra-prod-github-app

Copy link
Copy Markdown

Build failed.
https://gateway-cloud-softwarefactory.apps.ocp.cloud.ci.centos.org/zuul/t/ansible/buildset/2185a5bb36b245f2ae53d1d00b55e478

ansible-tox-py36 NODE_FAILURE Node(set) request 200-0000113253 failed in 0s
ansible-tox-py38 FAILURE in 11m 41s
ansible-tox-py39 FAILURE in 11m 58s
✔️ ansible-tox-linters SUCCESS in 6m 07s

@ybettan

ybettan commented Jun 8, 2026

Copy link
Copy Markdown
Author

There tests are passing locally:

ybettan network-runner (devel) $ python3 -m pytest tests/ -v
============================================================ test session starts ============================================================
platform linux -- Python 3.14.4, pytest-9.0.3, pluggy-1.6.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/ybettan/go/src/github.com/ansible-network/network-runner
plugins: cov-7.1.0, anyio-4.12.1
collected 80 items

tests/unit/test_api.py::TestGetHost::test_get_host PASSED                                                                             [  1%]
tests/unit/test_api.py::TestGetHost::test_get_host_by_ansible_host PASSED                                                             [  2%]
tests/unit/test_api.py::TestGetHost::test_get_host_fail PASSED                                                                        [  3%]
tests/unit/test_api.py::TestAddHost::test_add_host PASSED                                                                             [  5%]
tests/unit/test_api.py::TestAddHost::test_add_host_fail PASSED                                                                        [  6%]
tests/unit/test_api.py::TestCreateDeleteVlan::test_create_vlan PASSED                                                                 [  7%]
tests/unit/test_api.py::TestCreateDeleteVlan::test_delete_vlan PASSED                                                                 [  8%]
tests/unit/test_api.py::TestRun::test_run PASSED                                                                                      [ 10%]
tests/unit/test_api.py::TestRun::test_run_task_failures PASSED                                                                        [ 11%]
tests/unit/test_api.py::TestPlay::test_play PASSED                                                                                    [ 12%]
tests/unit/test_api.py::TestConfAccessPort::test_assign_access_port PASSED                                                            [ 13%]
tests/unit/test_api.py::TestConfAccessPort::test_assign_access_port_w_stp_edge PASSED                                                 [ 15%]
tests/unit/test_api.py::TestConfAccessPort::test_remove_access_port PASSED                                                            [ 16%]
tests/unit/test_api.py::TestConfAccessPort::test_remove_access_port_raises PASSED                                                     [ 17%]
tests/unit/test_api.py::TestConfTrunkPort::test_assign_trunk_port PASSED                                                              [ 18%]
tests/unit/test_api.py::TestConfTrunkPort::test_assign_trunk_port_w_stp_edge PASSED                                                   [ 20%]
tests/unit/test_api.py::TestConfTrunkPort::test_remove_trunk_port PASSED                                                              [ 21%]
tests/unit/test_api.py::TestConfTrunkPort::test_remove_trunk_port_raises PASSED                                                       [ 22%]
tests/unit/test_api.py::TestListVlans::test_list_vlans PASSED                                                                         [ 23%]
tests/unit/test_api.py::TestAddDeleteTrunkVlan::test_add_trunk_vlan PASSED                                                            [ 25%]
tests/unit/test_api.py::TestAddDeleteTrunkVlan::test_delete_trunk_vlan PASSED                                                         [ 26%]
tests/unit/test_helpers.py::test_isvalidattrname PASSED                                                                               [ 27%]
tests/unit/test_resources.py::TestResourcesInventory::test_child_vars_kwargs PASSED                                                   [ 28%]
tests/unit/test_resources.py::TestResourcesInventory::test_empty_child PASSED                                                         [ 30%]
tests/unit/test_resources.py::TestResourcesInventory::test_empty_host PASSED                                                          [ 31%]
tests/unit/test_resources.py::TestResourcesInventory::test_empty_inventory PASSED                                                     [ 32%]
tests/unit/test_resources.py::TestResourcesInventory::test_host_attrs PASSED                                                          [ 33%]
tests/unit/test_resources.py::TestResourcesInventory::test_host_attrs_alias PASSED                                                    [ 35%]
tests/unit/test_resources.py::TestResourcesInventory::test_host_invalid_ansible_network_os PASSED                                     [ 36%]
tests/unit/test_resources.py::TestResourcesInventory::test_host_vars PASSED                                                           [ 37%]
tests/unit/test_resources.py::TestResourcesInventory::test_host_vars_kwargs PASSED                                                    [ 38%]
tests/unit/test_resources.py::TestResourcesAnsiblePlaybook::test_empty_play PASSED                                                    [ 40%]
tests/unit/test_resources.py::TestResourcesAnsiblePlaybook::test_empty_playbook PASSED                                                [ 41%]
tests/unit/test_resources.py::TestResourcesAnsiblePlaybook::test_noop_task PASSED                                                     [ 42%]
tests/unit/test_resources.py::test_serialize_deserialize PASSED                                                                       [ 43%]
tests/unit/types/test_attrs.py::test_create_attribute_defaults PASSED                                                                 [ 45%]
tests/unit/types/test_attrs.py::test_str_attribute PASSED                                                                             [ 46%]
tests/unit/types/test_attrs.py::test_bool_attribute PASSED                                                                            [ 47%]
tests/unit/types/test_attrs.py::test_int_attribute PASSED                                                                             [ 48%]
tests/unit/types/test_attrs.py::test_list_attribute PASSED                                                                            [ 50%]
tests/unit/types/test_attrs.py::test_dict_attribute PASSED                                                                            [ 51%]
tests/unit/types/test_attrs.py::test_attribute_requires_type PASSED                                                                   [ 52%]
tests/unit/types/test_attrs.py::test_invalid_default_type PASSED                                                                      [ 53%]
tests/unit/types/test_attrs.py::test_call_list_with_default_value PASSED                                                              [ 55%]
tests/unit/types/test_attrs.py::test_call_dict_with_default_value PASSED                                                              [ 56%]
tests/unit/types/test_attrs.py::test_typeddict_container PASSED                                                                       [ 57%]
tests/unit/types/test_attrs.py::test_typedlist_container PASSED                                                                       [ 58%]
tests/unit/types/test_attrs.py::test_enums PASSED                                                                                     [ 60%]
tests/unit/types/test_attrs.py::test_bad_serialize_when_value PASSED                                                                  [ 61%]
tests/unit/types/test_attrs.py::test_bad_value_type PASSED                                                                            [ 62%]
tests/unit/types/test_attrs.py::test_typeddict_missing_item_key PASSED                                                                [ 63%]
tests/unit/types/test_containers.py::test_index PASSED                                                                                [ 65%]
tests/unit/types/test_containers.py::test_index_comparisons PASSED                                                                    [ 66%]
tests/unit/types/test_containers.py::test_map PASSED                                                                                  [ 67%]
tests/unit/types/test_containers.py::test_map_comparisons PASSED                                                                      [ 68%]
tests/unit/types/test_objects.py::test_instance PASSED                                                                                [ 70%]
tests/unit/types/test_objects.py::test_set_strattr PASSED                                                                             [ 71%]
tests/unit/types/test_objects.py::test_set_intattr PASSED                                                                             [ 72%]
tests/unit/types/test_objects.py::test_set_boolattr PASSED                                                                            [ 73%]
tests/unit/types/test_objects.py::test_set_listattr PASSED                                                                            [ 75%]
tests/unit/types/test_objects.py::test_set_dictattr PASSED                                                                            [ 76%]
tests/unit/types/test_objects.py::test_del_strattr PASSED                                                                             [ 77%]
tests/unit/types/test_objects.py::test_del_intattr PASSED                                                                             [ 78%]
tests/unit/types/test_objects.py::test_del_boolattr PASSED                                                                            [ 80%]
tests/unit/types/test_objects.py::test_del_listattr PASSED                                                                            [ 81%]
tests/unit/types/test_objects.py::test_del_dictattr PASSED                                                                            [ 82%]
tests/unit/types/test_objects.py::test_strattr_with_defaults PASSED                                                                   [ 83%]
tests/unit/types/test_objects.py::test_intattr_with_defaults PASSED                                                                   [ 85%]
tests/unit/types/test_objects.py::test_boolattr_with_defaults PASSED                                                                  [ 86%]
tests/unit/types/test_objects.py::test_listattr_with_defaults PASSED                                                                  [ 87%]
tests/unit/types/test_objects.py::test_dictattr_with_defaults PASSED                                                                  [ 88%]
tests/unit/types/test_objects.py::test_object_init_with_values PASSED                                                                 [ 90%]
tests/unit/types/test_objects.py::test_object_with_required_attr PASSED                                                               [ 91%]
tests/unit/types/test_objects.py::test_attr1_alias PASSED                                                                             [ 92%]
tests/unit/types/test_validators.py::test_choice_validator_pass PASSED                                                                [ 93%]
tests/unit/types/test_validators.py::test_choice_validator_fail PASSED                                                                [ 95%]
tests/unit/types/test_validators.py::test_range_validator_pass PASSED                                                                 [ 96%]
tests/unit/types/test_validators.py::test_range_validator_fail PASSED                                                                 [ 97%]
tests/unit/types/test_validators.py::test_port_validator_pass PASSED                                                                  [ 98%]
tests/unit/types/test_validators.py::test_port_validator_fail PASSED                                                                  [100%]

============================================================ 80 passed in 0.10s =============================================================

/retest

Is this an infra issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant