Skip to content

Commit

Permalink
Add replaced and overridden to System module (#159)
Browse files Browse the repository at this point in the history
* Add replaced and overridden to System module

* Move some lines
  • Loading branch information
mingjunzhang2019 authored Feb 13, 2023
1 parent 535b9e1 commit cd5f251
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 5 deletions.
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

0 comments on commit cd5f251

Please sign in to comment.