Giter VIP home page Giter VIP logo

dellemc.enterprise_sonic's Introduction

Ansible Network Collection for Enterprise SONiC Distribution by Dell Technologies

This collection includes Ansible core modules, network resource modules, and plugins needed to provision and manage Dell EMC PowerSwitch platforms running Enterprise SONiC Distribution by Dell Technologies. Sample playbooks and documentation are also included to show how the collection can be used.

Supported connections

The SONiC Ansible collection supports network_cli and httpapi connections.

Plugins

CLICONF plugin

Name Description
network_cli Use Ansible CLICONF to run commands on Enterprise SONiC

HTTPAPI plugin

Name Description
httpapi Use Ansible HTTPAPI to run commands on Enterprise SONiC

Collection core modules

Name Description Connection type
sonic_command Run commands through the Management Framework CLI network_cli
sonic_config Manage configuration through the Management Framework CLI network_cli
sonic_api Perform REST operations through the Management Framework REST API httpapi

Collection network resource modules

Listed are the SONiC Ansible network resource modules which need httpapi as the connection type. Supported operations are merged, deleted, replaced and overridden.

Name Description
sonic_aaa Manage AAA and its parameters
sonic_acl_interfaces Manage access control list (ACL) to interface binding
sonic_bfd Manage BFD configuration
sonic_bgp Manage global BGP and its parameters
sonic_bgp_af Manage global BGP address-family and its parameters
sonic_bgp_as_paths Manage BGP autonomous system path (or as-path-list) and its parameters
sonic_bgp_communities Manage BGP community and its parameters
sonic_bgp_ext_communities Manage BGP extended community-list and its parameters
sonic_bgp_neighbors Manage a BGP neighbor and its parameters
sonic_bgp_neighbors_af Manage the BGP neighbor address-family and its parameters
sonic_copp Manage CoPP configuration
sonic_dhcp_relay Manage DHCP and DHCPv6 relay configurations
sonic_dhcp_snooping Manage DHCP Snooping
sonic_interfaces Configure Interface attributes
sonic_ip_neighbor Manage IP neighbor global configuration
sonic_l2_acls Manage Layer 2 access control lists (ACL) configurations
sonic_l2_interfaces Configure interface-to-VLAN association
sonic_l3_acls Manage Layer 3 access control lists (ACL) configurations
sonic_l3_interfaces Configure the IPv4 and IPv6 parameters on Interfaces
sonic_lag_interfaces Manage link aggregation group (LAG) interface parameters
sonic_lldp_global Manage Global LLDP configurations
sonic_logging Manage logging configuration
sonic_mac Manage MAC configuration
sonic_mclag Manage multi chassis link aggregation groups domain (MCLAG) and its parameters
sonic_ntp Manage NTP configuration
sonic_pki Manages PKI attributes
sonic_port_breakout Configure port breakout settings on physical interfaces
sonic_port_group Manage port group configuration
sonic_prefix_lists Manage prefix list configuration
sonic_radius_server Manage RADIUS server and its parameters
sonic_route_maps Manage route map configuration
sonic_static_routes Manage static routes configuration
sonic_stp Manage STP configuration
sonic_system Configure system parameters
sonic_tacacs_server Manage TACACS server and its parameters
sonic_users Manage users and its parameters
sonic_vlan_mapping Configure vlan mappings
sonic_vlans Manage VLAN and its parameters
sonic_vrfs Manage VRFs and associate VRFs to interfaces
sonic_vxlans Manage VxLAN EVPN and its parameters

Sample use case playbooks

The playbooks directory includes this sample playbook that show end-to-end use cases.

Name Description
BGP Layer 3 fabric Example playbook to build a Layer 3 leaf-spine fabric

Version compatibility

  • Recommended Ansible version 2.14 or higher (This is required for enterprise_sonic collection version >= 2.4.0).
  • Enterprise SONiC Distribution by Dell Technologies version 3.1 or higher
  • Recommended Python 3.9 or higher (This is required for enterprise_sonic collection version >= 2.4.0.).
  • Dell Enterprise SONiC images for releases 3.1 - 3.5: Use Ansible Enterprise SONiC collection version 1.1.0 or later 1.m.n versions (from the 1.x branch of this repo)
  • Dell Enterprise SONiC images for release 4.0 and later 4.x.y releases: Use Ansible Enterprise SONiC collection version 2.0.0 or later 2.m.n releases (from the "2.x" branch of this repo).
  • In general: Dell Enterprise SONiC release versions "R.x.y" are supported by Ansible Enterprise SONiC collection versions "R-2.m.n" on branch "R-2.x".

NOTE: Community SONiC versions that include the Management Framework container should work as well, however, this collection has not been tested nor validated with community versions and is not supported.

Installation of Ansible 2.11+

Dependencies for Ansible Enterprise SONiC collection
  pip3 install paramiko>=2.7
  pip3 install jinja2>=2.8
  pip3 install ansible-core

Installation of Ansible 2.10+

Dependencies for Ansible Enterprise SONiC collection
  pip3 install paramiko>=2.7
  pip3 install jinja2>=2.8
  pip3 install ansible-base

Installation of Ansible 2.9

Dependencies for Ansible Enterprise SONiC collection
  pip3 install paramiko>=2.7
  pip3 install jinja2>=2.8
  pip3 install ansible
Setting Environment Variables

To use the Enterprise SONiC collection in Ansible 2.9, it is required to add one of the two available environment variables.

Option 1: Add the environment variable while running the playbook.

  ANSIBLE_NETWORK_GROUP_MODULES=sonic ansible-playbook sample_playbook.yaml -i inventory.ini

Option 2: Add the environment variable in user profile.

  ANSIBLE_NETWORK_GROUP_MODULES=sonic

Installation of Enterprise SONiC collection from Ansible Galaxy

Install the latest version of the Enterprise SONiC collection from Ansible Galaxy.

  ansible-galaxy collection install dellemc.enterprise_sonic

To install a specific version, specify a version range identifier. For example, to install the most recent version that is greater than or equal to 1.0.0 and less than 2.0.0.

  ansible-galaxy collection install 'dellemc.enterprise_sonic:>=1.0.0,<2.0.0'

Sample playbooks

VLAN configuration using CLICONF

sonic_network_cli.yaml

---

- name: SONiC Management Framework CLI configuration examples
  hosts: sonic_switches
  gather_facts: no
  connection: network_cli
  tasks:
    - name: Add VLAN entry
      dellemc.enterprise_sonic.sonic_config:
        commands: ['interface Vlan 700','exit']
        save: yes
      register: config_op
    - name: Test SONiC single command
      dellemc.enterprise_sonic.sonic_command:
        commands: 'show vlan'
      register: cmd_op

VLAN configuration using HTTPAPI

sonic_httpapi.yaml

---

- name: SONiC Management Framework REST API examples
  hosts: sonic_switches
  gather_facts: no
  connection: httpapi
  tasks:
    - name: Perform PUT operation to add a VLAN network instance
      dellemc.enterprise_sonic.sonic_api:
        url: data/openconfig-network-instance:network-instances/network-instance=Vlan100
        method: "PUT"
        body: {"openconfig-network-instance:network-instance": [{"name": "Vlan100","config": {"name": "Vlan100"}}]}
        status_code: 204
    - name: Perform GET operation to view VLAN network instance
      dellemc.enterprise_sonic.sonic_api:
        url: data/openconfig-network-instance:network-instances/network-instance=Vlan100
        method: "GET"
        status_code: 200
      register: api_op

Configuration using network resource modules

sonic_resource_modules.yaml

---

- name: VLANs, Layer 2 and Layer 3 interfaces configuration using Enterprise SONiC resource modules
  hosts: sonic_switches
  gather_facts: no
  connection: httpapi
  tasks:
   - name: Configure VLANs
     dellemc.enterprise_sonic.sonic_vlans:
        config:
         - vlan_id: 701
         - vlan_id: 702
         - vlan_id: 703
         - vlan_id: 704
        state: merged
     register: sonic_vlans_output
   - name: Configure Layer 2 interfaces
     dellemc.enterprise_sonic.sonic_l2_interfaces:
        config:
        - name: Eth1/2
          access:
            vlan: 701
          trunk:
            allowed_vlans:
              - vlan: 702
              - vlan: 703
        state: merged
     register: sonic_l2_interfaces_output
   - name: Configure Layer 3 interfaces
     dellemc.enterprise_sonic.sonic_l3_interfaces:
       config:
        - name: Eth1/3
          ipv4:
            - address: 8.1.1.1/16
          ipv6:
            - address: 3333::1/16
       state: merged
     register: sonic_l3_interfaces_output

host_vars/sonic_sw1.yaml

hostname: sonic_sw1

# Common parameters for connection type httpapi or network_cli:
ansible_user: xxxx
ansible_pass: xxxx
ansible_network_os: dellemc.enterprise_sonic.sonic

# Additional parameters for connection type httpapi:
ansible_httpapi_use_ssl: true
ansible_httpapi_validate_certs: false

inventory.ini

[sonic_sw1]
sonic_sw1 ansible_host=100.104.28.119

[sonic_sw2]
sonic_sw2 ansible_host=100.104.28.120

[sonic_switches:children]
sonic_sw1
sonic_sw2

Releasing, Versioning and Deprecation

This collection follows Semantic Versioning. More details on versioning can be found in the Ansible docs.

We plan to regularly release new minor or bugfix versions once new features or bugfixes have been implemented.

Enterprise SONiC Ansible Modules deprecation cycle is aligned with Ansible.

Source control branches on Github:

  • Released code versions are located on "release" branches with names of the form "M.x", where "M" specifies the "major" release version for releases residing on the branch.
  • Unreleased and pre-release code versions are located on sub-branches of the "main" branch. This is a development branch, and is not intended for use in production environments.

Code of Conduct

This repository adheres to the Ansible Community code of conduct

(c) 2020-2021 Dell Inc. or its subsidiaries. All Rights Reserved.

dellemc.enterprise_sonic's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dellemc.enterprise_sonic's Issues

Add BGP neighbor AF resource module support for the "fabric-external" configuration attribute

Describe the solution you'd like
Add the support for all defined Ansible playbook states for configuration handling of the "fabric-external" attribute for the l2vpn/evpn AFI/SAFI within the BGP neighbor AF resource module.

Describe alternatives you've considered
This attribute can currently be handled via CLI syntax within the sonic_config resource module, but the enhanced support via the REST API based BGP neighbor AF resource module is needed.

Additional context
Equivalent CLI invocation:

router bgp 30
  neighbor 1.2.3.4
    address-family l2vpn evpn 
       activate 
       fabric-external                     <<<<

Community Note

  • Please vote on this issue by adding a 👍 reaction
    to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions,
    they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

[BUG]: l3_interfaces.py fails when secondary: does not match between temp['secondary'] and ipv4['config']['secondary']

Bug Description

image

Fixed this locally by adding to line 93 and 94 of dellemc/enterprise_sonic/plugins/module_utils/network/sonic/facts/l3_interfaces/l3_interfaces.py:

secondary = ipv4['config'].get('secondary')
temp['secondary'] = secondary

Product Name

dellemc/enterprise_sonic/plugins/module_utils/network/sonic/facts/l3_interfaces/l3_interfaces.py

Component or Module Name

dellemc/enterprise_sonic/plugins/module_utils/network/sonic/facts/l3_interfaces/l3_interfaces.py

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.0.0

SONiC Software Version

4.0.2-Enterprise_Advanced

Configuration

none

Steps to Reproduce

In playbook we have:

  • name: Create L3 Interfaces
    sonic_l3_interfaces:
    config: "{{sonic_l3_interfaces}}"
    when: sonic_l3_interfaces is defined and sonic_l3_interfaces

the corresponding host_vars for sonic_l3_interfaces is:

sonic_l3_interfaces:

  • name: Vlan40
    ipv4:
    addresses:
    - address: 192.168.40.254/24
    - address: 192.168.40.251/24
    secondary: true

Expected Behavior

L3 interfaces do get configured correctly

Actual Behavior

but, when running playbook it errors out when secondary: does not match between temp['secondary'] and ipv4['config']['secondary']

Logs

unfortunately I don't have them

Screenshots

image

Additional Information

No response

[BUG]: sonic_bgp_neighbors changes encrypted password every time, even though unencrypted password is unchanged

Bug Description

When running a task that uses sonic_bgp_neighbors to create a neighbor with an unencrypted password, each and every subsequent run of the playbook will change the encrypted password, even though the unencrypted password remains unchanged.

Furthermore, even though --diff is being specified, no diff is being reported. (This may be a systemic issue as I've seen this behaviour in #361 and #359 as well.)

Product Name

SONiC-OS-4.2.0-Enterprise_Base

Component or Module Name

sonic_bgp_neighbors

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.4.0

SONiC Software Version

SONiC-OS-4.2.0-Enterprise_Base

Configuration

CONFIG_FILE() = /home/debian/ansible/ansible.cfg
DEFAULT_HASH_BEHAVIOUR(/home/debian/ansible/ansible.cfg) = merge
DEFAULT_HOST_LIST(/home/debian/ansible/ansible.cfg) = ['/home/debian/ansible/hosts.yml']
DEFAULT_JINJA2_EXTENSIONS(/home/debian/ansible/ansible.cfg) = jinja2.ext.do
HOST_KEY_CHECKING(/home/debian/ansible/ansible.cfg) = False
INTERPRETER_PYTHON(/home/debian/ansible/ansible.cfg) = auto_silent
MAX_FILE_SIZE_FOR_DIFF(/home/debian/ansible/ansible.cfg) = 1048576
PERSISTENT_COMMAND_TIMEOUT(/home/debian/ansible/ansible.cfg) = 3000

Steps to Reproduce

Run a playbook with the following tasks repeatedly:

    - name: Configure BGP
      dellemc.enterprise_sonic.sonic_bgp:
        config:
          - bgp_as: 1234
            router_id: 1.2.3.4

    - name: Configure BGP neighbors
      dellemc.enterprise_sonic.sonic_bgp_neighbors:
        config:
          - bgp_as: 1234
            peer_group:
              - name: ROUTESERVERS
                remote_as:
                  peer_type: external
                ebgp_multihop:
                  enabled: true
                auth_pwd:
                  pwd: secret123
                address_family:
                  afis:
                    - afi: ipv4
                      safi: unicast
                      activate: true
                      prefix_list_in: ROUTESERVERS-IN-IPV4
                      prefix_list_out: ROUTESERVERS-OUT-IPV4
                    - afi: ipv6
                      safi: unicast
                      activate: true
                      prefix_list_in: ROUTESERVERS-IN-IPV6
                      prefix_list_out: ROUTESERVERS-OUT-IPV6
            neighbors:
              - neighbor: 192.0.2.1
                peer_group: ROUTESERVERS

Expected Behavior

a. If the unencryped password does not change between subsequent runs, no changes should be reported (but ok)
b. The module should display a diff of the changes applied when ansible-playbook is run with --diff

Actual Behavior

a. Changes are reported and applied on each run
b. The module does not display a diff of the changes applied even though ansible-playbook is run with --diff

Logs

PLAY [ent_sonic] ***************************************************************

TASK [Configure BGP] ***********************************************************
ok: [leaf1] => {"before": [{"bestpath": {"as_path": {"confed": false, "ignore": false, "multipath_relax": false, "multipath_relax_as_set": false}, "compare_routerid": false, "med": {"always_compare_med": false, "confed": false, "missing_as_worst": false}}, "bgp_as": "1234", "log_neighbor_changes": true, "router_id": "1.2.3.4", "timers": {"holdtime": 180, "keepalive_interval": 60}, "vrf_name": "default"}], "changed": false, "commands": []}

TASK [Configure BGP neighbors] *************************************************
changed: [leaf1] => {"after": [{"bgp_as": "1234", "neighbors": [{"advertisement_interval": 0, "neighbor": "192.0.2.1", "passive": false, "peer_group": "ROUTESERVERS", "timers": {"connect_retry": 30, "keepalive": 60}}], "peer_group": [{"address_family": {"afis": [{"activate": true, "afi": "ipv4", "prefix_list_in": "ROUTESERVERS-IN-IPV4", "prefix_list_out": "ROUTESERVERS-OUT-IPV4", "safi": "unicast"}, {"activate": true, "afi": "ipv6", "prefix_list_in": "ROUTESERVERS-IN-IPV6", "prefix_list_out": "ROUTESERVERS-OUT-IPV6", "safi": "unicast"}]}, "advertisement_interval": 0, "auth_pwd": {"encrypted": true, "pwd": "U2FsdGVkX1+kCWpAUut3794ANoM6yEOOb10IJKbaDd8="}, "ebgp_multihop": {"enabled": true}, "name": "ROUTESERVERS", "passive": false, "remote_as": {"peer_type": "external"}, "timers": {"connect_retry": 30}}], "vrf_name": "default"}], "before": [{"bgp_as": "1234", "neighbors": [{"advertisement_interval": 0, "neighbor": "192.0.2.1", "passive": false, "peer_group": "ROUTESERVERS", "timers": {"connect_retry": 30, "keepalive": 60}}], "peer_group": [{"address_family": {"afis": [{"activate": true, "afi": "ipv4", "prefix_list_in": "ROUTESERVERS-IN-IPV4", "prefix_list_out": "ROUTESERVERS-OUT-IPV4", "safi": "unicast"}, {"activate": true, "afi": "ipv6", "prefix_list_in": "ROUTESERVERS-IN-IPV6", "prefix_list_out": "ROUTESERVERS-OUT-IPV6", "safi": "unicast"}]}, "advertisement_interval": 0, "auth_pwd": {"encrypted": true, "pwd": "U2FsdGVkX182G0luRsxMaMbz3fRxupYoP5NZRA2QNkY="}, "ebgp_multihop": {"enabled": true}, "name": "ROUTESERVERS", "passive": false, "remote_as": {"peer_type": "external"}, "timers": {"connect_retry": 30}}], "vrf_name": "default"}], "changed": true, "commands": [{"bgp_as": "1234", "peer_group": [{"auth_pwd": {"encrypted": false, "pwd": "secret123"}, "name": "ROUTESERVERS"}], "state": "merged", "vrf_name": "default"}]}

PLAY RECAP *********************************************************************
leaf1   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Screenshots

Diffing the before and after blobs reported from --verbose output shows the change to the password:

$ diff -u <(jq '.before' < out.json ) <(jq .after < out.json)
--- /dev/fd/63  2024-03-26 12:05:16.285328057 +0100
+++ /dev/fd/62  2024-03-26 12:05:16.286328060 +0100
@@ -36,7 +36,7 @@
         "advertisement_interval": 0,
         "auth_pwd": {
           "encrypted": true,
-          "pwd": "U2FsdGVkX182G0luRsxMaMbz3fRxupYoP5NZRA2QNkY="
+          "pwd": "U2FsdGVkX1+kCWpAUut3794ANoM6yEOOb10IJKbaDd8="
         },
         "ebgp_multihop": {
           "enabled": true

The encryped password was indeed changed accordingly:

admin@leaf1:~$ sonic-cli -c 'show running-configuration | grep password'
  password U2FsdGVkX1+kCWpAUut3794ANoM6yEOOb10IJKbaDd8= encrypted

I suspect this happens because a randomly generated salt is generated on each run, instead of re-using the same salt every time.

A viable workaround is to specify the password as encrypted instead of unencrypted. This way, ok is reported on subsequent runs after the password was initially set. However, this workaround reveals another bug (which I do not have time to report separately now): the module fails to change an encrypted password (i.e., if I change the value of pwd in the config dict, ansible-playbook will report changed: on each subsequent, but the actual encrypted password on the switch remains unchanged.)

Additional Information

No response

[BUG]: Installation from requirements.yml

Bug Description

The role doesn't contain a meta/main.yml file, so when downloading it throws an error since it can't parse the requirements.

Source

Product Name

SONiC OS

Component or Module Name

ansible

DellEMC Enterprise SONiC Ansible Collection Version

any

SONiC Software Version

irrevelant

Configuration

Inside requirements.yml:

- name: dellemc.enterprise_sonic
  src: https://github.com/sonic-net/sonic-restapi.git
  scm: git

Steps to Reproduce

Run ansible-galaxy install -r requirements.yml.

Expected Behavior

No warning should be thrown.

Actual Behavior

Output:

[WARNING]: - dellemc.enterprise_sonic was NOT installed successfully: this role does not appear to have a meta/main.yml file.
ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.

Logs

Starting galaxy role install process
[WARNING]: - dellemc.enterprise_sonic was NOT installed successfully: this role does not appear to have a meta/main.yml file.
ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.

Screenshots

No response

Additional Information

No response

[QUESTION]:FAILED! => {"changed": false, "code": -32603, "msg": "'command'"}

How can the team help?

Details: ? I tried to add a vlan for a interface and i am getting an error. Following is my simple playbook

  • name: Change access VLAN in specific PORTs in OOB TOR
    hosts: bed-lab-leB7d
    gather_facts: no
    connection: network_cli
    vars_files: /etc/ansible/host_vars/oob.yml
    tasks:
    • name: Modify access VLAN
      dellemc.enterprise_sonic.sonic_l2_interfaces:
      config:
      • name: "{{ Eth }}"
        access:
        vlan: "{{ vlan }}"
        state: merged

and this is my error message, it does not provide any description
fatal: [bed-lab-leB7d]: FAILED! => {"changed": false, "code": -32603, "msg": "'command'"}

[FEATURE]: Provide vlan range capability for the sonic_mclag resource modules

Describe the solution you'd like
When specifying a "vlan" value for these resource modules (sonic_mclag and sonic_vlans), provide the option ability to specify a list of vlan values including ranges:

e.g. vlan: 1,3-9,11,15-25

Describe alternatives you've considered
The only workaround is to individually specify each vlan.

Additional context
REF: Closed issue #61: (Add ability to specify VLAN ranges)

For the original issue referenced above, the specific request for the ability to configure ranges of trunk vlans has already been implemented.

Community Note

  • Please vote on this issue by adding a 👍 reaction
    to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions,
    they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Add ability to specify VLAN ranges

SUMMARY

I would like to configure VLAN ranges for trunk interfaces. Currently it is only possible to add VLANs in a list, bur this can be quite cumbersome if many (or all) VLANs are needed on an interface.

ISSUE TYPE
  • Feature Idea
COMPONENT NAME
  • sonic_l2_interfaces
  • sonic_mclag
  • sonic_vlans
ADDITIONAL INFORMATION

Instead of:

sonic_l2_interfaces:
  - name: PortChannel1
    trunk:
      allowed_vlans:
        - vlan: 101
        - vlan: 103
        - vlan: 104
        - vlan: 105
        - ...
        - vlan: 200

I would like the option to configure it somehow like this:

sonic_l2_interfaces:
  - name: PortChannel1
    trunk:
      allowed_vlans:
        - vlan_range: 100-200

[BUG]: "a bytes-like object is required, not 'str'" on sonic_interface module

Bug Description

"msg": "a bytes-like object is required, not 'str'",
"invocation": {
"module_args": {
"config": [
{
"name": "Eth1/1",
"description": "Uplink to UNV-LR1-SP1",
"enabled": null,
"mtu": null,
"speed": null,
"auto_negotiate": null,
"advertised_speed": null,
"fec": null
}
],
"state": "merged"
}

Product Name

Dell Enterprise Sonic

Component or Module Name

sonic_interface

DellEMC Enterprise SONiC Ansible Collection Version

2.4.0

SONiC Software Version

4.0.1

Configuration

Ran through AWX

- name: Interface Manager
  connection: httpapi
  dellemc.enterprise_sonic.sonic_interfaces:
    config:
      - name: "{{ item.name }}"
        description: "{{ item.description }}"

enabled: "{{ item.enabled | bool }}"

    state: merged

Steps to Reproduce

Ran through AWX

Expected Behavior

Update Description, and Enabled State without Error

Actual Behavior

"a bytes-like object is required, not 'str'"

Logs

{
"started": 1,
"finished": 1,
"stdout": "",
"stderr": "",
"stdout_lines": [],
"stderr_lines": [],
"ansible_job_id": "j708448897745.301",
"results_file": "/runner/.ansible_async/j708448897745.301",
"code": -32603,
"msg": "a bytes-like object is required, not 'str'",
"invocation": {
"module_args": {
"config": [
{
"name": "PortChannel 3",
"description": "UNV-LR1-L1 E1/3 & UNV-LR1-L2 E1/3",
"enabled": null,
"mtu": null,
"speed": null,
"auto_negotiate": null,
"advertised_speed": null,
"fec": null
}
],
"state": "merged"
}
}

Screenshots

No response

Additional Information

No response

[FEATURE]: module for STP operations

Currently, there doesn't appear to be any module that addresses STP operations either globally or per interface. As a huge percentage of environments still leverage STP this would be a helpful addition. The most common STP configurations that we set on projects are:

  • Setting STP mode globally (Rapid-PVST, PVST, MST, Disabled)
  • Setting priority per VLAN for Rapid-PVST/PVST
  • Setting priority per instance with MST
  • Setting per port settings such
    • BPDUguard
    • Rootguard
    • Loopguard
    • Edge port / Portfast mode
    • STP Disabled per interface

[BUG]: sonic_vrfs module doesn't work with the "state: overridden"

Bug Description

this ansible task, similar to the one in documentation", fails

- name: Configure vrf
  dellemc.enterprise_sonic.sonic_vrfs:
    state: "overridden"
    config:
      - name: Vrf-1G
        members:
          interfaces:
            - name: "Eth1/3"

with this message

fatal: [dell-sonic]: FAILED! => {
"changed": false,
"module_stderr": "argument of type 'NoneType' is not iterable",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error"
}

The same task is working with the state set to deleted or merged.

Product Name

Dell Enterprise Sonic

Component or Module Name

dellemc.enterprise_sonic.sonic_vrfs

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.2.0

SONiC Software Version

Software Version : 4.1.0-Edge_Standard

Configuration

CONFIG_FILE() = /home/guertinf/reseautique-CQ/ansible.cfg
DEFAULT_HOST_LIST(/home/guertinf/reseautique-CQ/ansible.cfg) = ['/home/guertinf/reseautique-CQ/inventory']
DEFAULT_ROLES_PATH(/home/guertinf/reseautique-CQ/ansible.cfg) = ['/home/guertinf/reseautique-CQ/roles']
PARAMIKO_HOST_KEY_AUTO_ADD(/home/guertinf/reseautique-CQ/ansible.cfg) = True
PERSISTENT_CONNECT_TIMEOUT(/home/guertinf/reseautique-CQ/ansible.cfg) = 120

Steps to Reproduce

The ansible playbook

---
- name: "Sonic playbook"
  hosts: sonic
  remote_user: admin
  gather_facts: false
  connection: httpapi
  vars:
    ansible_network_os: dellemc.enterprise_sonic.sonic
    ansible_httpapi_use_ssl: true
    ansible_httpapi_validate_certs: false
  roles:
    - sonic_vrf

and this role/task

- name: Configure vrf
  dellemc.enterprise_sonic.sonic_vrfs:
    state: "overridden"
    config:
      - name: Vrf-1G
        members:
          interfaces:
            - name: "Eth1/3"

See the result in the log boxe.

Expected Behavior

The sonic_vrfs module works fine with the staes "merged" and "deleted". The vrf is created or remove as expected.

Actual Behavior

It crashes with the state "overridden" with the message

fatal: [dell-sonic]: FAILED! => {
    "changed": false,
    "module_stderr": "argument of type 'NoneType' is not iterable",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error"
}

Logs

$ ANSIBLE_NETWORK_GROUP_MODULES=sonic ansible-playbook playbook/sonic.yml --limit dell-sonic --ask-vault-pass --ask-become --ask-pass -vvvv
ansible-playbook [core 2.15.0]
  config file = /home/guertinf/reseautique-CQ/ansible.cfg
  configured module search path = ['/home/guertinf/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/guertinf/ansible2.15/lib64/python3.11/site-packages/ansible
  ansible collection location = /home/guertinf/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/guertinf/ansible2.15/bin/ansible-playbook
  python version = 3.11.2 (main, Feb 18 2023, 08:12:16) [GCC 8.5.0 20210514 (Red Hat 8.5.0-18)] (/home/guertinf/ansible2.15/bin/python)
  jinja version = 3.1.2
  libyaml = True
Using /home/guertinf/reseautique-CQ/ansible.cfg as config file
SSH password: 
BECOME password[defaults to SSH password]: 
Vault password: 
setting up inventory plugins
Loading collection ansible.builtin from 
host_list declined parsing /home/guertinf/reseautique-CQ/inventory as it did not pass its verify_file() method
script declined parsing /home/guertinf/reseautique-CQ/inventory as it did not pass its verify_file() method
auto declined parsing /home/guertinf/reseautique-CQ/inventory as it did not pass its verify_file() method
Parsed /home/guertinf/reseautique-CQ/inventory inventory source with ini plugin
Loading collection dellemc.enterprise_sonic from /home/guertinf/.ansible/collections/ansible_collections/dellemc/enterprise_sonic
redirecting (type: action) dellemc.enterprise_sonic.sonic_vrfs to dellemc.enterprise_sonic.sonic
Loading callback plugin default of type stdout, v2.0 from /home/guertinf/ansible2.15/lib64/python3.11/site-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: sonic.yml ***********************************************************************************************************************************************************
Positional arguments: playbook/sonic.yml
verbosity: 4
connection: smart
timeout: 10
ask_pass: True
become_method: sudo
become_ask_pass: True
tags: ('all',)
inventory: ('/home/guertinf/reseautique-CQ/inventory',)
subset: dell-sonic
ask_vault_pass: True
forks: 5
1 plays in playbook/sonic.yml

PLAY [Sonic playbook] *********************************************************************************************************************************************************
Trying secret <ansible.parsing.vault.PromptVaultSecret object at 0x7f52af002910> for vault_id=default
Trying secret <ansible.parsing.vault.PromptVaultSecret object at 0x7f52af002910> for vault_id=default
redirecting (type: action) dellemc.enterprise_sonic.sonic_vrfs to dellemc.enterprise_sonic.sonic
Loading collection ansible.netcommon from /home/guertinf/.ansible/collections/ansible_collections/ansible/netcommon

TASK [sonic_vrf : Configure vrf] **********************************************************************************************************************************************
task path: /home/guertinf/reseautique-CQ/roles/sonic_vrf/tasks/main.yml:1
redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
Loading collection ansible.utils from /home/guertinf/.ansible/collections/ansible_collections/ansible/utils
<dell-sonic> attempting to start connection
<dell-sonic> using connection plugin ansible.netcommon.httpapi
Found ansible-connection at path /home/guertinf/ansible2.15/bin/ansible-connection
<dell-sonic> local domain socket does not exist, starting it
<dell-sonic> control socket path is /home/guertinf/.ansible/pc/c906188db7
<dell-sonic> Loading collection ansible.builtin from 
<dell-sonic> redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
<dell-sonic> Loading collection ansible.netcommon from /home/guertinf/.ansible/collections/ansible_collections/ansible/netcommon
<dell-sonic> Loading collection ansible.utils from /home/guertinf/.ansible/collections/ansible_collections/ansible/utils
<dell-sonic> Loading collection dellemc.enterprise_sonic from /home/guertinf/.ansible/collections/ansible_collections/dellemc/enterprise_sonic
<dell-sonic> local domain socket listeners started successfully
<dell-sonic> loaded API plugin ansible_collections.dellemc.enterprise_sonic.plugins.httpapi.sonic from path /home/guertinf/.ansible/collections/ansible_collections/dellemc/enterprise_sonic/plugins/httpapi/sonic.py for platform type dellemc.enterprise_sonic.sonic
<dell-sonic> Loading collection ansible.builtin from 
<dell-sonic> local domain socket path is /home/guertinf/.ansible/pc/c906188db7
redirecting (type: action) dellemc.enterprise_sonic.sonic_vrfs to dellemc.enterprise_sonic.sonic
redirecting (type: action) dellemc.enterprise_sonic.sonic_vrfs to dellemc.enterprise_sonic.sonic
<dell-sonic> ANSIBLE_NETWORK_IMPORT_MODULES: enabled
<dell-sonic> ANSIBLE_NETWORK_IMPORT_MODULES: found dellemc.enterprise_sonic.sonic_vrfs  at /home/guertinf/.ansible/collections/ansible_collections/dellemc/enterprise_sonic/plugins/modules/sonic_vrfs.py
<dell-sonic> ANSIBLE_NETWORK_IMPORT_MODULES: running dellemc.enterprise_sonic.sonic_vrfs
<dell-sonic> ANSIBLE_NETWORK_IMPORT_MODULES: complete
fatal: [dell-sonic]: FAILED! => {
    "changed": false,
    "module_stderr": "argument of type 'NoneType' is not iterable",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error"
}

PLAY RECAP ********************************************************************************************************************************************************************
dell-sonic                 : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

Screenshots

No response

Additional Information

No response

Implement replaced, overridden states in the Sonic Network Resource Modules

SUMMARY

Implement more Network Resource Module states in the sonic network resource modules.
The states are described here: https://docs.ansible.com/ansible/latest/network/user_guide/network_resource_modules.html
Implement replaced, overridden and gathered states for the sonic network resource modules.
Example on how it works in the ansible documentation: https://docs.ansible.com/ansible/latest/network/user_guide/network_resource_modules.html#using-network-resource-modules
See the table on the right for the replaced vs merged outcome.
This will make it possible to have a more declarative style playbooks without a lot of state handling.
Right now the network resource modules will only merge or delete, which means i need to read out existing config for for example vlans, check ansible vars what should be on the switch and the do a set comparison to delete and add vlans as needed.
If the replace method was implemented this complexity would be implemented in the network resource module instead of my playbook or ansible code.

ISSUE TYPE
  • Feature Idea
COMPONENT NAME
  • sonic_vlans
  • sonic_vrfs
  • sonic_vxlans
  • sonic_interfaces
  • sonic_l2_interfaces
  • sonic_l3_interfaces
  • sonic_lag_interfaces
  • etc
ADDITIONAL INFORMATION

It would make it easier to have more declarative ansible playbooks and reduce a lot of complexity when you want device config mirroring ansible device variables. without replace state deletion is added complexity I do not want or need.
Also, this would make these network resource modules more in line with ansible reference documentation and it would be more like feature parity with other network resource module collections.

- name: replaces given VLAN attributes with the device configuration
  dellemc.enterprise_sonic.sonic_vlans:
    config:
      - vlan_id: 10
      - vlan_id: 20
    state: replaced

This would make sure only vlan 10 and vlan 20 is configured and all others are removed.

[BUG]: deleted all in NTP is crashing with error

Bug Description

When NTP is configured and when DELETE ALL is performed, it fails.

Product Name

eSONiC Collections

Component or Module Name

sonic_ntp

DellEMC Enterprise SONiC Ansible Collection Version

2.0

SONiC Software Version

4.0

Configuration

NTP is configured using CLI as follows.

show ntp global

NTP Global Configuration

NTP authenticate: Yes

show ntp server

NTP Servers minpoll maxpoll Prefer Authentication key ID

1.1.1.1 6 10 False

Steps to Reproduce

After configuring, ran the following playbook to delete all NTP config.

  • name: Ansible resource module example for sonic_aaa
    hosts: datacenter
    gather_facts: False
    connection: httpapi
    collections:
    • dellemc.enterprise_sonic
      tasks:
    • name: Delete NTP server configuration
      sonic_ntp:
      state: deleted

Expected Behavior

It should delete all NTP configs.

Actual Behavior

It throws an error as follows.
TASK [Delete NTP server configuration] *****************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'list' object has no attribute 'get'
fatal: [sonic1]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n File "/root/.ansible/tmp/ansible-local-20769koewrw01/ansible-tmp-1680283498.5821176-20773-245238821663001/AnsiballZ_sonic_ntp.py", line 107, in \n _ansiballz_main()\n File "/root/.ansible/tmp/ansible-local-20769koewrw01/ansible-tmp-1680283498.5821176-20773-245238821663001/AnsiballZ_sonic_ntp.py", line 99, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File "/root/.ansible/tmp/ansible-local-20769koewrw01/ansible-tmp-1680283498.5821176-20773-245238821663001/AnsiballZ_sonic_ntp.py", line 47, in invoke_module\n runpy.run_module(mod_name='ansible_collections.dellemc.enterprise_sonic.plugins.modules.sonic_ntp', init_globals=dict(_module_fqn='ansible_collections.dellemc.enterprise_sonic.plugins.modules.sonic_ntp', _modlib_path=modlib_path),\n File "/usr/lib/python3.10/runpy.py", line 224, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File "/usr/lib/python3.10/runpy.py", line 96, in _run_module_code\n _run_code(code, mod_globals, init_globals,\n File "/usr/lib/python3.10/runpy.py", line 86, in _run_code\n exec(code, run_globals)\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/modules/sonic_ntp.py", line 450, in \n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/modules/sonic_ntp.py", line 445, in main\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/config/ntp/ntp.py", line 89, in execute_module\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/config/ntp/ntp.py", line 123, in set_config\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/config/ntp/ntp.py", line 139, in set_state\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/config/ntp/ntp.py", line 314, in preprocess_want\nAttributeError: 'list' object has no attribute 'get'\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

Logs

TASK [Delete NTP server configuration] *****************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'list' object has no attribute 'get'
fatal: [sonic1]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n File "/root/.ansible/tmp/ansible-local-20769koewrw01/ansible-tmp-1680283498.5821176-20773-245238821663001/AnsiballZ_sonic_ntp.py", line 107, in \n _ansiballz_main()\n File "/root/.ansible/tmp/ansible-local-20769koewrw01/ansible-tmp-1680283498.5821176-20773-245238821663001/AnsiballZ_sonic_ntp.py", line 99, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File "/root/.ansible/tmp/ansible-local-20769koewrw01/ansible-tmp-1680283498.5821176-20773-245238821663001/AnsiballZ_sonic_ntp.py", line 47, in invoke_module\n runpy.run_module(mod_name='ansible_collections.dellemc.enterprise_sonic.plugins.modules.sonic_ntp', init_globals=dict(_module_fqn='ansible_collections.dellemc.enterprise_sonic.plugins.modules.sonic_ntp', _modlib_path=modlib_path),\n File "/usr/lib/python3.10/runpy.py", line 224, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File "/usr/lib/python3.10/runpy.py", line 96, in _run_module_code\n _run_code(code, mod_globals, init_globals,\n File "/usr/lib/python3.10/runpy.py", line 86, in _run_code\n exec(code, run_globals)\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/modules/sonic_ntp.py", line 450, in \n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/modules/sonic_ntp.py", line 445, in main\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/config/ntp/ntp.py", line 89, in execute_module\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/config/ntp/ntp.py", line 123, in set_config\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/config/ntp/ntp.py", line 139, in set_state\n File "/tmp/ansible_sonic_ntp_payload_ohj2ff6n/ansible_sonic_ntp_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/config/ntp/ntp.py", line 314, in preprocess_want\nAttributeError: 'list' object has no attribute 'get'\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

Screenshots

No response

Additional Information

In plugins/module_utils/network/sonic/config/ntp/ntp.py, function preprocess_want is accessing "want" variable even for DELETE_ALL. In case of DELETE_ALL, want will be NULL.

[BUG]: overridden is not working as expected in sonic_interfaces module. Same issue for l2 & l3 interfaces as well

Bug Description

ref

sonic_interfaces code contains the code for both 'replaced' and for 'overridden'. Seems that the code for 'replaced' is working. But, the code for 'overridden' is not working as expected.

Product Name

eSONiC AnsibleCollections

Component or Module Name

sonic_interfaces

DellEMC Enterprise SONiC Ansible Collection Version

All versions

SONiC Software Version

All versions

Configuration

overridden_01:
module_args:
state: overridden
config:
- name: Eth1/1
mtu: 1600
existing_interfaces_config:
- path: "data/openconfig-interfaces:interfaces"
response:
code: 200
value:
openconfig-interfaces:interfaces:
interface:
- name: 'Eth1/1'
config:
mtu: 2000
- name: 'Eth1/2'
config:
mtu: 2000

Steps to Reproduce

By default, all physical interfaces exist. Add some configuration for Eth1/1, Eth1/2, Eth1/3.
Now, if we need to remove the configurations of Eth1/2 and Eth1/3, we need to do overridden for Eth1/1, with the expected params for Eth1/1

Expected Behavior

Eth1/2, Eth1/3 configs should be removed. ie. They should be set to ALL default values.
Eth1/1 - config should be replaced with the newly provided config.

Actual Behavior

It works similar to replaced.

Logs

NA

Screenshots

No response

Additional Information

No response

Feature Request: Add external-ip option to dellemc.enterprise_sonic.sonic_vxlans module

I propose adding an external-ip option to the dellemc.enterprise_sonic.sonic_vxlans module. Currently, this option is not available in the resource module, which limits its functionality compared to what is possible through sonic-cli on the device.

The implementation should allow users to specify an external-ip in the module configuration, functioning similarly to other existing options like source-ip and primary-ip.

Example Usage:

Before State Configuration:

# Running configuration before applying changes
# ...
#interface vxlan vteptest1
# source-ip 1.1.1.1
# primary-ip 2.2.2.2
# ...

Ansible Playbook Snippet:

- name: "Configure vxlan with external IP"
  dellemc.enterprise_sonic.sonic_vxlans:
    config:
      - name: vteptest2
        source_ip: 3.3.3.3
        primary_ip: 4.4.4.4
        external_ip: 5.5.5.5
        # Additional configuration
    state: overridden

After State Configuration:

# Expected running configuration after applying changes
# ...
#interface vxlan vteptest2
# source-ip 3.3.3.3
# primary-ip 4.4.4.4
# external-ip 5.5.5.5
# ...

Alternatives Considered:
None. The rationale for this feature is to align the module's capabilities with the configuration options available in sonic-cli, ensuring consistency and full utilization of the device's features.

[BUG]: Interface naming standard-extended is not supported by the sonic_system module

Bug Description

When trying to use the sonic_system module with a system that has interface naming standard extended the following error is encountered: "msg": "value of interface_naming must be one of: standard, native, got: standard-ext found in config"

Product Name

Dell Enterprise SONiC

Component or Module Name

sonic_system

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.2.0

SONiC Software Version

4.1.0-Enterprise_Base

Configuration

N/A (No output)

Steps to Reproduce

Configure a system with interface-naming standard-extended via the sonic-cli and try to leverage the ansible sonic_system module

Expected Behavior

Interface naming should support standard, native, and standard-ext

Actual Behavior

When attempting to change the interface naming state we get the error:
"msg": "value of interface_naming must be one of: standard, native, got: standard-ext found in config"

Logs

fatal: [S5212F-1]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"config": {
"anycast_address": null,
"hostname": "sonic",
"interface_naming": "standard-ext"
},
"state": "merged"
}
},
"msg": "value of interface_naming must be one of: standard, native, got: standard-ext found in config"
}
fatal: [S5212F-2]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"config": {
"anycast_address": null,
"hostname": "sonic",
"interface_naming": "standard-ext"
},
"state": "merged"
}
},
"msg": "value of interface_naming must be one of: standard, native, got: standard-ext found in config"
}

Screenshots

No response

Additional Information

No response

[BUG]: sonic_l2_interfaces module errors when multiple allowed VLANs are in sequential order

Bug Description

When the sonic_l2_interfaces module is run with consecutive vlans it properly sets the range but then errors out with a message of "fatal: [dcn01-s5212-01-sonic]: FAILED! => {"changed": false, "msg": "argument 'vlan' is of type <class 'str'> found in 'config -> trunk -> allowed_vlans'. and we were unable to convert to int: <class 'str'> cannot be converted to an int"}". This appears to be the result of the return value being a string that describes the range.

Product Name

Dell Enterprise SONiC

Component or Module Name

sonic_l2_interfaces

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.0.0

SONiC Software Version

Software Version : '4.0.2-Enterprise_Base'

Configuration

admin@AnsibleDeploymentStation:/test$ ansible-config dump --only-changed
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the
controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31
2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in
version 2.12. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
admin@AnsibleDeploymentStation:
/test$

Steps to Reproduce

Run the sonic_l2_interfaces module against SONiC 4.0.2 with a config of

  • name: PortChannel255
    access:
    vlan: 1
    trunk:
    allowed_vlans:
    - vlan: 2
    - vlan: 3

Expected Behavior

The vlans would be set and no error would occur.

Actual Behavior

When the sonic_l2_interfaces module is run with consecutive vlans it properly sets the range but then errors out with a message of "fatal: [dcn01-s5212-01-sonic]: FAILED! => {"changed": false, "msg": "argument 'vlan' is of type <class 'str'> found in 'config -> trunk -> allowed_vlans'. and we were unable to convert to int: <class 'str'> cannot be converted to an int"}".

Logs


config file definition for sonic_l2_interfaces:

  • name: PortChannel255
    access:
    vlan: 1
    trunk:
    allowed_vlans:
    - vlan: 2
    - vlan: 3

Result

TASK [Configure L2 Interfaces] *************************************************
task path: /home/admin/test/playbook.yml:67
redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
redirecting (type: action) dellemc.enterprise_sonic.sonic_l2_interfaces to dellemc.enterprise_sonic.sonic
redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
redirecting (type: action) dellemc.enterprise_sonic.sonic_l2_interfaces to dellemc.enterprise_sonic.sonic
redirecting (type: action) dellemc.enterprise_sonic.sonic_l2_interfaces to dellemc.enterprise_sonic.sonic
redirecting (type: action) dellemc.enterprise_sonic.sonic_l2_interfaces to dellemc.enterprise_sonic.sonic
redirecting (type: action) dellemc.enterprise_sonic.sonic_l2_interfaces to dellemc.enterprise_sonic.sonic
fatal: [dcn01-s5212-01-sonic]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"config": [
{
"access": {
"vlan": 2
},
"name": "Eth1/1",
"trunk": {
"allowed_vlans": [
{
"vlan": 3
}
]
}
},
{
"access": {
"vlan": 1
},
"name": "Eth1/10",
"trunk": null
},
{
"access": {
"vlan": 1
},
"name": "Eth1/15",
"trunk": null
},
{
"access": {
"vlan": 2
},
"name": "Eth1/2",
"trunk": {
"allowed_vlans": [
{
"vlan": 3
}
]
}
},
{
"access": {
"vlan": 1
},
"name": "Eth1/3",
"trunk": null
},
{
"access": {
"vlan": 1
},
"name": "Eth1/4",
"trunk": null
},
{
"access": {
"vlan": 1
},
"name": "Eth1/5",
"trunk": null
},
{
"access": {
"vlan": 1
},
"name": "Eth1/6",
"trunk": null
},
{
"access": {
"vlan": 1
},
"name": "Eth1/7",
"trunk": null
},
{
"access": {
"vlan": 1
},
"name": "Eth1/8",
"trunk": null
},
{
"access": {
"vlan": 1
},
"name": "Eth1/9",
"trunk": null
},
{
"access": {
"vlan": 1
},
"name": "PortChannel255",
"trunk": {
"allowed_vlans": [
{
"vlan": "2..3"
}
]
}
}
],
"state": "merged"
}
},
"msg": "argument 'vlan' is of type <class 'str'> found in 'config -> trunk -> allowed_vlans'. and we were unable to convert to int: <class 'str'> cannot be converted to an int"
}

Screenshots

No response

Additional Information

No response

[BUG]: sonic_interfaces fails to create Loopback interfaces

Bug Description

The following task fails to create the Loopback0 interface:

dellemc.enterprise_sonic.sonic_interfaces:
  config:
  - name: Loopback0
    description: Loopback Zero
  state: replaced

When running this in a playbook, it reports ok: [switch], i.e. no changes were done. The output from show running-configuration is identical before and after.

Follow-up tasks in the play that assume Loopback0 now exists, e.g., setting an IP address with sonic_l3_interfaces, fails with FAILED! => {"changed": false, "code": -32603, "msg": "{'ietf-restconf:errors': {'error': [{'error-type': 'application', 'error-tag': 'invalid-value', 'error-message': 'Resource not found'}]}, 'code': 404, 'request_data': {'path': 'data/openconfig-interfaces:interfaces/interface=Loopback0/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/addresses', 'method': 'PATCH'}}"}

In comparison, using dellemc.enterprise_sonic v2.2.0 will create the loopback interface using the exact same task. It reports changed: [switch] and interface Loopback 0 (notably without a description attribute) gets added to the output from show running-configuration, and follow-up tasks that assume Loopback0 now exists succeed.

Product Name

SONiC-OS-4.2.0-Enterprise_Base

Component or Module Name

sonic_interfaces

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.4.0

SONiC Software Version

SONiC-OS-4.2.0-Enterprise_Base

Configuration

CONFIG_FILE() = /home/debian/ansible/ansible.cfg
DEFAULT_HASH_BEHAVIOUR(/home/debian/ansible/ansible.cfg) = merge
DEFAULT_HOST_LIST(/home/debian/ansible/ansible.cfg) = ['/home/debian/ansible/hosts.yml']
DEFAULT_JINJA2_EXTENSIONS(/home/debian/ansible/ansible.cfg) = jinja2.ext.do
HOST_KEY_CHECKING(/home/debian/ansible/ansible.cfg) = False
INTERPRETER_PYTHON(/home/debian/ansible/ansible.cfg) = auto_silent
MAX_FILE_SIZE_FOR_DIFF(/home/debian/ansible/ansible.cfg) = 1048576
PERSISTENT_COMMAND_TIMEOUT(/home/debian/ansible/ansible.cfg) = 3000

Steps to Reproduce

Apply the task above using dellemc.enterprise_sonic v2.4.0.

Expected Behavior

Loopback0 should have been created with a description of Loopback Zero.

Actual Behavior

Loopback0 is not created.

Logs

See above, alternatively I need more information about which logs are requested.

Screenshots

No response

Additional Information

In case the issue was related to change discussed in #357, I also tried adding enabled: true to the configuration dict for Loopback0. This had no effect, however.

[BUG]: sonic_l2_interfaces VLAN configuration expects int

Bug Description

Hi,

I tried to run your sample playbook: sonic_resource_modules.yaml, more specific the following section:

- name: Configure Layer 2 interfaces
     dellemc.enterprise_sonic.sonic_l2_interfaces:
        config:
        - name: Eth1/2
          access:
            vlan: 701
          trunk:
            allowed_vlans:
              - vlan: 702
              - vlan: 703
        state: merged
     register: sonic_l2_interfaces_output

The above section fails with the following error message:

"msg": "argument vlan is of type <class 'str'> found in 'config -> trunk -> allowed_vlans'. and we were unable to convert to int: <class 'str'> cannot be converted to an int"

Product Name

Dell Enterprise SONIC

Component or Module Name

httpapi

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.0.0

SONiC Software Version

4.0.3-Enterprise_Base

Configuration

ansible 2.10.8
executable location = /usr/bin/ansible
python version = 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0]

Steps to Reproduce

  1. Get Ubuntu 22.04
  2. Install Ansible 2.10.8
  3. Install Dependencies
pip3 install paramiko>=2.7
pip3 install jinja2>=2.8
pip3 install ansible-base
ansible-galaxy collection install dellemc.enterprise_sonic
  1. Create sample structure:
sonic_resource_modules.yaml
host_vars/sonic_sw1.yaml
inventory.ini
  1. Run Playbook
ANSIBLE_NETWORK_GROUP_MODULES=sonic ansible-playbook sonic_resource_modules.yaml -i inventory.ini

NOTE: Ansible Playbook was run against an official GNS3 Enterprise SONIC 4.0.3 switch image

Expected Behavior

Eth1/2 is properly configured with access vlan 701 and tagged vlans 702 and 703

Actual Behavior

TASK [Configure Layer 2 interfaces] **********************************************************************************************************************************
fatal: [sonic_sw1]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "config": [
                {
                    "access": {
                        "vlan": 100
                    },
                    "name": "Eth1/1",
                    "trunk": null
                },
                {
                    "access": {
                        "vlan": 701
                    },
                    "name": "Eth1/2",
                    "trunk": {
                        "allowed_vlans": [
                            {
                                "vlan": "702..703"
                            }
                        ]
                    }
                }
            ],
            "state": "merged"
        }
    },
    "msg": "argument vlan is of type <class 'str'> found in 'config -> trunk -> allowed_vlans'. and we were unable to convert to int: <class 'str'> cannot be converted to an int"
}

Logs

host_vars/sonic_sw1.yaml

hostname: sonic_sw1

# Common parameters for connection type httpapi or network_cli:
ansible_user: xxx
ansible_pass: xxx
ansible_network_os: dellemc.enterprise_sonic.sonic

# Additional parameters for connection type httpapi:
ansible_httpapi_use_ssl: true
ansible_httpapi_validate_certs: false

inventory.ini

[sonic_sw1]
sonic_sw1 ansible_host=xxx

[sonic_sw2]
sonic_sw2 ansible_host=xxx

[sonic_switches:children]
sonic_sw1
sonic_sw2

sonic_resource_modules.yaml

---
- name: VLANs, Layer 2 and Layer 3 interfaces configuration using Enterprise SONiC resource modules
  hosts: sonic_sw1
  gather_facts: yes
  connection: httpapi
  tasks:
   - name: Configure VLANs
     dellemc.enterprise_sonic.sonic_vlans:
        config:
         - vlan_id: 701
         - vlan_id: 702
         - vlan_id: 703
         - vlan_id: 704
        state: merged
     register: sonic_vlans_output
   - name: Configure Layer 2 interfaces
     dellemc.enterprise_sonic.sonic_l2_interfaces:
        config:
        - name: Eth1/2
          access:
            vlan: 701
          trunk:
            allowed_vlans:
              - vlan: 702
              - vlan: 703
        state: merged
     register: sonic_l2_interfaces_output
   - name: Configure Layer 3 interfaces
     dellemc.enterprise_sonic.sonic_l3_interfaces:
       config:
        - name: Eth1/3
          ipv4:
            addresses:
              - address: 8.1.1.1/16
       state: merged
     register: sonic_l3_interfaces_output

Screenshots

No response

Additional Information

No response

Ansible Contributor Summit. Tuesday, April 12, 2022.

Ansible Contributor Summit

We are happy to announce that the registration for the Ansible Contributor Summit is open!

Why
  • This is a great opportunity for interested people to meet, discuss related topics, share their stories and opinions, get the latest important updates and just to hang out together.

  • There will be different announcements & presentations by Community, Core, Cloud, Network, and other teams.

  • Current contributors will be happy to share their stories and experience with newcomers.

  • There will be links to interactive self-passed instruqt scenarios shared during the event that help newcomers learn different aspects of development.

Where/when

Online on Matrix and Youtube. Tuesday, April 12, 2022, 12:00 - 20:00 UTC.

How to join
  • Add the event to your calendar. Use the ical URL (for example, in Google Calendar "Add other calendars" > "Import from URL") instead of importing the .ics file so that any updates to the event will be reflected in your calendar.

  • Check out the Summit page:

    • Add you name to attendees.
    • Suggest summit topics that would be interesting to you to hear about.
    • Vote on and propose changes to topics suggested by others.
    • If you want to be a presenter, please contact the Ansible Community team via [email protected].

We are looking forward to seeing you!:)

Collection Requirements Violation - Semantic Versioning

Bug Description

According to the changelog (https://github.com/ansible-collections/dellemc.enterprise_sonic/blob/main/CHANGELOG.rst#breaking-changes--porting-guide), the minor 2.1.0 release contains a breaking change. This is explicitly prohibited by semantic versioning (https://semver.org/) - breaking changes must happen in new major versions.

Semantic versioning is one of the main collection requirements for inclusion in Ansible (https://docs.ansible.com/ansible/devel/community/collection_contributors/collection_requirements.html#versioning-and-deprecation).

In today's Ansible 7.6.0 release, we pinned dellemc.enterprise_sonic to 2.0.0 to avoid breaking changes.

Please undo this breaking change and create a new 2.2.0 minor release without it as soon as possible, or risk freezing dellemc.enterprise_sonic to 2.0.0 for the remainder of the Ansible 7 and 8 release cycles and removal of the collection from Ansible 9.

Product Name

Component or Module Name

DellEMC Enterprise SONiC Ansible Collection Version

2.1.0

SONiC Software Version

Configuration

Steps to Reproduce

Expected Behavior

Actual Behavior

Logs

Screenshots

No response

Additional Information

No response

[BUG]: Removing an interface from Vrf is removing all other interfaces

Bug Description

Deletion of one interface from the VRF is deleting all the interfaces.

** CONFIG BEFORE RUNNING PLAYBOOK: **
z9432f-12003# show ip vrf
VRF-NAME INTERFACES
VrfReg1 Eth1/11
Eth1/12
Eth1/13
default

** PLAYBOOK TO DELETE ETH1/12 from VrfReg1 **

  • name: Ansible resource module example
    hosts: datacenter
    gather_facts: False
    connection: httpapi
    collections:
    • dellemc.enterprise_sonic
      tasks:
    • name: Configuring vrf deleted state
      dellemc.enterprise_sonic.sonic_vrfs:
      config:
      • name: VrfReg1
        members:
        interfaces:
        - name: Eth1/12
        state: deleted

** Show after executing the playbook **
z9432f-12003# show ip vrf
VRF-NAME INTERFACES
VrfReg1
default
z9432f-12003#

Product Name

eSONiC Collections

Component or Module Name

vrfs

DellEMC Enterprise SONiC Ansible Collection Version

2.0

SONiC Software Version

eSONiC 4.04

Configuration

z9432f-12003# configure terminal
z9432f-12003(config)# ip vrf VrfReg1
z9432f-12003(config)#
z9432f-12003(config)# interface Eth 1/11
z9432f-12003(config-if-Eth1/11)# ip vrf forwarding VrfReg1
z9432f-12003(config-if-Eth1/11)# interface Eth 1/12
z9432f-12003(config-if-Eth1/12)# ip vrf forwarding VrfReg1
z9432f-12003(config-if-Eth1/12)# interface Eth 1/13
z9432f-12003(config-if-Eth1/13)# ip vrf forwarding VrfReg1
z9432f-12003(config-if-Eth1/13)#
z9432f-12003(config-if-Eth1/13)#
z9432f-12003(config-if-Eth1/13)# end
z9432f-12003# show ip vrf
VRF-NAME INTERFACES

VrfReg1 Eth1/11
Eth1/12
Eth1/13
default

Steps to Reproduce


  • name: Ansible resource module example
    hosts: datacenter
    gather_facts: False
    connection: httpapi
    collections:
    • dellemc.enterprise_sonic
      tasks:
    • name: Configuring vrf deleted state
      dellemc.enterprise_sonic.sonic_vrfs:
      config:
      • name: VrfReg1
        members:
        interfaces:
        - name: Eth1/12
        state: deleted

Expected Behavior

Should delete only Eth1/12.

Actual Behavior

Its deleting all the 3 interfaces from VrfReg1

Logs

z9432f-12003# show ip vrf
VRF-NAME INTERFACES

VrfReg1
default
z9432f-12003#

Screenshots

No response

Additional Information

No response

[BUG]: argspec validation error seen while using ‘sonic_port_breakout’ module in Z9432F-ON platform.

Bug Description

Z9432F platform supports 8x10G and 8x25G breakout modes when changing hardware SKU from default to ‘DellEMC-Z9432f-T64C64O8-DPB’.
But ‘sonic_port_breakout’ module throws the below error when the facts have any of the above breakout modes.

Ansible module error:
"value of mode must be one of: 1x100G, 1x400G, 1x40G, 2x100G, 2x200G, 2x50G, 4x100G, 4x10G, 4x25G, 4x50G, got: 8x25G found in config"

Product Name

Dell Enterprise SONiC

Component or Module Name

sonic_port_breakout

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise.sonic 2.0.0

SONiC Software Version

4.0.1

Configuration

CONFIG_FILE() = /home/ansible.cfg
DEFAULT_HOST_LIST(/home/ansible.cfg) = ['/home/inventory/inventory.yml', '/home/inventory/host_cfg_inv_plugin.yaml']
DEFAULT_INVENTORY_PLUGIN_PATH(/home/ansible.cfg) = ['/home/inventory']
DISPLAY_SKIPPED_HOSTS(/home/ansible.cfg) = False
HOST_KEY_CHECKING(/home/ansible.cfg) = False
INJECT_FACTS_AS_VARS(/home/ansible.cfg) = False
INTERPRETER_PYTHON(/home/ansible.cfg) = /usr/bin/python3
PERSISTENT_COMMAND_TIMEOUT(/home/ansible.cfg) = 120
PERSISTENT_CONNECT_TIMEOUT(/home/ansible.cfg) = 120

Steps to Reproduce

  1. Configure hardware sku - ‘DellEMC-Z9432f-T64C64O8-DPB’ in SONiC device
  2. Configure any port to 8x10G or 8x25G
  3. Run ansible playbook using sonic_port_breakout module to configure any supported port breakout

Expected Behavior

Configures port breakout successfully

Actual Behavior

Throws below error:
"value of mode must be one of: 1x100G, 1x400G, 1x40G, 2x100G, 2x200G, 2x50G, 4x100G, 4x10G, 4x25G, 4x50G, got: 8x25G found in config"

Logs

NA

Screenshots

No response

Additional Information

No response

[QUESTION]: Command Timeout Triggered

How can the team help?

I'm trying to provision some switches with this Ansible collection.

The switches are from Edgecore and they're running their own Sonic version, so some API endpoints differ a bit. That's why I wanted to try to use sonic_command module to run some commands directly on the host.

However, I'm hitting command timeout triggered. I've been been following Ansible guide to try to debug the issue. I've set the debugging mode and such and I don't seem to find any interesting information.

I was running the following ad-hoc command:

ansible -i inventory.ini -m dellemc.enterprise_sonic.sonic_command leaf-sw-875sta-06 -e "ansible_connection=network_cli" -u admin -a "commands=['show version']"

Details

Actual error:

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: raise ConnectionError(to_text(msg, errors='surrogate_then_replace'
leaf-sw-875sta-06 | FAILED! => {
    "changed": false,
    "msg": "command timeout triggered, timeout value is 60 secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide."
}

I know that the user can login because I see these in the switch:

Jun 19 20:45:50 leaf-sw-875sta-06 sshd[1665270]: Accepted password for admin from <addr> port 34602 ssh2
Jun 19 20:45:50 leaf-sw-875sta-06 sshd[1665270]: pam_unix(sshd:session): session opened for user admin(uid=1000) by (uid=0)
Jun 19 20:45:50 leaf-sw-875sta-06 audit[1665270]: USER_LOGIN pid=1665270 uid=0 auid=1000 ses=304 subj==unconfined msg='op=login id=1000 exe="/usr/sbin/sshd" hostname=<hostname> addr=<addr> terminal=/dev/pts/1 res=success'
Jun 19 20:46:50 leaf-sw-875sta-06 sshd[1665270]: pam_unix(sshd:session): session closed for user admin

I've ran with ANSIBLE_LOG_PATH and ANSIBLE_DEBUG=True with no further useful information. I tried increasing ANSIBLE_PERSISTENT_COMMAND_TIMEOUT with no success either.

From the debug log, I can see this:

2024-02-29 16:46:28,208 p=975454 u=root n=ansible | network_os is set to dellemc.enterprise_sonic.sonic
2024-02-29 16:46:28,233 p=975464 u=root n=ansible | [DEPRECATION WARNING]: PlayContext.verbosity is deprecated, use
ansible.utils.display.Display.verbosity instead. This feature will be removed
in version 2.18. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
2024-02-29 16:46:28,233 p=975464 u=root n=ansible | [DEPRECATION WARNING]: The connection's stdin object is deprecated. Call
display.prompt_until(msg) instead. This feature will be removed in version
2.19. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
2024-02-29 16:47:28,233 p=975464 u=root n=ansible | command timeout triggered, timeout value is 60 secs.
See the timeout setting options in the Network Debug and Troubleshooting Guide.
2024-02-29 16:47:28,242 p=975454 u=root n=ansible | An exception occurred during task execution. To see the full traceback, use -vvv. The error was:     raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
2024-02-29 16:47:28,242 p=975454 u=root n=ansible | leaf-sw-875sta-06 | FAILED! => {
    "changed": false,
    "msg": "command timeout triggered, timeout value is 60 secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide."
}
2024-02-29 16:47:28,345 p=975464 u=root n=ansible | shutdown complete

I'm running with this Ansible version:

ansible [core 2.16.3]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.10/site-packages/ansible
  ansible collection location = /srv/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.10.2 (main, Feb 20 2024, 11:40:21) [GCC 8.5.0 20210514 (Red Hat 8.5.0-20)] (/usr/local/bin/python3.10)
  jinja version = 3.1.3
  libyaml = True

I'm not too sure what to search for next. I'm not able to pinpoint the error to something specific. Any help would be appreciated,
Thank you

[FEATURE]: BGP AF Route Aggregation

Describe the solution you'd like
I need to configure BGP route aggregation.

e.g.

router bgp 64701
...
 address-family ipv6 unicast
  network 2a00:12e8:700:103::/64
  aggregate-address 2a00:12e8:700:103::/64

This can be done with the RESTCONF resource sonic-bgp-global:sonic-bgp-global/BGP_GLOBALS_AF_AGGREGATE_ADDR

Describe alternatives you've considered
Use sonic_api module

Community Note

  • Please vote on this issue by adding a 👍 reaction
    to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions,
    they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Config src module is not working for dellemc.enterprise_sonic.sonic

I am creating the following config using a template which works on the cli and ansible config lines module but when trying to push with config src module, it's giving me an error:

config from template:

sonic-1.cfg

interface Ethernet0
  ip dhcp-relay 1.1.1.2
interface Ethernet4
  ip dhcp-relay 1.1.1.3

config add via cli:

sonic-1:~$ sonic-cli
sonic-1# configure terminal
sonic-1(config)# interface Ethernet0
sonic-1(conf-if-Ethernet0)# ip dhcp-relay 1.1.1.2
sonic-1(conf-if-Ethernet0)# end
sonic-1# write memory
sonic-1#

config add via ansible task:

- name: add config
  dellemc.enterprise_sonic.sonic_config:
    src: ./sonic-1.cfg
    save: yes

config error when trying to push with ansible config src:

TASK [add config] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
fatal: [sonic-1]: FAILED! => {"changed": false, "msg": "./sonic-1.cf\u001bEg\r\r\n                     ^\r\n% Error: Invalid input detected at \"^\" marker.\r\n\u0007sonic-1(config)# "}

Note: Testing done on the following SONiC code versions

SONiC.3.1.0-Cloud_Base
SONiC.3.1.2-Cloud_Base

ansible version :

ansible==2.10.0
ansible-base==2.10.10
napalm-ansible==0.10.0

[BUG]: Enterprise_sonic cannot import "is_masklen" module when using ansible.netcommon version 5.0

Bug Description

Enterprise_sonic tries to load the "is_masklen" module from a deprecated location when using ansible.netcommon version 5.0 and below error is reported:

2023-04-03 11:11:45,159 p=2767817 u=csoler n=ansible | TASK [Display SONiC version] *********************************************************************************************************************************
2023-04-03 11:11:45,799 p=2767817 u=csoler n=ansible | An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ImportError: cannot import name 'is_masklen' from 'ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils' (/home/csoler/scripts/ansible_sonic/lib64/python3.9/site-packages/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/utils.py)
2023-04-03 11:11:45,799 p=2767817 u=csoler n=ansible | fatal: [S01]: FAILED! => {"msg": "Unexpected failure during module execution: cannot import name 'is_masklen' from 'ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils' (/home/csoler/scripts/ansible_sonic/lib64/python3.9/site-packages/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/utils.py)", "stdout": ""}
2023-04-03 11:11:45,801 p=2767817 u=csoler n=ansible | PLAY RECAP ***************************************************************************************************************************************************

Product Name

Dell Enterprise SONiC

Component or Module Name

dellemc.enterprise_sonic.sonic_system

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.0.0

SONiC Software Version

S01# show version Software Version : 4.0.5-Enterprise_Base Product : Enterprise SONiC Distribution by Dell Technologies Distribution : Debian 10.13 Kernel : 4.19.0-9-2-amd64 Config DB Version : version_4_0_2 Build Commit : bd4c530f0 Build Date : Thu Feb 23 21:43:31 UTC 2023 Built By : sonicbld@sonic-lvn-csg-001 Platform : x86_64-kvm_x86_64-r0 HwSKU : DellEMC-S5248f-P-25G-DPB

Configuration

(ansible) [csoler@CS-RockyOS-VM01 ansible]$ ansible-config dump --only-changed
COLLECTIONS_PATHS(/home/csoler/scripts/ansible/ansible.cfg) = ['/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_co>
DEFAULT_DEBUG(/home/csoler/scripts/ansible/ansible.cfg) = False
DEFAULT_FORKS(/home/csoler/scripts/ansible/ansible.cfg) = 10
DEFAULT_LOG_PATH(/home/csoler/scripts/ansible/ansible.cfg) = /home/csoler/scripts/ansible/ansible.log
DEFAULT_VERBOSITY(/home/csoler/scripts/ansible/ansible.cfg) = 0
DEPRECATION_WARNINGS(/home/csoler/scripts/ansible/ansible.cfg) = False
HOST_KEY_CHECKING(/home/csoler/scripts/ansible/ansible.cfg) = False

Steps to Reproduce

  • Install a virtual environment with below packages:

/home/csoler/scripts/ansible/lib/python3.9/site-packages/ansible_collections

Collection Version


ansible.netcommon 5.0.0
ansible.utils 2.9.0
dellemc.enterprise_sonic 2.0.0

  • Run a simple ansible playbook against a SONiC device (like a command to show the device SONiC version):

  • name: Ansible playbook to display the SONiC version
    hosts: S01
    gather_facts: False
    collections:

    • dellemc.enterprise_sonic

    tasks:

    • name: "Display SONiC version"
      sonic_command:
      commands: show version
      register: show_ver

    • debug: var=show_ver

  • Below error is reported when using ansible.netcommon version 5.0:
    TASK [Display SONiC version] *********************************************************************************************************
    An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ImportError: cannot import name 'is_masklen' from 'ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils' (/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/utils.py)
    fatal: [S01]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}

PLAY RECAP ***************************************************************************************************************************
S01 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0

Expected Behavior

  • When downgrading the ansible.netcommon software to version 4.1, everything seems to work fine:

(ansible_sonic) [csoler@CS-RockyOS-VM01 ansible_sonic]$ ansible-galaxy collection list | grep netcomm
ansible.netcommon 4.1.0
(ansible_sonic) [csoler@CS-RockyOS-VM01 ansible_sonic]$ ansible-playbook -i inventory/inventory_sonic_lab playbooks/sonic_show_version.yml

PLAY [Ansible playbook to display the SONiC version] *********************************************************************************************************

TASK [Display SONiC version] *********************************************************************************************************************************
ok: [S01]

TASK [debug] *************************************************************************************************************************************************
ok: [S01] => {
"show_ver": {
"changed": false,
"failed": false,
"stdout": [
"Software Version : 4.0.5-Enterprise_Base\nProduct : Enterprise SONiC Distribution by Dell Technologies\nDistribution : Debian 10.13\nKernel : 4.19.0-9-2-amd64\nConfig DB Version : version_4_0_2\nBuild Commit : bd4c530f0\nBuild Date : Thu Feb 23 21:43:31 UTC 2023\nBuilt By : sonicbld@sonic-lvn-csg-001\nPlatform : x86_64-kvm_x86_64-r0\nHwSKU : DellEMC-S5248f-P-25G-DPB\nASIC : vs\nSerial Number : 000000\nUptime : 12:04:51 up 18:20, 2 users, load average: 2.03, 2.22, 2.20 \n \nREPOSITORY TAG IMAGE ID SIZE\ndocker-database 4.0.5-Enterprise_Base 83068bda4b46 349MB\ndocker-database latest 83068bda4b46 349MB\ndocker-dhcp-relay 4.0.5-Enterprise_Base b77ce0eef496 386MB\ndocker-dhcp-relay latest b77ce0eef496 386MB\ndocker-eventd 4.0.5-Enterprise_Base a44bf4f96728 350MB\ndocker-eventd latest a44bf4f96728 350MB\ndocker-fpm-frr 4.0.5-Enterprise_Base b3081ec93a23 408MB\ndocker-fpm-frr latest b3081ec93a23 408MB\ndocker-gbsyncd-vs 4.0.5-Enterprise_Base 102baeacd06f 349MB\ndocker-gbsyncd-vs latest 102baeacd06f 349MB\ndocker-iccpd 4.0.5-Enterprise_Base 8452793c9eca 387MB\ndocker-iccpd latest 8452793c9eca 387MB\ndocker-l2mcd 4.0.5-Enterprise_Base 4f2f2657f260 384MB\ndocker-l2mcd latest 4f2f2657f260 384MB\ndocker-lldp 4.0.5-Enterprise_Base 2663d4c03799 423MB\ndocker-lldp latest 2663d4c03799 423MB\ndocker-macsec 4.0.5-Enterprise_Base b678cf1edb9f 364MB\ndocker-macsec latest b678cf1edb9f 364MB\ndocker-nat 4.0.5-Enterprise_Base 8f29ce7996b7 386MB\ndocker-nat latest 8f29ce7996b7 386MB\ndocker-orchagent 4.0.5-Enterprise_Base 68e2ee150728 380MB\ndocker-orchagent latest 68e2ee150728 380MB\ndocker-platform-monitor 4.0.5-Enterprise_Base 601b0551fb41 559MB\ndocker-platform-monitor latest 601b0551fb41 559MB\ndocker-router-advertiser 4.0.5-Enterprise_Base dde4f5ea61db 349MB\ndocker-router-advertiser latest dde4f5ea61db 349MB\ndocker-sflow 4.0.5-Enterprise_Base 86d397bc7734 386MB\ndocker-sflow latest 86d397bc7734 386MB\ndocker-snmp 4.0.5-Enterprise_Base ff8f537e940e 372MB\ndocker-snmp latest ff8f537e940e 372MB\ndocker-sonic-mgmt-framework 4.0.5-Enterprise_Base 25f55c6758bb 580MB\ndocker-sonic-mgmt-framework latest 25f55c6758bb 580MB\ndocker-sonic-telemetry 4.0.5-Enterprise_Base a003ddd1fdd2 525MB\ndocker-sonic-telemetry latest a003ddd1fdd2 525MB\ndocker-stp 4.0.5-Enterprise_Base b72bb83c40c2 387MB\ndocker-stp latest b72bb83c40c2 387MB\ndocker-syncd-vs 4.0.5-Enterprise_Base a96595873dc4 356MB\ndocker-syncd-vs latest a96595873dc4 356MB\ndocker-tam 4.0.5-Enterprise_Base 0971c72b1a02 433MB\ndocker-tam latest 0971c72b1a02 433MB\ndocker-teamd 4.0.5-Enterprise_Base f3beca130050 384MB\ndocker-teamd latest f3beca130050 384MB\ndocker-udld 4.0.5-Enterprise_Base 88e105ae60e5 388MB\ndocker-udld latest 88e105ae60e5 388MB\ndocker-vrrp 4.0.5-Enterprise_Base a3cf4228bc30 396MB\ndocker-vrrp latest a3cf4228bc30 396MB"
],
"stdout_lines": [
[
"Software Version : 4.0.5-Enterprise_Base",
"Product : Enterprise SONiC Distribution by Dell Technologies",
"Distribution : Debian 10.13",
"Kernel : 4.19.0-9-2-amd64",
"Config DB Version : version_4_0_2",
"Build Commit : bd4c530f0",
"Build Date : Thu Feb 23 21:43:31 UTC 2023",
"Built By : sonicbld@sonic-lvn-csg-001",
"Platform : x86_64-kvm_x86_64-r0",
"HwSKU : DellEMC-S5248f-P-25G-DPB",
"ASIC : vs",
"Serial Number : 000000",
"Uptime : 12:04:51 up 18:20, 2 users, load average: 2.03, 2.22, 2.20 ",
" ",
"REPOSITORY TAG IMAGE ID SIZE",
"docker-database 4.0.5-Enterprise_Base 83068bda4b46 349MB",
"docker-database latest 83068bda4b46 349MB",
"docker-dhcp-relay 4.0.5-Enterprise_Base b77ce0eef496 386MB",
"docker-dhcp-relay latest b77ce0eef496 386MB",
"docker-eventd 4.0.5-Enterprise_Base a44bf4f96728 350MB",
"docker-eventd latest a44bf4f96728 350MB",
"docker-fpm-frr 4.0.5-Enterprise_Base b3081ec93a23 408MB",
"docker-fpm-frr latest b3081ec93a23 408MB",
"docker-gbsyncd-vs 4.0.5-Enterprise_Base 102baeacd06f 349MB",
"docker-gbsyncd-vs latest 102baeacd06f 349MB",
"docker-iccpd 4.0.5-Enterprise_Base 8452793c9eca 387MB",
"docker-iccpd latest 8452793c9eca 387MB",
"docker-l2mcd 4.0.5-Enterprise_Base 4f2f2657f260 384MB",
"docker-l2mcd latest 4f2f2657f260 384MB",
"docker-lldp 4.0.5-Enterprise_Base 2663d4c03799 423MB",
"docker-lldp latest 2663d4c03799 423MB",
"docker-macsec 4.0.5-Enterprise_Base b678cf1edb9f 364MB",
"docker-macsec latest b678cf1edb9f 364MB",
"docker-nat 4.0.5-Enterprise_Base 8f29ce7996b7 386MB",
"docker-nat latest 8f29ce7996b7 386MB",
"docker-orchagent 4.0.5-Enterprise_Base 68e2ee150728 380MB",
"docker-orchagent latest 68e2ee150728 380MB",
"docker-platform-monitor 4.0.5-Enterprise_Base 601b0551fb41 559MB",
"docker-platform-monitor latest 601b0551fb41 559MB",
"docker-router-advertiser 4.0.5-Enterprise_Base dde4f5ea61db 349MB",
"docker-router-advertiser latest dde4f5ea61db 349MB",
"docker-sflow 4.0.5-Enterprise_Base 86d397bc7734 386MB",
"docker-sflow latest 86d397bc7734 386MB",
"docker-snmp 4.0.5-Enterprise_Base ff8f537e940e 372MB",
"docker-snmp latest ff8f537e940e 372MB",
"docker-sonic-mgmt-framework 4.0.5-Enterprise_Base 25f55c6758bb 580MB",
"docker-sonic-mgmt-framework latest 25f55c6758bb 580MB",
"docker-sonic-telemetry 4.0.5-Enterprise_Base a003ddd1fdd2 525MB",
"docker-sonic-telemetry latest a003ddd1fdd2 525MB",
"docker-stp 4.0.5-Enterprise_Base b72bb83c40c2 387MB",
"docker-stp latest b72bb83c40c2 387MB",
"docker-syncd-vs 4.0.5-Enterprise_Base a96595873dc4 356MB",
"docker-syncd-vs latest a96595873dc4 356MB",
"docker-tam 4.0.5-Enterprise_Base 0971c72b1a02 433MB",
"docker-tam latest 0971c72b1a02 433MB",
"docker-teamd 4.0.5-Enterprise_Base f3beca130050 384MB",
"docker-teamd latest f3beca130050 384MB",
"docker-udld 4.0.5-Enterprise_Base 88e105ae60e5 388MB",
"docker-udld latest 88e105ae60e5 388MB",
"docker-vrrp 4.0.5-Enterprise_Base a3cf4228bc30 396MB",
"docker-vrrp latest a3cf4228bc30 396MB"
]
]
}
}

PLAY RECAP ***************************************************************************************************************************************************
S01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Actual Behavior

When using ansible.netcommon version 5.0, ansible is not able to load the "is_masklen" module:

(ansible) [csoler@CS-RockyOS-VM01 ansible]$ ansible-playbook -i inventory/inventory_sonic_lab playbooks/sonic_show_version.yml

PLAY [Ansible playbook to display the SONiC version] *********************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
[WARNING]: ansible-pylibssh not installed, falling back to paramiko
ok: [S01]

TASK [Display SONiC version] *********************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ImportError: cannot import name 'is_masklen' from 'ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils' (/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/utils.py)
fatal: [S01]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}

PLAY RECAP ***************************************************************************************************************************
S01 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0

Logs

(ansible) [csoler@CS-RockyOS-VM01 ansible]$ ansible-playbook -i inventory/inventory_sonic_lab playbooks/sonic_show_version.yml -vvv
ansible-playbook [core 2.13.0]
config file = /home/csoler/scripts/ansible/ansible.cfg
configured module search path = ['/home/csoler/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible
ansible collection location = /home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_collections:/home/csoler/scripts/ansible/lib/python3.9/site-packages/ansible_collections
executable location = /home/csoler/scripts/ansible/bin/ansible-playbook
python version = 3.9.13 (main, Nov 16 2022, 15:31:39) [GCC 8.5.0 20210514 (Red Hat 8.5.0-15)]
jinja version = 3.1.2
libyaml = True
Using /home/csoler/scripts/ansible/ansible.cfg as config file
host_list declined parsing /home/csoler/scripts/ansible/inventory/inventory_sonic_lab as it did not pass its verify_file() method
script declined parsing /home/csoler/scripts/ansible/inventory/inventory_sonic_lab as it did not pass its verify_file() method
auto declined parsing /home/csoler/scripts/ansible/inventory/inventory_sonic_lab as it did not pass its verify_file() method
Parsed /home/csoler/scripts/ansible/inventory/inventory_sonic_lab inventory source with ini plugin
redirecting (type: action) dellemc.enterprise_sonic.sonic_command to dellemc.enterprise_sonic.sonic
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: sonic_show_version.yml *****************************************************************************************************
1 plays in playbooks/sonic_show_version.yml

PLAY [Ansible playbook to display the SONiC version] *********************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
task path: /home/csoler/scripts/ansible/playbooks/sonic_show_version.yml:5
redirecting (type: become) ansible.builtin.enable to ansible.netcommon.enable
[WARNING]: ansible-pylibssh not installed, falling back to paramiko
<10.204.11.72> ESTABLISH LOCAL CONNECTION FOR USER: csoler
<10.204.11.72> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo /home/csoler/.ansible/tmp/ansible-local-2777093bw7b5f_9"&& mkdir "echo /home/csoler/.ansible/tmp/ansible-local-2777093bw7b5f_9/ansible-tmp-1680523637.333111-2777097-173860067954733" && echo ansible-tmp-1680523637.333111-2777097-173860067954733="echo /home/csoler/.ansible/tmp/ansible-local-2777093bw7b5f_9/ansible-tmp-1680523637.333111-2777097-173860067954733" ) && sleep 0'
Using module file /home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible/modules/setup.py
<10.204.11.72> PUT /home/csoler/.ansible/tmp/ansible-local-2777093bw7b5f_9/tmp8l6pw4df TO /home/csoler/.ansible/tmp/ansible-local-2777093bw7b5f_9/ansible-tmp-1680523637.333111-2777097-173860067954733/AnsiballZ_setup.py
<10.204.11.72> EXEC /bin/sh -c 'chmod u+x /home/csoler/.ansible/tmp/ansible-local-2777093bw7b5f_9/ansible-tmp-1680523637.333111-2777097-173860067954733/ /home/csoler/.ansible/tmp/ansible-local-2777093bw7b5f_9/ansible-tmp-1680523637.333111-2777097-173860067954733/AnsiballZ_setup.py && sleep 0'
<10.204.11.72> EXEC /bin/sh -c '/home/csoler/scripts/ansible/bin/python3.9 /home/csoler/.ansible/tmp/ansible-local-2777093bw7b5f_9/ansible-tmp-1680523637.333111-2777097-173860067954733/AnsiballZ_setup.py && sleep 0'
<10.204.11.72> EXEC /bin/sh -c 'rm -f -r /home/csoler/.ansible/tmp/ansible-local-2777093bw7b5f_9/ansible-tmp-1680523637.333111-2777097-173860067954733/ > /dev/null 2>&1 && sleep 0'
ok: [S01]
META: ran handlers
redirecting (type: action) dellemc.enterprise_sonic.sonic_command to dellemc.enterprise_sonic.sonic

TASK [Display SONiC version] *********************************************************************************************************
task path: /home/csoler/scripts/ansible/playbooks/sonic_show_version.yml:12
redirecting (type: become) ansible.builtin.enable to ansible.netcommon.enable
redirecting (type: action) dellemc.enterprise_sonic.sonic_command to dellemc.enterprise_sonic.sonic
redirecting (type: action) dellemc.enterprise_sonic.sonic_command to dellemc.enterprise_sonic.sonic
The full traceback is:
Traceback (most recent call last):
File "/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible/executor/task_executor.py", line 157, in run
res = self._execute()
File "/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible/executor/task_executor.py", line 630, in _execute
result = self._handler.run(task_vars=vars_copy)
File "/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_collections/dellemc/enterprise_sonic/plugins/action/sonic.py", line 50, in run
result = super(ActionModule, self).run(task_vars=task_vars)
File "/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_collections/ansible/netcommon/plugins/action/network.py", line 42, in run
filename, module = self._find_load_module()
File "/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_collections/ansible/netcommon/plugins/action/network.py", line 279, in _find_load_module
module = importlib.import_module(context.plugin_resolved_name)
File "/usr/lib64/python3.9/importlib/init.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 1030, in _gcd_import
File "", line 1007, in _find_and_load
File "", line 986, in _find_and_load_unlocked
File "", line 680, in _load_unlocked
File "/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible/utils/collection_loader/_collection_finder.py", line 434, in exec_module
exec(code_obj, module.dict)
File "/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_collections/dellemc/enterprise_sonic/plugins/modules/sonic_command.py", line 148, in
from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.utils.utils import command_list_str_to_dict
File "/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible/utils/collection_loader/_collection_finder.py", line 434, in exec_module
exec(code_obj, module.dict)
File "/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/utils/utils.py", line 17, in
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
ImportError: cannot import name 'is_masklen' from 'ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils' (/home/csoler/scripts/ansible/lib64/python3.9/site-packages/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/utils.py)
fatal: [S01]: FAILED! => {
"msg": "Unexpected failure during module execution.",
"stdout": ""
}

PLAY RECAP ***************************************************************************************************************************
S01 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0

Screenshots

No response

Additional Information

No response

Action required: Add stable-2.13 to the test matrix

Dear maintainers,

According to the Collection requirements, collections included in the ansible package MUST run the ansible-test sanity command from the latest stable ansible-core branch.

It has been recently announced via the news-for-maintainers repository that the ansible-core stable-2.13 branch is available for testing.

  • Please add the stable-2.13 branch to your test matrix in the .github/workflows directory, at least, in the sanity jobs section. Any questions, just mention me here.

  • If you have integration and/or unit tests, please consider adding the branch to the corresponding sections too.

  • If you're not subscribed to the news-for-maintainers repository, please do it to avoid CI related issues in the future.

  • If the issue is not relevant to your collection, please close it.

Thank you!

[BUG]:

Bug Description

sonic_vlans sucessfully creates the vlans but fails to set their description.

Product Name

Dell Enterprise SONiC

Component or Module Name

sonic_vlans

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.4.0

SONiC Software Version

Software Version : 4.2.0-Enterprise_Base

Configuration

No output from ansible-config dump --only-changed

Steps to Reproduce

Leverage sonic_vlans with above versions and following data:
sonic_vlans:

  • vlan_id: 1
    description:
  • vlan_id: 2
    description: "Servers"
  • vlan_id: 5
    description: "vMotion"
  • vlan_id: 999
    description: "DeadVlan"

Expected Behavior

VLANs are created along with descriptions

Actual Behavior

VLANs are created but description is not set. On each subsequent run it reports VLANs as changed but VLAN description is never set.

Logs


< TASK [Create Vlans] >

    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

task path: /mnt/c/Users/Matthew_Hannon/Downloads/ansible_demo_2024_02_20/ansible-sonic-rev1/playbook.yaml:31
redirecting (type: action) dellemc.enterprise_sonic.sonic_vlans to dellemc.enterprise_sonic.sonic
redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
redirecting (type: action) dellemc.enterprise_sonic.sonic_vlans to dellemc.enterprise_sonic.sonic
redirecting (type: action) dellemc.enterprise_sonic.sonic_vlans to dellemc.enterprise_sonic.sonic
redirecting (type: action) dellemc.enterprise_sonic.sonic_vlans to dellemc.enterprise_sonic.sonic
redirecting (type: action) dellemc.enterprise_sonic.sonic_vlans to dellemc.enterprise_sonic.sonic
*** before
--- after


*** 4,18 ****
'vlan_id': 1
},
{
! 'description': null,
'vlan_id': 2
},
{
! 'description': null,
'vlan_id': 5
},
{
! 'description': null,
'vlan_id': 999
}
]
--- 4,18 ----
'vlan_id': 1
},
{
! 'description': 'Servers',
'vlan_id': 2
},
{
! 'description': 'vMotion',
'vlan_id': 5
},
{
! 'description': 'DeadVlan',
'vlan_id': 999
}
]
changed: [S5232F-1] => {"after(generated)": [{"description": null, "vlan_id": 1}, {"description": "Servers", "vlan_id": 2}, {"description": "vMotion", "vlan_id": 5}, {"description": "DeadVlan", "vlan_id": 999}], "before": [{"description": null, "vlan_id": 1}, {"description": null, "vlan_id": 2}, {"description": null, "vlan_id": 5}, {"description": null, "vlan_id": 999}], "changed": true, "commands": [{"description": "Servers", "state": "overridden", "vlan_id": 2}, {"description": "vMotion", "state": "overridden", "vlan_id": 5}, {"description": "DeadVlan", "state": "overridden", "vlan_id": 999}]}
*** before
--- after

Screenshots

No response

Additional Information

No response

Upstream SONiC support in addition to Dell EMC Enterprise SONiC support

SUMMARY

SONiC does not have a good Ansible galaxy module. This one could be it without too much work.

ISSUE TYPE

I would like to ask if there are any plans on splitting out the DellEMC specific parts and rebrand the module to being a SONiC-generic module, with DellEMC Enterprise SONiC support?

The way I see it working together on a single SONiC Ansible plugin would benefit SONiC adoption as a whole and help everyone, including DellEMC.

An alternative is to fork this module and strip all the Dell EMC Enterprise SONiC specific things, but that would be a lot of duplicated work and messy to keep synchronized.

[BUG]: sonic_lag_interfaces module fails to set the port-channel ID on interfaces

Bug Description

The sonic_lag_interfaces module fails to set the port-channel ID on interfaces due to sending an incorrect string in the body. For example, if we want to assign PortChannel55 to Eth1/11 the string that should be sent is "openconfig-if-aggregate:aggregate-id": "PortChannel55" however the module appears to be sending just "openconfig-if-aggregate:aggregate-id": "55"

Product Name

Dell Enterprise SONiC

Component or Module Name

sonic_lag_interfaces

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.0.0

SONiC Software Version

Software Version : '4.0.2-Enterprise_Base'

Configuration

admin@AnsibleDeploymentStation:$ ansible-config dump --only-changed
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the
controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31
2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in
version 2.12. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
admin@AnsibleDeploymentStation:
$

Steps to Reproduce

To reproduce attempt to leverage the sonic_lag_interfaces module with SONiC 4.0.2 to set a port-channel. Example config passed to the module:

  • members:
    interfaces:
    - member: Eth1/11
    - member: Eth1/12
    mode: lacp
    name: PortChannel55

Expected Behavior

I would expect the module to set the port-channel ID on the member ports

Actual Behavior

TASK [Create LAG Interfaces] ***************************************************
fatal: [dcn01-s5212-01-sonic]: FAILED! => {"changed": false, "code": -32603, "msg": "{'ietf-restconf:errors': {'error': [{'error-type': 'application', 'error-tag': 'invalid-value', 'error-message': 'Invalid Interface:55'}]}, 'code': 400, 'request_data': {'path': 'data/openconfig-interfaces:interfaces/interface=Eth1%2F11/openconfig-if-ethernet:ethernet/config/openconfig-if-aggregate:aggregate-id', 'method': 'patch'}}"}

Logs

TASK [Create LAG Interfaces] ***************************************************
fatal: [dcn01-s5212-01-sonic]: FAILED! => {"changed": false, "code": -32603, "msg": "{'ietf-restconf:errors': {'error': [{'error-type': 'application', 'error-tag': 'invalid-value', 'error-message': 'Invalid Interface:55'}]}, 'code': 400, 'request_data': {'path': 'data/openconfig-interfaces:interfaces/interface=Eth1%2F11/openconfig-if-ethernet:ethernet/config/openconfig-if-aggregate:aggregate-id', 'method': 'patch'}}"}

Screenshots

No response

Additional Information

No response

"rebuild.sh" may remove other collections under dellemc

SUMMARY

The line "rm -rf /root/.ansible/collections/ansible_collections/dellemc/*" will remove other collections. preferably only sonic to be removed

ISSUE TYPE
  • Bug Report
COMPONENT NAME
ANSIBLE VERSION

CONFIGURATION

OS / ENVIRONMENT
STEPS TO REPRODUCE
EXPECTED RESULTS
ACTUAL RESULTS

Consider using true/false for all booleans in docs

Based on the community decision to use true/false for boolean values in documentation and examples, we ask that you evaluate booleans in this collection and consider changing any that do not use true/false (lowercase).

See documentation block format for more info (specifically, option defaults).

If you have already implemented this or decide not to, feel free to close this issue.


P.S. This is auto-generated issue, please raise any concerns here

[QUESTION]: Non-dell sonic switches

Looks like this is specific for Dell firmware only even though SONiC is open?

The switches we have support httpapi just fine but I run into an Ansible error:

 ANSIBLE_NETWORK_GROUP_MODULES=sonic ansible-playbook sonic_facts.yml -i inventory.ini
[WARNING]: Found both group and host with same name: sonic_sw1

PLAY [Ansible resource module facts example] ****************************************************************************************************************

TASK [Gather facts] *****************************************************************************************************************************************
fatal: [sonic_sw1]: FAILED! => {"changed": false, "code": -32603, "msg": "a bytes-like object is required, not 'str'"}

PLAY RECAP **************************************************************************************************************************************************
sonic_sw1                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

---
- name: Ansible resource module facts example
  hosts: sonic_switches
  gather_facts: True
  connection: httpapi
  collections:
    - dellemc.enterprise_sonic
  tasks:
    - name: "Gather facts"
      sonic_facts:
        gather_subset: min
        gather_network_resources:
          - bgp
      register: result

    - name: "debug facts"
      debug:
        msg: "{{ result.ansible_facts.ansible_network_resources }}"

The full traceback is:
  File "/home/s7admin/.ansible/collections/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/utils/bgp_utils.py", line 48, in get_all_vrfs
    response = edit_config(module, to_request(module, request))
  File "/home/s7admin/.ansible/collections/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/sonic.py", line 140, in edit_config
    return connection.edit_config(commands)
  File "/usr/lib/python3/dist-packages/ansible/module_utils/connection.py", line 200, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
fatal: [sonic_sw1]: FAILED! => {
    "changed": false,
    "code": -32603,
    "invocation": {
        "module_args": {
            "gather_network_resources": [
                "bgp"
            ],
            "gather_subset": [
                "min"
            ]
        }
    },
    "msg": "a bytes-like object is required, not 'str'"
}

[QUESTION]: Replacing LAG interface with L2, and vice versa

How can the team help?

We need to change some interfaces from being a LAG member to being a standalone L2 port, and vice versa. Problem is that the LAG can not be configured at physical interface level, but rather the interfaces need to be configured as a 'member' on the LAG interface using sonic_lag_interfaces.

Since configuring L2 and LAG interfaces are different tasks, one is executed at first. If the L2 interfaces are configured first, then there might still be a port-channel configured on a port making the config task fail.

Is there any recommended way of handling this?

Details: ?

Our task looks like this:

- name: Set LAG Interfaces
  dellemc.enterprise_sonic.sonic_lag_interfaces:
    config: "{{ switch_ports | scaleup_sonic_lacp_interfaces }}"
    state: replaced

- name: Configure L2 Interfaces
  dellemc.enterprise_sonic.sonic_l2_interfaces:
    config: "{{ switch_ports | scaleup_sonic_l2_interfaces }}"
    state: replaced

switch_ports | scaleup_sonic_lacp_interfaces will return a list of LAG interfaces, in this case including one with Ethernet124 as the member.

switch_ports | scaleup_sonic_l2_interfaces will return a list of all L2 interfaces, without Ethernet124 (prior configured as L2 interface)

interface Ethernet124
 mtu 9100
 speed 100000
 unreliable-los auto
 no shutdown
 switchport access Vlan 1
 switchport trunk allowed Vlan 100
!

Task runs:

fatal: [redacted]: FAILED! => {
    "changed": false,
    "code": -32603,
    "invocation": {
        "module_args": {
            "config": [
                (redacted)
            ],
            "state": "replaced"
        }
    },
    "msg": "{'ietf-restconf:errors': {'error': [{'error-type': 'application', 'error-tag': 'invalid-value', 'error-app-tag': 'Config Validation Error', 'error-message': 'PortChannel configuration not allowed. Access VLAN:1 configuration exists on interface Ethernet124.', 'error-info': {'cvl-error': {'error-code': 1002, 'table-name': 'PORTCHANNEL_MEMBER', 'key-values': ['PORTCHANNEL_MEMBER', 'PortChannel255', 'Ethernet124']}}}]}, 'code': 400, 'request_data': {'path': 'data/openconfig-interfaces:interfaces/interface=Ethernet124/openconfig-if-ethernet:ethernet/config/openconfig-if-aggregate:aggregate-id', 'method': 'patch'}}"
}

Sanity tests failing in dellemc.enterprise_sonic

SUMMARY

We are running sanity tests across every collection included in the Ansible community package (as part of this issue) and found that ansible-test sanity --docker against dellemc.enterprise_sonic 1.1.0 fails with ansible-core 2.13.0rc1 in ansible 6.0.0a2.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

n/a

ANSIBLE VERSION
ansible [core 2.13.0rc1]
COLLECTION VERSION
1.1.0
STEPS TO REPRODUCE
ansible-test sanity --docker
EXPECTED RESULTS

Tests are either passing or ignored.

ACTUAL RESULTS
ERROR: Found 1 action-plugin-docs issue(s) which need to be resolved:
ERROR: plugins/action/sonic.py:0:0: action plugin has no matching module to provide documentation
ERROR: Found 8 validate-modules issue(s) which need to be resolved:
ERROR: plugins/cliconf/sonic.py:0:0: invalid-documentation: DOCUMENTATION.cliconf: extra keys not allowed @ data['cliconf']. Got 'sonic'
ERROR: plugins/cliconf/sonic.py:0:0: invalid-documentation: DOCUMENTATION.name: required key not provided @ data['name']. Got None
ERROR: plugins/httpapi/sonic.py:0:0: invalid-documentation: DOCUMENTATION.author: Invalid author for dictionary value @ data['author']. Got 'Ansible Networking Team'
ERROR: plugins/httpapi/sonic.py:0:0: invalid-documentation: DOCUMENTATION.httpapi: extra keys not allowed @ data['httpapi']. Got 'sonic'
ERROR: plugins/httpapi/sonic.py:0:0: invalid-documentation: DOCUMENTATION.name: required key not provided @ data['name']. Got None
ERROR: plugins/modules/sonic_command.py:0:0: invalid-documentation-markup: DOCUMENTATION.description: Directive "M(sonic_config)" must contain a FQCN for dictionary value @ data['description']. Got ['Runs commands on remote devices running Enterprise SONiC Distribution by Dell Technologies. Sends arbitrary commands to an Enterprise SONiC node and returns the results that are read from the device. This module includes an argument that causes the module to wait for a specific condition before returning or time out if the condition is not met.', 'This module does not support running commands in configuration mode. To configure SONiC devices, use M(sonic_config).']
ERROR: plugins/modules/sonic_facts.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.gather_network_resources.description: Directive "M(!)" must contain a FQCN for dictionary value @ data['options']['gather_network_resources']['description']. Got ["When supplied, this argument restricts the facts collected to a given subset. Possible values for this argument include all and the resources like 'all', 'interfaces', 'vlans', 'lag_interfaces', 'l2_interfaces', 'l3_interfaces'. Can specify a list of values to include a larger subset. Values can also be used with an initial C(M(!)) to specify that a specific subset should not be collected."]
ERROR: plugins/modules/sonic_facts.py:0:0: invalid-documentation-markup: DOCUMENTATION.options.gather_subset.description: Directive "M(!)" must contain a FQCN for dictionary value @ data['options']['gather_subset']['description']. Got ['When supplied, this argument restricts the facts collected to a given subset. Possible values for this argument include all, min, hardware, config, legacy, and interfaces. Can specify a list of values to include a larger subset. Values can also be used with an initial C(M(!)) to specify that a specific subset should not be collected.']
ERROR: The 2 sanity test(s) listed below (out of 43) failed. See error output above for details.
action-plugin-docs
validate-modules
ERROR: Command "podman exec ansible-test-controller-YRxKRHwq /usr/bin/env ANSIBLE_TEST_CONTENT_ROOT=/root/ansible_collections/dellemc/enterprise_sonic LC_ALL=en_US.UTF-8 /usr/bin/python3.10 /root/ansible/bin/ansible-test sanity --containers '{}' --skip-test pylint --metadata tests/output/.tmp/metadata-0xrarmuu.json --truncate 0 --color no --host-path tests/output/.tmp/host-t6a8dtjw" returned exit status 1.

Minor cosmetic issues

  1. In changelogs/.plugin-cache.yaml:
  sonic_command:
      description: Runs commands on devices running Enterprise SONiC
      name: sonic_command
      namespace: ''
      version_added: 1.0.0

Clarify what "commands" means -- are these "exec mode CLI commands?"

    sonic_config:
      description: Manages configuration sections on devices running Enterprise SONiC
      name: sonic_config
      namespace: ''
      version_added: 1.0.0

Clarify what "configuration sections" means. Are these "config mode CLI commands?"

  1. plugins/cliconf/sonic.py makes a reference to OS10, which is incorrect.

[BUG]: Collection does not support ansible.netcommon 5.x.y, thus latest version will not be included in Ansible 8 until this is fixed

Bug Description

Currently the Ansible 8 pre-releases contain dellemc.enterprise_sonic 2.0.0, which claims to support ansible.netcommon 5.x.y. Since ansible.netcommon 5.x.y will be included in Ansible 8, Ansible 8 cannot include dellemc.enterprise_sonic 2.1.0 since that release claims to no longer support ansible.netcommon 5.x.y.

Since apparently dellemc.enterprise_sonic 2.0.0 doesn't work with ansible.netcommon 5.x.y - but doesn't document so - Ansible 8 will stick to the broken dellemc.enterprise_sonic 2.0.0 until a later dellemc.enterprise_sonic 2.x.y. release will work with ansible.netcommon 5.x.y again.

Please make sure that your collection is compatible with ansible.netcommon 5.x.y as soon as possible.

Ref: ansible-community/ansible-build-data#233
Ref: #176 which unfortunately does not say what's the problem with ansible.netcommon 5.0.0.

Product Name

Component or Module Name

DellEMC Enterprise SONiC Ansible Collection Version

2.1.0

SONiC Software Version

Configuration

Steps to Reproduce

Expected Behavior

Actual Behavior

Logs

Screenshots

No response

Additional Information

No response

No --diff output from network resource modules

SUMMARY

Implement "--diff" output in network resource modules such as sonic_interfaces, sonic_vlans etc etc.
This works with other vendors network resource modules, and also dellemc.os10 implements diff output.
I see the data is there when running in verbose mode (before and after) so i guess the data for ansible-playbook to display the diff is not implemented in the dellemc.enterprise_sonic network resource modules.

ISSUE TYPE
  • Feature Idea
COMPONENT NAME

implement diff mode for sonic network resource modules.

ADDITIONAL INFORMATION

It would be grate for sanity check in combination with "check mode" to see what effective changes to a device will be compared to the current running configuration.

- hosts: all
  connection: httpapi
  gather_facts: true
  collections:
    - dellemc.enterprise_sonic

  tasks:
    - name: Create Interfaces
      sonic_interfaces:
        config: '{{sonic_interfaces}}'
      when: sonic_interfaces is defined and sonic_interfaces

Using this variable data:

sonic_interfaces:
  - description: '"MCLAG to LEAF-2 Eth1/51"'
    enabled: true
    name: Eth1/51

Run this command

ansible-playbook -i inventory.yaml playbook.yaml

Change variable to this

sonic_interfaces:
  - description: '"MCLAG to LEAF-4 Eth1/51"'
    enabled: true
    name: Eth1/51

And run this:

ansible-playbook -i inventory.yaml playbook.yaml --check --diff

I would expact to return the diff (interface description for Eth1/51).
This is what happens with other network resource modules and i would expect the enterprise sonic ones to do the same.

sonic_l2_interfaces error "code": -32603,

SUMMARY

I'm running ansible automation platform 2.0 using automation controller 4.0. I'm trying to use the dellemc.enterprise collection and the dellemc.enterprise_sonic.sonic_l2_interfaces and it is not assigning ports to existing vlan

ISSUE TYPE
  • Bug Report
COMPONENT NAME

dellemc.enterprise_sonic.sonic_l2_interfaces

ANSIBLE VERSION

ansible [core 2.12.5]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.8/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.8.12 (default, Sep 16 2021, 10:46:05) [GCC 8.5.0 20210514 (Red Hat 8.5.0-3)]
  jinja version = 2.10.3
  libyaml = True

COLLECTION VERSION
Name                       Version       Shadowed  Type       Path                                                                              
 0│ansible.builtin            2.12.5.post0  False     contained  /usr/local/lib/python3.8/site-packages/ansible                                    
 1│ansible.controller         4.2.0         False     contained  /usr/share/ansible/collections/ansible_collections/ansible/controller             
 2│ansible.netcommon          3.0.1         False     contained  /usr/share/ansible/collections/ansible_collections/ansible/netcommon              
 3│ansible.posix              1.4.0         False     contained  /usr/share/ansible/collections/ansible_collections/ansible/posix                  
 4│ansible.utils              2.6.1         False     contained  /usr/share/ansible/collections/ansible_collections/ansible/utils                  
 5│community.general          5.1.0         False     contained  /usr/share/ansible/collections/ansible_collections/community/general              
 6│community.vmware           2.6.0         False     contained  /usr/share/ansible/collections/ansible_collections/community/vmware               
 7│dellemc.enterprise_sonic   1.1.0         False     contained  /usr/share/ansible/collections/ansible_collections/dellemc/enterprise_sonic       
 8│dellemc.openmanage         5.4.0         False     contained  /usr/share/ansible/collections/ansible_collections/dellemc/openmanage             
 9│dellemc.os10               1.1.1         False     contained  /usr/share/ansible/collections/ansible_collections/dellemc/os10                   
10│dellemc.powerflex          1.2.0         False     contained  /usr/share/ansible/collections/ansible_collections/dellemc/powerflex              
11│redhat.rhel_idm            1.7.0         False     contained  /usr/share/ansible/collections/ansible_collections/redhat/rhel_idm
CONFIGURATION

OS / ENVIRONMENT

z9100-02# show version

Software Version : '4.0.0-Enterprise_Advanced'
Product : Enterprise SONiC Distribution by Dell Technologies
Distribution : '10.12'
Kernel : '4.19.0-9-2-amd64'
Config DB Version : version_4_0_1
Build Commit : 'cfcae285b'
Build Date : Fri Apr 22 23:39:23 UTC 2022
Built By :
Platform : x86_64-dell_z9100_c2538-r0
HwSKU : Force10-Z9100-C32
ASIC : broadcom
Hardware Version : A00
Serial Number :
Uptime : 14:37:52 up 27 days, 1:26, 1 user, load average: 2.31, 1.99, 1.77
Mfg : DELL

STEPS TO REPRODUCE
---
# host_vars file
hostname: z9100-01
ansible_network_os: dellemc.enterprise_sonic.sonic

# Additional parameters for connection type httpapi:
ansible_httpapi_use_ssl: true
ansible_httpapi_validate_certs: false

---
# playbook
- name: Dell VLAN Management Demo
  hosts: dell_demo
  gather_facts: false
  connection: httpapi

  collections:
    - dellemc.enterprise_sonic
  
  tasks:
- name: Configure switch port of interfaces
  dellemc.enterprise_sonic.sonic_l2_interfaces:
    config:
     - name: Eth1/1/1
       access:
         vlan: 12
       trunk:
         allowed_vlans:
            - vlan: 13
            - vlan: 14
    state: merged
EXPECTED RESULTS
Before state:

do show Vlan
Q: A - Access (Untagged), T - Tagged
NUM Status Q Ports
10 Inactive
11 Inactive
12 Inactive A Eth1/4
13 Inactive T Eth1/4
14 Inactive A Eth1/5
15 Inactive T Eth1/5

Run Playbook:

- name: Configure switch port of interfaces
  dellemc.enterprise_sonic.sonic_l2_interfaces:
    config:
     - name: Eth1/1/1
       access:
         vlan: 12
       trunk:
         allowed_vlans:
            - vlan: 13
            - vlan: 14
    state: merged
After state:

do show Vlan
Q: A - Access (Untagged), T - Tagged
NUM Status Q Ports
10 Inactive
11 Inactive
12 Inactive A Eth1/1/1
A Eth1/4
13 Inactive T Eth1/1/1
T Eth1/4
14 Inactive A Eth1/1/1
A Eth1/5
15 Inactive T Eth1/5

ACTUAL RESULTS

{
"code": -32603,
"msg": "{'ietf-restconf:errors': {'error': [{'error-type': 'protocol', 'error-tag': 'invalid-value', 'error-message': 'Not Found'}]}, 'code': 404, 'request_data': {'path': 'data/openconfig-interfaces:interfaces/interface=Eth1%2f1/1/openconfig-if-ethernet:ethernet/openconfig-vlan:switched-vlan/config', 'method': 'PATCH'}}",
"exception": " File "/usr/share/ansible/collections/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/config/l2_interfaces/l2_interfaces.py", line 103, in execute_module\n edit_config(self._module, to_request(self._module, requests))\n File "/usr/share/ansible/collections/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/sonic.py", line 140, in edit_config\n return connection.edit_config(commands)\n File "/usr/local/lib/python3.8/site-packages/ansible/module_utils/connection.py", line 200, in rpc\n raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)\n",
"invocation": {
"module_args": {
"config": [
{
"name": "Eth1/1/1",
"access": {
"vlan": 42
},
"trunk": {
"allowed_vlans": [
{
"vlan": 10
}
]
}
}
],
"state": "merged"
}
},
"_ansible_no_log": false,
"changed": false


socket_path must be a value

I was trying to execute a simple playbook to shut the interface of sonic nos device but i am getting into error.

currently i am running in ansible 2.14.2

ksaran@XXXX:/etc/ansible# ansible --version
ansible [core 2.14.2]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/ksaran/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.11/site-packages/ansible

This is my playbook

---
- name: shut_test
  hosts: nva1
  become: yes
  gather_facts: no

  tasks:
    - name: shutting the device
      dellemc.enterprise_sonic.sonic_command:
        commands:
          - 'config t'
          - interface Eth1/7
          - shutdown
          - exit

and the error messages i am getting is

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AssertionError: socket_path must be a value
fatal: [XXXXa.net]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "module_stderr": "Shared connection to XXXX.net closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File "/home/admin/.ansible/tmp/ansible-tmp-1704685988.6898007-1476106-62438890930361/AnsiballZ_sonic_command.py", line 107, in \r\n _ansiballz_main()\r\n File "/home/admin/.ansible/tmp/ansible-tmp-1704685988.6898007-1476106-62438890930361/AnsiballZ_sonic_command.py", line 99, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File "/home/admin/.ansible/tmp/ansible-tmp-1704685988.6898007-1476106-62438890930361/AnsiballZ_sonic_command.py", line 48, in invoke_module\r\n run_name='main', alter_sys=True)\r\n File "/usr/lib/python3.7/runpy.py", line 205, in run_module\r\n return _run_module_code(code, init_globals, run_name, mod_spec)\r\n File "/usr/lib/python3.7/runpy.py", line 96, in _run_module_code\r\n mod_name, mod_spec, pkg_name, script_name)\r\n File "/usr/lib/python3.7/runpy.py", line 85, in _run_code\r\n exec(code, run_globals)\r\n File "/tmp/ansible_dellemc.enterprise_sonic.sonic_command_payload_ncieeksa/ansible_dellemc.enterprise_sonic.sonic_command_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/modules/sonic_command.py", line 235, in \r\n File "/tmp/ansible_dellemc.enterprise_sonic.sonic_command_payload_ncieeksa/ansible_dellemc.enterprise_sonic.sonic_command_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/modules/sonic_command.py", line 207, in main\r\n File "/tmp/ansible_dellemc.enterprise_sonic.sonic_command_payload_ncieeksa/ansible_dellemc.enterprise_sonic.sonic_command_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/sonic.py", line 121, in run_commands\r\n File "/tmp/ansible_dellemc.enterprise_sonic.sonic_command_payload_ncieeksa/ansible_dellemc.enterprise_sonic.sonic_command_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/sonic.py", line 52, in get_connection\r\n File "/tmp/ansible_dellemc.enterprise_sonic.sonic_command_payload_ncieeksa/ansible_dellemc.enterprise_sonic.sonic_command_payload.zip/ansible_collections/dellemc/enterprise_sonic/plugins/module_utils/network/sonic/sonic.py", line 66, in get_capabilities\r\n File "/tmp/ansible_dellemc.enterprise_sonic.sonic_command_payload_ncieeksa/ansible_dellemc.enterprise_sonic.sonic_command_payload.zip/ansible/module_utils/connection.py", line 124, in init\r\nAssertionError: socket_path must be a value\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

Add ability to specify VLAN description/name

SUMMARY

VLAN description/name is a pretty basic idea and SONIC supports it in the CLI.

ISSUE TYPE
  • Feature Idea
COMPONENT NAME

sonic_vlans

ADDITIONAL INFORMATION

Something like this:

sonic_vlans:
      config:
          - vlan_id: 2
            description: "Internal"
        state: merged

[BUG]: sonic_interfaces falsely claims changes are done/needed for Loopback interface

Bug Description

After successfully using sonic_interfaces to configure a description on a Loopback interface (which needs to already exist due to #358), repeated playbook runs will claim there the description must be set/changed, even though the description already has been set correctly. This does not happen for Ethernet interfaces.

For example, given the following starting point:

# show running-configuration interface Loopback 0
!
interface Loopback 0
 description "Loopback Zero"

Running the following task (with --check):

- name: Configure interfaces
  dellemc.enterprise_sonic.sonic_interfaces:
    config:
      - name: Loopback0
        description: Loopback Zero

Yields the following output:

TASK [Configure interfaces] ****************************************************
*** before
--- after
***************
*** 449,454 ****
--- 449,455 ----
          'speed': 'SPEED_25GB'
      },
      {
+         'description': 'Loopback Zero',
          'name': 'Loopback0'
      },
      {
changed: [switch]

Running ansible-playbook with --diff but without --check will for some reason make the diff not be displayed, but it still report changed:. With --check enabled, --diff works and the diff is displayed. This is the case both if the interface description actually was set/changed, but also when there was no actual change performed.

Product Name

SONiC-OS-4.2.0-Enterprise_Base

Component or Module Name

sonic_interfaces

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.4.0

SONiC Software Version

SONiC-OS-4.2.0-Enterprise_Base

Configuration

CONFIG_FILE() = /home/debian/ansible/ansible.cfg
DEFAULT_HASH_BEHAVIOUR(/home/debian/ansible/ansible.cfg) = merge
DEFAULT_HOST_LIST(/home/debian/ansible/ansible.cfg) = ['/home/debian/ansible/hosts.yml']
DEFAULT_JINJA2_EXTENSIONS(/home/debian/ansible/ansible.cfg) = jinja2.ext.do
HOST_KEY_CHECKING(/home/debian/ansible/ansible.cfg) = False
INTERPRETER_PYTHON(/home/debian/ansible/ansible.cfg) = auto_silent
MAX_FILE_SIZE_FOR_DIFF(/home/debian/ansible/ansible.cfg) = 1048576
PERSISTENT_COMMAND_TIMEOUT(/home/debian/ansible/ansible.cfg) = 3000

Steps to Reproduce

Described above

Expected Behavior

a. ansible-playbook should report ok: [switch] if the Loopback interface description was already set correctly
b. ansible-playbook --diff (without --check) should show a diff if the Loopback inteface was set/changed

Actual Behavior

a. ansible-playbook reports changed: [switch] even though Loopback interface description was already set correctly
b. ansible-playbook --diff (without --check) does not show a diff if the Loopback inteface was set/changed

Logs

Described above

Screenshots

No response

Additional Information

No response

[BUG]: sonic_prefix_lists falsely claim changes are done/necessary if 'le' is 32 (IPv4) or 128 (IPv6)

Bug Description

When applying the playbook containing prefix lists with le 32 (IPv4) or le 128 (IPv6), each and every subsequent run will claim there are changes to the prefix lists, even though that is not the case. This happens in with and without --check. Furthermore, --diff does not reveal what the claimed changes are, though the JSON output from --verbose gives a clue.

Product Name

SONiC-OS-4.2.0-Enterprise_Base

Component or Module Name

sonic_prefix_lists

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.4.0

SONiC Software Version

SONiC-OS-4.2.0-Enterprise_Base

Configuration

CONFIG_FILE() = /home/debian/ansible/ansible.cfg
DEFAULT_HASH_BEHAVIOUR(/home/debian/ansible/ansible.cfg) = merge
DEFAULT_HOST_LIST(/home/debian/ansible/ansible.cfg) = ['/home/debian/ansible/hosts.yml']
DEFAULT_JINJA2_EXTENSIONS(/home/debian/ansible/ansible.cfg) = jinja2.ext.do
HOST_KEY_CHECKING(/home/debian/ansible/ansible.cfg) = False
INTERPRETER_PYTHON(/home/debian/ansible/ansible.cfg) = auto_silent
MAX_FILE_SIZE_FOR_DIFF(/home/debian/ansible/ansible.cfg) = 1048576
PERSISTENT_COMMAND_TIMEOUT(/home/debian/ansible/ansible.cfg) = 3000

Steps to Reproduce

Run the following tasks at least twice:

    - name: Configure prefix lists
      dellemc.enterprise_sonic.sonic_prefix_lists:
        config:
          - name: ROUTESERVERS-IN-IPV4
            afi: ipv4
            prefixes:
              - sequence: 65535
                action: deny
                prefix: 0.0.0.0/0
                le: 32
          - name: ROUTESERVERS-IN-IPV6
            afi: ipv6
            prefixes:
              - sequence: 65535
                action: deny
                prefix: ::/0
                le: 128
          - name: ROUTESERVERS-OUT-IPV4
            afi: ipv4
            prefixes:
              - sequence: 65535
                action: deny
                prefix: 0.0.0.0/0
                le: 32
          - name: ROUTESERVERS-OUT-IPV6
            afi: ipv6
            prefixes:
              - sequence: 65535
                action: deny
                prefix: ::/0
                le: 128

Expected Behavior

a. Ansible-playbook should report changed on the initial run, when the prefix lists are created in the first place.
b. Ansible-playbook should report ok (that is: not changed) on subsequent runs.
c. Ansible-playbook should show a diff when run with --diff when it reports changed.

Actual Behavior

a. Ansible-playbook repors changed on the initial run, when the prefix lists are created in the first place. (this is OK)
b. Ansible-playbook reports changed on subsequent runs.
c. Ansible-playbook does not show a diff when run with --diff when it reports changed.

Logs

Subsequent runs show the following:

PLAY [ent_sonic] ***************************************************************

TASK [Configure prefix lists] **************************************************
changed: [leaf1]

PLAY RECAP *********************************************************************
leaf1   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Screenshots

When running with --verbose, the additional output reveals more of what is going on:

changed: [leaf1] => {"after": [{"afi": "ipv4", "name": "ROUTESERVERS-IN-IPV4", "prefixes": [{"action": "deny", "ge": null, "le": null, "prefix": "0.0.0.0/0", "sequence": 65535}]}, {"afi": "ipv6", "name": "ROUTESERVERS-IN-IPV6", "prefixes": [{"action": "deny", "ge": null, "le": null, "prefix": "::/0", "sequence": 65535}]}, {"afi": "ipv4", "name": "ROUTESERVERS-OUT-IPV4", "prefixes": [{"action": "deny", "ge": null, "le": null, "prefix": "0.0.0.0/0", "sequence": 65535}]}, {"afi": "ipv6", "name": "ROUTESERVERS-OUT-IPV6", "prefixes": [{"action": "deny", "ge": null, "le": null, "prefix": "::/0", "sequence": 65535}]}], "before": [{"afi": "ipv4", "name": "ROUTESERVERS-IN-IPV4", "prefixes": [{"action": "deny", "ge": null, "le": null, "prefix": "0.0.0.0/0", "sequence": 65535}]}, {"afi": "ipv6", "name": "ROUTESERVERS-IN-IPV6", "prefixes": [{"action": "deny", "ge": null, "le": null, "prefix": "::/0", "sequence": 65535}]}, {"afi": "ipv4", "name": "ROUTESERVERS-OUT-IPV4", "prefixes": [{"action": "deny", "ge": null, "le": null, "prefix": "0.0.0.0/0", "sequence": 65535}]}, {"afi": "ipv6", "name": "ROUTESERVERS-OUT-IPV6", "prefixes": [{"action": "deny", "ge": null, "le": null, "prefix": "::/0", "sequence": 65535}]}], "changed": true, "commands": [{"afi": "ipv4", "name": "ROUTESERVERS-IN-IPV4", "prefixes": [{"action": "deny", "le": 32, "prefix": "0.0.0.0/0", "sequence": 65535}], "state": "merged"}, {"afi": "ipv6", "name": "ROUTESERVERS-IN-IPV6", "prefixes": [{"action": "deny", "le": 128, "prefix": "::/0", "sequence": 65535}], "state": "merged"}, {"afi": "ipv4", "name": "ROUTESERVERS-OUT-IPV4", "prefixes": [{"action": "deny", "le": 32, "prefix": "0.0.0.0/0", "sequence": 65535}], "state": "merged"}, {"afi": "ipv6", "name": "ROUTESERVERS-OUT-IPV6", "prefixes": [{"action": "deny", "le": 128, "prefix": "::/0", "sequence": 65535}], "state": "merged"}]}

If I copy'n'paste this JSON blob into a file, I observe the following clues:

  1. The before and after blobs are exactly the same. This probably explains the missing output from --diff.
  2. Both the before and after blobs contain "le": null. This is obviously not correct, and probably explains why the module feels the need to change something.
  3. Diffing the before/after blobs with commands reveals an attempted change to the le attribute:
$ diff -u <(jq .before < out.json ) <(jq .commands < out.json)
--- /dev/fd/63  2024-03-26 11:26:07.403271295 +0100
+++ /dev/fd/62  2024-03-26 11:26:07.404271298 +0100
@@ -5,12 +5,12 @@
     "prefixes": [
       {
         "action": "deny",
-        "ge": null,
-        "le": null,
+        "le": 32,
         "prefix": "0.0.0.0/0",
         "sequence": 65535
       }
-    ]
+    ],
+    "state": "merged"
   },
   {
     "afi": "ipv6",
@@ -18,12 +18,12 @@
     "prefixes": [
       {
         "action": "deny",
-        "ge": null,
-        "le": null,
+        "le": 128,
         "prefix": "::/0",
         "sequence": 65535
       }
-    ]
+    ],
+    "state": "merged"
   },
   {
     "afi": "ipv4",
@@ -31,12 +31,12 @@
     "prefixes": [
       {
         "action": "deny",
-        "ge": null,
-        "le": null,
+        "le": 32,
         "prefix": "0.0.0.0/0",
         "sequence": 65535
       }
-    ]
+    ],
+    "state": "merged"
   },
   {
     "afi": "ipv6",
@@ -44,11 +44,11 @@
     "prefixes": [
       {
         "action": "deny",
-        "ge": null,
-        "le": null,
+        "le": 128,
         "prefix": "::/0",
         "sequence": 65535
       }
-    ]
+    ],
+    "state": "merged"
   }
 ]

Through experimentation I have found that this only happens for le values 32 and 128. If I change le to 31 and 127, subsequent playbook runs report ok and the commands blob in the JSON contains an empty array. The same happens if I remove le altogether. (Obviously this changes which prefixes are actually matched by the prefix list, so it cannot be used as a workaround.)

Finally, I'd like to note that specifying le 32/128 actually works as expected, in the sense that they end up being configured as such:

leaf1# show running-configuration | grep ROUTESERVERS
ip prefix-list ROUTESERVERS-IN-IPV4 seq 65535 deny 0.0.0.0/0 le 32
ip prefix-list ROUTESERVERS-OUT-IPV4 seq 65535 deny 0.0.0.0/0 le 32
ipv6 prefix-list ROUTESERVERS-IN-IPV6 seq 65535 deny ::/0 le 128
ipv6 prefix-list ROUTESERVERS-OUT-IPV6 seq 65535 deny ::/0 le 128

(Note: I put the above in the «Screenshots» text area, since the «Additional Information» only accepts a single line.)

Additional Information

No response

[BUG]: deleting one IP address from interface is removing all IP addresses

Bug Description

Configure more than 1 IP addresses on an interface as follows (using CLI) and then try to remove one of the secondary addresses using the playbook. This deletes all IP addresses instead of deleting one of them.
conf t
interface-naming standard extended
interface Ethernet0
ip address 11.22.33.44/8
ip address 55.66.77.88/8 secondary
ip address 1.1.1.1/8 secondary
ip address 2.2.2.2/8 secondary

PLAYBOOK:

  • name: Ansible resource module example
    hosts: datacenter
    gather_facts: False
    connection: httpapi
    collections:
    • dellemc.enterprise_sonic
      tasks:
    • name: sonic_l3_interfaces IP delete
      sonic_l3_interfaces:
      config:
      • name: Ethernet0
        ipv4:
        addresses:
        - address: 55.66.77.88/8
        secondary: True
        state: deleted

** POSSIBLE SOLUTION: **
File: plugins/module_utils/network/sonic/config/l3_interfaces/l3_interfaces.py
Definition: get_delete_l3_interfaces_requests
Buggy Line: elif ipv4 and ipv4.get('addresses') and not ipv4.get('anycast_addresses'):
Possible Solution: elif ipv4 and not ipv4.get('addresses') and not ipv4.get('anycast_addresses'):

Product Name

eSONiC AnsibleCollections

Component or Module Name

sonic_l3_interfaces

DellEMC Enterprise SONiC Ansible Collection Version

All collections

SONiC Software Version

all esonic versions

Configuration

conf t
interface-naming standard extended
interface Ethernet0
ip address 11.22.33.44/8
ip address 55.66.77.88/8 secondary
ip address 1.1.1.1/8 secondary
ip address 2.2.2.2/8 secondary

Steps to Reproduce

Run the playbook
PLAYBOOK:

  • name: Ansible resource module example
    hosts: datacenter
    gather_facts: False
    connection: httpapi
    collections:
    • dellemc.enterprise_sonic
      tasks:
    • name: sonic_l3_interfaces IP delete
      sonic_l3_interfaces:
      config:
      • name: Ethernet0
        ipv4:
        addresses:
        - address: 55.66.77.88/8
        secondary: True
        state: deleted

Expected Behavior

Supposed to remove only the "55.66.77.88/8" from the list of IP addresses.

Actual Behavior

All IP addresses are getting deleted.

Logs

ALL IP addresses are gone.

Screenshots

No response

Additional Information

No response

[BUG]: sonic_interfaces using overridden shuts down all interfaces

Bug Description

When dellemc.enterprise_sonic.sonic_interfaces is used with state: overridden, it will shut down all interfaces not mentioned in the dict passed to config:.

For example, running the following task:

- name: Configure interfaces
  tags: sonic_interfaces
  dellemc.enterprise_sonic.sonic_interfaces:
    config:
    - name: Loopback0
      description: Router ID
    - name: Loopback1
      description: Logical VTEP
    - name: Ethernet56
      speed: SPEED_40GB
    - name: Ethernet60
      speed: SPEED_40GB
    - name: Ethernet64
      speed: SPEED_40GB
    - name: Ethernet68
      speed: SPEED_40GB
    state: overridden

Results in the following change reported from ansible-playbook -D:

*** before
--- after
***************
*** 1,7 ****
  [
      {
          'auto_negotiate': false,
!         'enabled': true,
          'fec': 'FEC_DISABLED',
          'mtu': 9100,
          'name': 'Ethernet0',
--- 1,7 ----
  [
      {
          'auto_negotiate': false,
!         'enabled': false,
          'fec': 'FEC_DISABLED',
          'mtu': 9100,
          'name': 'Ethernet0',

Note how Ethernet0 is not mentioned in the config: dict, yet it is impacted by this change. So is almost every other interface on the device (including VlanXX and PortChannelXX interfaces).

This behaviour runs counter to the documentation. In the example using overridden, the before state shows Ethernet0 and Ethernet4 being UP:

# Using overridden
#
# Before state:
# -------------
#
# show interface status | no-more
#------------------------------------------------------------------------------------------
#Name Description Admin Oper AutoNeg Speed MTU
#------------------------------------------------------------------------------------------
#Ethernet0 E0 up 100000 9100
#Ethernet4 E4 up 100000 9100
#Ethernet8 E8 down 100000 9100
#Ethernet12 - down 1000 9100
#Ethernet16 - down 100000 9100

The documentation then goes on to show how the dellemc.enteprise_sonic.sonic_interfaces is called with a config dict that does not mention neither Ethernet0 nor Ethernet4:

- name: Configure interfaces
sonic_interfaces:
config:
- name: Ethernet8
fec: FEC_AUTO
- name: Ethernet12
description: 'Ethernet Twelve'
mtu: 3500
enabled: True
auto_negotiate: True
- name: Ethernet16
description: 'Ethernet Sixteen'
mtu: 3000
enabled: False
speed: SPEED_40GB
state: overridden

Finally, in the after state, Ethernet0 and Ethernet4 is shown as still UP:

#
# After state:
# ------------
#
# show interface status | no-more
#------------------------------------------------------------------------------------------
#Name Description Admin Oper AutoNeg Speed MTU
#------------------------------------------------------------------------------------------
#Ethernet0 - up 100000 9100
#Ethernet4 - up 100000 9100
#Ethernet8 - up 100000 9100
#Ethernet12 Ethernet Twelve up on 100000 3500
#Ethernet16 Ethernet Sixteen down 40000 3000

Product Name

SONiC-OS-4.2.0-Enterprise_Base

Component or Module Name

sonic_interfaces

DellEMC Enterprise SONiC Ansible Collection Version

dellemc.enterprise_sonic 2.4.0

SONiC Software Version

SONiC-OS-4.2.0-Enterprise_Base

Configuration

CONFIG_FILE() = /home/debian/ansible/ansible.cfg
DEFAULT_HASH_BEHAVIOUR(/home/debian/ansible/ansible.cfg) = merge
DEFAULT_HOST_LIST(/home/debian/ansible/ansible.cfg) = ['/home/debian/ansible/hosts.yml']
DEFAULT_JINJA2_EXTENSIONS(/home/debian/ansible/ansible.cfg) = jinja2.ext.do
HOST_KEY_CHECKING(/home/debian/ansible/ansible.cfg) = False
INTERPRETER_PYTHON(/home/debian/ansible/ansible.cfg) = auto_silent
MAX_FILE_SIZE_FOR_DIFF(/home/debian/ansible/ansible.cfg) = 1048576
PERSISTENT_COMMAND_TIMEOUT(/home/debian/ansible/ansible.cfg) = 3000

Steps to Reproduce

See above

Expected Behavior

Interfaces not mentioned in config dict should not be shut down (or the documentation should state that they will be)

Actual Behavior

Interfaces not mentioned in the config dict are shut down.

Logs

See above

Screenshots

See above

Additional Information

This does not happen with dellemc.enterprise_sonic 2.2.0. Testing this version, Ethernet 0 remains UP (in no shutdown) after the task has run. It is necessary to upgrade to 2.4.0 to reproduce the bug.

Important information for collection maintainers

SUMMARY

Dear maintainers,

This is important for your collections!

  • In accordance with the Community decision, we have created the news-for-maintainers repository for announcements of changes impacting collection maintainers (see the examples) instead of Issue 45 that will be closed soon.

    • To keep yourself well-informed and, therefore, things in your collection working, please subscribe to the repository by using the Watch button in the upper right corner on the repository's home page.
    • If you do not want to get notifications about related discussions, please subscribe only to Issues.
    • Please read the brief guidelines on how the repository should be used.
    • Please avoid unnecessary discussions in issues, use the Discussions feature. Every comment posted will notify a lot of folks!
  • Also we would like to remind you about the Bullhorn contributor newsletter which has recently started to be released weekly. To learn what it looks like, see the past releases. Please subscribe and talk to the Community via Bullhorn!

  • Join us in #ansible-social (for news reporting & chat), #ansible-community (for discussing collection & maintainer topics), and other channels on Matrix/IRC.

  • Help the Community and the Steering Committee to make right decisions by taking part in discussing and voting on the Community Topics that impact the whole project and the collections in particular. Your opinion there will be much appreciated!

Thank you!

Please use FQCN in the readme example playbooks

SUMMARY

To be consistent in documentation and avoid any problems, can you please modify the playbook etc samples in the readme file to use FQCN?
Note: this is not a blocker issue, just a nice to have.

ISSUE TYPE
  • Documentation Report
COMPONENT NAME
ANSIBLE VERSION

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.