Generating a group based on IP subnet membership (multiple questions)

38 views
Skip to first unread message

Christopher Young

unread,
Jan 22, 2016, 7:55:50 PM1/22/16
to Ansible Project
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_network: 10.16.250.0/24
      vlan_groupname: network-VLAN-250
      vlan_description: "Management VLAN"
    - vlan_id: 103
      vlan_name: VLAN-103
      vlan_network: 10.16.3.0/24
      vlan_groupname: network-VLAN-103
      vlan_description: "Storage VLAN"
    - vlan_id: 722
      vlan_name: VLAN-722
      vlan_network: 172.16.2.0/24
      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



Reply all
Reply to author
Forward
0 new messages