diff --git a/geant/gap_ansible/roles/iptrunk_checks/tasks/check_optical_levels.yaml b/geant/gap_ansible/roles/iptrunk_checks/tasks/check_optical_levels.yaml index 2c1deecad63c693740a2bce89ef7c7f63aa4c8f2..f5d65a81d83f9098328c5f0cd88fba756f991a26 100644 --- a/geant/gap_ansible/roles/iptrunk_checks/tasks/check_optical_levels.yaml +++ b/geant/gap_ansible/roles/iptrunk_checks/tasks/check_optical_levels.yaml @@ -1,32 +1,46 @@ --- -############################################################################################################### -# The playbook does the following: -# -# -# - Runs the command 'show interfaces diagnostics optics {{ interface }} | no-more' and gets the json output -# - From json output it retrieves the apporpriate metrics for optical levels -# - Saves the metrics in relevant variable names -############################################################################################################### - - name: Get Junos attributes for optical levels of interface "{{ item }}" when: local_side.iptrunk_side_node.vendor == "juniper" block: - name: Run Juniper Optical info junipernetworks.junos.junos_command: - commands: "show interfaces diagnostics optics {{ item.interface_name }} | no-more" - # display: json + commands: + - "show interfaces diagnostics optics {{ ae_member.interface_name }}" + display: json register: optical_status - - name: Show optical levels on Juniper interface "{{ item.interface_name }}" - ansible.builtin.debug: - msg: "{{ optical_status }}" + - name: Set variable for lanes + ansible.builtin.set_fact: + lanes: "{{ lanes | default([]) }}" + + - name: Populate the lanes data for "{{ ae_member.interface_name }}" + no_log: "{{ my_nolog }}" + ansible.builtin.set_fact: + lanes: "{{ lanes + [{'lane_id': iface_opt_lane['lane-index'][0]['data'], 'laser_current': iface_opt_lane['laser-bias-current'][0]['data'], 'laser_tx_mw': iface_opt_lane['laser-output-power'][0]['data'], 'laser_tx_dbm': iface_opt_lane['laser-output-power-dbm'][0]['data'], 'laser_rx_mw': iface_opt_lane['laser-rx-optical-power'][0]['data'], 'laser_rx_dbm': iface_opt_lane['laser-rx-optical-power-dbm'][0]['data']}] }}" + + vars: + obj: "{{ optical_status.stdout_lines[0]['interface-information'][0]['physical-interface'][0]['optics-diagnostics'][0] }}" + loop: "{{ obj['optics-diagnostics-lane-values'] }}" + loop_control: + loop_var: iface_opt_lane + + - name: Set variable for the PHY interface + no_log: "{{ my_nolog }}" + ansible.builtin.set_fact: + ae_result: "{{ ae_result | combine({item.key: item.value}) }}" + with_items: + - { key: "{{ ae_member.interface_name }}", value: "{{ lanes }}" } + + - name: Empty lanes variable for the next cycle + ansible.builtin.set_fact: + lanes: [] -- name: Get Nokia optical levels on port "{{ item.interface_name }}" +- name: Get Nokia optical levels on port "{{ ae_member.interface_name }}" when: local_side.iptrunk_side_node.vendor == "nokia" block: - name: Prepare the connector var ansible.builtin.set_fact: - connector: "{{ item.interface_name | regex_search('[1-9]/[1-9]/c[1-9]+') }}" + connector: "{{ ae_member.interface_name | regex_search('[1-9]/[1-9]/c[1-9]+') }}" - name: Run Nokia show command ansible.netcommon.netconf_rpc: @@ -35,13 +49,26 @@ content: | <global-operations xmlns="urn:nokia.com:sros:ns:yang:sr:oper-global"> <md-cli-raw-command> - <md-cli-input-line>show port {{ connector }} optical</md-cli-input-line> + <md-cli-input-line>show port {{ connector }} optical</md-cli-input-line> </md-cli-raw-command> </global-operations> display: json - register: output + register: out + + - name: Parse SROS port optical output + ansible.utils.cli_parse: + text: "{{out.output['rpc-reply']['nokiaoper:results']['nokiaoper:md-cli-output-block'].split('\n')}}" + parser: + name: ansible.netcommon.native + template_path: "{{ role_path }}/templates/sros_show_port_optical.yaml" + set_fact: lanes - - name: Show optical levels on Nokia port "{{ item.interface_name }}" - ansible.builtin.debug: - # msg: "{{ output }}" - msg: "{{out.output['rpc-reply']['nokiaoper:results']['nokiaoper:md-cli-output-block'].split('\n')}}" + - name: Set variable for the PHY interface + ansible.builtin.set_fact: + ae_result: "{{ ae_result | combine({item.key: item.value}) }}" + with_items: + - { key: "{{ ae_member.interface_name }}", value: "{{ lanes }}" } + + - name: Empty lanes variable for the next cycle + ansible.builtin.set_fact: + lanes: [] diff --git a/geant/gap_ansible/roles/iptrunk_checks/tasks/check_trunk_interface.yaml b/geant/gap_ansible/roles/iptrunk_checks/tasks/check_trunk_interface.yaml index 7b62fd3cfe1fd0cdefc3caba68cf6da87bcb2828..25bf3e4121e28cb75757117aed6ad7b32105c853 100644 --- a/geant/gap_ansible/roles/iptrunk_checks/tasks/check_trunk_interface.yaml +++ b/geant/gap_ansible/roles/iptrunk_checks/tasks/check_trunk_interface.yaml @@ -10,14 +10,23 @@ ansible.builtin.debug: var: response.stdout_lines - - name: Ping "{{ remote_side.iptrunk_side_node.router_fqdn }} on {{ side_b_ipv4_address.split('/')[0] }}" + - name: Rapid ping of {{ side_b_ipv4_address.split('/')[0] }}" junipernetworks.junos.junos_command: - commands: "ping {{ side_b_ipv4_address.split('/')[0] }} rapid size {{ ping_size }} count {{ ping_count }}" + commands: "ping {{ side_b_ipv4_address.split('/')[0] }} rapid size {{ rapid_ping_size }} count {{ rapid_ping_count }}" register: response - - name: Show ping resulst + - name: Show rapid ping resulst ansible.builtin.debug: - msg: "{{ response }}" + var: response.stdout_lines[0] + + - name: MTU ping of {{ side_b_ipv4_address.split('/')[0] }}" + junipernetworks.junos.junos_command: + commands: "ping {{ side_b_ipv4_address.split('/')[0] }} size {{ mtu_ping_size }} count {{ mtu_ping_count }} do-not-fragment" + register: response + + - name: Show MTU ping resulst + ansible.builtin.debug: + var: response.stdout_lines[0] - name: Nokia LACP check when: local_side.iptrunk_side_node.vendor == "nokia" @@ -39,14 +48,31 @@ ansible.builtin.debug: msg: "{{out.output['rpc-reply']['nokiaoper:results']['nokiaoper:md-cli-output-block'].split('\n')}}" - - name: Ping "{{ remote_side.iptrunk_side_node.router_fqdn }} on {{ side_b_ipv4_address.split('/')[0] }}" + - name: Rapid ping "{{ remote_side.iptrunk_side_node.router_fqdn }} on {{ side_b_ipv4_address.split('/')[0] }}" + ansible.netcommon.netconf_rpc: + rpc: action + xmlns: "urn:ietf:params:xml:ns:yang:1" + content: | + <global-operations xmlns="urn:nokia.com:sros:ns:yang:sr:oper-global"> + <md-cli-raw-command> + <md-cli-input-line>//ping count {{ rapid_ping_count }} size {{ rapid_ping_size }} rapid {{ side_b_ipv4_address.split('/')[0] }}</md-cli-input-line> + </md-cli-raw-command> + </global-operations> + display: json + register: out + + - name: Show ping results + ansible.builtin.debug: + msg: "{{out.output['rpc-reply']['nokiaoper:results']['nokiaoper:md-cli-output-block'].split('\n')}}" + + - name: MTU ping "{{ remote_side.iptrunk_side_node.router_fqdn }} on {{ side_b_ipv4_address.split('/')[0] }}" ansible.netcommon.netconf_rpc: rpc: action xmlns: "urn:ietf:params:xml:ns:yang:1" content: | <global-operations xmlns="urn:nokia.com:sros:ns:yang:sr:oper-global"> <md-cli-raw-command> - <md-cli-input-line>//ping count {{ ping_count }} size {{ ping_size }} rapid {{ side_b_ipv4_address.split('/')[0] }}</md-cli-input-line> + <md-cli-input-line>//ping count {{ mtu_ping_count }} size {{ mtu_ping_size }} {{ side_b_ipv4_address.split('/')[0] }} do-not-fragment</md-cli-input-line> </md-cli-raw-command> </global-operations> display: json diff --git a/geant/gap_ansible/roles/iptrunk_checks/tasks/diff_optical_results.yaml b/geant/gap_ansible/roles/iptrunk_checks/tasks/diff_optical_results.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2b509ce4db0cb313bf042f23545dde36d72154ab --- /dev/null +++ b/geant/gap_ansible/roles/iptrunk_checks/tasks/diff_optical_results.yaml @@ -0,0 +1,27 @@ +--- +- name: Set the PRE file var name + ansible.builtin.set_fact: + pre_file_name: "{{ opt_checks_dir }}/PRE_{{ inventory_hostname }}.yaml" + +- name: Set the PRE file var name + ansible.builtin.set_fact: + post_file_name: "{{ opt_checks_dir }}/POST_{{ inventory_hostname }}.yaml" + +- name: Check if PRE file exists + ansible.builtin.stat: + path: "{{ pre_file_name }}" + register: pre_file_stat + +- name: Check if POST file exists + ansible.builtin.stat: + path: "{{ post_file_name }}" + register: post_file_stat + +- name: Compare PRE and POST + when: >- + pre_file_stat is defined + and + post_file_stat is defined + ansible.utils.fact_diff: + before: "{{ lookup('ansible.builtin.file', pre_file_name) }}" + after: "{{ lookup('ansible.builtin.file', post_file_name) }}" diff --git a/geant/gap_ansible/roles/iptrunk_checks/tasks/main.yml b/geant/gap_ansible/roles/iptrunk_checks/tasks/main.yml index cbd64af784887bdad24857f496eac423e367e648..5f0e90ccb2e56037cfd121f9a77927cb71ed28f2 100644 --- a/geant/gap_ansible/roles/iptrunk_checks/tasks/main.yml +++ b/geant/gap_ansible/roles/iptrunk_checks/tasks/main.yml @@ -3,7 +3,7 @@ - name: Print the usage ansible.builtin.debug: msg: - - "Allowed checks: 'ping', 'isis'" + - "Allowed checks: 'ping', 'isis', 'lacp', 'optical_pre', 'optical_post'" when: (check is not defined) or (check not in checks) - name: Fail if arguments are not correct @@ -15,12 +15,20 @@ dir: /opt/ansible_inventory/group_vars/routers - name: Load local info + when: >- + inventory_hostname == wfo_ip_trunk_json.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn + or + inventory_hostname == wfo_ip_trunk_json.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn ansible.builtin.set_fact: local_side: "{{ wfo_ip_trunk_json | community.general.json_query(query) }}" vars: query: "iptrunk.iptrunk_sides[?iptrunk_side_node.router_fqdn == '{{ inventory_hostname }}'] | [0]" - name: Load remote info + when: >- + inventory_hostname == wfo_ip_trunk_json.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn + or + inventory_hostname == wfo_ip_trunk_json.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn ansible.builtin.set_fact: remote_side: "{{ wfo_ip_trunk_json | community.general.json_query(query) }}" vars: @@ -28,15 +36,42 @@ - name: Set ansible_host to terminal server when router is offline ansible.builtin.set_fact: - ansible_host: "{{ wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_ts_address }}" - ansible_port: "{{ wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_ts_port }}" - when: - ( wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_access_via_ts | ansible.builtin.bool ) is true + ansible_host: "{{ local_side.iptrunk_side_node.router_site.site_ts_address }}" + ansible_port: "{{ local_side.iptrunk_side_node.router_ts_port }}" + when: >- + local_side is defined + and + local_side.iptrunk_side_node.router_access_via_ts | ansible.builtin.bool - name: Load netconf connection config + when: local_side is defined ansible.builtin.set_fact: - ansible_connection: "{{ netconf_access[wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_node.vendor].ansible_connection }}" - ansible_network_os: "{{ netconf_access[wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_node.vendor].ansible_network_os }}" + ansible_connection: "{{ netconf_access[local_side.iptrunk_side_node.vendor].ansible_connection }}" + ansible_network_os: "{{ netconf_access[local_side.iptrunk_side_node.vendor].ansible_network_os }}" + +- name: Set local_side var when new_node is passed to use in optical_post + when: >- + new_node is defined + and + inventory_hostname == new_node.router.router_fqdn + ansible.builtin.set_fact: + ansible_connection: "{{ netconf_access[new_node.router.vendor].ansible_connection }}" + ansible_network_os: "{{ netconf_access[new_node.router.vendor].ansible_network_os }}" + local_side: + iptrunk_side_ae_members: "{{ new_lag_member_interfaces }}" + iptrunk_side_node: + vendor: "{{ new_node.router.vendor }}" + +- name: Set ansible_host when new_node is targeted + when: >- + new_node is defined + and + inventory_hostname == new_node.router.router_fqdn + and + new_node.router.router_access_via_ts | ansible.builtin.bool + ansible.builtin.set_fact: + ansible_host: "{{ new_node.router.router_site.site_ts_address }}" + ansible_port: "{{ new_node.router.router_ts_port }}" - name: Check ISIS ansible.builtin.include_tasks: check_isis.yaml @@ -46,7 +81,64 @@ ansible.builtin.include_tasks: check_trunk_interface.yaml when: check == "ping" +- name: Set the optical checks results directory name + when: check == "optical_pre" or check == "optical_post" + ansible.builtin.set_fact: + opt_checks_dir: "/var/tmp/ansible_trunk_checks_{{ trunks[0].id }}" + +- name: Set the optical checks results file name for PRE + when: check == "optical_pre" + ansible.builtin.set_fact: + opt_checks_file: "{{ opt_checks_dir }}/PRE_{{ inventory_hostname }}.yaml" + +- name: Set the optical checks results file name for POST + when: check == "optical_post" + ansible.builtin.set_fact: + opt_checks_file: "{{ opt_checks_dir }}/POST_{{ inventory_hostname }}.yaml" + +- name: Create a folder for the optical check results + when: check == "optical_pre" or check == "optical_post" + ansible.builtin.file: + path: "{{ opt_checks_dir }}" + state: directory + mode: '0755' + delegate_to: localhost + +- name: Create file for the optical check results + when: check == "optical_pre" or check == "optical_post" + ansible.builtin.file: + path: "{{ opt_checks_file }}" + state: touch + mode: '0644' + delegate_to: localhost + +- name: Create var for the result storage + when: check == "optical_pre" or check == "optical_post" + ansible.builtin.set_fact: + ae_result: "{{ ae_result | default({}) }}" + - name: Check optical levels + when: check == "optical_pre" or check == "optical_post" ansible.builtin.include_tasks: check_optical_levels.yaml - when: check == "optical" loop: "{{ local_side.iptrunk_side_ae_members }}" + loop_control: + loop_var: ae_member + +- name: Write result to the "{{ opt_checks_file }}" file + when: check == "optical_pre" or check == "optical_post" + ansible.builtin.copy: + mode: '0644' + content: "{{ ae_result | to_nice_yaml }}" + dest: "{{ opt_checks_file }}" + +- name: Display "{{ check | upper }}" check results + when: check == "optical_pre" or check == "optical_post" + ansible.builtin.debug: + msg: "{{ ae_result }}" + +- name: Produce the diff of optical check results on the "remaining" side + when: >- + check == "optical_post" + and + inventory_hostname != new_node.router.router_fqdn + ansible.builtin.include_tasks: diff_optical_results.yaml diff --git a/geant/gap_ansible/roles/iptrunk_checks/templates/sros_show_port_optical.yaml b/geant/gap_ansible/roles/iptrunk_checks/templates/sros_show_port_optical.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a8754bacaab086246e7edbc9d6fd89159e763684 --- /dev/null +++ b/geant/gap_ansible/roles/iptrunk_checks/templates/sros_show_port_optical.yaml @@ -0,0 +1,8 @@ +--- +- example: " 1 - 73.2 1.67 1.43" + getval: '\s+(?P<lane_id>\d)\s+-\s+(?P<tx_bias_ma>\d+(\.\d+)?)\s+(?P<tx_power_dbm>\d+(\.\d+)?)\s+(?P<rx_power_dbm>\d+(\.\d+)?)' + result: + "Lane {{ lane_id }}": + TX_bias_mA: "{{ tx_bias_ma }}" + TX_power_dBm: "{{ tx_power_dbm }}" + rx_power_dBm: "{{ rx_power_dbm }}" diff --git a/geant/gap_ansible/roles/iptrunk_checks/vars/main.yml b/geant/gap_ansible/roles/iptrunk_checks/vars/main.yml index 703b85162c02de0e094a27c07f1098888f603ea5..cb53fc84bb373f4b44ebb3e11ce9ad65e724a090 100644 --- a/geant/gap_ansible/roles/iptrunk_checks/vars/main.yml +++ b/geant/gap_ansible/roles/iptrunk_checks/vars/main.yml @@ -1,15 +1,19 @@ --- # vars file for iptrunks # - checks: - isis - ping - lacp - - optical + - optical_pre + - optical_post + +my_nolog: true -ping_count: 3 -ping_size: 9000 +mtu_ping_count: 3 +mtu_ping_size: 8972 +rapid_ping_count: 100 +rapid_ping_size: 100 wfo_trunk: "{{ wfo_ip_trunk_json }}" diff --git a/geant/gap_ansible/roles/iptrunk_migration/vars/main.yml b/geant/gap_ansible/roles/iptrunk_migration/vars/main.yml index 2fdb32327f536e06cf27e069098ef302c4a20c5a..a0bbad43e1a68357ca3d218703b937072e9fbad8 100644 --- a/geant/gap_ansible/roles/iptrunk_migration/vars/main.yml +++ b/geant/gap_ansible/roles/iptrunk_migration/vars/main.yml @@ -29,7 +29,7 @@ new_side: id: "{{ wfo_trunk.iptrunk.geant_s_sid }}" description: "{{ wfo_trunk.iptrunk.iptrunk_description }}" speed: "{{ wfo_trunk.iptrunk.iptrunk_speed }}" - is_leased_line: false ## Fix it to use iptrunk_type + is_leased_line: false ## FIX: it to use iptrunk_type isis_metric: "{{ wfo_trunk.iptrunk.iptrunk_isis_metric }}" minimum_links: "{{ wfo_trunk.iptrunk.iptrunk_minimum_links }}" name: "{{ wfo_trunk.iptrunk.iptrunk_sides[replace_index | int].iptrunk_side_node.router_fqdn }}"