4

I plan to reconfigure iptables on our servers (mostly CentOS 7, some CentOS 6) with different network configurations, some on 1Gbit interface, some on 10Gbit, some with VLANs and some with configured LACP.

I want to use Ansible, but couldn't find how to detect what inteface has private address. Private address we could get from inventory as ansible_ssh_host.

Is there any Ansible module that could help? Or I should write shell/Python script?

I checked all solutions on StackOverflow and ServerFault but haven't found anything.

3

Peter's module not working in CentOS and I write my own module:

#!/usr/bin/python
# encoding: utf-8

import subprocess
from ansible.module_utils.basic import *
from netaddr import IPNetwork

def get_priv_interface_info_for_ip(ip):
    network_config = subprocess.Popen(["/usr/sbin/ip", "-o", "addr", "show"], stdout=subprocess.PIPE)
    result = network_config.stdout.read()
    interface = ""
    network = ''
    ip_addr = ip
    for str in result.split("\n"):
        if 'inet ' in str:
            if ip in str:
                interface = str[3:str.find(" ", 3)]
                network = IPNetwork(str[str.find("net", 3) + 4:str.find("/", 3) + 3]).cidr

    return interface, ip_addr, network

def get_pub_interface_info_for_ip(ip):
    network_config = subprocess.Popen(["/usr/sbin/ip", "-o", "addr", "show"], stdout=subprocess.PIPE)
    result = network_config.stdout.read()
    interface = ''
    network = ''
    ip_addr = ''
    for str in result.split("\n"):
        if 'inet ' in str:
            if ip not in str and '127.0.0.1' not in str:
                print str
                interface = str[3:str.find(" ", 3)]
                network = IPNetwork(str[str.find("net", 3) + 4:str.find("/", 3) + 3]).cidr
                ip_addr = str[str.find("net", 3) + 4:str.find("/", 3)]

    return interface, ip_addr, network

def main(argv=None):
    if argv is None:
        argv = sys.argv

    fields = {"ip": {"required": True, "type": "str"}}
    module = AnsibleModule(argument_spec=fields)
    my_ip = module.params['ip']
    ifname_priv, ip_priv, network_priv = get_priv_interface_info_for_ip(my_ip)
    ifname_pub, ip_pub, network_pub = get_pub_interface_info_for_ip(my_ip)


    module.exit_json(changed=True, ifname_priv=ifname_priv, ip_priv=my_ip, network_priv=str(network_priv), ifname_pub=ifname_pub, ip_pub=ip_pub, network_pub=str(network_pub))


if __name__ == '__main__':
    main()

It works for servers with two network interfaces and provide information about public and private network interfaces.

Actual version of this module could be found in my GitHub.

2

I couldn't find it in Ansible, so I wrote something to help a couple of weeks ago:

import fcntl
import json
import os
import platform
import subprocess
import socket
import struct
import re
from random import randint
import time
from ansible.module_utils.basic import *

def get_interface_info_for_ip(ip):

  ifconfig_process = subprocess.Popen(['/sbin/ifconfig'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  ifconfig_stdout_lines, ifconfig_stderr_lines = ifconfig_process.communicate()

  for ifconfig_stdout_line in ifconfig_stdout_lines.split('\n'):
    if 'mtu' in ifconfig_stdout_line.split():
      current_ifdesc = ''
      current_mtu = ''
      current_ip = ''
      current_netmask = ''
      current_mac = ''
      ifdesc_line_match = re.match(r'(?P<ifdesc>[a-zA-Z0-9]+):.+mtu\s+(?P<mtu>[0-9]+)', ifconfig_stdout_line )
      if ifdesc_line_match:
        current_ifdesc = ifdesc_line_match.groupdict()['ifdesc']
        current_mtu = ifdesc_line_match.groupdict()['mtu']

    if 'inet' in ifconfig_stdout_line.split():
      inet_line_match = re.match(r'\s+inet\s+(?P<ip>[0-9.]+)\s+netmask\s+(?P<netmask>[0-9.]+)', ifconfig_stdout_line)
      if inet_line_match:
         current_ip = inet_line_match.groupdict()['ip']
         current_netmask = inet_line_match.groupdict()['netmask']

    if 'ether' in ifconfig_stdout_line.split():
      ether_line_match = re.match(r'\s+ether\s+(?P<mac>[0-9a-f:]+)', ifconfig_stdout_line)
      if ether_line_match:
         current_mac = ether_line_match.groupdict()['mac']

    if current_ifdesc and current_mtu and current_ip and current_netmask and current_mac and current_ip == ip:
      return current_ifdesc, current_mtu, current_ip, current_netmask, current_mac

def main(argv=None):
    if argv is None:
      argv = sys.argv

    module = AnsibleModule(
        argument_spec = dict(
           silo_ip = dict(required=True),
        )
    )
    my_ip = module.params['ip']
    ifdesc, mtu, ip, netmask, mac = get_interface_info_for_ip(my_ip)

    module.exit_json(changed=True, ifdesc=ifdesc, ip=ip, mac=mac, netmask=netmask, mtu=mtu)

if __name__ == '__main__':
    main()

Call the file get_ip_facts, put it in your library path and call it with:

name: get facts for ip address
get_ip_facts: ip={{ whatever_your_ip_is }}
  • That's looks interesting, but ifconfig removed from CentOS. They offer to use ip. I'll try to adopt your solution. – Alexander Tolkachev Jun 7 '17 at 11:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.