Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add replaced and overridden to System module #159

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def __init__(self, **kwargs):
'type': 'dict'
},
'state': {
'choices': ['merged', 'deleted'],
'choices': ['merged', 'replaced', 'overridden', 'deleted'],
'default': 'merged',
'type': 'str'
}
Expand Down
131 changes: 130 additions & 1 deletion plugins/module_utils/network/sonic/config/system/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.facts.facts import Facts
from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.utils.utils import (
update_states,
send_requests,
get_diff,
)
from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.sonic import (
Expand Down Expand Up @@ -127,6 +128,11 @@ def set_state(self, want, have):
elif state == 'merged':
diff = get_diff(want, have)
commands = self._state_merged(want, have, diff)
elif state == 'overridden':
commands = self._state_overridden(want, have)
elif state == 'replaced':
commands = self._state_replaced(want, have)

return commands

def _state_merged(self, want, have, diff):
Expand All @@ -142,6 +148,7 @@ def _state_merged(self, want, have, diff):
requests = self.get_create_system_request(want, diff)
if len(requests) > 0:
commands = update_states(diff, "merged")

return commands, requests

def _state_deleted(self, want, have):
Expand All @@ -167,6 +174,70 @@ def _state_deleted(self, want, have):
requests = self.get_delete_all_system_request(diff_want)
if len(requests) > 0:
commands = update_states(diff_want, "deleted")

return commands, requests

def _state_replaced(self, want, have):
""" The command generator when state is replaced

:param want: the desired configuration as a dictionary
:param have: the current configuration as a dictionary
:param diff: the difference between want and have
:rtype: A list
:returns: the commands necessary to migrate the current configuration
to the desired configuration
"""
new_want = self.patch_want_with_default(want, ac_address_only=True)
replaced_config = self.get_replaced_config(have, new_want)
if replaced_config:
requests = self.get_delete_all_system_request(replaced_config)
send_requests(self._module, requests)
commands = new_want
else:
diff = get_diff(new_want, have)
commands = diff
if not commands:
commands = []

requests = []

if commands:
requests = self.get_create_system_request(have, commands)

if len(requests) > 0:
commands = update_states(commands, "replaced")
else:
commands = []

return commands, requests

def _state_overridden(self, want, have):
""" The command generator when state is overridden

:param want: the desired configuration as a dictionary
:param have: the current configuration as a dictionary
:param diff: the difference between want and have
:rtype: A list
:returns: the commands necessary to migrate the current configuration
to the desired configuration
"""
new_want = self.patch_want_with_default(want)
if have and have != new_want:
requests = self.get_delete_all_system_request(have)
send_requests(self._module, requests)
have = []

commands = []
requests = []

if not have and new_want:
commands = new_want
requests = self.get_create_system_request(have, commands)
if len(requests) > 0:
commands = update_states(commands, "overridden")
else:
commands = []

return commands, requests

def get_create_system_request(self, want, commands):
Expand All @@ -190,8 +261,9 @@ def get_create_system_request(self, want, commands):
return requests

def build_create_hostname_payload(self, commands):
payload = {"openconfig-system:config": {}}
payload = {}
if "hostname" in commands and commands["hostname"]:
payload = {"openconfig-system:config": {}}
payload['openconfig-system:config'].update({"hostname": commands["hostname"]})
return payload

Expand Down Expand Up @@ -221,6 +293,63 @@ def build_create_anycast_payload(self, commands):
payload["sonic-sag:SAG_GLOBAL_LIST"].append(temp)
return payload

def patch_want_with_default(self, want, ac_address_only=False):
new_want = {}
if want is None:
if ac_address_only:
new_want = {'anycast_address': {'ipv4': True, 'ipv6': True, 'mac_address': None}}
else:
new_want = {'hostname': 'sonic', 'interface_naming': 'native',
'anycast_address': {'ipv4': True, 'ipv6': True, 'mac_address': None}}
else:
new_want = want.copy()
new_anycast = {}
anycast = want.get('anycast_address', None)
if not anycast:
new_anycast = {'ipv4': True, 'ipv6': True, 'mac_address': None}
else:
new_anycast = anycast.copy()
ipv4 = anycast.get("ipv4", None)
if ipv4 is None:
new_anycast["ipv4"] = True
ipv6 = anycast.get("ipv6", None)
if ipv6 is None:
new_anycast["ipv6"] = True
mac = anycast.get("mac_address", None)
if mac is None:
new_anycast["mac_address"] = None
new_want["anycast_address"] = new_anycast

if not ac_address_only:
hostname = want.get('hostname', None)
if hostname is None:
new_want["hostname"] = 'sonic'
intf_name = want.get('interface_naming', None)
if intf_name is None:
new_want["interface_naming"] = 'native'
return new_want

def get_replaced_config(self, have, want):

replaced_config = dict()

h_hostname = have.get('hostname', None)
w_hostname = want.get('hostname', None)
if (h_hostname != w_hostname) and w_hostname:
replaced_config = have.copy()
return replaced_config
h_intf_name = have.get('interface_naming', None)
w_intf_name = want.get('interface_naming', None)
if (h_intf_name != w_intf_name) and w_intf_name:
replaced_config = have.copy()
return replaced_config
h_ac_addr = have.get('anycast_address', None)
w_ac_addr = want.get('anycast_address', None)
if (h_ac_addr != w_ac_addr) and w_ac_addr:
replaced_config['anycast_address'] = h_ac_addr
return replaced_config
return replaced_config

def remove_default_entries(self, data):
new_data = {}
if not data:
Expand Down
85 changes: 84 additions & 1 deletion plugins/modules/sonic_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
- In case of merged, the input configuration will be merged with the existing system configuration on the device.
- In case of deleted the existing system configuration will be removed from the device.
default: merged
choices: ['merged', 'deleted']
choices: ['merged', 'replaced', 'overridden', 'deleted']
type: str
"""
EXAMPLES = """
Expand Down Expand Up @@ -167,6 +167,89 @@
#ipv6 anycast-address enable
#interface-naming standard

# Using replaced
#
# Before state:
# -------------
#!
#sonic(config)#do show running-configuration
#!
#ip anycast-mac-address aa:bb:cc:dd:ee:ff
#ip anycast-address enable
#ipv6 anycast-address enable

- name: Replace system configuration.
sonic_system:
config:
hostname: sonic
interface_naming: standard
state: replaced

# After state:
# ------------
#!
#SONIC(config)#do show running-configuration
#!
#interface-naming standard

# Using replaced
#
# Before state:
# -------------
#!
#sonic(config)#do show running-configuration
#!
#ip anycast-mac-address aa:bb:cc:dd:ee:ff
#interface-naming standard

- name: Replace system device configuration.
sonic_system:
config:
hostname: sonic
interface_naming: standard
anycast_address:
ipv6: true
ipv4: true
state: replaced

# After state:
# ------------
#!
#SONIC(config)#do show running-configuration
#!
#ip anycast-address enable
#ipv6 anycast-address enable
#interface-naming standard

# Using overridden
#
# Before state:
# -------------
#!
#sonic(config)#do show running-configuration
#!
#ip anycast-mac-address aa:bb:cc:dd:ee:ff
#ip anycast-address enable
#ipv6 anycast-address enable

- name: Override system configuration.
sonic_system:
config:
hostname: sonic
interface_naming: standard
anycast_address:
ipv4: true
mac_address: bb:aa:cc:dd:ee:ff
state: overridden

# After state:
# ------------
#!
#SONIC(config)#do show running-configuration
#!
#ip anycast-mac-address bb:aa:cc:dd:ee:ff
#ip anycast-address enable
#interface-naming standard

"""
RETURN = """
Expand Down
32 changes: 30 additions & 2 deletions tests/regression/roles/sonic_system/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ tests:
anycast_address:
mac_address: 00:09:5B:EC:EE:F2

- name: del_test_case_01
- name: test_case_04
description: Delete System properties
state: deleted
input:
Expand All @@ -34,13 +34,41 @@ tests:
anycast_address:
ipv4: false

- name: del_test_case_02
- name: test_case_05
description: Delete System associated anycast mac address
state: deleted
input:
anycast_address:
mac_address: 00:09:5B:EC:EE:F2

- name: test_case_06
description: Override System configuration
state: overridden
input:
hostname: SONIC-ov
interface_naming: standard
anycast_address:
ipv4: true
mac_address: 00:09:5B:EC:EE:F2

- name: test_case_07
description: Replace some System configuration
state: replaced
input:
anycast_address:
ipv4: true
ipv6: false
mac_address: 00:09:5B:EC:EE:F2

- name: test_case_08
description: Replace System configuration
state: replaced
input:
hostname: SONIC
interface_naming: native
anycast_address:
ipv4: true

test_delete_all:
- name: del_all_test_case_01
description: Delete System properties
Expand Down