From 2a6509223a096dcdb7f343b31c7b703ba812b2a6 Mon Sep 17 00:00:00 2001 From: Hemanth Kumar <97278032+hemanthKa677@users.noreply.github.com> Date: Mon, 24 Apr 2023 10:12:12 +0530 Subject: [PATCH] Fixes dynamic and static ip updation for a record (#182) * Fixes dynamic and static ip updation for a record * Fix for update A record with same name and different ip * Fix to raise exception for specific name and ipv4addr --- plugins/module_utils/api.py | 67 +++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index 4ae26305..3113b7f3 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -251,6 +251,11 @@ class WapiInventory(WapiBase): pass +class AnsibleError(Exception): + '''Implements raising exceptions''' + pass + + class WapiModule(WapiBase): ''' Implements WapiBase for executing a NIOS module ''' def __init__(self, module): @@ -326,6 +331,7 @@ def run(self, ib_obj_type, ib_spec): # To check for existing A_record with same name with input A_record by IP if each.get('ipv4addr') and each.get('ipv4addr') == proposed_object.get('ipv4addr'): current_object = each + break # To check for existing Host_record with same name with input Host_record by IP elif each.get('ipv4addrs') and each.get('ipv4addrs')[0].get('ipv4addr')\ == proposed_object.get('ipv4addrs')[0].get('ipv4addr'): @@ -396,6 +402,9 @@ def run(self, ib_obj_type, ib_spec): if 'remove' in proposed_object['ipv4addrs'][0]: del proposed_object['ipv4addrs'][0]['remove'] + # Checks if 'new_ipv4addr' param exists in ipv4addr args + proposed_object = self.check_for_new_ipv4addr(proposed_object) + res = None modified = not self.compare_objects(current_object, proposed_object) if 'extattrs' in proposed_object: @@ -483,6 +492,17 @@ def check_if_recordname_exists(self, obj_filter, ib_obj_ref, ib_obj_type, curren if obj_host_name == ref_host_name and current_ip_addr != proposed_ip_addr: self.create_object(ib_obj_type, proposed_object) + def get_network_view(self, proposed_object): + ''' Check for the associated network view with + the given dns_view''' + try: + network_view_ref = self.get_object('view', {"name": proposed_object['view']}, return_fields=['network_view']) + if network_view_ref: + network_view = network_view_ref[0].get('network_view') + except Exception: + raise Exception("object with dns_view: %s not found" % (proposed_object['view'])) + return network_view + def check_if_nios_next_ip_exists(self, proposed_object): ''' Check if nios_next_ip argument is passed in ipaddr while creating host record, if yes then format proposed object ipv4addrs and pass @@ -496,7 +516,18 @@ def check_if_nios_next_ip_exists(self, proposed_object): elif 'ipv4addr' in proposed_object: if 'nios_next_ip' in proposed_object['ipv4addr']: ip_range = check_type_dict(proposed_object['ipv4addr'])['nios_next_ip'] - proposed_object['ipv4addr'] = NIOS_NEXT_AVAILABLE_IP + ':' + ip_range + net_view = self.get_network_view(proposed_object) + proposed_object['ipv4addr'] = NIOS_NEXT_AVAILABLE_IP + ':' + ip_range + ',' + net_view + + return proposed_object + + def check_for_new_ipv4addr(self, proposed_object): + ''' Checks if new_ipv4addr parameter is passed in the argument + while updating the record with new ipv4addr with static allocation''' + if 'ipv4addr' in proposed_object: + if 'new_ipv4addr' in proposed_object['ipv4addr']: + new_ipv4 = check_type_dict(proposed_object['ipv4addr'])['new_ipv4addr'] + proposed_object['ipv4addr'] = new_ipv4 return proposed_object @@ -528,6 +559,14 @@ def check_if_add_remove_ip_arg_exists(self, proposed_object): del proposed_object['ipv4addrs'][0]['remove'] return update, proposed_object + def check_next_ip_status(self, obj_filter): + ''' Checks if nios next ip argument exists if True returns true + else returns false''' + if 'ipv4addr' in obj_filter: + if 'nios_next_ip' in obj_filter['ipv4addr']: + return True + return False + def issubset(self, item, objects): ''' Checks if item is a subset of objects :args item: the subset item to validate @@ -608,6 +647,7 @@ def get_object_ref(self, module, ib_obj_type, obj_filter, ib_spec): update = False old_name = new_name = None old_ipv4addr_exists = old_text_exists = False + next_ip_exists = False if ('name' in obj_filter): # gets and returns the current object based on name/old_name passed try: @@ -625,12 +665,27 @@ def get_object_ref(self, module, ib_obj_type, obj_filter, ib_spec): if old_name and new_name: if (ib_obj_type == NIOS_HOST_RECORD): test_obj_filter = dict([('name', old_name), ('view', obj_filter['view'])]) + # if there are multiple records with same name and different ip + elif (ib_obj_type == NIOS_A_RECORD): + test_obj_filter = dict([('name', old_name), ('ipv4addr', obj_filter['ipv4addr'])]) + try: + ipaddr_obj = check_type_dict(obj_filter['ipv4addr']) + ipaddr = ipaddr_obj.get('old_ipv4addr') + old_ipv4addr_exists = True if ipaddr else False + except TypeError: + ipaddr = test_obj_filter['ipv4addr'] + if old_ipv4addr_exists: + test_obj_filter['ipv4addr'] = ipaddr + else: + del test_obj_filter['ipv4addr'] else: test_obj_filter = dict([('name', old_name)]) # get the object reference ib_obj = self.get_object(ib_obj_type, test_obj_filter, return_fields=list(ib_spec.keys())) if ib_obj: obj_filter['name'] = new_name + elif old_ipv4addr_exists and (len(ib_obj) == 0): + raise Exception("object with name: '%s', ipv4addr: '%s' is not found" % (old_name, test_obj_filter['ipv4addr'])) else: raise Exception("object with name: '%s' is not found" % (old_name)) update = True @@ -658,9 +713,15 @@ def get_object_ref(self, module, ib_obj_type, obj_filter, ib_spec): ipaddr_obj = check_type_dict(obj_filter['ipv4addr']) ipaddr = ipaddr_obj.get('old_ipv4addr') old_ipv4addr_exists = True if ipaddr else False + if not old_ipv4addr_exists: + next_ip_exists = self.check_next_ip_status(test_obj_filter) except TypeError: ipaddr = obj_filter['ipv4addr'] - test_obj_filter['ipv4addr'] = ipaddr + if old_ipv4addr_exists: + test_obj_filter['ipv4addr'] = ipaddr + # resolve issue if nios_next_ip exists which is not searchable attribute + if next_ip_exists: + del test_obj_filter['ipv4addr'] elif (ib_obj_type == NIOS_TXT_RECORD): # resolves issue where multiple txt_records with same name and different text test_obj_filter = obj_filter @@ -688,7 +749,7 @@ def get_object_ref(self, module, ib_obj_type, obj_filter, ib_spec): ib_obj = self.get_object(ib_obj_type, test_obj_filter.copy(), return_fields=list(ib_spec.keys())) # prevents creation of a new A record with 'new_ipv4addr' when A record with a particular 'old_ipv4addr' is not found - if old_ipv4addr_exists and ib_obj is None: + if old_ipv4addr_exists and (ib_obj is None or len(ib_obj) == 0): raise Exception("A Record with ipv4addr: '%s' is not found" % (ipaddr)) # prevents creation of a new TXT record with 'new_text' when TXT record with a particular 'old_text' is not found if old_text_exists and ib_obj is None: