diff --git a/geant/gap_ansible/playbooks/check_l3_services.yaml b/geant/gap_ansible/playbooks/check_l3_services.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c709c3b66658e19043c0c17582859a74699f3c79
--- /dev/null
+++ b/geant/gap_ansible/playbooks/check_l3_services.yaml
@@ -0,0 +1,5 @@
+- name: Check L3 VPRN
+  hosts: all
+  gather_facts: false
+  roles:
+    - ../roles/promote_p_to_pe
diff --git a/geant/gap_ansible/playbooks/promote_p_to_pe.yaml b/geant/gap_ansible/playbooks/promote_p_to_pe.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..36378edc87d61aaf79b4936acb5c0c0eab42d7fe
--- /dev/null
+++ b/geant/gap_ansible/playbooks/promote_p_to_pe.yaml
@@ -0,0 +1,5 @@
+- name: Promote P router to PE
+  hosts: all
+  gather_facts: false
+  roles:
+    - ../roles/promote_p_to_pe
diff --git a/geant/gap_ansible/playbooks/update_pe_sdp_mesh.yaml b/geant/gap_ansible/playbooks/update_pe_sdp_mesh.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a895eecec53508de7de90073063f54fb891cad3a
--- /dev/null
+++ b/geant/gap_ansible/playbooks/update_pe_sdp_mesh.yaml
@@ -0,0 +1,5 @@
+- name: Update SDP mesh
+  hosts: all
+  gather_facts: false
+  roles:
+    - ../roles/promote_p_to_pe
diff --git a/geant/gap_ansible/roles/ibgp_update/tasks/check_p_ibgp.yaml b/geant/gap_ansible/roles/ibgp_update/tasks/check_nokia_ibgp.yaml
similarity index 95%
rename from geant/gap_ansible/roles/ibgp_update/tasks/check_p_ibgp.yaml
rename to geant/gap_ansible/roles/ibgp_update/tasks/check_nokia_ibgp.yaml
index bcfee22a5a74f2139b8075573171607f65eba4b1..8866ec46c43f21767856867f8dbcfff46b93d626 100644
--- a/geant/gap_ansible/roles/ibgp_update/tasks/check_p_ibgp.yaml
+++ b/geant/gap_ansible/roles/ibgp_update/tasks/check_nokia_ibgp.yaml
@@ -3,7 +3,7 @@
     ansible_network_os: nokia.sros.md
     ansible_connection: netconf
 
-- name: Nokia P - check BGP status
+- name: Check BGP status
   block:
     - name: Get BGP group status
       ansible.netcommon.netconf_rpc:
diff --git a/geant/gap_ansible/roles/ibgp_update/tasks/main.yml b/geant/gap_ansible/roles/ibgp_update/tasks/main.yml
index 6306f3171242a782a25666fcd2c3e85147ab53c6..8c62e6c7f75c8df7dd674db0b6b97a980608ab56 100644
--- a/geant/gap_ansible/roles/ibgp_update/tasks/main.yml
+++ b/geant/gap_ansible/roles/ibgp_update/tasks/main.yml
@@ -1,10 +1,18 @@
 ---
 # tasks file for ibg_update
 - name: Print the usage
+  when: (verb is not defined) or (verb not in verbs)
   ansible.builtin.debug:
     msg:
-      - "Allowed verbs: 'add_pe_to_p' and 'add_p_to_pe'. Use: -e 'verb=$verb'."
+      - "'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: Fail if arguments are missing
   ansible.legacy.meta: end_play
@@ -27,21 +35,18 @@
   ansible.builtin.debug:
     msg: "{{ opid }}"
 
-- name: Include PE mesh modification tasks
-  ansible.builtin.include_tasks: modify_pe_mesh.yaml
-  when: >
-    verb in [ "add_p_to_pe", "remove_pe_from_pe", "remove_p_from_pe" ]
-
-- name: Include PE into P tasks if selected
-  ansible.builtin.include_tasks: add_pe_to_p.yaml
+- name: Include list of routers modification tasks
+  ansible.builtin.include_tasks: modify_router_list.yaml
   when: >
-    verb in [ "add_pe_to_p", "verify_p_ibgp" ]
+    verb in [ "add_p_to_pe", "add_pe_to_pe_mesh", "add_pe_to_all_p",
+            "remove_p_from_pe", "remove_pe_from_pe" ]
 
-- name: Include PE removal from P tasks if selected
-  ansible.builtin.include_tasks: remove_pe_from_p.yaml
+- name: Include single router modification tasks
+  ansible.builtin.include_tasks: modify_subscription_router.yaml
   when: >
-    verb in [ "remove_pe_from_p" ]
+    verb in [ "add_pe_to_p", "verify_p_ibgp", "add_pe_mesh_to_pe",
+              "add_all_p_to_pe", "remove_pe_from_p" ]
 
-- name: Check status of iBGP on P router
-  ansible.builtin.include_tasks: check_p_ibgp.yaml
-  when: verb == "check_p_ibgp"
+- name: Check status of iBGP on Nokia router
+  ansible.builtin.include_tasks: check_nokia_ibgp.yaml
+  when: verb in [ "check_p_ibgp", "check_pe_ibgp" ]
diff --git a/geant/gap_ansible/roles/ibgp_update/tasks/modify_pe_mesh.yaml b/geant/gap_ansible/roles/ibgp_update/tasks/modify_router_list.yaml
similarity index 100%
rename from geant/gap_ansible/roles/ibgp_update/tasks/modify_pe_mesh.yaml
rename to geant/gap_ansible/roles/ibgp_update/tasks/modify_router_list.yaml
diff --git a/geant/gap_ansible/roles/ibgp_update/tasks/add_pe_to_p.yaml b/geant/gap_ansible/roles/ibgp_update/tasks/modify_subscription_router.yaml
similarity index 91%
rename from geant/gap_ansible/roles/ibgp_update/tasks/add_pe_to_p.yaml
rename to geant/gap_ansible/roles/ibgp_update/tasks/modify_subscription_router.yaml
index 0a41b8d9058b3624e30dd87884bfe2abe52979aa..5d23f4f2ba97676eeb737f0553c732aae229009d 100644
--- a/geant/gap_ansible/roles/ibgp_update/tasks/add_pe_to_p.yaml
+++ b/geant/gap_ansible/roles/ibgp_update/tasks/modify_subscription_router.yaml
@@ -5,18 +5,18 @@
 # FIX: Load ansible_network_os via group_vars
 #
 - name: Set variable to connect to nokia
-  ansible.legacy.set_fact:
+  ansible.builtin.set_fact:
     ansible_network_os: geant.gap_ansible.sros
     ansible_connection: netconf
 
 - name: Set ansible_host to terminal server when router is offline
-  ansible.legacy.set_fact:
+  ansible.builtin.set_fact:
     ansible_host: "{{ subscription.router.router_site.site_ts_address }}"
     ansible_port: "{{ subscription.router.router_ts_port }}"
   when: ( subscription.router.router_access_via_ts | ansible.builtin.bool ) is true
 
 - name: Set the vendor variable to select correct template
-  ansible.legacy.set_fact:
+  ansible.builtin.set_fact:
     vendor: "{{ subscription.router.vendor }}"
 
 - name: Include compile tasks
diff --git a/geant/gap_ansible/roles/ibgp_update/tasks/remove_pe_from_p.yaml b/geant/gap_ansible/roles/ibgp_update/tasks/remove_pe_from_p.yaml
deleted file mode 100644
index 01aae362b1ccc5826c36e50d98e165933bc097bb..0000000000000000000000000000000000000000
--- a/geant/gap_ansible/roles/ibgp_update/tasks/remove_pe_from_p.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
-# PE to P tasks:
-# This is th case of decomm of a PE router <- remove it from all Ps.
-# P routers will always be NOKIA
-# FIX: Load ansible_network_os via group_vars
-#
-- name: Set variable to connect to nokia
-  ansible.legacy.set_fact:
-    ansible_network_os: geant.gap_ansible.sros
-    ansible_connection: netconf
-
-# - name: Set ansible_host to terminal server when router is offline
-#   ansible.legacy.set_fact:
-#     ansible_host: "{{ subscription.router.router_site.site_ts_address }}"
-#     ansible_port: "{{ subscription.router.router_ts_port }}"
-#   when: ( subscription.router.router_access_via_ts | ansible.builtin.bool ) is true
-
-- name: Set vendor var for "remove_pe_from_p" case
-  ansible.builtin.set_fact:
-    vendor: "nokia"
-
-- name: Include compile tasks
-  ansible.builtin.include_tasks: compile.yaml
-
-- name: Include deploy tasks
-  ansible.builtin.include_tasks: deploy.yaml
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/juniper/add_p_to_pe.j2 b/geant/gap_ansible/roles/ibgp_update/templates/juniper/add_p_to_pe.j2
index f8ca8a8d6ee98b8d4a2292be11bb7409b59076b9..9308bdc20a52b575a5d941ef97b6812f61828d8b 100644
--- a/geant/gap_ansible/roles/ibgp_update/templates/juniper/add_p_to_pe.j2
+++ b/geant/gap_ansible/roles/ibgp_update/templates/juniper/add_p_to_pe.j2
@@ -1,2 +1,2 @@
-set protocols bgp group iGEANT6-P-ONLY neighbor {{ p_lo_ipv6_address }} description {{ p_router_fqdn }}
-set protocols bgp group iGEANT-P-ONLY neighbor {{ p_lo_ipv4_address }} description {{ p_router_fqdn }}
+set protocols bgp group {{ geant_bgp_groups.p_only.ipv6 }} neighbor {{ p_lo_ipv6_address }} description {{ p_router_fqdn }}
+set protocols bgp group {{ geant_bgp_groups.p_only.ipv4 }} neighbor {{ p_lo_ipv4_address }} description {{ p_router_fqdn }}
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/juniper/add_pe_to_pe_mesh.j2 b/geant/gap_ansible/roles/ibgp_update/templates/juniper/add_pe_to_pe_mesh.j2
new file mode 100644
index 0000000000000000000000000000000000000000..94ec3f3ab8076c504dc77c72bae8f91dc12b3293
--- /dev/null
+++ b/geant/gap_ansible/roles/ibgp_update/templates/juniper/add_pe_to_pe_mesh.j2
@@ -0,0 +1,2 @@
+set protocols bgp group {{ geant_bgp_groups.pe_mesh.ipv6 }} neighbor {{ subscription_lo_ipv6 }} description {{ subscription_fqdn }}
+set protocols bgp group {{ geant_bgp_groups.pe_mesh.ipv4 }} neighbor {{ subscription_lo_ipv4 }} description {{ subscription_fqdn }}
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/juniper/remove_p_from_pe.j2 b/geant/gap_ansible/roles/ibgp_update/templates/juniper/remove_p_from_pe.j2
index 0a139d34d9206da6cb197936779ec4f17775cdd0..b40bf1f9f3757fbcce95a205fdf175a9441b4181 100644
--- a/geant/gap_ansible/roles/ibgp_update/templates/juniper/remove_p_from_pe.j2
+++ b/geant/gap_ansible/roles/ibgp_update/templates/juniper/remove_p_from_pe.j2
@@ -1,2 +1,2 @@
-delete protocols bgp group iGEANT6-P-ONLY neighbor {{ p_lo_ipv6_address }}
-delete protocols bgp group iGEANT-P-ONLY neighbor {{ p_lo_ipv4_address }}
+delete protocols bgp group {{ geant_bgp_groups.p_only.ipv6 }} neighbor {{ p_lo_ipv6_address }}
+delete protocols bgp group {{ geant_bgp_groups.p_only.ipv4 }} neighbor {{ p_lo_ipv4_address }}
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/juniper/remove_pe_from_pe.j2 b/geant/gap_ansible/roles/ibgp_update/templates/juniper/remove_pe_from_pe.j2
index 9bd780dd826aa532f672683543211a61c869787e..79f83bd307db75768862dfa287efc0be4c07106f 100644
--- a/geant/gap_ansible/roles/ibgp_update/templates/juniper/remove_pe_from_pe.j2
+++ b/geant/gap_ansible/roles/ibgp_update/templates/juniper/remove_pe_from_pe.j2
@@ -1,2 +1,2 @@
-delete protocols bgp group iGEANT6 neighbor {{ subscription.router.router_lo_ipv6_address }}
-delete protocols bgp group iGEANT neighbor {{ subscription.router.router_lo_ipv4_address }}
+delete protocols bgp group {{ geant_bgp_groups.pe_mesh.ipv6 }} neighbor {{ subscription.router.router_lo_ipv6_address }}
+delete protocols bgp group {{ geant_bgp_groups.pe_mesh.ipv4 }} neighbor {{ subscription.router.router_lo_ipv4_address }}
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_all_p_to_pe.j2 b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_all_p_to_pe.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f25653e2175d2ac1bd718adf87b122667664c25a
--- /dev/null
+++ b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_all_p_to_pe.j2
@@ -0,0 +1,21 @@
+<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">
+    <router>
+    <router-name>Base</router-name>
+        <bgp>
+          {% for p_fqdn, p_ipadd in p_router_list.items() %}
+            <neighbor 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">
+              <ip-address>{{ p_ipadd.lo4 }}</ip-address>
+              <description>{{ p_fqdn }}</description>
+              <group>{{ geant_bgp_groups.p_only.ipv4 }}</group>
+            </neighbor>
+            <neighbor 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">
+              <ip-address>{{ p_ipadd.lo4 }}</ip-address>
+              <description>{{ p_fqdn }}</description>
+              <group>{{ geant_bgp_groups.p_only.ipv6 }}</group>
+            </neighbor>
+          {% endfor %}
+        </bgp>
+    </router>
+  </configure>
+</config>
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_p_to_pe.j2 b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_p_to_pe.j2
index 76f0cbffad592a293d0aa971926f874d17dde4bc..21ee04e5dd3542535aca0c0232c303a1ba36f634 100644
--- a/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_p_to_pe.j2
+++ b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_p_to_pe.j2
@@ -1,14 +1,19 @@
-<router>
-    <bgp>
-        <neighbor 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">
-          <ip-address>{{ p_lo_ipv4_address }}</ip-address>
-          <description>{{ p_router_fqdn }}</description>
-          <group>iGEANT-P-ONLY</group>
-        </neighbor>
-        <neighbor 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">
-          <ip-address>{{ p_lo_ipv6_address }}</ip-address>
-          <description>{{ p_router_fqdn }}</description>
-          <group>iGEANT-P-ONLY-v6</group>
-        </neighbor>
-    </bgp>
-</router>
+<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">
+    <router>
+    <router-name>Base</router-name>
+        <bgp>
+            <neighbor 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">
+              <ip-address>{{ p_lo_ipv4_address }}</ip-address>
+              <description>{{ p_router_fqdn }}</description>
+              <group>{{ geant_bgp_groups.p_only.ipv4 }}</group>
+            </neighbor>
+            <neighbor 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">
+              <ip-address>{{ p_lo_ipv6_address }}</ip-address>
+              <description>{{ p_router_fqdn }}</description>
+              <group>{{ geant_bgp_groups.p_only.ipv6 }}</group>
+            </neighbor>
+        </bgp>
+    </router>
+  </configure>
+</config>
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_mesh_to_pe.j2 b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_mesh_to_pe.j2
new file mode 100644
index 0000000000000000000000000000000000000000..4a8a6e460bfa580e5e810d891cb14e47901f2a6f
--- /dev/null
+++ b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_mesh_to_pe.j2
@@ -0,0 +1,21 @@
+<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">
+    <router>
+      <router-name>Base</router-name>
+        <bgp>
+          {% for pe_fqdn, pe_ipadd in pe_router_list.items() %}
+            <neighbor 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" alu:operation="replace">
+              <ip-address>{{ pe_ipadd.lo4 }}</ip-address>
+              <description>{{ pe_fqdn }}</description>
+              <group>{{ geant_bgp_groups.pe_mesh.ipv4 }}</group>
+            </neighbor>
+            <neighbor 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" alu:operation="replace">
+              <ip-address>{{ pe_ipadd.lo6 }}</ip-address>
+              <description>{{ pe_fqdn }}</description>
+              <group>{{ geant_bgp_groups.pe_mesh.ipv6 }}</group>
+            </neighbor>
+          {% endfor %}
+        </bgp>
+    </router>
+  </configure>
+</config>
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_all_p.j2 b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_all_p.j2
new file mode 100644
index 0000000000000000000000000000000000000000..b0a6ab02b11ac751bdbcf398f0f942e74bbf501e
--- /dev/null
+++ b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_all_p.j2
@@ -0,0 +1,19 @@
+<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">
+    <router>
+      <router-name>Base</router-name>
+        <bgp>
+            <neighbor 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" alu:operation="replace">
+              <ip-address>{{ subscription_lo_ipv4 }}</ip-address>
+              <description>{{ subscription_fqdn }}</description>
+              <group>{{ geant_bgp_groups.p_only.ipv4 }}</group>
+            </neighbor>
+            <neighbor 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" alu:operation="replace">
+              <ip-address>{{ subscription_lo_ipv6 }}</ip-address>
+              <description>{{ subscription_fqdn }}</description>
+              <group>{{ geant_bgp_groups.p_only.ipv6 }}</group>
+            </neighbor>
+        </bgp>
+    </router>
+  </configure>
+</config>
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_p.j2 b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_p.j2
index 198b8878514b5203a7af263af07df1d4e261ac5c..11e210f4e95f9d312e9123a40874c448f221437b 100644
--- a/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_p.j2
+++ b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_p.j2
@@ -7,12 +7,12 @@
             <neighbor 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" alu:operation="replace">
               <ip-address>{{ pe_ipadd.lo4 }}</ip-address>
               <description>{{ pe_fqdn }}</description>
-              <group>iGEANT-P-ONLY</group>
+              <group>{{ geant_bgp_groups.p_only.ipv4 }}</group>
             </neighbor>
             <neighbor 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" alu:operation="replace">
               <ip-address>{{ pe_ipadd.lo6 }}</ip-address>
               <description>{{ pe_fqdn }}</description>
-              <group>iGEANT6-P-ONLY</group>
+              <group>{{ geant_bgp_groups.p_only.ipv6 }}</group>
             </neighbor>
           {% endfor %}
         </bgp>
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_pe_mesh.j2 b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_pe_mesh.j2
new file mode 100644
index 0000000000000000000000000000000000000000..0ee4bf3ebf7e0bc904c01b043cdc87d58b94948f
--- /dev/null
+++ b/geant/gap_ansible/roles/ibgp_update/templates/nokia/add_pe_to_pe_mesh.j2
@@ -0,0 +1,19 @@
+<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">
+    <router>
+      <router-name>Base</router-name>
+        <bgp>
+            <neighbor 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" alu:operation="replace">
+              <ip-address>{{ subscription_lo_ipv4 }}</ip-address>
+              <description>{{ subscription_fqdn }}</description>
+              <group>{{ geant_bgp_groups.pe_mesh.ipv4 }}</group>
+            </neighbor>
+            <neighbor 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" alu:operation="replace">
+              <ip-address>{{ subscription_lo_ipv6 }}</ip-address>
+              <description>{{ subscription_fqdn }}</description>
+              <group>{{ geant_bgp_groups.pe_mesh.ipv6 }}</group>
+            </neighbor>
+        </bgp>
+    </router>
+  </configure>
+</config>
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_pe_from_p.j2 b/geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_p_from_pe.j2
similarity index 87%
rename from geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_pe_from_p.j2
rename to geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_p_from_pe.j2
index 07672c2bfc3955686044a5b52893498681590dfa..a62c1d3ed9cc4908c42c619d5577dd7d45a58603 100644
--- a/geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_pe_from_p.j2
+++ b/geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_p_from_pe.j2
@@ -5,9 +5,11 @@
         <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">
             <neighbor alu:operation="delete">
               <ip-address>{{ subscription.router.router_lo_ipv4_address }}</ip-address>
+              <group>{{ geant_bgp_groups.p_only.ipv4 }}</group>
             </neighbor>
             <neighbor alu:operation="delete">
               <ip-address>{{ subscription.router.router_lo_ipv6_address }}</ip-address>
+              <group>{{ geant_bgp_groups.p_only.ipv6 }}</group>
             </neighbor>
         </bgp>
     </router>
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_pe_from_pe.j2 b/geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_pe_from_pe.j2
index 48242b15b64be09b6891a1aabcc9bfc49917d4a8..56b342073dec1079f04c9f8c6b65a57ec8084ecd 100644
--- a/geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_pe_from_pe.j2
+++ b/geant/gap_ansible/roles/ibgp_update/templates/nokia/remove_pe_from_pe.j2
@@ -5,11 +5,11 @@
         <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">
             <neighbor alu:operation="delete">
               <ip-address>{{ subscription.router.router_lo_ipv4_address }}</ip-address>
-              <group>iGEANT</group>
+              <group>{{ geant_bgp_groups.pe_mesh.ipv4 }}</group>
             </neighbor>
             <neighbor alu:operation="delete">
               <ip-address>{{ subscription.router.router_lo_ipv6_address }}</ip-address>
-              <group>iGEANT6</group>
+              <group>{{ geant_bgp_groups.pe_mesh.ipv6 }}</group>
             </neighbor>
         </bgp>
     </router>
diff --git a/geant/gap_ansible/roles/ibgp_update/templates/nokia/verify_p_ibgp.j2 b/geant/gap_ansible/roles/ibgp_update/templates/nokia/verify_p_ibgp.j2
index 3c30bba2e56bf424f668e999a04a1ce04359f15d..3f3f8d4486b4d28d22c3d87db39517231a8b7861 100644
--- a/geant/gap_ansible/roles/ibgp_update/templates/nokia/verify_p_ibgp.j2
+++ b/geant/gap_ansible/roles/ibgp_update/templates/nokia/verify_p_ibgp.j2
@@ -11,7 +11,7 @@
                     <as-number>{{ geant_re_as_number }}</as-number>
                 </local-as>
                 <group alu:operation="replace">
-                    <group-name>iGEANT-P-ONLY</group-name>
+                    <group-name>{{ geant_bgp_groups.p_only.ipv4 }}</group-name>
                     <admin-state>enable</admin-state>
                     <next-hop-self>true</next-hop-self>
                     <type>internal</type>
@@ -23,7 +23,7 @@
                     </family>
                 </group>
                 <group alu:operation="replace">
-                    <group-name>iGEANT6-P-ONLY</group-name>
+                    <group-name>{{ geant_bgp_groups.p_only.ipv6 }}</group-name>
                     <next-hop-self>true</next-hop-self>
                     <type>internal</type>
                     <peer-as>{{ geant_re_as_number }}</peer-as>
@@ -37,12 +37,12 @@
                 <neighbor 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" alu:operation="replace">
                   <ip-address>{{ pe_ipadd.lo4 }}</ip-address>
                   <description>{{ pe_fqdn }}</description>
-                  <group>iGEANT-P-ONLY</group>
+                  <group>{{ geant_bgp_groups.p_only.ipv4 }}</group>
                 </neighbor>
                 <neighbor 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" alu:operation="replace">
                   <ip-address>{{ pe_ipadd.lo6 }}</ip-address>
                   <description>{{ pe_fqdn }}</description>
-                  <group>iGEANT6-P-ONLY</group>
+                  <group><{{ geant_bgp_groups.p_only.ipv6 }}/group>
                 </neighbor>
               {% endfor %}
             </bgp>
diff --git a/geant/gap_ansible/roles/ibgp_update/vars/main.yml b/geant/gap_ansible/roles/ibgp_update/vars/main.yml
index 6b064e84bb607c60b346aaee9c191d74504472f6..24f0b97d6ef52dfb26c038f1e3939b667621d024 100644
--- a/geant/gap_ansible/roles/ibgp_update/vars/main.yml
+++ b/geant/gap_ansible/roles/ibgp_update/vars/main.yml
@@ -1,19 +1,24 @@
 ---
-# vars file for ibg_update
+# vars file for ibgp_update
 dry_run: "True"
 is_verification_workflow: false
 verbs:
   - add_pe_to_p # Adds all the existing PEs in the P-GROUP on the newly installed P
   - add_p_to_pe # Adds the newly installed P to the P-GROUP in all the existing PEs
-  - check_p_ibgp
   - verify_p_ibgp  # Validates the config of BGP stanza including neighbors
   - remove_p_from_pe # placeholder for future use | Removes the P that is going to be promoted to PE from the P-GROUP on all PEs
   - remove_pe_from_p # PE router termination workflow
   - remove_pe_from_pe # When decommissiong a PE we remove it from PE-GROUP and P-GROUP on all the PE and P routers
-  - add_pe_to_pe # placeholder for future use | Adds the newly installed PE (could be an EX-P or a new PE) to the PE-GROUP on all the other PEs
-  - add_new_pe_to_p # placeholder for future use | Adds the newly installed PE (could be an EX-P or a new PE) the P-GROUP on all the Ps
-  - promote_p_to_pe # placeholder for future use | Deletes P-GROUP and adds
+  - add_pe_to_pe_mesh # placeholder for future use | Adds the newly installed PE (could be an EX-P or a new PE) to the PE-GROUP on all the other PEs
+  - add_pe_mesh_to_pe # placeholder for future use | Adds the newly installed PE (could be an EX-P or a new PE) the P-GROUP on all the Ps
+  - check_p_ibgp # Check BGP status on the newly provisioned P router
+  - check_pe_ibgp # Check BGP status on the newly provisioned PE router
+  - add_all_p_to_pe # Add P routers to the newly promoted PE router
+  - add_pe_to_all_p # Add newly promoted PE to all existing P routers
 wfo_router: "{{ subscription }}"
 p_lo_ipv4_address: "{{ wfo_router.router.router_lo_ipv4_address }}"
 p_lo_ipv6_address: "{{ wfo_router.router.router_lo_ipv6_address }}"
 p_router_fqdn: "{{ wfo_router.router.router_fqdn }}"
+subscription_lo_ipv4: "{{ subscription.router.router_lo_ipv4_address }}"
+subscription_lo_ipv6: "{{ subscription.router.router_lo_ipv6_address }}"
+subscription_fqdn: "{{ subscription.router.router_fqdn }}"
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/README.md b/geant/gap_ansible/roles/promote_p_to_pe/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..225dd44b9fc5b3abff7e9c68ff9e91d505cdd5f0
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/README.md
@@ -0,0 +1,38 @@
+Role Name
+=========
+
+A brief description of the role goes here.
+
+Requirements
+------------
+
+Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
+
+Role Variables
+--------------
+
+A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
+
+Dependencies
+------------
+
+A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
+
+Example Playbook
+----------------
+
+Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
+
+    - hosts: servers
+      roles:
+         - { role: username.rolename, x: 42 }
+
+License
+-------
+
+BSD
+
+Author Information
+------------------
+
+An optional section for the role authors to include contact information, or a website (HTML is not allowed).
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/defaults/main.yml b/geant/gap_ansible/roles/promote_p_to_pe/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..dc98c08359701e76a50d8ee490bfc3a191f71c0f
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+# defaults file for promote_p_to_pe
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/handlers/main.yml b/geant/gap_ansible/roles/promote_p_to_pe/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..591996568dfda14b77abd24049b68e265cb8ccad
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for promote_p_to_pe
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/meta/main.yml b/geant/gap_ansible/roles/promote_p_to_pe/meta/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..36d899dd86d8c01083aefc8c7000b2cf64cacd75
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/meta/main.yml
@@ -0,0 +1,35 @@
+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/promote_p_to_pe/tasks/check_routing_instances.yaml b/geant/gap_ansible/roles/promote_p_to_pe/tasks/check_routing_instances.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..653d21d0c0d4c3be22f85b6746bd3397e8417afa
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/tasks/check_routing_instances.yaml
@@ -0,0 +1,22 @@
+- name: Set variable to connect to nokia
+  ansible.builtin.set_fact:
+    ansible_network_os: nokia.sros.md
+    ansible_connection: netconf
+
+- name: Check VPRN BGP summary
+  block:
+    - name: Get BGP summary
+      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>show router service-name "{{ vprn.name | quote }}" bgp summary</md-cli-input-line>
+              </md-cli-raw-command>
+            </global-operations>
+        display: json
+      register: out
+    - name: Show BGP summary for VPRN "{{ vprn.name | quote }}"
+      ansible.builtin.debug:
+        msg: "{{out.output['rpc-reply']['nokiaoper:results']['nokiaoper:md-cli-output-block'].split('\n')}}"
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/tasks/compile.yaml b/geant/gap_ansible/roles/promote_p_to_pe/tasks/compile.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6208e177c9238a753ba6dd6c08b0d2b5075ec7dd
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/tasks/compile.yaml
@@ -0,0 +1,62 @@
+- name: Merge the variables
+  ansible.builtin.include_tasks: merge_variables.yaml
+
+- name: Set ansible host to localhost to compile config when router is offline
+  when:
+    subscription.router.router_access_via_ts | ansible.builtin.bool
+  ansible.builtin.set_fact:
+    ansible_host: "localhost"
+    ansible_connection: local
+
+- name: Create a folder for all the things
+  ansible.builtin.file:
+    path: "/var/tmp/ansible_run_{{ opid }}"
+    state: directory
+    mode: '0755'
+  delegate_to: localhost
+
+- name: Print the template in "/var/tmp/ansible_run_{{ opid }}/pe_base_config.conf"
+  when: verb == "deploy_pe_base_config"
+  ansible.builtin.template:
+    src: "routers/{{ subscription.router.vendor }}/pe_base_config.j2"
+    dest: "/var/tmp/ansible_run_{{ opid }}/pe_base_config.conf"
+    lstrip_blocks: true
+    trim_blocks: true
+    mode: '0755'
+  delegate_to: localhost
+
+- name: Print the template in "/var/tmp/ansible_run_{{ opid }}/pe_base_vprn.conf"
+  when: verb == "deploy_routing_instances"
+  ansible.builtin.template:
+    src: "routers/{{ subscription.router.vendor }}/pe_base_vprn.j2"
+    dest: "/var/tmp/ansible_run_{{ opid }}/pe_base_vprn.conf"
+    lstrip_blocks: true
+    trim_blocks: true
+    mode: '0755'
+
+- name: Print the template in "/var/tmp/ansible_run_{{ opid }}/pe_update_sdp.conf"
+  when: verb == "update_sdp_mesh"
+  ansible.builtin.template:
+    src: "routers/{{ subscription.router.vendor }}/pe_update_sdp.j2"
+    dest: "/var/tmp/ansible_run_{{ opid }}/pe_update_sdp.conf"
+    lstrip_blocks: true
+    trim_blocks: true
+    mode: '0755'
+  delegate_to: localhost
+
+- name: Print the template in "/var/tmp/ansible_run_{{ opid }}/delete_default_static_routes.conf"
+  when: verb == "delete_default_routes"
+  ansible.builtin.template:
+    src: "routers/{{ subscription.router.vendor }}/router/delete_default_static_routes.j2"
+    dest: "/var/tmp/ansible_run_{{ opid }}/delete_default_static_routes.conf"
+    lstrip_blocks: true
+    trim_blocks: true
+    mode: '0755'
+  delegate_to: localhost
+
+- name: Set back ansible_host to target terminal server if needed
+  when:
+    subscription.router.router_access_via_ts | ansible.builtin.bool
+  ansible.builtin.set_fact:
+    ansible_host: "{{ subscription.router.router_site.site_ts_address }}"
+    ansible_connection: netconf
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/tasks/configure_isis_overload.yaml b/geant/gap_ansible/roles/promote_p_to_pe/tasks/configure_isis_overload.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6b37deb703982954e030efd352d35cf3174243a5
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/tasks/configure_isis_overload.yaml
@@ -0,0 +1,9 @@
+- name: Deploy ISIS overload on "{{ inventory_hostname }}" [AND COMMIT][NOKIA]
+  geant.gap_ansible.nokia_netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ subscription.router.vendor }}/router/isis_overload.j2') }}"
+    commit: true
+    commit_comment: "{{ commit_comment }}"
+  diff: true
+  check_mode: false
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/tasks/deploy.yaml b/geant/gap_ansible/roles/promote_p_to_pe/tasks/deploy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..dbae83ee229ad12d4e0d68f717ccaa92aa391079
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/tasks/deploy.yaml
@@ -0,0 +1,115 @@
+- name: Deploy PE base_config on "{{ inventory_hostname }}" [CHECK ONLY][NOKIA]
+  when: >-
+      dry_run | ansible.builtin.bool
+      and verb == "deploy_pe_base_config"
+  geant.gap_ansible.nokia_netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ subscription.router.vendor }}/pe_base_config.j2') }}"
+    commit: true
+    validate: true
+  diff: true
+  register: output
+  check_mode: true
+
+- name: Deploy PE base VPRNs on "{{ inventory_hostname }}" [CHECK ONLY][NOKIA]
+  when: >-
+      dry_run | ansible.builtin.bool
+      and verb == "deploy_routing_instances"
+  geant.gap_ansible.nokia_netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ subscription.router.vendor }}/pe_base_vprn.j2') }}"
+    commit: true
+    validate: true
+  diff: true
+  register: output
+  check_mode: true
+
+- name: Deploy SDP mesh on "{{ inventory_hostname }}" [CHECK ONLY][NOKIA]
+  when: >-
+      dry_run | ansible.builtin.bool
+      and verb == "update_sdp_mesh"
+  geant.gap_ansible.nokia_netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ subscription.router.vendor }}/pe_update_sdp.j2') }}"
+    commit: true
+    validate: true
+  diff: true
+  register: output
+  check_mode: true
+
+- name: Delete default routes on "{{ inventory_hostname }}" [CHECK ONLY][NOKIA]
+  when: >-
+      dry_run | ansible.builtin.bool
+      and verb == "delete_default_routes"
+  geant.gap_ansible.nokia_netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ subscription.router.vendor }}/router/delete_default_static_routes.j2') }}"
+    commit: true
+    validate: true
+  diff: true
+  register: output
+  check_mode: true
+
+# - name: Fail if there is any diff
+#   ansible.builtin.fail:
+#     msg: Base config drift detected!!!
+#   when: >
+#     output.changed | ansible.builtin.bool
+#     and
+#     is_verification_workflow | ansible.builtin.bool
+
+- name: Deploy base_config on "{{ inventory_hostname }}" [AND COMMIT][NOKIA]
+  when: >-
+      not (dry_run | ansible.builtin.bool) and
+      verb == "deploy_pe_base_config"
+  geant.gap_ansible.nokia_netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ subscription.router.vendor }}/pe_base_config.j2') }}"
+    commit: true
+    commit_comment: "{{ commit_comment }}"
+  diff: true
+  check_mode: false
+
+- name: Deploy PE base VPRNs on "{{ inventory_hostname }}" [AND COMMIT][NOKIA]
+  when: >-
+      not (dry_run | ansible.builtin.bool) and
+      verb == "deploy_routing_instances"
+  geant.gap_ansible.nokia_netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ subscription.router.vendor }}/pe_base_vprn.j2') }}"
+    commit: true
+    commit_comment: "{{ commit_comment }}"
+  diff: true
+  check_mode: false
+
+- name: Deploy updated SDP mesh on "{{ inventory_hostname }}" [AND COMMIT][NOKIA]
+  when: >-
+      not (dry_run | ansible.builtin.bool) and
+      verb == "update_sdp_mesh"
+  geant.gap_ansible.nokia_netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ subscription.router.vendor }}/pe_update_sdp.j2') }}"
+    commit: true
+    commit_comment: "{{ commit_comment }}"
+  diff: true
+  check_mode: false
+
+- name: Delete default routes on "{{ inventory_hostname }}" [AND COMMIT][NOKIA]
+  when: >-
+      not (dry_run | ansible.builtin.bool)
+      and verb == "delete_default_routes"
+  geant.gap_ansible.nokia_netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ subscription.router.vendor }}/router/delete_default_static_routes.j2') }}"
+    commit: true
+    commit_comment: "{{ commit_comment }}"
+  diff: true
+  check_mode: false
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/tasks/main.yml b/geant/gap_ansible/roles/promote_p_to_pe/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d7a7208af17663f62cc072d8ff04a0bd56cef407
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/tasks/main.yml
@@ -0,0 +1,64 @@
+---
+# tasks file for P to PE
+- 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: Import routers variables
+  ansible.builtin.include_vars:
+    dir: /opt/ansible_inventory/group_vars/routers
+
+- name: Import variables from 'all'
+  ansible.builtin.include_vars:
+    dir: /opt/ansible_inventory/group_vars/all
+
+- name: Set ansible_host to terminal server when router is offline
+  when: subscription.router.router_access_via_ts | ansible.builtin.bool
+  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
+  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: 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: Include ISIS overload tasks
+  when: verb in ['set_isis_overload', 'remove_isis_overload']
+  ansible.builtin.include_tasks: configure_isis_overload.yaml
+
+- name: Include templates compilation
+  when: verb in [ 'deploy_pe_base_config', 'update_sdp_mesh' , 'deploy_routing_instances', 'delete_default_routes' ]
+  ansible.builtin.include_tasks: compile.yaml
+
+- name: Include deploy if selected
+  when: verb in [ 'deploy_pe_base_config', 'update_sdp_mesh', 'deploy_routing_instances', 'delete_default_routes' ]
+  ansible.builtin.include_tasks: deploy.yaml
+
+- name: Check VPRNs
+  when: verb == "check_base_ris"
+  loop: "{{ pe_vprns }}"
+  loop_control:
+    loop_var: vprn
+  ansible.builtin.include_tasks: check_routing_instances.yaml
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/tasks/merge_variables.yaml b/geant/gap_ansible/roles/promote_p_to_pe/tasks/merge_variables.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7ad3d7a9af5d8676b2415826f1b8d97e025ea9e2
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/tasks/merge_variables.yaml
@@ -0,0 +1,39 @@
+#
+# Preparation of PE-specific vars. E.g. PE CPM filters are extension of P CPM filters.
+#
+- name: Merge Nokia P CPM filters
+  ansible.builtin.set_fact:
+    cpm_filters: "{{ lookup('community.general.merge_variables', 'cpmf__to_merge', pattern_type='suffix') }}"
+
+- name: Prepare PE-specific base config vars
+  when: verb == "deploy_pe_base_config"
+  block:
+    - name: Merge Nokia PE additional CPM filters
+      ansible.builtin.set_fact:
+        pe_cpm: "{{ lookup('community.general.merge_variables', 'cpm_pe__to_merge') }}"
+
+    - name: Combine P and PE CPM filters
+      ansible.builtin.set_fact:
+        cpm_filters: "{{ [cpm_filters, pe_cpm] | community.general.lists_mergeby('family',
+                                                                                  list_merge='append') }}"
+    - name: Combine P and PE prefix-lists
+      ansible.builtin.set_fact:
+        nokia_prefix_lists: "{{ [nokia_prefix_lists, nokia_pe_prefix_lists] | community.general.lists_mergeby('name',
+                                                                                              list_merge='append') }}"
+
+    - name: Select SDP params for l2ciruit-type
+      ansible.builtin.set_fact:
+        sdp_type: "{{ (sdp_types | selectattr('id', 'equalto', '1'))[0] }}"
+
+- name: Prepare PE-specific base config vars
+  when: verb == "deploy_routing_instances"
+  block:
+    - name: Combine P and PE prefix-lists
+      ansible.builtin.set_fact:
+        nokia_prefix_lists: "{{ [nokia_prefix_lists, nokia_pe_prefix_lists, nokia_pe_ias_prefix_lists] | community.general.lists_mergeby('name',
+                                                                                              list_merge='append') }}"
+
+- name: Select SDP params for l2ciruit (epipe) type
+  when: verb == "update_sdp_mesh"
+  ansible.builtin.set_fact:
+    sdp_type: "{{ (sdp_types | selectattr('id', 'equalto', '1'))[0] }}"
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/cflowd.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/cflowd.j2
new file mode 100644
index 0000000000000000000000000000000000000000..ef8dcc9feaa4c0f5bb8e225f3e5e546dc432b375
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/cflowd.j2
@@ -0,0 +1,29 @@
+<cflowd 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" alu:operation="replace">
+    <cache-size>{{ cflowd.basic.cache_size }}</cache-size>
+    <enhanced-distribution>{{ cflowd.basic.enhanced_distribution }}</enhanced-distribution>
+    <overflow>{{ cflowd.basic.overflow }}</overflow>
+    <template-retransmit>{{ cflowd.basic.template_retransmit }}</template-retransmit>
+    <active-flow-timeout>{{ cflowd.basic.active_flow_timeout }}</active-flow-timeout>
+    <inactive-flow-timeout>{{ cflowd.basic.inactive_flow_timeout }}</inactive-flow-timeout>
+    {% if cflowd.sample_profiles is defined %}
+      {% for profile in cflowd.sample_profiles %}
+    <sample-profile>
+        <profile-id>{{ profile.id }}</profile-id>
+        <sample-rate>{{ profile.sample_rate }}</sample-rate>
+        <metering-process>{{ profile.metering_process }}</metering-process>
+    </sample-profile>
+      {% endfor %}
+    {% endif %}
+    {% if cflowd.collectors is defined %}
+      {% for collector in cflowd.collectors %}
+    <collector>
+        <ip-address>{{ collector.ip }}</ip-address>
+        <port>{{ collector.port }}</port>
+        <description>{{ collector.description }}</description>
+        <template-set>{{ collector.template_set }}</template-set>
+        <version>{{ collector.version }}</version>
+    </collector>
+      {% endfor %}
+    {% endif %}
+</cflowd>
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filter_log.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filter_log.j2
new file mode 100644
index 0000000000000000000000000000000000000000..7ab3675a89a19a00aa2ff97342c90e8969fa8e11
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filter_log.j2
@@ -0,0 +1,18 @@
+
+<filter 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_filter_logs is defined %}
+      {% for log in pe_filter_logs %}
+    <log alu:operation="replace">
+        <log-id>{{ log.id }}</log-id>
+        <description>{{ log.description }}</description>
+        <destination>
+          {% if log.destination == 'syslog' %}
+            <syslog>
+                <name>1</name>
+            </syslog>
+          {% endif %}
+        </destination>
+    </log>
+      {% endfor %}
+    {% endif %}
+</filter>
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/cpm_filters.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/cpm_filters.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f7a35874dadee962cf9b5440db091dfba84de7f6
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/cpm_filters.j2
@@ -0,0 +1,12 @@
+{% with is_cpm_filter=true, filters=cpm_filters %}
+{% include "filters/port_list_definitions.j2" %}
+
+<system>
+  <security>
+    <cpm-filter 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">
+      <default-action>{{ cpm_filter_policy.default_action }}</default-action>
+        {% include "filters/fw_filters.j2" %}
+    </cpm-filter>
+{% endwith %}
+  </security>
+</system>
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/fw_filters.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/fw_filters.j2
new file mode 100644
index 0000000000000000000000000000000000000000..4b804948c8cd8419f5c45cbe29e2be24986b861d
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/fw_filters.j2
@@ -0,0 +1,248 @@
+{# Template is meant to be called from either gen_filters.j2 or cmp_filters.j2 #}
+{% for filter in filters %}
+  {% if filter.family == "ipv4" %}
+        <ip-filter alu:operation="replace">
+  {% elif filter.family == "ipv6" %}
+        <ipv6-filter alu:operation="replace">
+  {% endif %}
+  {% if not is_cpm_filter %}
+        <filter-name>{{ filter.name }}</filter-name>
+  {% endif %}
+  {% if filter.offset is defined %}
+    {% set ns3 = namespace(entry_id = filter.offset | int) %}
+  {% else %}
+    {% set ns3 = namespace(entry_id = 10 | int) %}
+  {% endif %}
+  {% if is_cpm_filter %}
+        <admin-state>{{ filter.admin_state }}</admin-state>
+  {% endif %}
+  {% for term in filter.terms %}
+    {% if term.offset is defined %}
+      {% set ns3 = namespace(entry_id = term.offset | int) %}
+    {% endif %}
+    {% if term.from is not defined %}
+          <entry>
+            <entry-id>{{ ns3.entry_id }}</entry-id>
+            <description>{{ term.name }}</description>
+            {% if term.log is defined %}
+            <log>{{ term.log }}</log>
+            {% endif %}
+            <action>
+                <{{term.action}}></{{term.action}}>
+            </action>
+          </entry>
+    {% endif %}
+
+    {% if term.from is defined %}
+  {# This is the case for TCP_ESTABLISHED #}
+      {% if term.from.protocol is defined and term.from.protocol == "tcp" and term.from.tcp_flag is defined %}
+          <entry>
+            <entry-id>{{ ns3.entry_id }}</entry-id>
+            <description>{{ term.name }}</description>
+            {% if term.log is defined %}
+            <log>{{ term.log }}</log>
+            {% endif %}
+            <match>
+              {% if filter.family == "ipv4" %}
+              <protocol>{{ term.from.protocol }}</protocol>
+              {% else %}
+              <next-header>{{ term.from.protocol }}</next-header>
+              {% endif %}
+              <tcp-flags>
+                <{{ term.from.tcp_flag }}>true</{{ term.from.tcp_flag }}>
+              </tcp-flags>
+            </match>
+            <action>
+              <{{ term.action }}></{{ term.action }}>
+            </action>
+          </entry>
+        {% set ns3.entry_id = ns3.entry_id + 10 %}
+      {% endif %}
+      {# This is to cover CPM-ipv6 ND case where dst_prefix_list is defined, but not src_prefix_list #}
+      {%  if term.from.protocol is defined and term.from.protocol == "ipv6-icmp" and term.from.dst_prefix_list is defined %}
+        {% for dst_prefix_list_item in term.from.dst_prefix_list %}
+          <entry>
+            <entry-id>{{ ns3.entry_id }}</entry-id>
+            <description>{{ term.name }}</description>
+            {% if term.log is defined %}
+            <log>{{ term.log }}</log>
+            {% endif %}
+            <match>
+              <next-header>{{ term.from.protocol }}</next-header>
+              <dst-ip>
+              <ipv6-prefix-list>{{term.from.dst_prefix_list[loop.index0]}}</ipv6-prefix-list>
+              </dst-ip>
+            </match>
+            <action>
+              <{{ term.action }}></{{ term.action }}>
+            </action>
+          </entry>
+        {% set ns3.entry_id = ns3.entry_id + 10 %}
+          {% endfor %}
+      {% endif %}
+      {# Generic ICMP filters with ICMP types #}
+      {% if term.from.protocol is defined and (term.from.protocol == "icmp" or term.from.protocol == "ipv6-icmp") %}
+        {% if term.from.icmp_types is defined %}
+          {% for icmp_type in term.from.icmp_types %}
+          <entry>
+            <entry-id>{{ ns3.entry_id }}</entry-id>
+            <description>{{ term.name }}</description>
+            {% if term.log is defined %}
+            <log>{{ term.log }}</log>
+            {% endif %}
+            <match>
+                  {% if filter.family == "ipv4" %}
+              <protocol>{{ term.from.protocol }}</protocol>
+                  {% else %}
+              <next-header>{{ term.from.protocol }}</next-header>
+                  {% endif %}
+                <icmp>
+                  <type>{{ icmp_type }}</type>
+                </icmp>
+            </match>
+            <action>
+              <{{ term.action }}></{{ term.action }}>
+            </action>
+          </entry>
+        {% set ns3.entry_id = ns3.entry_id + 10 %}
+          {% endfor %}
+        {% endif %}
+      {% endif %}
+      {# Case when only need to match on protocol, e.g. PIM #}
+        {% if term.from.protocol is defined and term.from.protocol in ['pim', '58'] %}
+          <entry>
+            <entry-id>{{ ns3.entry_id }}</entry-id>
+            <description>{{ term.name }}</description>
+            {% if term.log is defined %}
+            <log>{{ term.log }}</log>
+            {% endif %}
+            <match>
+                  {% if filter.family == "ipv4" %}
+              <protocol>{{ term.from.protocol }}</protocol>
+                  {% else %}
+              <next-header>{{ term.from.protocol }}</next-header>
+                  {% endif %}
+            </match>
+            <action>
+              <{{ term.action }}></{{ term.action }}>
+            </action>
+          </entry>
+        {% set ns3.entry_id = ns3.entry_id + 10 %}
+      {% endif %}
+      {# Case when both src_prefix_list and dst_prefix_list are defined #}
+      {% if term.from.src_prefix_list is defined %}
+        {% for src_prefix_list_item in term.from.src_prefix_list%}
+          {% set src_index = loop.index0 %}
+          {% if term.from.dst_prefix_list is defined %}
+            {% for dst_prefix_list_item in term.from.dst_prefix_list %}
+          <entry>
+            <entry-id>{{ ns3.entry_id }}</entry-id>
+            <description>{{ term.name }}</description>
+            {% if term.log is defined %}
+            <log>{{ term.log }}</log>
+            {% endif %}
+            <match>
+              {% if term.from.protocol is defined %}
+                {% if filter.family == "ipv4" %}
+              <protocol>{{term.from.protocol}}</protocol>
+                {% else %}
+              <next-header>{{ term.from.protocol }}</next-header>
+                {% endif %}
+              {% endif %}
+            {% include 'filters/port_list_entries.j2' %}
+              <src-ip>
+                {% if filter.family == "ipv4" %}
+                <ip-prefix-list>{{term.from.src_prefix_list[src_index]}}</ip-prefix-list>
+                {% else %}
+                <ipv6-prefix-list>{{term.from.src_prefix_list[src_index]}}</ipv6-prefix-list>
+                {% endif %}
+              </src-ip>
+              <dst-ip>
+                {% if filter.family == "ipv4" %}
+                <ip-prefix-list>{{term.from.dst_prefix_list[loop.index0]}}</ip-prefix-list>
+                {% else %}
+                <ipv6-prefix-list>{{term.from.dst_prefix_list[loop.index0]}}</ipv6-prefix-list>
+                {% endif %}
+              </dst-ip>
+            </match>
+            {% set ns3.entry_id = ns3.entry_id + 10 %}
+            <action>
+                <{{term.action}}></{{term.action}}>
+            </action>
+          </entry>
+            {% endfor %}
+          {% else %}
+{# This is the case of CPM-filters, where destination prefix is not defined #}
+          <entry>
+            <entry-id> {{ ns3.entry_id }} </entry-id>
+            <description>{{ term.name }}</description>
+            {% if term.log is defined %}
+            <log>{{ term.log }}</log>
+            {% endif %}
+            <match>
+            {% if term.from.protocol is defined %}
+                {% if filter.family == "ipv4" %}
+              <protocol>{{term.from.protocol}}</protocol>
+                {% else %}
+              <next-header>{{ term.from.protocol }}</next-header>
+                {% endif %}
+            {% endif %}
+            {% include 'filters/port_list_entries.j2' %}
+              <src-ip>
+                {% if filter.family == "ipv4" %}
+                <ip-prefix-list>{{term.from.src_prefix_list[src_index]}}</ip-prefix-list>
+                {% else %}
+                <ipv6-prefix-list>{{term.from.src_prefix_list[src_index]}}</ipv6-prefix-list>
+                {% endif %}
+              </src-ip>
+            </match>
+            {% set ns3.entry_id = ns3.entry_id + 10 %}
+            <action>
+                <{{term.action}}></{{term.action}}>
+            </action>
+          </entry>
+          {% endif %}
+        {% endfor %}
+      {% endif %}
+      {# Case where only DST prefix list is defined #}
+      {% if term.from.dst_prefix_list is defined %}
+        {% for dst_prefix_list_item in term.from.dst_prefix_list %}
+          <entry>
+            <entry-id>{{ ns3.entry_id }}</entry-id>
+            <description>{{ term.name }}</description>
+            {% if term.log is defined %}
+            <log>{{ term.log }}</log>
+            {% endif %}
+            <match>
+              {% if term.from.protocol is defined %}
+                {% if filter.family == "ipv4" %}
+              <protocol>{{term.from.protocol}}</protocol>
+                {% else %}
+              <next-header>{{ term.from.protocol }}</next-header>
+                {% endif %}
+              {% endif %}
+            {% include 'filters/port_list_entries.j2' %}
+              <dst-ip>
+                {% if filter.family == "ipv4" %}
+                <ip-prefix-list>{{term.from.dst_prefix_list[loop.index0]}}</ip-prefix-list>
+                {% else %}
+                <ipv6-prefix-list>{{term.from.dst_prefix_list[loop.index0]}}</ipv6-prefix-list>
+                {% endif %}
+              </dst-ip>
+            </match>
+            {% set ns3.entry_id = ns3.entry_id + 10 %}
+            <action>
+                <{{term.action}}></{{term.action}}>
+            </action>
+          </entry>
+        {% endfor %}
+      {% endif %}
+    {% endif %}
+  {% endfor %}
+{# Terms end #}
+  {% if filter.family == "ipv4" %}
+        </ip-filter>
+  {% elif filter.family == "ipv6" %}
+        </ipv6-filter>
+  {% endif %}
+{% endfor %}
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/gen_filters.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/gen_filters.j2
new file mode 100644
index 0000000000000000000000000000000000000000..b25f975f8641f0f5056b545b2e8fc35bbb594b3e
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/gen_filters.j2
@@ -0,0 +1,9 @@
+{# This template takes care of configuring connectors and breakouts #}
+
+{% with is_cpm_filter=False, filters=gen_filters %}
+{% include "filters/port_list_definitions.j2" %}
+<filter 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 "filters/fw_filters.j2" %}
+</filter>
+{% endwith %}
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/port_list_definitions.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/port_list_definitions.j2
new file mode 100644
index 0000000000000000000000000000000000000000..34c35ad8a8badead9cdc176196453a482ee03b37
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/port_list_definitions.j2
@@ -0,0 +1,66 @@
+{# This template takes care of configuring connectors and breakouts #}
+<filter 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">
+  <match-list>
+  {% for filter in filters %}
+    {% for term in filter.terms %}
+    {% if term.from.port is defined and term.from.port.__class__.__name__ == 'list'%}
+    <port-list>
+      <port-list-name>{{filter.name}}-{{term.name}}-PORTS</port-list-name>
+      {%for port in term.from.port %}
+        <port>
+            <value>{{port}}</value>
+        </port>
+      {% endfor %}
+    </port-list>
+    {% endif %}
+    {% if term.from.src_port is defined and term.from.src_port.__class__.__name__ == 'list'%}
+    <port-list>
+      <port-list-name>{{filter.name}}-{{term.name}}-SRC_PORTS</port-list-name>
+      {%for port in term.from.src_port %}
+        <port>
+          <value>{{port}}</value>
+        </port>
+      {% endfor %}
+    </port-list>
+    {% endif %}
+    {% if term.from.dst_port is defined and term.from.dst_port.__class__.__name__ == 'list'%}
+    <port-list>
+      <port-list-name>{{filter.name}}-{{term.name}}-DST_PORTS</port-list-name>
+      {%for port in term.from.dst_port %}
+        <port>
+          <value>{{port}}</value>
+        </port>
+      {% endfor %}
+      </port-list>
+    {% endif %}
+    {% if term.from.port_range is defined %}
+    <port-list>
+      <port-list-name>{{filter.name}}-{{term.name}}-PORT_RANGE</port-list-name>
+      <range>
+        <start>{{ term.from.port_range.start }}</start>
+        <end>{{ term.from.port_range.end }}</end>
+      </range>
+    </port-list>
+    {% endif %}
+    {% if term.from.src_port_range is defined %}
+    <port-list>
+      <port-list-name>{{filter.name}}-{{term.name}}-SRC_PORT_RANGE</port-list-name>
+      <range>
+        <start>{{ term.from.src_port_range.start }}</start>
+        <end>{{ term.from.src_port_range.end }}</end>
+      </range>
+    </port-list>
+    {% endif %}
+    {% if term.from.dst_port_range is defined %}
+    <port-list>
+      <port-list-name>{{filter.name}}-{{term.name}}-DST_PORT_RANGE</port-list-name>
+      <range>
+        <start>{{ term.from.dst_port_range.start }}</start>
+        <end>{{ term.from.dst_port_range.end }}</end>
+      </range>
+    </port-list>
+    {% endif %}
+    {% endfor %}
+  {% endfor %}
+  </match-list>
+</filter>
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/port_list_entries.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/port_list_entries.j2
new file mode 100644
index 0000000000000000000000000000000000000000..4f3352655be583736e811c58adb6546645841bdd
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/filters/port_list_entries.j2
@@ -0,0 +1,48 @@
+{#This is the case it's a port-list #}
+{% if term.from.port is defined and term.from.port.__class__.__name__ == 'list'%}
+  <port>
+      <port-list>{{filter.name}}-{{term.name}}-PORTS</port-list>
+  </port>
+{% endif %}
+{% if term.from.src_port is defined and term.from.src_port.__class__.__name__ == 'list'%}
+  <src-port>
+      <port-list>{{filter.name}}-{{term.name}}-SRC_PORTS</port-list>
+  </src-port>
+{% endif %}
+{% if term.from.dst_port is defined and term.from.dst_port.__class__.__name__ == 'list'%}
+  <dst-port>
+      <port-list>{{filter.name}}-{{term.name}}-DST_PORTS</port-list>
+  </dst-port>
+{% endif %}
+{#This is the case it's a single port #}
+{% if term.from.port is defined and term.from.port.__class__.__name__ != 'list'%}
+  <port>
+      <eq>{{term.from.port}}</eq>
+  </port>
+{% endif %}
+{% if term.from.src_port is defined and term.from.src_port.__class__.__name__ != 'list'%}
+  <src-port>
+      <eq>{{term.from.src_port}}</eq>
+  </src-port>
+{% endif %}
+{% if term.from.dst_port is defined and term.from.dst_port.__class__.__name__ != 'list'%}
+  <dst-port>
+    <eq>{{term.from.dst_port}}</eq>
+  </dst-port>
+{% endif %}
+ {# Port range #}
+ {% if term.from.port_range is defined %}
+  <port>
+      <port-list>{{filter.name}}-{{term.name}}-PORT_RANGE</port-list>
+  </port>
+{% endif %}
+{% if term.from.src_port_range is defined %}
+  <src-port>
+      <port-list>{{filter.name}}-{{term.name}}-SRC_PORT_RANGE</port-list>
+  </src-port>
+{% endif %}
+{% if term.from.dst_port_range is defined %}
+  <dst-port>
+      <port-list>{{filter.name}}-{{term.name}}-DST_PORT_RANGE</port-list>
+  </dst-port>
+{% endif %}
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/ip_prefix_list.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/ip_prefix_list.j2
new file mode 120000
index 0000000000000000000000000000000000000000..c9c4c6dfa9e199351407e24a82bd99c5001abb39
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/ip_prefix_list.j2
@@ -0,0 +1 @@
+../../../../base_config/templates/routers/nokia/ip_prefix_list.j2
\ No newline at end of file
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/pe_base_config.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/pe_base_config.j2
new file mode 100644
index 0000000000000000000000000000000000000000..c3c587bbd0008dcb27c8486f2220b49c9f79f87e
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/pe_base_config.j2
@@ -0,0 +1,11 @@
+<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">
+       {% include 'filter_log.j2' %}
+       {% include 'ip_prefix_list.j2' %}
+       {% include 'filters/cpm_filters.j2' %}
+       {% include 'policy_options/policy_options.j2' %}
+       {% include 'cflowd.j2' %}
+       {% include 'router/router_base.j2' %}
+       {% include 'sdp_mesh.j2' %}
+   </configure>
+</config>
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/pe_base_vprn.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/pe_base_vprn.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f8467b331828c1df32a19da5ba3d008a6a4126a1
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/pe_base_vprn.j2
@@ -0,0 +1,5 @@
+<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">
+       {% include 'service_vprn.j2' %}
+   </configure>
+</config>
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/pe_update_sdp.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/pe_update_sdp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..5ffc1bde7a724b448f845b747718a4c5bdcb13ba
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/pe_update_sdp.j2
@@ -0,0 +1,5 @@
+<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">
+       {% include 'sdp_mesh.j2' %}
+   </configure>
+</config>
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/as_paths.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/as_paths.j2
new file mode 100644
index 0000000000000000000000000000000000000000..fadb9c5b01a5b69c57cd13877f0c9b4d86dea62a
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/as_paths.j2
@@ -0,0 +1,6 @@
+    {% for as_path in as_paths_obj %}
+    <as-path alu:operation="replace">
+      <name>{{ as_path.name }}</name>
+      <expression>{{ as_path.expression}}</expression>
+    </as-path>
+    {% endfor %}
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/communities.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/communities.j2
new file mode 100644
index 0000000000000000000000000000000000000000..631ddacf38c264784038e969961227f8a09f186c
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/communities.j2
@@ -0,0 +1,8 @@
+    {% for community in communities_obj %}
+    <community alu:operation="replace">
+      <name>{{ community.name }}</name>
+        <member>
+          <member>{{ community.member }}</member>
+        </member>
+    </community>
+    {% endfor %}
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/policy_options.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/policy_options.j2
new file mode 100644
index 0000000000000000000000000000000000000000..bb4790c644b63d38021a989f56870478946505b2
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/policy_options.j2
@@ -0,0 +1,30 @@
+  <policy-options 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 nokia_po_prefix_lists is defined %}
+      {% with prefix_lists_obj=nokia_po_prefix_lists %}
+      {% include 'policy_options/prefix_lists.j2' %}
+      {% endwith %}
+    {% endif %}
+  
+    {# Communities #}
+    {% if nokia_po_communities is defined %}
+      {% with communities_obj=nokia_po_communities %}
+      {% include 'policy_options/communities.j2' %}
+      {% endwith %}
+    {% endif %}
+  
+    {# AS paths #}
+    {% if nokia_po_as_paths is defined %}
+      {% with as_paths_obj=nokia_po_as_paths %}
+      {% include 'policy_options/as_paths.j2' %}
+      {% endwith %}
+    {% endif %}
+  
+  {# Policy statements #}
+    {% if nokia_po_policy_statements is defined %}
+      {% with policy_obj=nokia_po_policy_statements %}
+      {% include 'policy_options/policy_statements.j2' %}
+      {% endwith %}
+    {% endif %}
+  
+  </policy-options>
+  
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/policy_statements.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/policy_statements.j2
new file mode 100644
index 0000000000000000000000000000000000000000..95126f78838203c9bce99458cee179a0a87f5f75
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/policy_statements.j2
@@ -0,0 +1,66 @@
+    {% for pol in policy_obj %}
+    <policy-statement alu:operation="replace">
+      <name>{{ pol.name }}</name>
+      <entry-type>{{ pol.entry_type }}</entry-type>
+      {% for entry in pol.entries %}
+        {% if pol.entry_type == 'named' %}
+      <named-entry>
+        {% endif %}
+        <entry-name>{{ entry.name }}</entry-name>
+        {% if entry.from is defined %}
+        <from>
+          {% if entry.from.as_path is defined %}
+            <as-path>
+            {% if entry.from.as_path.name is defined %}
+                <name>{{ entry.from.as_path.name }}</name>
+            {% endif %}
+            {% if entry.from.as_path.length is defined %}
+                <length>
+                      <value>{{ entry.from.as_path.length }}</value>
+                </length>
+            {% endif %}
+            </as-path>
+          {% endif %}
+          {% if entry.from.prefix_list is defined %}
+            {% for pl in entry.from.prefix_list %}
+            <prefix-list>{{ pl }}</prefix-list>
+            {% endfor %}
+          {% endif %}
+          {% if entry.from.community is defined %}
+            <community>
+                <name>{{ entry.from.community }}</name>
+            </community>
+          {% endif %}
+          {% if entry.from.origin_validation_state is defined %}
+            <origin-validation-state>{{ entry.from.origin_validation_state }}</origin-validation-state>
+          {% endif %}
+          {% if entry.from.protocol is defined %}
+            {% for proto in entry.from.protocol %}
+            <protocol>
+                  <name>{{ proto }}</name>
+            </protocol>
+            {% endfor %}
+          {% endif %}
+        </from>
+        {% endif %}
+        <action>
+            <action-type>{{ entry.action_type }}</action-type>
+          {% if entry.action is defined %}
+            {% for action_item in entry.action %}
+              {% for act_k, act_v in action_item.items() %}
+                {% if act_k == "community_add" %}
+            <community>
+                <add>{{ act_v }}</add>
+            </community>
+                {% else %}
+            <{{ act_k | replace("_", "-") }}>{{ act_v }}</{{act_k  | replace("_", "-") }}>
+                {% endif %}
+              {% endfor %}
+            {% endfor %}
+          {% endif %}
+        </action>
+      </named-entry>
+      {% endfor %}
+    </policy-statement>
+
+    {% endfor %}
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/prefix_lists.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/prefix_lists.j2
new file mode 100644
index 0000000000000000000000000000000000000000..507986e60983c0445d2110328584695d67b2b70a
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/policy_options/prefix_lists.j2
@@ -0,0 +1,15 @@
+    {% for prefix_list in prefix_lists_obj %}
+    <prefix-list alu:operation="replace">
+        <name>{{ prefix_list.name }}</name>
+        {% for prefix in prefix_list.prefixes %}
+        <prefix>
+          <ip-prefix>{{ prefix.ip }}</ip-prefix>
+          <type>{{ prefix.type }}</type>
+          {% if prefix.type == 'range' %}
+          <start-length>{{ prefix.range_start_length }}</start-length>
+          <end-length>{{ prefix.range_end_length }}</end-length>
+          {% endif %}
+        </prefix>
+        {% endfor %}
+    </prefix-list>
+    {% endfor %}
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/base_bgp.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/base_bgp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..e6159684954581f2b05213097bd0afac75037c8f
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/base_bgp.j2
@@ -0,0 +1,36 @@
+            <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">
+              {% if pe_bgp_base.best_path_selection is defined %}
+                <best-path-selection>
+                {% for bps in pe_bgp_base.best_path_selection %}
+                    <{{ bps }}>true</{{ bps }}>
+                {% endfor %}
+                </best-path-selection>
+              {% endif %}
+              {% if pe_bgp_base.error_handling is defined %}
+                <error-handling>
+                    <{{ pe_bgp_base.error_handling }}>true</{{ pe_bgp_base.error_handling }}>
+                </error-handling>
+              {% endif %}
+              {% if pe_bgp_base.next_hop_resolution.shortcut_tunnel is defined %}
+                <next-hop-resolution>
+                    <shortcut-tunnel>
+                    {% for nhr in pe_bgp_base.next_hop_resolution.shortcut_tunnel %}
+                        <family>
+                            <family-type>{{ nhr.type }}</family-type>
+                            <resolution-filter>
+                                <{{ nhr.resolution_filter }}>true</{{ nhr.resolution_filter }}>
+                            </resolution-filter>
+                        </family>
+                    {% endfor %}
+                    </shortcut-tunnel>
+                </next-hop-resolution>
+              {% endif %}
+{% with bgp_obj=pe_bgp_tools %}
+        {% include "router/bgp_group.j2" %}
+        {% include "router/bgp_neighbor.j2" %}
+{% endwith %}
+{% with bgp_obj=pe_bgp_internal %}
+        {% include "router/bgp_group.j2" %}
+{% endwith %}
+            </bgp>
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/base_static_routes.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/base_static_routes.j2
new file mode 100644
index 0000000000000000000000000000000000000000..437738fe2a78567504cfd1bfbe69d4605ab9dfb7
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/base_static_routes.j2
@@ -0,0 +1,6 @@
+          <static-routes 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">
+          {% with static_routes_obj=nokia_pe_static_routes %}
+          {% include 'router/static_routes.j2' %}
+          {% endwith %}
+          </static-routes>
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/bgp_group.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/bgp_group.j2
new file mode 100644
index 0000000000000000000000000000000000000000..fad9162f1e2e78301f789d2a5ba8f00292cac42f
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/bgp_group.j2
@@ -0,0 +1,81 @@
+                {% for group in bgp_obj.groups %}
+                <group alu:operation="replace">
+                    <group-name>{{ group.name }}</group-name>
+                    <admin-state>{{ group.admin_state | default('enable') }}</admin-state>
+                    {% if group.nhs is defined %}
+                    <next-hop-self>{{ group.nhs }}</next-hop-self>
+                    {% endif %}
+                    <type>{{ group.type }}</type>
+                    {% if group.bfd_liveness is defined %}
+                    <bfd-liveness>{{ group.bfd_liveness }}</bfd-liveness>
+                    {% endif %}
+                    {% if group.ebgp_default_reject is defined %}
+                    <ebgp-default-reject-policy>
+                      {% for pk, pv in group.ebgp_default_reject.items() %}
+                        <{{ pk }}>{{ pv }}</{{ pk }}>
+                      {% endfor %}
+                    </ebgp-default-reject-policy>
+                    {% endif %}
+                    {% if group.peer_as is defined %}
+                    <peer-as>{{ group.peer_as }}</peer-as>
+                    {% endif %}
+                    {% if group.local_as is defined %}
+                    <local-as>
+                        <as-number>{{ group.local_as }}</as-number>
+                        {% if group.prepend_global_as is defined %}
+                        <prepend-global-as>{{ group.prepend_global_as }}</prepend-global-as>
+                        {% endif %}
+                    </local-as>
+                    {% endif %}
+                    {% if group.capability_neg is defined %}
+                    <capability-negotiation>{{ group.capability_neg }}</capability-negotiation>
+                    {% endif %}
+                    {% if bgp_group_context != 'vprn' %}
+                      {% if (group.local_address is defined) and group.local_address == 'ipv4' %}
+                    <local-address>{{ lo_ipv4_address }}</local-address>
+                      {% elif (group.local_address is defined) and group.local_address == 'ipv6' %}
+                    <local-address>{{ lo_ipv6_address }}</local-address>
+                      {% endif %}
+                    {% endif %}
+                    {% if group.hold_time is defined %}
+                    <hold-time>
+                        <seconds>{{ group.hold_time }}</seconds>
+                    </hold-time>
+                    {% endif %}
+                    {% if group.origin_validattion is defined %}
+                    <origin-validation>
+                      {% for ov in group.origin_validattion %}
+                      <{{ ov }}>true</{{ ov }}>
+                      {% endfor %}
+                    </origin-validation>
+                    {% endif %}
+                    {% if group.send_communities is defined %}
+                    <send-communities>
+                      {% for sc_k, sc_v in group.send_communities.items() %}
+                      <{{ sc_k }}>{{ sc_v }}</{{ sc_k }}>
+                      {% endfor %}
+                    </send-communities>
+                    {% endif %}
+                    {% if group.families is defined %}
+                    <family>
+                      {% for family in group.families %}
+                        <{{ family }}>true</{{ family }}>
+                      {% endfor %}
+                    </family>
+                    {% endif %}
+                    {% if group.policies.import is defined %}
+                    <import>
+                        {% for imp_pol in group.policies.import %}
+                        <policy>{{ imp_pol }}</policy>
+                        {% endfor %}
+                    </import>
+                    {% endif %}
+                    {% if group.policies.export is defined %}
+                    <export>
+                        {% for exp_pol in group.policies.export %}
+                        <policy>{{ exp_pol }}</policy>
+                        {% endfor %}
+                    </export>
+                    {% endif %}
+                </group>
+                {% endfor %}
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/bgp_neighbor.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/bgp_neighbor.j2
new file mode 100644
index 0000000000000000000000000000000000000000..12bf86f8dacf9a58ce21291381ee6b0c2faaf8fe
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/bgp_neighbor.j2
@@ -0,0 +1,29 @@
+                {% for neighbor in bgp_obj.neighbors %}
+                <neighbor alu:operation="replace">
+                    <ip-address>{{ neighbor.ip }}</ip-address>
+                    <description>{{ neighbor.description }}</description>
+                    <group>{{ neighbor.group }}</group>
+                    {% if neighbor.families is defined %}
+                    <family>
+                      {% for family in neighbor.families %}
+                        <{{ family }}>true</{{ family }}>
+                      {% endfor %}
+                    </family>
+                    {% endif %}
+                    {% if neighbor.policies.import is defined %}
+                    <import>
+                        {% for imp_pol in neighbor.policies.import %}
+                        <policy>{{ imp_pol }}</policy>
+                        {% endfor %}
+                    </import>
+                    {% endif %}
+                    {% if neighbor.policies.export is defined %}
+                    <export>
+                        {% for exp_pol in neighbor.policies.export %}
+                        <policy>{{ exp_pol }}</policy>
+                        {% endfor %}
+                    </export>
+                    {% endif %}
+                </neighbor>
+                {% endfor %}
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/delete_default_static_routes.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/delete_default_static_routes.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f3d8d46b24117664afda6c35adc295394dcab927
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/delete_default_static_routes.j2
@@ -0,0 +1,15 @@
+<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">
+        <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>
+          <static-routes 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">
+          {% for route in nokia_static_routes %}
+            <route alu:operation="delete">
+              <ip-prefix>{{ route.ip_prefix }}</ip-prefix>
+              <route-type>{{ route.route_type }}</route-type>
+            </route>
+          {% endfor %}
+          </static-routes>
+        </router>
+   </configure>
+</config>
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/flowspec.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/flowspec.j2
new file mode 100644
index 0000000000000000000000000000000000000000..e1f40f15591b33f7c89caf5c99ceac6783e1c172
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/flowspec.j2
@@ -0,0 +1,6 @@
+
+  <flowspec alu:operation="replace">
+      <ip-filter-max-size>{{ nokia_flowspec.ip_filter_max_size }}</ip-filter-max-size>
+      <ipv6-filter-max-size>{{ nokia_flowspec.ipv6_filter_max_size }}</ipv6-filter-max-size>
+  </flowspec>
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/isis_overload.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/isis_overload.j2
new file mode 100644
index 0000000000000000000000000000000000000000..c8d177abbfd4d3d0ab9fac1493535533e03fb2af
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/isis_overload.j2
@@ -0,0 +1,18 @@
+<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">
+        <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>
+              <isis>
+                <isis-instance>0</isis-instance>
+              {% if verb == 'set_isis_overload' %}
+                <overload 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">
+                </overload>
+              {% endif %}
+              {% if verb == 'remove_isis_overload' %}
+                <overload 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" alu:operation="delete">
+                </overload>
+              {% endif %}
+              </isis>
+        </router>
+   </configure>
+</config>
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/ldp.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/ldp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..8a312b716654e67525ec4dfde5448d33e2d3fa24
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/ldp.j2
@@ -0,0 +1,7 @@
+        <ldp 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">
+            <admin-state>enable</admin-state>
+            <targeted-session>
+                <sdp-auto-targeted-session>true</sdp-auto-targeted-session>
+            </targeted-session>
+        </ldp>
+ 
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/router_base.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/router_base.j2
new file mode 100644
index 0000000000000000000000000000000000000000..ce792e856c3f5eb97ac854e2e5870a47f37ce0f0
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/router_base.j2
@@ -0,0 +1,13 @@
+        <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>
+            {% with static_routes_obj=nokia_pe_static_routes %}
+            {% include 'router/static_routes.j2' %}
+            {% endwith %}
+            {% with bgp_group_context='bgp_base' %}
+            {% include 'router/base_bgp.j2' %}
+            {% endwith %}
+            {% include 'router/flowspec.j2' %}
+            {% include 'router/ldp.j2' %}
+            {% include 'router/rpki.j2' %}
+       </router>
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/rpki.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/rpki.j2
new file mode 100644
index 0000000000000000000000000000000000000000..ce18ab742af4c1b4b1608f54f8006aaa0327dbf7
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/rpki.j2
@@ -0,0 +1,13 @@
+  <origin-validation 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">
+    {% for validator in pe_rpki.validators %}
+      <rpki-session alu:operation="replace">
+          <ip-address>{{ validator.ip }}</ip-address>
+          <admin-state>{{ validator.admin_state | default('enable') }}</admin-state>
+          <connect-retry>{{ validator.connect_retry }}</connect-retry>
+          <local-address>{{ lo_ipv4_address }}</local-address>
+          <port>{{ validator.port }}</port>
+          <stale-time>{{ validator.stale_time }}</stale-time>
+      </rpki-session>
+    {% endfor %}
+  </origin-validation>
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/static_routes.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/static_routes.j2
new file mode 100644
index 0000000000000000000000000000000000000000..1c1d8f4b68394be625b67cef8261ed0b16278036
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/static_routes.j2
@@ -0,0 +1,38 @@
+          <static-routes 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">
+            {% for route in static_routes_obj %}
+              <route alu:operation="replace">
+                <ip-prefix>{{ route.ip_prefix }}</ip-prefix>
+                <route-type>{{ route.route_type }}</route-type>
+                {% if route.indirect is defined %}
+                  {% for ir in route.indirect %}
+                <indirect>
+                  <ip-address>{{ ir.next_hop }}</ip-address>
+                  <admin-state>{{ ir.admin_state }}</admin-state>
+                    {% if ir.description is defined %}
+                  <description>{{ ir.description }}</description>
+                    {% endif %}
+                    {% if ir.preference is defined %}
+                   <preference>{{ ir.preference }}</preference>
+                    {% endif %}
+                </indirect>
+                  {% endfor %}
+                {% endif %}
+                {# Blackhole #}
+                {% if route.blackhole is defined %}
+                <blackhole>
+                    <admin-state>{{ route.blackhole.admin_state }}</admin-state>
+                    {% if route.blackhole.description is defined %}
+                    <description>{{ route.blackhole.description }}</description>
+                    {% endif %}
+                </blackhole>
+                {% endif %}
+                {# Communities #}
+                {% if route.communities is defined %}
+                  {% for community in route.communities %}
+                <community>{{ community }}</community>
+                  {% endfor %}
+                {% endif %}
+              </route>
+            {% endfor %}
+          </static-routes>
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/vprn.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/vprn.j2
new file mode 100644
index 0000000000000000000000000000000000000000..c6c049644f15d58cb914a40b34030c847ad0402c
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/router/vprn.j2
@@ -0,0 +1,58 @@
+    {% for vprn in pe_vprns %}
+    <vprn alu:operation="replace">
+        <service-name>{{ vprn.name }}</service-name>
+        <admin-state>{{ vprn.admin_state | default('enable') }}</admin-state>
+        {% if vprn.description is defined %}
+        <description>{{ vprn.description }}</description>
+        {% endif %}
+        <service-id>{{ vprn.service_id }}</service-id>
+        <customer>{{ vprn.customer_id }}</customer>
+        <autonomous-system>{{ vprn.asn }}</autonomous-system>
+        <bgp-ipvpn>
+            <mpls>
+                <admin-state>enable</admin-state>
+                <route-distinguisher>{{ vprn.bgp_ipvpn.mpls.rd }}</route-distinguisher>
+                <vrf-target>
+                    <community>{{ vprn.bgp_ipvpn.mpls.target }}</community>
+                </vrf-target>
+                <auto-bind-tunnel>
+                    <resolution>{{ vprn.bgp_ipvpn.mpls.auto_bind_tunnel.resolution }}</resolution>
+                    <resolution-filter>
+                        <{{ vprn.bgp_ipvpn.mpls.auto_bind_tunnel.resolution_filter }}>true</{{ vprn.bgp_ipvpn.mpls.auto_bind_tunnel.resolution_filter }}>
+                    </resolution-filter>
+                </auto-bind-tunnel>
+            </mpls>
+        </bgp-ipvpn>
+        <bgp>
+            {% if vprn.bgp.families is defined %}
+            <family>
+              {% for fam in vprn.bgp.families %}
+                <{{ fam }}>true</{{ fam }}>
+              {% endfor %}
+            </family>
+            {% endif %}
+            {% if vprn.bgp.best_path_selection is defined %}
+            <best-path-selection>
+              {% for bps in vprn.bgp.best_path_selection %}
+                <{{ bps }}>true</{{ bps }}>
+              {% endfor %}
+            </best-path-selection>
+            {% endif %}
+            {% with bgp_obj=vprn.bgp, bgp_group_context='vprn' %}
+            {% include 'router/bgp_group.j2' %}
+            {% endwith %}
+        </bgp>
+        {% if vprn.static_routes is defined %}
+        {% with static_routes_obj=vprn.static_routes %}
+        {% include 'router/static_routes.j2' %}
+        {% endwith %}
+        {% endif %}
+        {% if vprn.flowspec is defined %}
+        <flowspec>
+            <ip-filter-max-size>{{ vprn.flowspec.ip_filter_max_size }}</ip-filter-max-size>
+            <ipv6-filter-max-size>{{ vprn.flowspec.ipv6_filter_max_size }}</ipv6-filter-max-size>
+        </flowspec>
+        {% endif %}
+    </vprn>
+    {% endfor %}
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/sdp_mesh.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/sdp_mesh.j2
new file mode 100644
index 0000000000000000000000000000000000000000..df67f22d70e11a8c7d89687b0837fa2049d00e8b
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/sdp_mesh.j2
@@ -0,0 +1,20 @@
+    <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">
+            {% 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>
+            <sdp-id>{{ sdp_id }}</sdp-id>
+            <admin-state>enable</admin-state>
+            <description>SDP_{{ sdp_id }}</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 %}
+    </service>
+    
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/service_vprn.j2 b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/service_vprn.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d14800d4014fa130678e26489f8bf03b1ae08afe
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/templates/routers/nokia/service_vprn.j2
@@ -0,0 +1,12 @@
+
+<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">
+    <md-auto-id>
+        <service-id-range alu:operation="replace">
+            <start>{{ pe_service.md_auto_id.service_id_range.start | default('10001') }}</start>
+            <end>{{ pe_service.md_auto_id.service_id_range.end | default('19999') }}</end>
+        </service-id-range>
+    </md-auto-id>
+    {% include 'router/vprn.j2' %}
+</service>
+    {% include 'ip_prefix_list.j2' %}
+
diff --git a/geant/gap_ansible/roles/promote_p_to_pe/vars/main.yml b/geant/gap_ansible/roles/promote_p_to_pe/vars/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..33851df6536e31c0e07305d65540f3300be84706
--- /dev/null
+++ b/geant/gap_ansible/roles/promote_p_to_pe/vars/main.yml
@@ -0,0 +1,14 @@
+---
+# vars file for promote_p_to_pe
+dry_run: true
+verbs:
+  - set_isis_overload # Drain traffic to/from the router by setting ISIS overload
+  - remove_isis_overload # Remove overload bit from ISIS config
+  - deploy_pe_base_config # Deploy PE-specific base config on top of existing P-only config
+  - delete_default_routes # Delete default static routes configured as part P base-config
+  - deploy_routing_instances # Deploy standard PE VPRNs
+  - update_sdp_mesh # Upadate SDP mesh on other Nokia PE routers with this promoted router
+  - check_base_ris # Check BGP summary for base VPRNs
+
+lo_ipv4_address: "{{ subscription.router.router_lo_ipv4_address }}"
+lo_ipv6_address: "{{ subscription.router.router_lo_ipv6_address }}"