1
votes

I would like to determine the interface ipv6 address of the host, where ansible connects from and use it as variable in my playbook. I know how to get the ipv6 address from the facts:

{{ ansible_facts['ens192']['ipv6'][0]['address'] }}

My only problem is that the interface might be something else but ens192, because I have hosts with multiple interfaces. I always need that interface's address where ansible connect to host, which might be ensX

If you could provide me a solution for IPv4, it is good enough for me. :) Please note that default_ipv4_address does not work for me, because the default interface is not always where the ansible connection is coming.

UPDATE:

I think it will be good if I could get the IPv6 address where ansible connects to and get it's variable somehow. So if ansible connects to host1.something.local and it has an IPv6 address: 2001:1:2:3::4 get that IPv6 address as variable and use it in playbook.

3

3 Answers

1
votes

It looks like you've got a solution that works, but for what it's worth you could also just query your routing tables for that information. The ip route get command will show you both the interface name and source address used to connect to another host. For example:

$ ip route get 2607:f8b0:4006:800::200e
2607:f8b0:4006:800::200e from :: via 2001:470:1f06:46f::1 dev he-ipv6 proto static src 2001:470:1f06:46f::2 metric 675 pref medium

From the above output, we see that a connection to 2607:f8b0:4006:800::200e will use interface he-ipv6 and source address 2001:470:1f06:46f::2.

You could use this in a playbook like this:

---
- hosts: targethost
  tasks:
    - name: get local address
      delegate_to: localhost
      command: >-
        ip route get {{ hostvars['targethost'].ansible_default_ipv6.address }}
      register: route

    - set_fact:
        local_address: "{{ dict(route_parts|zip(route_parts[1:])).src }}"
        local_interface: "{{ dict(route_parts|zip(route_parts[1:])).dev }}"
      vars:
        route_parts: "{{ route.stdout.splitlines()[0].split()[1:] }}"

    - debug:
        msg:
          - "local address: {{ local_address }}"
          - "local interface: {{ local_interface }}"

This should work with both ipv4 and ipv6 addresses.

0
votes

Okey, I think I found it:

{{ hostvars[inventory_hostname]['ansible_env'].SSH_CONNECTION.split(' ')[2] }}

This will get the address where ansible connects to. If IPv6 is preferred, then it will be an IPv6 address. Otherwise it will be an IPv4 address.

0
votes

1.This is the most simple way to get the default ip address which the default route points to

"{{ ansible_default_ipv6.address }}"

As for variable ansible_default_ipv6, you can get more infomation.

such as interface name, gateway, mac address and so on.

2.another workaround method

You can get all ipv6 address of the host from this variable

"{{ ansible_all_ipv6_addresses }}"

And according to the ip address, you can distinguish the ip address which is in same 'network segment' of ansible host

Tips: replace ipv6 with ipv4, also works fine