I want to run these mikrotik commands using ansible
interface bridge port add bridge=bridge1 ingress-filtering=no interface=ether3
interface bridge port add bridge=bridge1 ingress-filtering=no interface=ether4
BUT NOT
interface bridge port add bridge=bridge1 ingress-filtering=no interface=ether3,ether4
my playbook run wrong command
How to fix that
tq
`# cat main.yml
- hosts: mikrotiks
gather_facts: no
connection: network_cli
vars:
ansible_network_os: routeros
vlans:
- 10:
interfaces:
- ether3
- ether4
untagged_interfaces: ether2
tagged_interfaces: bridge1,ether3,ether4
network: 10.0.10.0
netmask: 24
ip_address1: 10.0.10.1
ip_address2: 10.0.10.2
dns: 192.168.88.1
dhcp_pool1: 10.0.10.101-10.0.10.150
dhcp_pool2: 10.0.10.151-10.0.10.200
leasetime: 1d
- 20:
interfaces:
- ether3
- ether4
untagged_interfaces: ether2
tagged_interfaces: bridge1,ether3,ether4
network: 10.0.20.0
netmask: 24
ip_address1: 10.0.20.1
ip_address2: 10.0.20.2
dns: 192.168.88.1
dhcp_pool1: 10.0.20.101-10.0.20.150
dhcp_pool2: 10.0.20.151-10.0.20.200
leasetime: 1d
tasks:
- import_tasks: vlan.yml
cat vlan.yml
- name: create vlans on R1
routeros_command:
commands:
- "interface bridge port add bridge=bridge1 ingress-filtering=no interface={{ item.value.interfaces }}"
- "interface bridge port add bridge=bridge1 frame-types=admit-only-untagged-and-priority-tagged pvid=10 interface={{ item.value.interfaces }}"
with_dict: "{{ vlans }}"\`
EDIT: my mikrotik commands should be like this
R1 /interface bridge port add bridge=bridge1 ingress-filtering=no interface=ether3 add bridge=bridge1 ingress-filtering=no interface=ether4 add bridge=bridge1 frame-types=admit-only-untagged-and-priority-tagged interface=ether2 pvid=10 /interface bridge vlan add bridge=bridge1 tagged=bridge1,ether3,ether4 untagged=ether2 vlan-ids=10 add bridge=bridge1 tagged=bridge1,ether3,ether4 vlan-ids=20
when I use these
\`routeros_command:
commands:
- "/interface bridge port add bridge=bridge1 ingress-filtering=no interface={{ item.1 }}"
- "/interface bridge port add bridge=bridge1 frame-types=admit-only-untagged-and-priority-tagged pvid=10 interface={{ item.1 }}"
with_subelements:
- "{{ vlans }}"
- interfaces`
I got this error
`fatal: [R1]: FAILED! => {
"msg": "could not find 'interfaces' key in iterated item '{10: {'interfaces': ['ether3', 'ether4'], 'untagged_interfaces': 'ether2', 'tagged_interfaces': 'bridge1,ether3,ether4', 'network': '10.0.10.0', 'netmask': 24, 'ip_address1': '10.0.10.1', 'ip_address2': '10.0.10.2', 'dns': '192.168.88.1', 'dhcp_pool1': '10.0.10.101-10.0.10.150', 'dhcp_pool2': '10.0.10.151-10.0.10.200', 'leasetime': '1d'}}'"`
Iterate with_subelements, e.g.
- debug:
msg: "{{ item.0.keys()|first }} ... interface={{ item.1 }}"
with_subelements:
- "{{ vlans }}"
- interfaces
gives
msg: 10 ... interface=ether3
msg: 10 ... interface=ether4
msg: 20 ... interface=ether3
msg: 20 ... interface=ether4
Related
I am writing a playbook to configure Cisco ASA and trying to figure out a way to form route commands based on values from these two lists of dictionaries:
dict1:
- name: Interface_LAN
vrf: LAN
gw: 10.10.10.1
vlan: 10
- name: Interface_DMZ
vrf: DMZ
gw: 10.20.20.1
vlan: 20
dict2:
- name: LAN
vrf: LAN
subnet: 192.168.100.0
- name: LAN2
vrf: LAN
subnet: 192.168.200.0
- name: DMZ
vrf: DMZ
subnet: 192.168.300.0
The item selection per command would be based on the VRF attribute.
The commands I need to construct:
route Interface_LAN 192.168.100.0 255.255.255.0 10.10.10.1 1
route Interface_LAN 192.168.200.0 255.255.255.0 10.10.10.1 1
route Interface_DMZ 192.168.300.0 255.255.255.0 10.20.20.1 1
Could someone suggest a way to do this?
You can use the filter selectattr in order to select the interface matching the VRF from the other list.
You task would then be:
- command: >-
route {{ vrf.name }} {{ item.subnet }} 255.255.255.0 {{ vrf.gw }} 1
loop: "{{ dict2 }}"
loop_control:
label: "{{ item.subnet }}"
vars:
vrf: "{{ dict1 | selectattr('vrf', '==', item.vrf) | first }}"
As a demonstration, given the task:
- debug:
msg: "route {{ vrf.name }} {{ item.subnet }} 255.255.255.0 {{ vrf.gw }} 1"
loop: "{{ dict2 }}"
loop_control:
label: "{{ item.subnet }}"
vars:
vrf: "{{ dict1 | selectattr('vrf', '==', item.vrf) | first }}"
dict1:
- name: Interface_LAN
vrf: LAN
gw: 10.10.10.1
vlan: 10
- name: Interface_DMZ
vrf: DMZ
gw: 10.20.20.1
vlan: 20
dict2:
- name: LAN
vrf: LAN
subnet: 192.168.100.0
- name: LAN2
vrf: LAN
subnet: 192.168.200.0
- name: DMZ
vrf: DMZ
subnet: 192.168.300.0
This yields:
ok: [localhost] => (item=192.168.100.0) =>
msg: route Interface_LAN 192.168.100.0 255.255.255.0 10.10.10.1 1
ok: [localhost] => (item=192.168.200.0) =>
msg: route Interface_LAN 192.168.200.0 255.255.255.0 10.10.10.1 1
ok: [localhost] => (item=192.168.300.0) =>
msg: route Interface_DMZ 192.168.300.0 255.255.255.0 10.20.20.1 1
I want to write an Ansible script for Cisco Catalyst. My target is all ports that are access ports will be configured with spanning-tree bpduguard enable and if there is configured spanning-tree portfast bpdufilter that will be disabled.
I wrote the below script and got the below result where "skip_reason": "Conditional result was False"
if anyone could help I will be very glad.
---
- name: bpdu guard enable
hosts: catalyst
gather_facts: false
vars:
ansible_connection: ansible.netcommon.network_cli
ansible_network_os: cisco.ios.ios
ansible_become: yes
ansible_become_method: enable
ansible_user: ****
ansible_password: ******
tasks:
- name: Gather listed l3 interfaces
cisco.ios.ios_l3_interfaces:
config:
state: gathered
register: f
- name: debug the collected output and file
with_items: '{{ f["gathered"] }}'
debug:
msg: '{{ item["name"] }} is mode {{ item["mode"] }}'
when: 'item["mode"] is defined and item["mode"] == "access"'
- name: conf push no bpdufilter
cisco.ios.ios_config:
lines:
- no spanning-tree portfast bpdufilter
parents: '{{ item["name"] }}'
when: 'item["mode"] is defined and item["mode"] == "access"'
- name: conf push bpduguard
cisco.ios.ios_config:
lines:
- spanning-tree bpduguard enable
parents: '{{ item["name"] }}'
when: 'item["mode"] is defined and item["mode"] == "access"'
I have this simple playbook:
---
- hosts: all
become: yes
vars:
my_hosts:
- 192.168.0.1
- 192.168.0.2
- 192.168.0.3
tasks:
- name: Check ports
wait_for:
port: "{{ item.1 }}"
host: "{{ item.0 }}"
timeout: 10
loop: "{{ product(my_hosts) | product([443, 80443]) | list }}"
When I run it like so ...
$ ansible-playbook -i,192.168.2.2 run_wait_for.yml
... I get this error ...
fatal: [192.168.2.2]: FAILED! => {"msg": "'product' is undefined"}
What am I doing wrong?
Fix the syntax
loop: "{{ my_hosts | product([443, 80443]) }}"
For example
- debug:
msg: "Check host: {{ item.0 }} port: {{ item.1 }}"
loop: "{{ my_hosts|product([443, 80443]) }}"
gives (abridged)
msg: 'Check host: 192.168.0.1 port: 443'
msg: 'Check host: 192.168.0.1 port: 80443'
msg: 'Check host: 192.168.0.2 port: 443'
msg: 'Check host: 192.168.0.2 port: 80443'
msg: 'Check host: 192.168.0.3 port: 443'
msg: 'Check host: 192.168.0.3 port: 80443'
I've Ansible 2.9 and this worked to me:
---
- name: Playbook for Check Ports
hosts: localhost
connection: local
gather_facts: no
vars:
my_hosts:
- 192.168.0.1
- 192.168.0.2
- 192.168.0.3
ports:
- 443
- 80443
tasks:
- name: Check Ports.
debug:
msg: "Check host: {{ item[0] }} port: {{ item[1] }}"
loop: "{{ my_hosts | product(ports) | list }}"
...
I am currently using the netbox ansible module to pull interface information from Cisco devices into Netbox. So far I have managed to pull in the interfaces and basic information like their MAC addresses.
Is there a way that you can get the untagged and tagged VLANS on each port and push them into netbox too?
This is my current ansible playbook:
---
- name: "PLAY 1: ADD INTERFACES TO NETBOX AND CLEANUP TEMP"
connection: network_cli
hosts: platforms_ios
tags: [ ios ]
tasks:
- name: "TASK 1: IOS >> GET IOS FACTS"
ios_facts:
gather_subset: "!config"
when: "ansible_network_os == 'ios'"
- name: "TASK 2: NETBOX >> ADD INTERFACES TO NETBOX"
netbox.netbox.netbox_device_interface:
netbox_url: "<netbox url>"
netbox_token: "<netbox_token>"
data:
device: "{{ inventory_hostname }}"
name: "{{ item.key }}"
form_factor: "{{ item.key | get_interface_type }}"
mac_address: "{{ item.value.macaddress | convert_mac_address }}"
state: present
with_dict:
- "{{ ansible_facts['net_interfaces'] }}"
loop_control:
label: "{{ item.key }}"
netbox.netbox.netbox_device_interface has options for untagged_vlan: and tagged_vlans: in their documentation. I am unsure if this information can be provided from ansible however.
I have a network with different hosts and different networks and I want to use ansible to ping each host in each network.
In my host_vars directory all informations about every host and its network are stored in its own file. A hostfile looks like this:
bond:
- conn_name: net1
ip4: '10.10.44.21'
gw4: '10.10.44.1'
- conn_name: net2
ip4: '10.10.47.21'
gw4: '10.10.47.1'
- conn_name: net3
ip4: '10.10.46.21'
gw4: '10.10.46.1'
bond_slave:
- conn_name: eno1
ifname: eno1
master: net1
- conn_name: eno2
ifname: eno2
master: net2
- conn_name: ens2f1
ifname: ens2f1
master: net2
- conn_name: ens2f0
ifname: ens2f0
master: net2
- conn_name: ens4f1
ifname: ens4f1
master: net3
- conn_name: ens4f0
ifname: ens4f0
master: net3
My purpose is to get every ip4-value and ping it from every host. what i can do is include all files from host_vars directory and ping the ip-adress of the first bond item of each file.
---
- hosts: all
- name: Include information about all hosts
include_vars: ../../host_vars/{{ item }}.yaml
with_items: hosts
register: "r"
- name: execute ping
command: ping {{ bond[0].ip4 }} -c 3
with_items: "{{ r.results }}"
But the bond can have from 2 to 4 networks. How do i loop through each bond to access all ip-address?
Solution
Even though the snippet of Konstantin Suvorov wasn't working for me, it helped me to find the right solution:
- name: execute ping
command: ping {{ item.ip4 }} -c 3
with_items: "{{ r.results | map(attribute='ansible_facts.bond') | list }}"
If you have bond var defined for each host via host_vars, you can use hostvars magic variable (no need to do this ugly include task):
- name: ping everything
command: ping {{ item }} -c 3
with_items: "{{ play_hosts | map('extract',hostvars,'bond') | list }}"
Actually this Jinja2 expression will return a list of lists, but with_items flattends them, so you end up with long list all elements from every bond of every host in current play.