From 79310795023ce5d65bf32df200542d63e0ff2d6b Mon Sep 17 00:00:00 2001
From: Aleksandr Kurbatov <ak@geant.org>
Date: Tue, 22 Apr 2025 14:11:06 +0100
Subject: [PATCH 1/8] fw_filters: l3_core_service_type -> product.product_type

---
 .../fw_filters/tasks/merge_variables.yaml     | 22 ++++++++-----------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/geant/gap_ansible/roles/fw_filters/tasks/merge_variables.yaml b/geant/gap_ansible/roles/fw_filters/tasks/merge_variables.yaml
index 227ae8ef..2d12a599 100644
--- a/geant/gap_ansible/roles/fw_filters/tasks/merge_variables.yaml
+++ b/geant/gap_ansible/roles/fw_filters/tasks/merge_variables.yaml
@@ -5,7 +5,7 @@
   # when: >-
   #   subscription.product.product_type == "L3CoreService"
   #   and
-  #   subscription.l3_core_service_type in l3_service_types.ies or subscription.l3_core_service_type in l3_service_types.vprn
+  #   subscription.product.product_type | upper in l3_service_types.ies or subscription.product.product_type | upper in l3_service_types.vprn
   #   and
   #   ap.sbp.custom_firewall_filters | ansible.builtin.bool
   block:
@@ -13,7 +13,7 @@
       when: >
         ap.sbp.custom_firewall_filters | ansible.builtin.bool
         and
-        subscription.l3_core_service_type in l3_service_types.ies
+        subscription.product.product_type | upper in l3_service_types.ies
       ansible.builtin.set_fact:
         custom_edge_fw: "{{ [STANDARD_NREN_FW__to_merge, CUSTOM_NREN_FW] | community.general.lists_mergeby('name',
                                                                             recursive=true, list_merge='append') }}"
@@ -22,7 +22,7 @@
       when: >
         ap.sbp.custom_firewall_filters | ansible.builtin.bool
         and
-        subscription.l3_core_service_type in l3_service_types.ies
+        subscription.product.product_type | upper in l3_service_types.ies
       ansible.builtin.set_fact:
         gen_filters: "{{ [STANDARD_EDGE_FW__to_merge, custom_edge_fw] | community.general.lists_mergeby('name') }}"
 
@@ -33,15 +33,15 @@
       when: >
         ap.sbp.custom_firewall_filters | ansible.builtin.bool
         and
-        subscription.l3_core_service_type in l3_service_types.vprn
+        subscription.product.product_type | upper in l3_service_types.vprn
       ansible.builtin.set_fact:
-        standard_nren_fw: "STANDARD_{{ subscription.l3_core_service_type }}_NREN_FW__to_merge"
+        standard_nren_fw: "STANDARD_{{ subscription.product.product_type | upper }}_NREN_FW__to_merge"
 
     - name: Load Standard NREN FW
       when: >
         ap.sbp.custom_firewall_filters | ansible.builtin.bool
         and
-        subscription.l3_core_service_type in l3_service_types.vprn
+        subscription.product.product_type | upper in l3_service_types.vprn
       ansible.builtin.set_fact:
         standard_nren_fw: "{{ lookup('community.general.merge_variables', standard_nren_fw) }}"
 
@@ -50,7 +50,7 @@
       when: >
         ap.sbp.custom_firewall_filters | ansible.builtin.bool
         and
-        subscription.l3_core_service_type in l3_service_types.vprn
+        subscription.product.product_type | upper in l3_service_types.vprn
       ansible.builtin.set_fact:
         custom_edge_fw: "{{ [CUSTOM_NREN_FW, standard_nren_fw] | community.general.lists_mergeby('name',
                                                                             recursive=true, list_merge='append') }}"
@@ -63,16 +63,12 @@
       when: >
         ap.sbp.custom_firewall_filters | ansible.builtin.bool
         and
-        subscription.l3_core_service_type in l3_service_types.vprn
+        subscription.product.product_type | upper in l3_service_types.vprn
       ansible.builtin.set_fact:
         gen_filters: "{{ [STANDARD_EDGE_FW__to_merge, custom_edge_fw] | community.general.lists_mergeby('name') }}"
 
 - name: Prepare FW vars for NREN L3 Core Service with standard filters
-  when: >-
-    subscription.product.product_type == "L3CoreService"
-    and
-    subscription.l3_core_service_type in l3_service_types.ies or subscription.l3_core_service_type in l3_service_types.vprn
-    and
+  when: >
     not ap.sbp.custom_firewall_filters | ansible.builtin.bool
   block:
     - name: Merge NREN standard filters
-- 
GitLab


From bff0edf5fed8de1213678da1c28f9e489ecc22a1 Mon Sep 17 00:00:00 2001
From: Aleksandr Kurbatov <ak@geant.org>
Date: Wed, 23 Apr 2025 16:06:17 +0100
Subject: [PATCH 2/8] `sbp` role: l3_core_service_type -> product.product_type

---
 .../roles/sbp/templates/nokia/deploy/sbp.j2   | 30 +++++++++----------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/geant/gap_ansible/roles/sbp/templates/nokia/deploy/sbp.j2 b/geant/gap_ansible/roles/sbp/templates/nokia/deploy/sbp.j2
index 52195314..9b650c67 100644
--- a/geant/gap_ansible/roles/sbp/templates/nokia/deploy/sbp.j2
+++ b/geant/gap_ansible/roles/sbp/templates/nokia/deploy/sbp.j2
@@ -4,24 +4,24 @@
 {% endif %}
 
         <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 subscription.l3_core_service_type in l3_service_types.ies %}
+  {% if subscription.product.product_type | upper in l3_service_types.ies %}
             <ies 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">
             <service-name>{{ ies_re_name }}</service-name>
-  {% elif subscription.l3_core_service_type in l3_service_types.vprn %}
+  {% elif subscription.product.product_type | upper in l3_service_types.vprn %}
             <vprn 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">
             <service-name>{{ vprn_name }}</service-name>
   {% endif %}
                 <interface alu:operation="replace">
                     <interface-name>{{ lag_name }}.{{ ap.sbp.vlan_id }}</interface-name>
-                {% if subscription.l3_core_service_type in l3_service_types.ies %}
+                {% if subscription.product.product_type | upper in l3_service_types.ies %}
                     <description>SRV_GLOBAL CUSTOMER {{ partner_name }} {{ '#'+ap.custom_service_name if ap.custom_service_name is string }} ${{ ap.sbp.gs_id }} | ASN{{ partner.asn }} | </description>
-                {% elif subscription.l3_core_service_type == 'IAS' %}
+                {% elif subscription.product.product_type | upper == 'IAS' %}
                     <description>SRV_IAS CUSTOMER {{ partner_name }} {{ '#'+ap.custom_service_name if ap.custom_service_name is string }} {{ partner.ias_flavour | regex_search('IAS(GWS)?(PS)?') }} ${{ ap.sbp.gs_id }} | ASN{{ partner.asn }} | </description>
                     <ingress>
                         <policy-accounting>GEANT_DEST_CLASS_POL_TEMPLATE_01</policy-accounting>
                         <destination-class-lookup>true</destination-class-lookup>
                     </ingress>
-                {% elif subscription.l3_core_service_type in l3_service_types.vprn %}
+                {% elif subscription.product.product_type | upper in l3_service_types.vprn %}
                     <description>SRV_L3VPN CUSTOMER {{ partner_name }} {{ '#'+ap.custom_service_name if ap.custom_service_name is string }} ${{ ap.sbp.gs_id }} | ASN{{ partner.asn }} | </description>
                 {% endif %}
                     <ip-mtu>{{ sbp_params.ip_mtu }}</ip-mtu>
@@ -48,23 +48,23 @@
                       {% endif %}
                         <ingress>
                             <filter>
-                {% if subscription.l3_core_service_type in l3_service_types.ies %}
+                {% if subscription.product.product_type | upper in l3_service_types.ies %}
                                 <ip>{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_EDGE_IN</ip>
                                 <ipv6>{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_EDGE_IN_V6</ipv6>
-                {% elif subscription.l3_core_service_type in l3_service_types.vprn %}
-                                <ip>{{ subscription.l3_core_service_type }}_{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_IN</ip>
-                                <ipv6>{{ subscription.l3_core_service_type }}_{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_IN_V6</ipv6>
+                {% elif subscription.product.product_type | upper in l3_service_types.vprn %}
+                                <ip>{{ subscription.product.product_type | upper }}_{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_IN</ip>
+                                <ipv6>{{ subscription.product.product_type | upper }}_{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_IN_V6</ipv6>
                 {% endif %}
                             </filter>
                         </ingress>
                         <egress>
                             <filter>
-                {% if subscription.l3_core_service_type in l3_service_types.ies %}
+                {% if subscription.product.product_type | upper in l3_service_types.ies %}
                                 <ip>{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_EDGE_OUT</ip>
                                 <ipv6>{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_EDGE_OUT_V6</ipv6>
-                {% elif subscription.l3_core_service_type in l3_service_types.vprn %}
-                                <ip>{{ subscription.l3_core_service_type }}_{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_OUT</ip>
-                                <ipv6>{{ subscription.l3_core_service_type }}_{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_OUT_V6</ipv6>
+                {% elif subscription.product.product_type | upper in l3_service_types.vprn %}
+                                <ip>{{ subscription.product.product_type | upper }}_{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_OUT</ip>
+                                <ipv6>{{ subscription.product.product_type | upper }}_{{ partner_name | upper }}_{{ ap.ap_type[:1] }}_OUT_V6</ipv6>
                 {% endif %}
                             </filter>
                         </egress>
@@ -122,9 +122,9 @@
                         </address>
                     </ipv6>
                 </interface>
-      {% if subscription.l3_core_service_type in l3_service_types.ies %}
+      {% if subscription.product.product_type | upper in l3_service_types.ies %}
             </ies>
-      {% elif subscription.l3_core_service_type in l3_service_types.vprn %}
+      {% elif subscription.product.product_type | upper in l3_service_types.vprn %}
             </vprn>
       {% endif %}
         </service>
-- 
GitLab


From ea6ba2a59f3c36d8913fdad9aeaa198a18b3ef32 Mon Sep 17 00:00:00 2001
From: Aleksandr Kurbatov <ak@geant.org>
Date: Wed, 23 Apr 2025 16:08:33 +0100
Subject: [PATCH 3/8] `deploy_service_config`: replace L3CoreService
 product_type

---
 geant/gap_ansible/roles/deploy_service_config/tasks/main.yml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/geant/gap_ansible/roles/deploy_service_config/tasks/main.yml b/geant/gap_ansible/roles/deploy_service_config/tasks/main.yml
index db97f9ff..88c0a37e 100644
--- a/geant/gap_ansible/roles/deploy_service_config/tasks/main.yml
+++ b/geant/gap_ansible/roles/deploy_service_config/tasks/main.yml
@@ -6,11 +6,13 @@
 # However, mixing "imports" with "includes" is not recommended.
 # Another way is to "apply" the "delegate_to: localhost".
 - name: Set router and vendor for the use with SBP
-  when: subscription.product.product_type == 'L3CoreService'
+  when: subscription.product.product_type | upper in l3_service_types.ies
+    or subscription.product.product_type | upper in l3_service_types.vprn
   ansible.builtin.set_fact:
     router: "{{ ap.sbp.edge_port.node }}"
     vendor: "{{ ap.sbp.edge_port.node.vendor }}"
 
+# TODO: check product_type VRF
 - name: Extract current inventory router from "vrf_router_list"
   when: subscription.product.product_type == 'VRF'
   ansible.builtin.set_fact:
-- 
GitLab


From c0f4292317274dc00d0a71e7a53148bcdc6a5f07 Mon Sep 17 00:00:00 2001
From: Aleksandr Kurbatov <ak@geant.org>
Date: Fri, 25 Apr 2025 18:23:14 +0100
Subject: [PATCH 4/8] Update L3-related playbook to match an updated GSO
 subscription structure

---
 .../playbooks/l3_core_service.yaml            | 50 +++++++++++--------
 .../playbooks/manage_bgp_peers.yaml           | 22 +++++---
 geant/gap_ansible/playbooks/manage_sbp.yaml   | 17 ++++---
 .../playbooks/validate_prefix_list.yaml       | 20 +++++---
 4 files changed, 68 insertions(+), 41 deletions(-)

diff --git a/geant/gap_ansible/playbooks/l3_core_service.yaml b/geant/gap_ansible/playbooks/l3_core_service.yaml
index a610d12a..b1ec56b9 100644
--- a/geant/gap_ansible/playbooks/l3_core_service.yaml
+++ b/geant/gap_ansible/playbooks/l3_core_service.yaml
@@ -10,7 +10,7 @@
       # ansible.builtin.include_role:
       #   name: service_checks
       # loop:
-      #   "{{ subscription.l3_core_service.ap_list }}"
+      #   "{{ subscription.l3_subscription_type.l3_core.ap_list }}"
       # loop_control:
       #   loop_var: ap
 
@@ -43,34 +43,42 @@
 
     - name: Import standard general variables for GEANT L3 Core Services
       ansible.builtin.include_vars:
-        file: /opt/ansible_inventory/geant_services/{{ subscription.product.product_type }}/general.yaml
+        file: /opt/ansible_inventory/geant_services/L3CoreService/general.yaml
+
+    - name: Set the L3 subscription key
+      ansible.builtin.set_fact:
+        subscription_key: "{{ l3_services[subscription.product.product_type | upper] }}"
+
+    - name: Set the AP list var
+      ansible.builtin.set_fact:
+        ap_list: "{{ subscription[subscription_key].l3_core.ap_list }}"
 
     - name: Import general variables for {{ partner_name | upper }}
       ansible.builtin.include_vars:
         file: /opt/ansible_inventory/geant_partners/{{ partner_name | upper }}/general.yaml
 
-    - name: Import standard variables for "{{ subscription.product.product_type }}/{{ subscription.l3_core_service_type | replace(' ', '_') }}"
+    - name: Import standard variables for "L3CoreService/{{ subscription.product.product_type | replace(' ', '_') | upper }}"
       ansible.builtin.include_vars:
-        dir: /opt/ansible_inventory/geant_services/{{ subscription.product.product_type }}/{{ subscription.l3_core_service_type | replace(' ', '_') }}
+        dir: /opt/ansible_inventory/geant_services/L3CoreService/{{ subscription.product.product_type | replace(' ', '_') | upper }}
 
-    - name: Import {{ partner_name | upper }} specific variables for {{ subscription.l3_core_service_type | replace(' ', '_') }}
+    - name: Import {{ partner_name | upper }} specific variables for {{ subscription.product.product_type | replace(' ', '_') | upper }}
       when: >
-        subscription.l3_core_service.ap_list | selectattr('sbp.custom_firewall_filters', 'eq', true) | list | length > 0
+        ap_list | selectattr('sbp.custom_firewall_filters', 'eq', true) | list | length > 0
         or
-        subscription.l3_core_service.ap_list | map(attribute='sbp.bgp_session_list') | flatten | selectattr('has_custom_policies', 'eq', true) | list | length > 0
+        ap_list | map(attribute='sbp.bgp_session_list') | flatten | selectattr('has_custom_policies', 'eq', true) | list | length > 0
       ansible.builtin.include_vars:
-        dir: /opt/ansible_inventory/geant_partners/{{ partner_name | upper }}/{{ subscription.l3_core_service_type | replace(' ', '_') }}
+        dir: /opt/ansible_inventory/geant_partners/{{ partner_name | upper }}/{{ subscription.product.product_type | replace(' ', '_') }}
 
     - name: Compile SBP-related config
       when: object == 'sbp'
       block:
         - name: Include IP prefix list if Custom FW is selected
           when: >
-            subscription.l3_core_service.ap_list | selectattr('sbp.custom_firewall_filters', 'eq', true) | list | length > 0
+            ap_list | selectattr('sbp.custom_firewall_filters', 'eq', true) | list | length > 0
           ansible.builtin.include_role:
             name: ip_prefix_lists
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
@@ -78,7 +86,7 @@
           ansible.builtin.include_role:
             name: fw_filters
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
@@ -86,7 +94,7 @@
           ansible.builtin.include_role:
             name: sbp
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
@@ -99,7 +107,7 @@
           vars:
             qry: "bgp_session_list[?ip_type == 'ipv4'] | [0]"
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
@@ -109,7 +117,7 @@
           vars:
             qry: "bgp_session_list[?ip_type == 'ipv6'] | [0]"
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
@@ -117,20 +125,20 @@
           when: >
             bgp_session_v4.families is contains('mcast-ipv4') or bgp_session_v6 is contains('mcast-ipv6')
             and
-            subscription.l3_core_service_type in l3_service_types.ies
+            subscription.product.product_type | upper in l3_service_types.ies
           ansible.builtin.include_role:
             name: pim
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
         - name: Include PO prefix list generation
-          when: subscription.l3_core_service_type in generate_po_prefix_lists
+          when: subscription.product.product_type | upper in l3_generate_po_prefix_lists
           ansible.builtin.include_role:
             name: po_prefix_lists
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
@@ -138,7 +146,7 @@
           ansible.builtin.include_role:
             name: policy_options
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
@@ -146,7 +154,7 @@
           ansible.builtin.include_role:
             name: bgp_config
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
@@ -158,6 +166,6 @@
           ansible.builtin.include_role:
             name: deploy_service_config
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
diff --git a/geant/gap_ansible/playbooks/manage_bgp_peers.yaml b/geant/gap_ansible/playbooks/manage_bgp_peers.yaml
index d594de83..113fa28b 100644
--- a/geant/gap_ansible/playbooks/manage_bgp_peers.yaml
+++ b/geant/gap_ansible/playbooks/manage_bgp_peers.yaml
@@ -25,20 +25,28 @@
       ansible.builtin.include_vars:
         file: /opt/ansible_inventory/geant_partners/{{ partner_name | upper }}/general.yaml
 
-    - name: Import general variables for {{ subscription.product.product_type }}
+    - name: Import standard general variables for GEANT L3 Core Services
       ansible.builtin.include_vars:
-        file: /opt/ansible_inventory/geant_services/{{ subscription.product.product_type }}/general.yaml
+        file: /opt/ansible_inventory/geant_services/L3CoreService/general.yaml
 
-    - name: Import BGP specific vars for {{ subscription.l3_core_service_type | replace(' ', '_') }}
+    - name: Set the L3 subscription key
+      ansible.builtin.set_fact:
+        subscription_key: "{{ l3_services[subscription.product.product_type | upper] }}"
+
+    - name: Set the AP list var
+      ansible.builtin.set_fact:
+        ap_list: "{{ subscription[subscription_key].l3_core.ap_list }}"
+
+    - name: Import BGP specific vars for {{ subscription.product.product_type | upper | replace(' ', '_') }}
       ansible.builtin.include_vars:
-        file: /opt/ansible_inventory/geant_services/{{ subscription.product.product_type }}/{{ subscription.l3_core_service_type | replace(' ', '_') }}/bgp.yaml
+        file: /opt/ansible_inventory/geant_services/L3CoreService/{{ subscription.product.product_type | upper | replace(' ', '_') }}/bgp.yaml
 
     - name: Check BGP neighbors
       when: verb == 'check'
       ansible.builtin.include_role:
         name: service_checks
       loop:
-        "{{ subscription.l3_core_service.ap_list }}"
+        "{{ ap_list }}"
       loop_control:
         loop_var: ap
 
@@ -48,7 +56,7 @@
       ansible.builtin.include_role:
         name: bgp_config
       loop:
-        "{{ subscription.l3_core_service.ap_list }}"
+        "{{ ap_list }}"
       loop_control:
         loop_var: ap
 
@@ -59,6 +67,6 @@
           ansible.builtin.include_role:
             name: deploy_service_config
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
diff --git a/geant/gap_ansible/playbooks/manage_sbp.yaml b/geant/gap_ansible/playbooks/manage_sbp.yaml
index 8298ef64..75665516 100644
--- a/geant/gap_ansible/playbooks/manage_sbp.yaml
+++ b/geant/gap_ansible/playbooks/manage_sbp.yaml
@@ -21,20 +21,23 @@
       ansible.builtin.include_vars:
         dir: /opt/ansible_inventory/group_vars/all
 
-    - name: Import general variables for {{ subscription.product.product_type }}
+    - name: Import standard general variables for GEANT L3 Core Services
       ansible.builtin.include_vars:
-        file: /opt/ansible_inventory/geant_services/{{ subscription.product.product_type }}/general.yaml
+        file: /opt/ansible_inventory/geant_services/L3CoreService/general.yaml
 
-    # - name: Import BGP specific vars for {{ subscription.l3_core_service_type }}
-    #   ansible.builtin.include_vars:
-    #     file: /opt/ansible_inventory/geant_services/{{ subscription.product.product_type }}/{{ subscription.l3_core_service_type }}/bgp.yaml
+    - name: Set the L3 subscription key
+      ansible.builtin.set_fact:
+        subscription_key: "{{ l3_services[subscription.product.product_type | upper] }}"
 
+    - name: Set the AP list var
+      ansible.builtin.set_fact:
+        ap_list: "{{ subscription[subscription_key].l3_core.ap_list }}"
 
     - name: Deactivate SPB on the old router
       ansible.builtin.include_role:
         name: sbp
       loop:
-        "{{ subscription.l3_core_service.ap_list }}"
+        "{{ ap_list }}"
       loop_control:
         loop_var: ap
 
@@ -45,6 +48,6 @@
           ansible.builtin.include_role:
             name: deploy_service_config
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
diff --git a/geant/gap_ansible/playbooks/validate_prefix_list.yaml b/geant/gap_ansible/playbooks/validate_prefix_list.yaml
index 00f1e9cf..691c055c 100644
--- a/geant/gap_ansible/playbooks/validate_prefix_list.yaml
+++ b/geant/gap_ansible/playbooks/validate_prefix_list.yaml
@@ -24,24 +24,32 @@
 
     - name: Import standard general variables for GEANT L3 Core Services
       ansible.builtin.include_vars:
-        file: /opt/ansible_inventory/geant_services/{{ subscription.product.product_type }}/general.yaml
+        file: /opt/ansible_inventory/geant_services/L3CoreService/general.yaml
+
+    - name: Set the L3 subscription key
+      ansible.builtin.set_fact:
+        subscription_key: "{{ l3_services[subscription.product.product_type | upper] }}"
+
+    - name: Set the AP list var
+      ansible.builtin.set_fact:
+        ap_list: "{{ subscription[subscription_key].l3_core.ap_list }}"
 
     - name: Import general variables for {{ partner_name | upper }}
       ansible.builtin.include_vars:
         file: /opt/ansible_inventory/geant_partners/{{ partner_name | upper }}/general.yaml
 
-    - name: Import standard variables for "{{ subscription.product.product_type }}/{{ subscription.l3_core_service_type | replace(' ', '_') }}"
+    - name: Import standard variables for "L3CoreService/{{ subscription.product.product_type | replace(' ', '_') | upper }}"
       ansible.builtin.include_vars:
-        dir: /opt/ansible_inventory/geant_services/{{ subscription.product.product_type }}/{{ subscription.l3_core_service_type | replace(' ', '_') }}
+        dir: /opt/ansible_inventory/geant_services/L3CoreService/{{ subscription.product.product_type | replace(' ', '_') | upper }}
 
     - name: Generate PO prefix lists
       block:
         - name: Include PO prefix list role
-          when: subscription.l3_core_service_type in generate_po_prefix_lists
+          when: subscription.product.product_type | upper in l3_generate_po_prefix_lists
           ansible.builtin.include_role:
             name: po_prefix_lists
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
 
@@ -52,6 +60,6 @@
           ansible.builtin.include_role:
             name: deploy_service_config
           loop:
-            "{{ subscription.l3_core_service.ap_list }}"
+            "{{ ap_list }}"
           loop_control:
             loop_var: ap
-- 
GitLab


From 5a20e4e4b6ac51538266b4ba7b42ae89a8479def Mon Sep 17 00:00:00 2001
From: Aleksandr Kurbatov <ak@geant.org>
Date: Fri, 25 Apr 2025 18:24:46 +0100
Subject: [PATCH 5/8] `bgp_config`: Update tasks and templates to match the new
 GSO L3 subscription structure

---
 .../gap_ansible/roles/bgp_config/tasks/merge_vars.yaml | 10 +++++-----
 .../bgp_config/templates/juniper/deactivate/bgp.j2     |  4 ++--
 .../roles/bgp_config/templates/nokia/deploy/bgp.j2     |  4 ++--
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/geant/gap_ansible/roles/bgp_config/tasks/merge_vars.yaml b/geant/gap_ansible/roles/bgp_config/tasks/merge_vars.yaml
index ead8d780..58cab6fd 100644
--- a/geant/gap_ansible/roles/bgp_config/tasks/merge_vars.yaml
+++ b/geant/gap_ansible/roles/bgp_config/tasks/merge_vars.yaml
@@ -1,16 +1,16 @@
 ---
-- name: Set Standard BGP import and export policy names for {{ subscription.l3_core_service_type }}
+- name: Set Standard BGP import and export policy names for {{ subscription.product.product_type | upper }}
   when: >
-    subscription.l3_core_service_type in l3_service_types.ies
+    subscription.product.product_type | upper in l3_service_types.ies
   ansible.builtin.set_fact:
     import_policies_v4: "{{ bgp.policies.import.v4 }}"
     import_policies_v6: "{{ bgp.policies.import.v6 }}"
     export_policies_v4: "{{ bgp.policies.export.v4 }}"
     export_policies_v6: "{{ bgp.policies.export.v6 }}"
 
-- name: Set standard BGP import and export policy names for VPRN {{ subscription.l3_core_service_type }}
+- name: Set standard BGP import and export policy names for VPRN {{ subscription.product.product_type | upper }}
   when: >
-    subscription.l3_core_service_type in l3_service_types.vprn
+    subscription.product.product_type | upper in l3_service_types.vprn
     and
     not bgp_session_v4.has_custom_policies | ansible.builtin.bool
     or
@@ -23,7 +23,7 @@
 
 - name: Set custom BGP import and export policy names for VPRN
   when: >
-    subscription.l3_core_service_type in l3_service_types.vprn
+    subscription.product.product_type | upper in l3_service_types.vprn
     and
     bgp_session_v4.has_custom_policies | ansible.builtin.bool
     or
diff --git a/geant/gap_ansible/roles/bgp_config/templates/juniper/deactivate/bgp.j2 b/geant/gap_ansible/roles/bgp_config/templates/juniper/deactivate/bgp.j2
index b0e88b28..07d4fa49 100644
--- a/geant/gap_ansible/roles/bgp_config/templates/juniper/deactivate/bgp.j2
+++ b/geant/gap_ansible/roles/bgp_config/templates/juniper/deactivate/bgp.j2
@@ -1,11 +1,11 @@
 {% for neighbor in bgp_obj %}
-  {% if subscription.l3_core_service_type in l3_service_types.ies %}
+  {% if subscription.product.product_type | upper in l3_service_types.ies %}
     {% if neighbor.ip_type == 'ipv4' %}
       deactivate protocols bgp group {{ bgp.group.ipv4_juniper }} neighbor {{ neighbor.peer_address }}
     {% elif neighbor.ip_type == 'ipv6' %}
       deactivate protocols bgp group {{ bgp.group.ipv6_juniper }} neighbor {{ neighbor.peer_address }}
     {% endif %}
-  {% elif subscription.l3_core_service_type in l3_service_types.vprn %}
+  {% elif subscription.product.product_type | upper in l3_service_types.vprn %}
     {% if neighbor.ip_type == 'ipv4' %}
       deactivate routing-instances {{ bgp.routing_instance_juniper }} protocols bgp group {{ bgp.group.ipv4_juniper }} neighbor {{ neighbor.peer_address }}
     {% elif neighbor.ip_type == 'ipv6' %}
diff --git a/geant/gap_ansible/roles/bgp_config/templates/nokia/deploy/bgp.j2 b/geant/gap_ansible/roles/bgp_config/templates/nokia/deploy/bgp.j2
index 97d6c5cf..c09c5d02 100644
--- a/geant/gap_ansible/roles/bgp_config/templates/nokia/deploy/bgp.j2
+++ b/geant/gap_ansible/roles/bgp_config/templates/nokia/deploy/bgp.j2
@@ -1,11 +1,11 @@
-  {% if subscription.l3_core_service_type in l3_service_types.ies %}
+  {% if subscription.product.product_type | upper in l3_service_types.ies %}
         <router 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">
             <router-name>Base</router-name>
             <bgp 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">
             {% include 'bgp_neighbor.j2' %}
             </bgp>
        </router>
-  {% elif subscription.l3_core_service_type in l3_service_types.vprn %}
+  {% elif subscription.product.product_type | upper in l3_service_types.vprn %}
         <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">
             <vprn 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">
             <service-name>{{ vprn_name }}</service-name>
-- 
GitLab


From c99370b86113fedd0e9568afe965a9309fb3ed1d Mon Sep 17 00:00:00 2001
From: Aleksandr Kurbatov <ak@geant.org>
Date: Fri, 25 Apr 2025 18:25:29 +0100
Subject: [PATCH 6/8] `deploy_service_config`: Update tasks to match the new
 GSO L3 subscription

---
 .../gap_ansible/roles/deploy_service_config/tasks/main.yml  | 6 ++++--
 .../roles/deploy_service_config/tasks/push_config.yml       | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/geant/gap_ansible/roles/deploy_service_config/tasks/main.yml b/geant/gap_ansible/roles/deploy_service_config/tasks/main.yml
index 88c0a37e..c7194182 100644
--- a/geant/gap_ansible/roles/deploy_service_config/tasks/main.yml
+++ b/geant/gap_ansible/roles/deploy_service_config/tasks/main.yml
@@ -6,8 +6,10 @@
 # However, mixing "imports" with "includes" is not recommended.
 # Another way is to "apply" the "delegate_to: localhost".
 - name: Set router and vendor for the use with SBP
-  when: subscription.product.product_type | upper in l3_service_types.ies
-    or subscription.product.product_type | upper in l3_service_types.vprn
+  when: >
+    subscription.product.product_type | upper in l3_services.keys() | list
+  # when: subscription.product.product_type | upper in l3_service_types.ies
+  #   or subscription.product.product_type | upper in l3_service_types.vprn
   ansible.builtin.set_fact:
     router: "{{ ap.sbp.edge_port.node }}"
     vendor: "{{ ap.sbp.edge_port.node.vendor }}"
diff --git a/geant/gap_ansible/roles/deploy_service_config/tasks/push_config.yml b/geant/gap_ansible/roles/deploy_service_config/tasks/push_config.yml
index a4c61832..59c2a28b 100644
--- a/geant/gap_ansible/roles/deploy_service_config/tasks/push_config.yml
+++ b/geant/gap_ansible/roles/deploy_service_config/tasks/push_config.yml
@@ -24,7 +24,7 @@
     subscription.product.product_type == 'L3CoreService'
   ansible.builtin.fail:
     msg: >
-      The config of {{ object }} in {{ subscription.l3_core_service_type }}
+      The config of {{ object }} in {{ subscription.product.product_type | upper }}
       for {{ partner_name | upper }} drifted!
 
 - name: Fail if there is any diff - Any product
-- 
GitLab


From 076c9f7bdc82fcf4a64501dae3ceb3e4c4703786 Mon Sep 17 00:00:00 2001
From: Aleksandr Kurbatov <ak@geant.org>
Date: Fri, 25 Apr 2025 18:27:09 +0100
Subject: [PATCH 7/8] `policy_options`: Update tasks to match the new GSO L3
 subscription

---
 .../tasks/calc_nren_communities.yaml          |  4 ++--
 .../roles/policy_options/tasks/main.yml       | 21 ++++++++++---------
 .../tasks/merge_ias_vrf_standard_vars.yaml    |  8 +++----
 .../tasks/merge_vrf_custom_vars.yaml          |  6 +++---
 .../tasks/merge_vrf_standard_vars.yaml        |  6 +++---
 5 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/geant/gap_ansible/roles/policy_options/tasks/calc_nren_communities.yaml b/geant/gap_ansible/roles/policy_options/tasks/calc_nren_communities.yaml
index f79109f3..5ab21b1c 100644
--- a/geant/gap_ansible/roles/policy_options/tasks/calc_nren_communities.yaml
+++ b/geant/gap_ansible/roles/policy_options/tasks/calc_nren_communities.yaml
@@ -1,11 +1,11 @@
 ---
 - name: Set NREN community names
-  when: not subscription.l3_core_service_type in ['LHCONE']
+  when: not subscription.product.product_type | upper  in ['LHCONE']
   ansible.builtin.set_fact:
     nren_community_names: ["GEANT_{{ partner_name | upper }}", "GEANT_{{ partner_name | upper }}_BLOCK"]
 
 - name: Set NREN community names
-  when: subscription.l3_core_service_type in ['LHCONE']
+  when: subscription.product.product_type | upper  in ['LHCONE']
   ansible.builtin.set_fact:
     nren_community_names: ["GEANT_{{ partner_name | upper }}", "LHCONE_{{ partner_name | upper }}_BLOCK"]
 
diff --git a/geant/gap_ansible/roles/policy_options/tasks/main.yml b/geant/gap_ansible/roles/policy_options/tasks/main.yml
index fcd5c618..701eac27 100644
--- a/geant/gap_ansible/roles/policy_options/tasks/main.yml
+++ b/geant/gap_ansible/roles/policy_options/tasks/main.yml
@@ -2,7 +2,7 @@
 # tasks file for policy_options
 - name: Set BGP V4 session object to check for custom policies
   when: >
-    subscription.product.product_type == "L3CoreService"
+    subscription.product.product_type | upper in l3_services.keys() | list
   ansible.builtin.set_fact:
     bgp_session_v4: "{{ ap.sbp | json_query(qry) }}"
   vars:
@@ -10,7 +10,7 @@
 
 - name: Set BGP V6 session object to check for custom policies
   when: >
-    subscription.product.product_type == "L3CoreService"
+    subscription.product.product_type | upper in l3_services.keys() | list
   ansible.builtin.set_fact:
     bgp_session_v6: "{{ ap.sbp | json_query(qry) }}"
   vars:
@@ -18,14 +18,14 @@
 
 - name: Calculate NREN-specific communities
   when: >
-    subscription.product.product_type == "L3CoreService"
+    subscription.product.product_type | upper in l3_services.keys() | list
   ansible.builtin.include_tasks: calc_nren_communities.yaml
 
 - name: Load GEANT-IP policies
   when: >
-    subscription.product.product_type == "L3CoreService"
+    subscription.product.product_type | upper in l3_services.keys() | list
     and
-    subscription.l3_core_service_type in l3_service_types.ies
+    subscription.product.product_type | upper in l3_service_types.ies
   block:
     - name: Load GEANT-IP standard policies if selected
       when: >
@@ -43,9 +43,9 @@
 
 - name: Load IAS VRF policies
   when: >
-    subscription.product.product_type == "L3CoreService"
+    subscription.product.product_type | upper in l3_services.keys() | list
     and
-    subscription.l3_core_service_type == "IAS"
+    subscription.product.product_type | upper == "IAS"
   block:
     - name: Load NREN standard VRF policies
       when: >
@@ -63,11 +63,11 @@
 
 - name: Load VRF policies
   when: >
-    subscription.product.product_type == "L3CoreService"
+    subscription.product.product_type | upper in l3_services.keys() | list
     and
-    subscription.l3_core_service_type in l3_service_types.vprn
+    subscription.product.product_type | upper in l3_service_types.vprn
     and
-    not subscription.l3_core_service_type == "IAS"
+    not subscription.product.product_type | upper == "IAS"
   block:
     - name: Load NREN standard VRF policies
       when: >
@@ -83,6 +83,7 @@
         bgp_session_v6.has_custom_policies | ansible.builtin.bool
       ansible.builtin.include_tasks: merge_vrf_custom_vars.yaml
 
+# TODO: Check product_type VRF
 - name: Load Standard Policy Options for creation of VRF {{ subscription.vrf.vrf_name }}
   when: >
     subscription.product.product_type == "VRF"
diff --git a/geant/gap_ansible/roles/policy_options/tasks/merge_ias_vrf_standard_vars.yaml b/geant/gap_ansible/roles/policy_options/tasks/merge_ias_vrf_standard_vars.yaml
index 679f6c1b..e00c0948 100644
--- a/geant/gap_ansible/roles/policy_options/tasks/merge_ias_vrf_standard_vars.yaml
+++ b/geant/gap_ansible/roles/policy_options/tasks/merge_ias_vrf_standard_vars.yaml
@@ -1,13 +1,13 @@
 ---
-- name: Load Standard Policy Options prefix lists for VRF {{ subscription.l3_core_service_type }}
+- name: Load Standard Policy Options prefix lists for VRF {{ subscription.product.product_type | upper }}
   ansible.builtin.set_fact:
     po_final_prefix_lists: "{{ lookup('community.general.merge_variables', 'STANDARD_VRF_PO_PREFIX_LISTS') }}"
 
 - name: Set the policy name based on the partner "ias_flavour" for {{ partner_name | upper }}
   ansible.builtin.set_fact:
-    po_policy_name: "STANDARD_VRF_PO_POLICIES_{{ partner.ias_flavour }}"
+    po_policy_name: "STANDARD_VRF_PO_POLICIES_{{ subscription[subscription_key].ias_flavor }}"
 
-- name: Load Standard Policy Options policies for {{ partner.ias_flavour }}
+- name: Load Standard Policy Options policies for {{ subscription[subscription_key].ias_flavor }}
   ansible.builtin.set_fact:
     po_final_policies: "{{ lookup('community.general.merge_variables', po_policy_name) }}"
 
@@ -53,7 +53,7 @@
   ansible.builtin.set_fact:
     po_final_policies: "{{ [po_final_policies, po_policy_default_route_v6] | community.general.lists_mergeby('name') }}"
 
-- name: Load Standard Policy Options prefix lists for VRF {{ subscription.l3_core_service_type }}
+- name: Load Standard Policy Options prefix lists for VRF {{ subscription.product.product_type | upper }}
   ansible.builtin.set_fact:
     po_vrf_communities: "{{ lookup('community.general.merge_variables', 'STANDARD_VRF_COMMUNITIES') }}"
 
diff --git a/geant/gap_ansible/roles/policy_options/tasks/merge_vrf_custom_vars.yaml b/geant/gap_ansible/roles/policy_options/tasks/merge_vrf_custom_vars.yaml
index e792d228..4e6a6852 100644
--- a/geant/gap_ansible/roles/policy_options/tasks/merge_vrf_custom_vars.yaml
+++ b/geant/gap_ansible/roles/policy_options/tasks/merge_vrf_custom_vars.yaml
@@ -1,13 +1,13 @@
 ---
-- name: Load Standard Policy Options prefix lists for VRF {{ subscription.l3_core_service_type }}
+- name: Load Standard Policy Options prefix lists for VRF {{ subscription.product.product_type | upper }}
   ansible.builtin.set_fact:
     po_final_prefix_lists: "{{ lookup('community.general.merge_variables', 'STANDARD_VRF_PO_PREFIX_LISTS') }}"
 
-- name: Load Standard Policy Options policies for VRF {{ subscription.l3_core_service_type }}
+- name: Load Standard Policy Options policies for VRF {{ subscription.product.product_type | upper }}
   ansible.builtin.set_fact:
     po_final_policies: "{{ lookup('community.general.merge_variables', 'CUSTOM_VRF_PO_POLICIES') }}"
 
-- name: Load Standard Policy Options prefix lists for VRF {{ subscription.l3_core_service_type }}
+- name: Load Standard Policy Options prefix lists for VRF {{ subscription.product.product_type | upper }}
   ansible.builtin.set_fact:
     po_vrf_communities: "{{ lookup('community.general.merge_variables', 'STANDARD_VRF_COMMUNITIES') }}"
 
diff --git a/geant/gap_ansible/roles/policy_options/tasks/merge_vrf_standard_vars.yaml b/geant/gap_ansible/roles/policy_options/tasks/merge_vrf_standard_vars.yaml
index 08199e70..003fbb1f 100644
--- a/geant/gap_ansible/roles/policy_options/tasks/merge_vrf_standard_vars.yaml
+++ b/geant/gap_ansible/roles/policy_options/tasks/merge_vrf_standard_vars.yaml
@@ -1,13 +1,13 @@
 ---
-- name: Load Standard Policy Options prefix lists for VRF {{ subscription.l3_core_service_type }}
+- name: Load Standard Policy Options prefix lists for VRF {{ subscription.product.product_type | upper }}
   ansible.builtin.set_fact:
     po_final_prefix_lists: "{{ lookup('community.general.merge_variables', 'STANDARD_VRF_PO_PREFIX_LISTS') }}"
 
-- name: Load Standard Policy Options policies for VRF {{ subscription.l3_core_service_type }}
+- name: Load Standard Policy Options policies for VRF {{ subscription.product.product_type | upper }}
   ansible.builtin.set_fact:
     po_final_policies: "{{ lookup('community.general.merge_variables', 'STANDARD_VRF_PO_POLICIES') }}"
 
-- name: Load Standard Policy Options prefix lists for VRF {{ subscription.l3_core_service_type }}
+- name: Load Standard Policy Options prefix lists for VRF {{ subscription.product.product_type | upper }}
   ansible.builtin.set_fact:
     po_vrf_communities: "{{ lookup('community.general.merge_variables', 'STANDARD_VRF_COMMUNITIES') }}"
 
-- 
GitLab


From d7eb3bb69f863712edee7d805b0b0e0131b0bb58 Mon Sep 17 00:00:00 2001
From: Aleksandr Kurbatov <ak@geant.org>
Date: Fri, 25 Apr 2025 18:27:46 +0100
Subject: [PATCH 8/8] `sbp`: Update template to use IAS flavor parameter from
 GSO

---
 geant/gap_ansible/roles/sbp/templates/nokia/deploy/sbp.j2 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/geant/gap_ansible/roles/sbp/templates/nokia/deploy/sbp.j2 b/geant/gap_ansible/roles/sbp/templates/nokia/deploy/sbp.j2
index 9b650c67..5d6daeab 100644
--- a/geant/gap_ansible/roles/sbp/templates/nokia/deploy/sbp.j2
+++ b/geant/gap_ansible/roles/sbp/templates/nokia/deploy/sbp.j2
@@ -16,7 +16,7 @@
                 {% if subscription.product.product_type | upper in l3_service_types.ies %}
                     <description>SRV_GLOBAL CUSTOMER {{ partner_name }} {{ '#'+ap.custom_service_name if ap.custom_service_name is string }} ${{ ap.sbp.gs_id }} | ASN{{ partner.asn }} | </description>
                 {% elif subscription.product.product_type | upper == 'IAS' %}
-                    <description>SRV_IAS CUSTOMER {{ partner_name }} {{ '#'+ap.custom_service_name if ap.custom_service_name is string }} {{ partner.ias_flavour | regex_search('IAS(GWS)?(PS)?') }} ${{ ap.sbp.gs_id }} | ASN{{ partner.asn }} | </description>
+                    <description>SRV_IAS CUSTOMER {{ partner_name }} {{ '#'+ap.custom_service_name if ap.custom_service_name is string }} {{ subscription[subscription_key].ias_flavor | regex_search('IAS(GWS)?(PS)?') }} ${{ ap.sbp.gs_id }} | ASN{{ partner.asn }} | </description>
                     <ingress>
                         <policy-accounting>GEANT_DEST_CLASS_POL_TEMPLATE_01</policy-accounting>
                         <destination-class-lookup>true</destination-class-lookup>
-- 
GitLab