fix vyos_l3_interface adding multiple addresses to interface (#36377)

* fix vyos_l3_interface adding multiple addresses to interface

Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>

* add test

Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>
This commit is contained in:
Trishna Guha 2018-02-20 20:54:27 +05:30 committed by GitHub
parent 66c38dd6c3
commit 3d06ce245a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 22 deletions

View file

@ -88,14 +88,39 @@ commands:
sample: sample:
- set interfaces ethernet eth0 address '192.168.0.1/24' - set interfaces ethernet eth0 address '192.168.0.1/24'
""" """
import socket
import re
from copy import deepcopy from copy import deepcopy
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.common.utils import is_masklen, validate_ip_address
from ansible.module_utils.network.common.utils import remove_default_spec from ansible.module_utils.network.common.utils import remove_default_spec
from ansible.module_utils.network.vyos.vyos import load_config, run_commands from ansible.module_utils.network.vyos.vyos import load_config, run_commands
from ansible.module_utils.network.vyos.vyos import vyos_argument_spec from ansible.module_utils.network.vyos.vyos import vyos_argument_spec
def is_ipv4(value):
if value:
address = value.split('/')
if is_masklen(address[1]) and validate_ip_address(address[0]):
return True
return False
def is_ipv6(value):
if value:
address = value.split('/')
if 0 <= int(address[1]) <= 128:
try:
socket.inet_pton(socket.AF_INET6, address[0])
except socket.error:
return False
return True
return False
def search_obj_in_list(name, lst): def search_obj_in_list(name, lst):
for o in lst: for o in lst:
if o['name'] == name: if o['name'] == name:
@ -115,6 +140,7 @@ def map_obj_to_commands(updates, module):
state = w['state'] state = w['state']
obj_in_have = search_obj_in_list(name, have) obj_in_have = search_obj_in_list(name, have)
if state == 'absent' and obj_in_have: if state == 'absent' and obj_in_have:
if not ipv4 and not ipv6 and (obj_in_have['ipv4'] or obj_in_have['ipv6']): if not ipv4 and not ipv6 and (obj_in_have['ipv4'] or obj_in_have['ipv6']):
if name == "lo": if name == "lo":
@ -122,24 +148,24 @@ def map_obj_to_commands(updates, module):
else: else:
commands.append('delete interfaces ethernet ' + name + ' address') commands.append('delete interfaces ethernet ' + name + ' address')
else: else:
if ipv4 and obj_in_have['ipv4']: if ipv4 and ipv4 in obj_in_have['ipv4']:
if name == "lo": if name == "lo":
commands.append('delete interfaces loopback lo address ' + ipv4) commands.append('delete interfaces loopback lo address ' + ipv4)
else: else:
commands.append('delete interfaces ethernet ' + name + ' address ' + ipv4) commands.append('delete interfaces ethernet ' + name + ' address ' + ipv4)
if ipv6 and obj_in_have['ipv6']: if ipv6 and ipv6 in obj_in_have['ipv6']:
if name == "lo": if name == "lo":
commands.append('delete interfaces loopback lo address ' + ipv6) commands.append('delete interfaces loopback lo address ' + ipv6)
else: else:
commands.append('delete interfaces ethernet ' + name + ' address ' + ipv6) commands.append('delete interfaces ethernet ' + name + ' address ' + ipv6)
elif (state == 'present' and obj_in_have): elif (state == 'present' and obj_in_have):
if ipv4 and ipv4 != obj_in_have['ipv4']: if ipv4 and ipv4 not in obj_in_have['ipv4']:
if name == "lo": if name == "lo":
commands.append('set interfaces loopback lo address ' + ipv4) commands.append('set interfaces loopback lo address ' + ipv4)
else: else:
commands.append('set interfaces ethernet ' + name + ' address ' + ipv4) commands.append('set interfaces ethernet ' + name + ' address ' + ipv4)
if ipv6 and ipv6 != obj_in_have['ipv6']: if ipv6 and ipv6 not in obj_in_have['ipv6']:
if name == "lo": if name == "lo":
commands.append('set interfaces loopback lo address ' + ipv6) commands.append('set interfaces loopback lo address ' + ipv6)
else: else:
@ -151,29 +177,32 @@ def map_obj_to_commands(updates, module):
def map_config_to_obj(module): def map_config_to_obj(module):
obj = [] obj = []
output = run_commands(module, ['show interfaces']) output = run_commands(module, ['show interfaces'])
lines = output[0].splitlines() lines = re.split(r'\n[e|l]', output[0])[1:]
if len(lines) > 3: if len(lines) > 0:
for line in lines[3:]: for line in lines:
splitted_line = line.split() splitted_line = line.split()
if len(splitted_line) > 1: if len(splitted_line) > 0:
name = splitted_line[0] ipv4 = []
address = splitted_line[1] ipv6 = []
if address == '-': if splitted_line[0].lower().startswith('th'):
address = None name = 'e' + splitted_line[0].lower()
elif splitted_line[0].lower().startswith('o'):
name = 'l' + splitted_line[0].lower()
for i in splitted_line[1:]:
if (('.' in i or ':' in i) and '/' in i):
value = i.split(r'\n')[0]
if is_ipv4(value):
ipv4.append(value)
elif is_ipv6(value):
ipv6.append(value)
if address is not None and ':' not in address:
obj.append({'name': name, obj.append({'name': name,
'ipv4': address, 'ipv4': ipv4,
'ipv6': None}) 'ipv6': ipv6})
else:
obj.append({'name': name,
'ipv6': address,
'ipv4': None})
else:
obj[-1]['ipv6'] = splitted_line[0]
return obj return obj

View file

@ -149,6 +149,7 @@
aggregate: aggregate:
- { name: eth1, ipv4: 192.168.2.10/24 } - { name: eth1, ipv4: 192.168.2.10/24 }
- { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } - { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" }
- { name: eth2, ipv4: 192.168.4.10/24 }
register: result register: result
- assert: - assert:
@ -157,12 +158,14 @@
- '"set interfaces ethernet eth1 address 192.168.2.10/24" in result.commands' - '"set interfaces ethernet eth1 address 192.168.2.10/24" in result.commands'
- '"set interfaces ethernet eth2 address 192.168.3.10/24" in result.commands' - '"set interfaces ethernet eth2 address 192.168.3.10/24" in result.commands'
- '"set interfaces ethernet eth2 address fd5d:12c9:2201:1::1/64" in result.commands' - '"set interfaces ethernet eth2 address fd5d:12c9:2201:1::1/64" in result.commands'
- '"set interfaces ethernet eth2 address 192.168.4.10/24" in result.commands'
- name: Set IP addresses on aggregate (idempotent) - name: Set IP addresses on aggregate (idempotent)
vyos_l3_interface: vyos_l3_interface:
aggregate: aggregate:
- { name: eth1, ipv4: 192.168.2.10/24 } - { name: eth1, ipv4: 192.168.2.10/24 }
- { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } - { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" }
- { name: eth2, ipv4: 192.168.4.10/24 }
register: result register: result
- assert: - assert:
@ -174,6 +177,7 @@
aggregate: aggregate:
- { name: eth1, ipv4: 192.168.2.10/24 } - { name: eth1, ipv4: 192.168.2.10/24 }
- { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } - { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" }
- { name: eth2, ipv4: 192.168.4.10/24 }
state: absent state: absent
register: result register: result
@ -183,12 +187,14 @@
- '"delete interfaces ethernet eth1 address 192.168.2.10/24" in result.commands' - '"delete interfaces ethernet eth1 address 192.168.2.10/24" in result.commands'
- '"delete interfaces ethernet eth2 address 192.168.3.10/24" in result.commands' - '"delete interfaces ethernet eth2 address 192.168.3.10/24" in result.commands'
- '"delete interfaces ethernet eth2 address fd5d:12c9:2201:1::1/64" in result.commands' - '"delete interfaces ethernet eth2 address fd5d:12c9:2201:1::1/64" in result.commands'
- '"delete interfaces ethernet eth2 address 192.168.4.10/24" in result.commands'
- name: Remove IP addresses on aggregate (idempotent) - name: Remove IP addresses on aggregate (idempotent)
vyos_l3_interface: vyos_l3_interface:
aggregate: aggregate:
- { name: eth1, ipv4: 192.168.2.10/24 } - { name: eth1, ipv4: 192.168.2.10/24 }
- { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } - { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" }
- { name: eth2, ipv4: 192.168.4.10/24 }
state: absent state: absent
register: result register: result