From 050f4d917b37bf0bd9d198114ac6160d8d05a5e5 Mon Sep 17 00:00:00 2001 From: Aleksandr Kurbatov <aleksandr.kurbatov@GL1342.local> Date: Thu, 25 Apr 2024 21:33:05 +0100 Subject: [PATCH] Rework of check_optical levels Added parsers to get optical values per lane for both Junos and SROS. Junos: getting output in JSON, then parsing is easy. SROS: no option to get output in JSON, hence need to parse using `ansible.utils.cli_parse`. `templates/sros_show_port_optical.yaml` is part of SROS parsing. For the "remaining" side of a trunk: Because it will be the same router/vendor in PRE and POST, we can produce the diff on PRE/POST. So then all the PRE and POST results are saved in individual files and the final task would be to produce the diff. However, the optical levels always fluctuate a little, so there always be a diff on wide range of values. --- .../tasks/check_optical_levels.yaml | 71 +++++++++++++------ .../tasks/diff_optical_results.yaml | 27 +++++++ .../roles/iptrunk_checks/tasks/main.yml | 33 ++++++++- .../templates/sros_show_port_optical.yaml | 8 +++ 4 files changed, 116 insertions(+), 23 deletions(-) create mode 100644 geant/gap_ansible/roles/iptrunk_checks/tasks/diff_optical_results.yaml create mode 100644 geant/gap_ansible/roles/iptrunk_checks/templates/sros_show_port_optical.yaml 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 b4b83f5c..c6b85f77 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 @@ -5,28 +5,46 @@ - name: Run Juniper Optical info junipernetworks.junos.junos_command: commands: - # - show interfaces diagnostics optics {{ item.interface_name }} | no-more - - show interfaces terse {{ item.interface_name }} - # display: json + - "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 }}" + 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 + ansible.builtin.set_fact: + ae_result: "{{ ae_result | combine({item.key: item.value}) }}" + with_items: + - { key: "{{ ae_member.interface_name }}", value: "{{ lanes }}" } - - name: Write output to the file - ansible.builtin.blockinfile: - path: "{{ opt_checks_file }}" - marker: "# {mark} --- {{ check | uppper }} check on {{ inventory_hostname }} for {{ item.interface_name }} ---" - append_newline: true - block: "{{ optical_status }}" + - 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 +53,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 | match "Lane ID" pre-lines 1 post-lines 5</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: 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/diff_optical_results.yaml b/geant/gap_ansible/roles/iptrunk_checks/tasks/diff_optical_results.yaml new file mode 100644 index 00000000..3d42a9e2 --- /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 48646bfa..5dbcbc8e 100644 --- a/geant/gap_ansible/roles/iptrunk_checks/tasks/main.yml +++ b/geant/gap_ansible/roles/iptrunk_checks/tasks/main.yml @@ -51,10 +51,15 @@ ansible.builtin.set_fact: opt_checks_dir: "/var/tmp/ansible_trunk_checks_{{ trunks[0].id }}" -- name: Set the optical checks results file name - when: check == "optical_pre" or check == "optical_post" +- 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 }}/checks_{{ process_id }}.txt" + 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" @@ -72,7 +77,29 @@ 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 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: + content: "{{ ae_result | to_nice_yaml }}" + dest: "{{ opt_checks_file }}" + +- name: Display "{{ check | upper }}" check results for "{{ inventory_hostname }}" + 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" + 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 00000000..a8754bac --- /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 }}" -- GitLab