From c53f27e22923d9936b6ed3fbaf3c90bab901fbea Mon Sep 17 00:00:00 2001 From: Aleksandr Kurbatov <ak@geant.org> Date: Thu, 3 Apr 2025 22:07:43 +0100 Subject: [PATCH 1/2] Add new role for SDP config --- geant/gap_ansible/roles/sdp/README.md | 29 +++++++++++++++ geant/gap_ansible/roles/sdp/defaults/main.yml | 2 ++ geant/gap_ansible/roles/sdp/handlers/main.yml | 2 ++ geant/gap_ansible/roles/sdp/meta/main.yml | 36 +++++++++++++++++++ .../gap_ansible/roles/sdp/tasks/compile.yaml | 14 ++++++++ .../roles/sdp/tasks/connection_tasks.yaml | 29 +++++++++++++++ geant/gap_ansible/roles/sdp/tasks/main.yml | 34 ++++++++++++++++++ .../roles/sdp/tasks/merge_vars.yaml | 13 +++++++ .../roles/sdp/tasks/push_config.yaml | 36 +++++++++++++++++++ .../roles/sdp/tasks/standard_tasks.yaml | 15 ++++++++ .../routers/nokia/add_pe_to_sdp_mesh/sdp.j2 | 25 +++++++++++++ .../nokia/remove_pe_from_sdp_mesh/sdp.j2 | 14 ++++++++ geant/gap_ansible/roles/sdp/vars/main.yml | 8 +++++ 13 files changed, 257 insertions(+) create mode 100644 geant/gap_ansible/roles/sdp/README.md create mode 100644 geant/gap_ansible/roles/sdp/defaults/main.yml create mode 100644 geant/gap_ansible/roles/sdp/handlers/main.yml create mode 100644 geant/gap_ansible/roles/sdp/meta/main.yml create mode 100644 geant/gap_ansible/roles/sdp/tasks/compile.yaml create mode 100644 geant/gap_ansible/roles/sdp/tasks/connection_tasks.yaml create mode 100644 geant/gap_ansible/roles/sdp/tasks/main.yml create mode 100644 geant/gap_ansible/roles/sdp/tasks/merge_vars.yaml create mode 100644 geant/gap_ansible/roles/sdp/tasks/push_config.yaml create mode 100644 geant/gap_ansible/roles/sdp/tasks/standard_tasks.yaml create mode 100644 geant/gap_ansible/roles/sdp/templates/routers/nokia/add_pe_to_sdp_mesh/sdp.j2 create mode 100644 geant/gap_ansible/roles/sdp/templates/routers/nokia/remove_pe_from_sdp_mesh/sdp.j2 create mode 100644 geant/gap_ansible/roles/sdp/vars/main.yml diff --git a/geant/gap_ansible/roles/sdp/README.md b/geant/gap_ansible/roles/sdp/README.md new file mode 100644 index 00000000..5beb3179 --- /dev/null +++ b/geant/gap_ansible/roles/sdp/README.md @@ -0,0 +1,29 @@ +# Role Name + +Role to manage l2circuits/epipes in multivendor network. + +## Requirements + +GEANT custom netconf module with Nokia "commit_comment" and "config_mode" features. + +## Role Variables + +- vars/main.yaml +- external inventory (group_vars) +- orchestrator (GSO) + +## Dependencies + +n/a + +## Example Playbook + +Role is supposed to be driven by GSO. + +## License + +MIT + +## Author Information + +A. Kurbatov. GEANT Orchestration and Automation Team (GOAT). diff --git a/geant/gap_ansible/roles/sdp/defaults/main.yml b/geant/gap_ansible/roles/sdp/defaults/main.yml new file mode 100644 index 00000000..c2376894 --- /dev/null +++ b/geant/gap_ansible/roles/sdp/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for sdp diff --git a/geant/gap_ansible/roles/sdp/handlers/main.yml b/geant/gap_ansible/roles/sdp/handlers/main.yml new file mode 100644 index 00000000..790d04df --- /dev/null +++ b/geant/gap_ansible/roles/sdp/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for sdp diff --git a/geant/gap_ansible/roles/sdp/meta/main.yml b/geant/gap_ansible/roles/sdp/meta/main.yml new file mode 100644 index 00000000..8e604b5c --- /dev/null +++ b/geant/gap_ansible/roles/sdp/meta/main.yml @@ -0,0 +1,36 @@ +galaxy_info: + author: A. Kurbatov + description: GEANT Orchestration and Automation Team + company: GEANT + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: MIT + + min_ansible_version: "2.10" + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + galaxy_tags: + - network + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: + [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/geant/gap_ansible/roles/sdp/tasks/compile.yaml b/geant/gap_ansible/roles/sdp/tasks/compile.yaml new file mode 100644 index 00000000..8e128116 --- /dev/null +++ b/geant/gap_ansible/roles/sdp/tasks/compile.yaml @@ -0,0 +1,14 @@ +--- +- name: Set ansible host to localhost to compile template + ansible.builtin.set_fact: + ansible_host: "localhost" + ansible_connection: local + +- name: Print the template in "/var/tmp/ansible_run_{{ opid }}/SDP.conf" + ansible.builtin.template: + src: "routers/nokia/{{ verb }}/sdp.j2" + dest: "/var/tmp/ansible_run_{{ opid }}/SDP.conf" + lstrip_blocks: true + trim_blocks: true + mode: "0755" + delegate_to: localhost diff --git a/geant/gap_ansible/roles/sdp/tasks/connection_tasks.yaml b/geant/gap_ansible/roles/sdp/tasks/connection_tasks.yaml new file mode 100644 index 00000000..da9016ea --- /dev/null +++ b/geant/gap_ansible/roles/sdp/tasks/connection_tasks.yaml @@ -0,0 +1,29 @@ +--- +# Connection tasks for SDP role +# +- name: Set ansible_host to terminal server when router is offline + when: subscription.router.router_access_via_ts | ansible.builtin.bool and + inventory_hostname == subscription.router.router_fqdn + ansible.builtin.set_fact: + ansible_host: "{{ subscription.router.router_site.site_ts_address }}" + ansible_port: "{{ subscription.router.router_ts_port }}" + +- name: Load netconf connection config for subscription router + when: inventory_hostname == subscription.router.router_fqdn + ansible.builtin.set_fact: + ansible_connection: "{{ netconf_access[subscription.router.vendor].ansible_connection }}" + ansible_network_os: "{{ netconf_access[subscription.router.vendor].ansible_network_os }}" + +# - name: Debug hostvars +# ansible.builtin.debug: +# var: hostvars[inventory_hostname].vendor + +- name: Set ansible_host back to the {{ inventory_hostname }} + ansible.builtin.set_fact: + ansible_host: "{{ inventory_hostname }}" + +- name: Load netconf connection config for mesh routers + when: inventory_hostname != subscription.router.router_fqdn + ansible.builtin.set_fact: + ansible_connection: "{{ netconf_access[hostvars[inventory_hostname].vendor].ansible_connection }}" + ansible_network_os: "{{ netconf_access[hostvars[inventory_hostname].vendor].ansible_network_os }}" diff --git a/geant/gap_ansible/roles/sdp/tasks/main.yml b/geant/gap_ansible/roles/sdp/tasks/main.yml new file mode 100644 index 00000000..356a4abd --- /dev/null +++ b/geant/gap_ansible/roles/sdp/tasks/main.yml @@ -0,0 +1,34 @@ +--- +# main tasks for SDP +# +- name: Print the usage + when: (verb is not defined) or (verb not in verbs) + ansible.builtin.debug: + msg: + - "'verb' keyword is mandatory. Usage: -e verb=$verb" + +- name: Print defined verbs + when: (verb is not defined) or (verb not in verbs) + ansible.builtin.debug: + msg: + - "Allowed verb: {{ item }}" + loop: "{{ verbs }}" + +- name: Stop if arguments are incorrect + when: (verb is not defined) or (verb not in verbs) + ansible.builtin.meta: end_play + +- name: Include standard tasks + ansible.builtin.include_tasks: standard_tasks.yaml + +- name: Include merge vars tasks + ansible.builtin.include_tasks: merge_vars.yaml + +- name: Include config compilation tasks + ansible.builtin.include_tasks: compile.yaml + +- name: Include connection tasks + ansible.builtin.include_tasks: connection_tasks.yaml + +- name: Include config deployment tasks + ansible.builtin.include_tasks: push_config.yaml diff --git a/geant/gap_ansible/roles/sdp/tasks/merge_vars.yaml b/geant/gap_ansible/roles/sdp/tasks/merge_vars.yaml new file mode 100644 index 00000000..fe6c16fe --- /dev/null +++ b/geant/gap_ansible/roles/sdp/tasks/merge_vars.yaml @@ -0,0 +1,13 @@ +--- +# merge vars for SDP +- name: Import variables from 'all' + ansible.builtin.include_vars: + dir: /opt/ansible_inventory/group_vars/all + +- name: Import routers variables + ansible.builtin.include_vars: + dir: /opt/ansible_inventory/group_vars/routers + +- name: Select SDP params for l2ciruit-type + ansible.builtin.set_fact: + sdp_type: "{{ (sdp_types | selectattr('id', 'equalto', '1'))[0] }}" diff --git a/geant/gap_ansible/roles/sdp/tasks/push_config.yaml b/geant/gap_ansible/roles/sdp/tasks/push_config.yaml new file mode 100644 index 00000000..8ac1c0e9 --- /dev/null +++ b/geant/gap_ansible/roles/sdp/tasks/push_config.yaml @@ -0,0 +1,36 @@ +--- +- name: Config deploy [CHECK ONLY][NOKIA] + when: > + dry_run | ansible.builtin.bool + geant.gap_ansible.nokia_netconf_config: + format: xml + default_operation: merge + content: "{{ lookup('ansible.builtin.file', '/var/tmp/ansible_run_{{ opid }}/SDP.conf') }}" + commit: true + validate: true + config_mode: private + diff: true + register: output + check_mode: true + +- name: Fail if config diff is detected + when: > + output.changed | ansible.builtin.bool + and + is_verification_workflow | ansible.builtin.bool + ansible.builtin.fail: + msg: > + The config for {{ subscription.description }} has drifted! + +- name: Config deploy [REAL][NOKIA] + when: > + not dry_run | ansible.builtin.bool + geant.gap_ansible.nokia_netconf_config: + format: xml + default_operation: merge + content: "{{ lookup('ansible.builtin.file', '/var/tmp/ansible_run_{{ opid }}/SDP.conf') }}" + commit: true + commit_comment: "{{ commit_comment }}" + config_mode: private + diff: true + register: output diff --git a/geant/gap_ansible/roles/sdp/tasks/standard_tasks.yaml b/geant/gap_ansible/roles/sdp/tasks/standard_tasks.yaml new file mode 100644 index 00000000..4772e5bb --- /dev/null +++ b/geant/gap_ansible/roles/sdp/tasks/standard_tasks.yaml @@ -0,0 +1,15 @@ +--- +- name: Generate an ID for this run + ansible.builtin.set_fact: + opid: "{{ lookup('community.general.random_string', length=18, special=false) }}" + +- name: Print the ID + ansible.builtin.debug: + msg: "{{ opid }}" + +- name: Create a folder for all compiled output + ansible.builtin.file: + path: "/var/tmp/ansible_run_{{ opid }}" + state: directory + mode: "0755" + delegate_to: localhost diff --git a/geant/gap_ansible/roles/sdp/templates/routers/nokia/add_pe_to_sdp_mesh/sdp.j2 b/geant/gap_ansible/roles/sdp/templates/routers/nokia/add_pe_to_sdp_mesh/sdp.j2 new file mode 100644 index 00000000..97dee48b --- /dev/null +++ b/geant/gap_ansible/roles/sdp/templates/routers/nokia/add_pe_to_sdp_mesh/sdp.j2 @@ -0,0 +1,25 @@ +<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:alu="urn:ietf:params:xml:ns:netconf:base:1.0"> + <configure xmlns="urn:nokia.com:sros:ns:yang:sr:conf"> + <service xmlns="urn:nokia.com:sros:ns:yang:sr:conf" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nokia-attr="urn:nokia.com:sros:ns:yang:sr:attributes"> + {% if pe_router_list|length != 0 %} + {% for pe_fqdn, pe_addr in pe_router_list.items() %} + {% set sdp_id = pe_addr.lo4 | replace(sdp_prefix_regex, '') | replace('.', '') + sdp_type.id %} + <sdp alu:operation="replace"> + <sdp-id>{{ sdp_id }}</sdp-id> + <admin-state>enable</admin-state> + <description>{{ pe_fqdn }}</description> + <delivery-type>mpls</delivery-type> + <path-mtu>{{ sdp_type.path_mtu }}</path-mtu> + {% if sdp_type.signaling is defined %} + <signaling>{{ sdp_type.signaling}}</signaling> + {% endif %} + <sr-isis>{{ sdp_type.sr_isis | lower }}</sr-isis> + <far-end> + <ip-address>{{ pe_addr.lo4 }}</ip-address> + </far-end> + </sdp> + {% endfor %} + {% endif %} + </service> + </configure> +</config> diff --git a/geant/gap_ansible/roles/sdp/templates/routers/nokia/remove_pe_from_sdp_mesh/sdp.j2 b/geant/gap_ansible/roles/sdp/templates/routers/nokia/remove_pe_from_sdp_mesh/sdp.j2 new file mode 100644 index 00000000..7101bbf9 --- /dev/null +++ b/geant/gap_ansible/roles/sdp/templates/routers/nokia/remove_pe_from_sdp_mesh/sdp.j2 @@ -0,0 +1,14 @@ +<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:alu="urn:ietf:params:xml:ns:netconf:base:1.0"> + <configure xmlns="urn:nokia.com:sros:ns:yang:sr:conf"> + <service xmlns="urn:nokia.com:sros:ns:yang:sr:conf" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nokia-attr="urn:nokia.com:sros:ns:yang:sr:attributes"> + {% if pe_router_list|length != 0 %} + {% for pe_fqdn, pe_addr in pe_router_list.items() %} + {% set sdp_id = pe_addr.lo4 | replace(sdp_prefix_regex, '') | replace('.', '') + sdp_type.id %} + <sdp alu:operation="delete"> + <sdp-id>{{ sdp_id }}</sdp-id> + </sdp> + {% endfor %} + {% endif %} + </service> + </configure> +</config> diff --git a/geant/gap_ansible/roles/sdp/vars/main.yml b/geant/gap_ansible/roles/sdp/vars/main.yml new file mode 100644 index 00000000..f82ca880 --- /dev/null +++ b/geant/gap_ansible/roles/sdp/vars/main.yml @@ -0,0 +1,8 @@ +--- +# vars file for sdp +dry_run: true +is_verification_workflow: false + +verbs: + - add_pe_to_sdp_mesh + - remove_pe_from_sdp_mesh -- GitLab From 83a832f4b0b0992a8ab279f482deabca118621aa Mon Sep 17 00:00:00 2001 From: Aleksandr Kurbatov <ak@geant.org> Date: Thu, 3 Apr 2025 22:08:04 +0100 Subject: [PATCH 2/2] Update SDP playbook to use SDP role --- geant/gap_ansible/playbooks/update_pe_sdp_mesh.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/geant/gap_ansible/playbooks/update_pe_sdp_mesh.yaml b/geant/gap_ansible/playbooks/update_pe_sdp_mesh.yaml index a895eece..48010d54 100644 --- a/geant/gap_ansible/playbooks/update_pe_sdp_mesh.yaml +++ b/geant/gap_ansible/playbooks/update_pe_sdp_mesh.yaml @@ -2,4 +2,5 @@ hosts: all gather_facts: false roles: - - ../roles/promote_p_to_pe + # - ../roles/promote_p_to_pe + - ../roles/sdp -- GitLab