[wip] Remove network content (#84)

* rebase

* remove broken symlinks

* more deletes

* restore cs_* integration tests

* More deletes - from Felix

* cs_common

* Remove some more ignores
This commit is contained in:
John R Barker 2020-04-01 20:34:05 +01:00 committed by GitHub
parent 8d203225d3
commit c313c825f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2215 changed files with 0 additions and 333978 deletions

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,85 +0,0 @@
---
- debug:
msg: "START ce_is_is_instance merged integration tests on connection={{ ansible_connection }}"
- block:
- name: berfore merged, there should be no isis 100.
ce_is_is_instance: &delete
instance_id: 100
state: absent
- name: Merge the provided configuration with the exisiting running configuration
ce_is_is_instance: &merged
instance_id: 100
vpn_name: '__public__'
register: result
- name: change ansible_connection to network_cli
ce_netconf:
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId></instanceId>
<vpnName></vpnName>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- "'<instanceId>100</instanceId>' in result_xml.end_state.result"
- "'<vpnName>__public__</vpnName>' in result_xml.end_state.result"
- name: Merge the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_instance: *merged
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
- name: delete the provided configuration with the exisiting running configuration
ce_is_is_instance: *delete
register: result
- name: change ansible_connection to network_cli
ce_netconf:
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId></instanceId>
<vpnName></vpnName>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- "'<instanceId>100</instanceId>' not in result_xml.end_state.result"
- "'<vpnName>__public__</vpnName>' not in result_xml.end_state.result"
- name: delete the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_instance: *delete
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
- debug:
msg: "END ce_is_is_instance merged integration tests on connection={{ ansible_connection }}"

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,133 +0,0 @@
---
- debug:
msg: "START ce_is_is_interface merged integration tests on connection={{ ansible_connection }}"
- block:
- name: Merge the provided configuration with the exisiting running configuration
ce_is_is_interface: &delete
instance_id: 100
ifname: 10GE1/0/1
leveltype: level_1
level1dispriority: 10
silentenable: true
silentcost: true
typep2penable: true
snpacheck: true
p2pnegotiationmode: 2_way
p2ppeeripignore: true
ppposicpcheckenable: true
level2cost: 10
state: absent
register: result
- name: Merge the provided configuration with the exisiting running configuration
ce_is_is_interface: &merged
instance_id: 100
ifname: 10GE1/0/1
leveltype: level_1
level1dispriority: 10
silentenable: true
silentcost: true
typep2penable: true
snpacheck: true
p2pnegotiationmode: 2_way
p2ppeeripignore: true
ppposicpcheckenable: true
level2cost: 10
register: result
- name: use ce_netconf to get configuration
ce_netconf:
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isCircuits>
<isCircuit>
</isCircuit>
</isCircuits>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: Assert the configuration is reflected on host
assert:
that:
- "'<ifName>10GE1/0/1</ifName>' in result_xml.end_state.result"
- "'<circuitLevelType>level_1</circuitLevelType>' in result_xml.end_state.result"
- "'<level1DisPriority>10</level1DisPriority>' in result_xml.end_state.result"
- "'<level2DisPriority>10</level2DisPriority>' in result_xml.end_state.result"
- "'<silentEnable>true</silentEnable>' in result_xml.end_state.result"
- "'<silentCost>true</silentCost>' in result_xml.end_state.result"
- "'<typeP2pEnable>true</typeP2pEnable>' in result_xml.end_state.result"
- "'<snpaCheck>true</snpaCheck>' in result_xml.end_state.result"
- "'<p2pNegotiationMode>2_way</p2pNegotiationMode>' in result_xml.end_state.result"
- "'<p2pPeerIPIgnore>true</p2pPeerIPIgnore>' in result_xml.end_state.result"
- "'<pPPOsicpCheckEnable>true</pPPOsicpCheckEnable>' in result_xml.end_state.result"
- "'<level1Cost>10</level1Cost>' in result_xml.end_state.result"
- "'<level2Cost>10</level2Cost>' in result_xml.end_state.result"
- name: Merge the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_interface: *merged
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
- name: delete the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_interface: *delete
register: result
- name: use ce_netconf to get configuration
ce_netconf:
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isCircuits>
<isCircuit>
</isCircuit>
</isCircuits>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: Assert the configuration is reflected on host
assert:
that:
- "'<ifName>10GE1/0/1</ifName>' not in result_xml.end_state.result"
- "'<circuitLevelType>level_1</circuitLevelType>' not in result_xml.end_state.result"
- "'<level1DisPriority>10</level1DisPriority>' not in result_xml.end_state.result"
- "'<level2DisPriority>10</level2DisPriority>' not in result_xml.end_state.result"
- "'<silentEnable>true</silentEnable>' not in result_xml.end_state.result"
- "'<silentCost>true</silentCost>' not in result_xml.end_state.result"
- "'<typeP2pEnable>true</typeP2pEnable>' not in result_xml.end_state.result"
- "'<snpaCheck>true</snpaCheck>' not in result_xml.end_state.result"
- "'<p2pNegotiationMode>2_way</p2pNegotiationMode>' not in result_xml.end_state.result"
- "'<p2pPeerIPIgnore>true</p2pPeerIPIgnore>' not in result_xml.end_state.result"
- "'<pPPOsicpCheckEnable>true</pPPOsicpCheckEnable>' not in result_xml.end_state.result"
- "'<level1Cost>10</level1Cost>' not in result_xml.end_state.result"
- "'<level2Cost>10</level2Cost>' not in result_xml.end_state.result"
- name: delete the provided configuration with the existing running configuration (REPEAT)
ce_is_is_interface: *delete
register: result
- name: Assert that the previous task was REPEAT
assert:
that:
- "result['changed'] == false"
- debug:
msg: "END ce_is_is_interface merged integration tests on connection={{ ansible_connection }}"

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,21 +0,0 @@
---
- debug:
msg: "CLEANUP ce_is_is_view, deleted integration tests on connection={{ ansible_connection }}"
- name: Get lacp config by ce_netconf.
ce_netconf:
rpc: get
cfg_xml: "<config>
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite operation=\"delete\">
<instanceId>100</instanceId>
<vpnName>_public_</vpnName>
<description>ISIS</description>
</isSite>
</isSites>
</isiscomm>
</config>"
- debug:
msg: "END CLEANUP ce_is_is_view, deleted integration tests on connection={{ ansible_connection }}"

View file

@ -1,22 +0,0 @@
---
- debug:
msg: "SETUP ce_is_is_view integration tests on connection={{ ansible_connection }}"
# create ISIS 100
- name: Get lacp config by ce_netconf.
ce_netconf:
rpc: get
cfg_xml: "<config>
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite operation=\"merg\">
<instanceId>100</instanceId>
<vpnName>_public_</vpnName>
<description>ISIS</description>
</isSite>
</isSites>
</isiscomm>
</config>"
- debug:
msg: "END SETUP ce_is_is_view integration tests on connection={{ ansible_connection }}"

View file

@ -1,78 +0,0 @@
---
- debug:
msg: "START ce_is_is_view entity presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
netentity: isis_net_entity
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isNetEntitys>
<isNetEntity>
<netEntity></netEntity>
</isNetEntity>
</isNetEntitys>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<instanceId>100</instanceId>' in result_xml.end_state.result"
- "'<netEntity>isis_net_entity</netEntity>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
netentity: isis_net_entity
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<instanceId>100</instanceId>' not in result_xml.end_state.result"
- "''<netEntity>isis_net_entity</netEntity>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view pentity resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,92 +0,0 @@
---
- debug:
msg: "START ce_is_is_view EXPORTROUTE route policy presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
bfd_min_rx: 100
bfd_min_tx: 100
bfd_multiplier_num: 10
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<addressFamily>afIpv4</addressFamily>
<mtId>0</mtId>
<bfdMinRx></bfdMinRx>
<bfdMinTx></bfdMinTx>
<bfdMultNum></bfdMultNum>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<bfdMinRx>100</bfdMinRx>' in result_xml.end_state.result"
- "'<bfdMinTx>100</bfdMinTx>' in result_xml.end_state.result"
- "'<bfdMultNum>10</bfdMultNum>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
defaultmode: always
cost: 10
mode_tag: 10
level_type: level_1
avoid_learning: true
mode_routepolicyname: routepolicy_name
tag: 100
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<bfdMinRx>100</bfdMinRx>' not in result_xml.end_state.result"
- "'<bfdMinTx>100</bfdMinTx>' not in result_xml.end_state.result"
- "'<bfdMultNum>10</bfdMultNum>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view EXPORTROUTE route policy resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,96 +0,0 @@
---
- debug:
msg: "START ce_is_is_view EXPORTROUTE route policy presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
export_protocol: ospf
export_policytype: aclNumOrName
export_processid: 100
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<addressFamily>afIpv4</addressFamily>
<mtId>0</mtId>
<isFilterExports>
<isFilterExport>
<protocol></protocol>
<processId></processId>
<policyType></policyType>
</isFilterExport>
</isFilterExports>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<protocol>ospf</protocol>' in result_xml.end_state.result"
- "'<processId>100</processId>' in result_xml.end_state.result"
- "'<policyType>level_1</policyType>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
defaultmode: always
cost: 10
mode_tag: 10
level_type: level_1
avoid_learning: true
mode_routepolicyname: routepolicy_name
tag: 100
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<protocol>ospf</protocol>' not in result_xml.end_state.result"
- "'<processId>100</processId>' not in result_xml.end_state.result"
- "'<policyType>level_1</policyType>' in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view EXPORTROUTE route policy resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,124 +0,0 @@
---
- debug:
msg: "START ce_is_is_view import route policy presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
protocol: ospf
processid: 100
cost_type: external
import_cost: 10
import_tag: 10
import_route_policy: routepolicy_name
impotr_leveltype: level_1
inheritcost: true
permitibgp: true
tag: 100
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<addressFamily>afIpv4</addressFamily>
<mtId>0</mtId>
<isImportRoutes>
<isImportRoute>
<protocol></protocol>
<processId></processId>
<costType></costType>
<cost></cost>
<tag></tag>
<policyType></policyType>
<routePolicyName></routePolicyName>
<levelType></levelType>
<inheritCost></inheritCost>
<permitIbgp></permitIbgp>
</isImportRoute>
</isImportRoutes>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<protocol>ospf</protocol>' in result_xml.end_state.result"
- "'<processId>100</processId>' in result_xml.end_state.result"
- "'<costType>external</costType>' in result_xml.end_state.result"
- "'<cost>10</cost>' in result_xml.end_state.result"
- "'<tag>10</tag>' in result_xml.end_state.result"
- "'<policyType>level_1</policyType>' in result_xml.end_state.result"
- "'<routePolicyName>routepolicy_name</routePolicyName>' in result_xml.end_state.result"
- "'<levelType>level_1</levelType>' in result_xml.end_state.result"
- "'<inheritCost>true</inheritCost>' in result_xml.end_state.result"
- "'<permitIbgp>true</permitIbgp>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
defaultmode: always
cost: 10
mode_tag: 10
level_type: level_1
avoid_learning: true
mode_routepolicyname: routepolicy_name
tag: 100
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<protocol>ospf</protocol>' not in result_xml.end_state.result"
- "'<processId>100</processId>' not in result_xml.end_state.result"
- "'<costType>external</costType>' not in result_xml.end_state.result"
- "'<cost>10</cost>' not in result_xml.end_state.result"
- "'<tag>10</tag>' not in result_xml.end_state.result"
- "'<policyType>level_1</policyType>' not in result_xml.end_state.result"
- "'<routePolicyName>routepolicy_name</routePolicyName>' not in result_xml.end_state.result"
- "'<levelType>level_1</levelType>' not in result_xml.end_state.result"
- "'<inheritCost>true</inheritCost>' not in result_xml.end_state.result"
- "'<permitIbgp>true</permitIbgp>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view import route policy resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,109 +0,0 @@
---
- debug:
msg: "START ce_is_is_view import route policy presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
allow_filter: true
allow_up_down: true
ip_prefix_name: prefix_name
aclnum_or_name: 3001
penetration_direct: level1-level2
import_routepolicy_name: routepolicy_name
tag: 100
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<addressFamily>afIpv4</addressFamily>
<mtId>0</mtId>
<isLeakRouteLevel2ToLevel1s>
<isLeakRouteLevel2ToLevel1>
<tag></tag>
<routePolicyName></routePolicyName>
<aclNumOrName></aclNumOrName>
<ipPrefix></ipPrefix>
<allowFilter></allowFilter>
<allowUpdown></allowUpdown>
</isLeakRouteLevel2ToLevel1>
</isLeakRouteLevel2ToLevel1s>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<tag>100</tag>' in result_xml.end_state.result"
- "'<routePolicyName>routepolicy_name</routePolicyName>' in result_xml.end_state.result"
- "'<allowUpdown>true</allowUpdown>' in result_xml.end_state.result"
- "'<aclNumOrName>3001</aclNumOrName>' in result_xml.end_state.result"
- "'<ipPrefix>prefix_name</ipPrefix>' in result_xml.end_state.result"
- "'<allowFilter>true</allowFilter>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
allow_filter: true
allow_up_down: true
ip_prefix_name: prefix_name
aclnum_or_name: 3001
penetration_direct: level1-level2
import_routepolicy_name: routepolicy_name
tag: 100
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<tag>100</tag>' in result_xml.end_state.result"
- "'<routePolicyName>routepolicy_name</routePolicyName>' not in result_xml.end_state.result"
- "'<allowUpdown>true</allowUpdown>' not in result_xml.end_state.result"
- "'<aclNumOrName>3001</aclNumOrName>' not in result_xml.end_state.result"
- "'<ipPrefix>prefix_name</ipPrefix>' not in result_xml.end_state.result"
- "'<allowFilter>true</allowFilter>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view import route policy resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,109 +0,0 @@
---
- debug:
msg: "START ce_is_is_view import route policy presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
penetration_direct: level2-level1
allow_filter: true
allow_up_down: true
ip_prefix_name: prefix_name
aclnum_or_name: 3001
import_routepolicy_name: routepolicy_name
tag: 100
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<addressFamily>afIpv4</addressFamily>
<mtId>0</mtId>
<isLeakRouteLevel2ToLevel1s>
<isLeakRouteLevel1ToLevel2s>
<tag></tag>
<routePolicyName></routePolicyName>
<aclNumOrName></aclNumOrName>
<ipPrefix></ipPrefix>
<allowFilter></allowFilter>
<allowUpdown></allowUpdown>
</isLeakRouteLevel1ToLevel2s>
</isLeakRouteLevel2ToLevel1s>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<tag>100</tag>' in result_xml.end_state.result"
- "'<routePolicyName>routepolicy_name</routePolicyName>' in result_xml.end_state.result"
- "'<allowUpdown>true</allowUpdown>' in result_xml.end_state.result"
- "'<aclNumOrName>3001</aclNumOrName>' in result_xml.end_state.result"
- "'<ipPrefix>prefix_name</ipPrefix>' in result_xml.end_state.result"
- "'<allowFilter>true</allowFilter>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
penetration_direct: level2-level1
allow_filter: true
allow_up_down: true
ip_prefix_name: prefix_name
aclnum_or_name: 3001
import_routepolicy_name: routepolicy_name
tag: 100
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<tag>100</tag>' in result_xml.end_state.result"
- "'<routePolicyName>routepolicy_name</routePolicyName>' not in result_xml.end_state.result"
- "'<allowUpdown>true</allowUpdown>' not in result_xml.end_state.result"
- "'<aclNumOrName>3001</aclNumOrName>' not in result_xml.end_state.result"
- "'<ipPrefix>prefix_name</ipPrefix>' not in result_xml.end_state.result"
- "'<allowFilter>true</allowFilter>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view import route policy resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,80 +0,0 @@
---
- debug:
msg: "START ce_is_is_view maxLoadBalancing presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
max_load: 30
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<addressFamily>afIpv4</addressFamily>
<mtId>0</mtId>
<maxLoadBalancing></maxLoadBalancing>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<instanceId>100</instanceId>' in result_xml.end_state.result"
- "'<maxLoadBalancing>30</maxLoadBalancing>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
max_load: 30
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<instanceId>100</instanceId>' not in result_xml.end_state.result"
- "'<maxLoadBalancing>30</maxLoadBalancing>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view maxLoadBalancing resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,87 +0,0 @@
---
- debug:
msg: "START ce_is_is_view preferences presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
preference_value: 100
route_policy_name: route
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<isPreferences>
<isPreference>
<preferenceValue></preferenceValue>
<routePolicyName></routePolicyName>
</isPreference>
</isPreferences>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<instanceId>100</instanceId>' in result_xml.end_state.result"
- "'<preferenceValue>100</preferenceValue>' in result_xml.end_state.result"
- "'<routePolicyName>route</routePolicyName>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
preference_value: 100
route_policy_name: route
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<instanceId>100</instanceId>' not in result_xml.end_state.result"
- "''<preferenceValue>100</preferenceValue>' not in result_xml.end_state.result"
- "''<routePolicyName>route</routePolicyName>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view Preference resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,115 +0,0 @@
---
- debug:
msg: "START ce_is_is_view presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
description: ISIS
islevel: level_1
coststyle: narrow
relaxSpfLimit: true
stdlevel1cost: 60
stdlevel2cost: 60
stdbandwidth: 100
autocostenable: true
autocostenablecompatible: true
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<description></description>
<isLevel></isLevel>
<costStyle></costStyle>
<relaxSpfLimit></relaxSpfLimit>
<stdLevel1Cost></stdLevel1Cost>
<stdLevel2Cost></stdLevel2Cost>
<stdbandwidth></stdbandwidth>
<stdAutoCostEnable></stdAutoCostEnable>
<stdAutoCostEnableCompatible></stdAutoCostEnableCompatible>
</isSite>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<instanceId>100</instanceId>' in result_xml.end_state.result"
- "'<vpnName>_public_</vpnName>' in result_xml.end_state.result"
- "'<description>ISIS</description>' in result_xml.end_state.result"
- "'<isLevel>level_1</isLevel>' in result_xml.end_state.result"
- "'<costStyle>narrow</costStyle>' in result_xml.end_state.result"
- "'<relaxSpfLimit>true</relaxSpfLimit>' in result_xml.end_state.result"
- "'<stdLevel1Cost>60</stdLevel1Cost>' in result_xml.end_state.result"
- "'<stdLevel2Cost>60</stdLevel2Cost>' in result_xml.end_state.result"
- "'<stdbandwidth>100</stdbandwidth>' in result_xml.end_state.result"
- "'<stdAutoCostEnable>true</stdAutoCostEnable>' in result_xml.end_state.result"
- "'<stdAutoCostEnableCompatible>true</stdAutoCostEnableCompatible>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
description: ISIS
islevel: level_1
coststyle: narrow
relaxSpfLimit: true
stdlevel1cost: 60
stdlevel2cost: 60
stdbandwidth: 100
autocostenable: true
autocostenablecompatible: true
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<instanceId>100</instanceId>' not in result_xml.end_state.result"
- "'<vpnName>_public_</vpnName>' not in result_xml.end_state.result"
- "'<description>ISIS</description>' not in result_xml.end_state.result"
- "'<isLevel>level_1</isLevel>' not in result_xml.end_state.result"
- "'<costStyle>narrow</costStyle>' not in result_xml.end_state.result"
- "'<relaxSpfLimit>true</relaxSpfLimit>' not in result_xml.end_state.result"
- "'<stdLevel1Cost>60</stdLevel1Cost>' not in result_xml.end_state.result"
- "'<stdLevel2Cost>60</stdLevel2Cost>' not in result_xml.end_state.result"
- "'<stdbandwidth>100</stdbandwidth>' not in result_xml.end_state.result"
- "'<stdAutoCostEnable>true</stdAutoCostEnable>' not in result_xml.end_state.result"
- "'<stdAutoCostEnableCompatible>true</stdAutoCostEnableCompatible>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view presentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,111 +0,0 @@
---
- debug:
msg: "START ce_is_is_view import route policy presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
defaultmode: always
cost: 10
mode_tag: 10
level_type: level_1
avoid_learning: true
mode_routepolicyname: routepolicy_name
tag: 100
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<addressFamily>afIpv4</addressFamily>
<mtId>0</mtId>
<isDefaultRoutes>
<isDefaultRoute>
<defaultMode></defaultMode>
<routePolicyName></routePolicyName>
<cost></cost>
<tag></tag>
<levelType></levelType>
<avoidLearning></avoidLearning>
</isDefaultRoute>
</isDefaultRoutes>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<tag>100</tag>' in result_xml.end_state.result"
- "'<defaultMode>always</defaultMode>' in result_xml.end_state.result"
- "'<routePolicyName>routepolicy_name</routePolicyName>' in result_xml.end_state.result"
- "'<cost>10</cost>' in result_xml.end_state.result"
- "'<tag>10</tag>' in result_xml.end_state.result"
- "'<levelType>level_1</levelType>' in result_xml.end_state.result"
- "'<avoidLearning>true</avoidLearning>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
defaultmode: always
cost: 10
mode_tag: 10
level_type: level_1
avoid_learning: true
mode_routepolicyname: routepolicy_name
tag: 100
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<tag>100</tag>' not in result_xml.end_state.result"
- "'<defaultMode>always</defaultMode>' not in result_xml.end_state.result"
- "'<routePolicyName>routepolicy_name</routePolicyName>' not in result_xml.end_state.result"
- "'<cost>10</cost>' not in result_xml.end_state.result"
- "'<tag>10</tag>' not in result_xml.end_state.result"
- "'<levelType>level_1</levelType>' not in result_xml.end_state.result"
- "'<avoidLearning>true</avoidLearning>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view import route policy resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,97 +0,0 @@
---
- debug:
msg: "START ce_is_is_view EXPORTROUTE route policy presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
import_aclnumorname: 301
import_ipprefix: ipprefix
import_routepolicyname: routepolicyname
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<addressFamily>afIpv4</addressFamily>
<mtId>0</mtId>
<isFilterImports>
<isFilterImport>
<aclNumOrName></aclNumOrName>
<ipPrefix></ipPrefix>
<routePolicyName></routePolicyName>
</isFilterImport>
</isFilterImports>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<aclNumOrName>3001</aclNumOrName>' in result_xml.end_state.result"
- "'<ipPrefix>ipprefix</ipPrefix>' in result_xml.end_state.result"
- "'<routePolicyName>routepolicyname</routePolicyName>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
defaultmode: always
cost: 10
mode_tag: 10
level_type: level_1
avoid_learning: true
mode_routepolicyname: routepolicy_name
tag: 100
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<aclNumOrName>3001</aclNumOrName>' not in result_xml.end_state.result"
- "'<ipPrefix>ipprefix</ipPrefix>' not in result_xml.end_state.result"
- "'<routePolicyName>routepolicyname</routePolicyName>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view EXPORTROUTE route policy resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,87 +0,0 @@
---
- debug:
msg: "START ce_is_is_view next hop presented integration tests on connection={{ ansible_connection }}"
- include_tasks: setup.yaml
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &present
instance_id: 100
ip_address: 1.1.1.1
weight: 100
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<isiscomm xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<isSites>
<isSite>
<instanceId>100</instanceId>
<isSiteMTs>
<isSiteMT>
<addressFamily>afIpv4</addressFamily>
<mtId>0</mtId>
<isNextHopWeights>
<isNextHopWeight>
<ipAddress></ipAddress>
<weight></weight>
</isNextHopWeight>
</isNextHopWeights>
</isSiteMT>
</isSiteMTs>
</isSite>
</isSites>
</isiscomm>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<ipAddress>1.1.1.1</ipAddress>' in result_xml.end_state.result"
- "'<weight>100</weight>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_is_is_view: &absent
instance_id: 100
ip_address: 1.1.1.1
weight: 100
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_is_is_view: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<ipAddress>1.1.1.1</ipAddress>' not in result_xml.end_state.result"
- "'<weight>100</weight>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_is_is_view next hop resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,95 +0,0 @@
---
- debug:
msg: "START ce_lacp merged integration tests on connection={{ ansible_connection }}"
# befor removing, it should be merged
- include_tasks: merge.yaml
- name: Merge the provided configuration with the exisiting running configuration
ce_lacp: &absent
mode: Dynamic
trunk_id: 10
preempt_enable: True
state_flapping: True
port_id_extension_enable: True
unexpected_mac_disable: True
system_id: 1111-2222-3333
timeout_type: Fast
fast_timeout: 12
mixed_rate_link_enable: True
preempt_delay: 12
collector_delay: 12
max_active_linknumber: 2
select: Prority
priority: 23
global_priority: 123
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get lacp config by ce_netconf.
ce_netconf:
rpc: get
cfg_xml: "<filter type=\"subtree\">
<ifmtrunk xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<TrunkIfs>
<TrunkIf>
<ifName>Eth-Trunk10</ifName>
<lacpTrunk>
<isSupportPrmpt></isSupportPrmpt>
<rcvTimeoutType></rcvTimeoutType>
<fastTimeoutUserDefinedValue></fastTimeoutUserDefinedValue>
<selectPortStd></selectPortStd>
<promptDelay></promptDelay>
<maxActiveNum></maxActiveNum>
<collectMaxDelay></collectMaxDelay>
<mixRateEnable></mixRateEnable>
<dampStaFlapEn></dampStaFlapEn>
<dampUnexpMacEn></dampUnexpMacEn>
<trunkSysMac></trunkSysMac>
<trunkPortIdExt></trunkPortIdExt>
</lacpTrunk>
</TrunkIf>
</TrunkIfs>
</ifmtrunk>
</filter>"
register: result_ifs_merged
- name: Get lacp config by ce_netconf.
ce_netconf:
rpc: get
cfg_xml: "<filter type=\"subtree\">
<ifmtrunk xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<lacpSysInfo>
<priority></priority>
</lacpSysInfo>
</ifmtrunk>
</filter>"
register: result_global_merged
- name: Merge the provided configuration with the existing running configuration (IDEMPOTENT)
ce_lacp: *absent
register: result_re_merged
- name: Assert that the previous task was idempotent, some become ot default values, others depend on devices.
assert:
that:
- "result_re_merged.changed == false"
- "'<isSupportPrmpt>false</isSupportPrmpt>' == result_ifs_merged.end_state.result"
- "'<rcvTimeoutType>Slow</rcvTimeoutType>' == result_ifs_merged.end_state.result"
- "'<fastTimeoutUserDefinedValue>90</fastTimeoutUserDefinedValue>' == result_ifs_merged.end_state.result"
- "'<selectPortStd>Prority</selectPortStd>' == result_ifs_merged.end_state.result"
- "'<promptDelay>30</promptDelay>' == result_ifs_merged.end_state.result"
- "'<collectMaxDelay>0</collectMaxDelay>' in result_ifs_merged.end_state.result"
- "'<mixRateEnable>false</mixRateEnable>' in result_ifs_merged.end_state.result"
- "'<dampStaFlapEn>false</dampStaFlapEn>' in result_ifs_merged.end_state.result"
- "'<dampUnexpMacEn>false</dampUnexpMacEn>' in result_ifs_merged.end_state.result"
- "'<trunkSysMac>false</trunkSysMac>' in result_ifs_merged.end_state.result"
- "'<priority>32768</priority>' in result_global_merged.end_state.result"
- debug:
msg: "END ce_lacp merged integration tests on connection={{ ansible_connection }}"

View file

@ -1,32 +0,0 @@
---
- debug:
msg: "START ce_lacp deleted integration tests on connection={{ ansible_connection }}"
- name: Merge the provided configuration with the exisiting running configuration
ce_lacp:
mode: Dynamic
trunk_id: 10
preempt_enable: True
state_flapping: True
port_id_extension_enable: True
unexpected_mac_disable: True
system_id: 1111-2222-3333
timeout_type: Fast
fast_timeout: 12
mixed_rate_link_enable: True
preempt_delay: 12
collector_delay: 12
max_active_linknumber: 2
select: Prority
priority: 23
global_priority: 123
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- debug:
msg: "END ce_lacp deleted integration tests on connection={{ ansible_connection }}"

View file

@ -1,31 +0,0 @@
---
- debug:
msg: "START ce_lacp merged integration tests on connection={{ ansible_connection }}"
- name: Merge the provided configuration with the exisiting running configuration
ce_lacp:
mode: Dynamic
trunk_id: 10
preempt_enable: True
state_flapping: True
port_id_extension_enable: True
unexpected_mac_disable: True
system_id: 1111-2222-3333
timeout_type: Fast
fast_timeout: 12
mixed_rate_link_enable: True
preempt_delay: 12
collector_delay: 12
max_active_linknumber: 2
select: Prority
priority: 23
global_priority: 123
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- debug:
msg: "END ce_lacp merged integration tests on connection={{ ansible_connection }}"

View file

@ -1,103 +0,0 @@
---
- debug:
msg: "START ce_lacp presented integration tests on connection={{ ansible_connection }}"
- name: present the provided configuration with the exisiting running configuration
ce_lacp: &present
mode: Dynamic
trunk_id: 10
preempt_enable: True
state_flapping: True
port_id_extension_enable: True
unexpected_mac_disable: True
system_id: 1111-2222-3333
timeout_type: Fast
fast_timeout: 12
mixed_rate_link_enable: True
preempt_delay: 12
collector_delay: 12
max_active_linknumber: 2
select: Prority
priority: 23
global_priority: 123
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get lacp config by ce_netconf.
ce_netconf:
rpc: get
cfg_xml: "<filter type=\"subtree\">
<ifmtrunk xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<TrunkIfs>
<TrunkIf>
<ifName>Eth-Trunk10</ifName>
<workMode></workMode>
<lacpTrunk>
<isSupportPrmpt></isSupportPrmpt>
<rcvTimeoutType></rcvTimeoutType>
<fastTimeoutUserDefinedValue></fastTimeoutUserDefinedValue>
<selectPortStd></selectPortStd>
<promptDelay></promptDelay>
<maxActiveNum></maxActiveNum>
<collectMaxDelay></collectMaxDelay>
<mixRateEnable></mixRateEnable>
<dampStaFlapEn></dampStaFlapEn>
<dampUnexpMacEn></dampUnexpMacEn>
<trunkSysMac></trunkSysMac>
<trunkPortIdExt></trunkPortIdExt>
</lacpTrunk>
</TrunkIf>
</TrunkIfs>
</ifmtrunk>
</filter>"
register: result_ifs_presentd
- name: Get global lacp config by ce_netconf.
ce_netconf:
rpc: get
cfg_xml: "<filter type=\"subtree\">
<ifmtrunk xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<lacpSysInfo>
<priority></priority>
<lacpMlagGlobal>
<lacpMlagPriority></lacpMlagPriority>
<lacpMlagSysId></lacpMlagSysId>
</lacpMlagGlobal>
</lacpSysInfo>
</ifmtrunk>
</filter>"
register: result_global_presentd
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_lacp: *present
register: result_re_presentd
- name: Assert that the previous task was idempotent
assert:
that:
- "result_re_presentd.changed == false"
- "'<workMode>Dynamic</workMode>' == result_ifs_presentd.end_state.result"
- "'<isSupportPrmpt>true</isSupportPrmpt>' == result_ifs_presentd.end_state.result"
- "'<rcvTimeoutType>Fast</rcvTimeoutType>' == result_ifs_presentd.end_state.result"
- "'<fastTimeoutUserDefinedValue>12</fastTimeoutUserDefinedValue>' == result_ifs_presentd.end_state.result"
- "'<selectPortStd>Prority</selectPortStd>' == result_ifs_presentd.end_state.result"
- "'<promptDelay>12</promptDelay>' == result_ifs_presentd.end_state.result"
- "'<maxActiveNum>2</maxActiveNum>' == result_ifs_presentd.end_state.result"
- "'<collectMaxDelay>12</collectMaxDelay>' in result_ifs_presentd.end_state.result"
- "'<mixRateEnable>true</mixRateEnable>' in result_ifs_presentd.end_state.result"
- "'<dampStaFlapEn>true</dampStaFlapEn>' in result_ifs_presentd.end_state.result"
- "'<dampUnexpMacEn>true</dampUnexpMacEn>' in result_ifs_presentd.end_state.result"
- "'<trunkSysMac>true</trunkSysMac>' in result_ifs_presentd.end_state.result"
- "'<trunkPortIdExt>true</trunkPortIdExt>' in result_ifs_presentd.end_state.result"
- "'<lacpMlagSysId>1111-2222-3333</lacpMlagSysId>' in result_global_presentd.end_state.result"
- "'<priority>123</priority>' in result_global_presentd.end_state.result"
# after present, it should be deleted
- include_tasks: delete.yaml
- debug:
msg: "END ce_lacp presentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,108 +0,0 @@
---
- debug:
msg: "START ce_lldp absent integration tests on connection={{ ansible_connection }}"
- block:
- name: present the provided configuration befor absent
ce_lldp:
lldpenable: enabled
mdnstatus: rxOnly
interval: 35
hold_multiplier: 5
restart_delay: 3
transmit_delay: 5
notification_interval: 6
fast_count: 5
mdn_notification_interval: 10.1.1.1
management_address: 10.10.10.1
bind_name: vlanif100
register: result
- name: change ansible_connection to network_cli
set_fact:
ansible_connection: network_cli
- name: display lldp
ce_command:
commands:
- display current-configuration | include lldp
register: result_display
- name: change ansible_connection to netconf
set_fact:
ansible_connection: netconf
# There should be some configuration(LLDP) on host befor absent
- name: Assert the configuration is reflected on host
assert:
that:
- "'lldp enable' in result_display.stdout[0]"
- "'undo lldp mdn disable' in result_display.stdout[0]"
- "'lldp transmit interval 35' in result_display.stdout[0]"
- "'lldp transmit multiplier 5' in result_display.stdout[0]"
- "'lldp restart 3' in result_display.stdout[0]"
- "'lldp transmit delay 5' in result_display.stdout[0]"
- "'lldp fast-count 5' in result_display.stdout[0]"
- "'lldp management-address 10.10.10.1' in result_display.stdout[0]"
- "'lldp mdn trap-interval 6' in result_display.stdout[0]"
- "'lldp trap-interval 6' in result_display.stdout[0]"
- "'lldp management-address bind interface vlanif100' in result_display.stdout[0]"
- name: absent the provided configuration with the exisiting running configuration
ce_lldp: &absent
lldpenable: enabled
mdnstatus: rxOnly
interval: 35
hold_multiplier: 5
restart_delay: 3
transmit_delay: 5
notification_interval: 6
fast_count: 5
mdn_notification_interval: 10.1.1.1
management_address: 10.10.10.1
bind_name: vlanif100
state: absent
register: result
- name: change ansible_connection to network_cli
set_fact:
ansible_connection: network_cli
- name: display lldp
ce_command:
commands:
- display current-configuration | include lldp
register: result_display
- name: change ansible_connection to netconf
set_fact:
ansible_connection: netconf
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- "'lldp enable' not in result_display.stdout[0]"
- "'undo lldp mdn disable' not in result_display.stdout[0]"
- "'lldp transmit interval 35' not in result_display.stdout[0]"
- "'lldp transmit multiplier 5' not in result_display.stdout[0]"
- "'lldp restart 3' not in result_display.stdout[0]"
- "'lldp transmit delay 5' not in result_display.stdout[0]"
- "'lldp fast-count 5' not in result_display.stdout[0]"
- "'lldp management-address 10.10.10.1' not in result_display.stdout[0]"
- "'lldp mdn trap-interval 6' not in result_display.stdout[0]"
- "'lldp trap-interval 6' not in result_display.stdout[0]"
- "'lldp management-address bind interface vlanif100' not in result_display.stdout[0]"
- name: Merge the provided configuration with the existing running configuration (IDEMPOTENT)
ce_lldp: *absent
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
- debug:
msg: "END ce_lldp absent integration tests on connection={{ ansible_connection }}"

View file

@ -1,20 +0,0 @@
---
- debug:
msg: "Start ce_lldp deleted remove interface config ansible_connection={{ ansible_connection }}"
- name: change ansible_connection to network_cli
set_fact:
ansible_connection: network_cli
# After the global LLDP function is disabled, all LLDP configuration restore defaults except the LLDP alarm function.
- name: display lldp
ce_command:
commands:
- undo lldp enable
- lldp mdn disable
- name: change ansible_connection to netconf
set_fact:
ansible_connection: netconf
- debug:
msg: "End ce_lldp deleted remove interface config ansible_connection={{ ansible_connection }}"

View file

@ -1,66 +0,0 @@
---
- debug:
msg: "START ce_lldp merged integration tests on connection={{ ansible_connection }}"
- block:
- include_tasks: cleanup.yaml
- name: Merge the provided configuration with the exisiting running configuration
ce_lldp: &merged
lldpenable: enabled
mdnstatus: rxOnly
interval: 35
hold_multiplier: 5
restart_delay: 3
transmit_delay: 5
notification_interval: 6
fast_count: 5
mdn_notification_interval: 10.1.1.1
management_address: 10.10.10.1
bind_name: vlanif100
register: result
- name: change ansible_connection to network_cli
set_fact:
ansible_connection: network_cli
- name: display lldp
ce_command:
commands:
- display current-configuration | include lldp
register: result_display
- name: change ansible_connection to netconf
set_fact:
ansible_connection: netconf
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- "'lldp enable' in result_display.stdout[0]"
- "'undo lldp mdn disable' in result_display.stdout[0]"
- "'lldp transmit interval 35' in result_display.stdout[0]"
- "'lldp transmit multiplier 5' in result_display.stdout[0]"
- "'lldp restart 3' in result_display.stdout[0]"
- "'lldp transmit delay 5' in result_display.stdout[0]"
- "'lldp fast-count 5' in result_display.stdout[0]"
- "'lldp management-address 10.10.10.1' in result_display.stdout[0]"
- "'lldp mdn trap-interval 6' in result_display.stdout[0]"
- "'lldp trap-interval 6' in result_display.stdout[0]"
- "'lldp management-address bind interface vlanif100' in result_display.stdout[0]"
- name: Merge the provided configuration with the existing running configuration (IDEMPOTENT)
ce_lldp: *merged
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_lldp merged integration tests on connection={{ ansible_connection }}"

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,155 +0,0 @@
---
- debug:
msg: "START ce_lldp_interface merged integration tests on connection={{ ansible_connection }}"
- block:
- name: Merge the provided configuration with the exisiting running configuration - basic-tlv
ce_lldp_interface: &merged1
config:
msg_interval: 8
ifname: 10GE 1/0/1
admin_status: txandrx
basic_tlv:
management_addr: true
port_desc: true
system_capability: true
system_description: true
system_name: true
register: result1
- name: Merge the provided configuration with the existing running configuration (REPEAT)
ce_lldp_interface: *merged1
register: result2
- name: "Netconf get operation"
ce_netconf:
rpc: get
cfg_xml: '<filter type=\"subtree\">
<lldp xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<lldpInterfaces>
<lldpInterface>
<ifName>10GE1/0/1</ifName>
<msgInterval>
<txInterval></txInterval>
</msgInterval>
<lldpAdminStatus></lldpAdminStatus>
<tlvTxEnable>
<manAddrTxEnable></manAddrTxEnable>
<portDescTxEnable></portDescTxEnable>
<sysCapTxEnable></sysCapTxEnable>
</tlvTxEnable>
</lldpInterface>
</lldpInterfaces>
</lldp>
</filter>'
register: result3
- name: Assert the configuration is reflected on host
assert:
that:
- "result1['changed'] == true"
- "result2['changed'] == false"
- "'<txInterval>8</txInterval>' in result3.endstate.result"
- "'<lldpAdminStatus>txAndRx</lldpAdminStatus>' in result3.endstate.result"
- "'<manAddrTxEnable>true</manAddrTxEnable>' in result3.endstate.result"
- "'<portDescTxEnable>true</portDescTxEnable>' in result3.endstate.result"
- "'<sysCapTxEnable>true</sysCapTxEnable>' in result3.endstate.result"
- name: Merge the provided configuration with the exisiting running configuration - dot1-tlv
ce_lldp_interface: &merged2
config:
msg_interval: 8
ifname: 10GE 1/0/1
dot1_tlv:
port_vlan_enable: true
port_desc: true
prot_vlan_enable: true
prot_vlan_id: 123
vlan_name: 234
vlan_name_enable: true
register: result1
- name: Merge the provided configuration with the existing running configuration (REPEAT)
ce_lldp_interface: *merged2
register: result2
- name: "Netconf get operation"
ce_netconf:
rpc: get
cfg_xml: '<filter type=\"subtree\">
<lldp xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<lldpInterfaces>
<lldpInterface>
<ifName>10GE1/0/1</ifName>
<msgInterval>
<txInterval></txInterval>
</msgInterval>
<lldpAdminStatus></lldpAdminStatus>
<tlvTxEnable>
<portVlanTxEnable></portVlanTxEnable>
<protoVlanTxEnable></protoVlanTxEnable>
<txProtocolVlanId></txProtocolVlanId>
<vlanNameTxEnable></vlanNameTxEnable>
<txVlanNameId></txVlanNameId>
<protoIdTxEnable></protoIdTxEnable>
</tlvTxEnable>
</lldpInterface>
</lldpInterfaces>
</lldp>
</filter>'
register: result3
- name: Assert the configuration is reflected on host
assert:
that:
- "result1['changed'] == true"
- "result2['changed'] == false"
- "'<portVlanTxEnable>true</portVlanTxEnable>' in result3.endstate.result"
- "'<protoVlanTxEnable>true</protoVlanTxEnable>' in result3.endstate.result"
- "'<txProtocolVlanId>123</txProtocolVlanId>' in result3.endstate.result"
- "'<vlanNameTxEnable>true</vlanNameTxEnable>' in result3.endstate.result"
- "'<txVlanNameId>true</txVlanNameId>' in result3.endstate.result"
- "'<protoIdTxEnable>true</protoIdTxEnable>' in result3.endstate.result"
- name: Merge the provided configuration with the exisiting running configuration - dot3-tlv
ce_lldp_interface: &merged
config:
msg_interval: 8
ifname: 10GE 1/0/1
dot3_tlv:
eee: true
link_aggregation: true
mac_physic: true
max_frame_size: true
register: result1
- name: Merge the provided configuration with the existing running configuration (REPEAT)
ce_lldp_interface: *merged
register: result2
- name: "Netconf get operation"
ce_netconf:
rpc: get
cfg_xml: '<filter type=\"subtree\">
<lldp xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<lldpInterfaces>
<lldpInterface>
<ifName>10GE1/0/1</ifName>
<msgInterval>
<txInterval></txInterval>
</msgInterval>
<lldpAdminStatus></lldpAdminStatus>
<tlvTxEnable>
<macPhyTxEnable></macPhyTxEnable>
<linkAggreTxEnable></linkAggreTxEnable>
<maxFrameTxEnable></maxFrameTxEnable>
<eee></eee>
</tlvTxEnable>
</lldpInterface>
</lldpInterfaces>
</lldp>
</filter>'
register: result3
- name: Assert the configuration is reflected on host
assert:
that:
- "result1['changed'] == true"
- "result2['changed'] == false"
- "'<macPhyTxEnable>true</macPhyTxEnable>' in result3.endstate.result"
- "'<linkAggreTxEnable>true</linkAggreTxEnable>' in result3.endstate.result"
- "'<maxFrameTxEnable>123</maxFrameTxEnable>' in result3.endstate.result"
- debug:
msg: "END ce_lldp_interface merged integration tests on connection={{ ansible_connection }}"

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,97 +0,0 @@
---
- debug:
msg: "START ce_mdn_interface presented integration tests on connection={{ ansible_connection }}"
# set up default before test
- name: clean up default configuration with the exisiting running configuration
ce_mdn_interface:
lldpenable: disabled
mdnstatus: disabled
ifname: 10GE1/0/1
- name: present the provided configuration with the exisiting running configuration
ce_mdn_interface: &present
lldpenable: enabled
mdnstatus: rxOnly
ifname: 10GE1/0/1
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get mdnInterface config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<lldp xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<mdnInterfaces>
<mdnInterface>
<ifName>10GE1/0/1</ifName>
<mdnStatus></mdnStatus>
</mdnInterface>
</mdnInterfaces>
</lldp>
</filter>"
register: result_xml
- name: Get lldp enabled config by ce_netconf.
ce_netconf: &get_config_lldp
rpc: get
cfg_xml: "<filter type=\"subtree\">
<lldp xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<lldpSys>
<lldpEnable></lldpEnable>
</lldpSys>
</lldp>
/filter>"
register: result_xml_lldp
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_mdn_interface: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<mdnStatus>rxOnly</mdnStatus>' in result_xml.end_state.result"
- "'<lldpEnable>enabled</lldpEnable>' in result_xml_lldp.end_state.result"
- name: absent the provided configuration with the exisiting running configuration
ce_mdn_interface: &absent
lldpenable: disabled
mdnstatus: disabled
ifname: 10GE1/0/1
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: absent the provided configuration with the existing running configuration (REPEAT)
ce_mdn_interface: *absent
register: repeat
- name: Get mdnInterface config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Get lldp enabled config by ce_netconf.
ce_netconf: *get_config
register: result_xml_lldp
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
- "'<mdnStatus>disabled</mdnStatus>' not in result_xml.end_state.result"
- "'<lldpEnable>disabled</lldpEnable>' in result_xml_lldp.end_state.result"
# after present, isis 100 should be deleted
- debug:
msg: "END ce_mdn_interface resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,73 +0,0 @@
---
- debug:
msg: "START ce_multicast_global presented integration tests on connection={{ ansible_connection }}"
- name: present the provided configuration with the exisiting running configuration
ce_multicast_global: &present
aftype: v4
vrf: vpna
weight: 100
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<mcastbase xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<mcastAfsEnables>
<mcastAfsEnable>
<vrfName></vrfName>
<addressFamily></addressFamily>
</mcastAfsEnable>
</mcastAfsEnables>
</mcastbase>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_multicast_global: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<vrfName>vpna</vrfName>' in result_xml.end_state.result"
- "'<addressFamily>vpna</addressFamily>' in result_xml.end_state.result"
- name: present the provided configuration with the exisiting running configuration
ce_multicast_global: &absent
aftype: v4
vrf: vpna
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_multicast_global: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<vrfName>vpna</vrfName>' not in result_xml.end_state.result"
- "'<addressFamily>vpna</addressFamily>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- debug:
msg: "END ce_multicast_global resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,95 +0,0 @@
---
- debug:
msg: "START ce_multicast_igmp_enable presented integration tests on connection={{ ansible_connection }}"
# clean up before test
- name: clean up configuration with the exisiting running configuration
ce_multicast_igmp_enable: &absent
aftype: v4
features: vlan
vlan_id: 100
igmp: true
version: 2
proxy: true
- name: present the provided configuration with the exisiting running configuration
ce_multicast_igmp_enable: &present
aftype: v4
features: vlan
vlan_id: 100
igmp: true
version: 2
proxy: true
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: Get basic config by ce_netconf.
ce_netconf: &get_config
rpc: get
cfg_xml: "<filter type=\"subtree\">
<l2mc xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<vlan>
<l2McVlanCfgs>
<l2McVlanCfg>
<addrFamily></addrFamily>
<vlanId></vlanId>
<snoopingEnable></snoopingEnable>
<version></version>
<proxyEnable></proxyEnable>
</l2McVlanCfg>
</l2McVlanCfgs>
</vlan>
</l2mc>
</filter>"
register: result_xml
- name: present the provided configuration with the existing running configuration (IDEMPOTENT)
ce_multicast_igmp_enable: *present
register: repeat
- name: Assert that the previous task was idempotent
assert:
that:
- "repeat.changed == false"
- "'<addrFamily>ipv4unicast</addrFamily>' in result_xml.end_state.result"
- "'<vlanId>100</vlanId>' in result_xml.end_state.result"
- "'<snoopingEnable>true</snoopingEnable>' in result_xml.end_state.result"
- "'<version>2</version>' in result_xml.end_state.result"
- "'<proxyEnable>true</proxyEnable>' in result_xml.end_state.result"
- name: absent the provided configuration with the exisiting running configuration
ce_multicast_igmp_enable: *absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: absent the provided configuration with the existing running configuration (REPEAT)
ce_multicast_igmp_enable: *absent
register: repeat
- name: Get basic config by ce_netconf.
ce_netconf: *get_config
register: result_xml
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
- "'<addrFamily>ipv4unicast</addrFamily>' not in result_xml.end_state.result"
- "'<vlanId>100</vlanId>' not in result_xml.end_state.result"
- "'<snoopingEnable>true</snoopingEnable>' not in result_xml.end_state.result"
- "'<version>2</version>' not in result_xml.end_state.result"
- "'<proxyEnable>true</proxyEnable>' not in result_xml.end_state.result"
# after present, isis 100 should be deleted
- debug:
msg: "END ce_multicast_igmp_enable resentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,3 +0,0 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -1,2 +0,0 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -1,17 +0,0 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,150 +0,0 @@
---
- debug:
msg: "START ce_static_route_bfd presented integration tests on connection={{ ansible_connection }}"
- include_tasks: cleanup.yaml
- name: Config an ip route-static bfd 10GE1/0/1 3.3.3.3 min-rx-interval 50 min-tx-interval 50 detect-multiplier 5
ce_static_route_bfd: &merge1
function_flag: 'singleBFD'
nhp_interface: 10GE1/0/1
next_hop: 3.3.3.3
min_tx_interval: 50
min_rx_interval: 50
detect_multiplier: 5
aftype: v4
state: present
register: result1
- name: (repeat)Config an ip route-static bfd 10GE1/0/1 3.3.3.3 min-rx-interval 50 min-tx-interval 50 detect-multiplier 5
ce_static_route_bfd:
<<: *merge1
register: result2
- name: Assert the configuration is reflected on host
assert:
that:
- "result1['changed'] == true"
- "result2['changed'] == false"
# ip route-static bfd [ interface-type interface-number | vpn-instance vpn-instance-name ] nexthop-address
- name: ip route-static bfd 10GE1/0/1 3.3.3.4
ce_static_route_bfd: &merge2
function_flag: 'singleBFD'
nhp_interface: 10GE1/0/1
next_hop: 3.3.3.4
aftype: v4
register: result1
- name: (repeat)ip route-static bfd 10GE1/0/1 3.3.3.4
ce_static_route_bfd:
<<: *merge2
register: result2
- name: Assert the configuration is reflected on host
assert:
that:
- "result1['changed'] == true"
- "result2['changed'] == false"
#ip route-static default-bfd { min-rx-interval {min-rx-interval} | min-tx-interval {min-tx-interval} | detect-multiplier {multiplier}}
- name: Config an ip route-static default-bfd min-rx-interval 50 min-tx-interval 50 detect-multiplier 6
ce_static_route_bfd: &merge3
function_flag: 'globalBFD'
min_tx_interval: 50
min_rx_interval: 50
detect_multiplier: 6
aftype: v4
state: present
register: result1
- name: (repeat)Config an ip route-static default-bfd min-rx-interval 50 min-tx-interval 50 detect-multiplier 6
ce_static_route_bfd:
<<: *merge3
register: result2
- name: Assert the configuration is reflected on host
assert:
that:
- "result1['changed'] == true"
- "result2['changed'] == false"
- name: undo ip route-static default-bfd
ce_static_route_bfd: &merge4
function_flag: 'globalBFD'
aftype: v4
state: absent
commands: 'sys,undo ip route-static default-bfd,commit'
register: result1
- name: (repeat)undo ip route-static default-bfd
ce_static_route_bfd:
<<: *merge4
register: result2
- name: Assert the configuration is reflected on host
assert:
that:
- "result1['changed'] == true"
- "result2['changed'] == false"
- name: Config an ipv4 static route 2.2.2.0/24 2.2.2.1 preference 1 tag 2 description test for staticBFD
ce_static_route_bfd: &merge5
function_flag: 'staticBFD'
prefix: 2.2.2.2
mask: 24
next_hop: 2.2.2.1
tag: 2
description: test
pref: 1
aftype: v4
bfd_session_name: btoa
state: present
register: result1
- name: (repeat) Config an ipv4 static route 2.2.2.0/24 2.2.2.1 preference 1 tag 2 description test for staticBFD
ce_static_route_bfd:
<<: *merge5
register: result2
- name: Assert the configuration is reflected on host
assert:
that:
- "result1['changed'] == true"
- "result2['changed'] == false"
- name: Get lacp config by ce_netconf.
ce_netconf:
rpc: get
cfg_xml: "<get>
<filter type=\"subtree\">
<staticrt xmlns=\"http://www.huawei.com/netconf/vrp\" content-version=\"1.0\" format-version=\"1.0\">
<staticrtbase>
<srBfdParas>
<srBfdPara>
<afType/>
<ifName/>
<destVrfName/>
<nexthop/>
<localAddress/>
<minTxInterval/>
<minRxInterval/>
<multiplier/>
</srBfdPara>
</srBfdParas>
</staticrtbase>
</staticrt>
</filter>
</get>"
register: result_present
- name: Assert that the previous task was idempotent
assert:
that:
- "'<afType>v4</afType>' == result_present.end_state.result"
- "'<ifName>10GE1/0/1</ifName>' == result_present.end_state.result"
- "'<rcvTimeoutType>Fast</rcvTimeoutType>' == result_present.end_state.result"
- "'<destVrfName>__publiv__</destVrfName>' == result_present.end_state.result"
- "'<selectPortStd>Prority</selectPortStd>' == result_present.end_state.result"
- "'<nexthop>2.2.2.1</nexthop>' == result_present.end_state.result"
- "'<localAddress>2.2.2.2</localAddress>' == result_present.end_state.result"
- "'<minTxInterval>12</minTxInterval>' in result_present.end_state.result"
- "'<mixRateEnable>true</mixRateEnable>' in result_present.end_state.result"
- "'<multiplier>true</multiplier>' in result_present.end_state.result"
- "'<dampUnexpMacEn>true</dampUnexpMacEn>' in result_present.end_state.result"
- "'<trunkSysMac>true</trunkSysMac>' in result_present.end_state.result"
- "'<trunkPortIdExt>true</trunkPortIdExt>' in result_present.end_state.result"
- "'<lacpMlagSysId>1111-2222-3333</lacpMlagSysId>' in result_present.end_state.result"
- "'<priority>123</priority>' in result_present.end_state.result"
- include_tasks: cleanup.yaml
- debug:
msg: "END ce_static_route_bfd presentd integration tests on connection={{ ansible_connection }}"

View file

@ -1,31 +0,0 @@
---
- name: Merge the provided configuration with the exisiting running configuration
ce_static_route_bfd:
function_flag: 'singleBFD'
nhp_interface: 10GE1/0/1
next_hop: 3.3.3.3
min_tx_interval: 50
min_rx_interval: 50
detect_multiplier: 5
aftype: v4
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"
- name: ip route-static bfd 10GE1/0/1 3.3.3.4
ce_static_route_bfd: &merge
function_flag: 'globalBFD'
min_tx_interval: 50
min_rx_interval: 50
detect_multiplier: 6
aftype: v4
state: absent
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "result['changed'] == true"

View file

@ -1,115 +0,0 @@
# Ansible Role: cnos_backup_sample - Saving the switch configuration to a remote server
---
<add role description below>
This role is an example of using the *cnos_backup.py* Lenovo module in the context of CNOS switch configuration. This module allows you to work with switch configurations. It provides a way to back up the running or startup configurations of a switch to a remote server. This is achieved by periodically saving a copy of the startup or running configuration of the network device to a remote server using FTP, SFTP, TFTP, or SCP.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_backup](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_backup.html&cp=0_3_1_0_4_4).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](http://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`ansible_connection` | Has to be `network_cli`
`ansible_network_os` | Has to be `cnos`
`ansible_ssh_user` | Specifies the username used to log into the switch
`ansible_ssh_pass` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296, **g8332_cnos** - G8332, **NE10032** - NE10032, **NE1072T** - NE1072T, **NE1032** - NE1032, **NE1032T** - NE1032T, **NE2572** - NE2572, **NE0152T** - NE0152T)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`configType` | Specifies the type of configuration to be backed up to the remote server (**running-config** - running configuration, **startup-config** - startup configuration)
`protocol` | Specifies the protocol used by the network device to interact with the remote server to where to upload the backup configuration (**ftp** - FTP, **sftp** - SFTP, **tftp** - TFTP, **scp** - SCP)
`serverip` | Specifies the IP Address of the remote server to where the configuration will be backed up
`rcpath` | Specifies the full file path where the configuration file will be copied on the remote server (when backing up the switch configuration through TFTP, an empty directory needs to be created, otherwise the operation will fail)
`serverusername` | Configures the username for the server relating to the protocol used
`serverpassword` | Configures the password for the server relating to the protocol used
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_backup.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_backup_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_backup_sample]
10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos
10.241.107.40 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_backup_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to back up configuration
hosts: cnos_backup_sample
gather_facts: no
connection: local
roles:
- cnos_backup_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

View file

@ -1,2 +0,0 @@
# No Lenovo Switch simulator yet, so not enabled
unsupported

View file

@ -1,17 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip Addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_backup_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_backup_sample]
10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos rcpath=/root/cnos_config/G8272-running-config.txt
#Use this in case its TFTP as tftpboot folder is the starting point for tftp
#10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos rcpath=/anil/G8272-running-config.txt

View file

@ -1,25 +0,0 @@
# This contain sample config back up tasks
---
- name: Test Startup Config Backup
cnos_backup: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_backup_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath='{{item.rcpath}}' serverusername='{{item.serverusername}}' serverpassword='{{item.serverpassword}}'
with_items: "{{test_config_data2}}"
- name: Test Running Config Backup
cnos_backup: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_backup_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath='{{item.rcpath}}' serverusername='{{item.serverusername}}' serverpassword='{{item.serverpassword}}'
with_items: "{{test_config_data1}}"
#Root folder will be different for SFTP/SCP and TFTP
#The following task is commented.
#Before trying this, please change in /etc/ansible/hosts file
#and backup the config file with reference to your tftp-root folder
#- name: Test Running Config Backup -TFTP
# cnos_backup: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_backup_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath='{{item.rcpath}}'
# with_items: "{{test_config_data3}}"
#- name: Test Startup Config Backup - TFTP
# cnos_backup: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_backup_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath='{{item.rcpath}}'
# with_items: "{{test_config_data4}}"
# Completed file

View file

@ -1,12 +0,0 @@
---
test_config_data1:
- {configType: "running-config", protocol: "sftp", serverip: "10.241.106.118", serverusername: "root", serverpassword: "root123", rcpath: "/root/cnos_config/"}
test_config_data2:
- {configType: "startup-config", protocol: "sftp", serverip: "10.241.106.118", serverusername: "root", serverpassword: "root123", rcpath: "/root/cnos_config/"}
test_config_data3:
- {configType: running-config, protocol: "tftp", serverip: "10.241.106.118", rcpath: "/root/cnos_config/"}
test_config_data4:
- {configType: startup-config, protocol: "tftp", serverip: "10.241.106.118", rcpath: "/root/cnos_config/"}

View file

@ -1,2 +0,0 @@
# No Lenovo Switch simulator yet, so not enabled
unsupported

View file

@ -1,14 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip Addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_banner_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_banner_sample]
10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password>

View file

@ -1,2 +0,0 @@
---
testcase: "*"

View file

@ -1,22 +0,0 @@
---
- name: collect all cli test cases
find:
paths: "{{ role_path }}/tests/cli"
patterns: "{{ testcase }}.yaml"
register: test_cases
delegate_to: localhost
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test cases (connection=network_cli)
include: "{{ test_case_to_run }}"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run
- name: run test case (connection=local)
include: "{{ test_case_to_run }} ansible_connection=local"
with_first_found: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,2 +0,0 @@
---
- { include: cli.yaml, tags: ['cli'] }

View file

@ -1,43 +0,0 @@
---
- name: setup - remove login
cnos_banner:
banner: login
state: absent
provider: "{{ cli }}"
- name: Set login
cnos_banner:
banner: login
text: |
this is my login banner
that has a multiline
string
state: present
provider: "{{ cli }}"
register: result
- debug:
msg: "{{ result }}"
- assert:
that:
- "result.changed == true"
- name: Set login again (idempotent)
cnos_banner:
banner: login
text: |
this is my login banner
that has a multiline
string
state: present
provider: "{{ cli }}"
register: result
- assert:
that:
- "result.changed == false"
- "result.commands | length == 0"

View file

@ -1,45 +0,0 @@
---
- name: setup - remove motd
cnos_banner:
banner: motd
state: absent
provider: "{{ cli }}"
- name: Set motd
cnos_banner:
banner: motd
text: |
this is my motd banner
that has a multiline
string
state: present
provider: "{{ cli }}"
register: result
- debug:
msg: "{{ result }}"
- assert:
that:
- "result.changed == true"
# - "'banner motd @\nthis is my motd banner\nthat has a multiline\nstring\n@' in result.commands"
- name: Set motd again (idempotent)
cnos_banner:
banner: motd
text: |
this is my motd banner
that has a multiline
string
state: present
provider: "{{ cli }}"
register: result
- assert:
that:
- "result.changed == false"
- "result.commands | length == 0"

View file

@ -1,36 +0,0 @@
---
- name: Setup
cnos_banner:
banner: login
text: |
Junk login banner
over multiple lines
state: present
provider: "{{ cli }}"
- name: remove login
cnos_banner:
banner: login
state: absent
provider: "{{ cli }}"
register: result
- debug:
msg: "{{ result }}"
- assert:
that:
- "result.changed == true"
- "'no banner login' in result.commands" # does this break due to "contains?"
- name: remove login (idempotent)
cnos_banner:
banner: login
state: absent
provider: "{{ cli }}"
register: result
- assert:
that:
- "result.changed == false"
- "result.commands | length == 0"

View file

@ -1,9 +0,0 @@
---
cli:
host: "{{ inventory_hostname }}"
port: 22
username: admin
password: admin
timeout: 30
authorize: True
auth_pass:

View file

@ -1,119 +0,0 @@
# Ansible Role: cnos_bgp_sample - CNOS Switch BGP Configuration
---
<add role description below>
This role is an example of using the *cnos_bgp.py* Lenovo module in the context of CNOS switch configuration. This module allows you to work with Border Gateway Protocol (BGP) related configurations. The operators used are overloaded to ensure control over switch BGP configurations. This module is invoked using method with *asNumber* as one of its arguments.
The first level of the BGP configuration allows to set up an AS number, with the following attributes going into various configuration operations under the context of BGP. After passing this level, there are eight BGP arguments that will perform further configurations. They are *bgpArg1*, *bgpArg2*, *bgpArg3*, *bgpArg4*, *bgpArg5*, *bgpArg6*, *bgpArg7*, and *bgpArg8*.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_bgp](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_bgp.html&cp=0_3_1_0_4_16).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](http://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`ansible_connection` | Has to be `network_cli`
`ansible_network_os` | Has to be `cnos`
`ansible_ssh_user` | Specifies the username used to log into the switch
`ansible_ssh_pass` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296, **g8332_cnos** - G8332, **NE10032** - NE10032, **NE1072T** - NE1072T, **NE1032** - NE1032, **NE1032T** - NE1032T, **NE2572** - NE2572, **NE0152T** - NE0152T)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`asNum` | Specifies the AS number
`bgpArg1` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **address-family**, **bestpath**, **bgp**, **cluster-id**, **confederation**, **enforce-first-as**, **fast-external-failover**, **graceful-restart**, **graceful-restart-helper**, **log-neighbor-changes**, **maxas-limit**, **neighbor**, **router-id**, **shutdown**, **synchronization**, **timers**, **vrf**.
`bgpArg2` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **ipv4**, **ipv6**, **always-compare-med**, **compare-confed-aspath**, **compare-routerid**, **dont-compare-originator-id**, **tie-break-on-age**, **as-path**, **med**, number of times to prepend the local AS, Route Reflector Cluster ID as a 32 bit quantity or in IP address format, **identifier**, **peers**, delay value, number of autonomous systems in the AS-path attribute, neighbor address, neighbor prefix, manually configured router identifier, keepalive interval.
`bgpArg3` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **aggregate-address**, **client-to-client**, **dampening**, **distance**, **maximum-paths**, **network**, **nexthop**, **redistribute**, **save**, **synchronization**, **ignore**, **multipath-relax**, **confed**, **missing-as-worst**, **non-deterministic**, **remove-recv-med**, **remove-send-med**, set routing domain confederation AS, AS number.
`bgpArg4` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: IP address/prefix length, **route-map**, time after which a penalty is decreased by half, administrative distance to routes outside the AS, **ebgp**, **ibgp**, **synchronization**, IP address, delay value, **direct**, **ospf**, **static**, **memory**.
`bgpArg5` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **as-set**, **summary-only**, name of the route map that controls where BGP route dampening is enabled, value to start reusing a route, administrative distance to routes inside the AS, value for maximum path numbers, **backdoor**, **mask**, **route-map**.
`bgpArg6` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **summary-only**, **as-set**, value to start suppressing a route, administrative distance for local routes, IP subnet address mask, name of the route map.
`bgpArg7` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: maximum duration to suppress a stable route, **route-map**, **backdoor**.
'bgpArg8' | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: time after which an unreachable route's penalty is decreased by half, **backdoor**.
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_bgp.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_bgp_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_bgp_sample]
10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos
10.241.107.40 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_bgp_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do BGP configuration
hosts: cnos_bgp_sample
gather_facts: no
connection: local
roles:
- cnos_bgp_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

View file

@ -1,2 +0,0 @@
# No Lenovo Switch simulator yet, so not enabled
unsupported

View file

@ -1,14 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip Addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_bgp_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_bgp_sample]
10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos

View file

@ -1,78 +0,0 @@
## This contain sample BGP execution tasks
---
- name: Test BGP - neighbor
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}' bgpArg4='{{item.bgpArg4}}' bgpArg5='{{item.bgpArg5}}' bgpArg6='{{item.bgpArg6}}'
with_items: "{{test_bgp_data13}}"
- name: Test BGP - BFD
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}' bgpArg4='{{item.bgpArg4}}'
with_items: "{{test_bgp_data19}}"
- name: Test BGP - address-family - dampening
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}' bgpArg4='{{item.bgpArg4}}' bgpArg5='{{item.bgpArg5}}' bgpArg6='{{item.bgpArg6}}' bgpArg7='{{item.bgpArg7}}' bgpArg8='{{item.bgpArg8}}'
with_items: "{{test_bgp_data1}}"
- name: Test BGP - address-family - network
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}' bgpArg4='{{item.bgpArg4}}' bgpArg5='{{item.bgpArg5}}'
with_items: "{{test_bgp_data18}}"
- name: Test BGP - bestpath - always-compare-med
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data2}}"
- name: Test BGP - bestpath-compare-confed-aspat
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data3}}"
- name: Test BGP - bgp
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data4}}"
- name: Test BGP - cluster-id
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data5}}"
- name: Test BGP - confederation-identifier
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}'
with_items: "{{test_bgp_data6}}"
- name: Test BGP - enforce-first-as
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data7}}"
- name: Test BGP - fast-external-failover
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data8}}"
- name: Test BGP - graceful-restart
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data9}}"
- name: Test BGP - graceful-restart-helper
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data10}}"
- name: Test BGP - maxas-limit
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data11}}"
#- name: Test BGP - neighbor
# cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}'
# with_items: "{{test_bgp_data13}}"
- name: Test BGP - router-id
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data14}}"
- name: Test BGP - synchronization
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data15}}"
- name: Test BGP - timers
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}'
with_items: "{{test_bgp_data16}}"
- name: Test BGP - vrf
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data17}}"
# Completed file

View file

@ -1,37 +0,0 @@
---
test_bgp_data1:
- {asNum: 33, bgpArg1: "address-family", bgpArg2: "ipv4", bgpArg3: "dampening", bgpArg4: 13, bgpArg5: 233, bgpArg6: 333, bgpArg7: 15, bgpArg8: 33 }
test_bgp_data2:
- {asNum: 33, bgpArg1: "bestpath", bgpArg2: "always-compare-med"}
test_bgp_data3:
- {asNum: 33, bgpArg1: "bestpath", bgpArg2: "compare-confed-aspath"}
test_bgp_data4:
- {asNum: 33, bgpArg1: "bgp", bgpArg2: 33}
test_bgp_data5:
- {asNum: 33, bgpArg1: "cluster-id", bgpArg2: "1.2.3.4"}
test_bgp_data6:
- {asNum: 33, bgpArg1: "confederation", bgpArg2: "identifier", bgpArg3: 333}
test_bgp_data7:
- {asNum: 33, bgpArg1: "enforce-first-as"}
test_bgp_data8:
- {asNum: 33, bgpArg1: "fast-external-failover"}
test_bgp_data9:
- {asNum: 33, bgpArg1: "graceful-restart", bgpArg2: 333}
test_bgp_data10:
- {asNum: 33, bgpArg1: "graceful-restart-helper"}
test_bgp_data11:
- {asNum: 33, bgpArg1: "maxas-limit", bgpArg2: 333}
test_bgp_data13:
- {asNum: 33, bgpArg1: "neighbor", bgpArg2: "10.241.107.40", bgpArg3: 13, bgpArg4: "address-family", bgpArg5: "ipv4", bgpArg6: "next-hop-self" }
test_bgp_data14:
- {asNum: 33, bgpArg1: "router-id", bgpArg2: "1.2.3.4"}
test_bgp_data15:
- {asNum: 33, bgpArg1: "synchronization"}
test_bgp_data16:
- {asNum: 33, bgpArg1: "timers", bgpArg2: 333, bgpArg3: 3333}
test_bgp_data17:
- {asNum: 33, bgpArg1: "vrf"}
test_bgp_data18:
- {asNum: 33, bgpArg1: "address-family", bgpArg2: "ipv4", bgpArg3: "network", bgpArg4: "1.2.3.4/5", bgpArg5: "backdoor"}
test_bgp_data19:
- {asNum: 33, bgpArg1: "neighbor", bgpArg2: "10.241.107.40", bgpArg3: 13, bgpArg4: "bfd"}

View file

@ -1,115 +0,0 @@
# Ansible Role: cnos_command - Executes any CLI command on switch and results are displayed.
---
<add role description below>
Sends arbitrary commands to an CNOS node and returns the results
read from the device. The C(cnos_command) module includes an
argument that will cause the module to wait for a specific condition
before returning or timing out if the condition is not met.
## Requirements
---
<add role requirements information below>
- Ansible version 2.6 or later ([Ansible installation documentation](http://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`ansible_connection` | Has to be `network_cli`
`ansible_network_os` | Has to be `cnos`
`ansible_ssh_user` | Specifies the username used to log into the switch
`ansible_ssh_pass` | Specifies the password used to log into the switch
These are the various options the customer have in executing the cnos_command modules:
Variable | Description
--- | ---
`commands` | List of commands to send to the remote device. The resulting output from the command is returned. If the I(wait_for) argument is provided, the module is not returned until the condition is satisfied or the number of retires as expired.
`wait_for` | List of conditions to evaluate against the output of the command. The task will wait for each condition to be true before moving forward. If the conditional is not true within the configured number of retries, the task fails. See examples.
`match` | The I(match) argument is used in conjunction with the I(wait_for) argument to specify the match policy. Valid values are C(all) or C(any). If the value is set to C(all) then all conditionals in the wait_for must be satisfied. If the value is set to C(any) then only one of the values must be satisfied.
`retries` | Specifies the number of retries a command should by tried before it is considered failed. The command is run on the target device every retry and evaluated against the I(wait_for) conditions.
`interval` | Configures the interval in seconds to wait between retries of the command. If the command does not pass the specified conditions, the interval indicates how long to wait before trying the command again.
Need to specify these variables in vars/main.yml under variable `cli`
Variable | Description
--- | ---
`host` | Has to be "{{ inventory_hostname }}"
`port` | Has to be`22`
`username` | User Name of switch
`password` | Password of switch
`timeout` | time out value for CLI
`authorize` | Whether u have to enter enable mode for data collection.
`auth_pass`| Enable Password if required
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_command.py - This module file will be located at lib/ansible/modules/network/cnos/ of Ansible installation.
- cnos.py - This module util file will be located at lib/ansible/module_utils/network/cnos of Ansible installation.
- cnos.py - This module plugin file will be located at lib/ansible/plugins/action of Ansible installation.
- cnos.py - This module plugin file will be located at lib/ansible/plugins/cliconf of Ansible installation.
- cnos.py - This module plugin file will be located at lib/ansible/plugins/cliconf of Ansible installation.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_command_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_command]
10.241.107.39 ansible_connection=network_cli ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password>
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_command_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do some CLI Command configurations
hosts: cnos_command
gather_facts: no
connection: network_cli
roles:
- cnos_command
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, eithe
r version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PU
RPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

View file

@ -1,2 +0,0 @@
# No Lenovo Switch simulator yet, so not enabled
unsupported

View file

@ -1,14 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip Addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_command_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_command_sample]
10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos

View file

@ -1,3 +0,0 @@
---
testcase: "*"
test_items: []

View file

@ -1,15 +0,0 @@
---
- name: collect all cli test cases
find:
paths: "{{ role_path }}/tests/cli"
patterns: "{{ testcase }}.yaml"
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case
include: "{{ test_case_to_run }}"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -1,2 +0,0 @@
---
- { include: cli.yaml, tags: ['cli'] }

View file

@ -1,19 +0,0 @@
---
- debug: msg="START cli/bad_operator.yaml"
- name: test bad operator
cnos_command:
commands:
- display version
- display interface brief
wait_for:
- result[0] contains 'Description: Foo'
register: result
ignore_errors: yes
- assert:
that:
- "result.failed == true"
- "result.msg is defined"
- debug: msg="END cli/bad_operator.yaml"

View file

@ -1,19 +0,0 @@
---
- debug: msg="START cli/contains.yaml"
- name: test contains operator
cnos_command:
commands:
- display version
- display process memory
wait_for:
- "result[0] contains 'Lenovo'"
- "result[1] contains 'Mem:'"
register: result
- assert:
that:
- "result.changed == false"
- "result.stdout is defined"
- debug: msg="END cli/contains.yaml"

View file

@ -1,27 +0,0 @@
---
- debug: msg="START cli/invalid.yaml"
- name: run invalid command
cnos_command:
commands: ['display foo']
register: result
ignore_errors: yes
- assert:
that:
- "result.failed"
- name: run commands that include invalid command
cnos_command:
commands:
- display version
- display foo
register: result
ignore_errors: yes
- assert:
that:
- "result.failed"
ignore_errors: true
- debug: msg="END cli/invalid.yaml"

View file

@ -1,27 +0,0 @@
---
- debug: msg="START cli/output.yaml"
- name: get output for single command
cnos_command:
commands: ['display version']
register: result
- assert:
that:
- "result.changed == false"
- "result.stdout is defined"
- name: get output for multiple commands
cnos_command:
commands:
- display version
- display interface brief
register: result
- assert:
that:
- "result.changed == false"
- "result.stdout is defined"
- "result.stdout | length == 2"
- debug: msg="END cli/output.yaml"

View file

@ -1,18 +0,0 @@
---
- debug: msg="START cli/timeout.yaml"
- name: test bad condition
cnos_command:
commands:
- display version
wait_for:
- "result[0] contains bad_value_string"
register: result
ignore_errors: yes
- assert:
that:
- "result.failed == true"
- "result.msg is defined"
- debug: msg="END cli/timeout.yaml"

View file

@ -1,120 +0,0 @@
# Ansible Role: cnos_conditional_command_sample - Executing a single CNOS command with respect to conditions specified in the inventory
---
<add role description below>
This role is an example of using the *cnos_conditional_command.py* Lenovo module in the context of CNOS switch configuration. This module allows you to modify the running configuration of a switch. It provides a way to execute a single CNOS command on a network device by evaluating the current running configuration and executing the command only if the specific settings have not been already configured.
The CNOS command is passed as an argument of the method.
This module functions the same as the *cnos_command.py* module. The only exception is that the following inventory variable can be specified: condition = &lt;flag string&gt;
When this inventory variable is specified as the variable of a task, the command is executed for the network element that matches the flag string.
Usually, commands are executed across a group of network devices. When there is a requirement to skip the execution of the command on one or more devices, it is recommended to use this module.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_conditional_command](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_conditional_command.html&cp=0_3_1_0_4_9).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](http://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`ansible_connection` | Has to be `network_cli`
`ansible_network_os` | Has to be `cnos`
`ansible_ssh_user` | Specifies the username used to log into the switch
`ansible_ssh_pass` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296, **g8332_cnos** - G8332, **NE10032** - NE10032, **NE1072T** - NE1072T, **NE1032** - NE1032, **NE1032T** - NE1032T, **NE2572** - NE2572, **NE0152T** - NE0152T)
`condition` | If `condition=false` is specified in the inventory file against any device, the command execution is skipped for that device (**true**, **false**)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`flag` | If a task needs to be executed, the flag needs to be set the same as it is specified in the inventory for that device
`clicommand` | Specifies the CLI command as an attribute to this method
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_conditional_command.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_conditional_command_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_conditional_command_sample]
10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos condition=pass
10.241.107.40 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_conditional_command_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do some configurations
hosts: cnos_conditional_command_sample
gather_facts: no
connection: local
roles:
- cnos_conditional_command_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

View file

@ -1,2 +0,0 @@
# No Lenovo Switch simulator yet, so not enabled
unsupported

View file

@ -1,14 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip Addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_conditional_command_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_conditional_command_sample]
10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos

View file

@ -1,7 +0,0 @@
# This contain sample command execution tasks
---
- name: Run a command
cnos_conditional_command: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['ansible_ssh_user']}} password={{ hostvars[inventory_hostname]['ansible_ssh_pass']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} condition={{ hostvars[inventory_hostname]['condition'] }} flag='{{item.flag}}' clicommand='{{item.clicommand}}' outputfile=./results/cnos_conditional_command_{{ inventory_hostname }}_output.txt
with_items: "{{conditional_command_data1}}"
# Completed file

View file

@ -1,3 +0,0 @@
---
conditional_command_data1:
- {flag: "pass", clicommand: "display users"}

View file

@ -1,120 +0,0 @@
# Ansible Role: cnos_conditional_template_sample - Manages switch configuration using templates with respect to conditions specified in the inventory
---
<add role description below>
This role is an example of using the *cnos_conditional_template.py* Lenovo module in the context of CNOS switch configuration. This module allows you to work with the running configuration of a switch. It provides a way to execute a set of CNOS commands on a switch by evaluating the current running configuration and executing the commands only if the specific settings have not been already configured.
The configuration source can be a set of commands or a template written in the Jinja2 templating language.
This module functions the same as the *cnos_template.py* module. The only exception is that the following inventory variable can be specified: condition = &lt;flag string&gt;
When this inventory variable is specified as the variable of a task, the template is executed for the network element that matches the flag string.
Usually, templates are used when commands are the same across a group of network devices. When there is a requirement to skip the execution of the template on one or more devices, it is recommended to use this module.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_conditional_template](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_conditional_template.html&cp=0_3_1_0_4_11).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](http://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`ansible_connection` | Has to be `network_cli`
`ansible_network_os` | Has to be `cnos`
`ansible_ssh_user` | Specifies the username used to log into the switch
`ansible_ssh_pass` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296, **g8332_cnos** - G8332, **NE10032** - NE10032, **NE1072T** - NE1072T, **NE1032** - NE1032, **NE1032T** - NE1032T, **NE2572** - NE2572, **NE0152T** - NE0152T)
`condition` | If `condition=<flag string>` is specified in the inventory file against any device, the template execution is done for that device in case it matches the flag setting for that task
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`flag` | If a task needs to be executed, you have to set the flag the same as it is specified in the inventory for that device
`commandfile` | Specifies the path to the CNOS command file which needs to be applied
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_conditional_template.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_conditional_template_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_conditional_template_sample]
10.241.107.39 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos condition=pass
10.241.107.40 ansible_network_os=cnos ansible_ssh_user=<username> ansible_ssh_pass=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_conditional_template_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do some template configurations
hosts: cnos_conditional_template_sample
gather_facts: no
connection: local
roles:
- cnos_conditional_template_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

View file

@ -1,2 +0,0 @@
# No Lenovo Switch simulator yet, so not enabled
unsupported

Some files were not shown because too many files have changed in this diff Show more