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):
    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
예제 #5
0
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
예제 #6
0
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 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, 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 = 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
예제 #10
0
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
예제 #11
0
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