def check_declarative_intent_params(module, want, result): failed_conditions = [] for w in want: want_state = w.get('state') want_tx_rate = w.get('tx_rate') want_rx_rate = w.get('rx_rate') if want_state not in ( 'up', 'down') and not want_tx_rate and not want_rx_rate: continue if result['changed']: sleep(w['delay']) command = 'show interfaces %s' % w['name'] rc, out, err = exec_command(module, command) if rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) if want_state in ('up', 'down'): match = re.search(r'%s (\w+)' % 'line protocol is', out, re.M) have_state = None if match: have_state = match.group(1) if have_state.strip() == 'administratively': match = re.search(r'%s (\w+)' % 'administratively', out, re.M) if match: have_state = match.group(1) if have_state is None or not conditional(want_state, have_state.strip()): failed_conditions.append('state ' + 'eq(%s)' % want_state) if want_tx_rate: match = re.search(r'%s (\d+)' % 'output rate', out, re.M) have_tx_rate = None if match: have_tx_rate = match.group(1) if have_tx_rate is None or not conditional( want_tx_rate, have_tx_rate.strip(), cast=int): failed_conditions.append('tx_rate ' + want_tx_rate) if want_rx_rate: match = re.search(r'%s (\d+)' % 'input rate', out, re.M) have_rx_rate = None if match: have_rx_rate = match.group(1) if have_rx_rate is None or not conditional( want_rx_rate, have_rx_rate.strip(), cast=int): failed_conditions.append('rx_rate ' + want_rx_rate) return failed_conditions
def check_declarative_intent_params(module, want, result): failed_conditions = [] for w in want: want_state = w.get('state') want_tx_rate = w.get('tx_rate') want_rx_rate = w.get('rx_rate') if want_state not in ('up', 'down') and not want_tx_rate and not want_rx_rate: continue if result['changed']: sleep(w['delay']) command = 'show interfaces %s' % w['name'] rc, out, err = exec_command(module, command) if rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) if want_state in ('up', 'down'): match = re.search(r'%s (\w+)' % 'line protocol is', out, re.M) have_state = None if match: have_state = match.group(1) if have_state.strip() == 'administratively': match = re.search(r'%s (\w+)' % 'administratively', out, re.M) if match: have_state = match.group(1) if have_state is None or not conditional(want_state, have_state.strip()): failed_conditions.append('state ' + 'eq(%s)' % want_state) if want_tx_rate: match = re.search(r'%s (\d+)' % 'output rate', out, re.M) have_tx_rate = None if match: have_tx_rate = match.group(1) if have_tx_rate is None or not conditional(want_tx_rate, have_tx_rate.strip(), cast=int): failed_conditions.append('tx_rate ' + want_tx_rate) if want_rx_rate: match = re.search(r'%s (\d+)' % 'input rate', out, re.M) have_rx_rate = None if match: have_rx_rate = match.group(1) if have_rx_rate is None or not conditional(want_rx_rate, have_rx_rate.strip(), cast=int): failed_conditions.append('rx_rate ' + want_rx_rate) return failed_conditions
def check_declarative_intent_params(module, want, result): failed_conditions = [] have_neighbors = None for w in want: want_state = w.get('state') want_tx_rate = w.get('tx_rate') want_rx_rate = w.get('rx_rate') want_neighbors = w.get('neighbors') if want_state not in ('up', 'down') and not want_tx_rate and not want_rx_rate and not want_neighbors: continue if result['changed']: sleep(w['delay']) command = 'show interfaces ethernet %s' % w['name'] rc, out, err = exec_command(module, command) if rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) if want_state in ('up', 'down'): match = re.search(r'%s (\w+)' % 'state', out, re.M) have_state = None if match: have_state = match.group(1) if have_state is None or not conditional(want_state, have_state.strip().lower()): failed_conditions.append('state ' + 'eq(%s)' % want_state) if want_neighbors: have_host = [] have_port = [] if have_neighbors is None: rc, have_neighbors, err = exec_command(module, 'show lldp neighbors detail') if rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) if have_neighbors: lines = have_neighbors.strip().split('Interface: ') for line in lines: field = line.split('\n') if field[0].split(',')[0].strip() == w['name']: for item in field: if item.strip().startswith('SysName:'): have_host.append(item.split(':')[1].strip()) if item.strip().startswith('PortDescr:'): have_port.append(item.split(':')[1].strip()) for item in want_neighbors: host = item.get('host') port = item.get('port') if host and host not in have_host: failed_conditions.append('host ' + host) if port and port not in have_port: failed_conditions.append('port ' + port) return failed_conditions
def check_declarative_intent_params(self, result): failed_conditions = [] for req_if in self._required_config: want_state = req_if.get('state') name = req_if['name'] if want_state not in ('up', 'down'): continue if result['changed']: sleep(req_if['delay']) curr_if = self._current_config.get(name) curr_state = curr_if['state'] if curr_state is None or not \ conditional(want_state, curr_state.strip()): failed_conditions.append('state ' + 'eq(%s)' % want_state) return failed_conditions
def main(): """ main entry point for module execution """ neighbors_spec = dict(host=dict(), port=dict()) element_spec = dict(name=dict(), description=dict(), enabled=dict(default=True, type='bool'), speed=dict(), mtu=dict(type='int'), duplex=dict(choices=['full', 'half', 'auto']), tx_rate=dict(), rx_rate=dict(), neighbors=dict(type='list', elements='dict', options=neighbors_spec), delay=dict(default=10, type='int'), state=dict(default='present', choices=['present', 'absent', 'up', 'down']), active=dict(default=True, type='bool')) aggregate_spec = deepcopy(element_spec) aggregate_spec['name'] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict(aggregate=dict(type='list', elements='dict', options=aggregate_spec), ) argument_spec.update(element_spec) argument_spec.update(junos_argument_spec) required_one_of = [['name', 'aggregate']] mutually_exclusive = [['name', 'aggregate']] module = AnsibleModule(argument_spec=argument_spec, required_one_of=required_one_of, mutually_exclusive=mutually_exclusive, supports_check_mode=True) warnings = list() result = {'changed': False} if warnings: result['warnings'] = warnings top = 'interfaces/interface' param_to_xpath_map = collections.OrderedDict() param_to_xpath_map.update([('name', { 'xpath': 'name', 'is_key': True }), ('description', 'description'), ('speed', 'speed'), ('mtu', 'mtu'), ('duplex', 'link-mode'), ('disable', { 'xpath': 'disable', 'tag_only': True })]) choice_to_value_map = { 'link-mode': { 'full': 'full-duplex', 'half': 'half-duplex', 'auto': 'automatic' } } params = to_param_list(module) requests = list() for param in params: # if key doesn't exist in the item, get it from module.params for key in param: if param.get(key) is None: param[key] = module.params[key] item = param.copy() state = item.get('state') item['disable'] = True if not item.get('enabled') else False if state in ('present', 'up', 'down'): item['state'] = 'present' validate_param_values(module, param_to_xpath_map, param=item) want = map_params_to_obj(module, param_to_xpath_map, param=item) requests.append( map_obj_to_ele(module, want, top, value_map=choice_to_value_map, param=item)) diff = None with locked_config(module): for req in requests: diff = load_config(module, tostring(req), warnings, action='merge') # issue commit after last configuration change is done commit = not module.check_mode if diff: if commit: commit_configuration(module) else: discard_changes(module) result['changed'] = True if module._diff: result['diff'] = {'prepared': diff} failed_conditions = [] neighbors = None for item in params: state = item.get('state') tx_rate = item.get('tx_rate') rx_rate = item.get('rx_rate') want_neighbors = item.get('neighbors') if state not in ( 'up', 'down' ) and tx_rate is None and rx_rate is None and want_neighbors is None: continue element = Element('get-interface-information') intf_name = SubElement(element, 'interface-name') intf_name.text = item.get('name') if result['changed']: sleep(item.get('delay')) reply = exec_rpc(module, tostring(element), ignore_warning=False) if state in ('up', 'down'): admin_status = reply.xpath( 'interface-information/physical-interface/admin-status') if not admin_status or not conditional( state, admin_status[0].text.strip()): failed_conditions.append('state ' + 'eq(%s)' % state) if tx_rate: output_bps = reply.xpath( 'interface-information/physical-interface/traffic-statistics/output-bps' ) if not output_bps or not conditional( tx_rate, output_bps[0].text.strip(), cast=int): failed_conditions.append('tx_rate ' + tx_rate) if rx_rate: input_bps = reply.xpath( 'interface-information/physical-interface/traffic-statistics/input-bps' ) if not input_bps or not conditional( rx_rate, input_bps[0].text.strip(), cast=int): failed_conditions.append('rx_rate ' + rx_rate) if want_neighbors: if neighbors is None: element = Element('get-lldp-interface-neighbors') intf_name = SubElement(element, 'interface-device') intf_name.text = item.get('name') reply = exec_rpc(module, tostring(element), ignore_warning=False) have_host = [ item.text for item in reply.xpath( 'lldp-neighbors-information/lldp-neighbor-information/lldp-remote-system-name' ) ] have_port = [ item.text for item in reply.xpath( 'lldp-neighbors-information/lldp-neighbor-information/lldp-remote-port-id' ) ] for neighbor in want_neighbors: host = neighbor.get('host') port = neighbor.get('port') if host and host not in have_host: failed_conditions.append('host ' + host) if port and port not in have_port: failed_conditions.append('port ' + port) if failed_conditions: msg = 'One or more conditional statements have not be satisfied' module.fail_json(msg=msg, failed_conditions=failed_conditions) module.exit_json(**result)
def test_conditional(self): self.assertTrue(conditional(10, 10)) self.assertTrue(conditional('10', '10')) self.assertTrue(conditional('foo', 'foo')) self.assertTrue(conditional(True, True)) self.assertTrue(conditional(False, False)) self.assertTrue(conditional(None, None)) self.assertTrue(conditional("ge(1)", 1)) self.assertTrue(conditional("gt(1)", 2)) self.assertTrue(conditional("le(2)", 2)) self.assertTrue(conditional("lt(3)", 2)) self.assertTrue(conditional("eq(1)", 1)) self.assertTrue(conditional("neq(0)", 1)) self.assertTrue(conditional("min(1)", 1)) self.assertTrue(conditional("max(1)", 1)) self.assertTrue(conditional("exactly(1)", 1))
def main(): """ main entry point for module execution """ neighbors_spec = dict( host=dict(), port=dict() ) element_spec = dict( name=dict(), description=dict(), enabled=dict(default=True, type='bool'), speed=dict(), mtu=dict(type='int'), duplex=dict(choices=['full', 'half', 'auto']), tx_rate=dict(), rx_rate=dict(), neighbors=dict(type='list', elements='dict', options=neighbors_spec), delay=dict(default=10, type='int'), state=dict(default='present', choices=['present', 'absent', 'up', 'down']), active=dict(default=True, type='bool') ) aggregate_spec = deepcopy(element_spec) aggregate_spec['name'] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( aggregate=dict(type='list', elements='dict', options=aggregate_spec), ) argument_spec.update(element_spec) argument_spec.update(junos_argument_spec) required_one_of = [['name', 'aggregate']] mutually_exclusive = [['name', 'aggregate']] module = AnsibleModule(argument_spec=argument_spec, required_one_of=required_one_of, mutually_exclusive=mutually_exclusive, supports_check_mode=True) warnings = list() check_args(module, warnings) result = {'changed': False} if warnings: result['warnings'] = warnings top = 'interfaces/interface' param_to_xpath_map = collections.OrderedDict() param_to_xpath_map.update([ ('name', {'xpath': 'name', 'is_key': True}), ('description', 'description'), ('speed', 'speed'), ('mtu', 'mtu'), ('duplex', 'link-mode'), ('disable', {'xpath': 'disable', 'tag_only': True}) ]) choice_to_value_map = { 'link-mode': {'full': 'full-duplex', 'half': 'half-duplex', 'auto': 'automatic'} } params = to_param_list(module) requests = list() for param in params: # if key doesn't exist in the item, get it from module.params for key in param: if param.get(key) is None: param[key] = module.params[key] item = param.copy() state = item.get('state') item['disable'] = True if not item.get('enabled') else False if state in ('present', 'up', 'down'): item['state'] = 'present' validate_param_values(module, param_to_xpath_map, param=item) want = map_params_to_obj(module, param_to_xpath_map, param=item) requests.append(map_obj_to_ele(module, want, top, value_map=choice_to_value_map, param=item)) diff = None with locked_config(module): for req in requests: diff = load_config(module, tostring(req), warnings, action='merge') # issue commit after last configuration change is done commit = not module.check_mode if diff: if commit: commit_configuration(module) else: discard_changes(module) result['changed'] = True if module._diff: result['diff'] = {'prepared': diff} failed_conditions = [] neighbors = None for item in params: state = item.get('state') tx_rate = item.get('tx_rate') rx_rate = item.get('rx_rate') want_neighbors = item.get('neighbors') if state not in ('up', 'down') and tx_rate is None and rx_rate is None and want_neighbors is None: continue element = Element('get-interface-information') intf_name = SubElement(element, 'interface-name') intf_name.text = item.get('name') if result['changed']: sleep(item.get('delay')) reply = send_request(module, element, ignore_warning=False) if state in ('up', 'down'): admin_status = reply.xpath('interface-information/physical-interface/admin-status') if not admin_status or not conditional(state, admin_status[0].text.strip()): failed_conditions.append('state ' + 'eq(%s)' % state) if tx_rate: output_bps = reply.xpath('interface-information/physical-interface/traffic-statistics/output-bps') if not output_bps or not conditional(tx_rate, output_bps[0].text.strip(), cast=int): failed_conditions.append('tx_rate ' + tx_rate) if rx_rate: input_bps = reply.xpath('interface-information/physical-interface/traffic-statistics/input-bps') if not input_bps or not conditional(rx_rate, input_bps[0].text.strip(), cast=int): failed_conditions.append('rx_rate ' + rx_rate) if want_neighbors: if neighbors is None: element = Element('get-lldp-interface-neighbors') intf_name = SubElement(element, 'interface-device') intf_name.text = item.get('name') reply = send_request(module, element, ignore_warning=False) have_host = [item.text for item in reply.xpath('lldp-neighbors-information/lldp-neighbor-information/lldp-remote-system-name')] have_port = [item.text for item in reply.xpath('lldp-neighbors-information/lldp-neighbor-information/lldp-remote-port-id')] for neighbor in want_neighbors: host = neighbor.get('host') port = neighbor.get('port') if host and host not in have_host: failed_conditions.append('host ' + host) if port and port not in have_port: failed_conditions.append('port ' + port) if failed_conditions: msg = 'One or more conditional statements have not be satisfied' module.fail_json(msg=msg, failed_conditions=failed_conditions) module.exit_json(**result)
def check_declarative_intent_params(module, want, result): failed_conditions = [] have_neighbors = None for w in want: want_state = w.get('state') want_tx_rate = w.get('tx_rate') want_rx_rate = w.get('rx_rate') want_neighbors = w.get('neighbors') if want_state not in ('up', 'down') and not want_tx_rate and not want_rx_rate and not want_neighbors: continue if result['changed']: sleep(w['delay']) command = 'show interfaces %s' % w['name'] rc, out, err = exec_command(module, command) if rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) if want_state in ('up', 'down'): match = re.search(r'%s (\w+)' % 'line protocol is', out, re.M) have_state = None if match: have_state = match.group(1) if have_state is None or not conditional(want_state, have_state.strip()): failed_conditions.append('state ' + 'eq(%s)' % want_state) if want_tx_rate: match = re.search(r'%s (\d+)' % 'output rate', out, re.M) have_tx_rate = None if match: have_tx_rate = match.group(1) if have_tx_rate is None or not conditional(want_tx_rate, have_tx_rate.strip(), cast=int): failed_conditions.append('tx_rate ' + want_tx_rate) if want_rx_rate: match = re.search(r'%s (\d+)' % 'input rate', out, re.M) have_rx_rate = None if match: have_rx_rate = match.group(1) if have_rx_rate is None or not conditional(want_rx_rate, have_rx_rate.strip(), cast=int): failed_conditions.append('rx_rate ' + want_rx_rate) if want_neighbors: have_host = [] have_port = [] if have_neighbors is None: rc, have_neighbors, err = exec_command(module, 'show lldp neighbors detail') if rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) if have_neighbors: lines = have_neighbors.strip().split('Local Intf: ') for line in lines: field = line.split('\n') if field[0].strip() == w['name']: for item in field: if item.startswith('System Name:'): have_host.append(item.split(':')[1].strip()) if item.startswith('Port Description:'): have_port.append(item.split(':')[1].strip()) for item in want_neighbors: host = item.get('host') port = item.get('port') if host and host not in have_host: failed_conditions.append('host ' + host) if port and port not in have_port: failed_conditions.append('port ' + port) return failed_conditions