jedelman8 / nxos-ansible

Ansible modules to automate Cisco NX-OS switches
Other
169 stars 106 forks source link

Syntax for hosts variables #74

Closed krikoon73 closed 7 years ago

krikoon73 commented 8 years ago

Hello,

I'm trying to streamline CLI conf as you explained in the README.md.

But I have the following issue when I apply the playbook :

[config_builder] $ ansible-playbook vxlan_builder.yml 

PLAY [Generate VXLAN Underlay CLI commands for Leaves] ************************ 

TASK: [template src=templates/Leaf-template-CREATE.j2 dest=configs/{{ inventory_hostname }}_underlay.cfg] *** 
ok: [ilm-nxos-vtep2]
ok: [ilm-nxos-vtep1]

PLAY [Generate VXLAN Underlay CLI commands for Spines] ************************ 

TASK: [template src=templates/Spine-template-CREATE.j2 dest=configs/{{ inventory_hostname }}_underlay.cfg] *** 
ok: [ilm-nxos-9508]

PLAY [Generate VXLAN Overlay CLI commandes for Leaves for Tenant Production] *** 

TASK: [template src=templates/NewSegment.j2 dest=configs/{{ inventory_hostname }}_overlay.cfg] *** 
fatal: [ilm-nxos-vtep1] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'Loopbacks2'", 'failed': True}
fatal: [ilm-nxos-vtep1] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'Loopbacks2'", 'failed': True}
fatal: [ilm-nxos-vtep2] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'Loopbacks2'", 'failed': True}
fatal: [ilm-nxos-vtep2] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'Loopbacks2'", 'failed': True}

FATAL: all hosts have already failed -- aborting

PLAY RECAP ******************************************************************** 
           to retry, use: --limit @/Users/ccompain/vxlan_builder.retry

ilm-nxos-9508              : ok=1    changed=0    unreachable=0    failed=0   
ilm-nxos-vtep1             : ok=1    changed=0    unreachable=1    failed=0   
ilm-nxos-vtep2             : ok=1    changed=0    unreachable=1    failed=0   

Version of Ansible : [config_builder] $ ansible --version ansible 1.9.4 configured module search path = /usr/local/share/ansible

OSX 10.11.3

I'm using the following yml for hosts_var :

'---
'
'ip: ilm-nxos-vtep1
'username: admin
'password: cisco
'template: Leaf-template-CREATE.j2
'mcast_range: 232.0.0.0/8
'Overlays:
' - {id: nve1, loopback: loopback0}
'Interfaces:
' - {id: e2/1, descr: To_Spine, ip: 100.1.10.1/24, ospf_process: 1, ospf_area: 0.0.0.0}
'Loopbacks:
' - {id: loopback0, ip: 100.0.0.1/32, ospf_process: 1, ospf_area: 0.0.0.0}
'ospf_process: 1
'ospf_router_id : 100.0.0.1
'bgp_asn : 65000
'bgp_router_id: 100.0.0.1
'bgp_neighbors:
' - {ip: 100.0.0.10, asn: 65000}
'Tenants:
' name: Production
' Loopbacks2:
' - {id: loopback1, ip: 20.20.20.1/32}
' L3Vlan: 100
' L3vnid: 10000
' L2Segments:
' - {vlan: 101, vnid: 10001, IPDG: 101.0.0.254/24}
' - {vlan: 102, vnid: 10002, IPDG: 102.0.0.254/24}
' - {vlan: 103, vnid: 10003, IPDG: 103.0.0.254/24}
' name: TestBed
' L3Vlan: 200
' L3vnid: 20000
' L2Segments:
' - {vlan: 201, vnid: 20001, IPDG: 201.0.0.254/24}
' - {vlan: 202, vnid: 20002, IPDG: 202.0.0.254/24}
' - {vlan: 203, vnid: 20003, IPDG: 203.0.0.254/24}

FYI : the playbook run well if I drop the [Tenants] part of the yml file. I think it is just a question of syntax but I didn't find a good tuto for knowing what are the limits/rules in terms of arbo. I would like to have 4 levels of indent.

The Jinja template is :

'route-map matchtag
' match tag 1234
'{% for tenant in Tenants %}
'{% for Loopback in tenant.Loopbacks2%}
'interface {{ Loopback.id }}
'  vrf member {{ tenant.name }}
'  ip address {{ Loopback.ip }} tag 1234
'{% endfor %}
'vlan {{ tenant.L3Vlan }}
'  name L3_VNI_VLAN_{{ tenant.L3Vlan }}_for_{{tenant.name}}
'  vn-segment {{ tenant.L3vnid }}
'vrf context {{ tenant.name }}
'  vni {{ tenant.L3vnid }}
'  rd auto
'  address-family ipv4 unicast
'    route-target import {{ tenant.L3vnid }}:{{ tenant.L3vnid }}
'    route-target export {{ tenant.L3vnid }}:{{ tenant.L3vnid }}
'    route-target both auto evpn
'interface Vlan{{ tenant.L3Vlan }}
'  description *** L3_VNI_VLAN_{{ tenant.L3Vlan }}_for_{{tenant.name}} ***
'  no shutdown
'  vrf member {{ tenant.name }}
'interface nve1
'  member vni {{ tenant.L3vnid }} associate-vrf
'router bgp 65000
'  vrf {{ tenant.name }}
'    address-family ipv4 unicast
'      advertise l2vpn evpn
'      redistribute direct route-map matchtag
'{% for segment in tenant.L2Segments %}
'vlan {{ segment.vlan }}
'  name L2_VNI_VLAN_{{ segment.vlan }}_for_{{tenant.name}}
'  vn-segment {{ segment.vnid }}
'interface Vlan{{ segment.vlan }}
'  description *** L2_VNI_VLAN_{{ segment.vlan }}_for_{{tenant.name}} ***
'  no shutdown
'  vrf member {{tenant.name}}
'  ip address {{ segment.IPDG }} tag 1234
'  fabric forwarding mode anycast-gateway
'interface nve1
'  member vni {{ segment.vnid }}
'    mcast-group 239.1.1.1
'evpn
'  vni {{ segment.vnid }} l2
'    rd auto
'    route-target import auto
'    route-target export auto
'{% endfor %}
'{% endfor %}

Thanks in advance,

Christophe

jedelman8 commented 8 years ago

Can you add task at the top of your playbook that uses the debug module?

debug: var=Tenants

Let's see what it thinks Tenants is. Also, why do you have a single quote in front of each line in your template?

krikoon73 commented 8 years ago

I put a single quote just to be sure that the "github editor" doesn't interpret any characters ... I very very new to github ... :-)

I executed the debug and I have the following output which is quite strange because I cannot found any "Production" section in the json.

Any idee ?

[config_builder] $ ansible-playbook vxlan_builder.yml 

PLAY [Generate VXLAN Underlay CLI commands for Leaves] ************************ 

TASK: [template src=templates/Leaf-template-CREATE.j2 dest=configs/{{ inventory_hostname }}_underlay.cfg] *** 
ok: [ilm-nxos-vtep1]
ok: [ilm-nxos-vtep2]

PLAY [Generate VXLAN Underlay CLI commands for Spines] ************************ 

TASK: [template src=templates/Spine-template-CREATE.j2 dest=configs/{{ inventory_hostname }}_underlay.cfg] *** 
ok: [ilm-nxos-9508]

PLAY [Generate VXLAN Overlay CLI commandes for Leaves for Tenant Production] *** 

TASK: [debug var=Tenants] ***************************************************** 
ok: [ilm-nxos-vtep1] => {
    "var": {
        "Tenants": {
            "L2Segments": [
                {
                    "IPDG": "201.0.0.254/24", 
                    "vlan": 201, 
                    "vnid": 20001
                }, 
                {
                    "IPDG": "202.0.0.254/24", 
                    "vlan": 202, 
                    "vnid": 20002
                }, 
                {
                    "IPDG": "203.0.0.254/24", 
                    "vlan": 203, 
                    "vnid": 20003
                }
            ], 
            "L3Vlan": 200, 
            "L3vnid": 20000, 
            "Loopbacks2": [
                {
                    "id": "loopback1", 
                    "ip": "20.20.20.1/32"
                }
            ], 
            "name": "TestBed"
        }
    }
}
ok: [ilm-nxos-vtep2] => {
    "var": {
        "Tenants": {
            "L2Segments": [
                {
                    "IPDG": "201.0.0.254/24", 
                    "vlan": 201, 
                    "vnid": 20001
                }, 
                {
                    "IPDG": "202.0.0.254/24", 
                    "vlan": 202, 
                    "vnid": 20002
                }, 
                {
                    "IPDG": "203.0.0.254/24", 
                    "vlan": 203, 
                    "vnid": 20003
                }
            ], 
            "L3Vlan": 200, 
            "L3vnid": 20000, 
            "Loopbacks2": [
                {
                    "id": "loopback1", 
                    "ip": "20.20.20.1/32"
                }
            ], 
            "name": "TestBed"
        }
    }
}

TASK: [template src=templates/NewSegment.j2 dest=configs/{{ inventory_hostname }}_overlay.cfg] *** 
fatal: [ilm-nxos-vtep1] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'Loopbacks2'", 'failed': True}
fatal: [ilm-nxos-vtep1] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'Loopbacks2'", 'failed': True}
fatal: [ilm-nxos-vtep2] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'Loopbacks2'", 'failed': True}
fatal: [ilm-nxos-vtep2] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'Loopbacks2'", 'failed': True}

FATAL: all hosts have already failed -- aborting

PLAY RECAP ******************************************************************** 
           to retry, use: --limit @/Users/ccompain/vxlan_builder.retry

ilm-nxos-9508              : ok=1    changed=0    unreachable=0    failed=0   
ilm-nxos-vtep1             : ok=2    changed=0    unreachable=1    failed=0   
ilm-nxos-vtep2             : ok=2    changed=0    unreachable=1    failed=0  
jedelman8 commented 8 years ago

Okay, when you post output from your terminal, can you make it a code block? You can see how I'm updating your comments making them easier to read. You can use <> button or use back-ticks, i.e. ``` above and below your code.

Can you verify the template you pasted is NewSegment.j2?

jedelman8 commented 8 years ago

Just realized Tenants is a dictionary.

You shouldn't need this:

{% for tenant in Tenants %}

and you can change to this:

{% for Looback in Tenants.Loopbacks2 %}
interface {{ Loopback.id }}
  vrf member {{ tenant.name }}
  ip address {{ Loopback.ip }} tag 1234
< this is a snippet, you'll still need to close the loop, etc. after your next code block>

Make sense? You'll also need to modify other things in the outer loop.
If you do want to loop through a dictionary, you'll need something like for key, value object.iteritems() and for lists, it's how you have it for x in my_list, etc.

Make sense?

krikoon73 commented 8 years ago

I have 2 Tenants => when I look at the debug there is no "Production Tenant". Perhaps, I need also to add a Loopbacks2: section in the tenant TestBed => Make sens ?

As you said, Ansible doesn't loop on the dictionary. I didn't catch what you explained in your previous post.

PS : Thanks for the tips but back-ticks kill the CR. I think I miss something again.

jedelman8 commented 8 years ago

To clarify, this is looping in the Jinja2 template. And it still loops without iteritems, just not on both the keys and values.

I would recommend starting with a smaller template such as this (don't use a big template to get started- too much can go wrong):

Use this:

{% for Looback in Tenants.Loopbacks2 %}
interface {{ Loopback.id }}
  vrf member {{ tenant.name }}
  ip address {{ Loopback.ip }} tag 1234
{% endfor %}

Then gradually add more sections, one at a time to make sure you understand how Jinja2 works.

With your current YAML file, you'll need several more loops just like the one above.

krikoon73 commented 8 years ago

Thanks - Will do - Keep you posted.

krikoon73 commented 8 years ago

Finally I could not reproduce with Ansible what I did whit a python script with the Jinja module. But based on your advice, I found a Ansible solution for my VXLAN lab :

Question : is-it possible to use Ansible to execute on the switches the CLI files generated previously ? (I ask that because the NXAPI 2.0 for VXLAN is not available today / only NXAPI 1.0 CLI)