Version: Ansible 1.9.4
I'm going to try and describe this as well as a I can. Please comment and let me know any questions.
I'm trying to design a role that will do the following:
* Get a list of interface IP addresses for each host (minus 'lo' and any non-active interfaces)
* Use that IP listing to test each IP against a IP subnet(VLAN)
- I have a quick perl script I had written to test this (rc.0 = on same subnet/VLAN, rc.1 = NOT on the same VLAN/subnet)
- This script also prints to stdout the VLAN/subnet "group name" when there is a match
* I'd then like to take each subnet written to stdout (not the skipped items or anything null, obviously)
- Use that list to somehow set facts that could then be used to put hosts in various host groups based on those subnet names
This sounds simple enough, though I'm not the most advanced Ansible user and certainly not a Python dev. I've been trying a bunch of approach, though I appear to be getting farther from a solution lately.
Here is what my vars look like (slightly modified to reveal less):
=====
network_script_packages:
- perl-NetAddr-IP
check_network_script: check-IP-network.pl
check_network_remotedir: /usr/local/bin
network_VLAN_remotedir: /var/cache/ansible-network-vlans
network_VLAN_remotesubdirs:
- primary
- member
network_VLANs:
- vlan_id: 250
vlan_name: VLAN-250
vlan_groupname: network-VLAN-250
vlan_description: "Management VLAN"
- vlan_id: 103
vlan_name: VLAN-103
vlan_groupname: network-VLAN-103
vlan_description: "Storage VLAN"
- vlan_id: 722
vlan_name: VLAN-722
vlan_groupname: network-VLAN-722
vlan_description: "Restricted VLAN"
====
Here is what my tasks look like (keep in mind that I've made a mess of things trying approaches):
=====
---
- name: NETWORK | Get all host interface IP addresses
shell: "echo {{ hostvars[inventory_hostname]['ansible_' + item].ipv4.address }}"
register: network_interface_IPs
with_items: ansible_interfaces
changed_when: False
when: "item != 'lo' and {{ hostvars[inventory_hostname]['ansible_' + item].active }} == True"
- name: NETWORK | Copy network check script
sudo: yes
copy: src={{ check_network_script }} dest={{ check_network_remotedir }}/{{ check_network_script }} owner=root group=root mode=755
run_once: yes
delegate_to: 127.0.0.1
- name: NETWORK | Determine network membership
command: "{{ check_network_remotedir }}/{{ check_network_script }} {{ item.1 }} {{ item.0.vlan_network }} {{ item.0.vlan_groupname }}"
# command: "{{ check_network_remotedir }}/{{ check_network_script }} {{ item.1.stdout }} {{ item.0.vlan_network }} {{ item.0.vlan_groupname }}"
register: network_VLAN_groups
delegate_to: 127.0.0.1
with_nested:
- network_VLANs
- "{{ network_interface_IPs.results|map(attribute='stdout')|list }}"
# - "{{ network_interface_IPs.results|map(attribute='stdout')|list }}"
# - network_interface_IPs.results
changed_when: "network_VLAN_groups.rc == 0"
failed_when: False
when:
- not((item.1 is undefined) or (item.1 is none) or (item.1|trim == ''))
# - not((item.1.stdout is undefined) or (item.1.stdout is none) or (item.1.stdout|trim == ''))
### **** The rest seems to get messy as I obviously get very large dictionary where getting JUST the stdout entries (perhaps since these are made up of multiple dictionary from the previous commands)
- name: FACT | Set facts for VLAN membership
set_fact:
"host_VLANS={{ [ item.stdout ] }}"
with_items: network_VLAN_groups.results
when:
- not((item.stdout is undefined) or (item.stdout is none) or (item.stdout|trim == ''))
- debug: var={{ item }}
with_items: network_VLAN_groups.results
- name: GROUP | Create a group for each VLAN
group_by: key={{ item }}
with_items: network_VLANs.vlan_groupname
# when: network_VLANs.vlan_groupname == true
===============
You can see all of my multiple attempts are learning and getting this right. I believe i need ideas of a few key pieces (and advice on approaches):
1. What is the best way to "clean up" a dictionary in such a way that I can get a simple list (without all the null, undefined, in it)?
2. How can I utilize that simplified list to run the second command (thus determining VLAN/subnet matches)?
- I've tried a few ways, but they get sloppy and/or don't _seem_ to give me what I'm looking for.
3. How can I then store this VLAN/subnet 'membership' into something that can then be used to generate a hostgroup (dynamically would be preferred)?
- I've seen some combo of set_fact with group_by, however I'm in a situation where systems will have multiple interfaces on various subnet and thus will need to be members of multiple groups.
I've tried everything from generating files per subnet/VLAN containing hostnames, but even then, I'm in a situation where I need to be able to add hosts to a group based on which files they exist in. Yet another challenge. :)
In any case, I know this is a long post, but I've been banging my head against this a while, and I think it is time to get some fresh throughs and approaches as well as some education. Any help is very much appreciated.
Thanks,
Chris