ntc-ansible “response” and “module_args” (how acce

2019-09-22 03:49发布

问题:

I am using the networktocode ntc-ansible module in Ansible to control Cisco IOS devices (switches currently). I successfully can use ntc_show_Command to get 'show version' and 'show ip int brief' and put the result into a local file. But when I use the -vvv at the end of the ansible-playbook command, I see structured JSON output in the terminal. How do I get a access the "module_args" and the "response" from the ntc_show_command, ie. if i use "show ip int brief" and i want to know the status of int gi1/0/5. How can I access that? And then... what playbook commands would/could I use to grab the specific data I am looking for?

Here is the output I can see when I run the playbook, with -vvv, but I don't know how to access the structured data

ok: [VTgroup_SW] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "command": "show ip interface brief",
            "connection": "ssh",
            "connection_args": {},
            "delay": "1",
            "file": null,
            "global_delay_factor": "1",
            "host": "x.x.x.x",
            "index_file": "index",
            "key_file": null,
            "local_file": "verification/192.168.2.101.cfg",
            "optional_args": {},
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "platform": "cisco_ios",
            "port": null,
            "provider": null,
            "secret": null,
            "template_dir": "/home/melshman/.ansible/plugins/modules/ntc- 
ansible/ntc-templates/templates",
            "trigger_device_list": null,
            "use_keys": false,
            "use_templates": true,
            "username": "admin"
        }
    },
    "response": [
        {
            "intf": "Vlan1",
            "ipaddr": "y.y.y.y",
            "proto": "down",
            "status": "administratively down"
        },
        {
            "intf": "Vlan2",
            "ipaddr": "x.x.x.x",
            "proto": "up",
            "status": "up"
        },
TRUNCATED...

Here is the output of the Show ip int brief in the local file.

Interface              IP-Address      OK? Method Status                
Protocol
Vlan1                  172.16.x.xxx    YES NVRAM  administratively down down
Vlan2                  192.168.x.xxx   YES NVRAM  up                    up
Vlan10                 10.10.yy.xxx      YES NVRAM  administratively down down

Here is my play...

    - name: VERIFY INTERFACES
      ntc_show_command:
        connection: ssh
        platform: "cisco_ios"
        command: 'show ip interface brief'
        delay: 1 # delay before performing actions / commands in seconds
        global_delay_factor: 1 # delay between commands
        local_file: verification/{{ ansible_host }}.cfg
        host: "{{ ansible_host }}"
        username: "{{ ansible_user }}"
        password: "{{ ansible_ssh_pass }}"
        use_templates: True
        template_dir: '/home/melshman/.ansible/plugins/modules/ntc- 
  ansible/ntc-templates/templates'

UPDATE I updated code based on suggestions as such:

I made progress, but I seem to still be missing something important. My first debug statement (below) is outputting the full output (not shown here), which works. I can set_fact successfully to 'interfaces'. I can loop through the interfaces variable and detect a condition set with the when statement, which I changed to look for all up/up interfaces. BUT... my output (shown below doesn't show the details yours showed. Mine shows (item=None) for all and an OK on items which match the criteria, but not the details your output shows (your second code block in original answer).
UPDATED - I modified the debug var to 'item.intf' and now I get intf name, but still not all details.

**QUESTION: How can I grab an output that shows only the interfaces that meet the criteria? Can this structured data be saved to a file?

UPDATE 2::: I was able to use the copy module to copy {{ interfaces }} to a file as structured data, but when I try to just show the interfaces, and not the rest of the data, but using {{ interfaces.intf }} I get an error. (See below)

Question: How can I get a output / file that shows only the interface names?
Question: How can I get an output / file that shows only the interfaces names that are up/up?

My second debug statement (below) is outputting this, which identifies the up/up interfaces: UPDATED.

skipping: [VTgroup_SW] => (item=None)
ok: [VTgroup_SW] => (item=None) => {
    "item.intf": "Vlan2"
}
skipping: [VTgroup_SW] => (item=None)
skipping: [VTgroup_SW] => (item=None)
skipping: [VTgroup_SW] => (item=None)
ok: [VTgroup_SW] => (item=None) => {
    "item.intf": "GigabitEthernet1/0/27"

Additions to playbook UPDATE 2

  - debug:
      var: output

  - set_fact:
      interfaces: "{{ output.response }}"

# shows all the intf that are up/up
  - debug:
      var: item.intf
    when:
      - '"up" in item.proto'
      - '"up" in item.status'
    loop: "{{ interfaces }}"


  - name:  Structured Data - INTERFACES
    copy:
      content:  "{{ interfaces }}"
      dest: "verification/interfaces_{{ansible_host}}.txt"

# This causes error (see traceback)
  - name:  Structured Data - INTERFACES with .intf
    copy:
      content:  "{{ interfaces.intf }}"
      dest: "verification/interfaces_{{ansible_host}}.txt"

Output from play; - name: Structured Data - INTERFACES (TRUNCATED)

[{"status": "administratively down", "intf": "Vlan1", "ipaddr": "172.16.0.253", "proto": "down"}, {"status": "up", "intf": "Vlan2", "ipaddr": "192.168.2.101", "proto": "up"}, {"status": "administratively down", "intf": "Vlan10", "ipaddr": "10.10.10.1", "proto": "down"}, {"status": "administratively down", "intf": "Vlan20", "ipaddr": "10.10.20.1", "proto": "down"}, {"status": "administratively down", "intf": "Vlan51", "ipaddr": "192.168.1.1", "proto": "down"}, ---- TRUNCATED

Traceback on last play; - name: Structured Data - INTERFACES with .intf

TASK [Structured Data - INTERFACES] ************************************************************************************
task path: /home/melshman/projects/ansible/from-kbyer-ios-pb.yml:117
fatal: [VTgroup_SW]: FAILED! => {
    "msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'intf'\n\nThe error appears to have been in '/home/melshman/projects/ansible/from-kbyer-ios-pb.yml': line 117, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n  - name:  Structured Data - INTERFACES\n    ^ here\n"

回答1:

You need to register the output and then start using debug and set_fact to retrieve the data structure elements that you want to retrieve:

Here I register the output and then only retrieve the 'FastEthernet4' interface.

- name: Cisco IOS Automation
  hosts: pynet-rtr1
  connection: local
  gather_facts: no

  tasks:
    - name: VERIFY INTERFACES
      ntc_show_command:
        connection: ssh
        platform: "cisco_ios"
        command: 'show ip interface brief'
        host: "{{ ansible_host }}"
        username: "{{ ansible_user }}"
        password: "{{ ansible_ssh_pass }}"
        use_templates: True
        template_dir: '/home/kbyers/ntc-templates/templates'
      register: output

    - debug:
        var: output

    - set_fact:
        interfaces: "{{ output.response }}"

    - debug:
        var: item
      when: '"FastEthernet4" in item.intf'
      loop: "{{ interfaces }}"

Once again you could do another set_fact and save only this FastEthernet4 interface and then look at the 'proto' and 'status' fields (i.e. 'up' and 'up').

Here is what the very end of the execution looks like:

TASK [debug] *****************************************************************************************************************************************************************************
skipping: [pynet-rtr1] => (item={u'status': u'down', u'intf': u'FastEthernet0', u'ipaddr': u'unassigned', u'proto': u'down'}) 
skipping: [pynet-rtr1] => (item={u'status': u'down', u'intf': u'FastEthernet1', u'ipaddr': u'unassigned', u'proto': u'down'}) 
skipping: [pynet-rtr1] => (item={u'status': u'down', u'intf': u'FastEthernet2', u'ipaddr': u'unassigned', u'proto': u'down'}) 
skipping: [pynet-rtr1] => (item={u'status': u'down', u'intf': u'FastEthernet3', u'ipaddr': u'unassigned', u'proto': u'down'}) 
ok: [pynet-rtr1] => (item={u'status': u'up', u'intf': u'FastEthernet4', u'ipaddr': u'10.220.88.20', u'proto': u'up'}) => {
    "item": {
        "intf": "FastEthernet4", 
        "ipaddr": "10.220.88.20", 
        "proto": "up", 
        "status": "up"
    }
}
skipping: [pynet-rtr1] => (item={u'status': u'down', u'intf': u'Vlan1', u'ipaddr': u'unassigned', u'proto': u'down'}) 

PLAY RECAP *******************************************************************************************************************************************************************************
pynet-rtr1                 : ok=4    changed=0    unreachable=0    failed=0   

Adding more info on the set_fact (i.e. here is how you could save a variable corresponding to only that one interface).

- set_fact:
    intf_fa4: "{{ item }}"
  when: '"FastEthernet4" in item.intf'
  loop: "{{ interfaces }}"

- debug:
    var: intf_fa4