def check_declarative_intent_params(self): failed_conditions = [] for want_item in self._want: want_state = want_item.get('state') want_tx_rate = want_item.get('tx_rate') want_rx_rate = want_item.get('rx_rate') if want_state not in ( 'up', 'down') and not want_tx_rate and not want_rx_rate: continue if self._result['changed']: sleep(want_item['delay']) command = 'show interfaces {0!s}'.format(want_item['name']) out = run_commands(self._module, command)[0] 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({0!s})'.format(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 failed_conditions: msg = 'One or more conditional statements have not been satisfied' self._module.fail_json(msg=msg, failed_conditions=failed_conditions)
def check_declarative_intent_params(self, result): failed_conditions = [] delay_called = False rates = None statuses = None for req_if in self._required_config: want_state = req_if.get('state') want_tx_rate = req_if.get('tx_rate') want_rx_rate = req_if.get('rx_rate') name = req_if['name'] if want_state not in ('up', 'down') and not want_tx_rate and not \ want_rx_rate: continue if not delay_called and result['changed']: delay_called = True delay = req_if['delay'] if delay > 0: sleep(delay) if want_state in ('up', 'down'): if statuses is None: statuses = self._get_interfaces_status() or {} cond = self._check_state(name, want_state, statuses) if cond: failed_conditions.append(cond) if_rates = None if want_tx_rate or want_rx_rate: if not rates: rates = self._get_interfaces_rates() if_rates = rates.get(name) if if_rates: if_rates = if_rates[0] if want_tx_rate: have_tx_rate = None if if_rates: have_tx_rate = if_rates.get('egress rate') if have_tx_rate: have_tx_rate = have_tx_rate.split()[0] 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: have_rx_rate = None if if_rates: have_rx_rate = if_rates.get('ingress rate') if have_rx_rate: have_rx_rate = have_rx_rate.split()[0] 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_state(self, name, want_state, statuses): curr_if = statuses.get(name, {}) if curr_if: curr_if = curr_if[0] curr_state = self.get_oper_state(curr_if).strip() if curr_state is None or not conditional(want_state, curr_state): return 'state eq(%s)' % want_state
def check_declarative_intent_params(module, want, result): failed_conditions = [] have_neighbors_lldp = None have_neighbors_cdp = 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_lldp is None: rc, have_neighbors_lldp, 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_lldp: lines = have_neighbors_lldp.strip().split('Local port: ') for line in lines: field = line.split('\n') if field[0].strip() == w['name'].split(' ')[1]: for item in field: match = re.search( r'\s*\+\s+System name\s+:\s+"(.*)"', item, re.M) if match: have_host.append(match.group(1)) match = re.search( r'\s*\+\s+Port description\s+:\s+"(.*)"', item, re.M) if match: have_port.append(match.group(1)) 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 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 been 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_lldp = None have_neighbors_cdp = 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 = [] # Process LLDP neighbors if have_neighbors_lldp is None: rc, have_neighbors_lldp, 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_lldp: lines = have_neighbors_lldp.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()) # Process CDP neighbors if have_neighbors_cdp is None: rc, have_neighbors_cdp, err = exec_command(module, 'show cdp neighbors detail') if rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) if have_neighbors_cdp: neighbors_cdp = re.findall('Device ID: (.*?)\n.*?Interface: (.*?), Port ID .outgoing port.: (.*?)\n', have_neighbors_cdp, re.S) for host, localif, remoteif in neighbors_cdp: if localif == w['name']: have_host.append(host) have_port.append(remoteif) 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(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 = { 'command': 'show interfaces %s' % w['name'], 'output': 'text' } output = run_commands(module, [command]) if want_state in ('up', 'down'): match = re.search(r'%s (\w+)' % 'line protocol is', output[0], 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', output[0], 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', output[0], 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: command = { 'command': 'show lldp neighbors {0}'.format(w['name']), 'output': 'text' } have_neighbors = run_commands(module, [command]) if have_neighbors[0]: lines = have_neighbors[0].strip().split('\n') col = None for index, line in enumerate(lines): if re.search( r"^Port\s+Neighbor Device ID\s+Neighbor Port ID\s+TTL", line): col = index break if col and col < len(lines) - 1: for items in lines[col + 1:]: value = re.split(r'\s+', items) try: have_port.append(value[2]) have_host.append(value[1]) except IndexError: pass 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(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 interface %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', 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', 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 Interface: ') short_name = w['name'].replace('Ethernet', 'Eth') for line in lines: field = line.split('\n') if field[0].split('(')[0].strip() == short_name: for item in field: if item.startswith('System Name:'): have_host.append(item.split(':')[1].strip()) if item.startswith('Remote Interface:'): have_port.append(item.split(':')[1].split('(')[0].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(module, want, result): failed_conditions = [] have_neighbors_lldp = 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 interface %s brief' % 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'): state_data = out.strip().lower().split(w['name']) have_state = None have_state = state_data[1].split()[3] if have_state is None or not conditional(want_state, have_state.strip()): failed_conditions.append('state ' + 'eq(%s)' % want_state) command = 'show interface %s' % w['name'] rc, out, err = exec_command(module, command) have_tx_rate = None have_rx_rate = None rates = out.splitlines() for s in rates: s = s.strip() if 'output rate' in s and 'input rate' in s: sub = s.split() if want_tx_rate: have_tx_rate = sub[8] 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: have_rx_rate = sub[2] 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 = [] # Process LLDP neighbors if have_neighbors_lldp is None: rc, have_neighbors_lldp, 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_lldp: lines = have_neighbors_lldp.strip().split('Local Port ID: ') 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
def test_conditional(): assert conditional(10, 10) assert conditional('10', '10') assert conditional('foo', 'foo') assert conditional(True, True) assert conditional(False, False) assert conditional(None, None) assert conditional("ge(1)", 1) assert conditional("gt(1)", 2) assert conditional("le(2)", 2) assert conditional("lt(3)", 2) assert conditional("eq(1)", 1) assert conditional("neq(0)", 1) assert conditional("min(1)", 1) assert conditional("max(1)", 1) assert conditional("exactly(1)", 1)
def check_declarative_intent_params(module, want): failed_conditions = [] have_neighbors = None for w in want: if w['interface_type']: continue want_tx_rate = w.get('tx_rate') want_rx_rate = w.get('rx_rate') want_neighbors = w.get('neighbors') if not (want_tx_rate or want_rx_rate or want_neighbors): continue time.sleep(module.params['delay']) cmd = [{ 'command': 'show interface {0}'.format(w['name']), 'output': 'text' }] try: out = run_commands(module, cmd, check_rc=False)[0] except (AttributeError, IndexError, TypeError): out = '' if want_tx_rate: match = re.search(r'output rate (\d+)', 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'input rate (\d+)', 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: cmd = [{ 'command': 'show lldp neighbors interface {0} detail'.format( w['name']), 'output': 'text' }] output = run_commands(module, cmd, check_rc=False) if output: have_neighbors = output[0] else: have_neighbors = '' if have_neighbors and 'Total entries displayed: 0' not in have_neighbors: for line in have_neighbors.strip().split('\n'): if line.startswith('Port Description'): have_port.append(line.split(': ')[1]) if line.startswith('System Name'): have_host.append(line.split(': ')[1]) 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