diff --git a/.ansible-lint b/.ansible-lint
new file mode 100644
index 0000000000000000000000000000000000000000..72e7dc9ca688165414ad6e005569f51c175b934a
--- /dev/null
+++ b/.ansible-lint
@@ -0,0 +1,5 @@
+skip_list:
+  - 'name[template]' # Jinja templates should only be at the end of ‘name’.
+  - 'yaml[line-length]' # Line too long (162 > 160 characters)
+  - 'no-free-form' # Avoid using free-form when calling module actions. (ansible.builtin.set_fact)
+  - 'role-name[path]' # Avoid using paths when importing roles.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c18dd8d83ceed1806b50b0aaa46beb7e335fff13
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+__pycache__/
diff --git a/.install.sh b/.install.sh
new file mode 100644
index 0000000000000000000000000000000000000000..c510b520b79bafe7043e94ed6819c07d525fb608
--- /dev/null
+++ b/.install.sh
@@ -0,0 +1,5 @@
+# here we should put everything related with installing Ansible: 
+- pip dependencies
+- ansible dependencies
+- config files
+### TODO
diff --git a/ansible.cfg b/ansible.cfg
index b0f9a1dc314fd9300fa60064e751688fefc9eed3..d094b3f7fd60fd9b8069dbe70ea805fa3ee3b738 100644
--- a/ansible.cfg
+++ b/ansible.cfg
@@ -1,2 +1,6 @@
 [defaults]
-nocolor=true
+#nocolor=true
+host_key_checking=false
+display_skipped_hosts = false
+#stdout_callback = actionable
+
diff --git a/base_config.yaml b/base_config.yaml
index d7062f7d3d75fe44f2efc1fd043d2aba8877a9da..b25f689a1b18b3c6242a673837f85319269615d1 100644
--- a/base_config.yaml
+++ b/base_config.yaml
@@ -1,13 +1,7 @@
 - name: Manage base config playbook
   hosts: all
-  gather_facts: yes
+  gather_facts: false
   remote_user: admin
-  vars_files:
-    - /opt/ansible_inventory/group_vars/junos/device_access.yaml
   roles:
     - Juniper.junos
     - roles/base_config
-  tasks: 
-    - name: Import routers variables
-      ansible.builtin.include_vars: 
-        dir:  /opt/ansible_inventory/group_vars/routers
diff --git a/hosts.yaml b/hosts.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..aa5eef44b6de81ba304fd9e7ac56cbba3e686d74
--- /dev/null
+++ b/hosts.yaml
@@ -0,0 +1,4 @@
+all:
+  hosts:
+    rt2.hlv01.nl.geant.net:
+    rt2.pi01.it.geant.net:
diff --git a/iptrunks.yaml b/iptrunks.yaml
index ac72485be715a234f7e31baa4f9d0a0280517743..977aa57f090e6197029215ae5ecf5dee442e60f9 100644
--- a/iptrunks.yaml
+++ b/iptrunks.yaml
@@ -1,5 +1,11 @@
-- name: Manage base config playbook
-  hosts: staging_routers
+- name: Manage iptrunks playbook
+  hosts: all
+  remote_user: admin
+  gather_facts: false
   roles:
     - Juniper.junos
     - roles/iptrunks
+  tasks:
+    #  - name: Import routers variables
+    #    ansible.builtin.include_vars:
+    #      dir:  /opt/ansible_inventory/group_vars/routers
diff --git a/iptrunks_checks.yaml b/iptrunks_checks.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..040dda4f2b8ca48f53da118ac1aaaf74dbe86a95
--- /dev/null
+++ b/iptrunks_checks.yaml
@@ -0,0 +1,8 @@
+- name: Manage iptrunks checks playbook
+  hosts: all
+  remote_user: admin
+  vars_files:
+    - /opt/ansible_inventory/group_vars/junos/router_access.yaml
+  roles:
+    - Juniper.junos
+    - roles/iptrunks_checks
diff --git a/roles/base_config/meta/main.yml b/roles/base_config/meta/main.yml
index c572acc9f8b466bea50f2799b0ca1956418b862c..bccfe25460a93a85f7b355234663759e221c5e2d 100644
--- a/roles/base_config/meta/main.yml
+++ b/roles/base_config/meta/main.yml
@@ -1,7 +1,7 @@
 galaxy_info:
-  author: your name
-  description: your role description
-  company: your company (optional)
+  author: Simone Spinelli for GOAT
+  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
@@ -14,9 +14,9 @@ galaxy_info:
   # - GPL-3.0-only
   # - Apache-2.0
   # - CC-BY-4.0
-  license: license (GPL-2.0-or-later, MIT, etc)
+  license: license BSD-3-Clause
 
-  min_ansible_version: 2.1
+  min_ansible_version: '2.10'
 
   # If this a Container Enabled role, provide the minimum Ansible Container version.
   # min_ansible_container_version:
@@ -39,7 +39,8 @@ galaxy_info:
   #   - 7
   #   - 99.99
 
-  galaxy_tags: []
+  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.
@@ -48,5 +49,7 @@ galaxy_info:
     #       Maximum 20 tags per role.
 
 dependencies: []
+
+  # - role: "Juniper.junos"
   # List your role dependencies here, one per line. Be sure to remove the '[]' above,
   # if you add dependencies to this list.
diff --git a/roles/base_config/tasks/compile_base_config.yaml b/roles/base_config/tasks/compile_base_config.yaml
index 01c439e33b8cde7ba4051b36aefee448c74c9ade..3e4c722bf1839f10a7b9131f592bd7f556e855c6 100644
--- a/roles/base_config/tasks/compile_base_config.yaml
+++ b/roles/base_config/tasks/compile_base_config.yaml
@@ -1,21 +1,40 @@
+- name: Merge the variables
+  ansible.builtin.include_tasks: merge_variables.yaml
+
+- name: Fix ISO_system_id for Nokia (step1)
+  ansible.builtin.set_fact:
+    lo_iso_address_as_a_list: "{{ wfo_router.router.router_lo_iso_address.split('.') }}"
+
+- name: Fix ISO_system_id for Nokia (step2)
+  ansible.builtin.set_fact:
+    iso_system_id: "{{ lo_iso_address_as_a_list[3:6] | join('.') }}"
+
+- name: Set ansible host to localhost to compile config when router is offline
+  ansible.builtin.set_fact:
+    ansible_host: "localhost"
+    ansible_connection: local
+  when:
+    ( wfo_router.router.router_access_via_ts | ansible.builtin.bool ) is true
+
 - name: Create a folder for all the things
   ansible.builtin.file:
-    path: "/var/tmp/ansible_run_{{opid}}"
+    path: "/var/tmp/ansible_run_{{ opid }}"
     state: directory
     mode: '0755'
+  delegate_to: localhost
 
-- name: Merge the variables
-  include_tasks: merge_variables.yaml
-
-- name: Print the template in "/var/tmp/ansible_run_{{opid}}/{{mytemplates.template_name}}.conf"
-  template:
-     src: "{{ mytemplates.template_path }}"
-     dest: "/var/tmp/ansible_run_{{opid}}/{{mytemplates.template_name}}.conf"
-     lstrip_blocks: yes
-     trim_blocks: yes
+- name: Print the template in "/var/tmp/ansible_run_{{ opid }}/base_config.conf"
+  ansible.builtin.template:
+    src: "routers/{{ wfo_router.router.router_vendor }}/base_config.j2"
+    dest: "/var/tmp/ansible_run_{{ opid }}/base_config.conf"
+    lstrip_blocks: true
+    trim_blocks: true
+    mode: '0755'
   delegate_to: localhost
 
-- name: Send message to syslog
-  syslogger:
-    msg: "[[{{opid}}]] {{mytemplates.template_name}} compiled"
-    log_pid: true
+- name: Set back ansible_host to target terminal server
+  ansible.builtin.set_fact:
+    ansible_host: "{{ wfo_router.router.router_site.site_ts_address }}"
+    ansible_connection: netconf
+  when:
+    ( wfo_router.router.router_access_via_ts | ansible.builtin.bool ) is true
diff --git a/roles/base_config/tasks/deploy_base_config.yaml b/roles/base_config/tasks/deploy_base_config.yaml
index cc51ee96c37b6fe04f207950b19d4749c25b6bc4..b6fc6bcacf9f06975d36de1136ce14dc2579863e 100644
--- a/roles/base_config/tasks/deploy_base_config.yaml
+++ b/roles/base_config/tasks/deploy_base_config.yaml
@@ -1,45 +1,68 @@
-- name: Send end of operation in syslog
-  syslogger:
-    msg: "[[{{opid}}]] deploy base config on {{inventory_hostname}} dry run"
-    log_pid: true
-
-- name: Deploy base_config on "{{inventory_hostname}}" [CHECK ONLY]
+- name: Deploy base_config on "{{ inventory_hostname }}" [CHECK ONLY][Juniper]
   juniper_junos_config:
     load: 'replace'
-    src: "/var/tmp/ansible_run_{{opid}}/{{mytemplates.template_name}}.conf"
+    src: "/var/tmp/ansible_run_{{ opid }}/{{ mytemplates.template_name }}.conf"
     format: text
     config_mode: "private"
-    check: yes
-    commit: no
+    check: true
+    commit: false
   register: response
-  when: verb == "deploy" and dryrun == "True"
-
-#- name: Show diff for dry run
-#  debug:
-#    msg: "{{ response }}"
-#  when: verb == "deploy" and dryrun == "True"
+  when: >
+    verb == "deploy" and
+    ( dry_run | ansible.builtin.bool ) is true and
+    wfo_router.router.router_vendor == "juniper"
 
-- name: Send end of operation in syslog
-  syslogger:
-    msg: "[[{{opid}}]] deploy base config on {{inventory_hostname}} for real "
-    log_pid: true
+- name: Show diff for dry run
+  ansible.builtin.debug:
+    msg: "{{ response }}"
+  when: >
+    verb == "deploy" and
+    ( dry_run | ansible.builtin.bool ) is true and
+    wfo_router.router.router_vendor == "juniper"
 
-- name: Deploy base_config on "{{inventory_hostname}}" [AND COMMIT]
+- name: Deploy base_config on "{{ inventory_hostname }}" [AND COMMIT][Juniper]
   juniper_junos_config:
     load: 'replace'
-    src: "/var/tmp/ansible_run_{{opid}}/{{mytemplates.template_name}}.conf"
+    src: "/var/tmp/ansible_run_{{ opid }}/{{ mytemplates.template_name }}.conf"
     format: text
     config_mode: "private"
     comment: "{{ commit_comment }}"
   register: response
-  when: verb == "deploy" and dryrun == "False"
+  when: >
+    verb == "deploy" and
+    ( dry_run | ansible.builtin.bool ) is false and
+    wfo_router.router.router_vendor == "juniper"
 
 - name: Show diff
-  debug:
+  ansible.builtin.debug:
     msg: "{{ response }}"
-  when: verb == "deploy" and dryrun == "False"
+  when: >
+    verb == "deploy" and
+    ( dry_run | ansible.builtin.bool ) is false and
+    wfo_router.router.router_vendor == "juniper"
+
+- name: Deploy base_config on "{{ inventory_hostname }}" [CHECK ONLY][NOKIA]
+  ansible.netcommon.netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ wfo_router.router.router_vendor }}/base_config.j2') }}"
+    commit: true
+  diff: true
+  check_mode: true
+  when: >
+    verb == "deploy" and
+    ( dry_run | ansible.builtin.bool ) is true and
+    wfo_router.router.router_vendor == "nokia"
 
-- name: Send end of operation in syslog
-  syslogger:
-    msg: "[[{{opid}}]] Ending operations "
-    log_pid: true
+- name: Deploy base_config on "{{ inventory_hostname }}" [AND COMMIT][NOKIA]
+  ansible.netcommon.netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', 'routers/{{ wfo_router.router.router_vendor }}/base_config.j2') }}"
+    commit: true
+  diff: true
+  check_mode: false
+  when: >
+    verb == "deploy" and
+    ( dry_run | ansible.builtin.bool ) is false and
+    wfo_router.router.router_vendor == "nokia"
diff --git a/roles/base_config/tasks/main.yml b/roles/base_config/tasks/main.yml
index 2a9471d4f64fd8fd0f0d21c1c9089f811cc716bb..46a6581f8819ed9f71285c6b7d051a41913bc838 100644
--- a/roles/base_config/tasks/main.yml
+++ b/roles/base_config/tasks/main.yml
@@ -1,33 +1,60 @@
 ---
 # tasks file for base_config
 - name: Print the usage
-  debug:
-    msg: 
-    - "Allowed verbs: 'compile' and 'deploy'. Use: -e 'verb=$verb'."
+  ansible.builtin.debug:
+    msg:
+      - "Allowed verbs: 'compile' and 'deploy'. Use: -e 'verb=$verb'."
   when: (verb is not defined) or (verb not in verbs)
 
-- meta: end_play
+- name: Set ansible_host to terminal server when router is offline
+  ansible.legacy.set_fact:
+    ansible_host: "{{ wfo_router.router.router_site.site_ts_address }}"
+    ansible_port: "{{ wfo_router.router.router_ts_port }}"
+  when:
+    ( wfo_router.router.router_access_via_ts | ansible.builtin.bool ) is true
+
+- name: Set variable to connect to nokia
+  ansible.legacy.set_fact:
+    ansible_network_os: nokia.sros.md
+    ansible_connection: netconf
+  when:
+    wfo_router.router.router_vendor == "nokia"
+
+- name: Set variables for connecting to Junos
+  ansible.legacy.set_fact:
+    ansible_network_os: junos
+    ansible_connection: netconf
+  when:
+    wfo_router.router.router_vendor == "juniper"
+
+- name: Fail if arguments are missing
+  ansible.legacy.meta: end_play
   when: (verb is not defined) or (verb not in verbs)
 
-- name: Gather_facts
+- name: Get the facts from Juniper router
   junipernetworks.junos.junos_facts:
     gather_subset: all
+  when:
+    wfo_router.router.router_vendor == "juniper"
 
 - name: Import routers variables
   ansible.builtin.include_vars:
-    dir:  /opt/ansible_inventory/group_vars/routers
+    dir: /opt/ansible_inventory/group_vars/routers
 
-- set_fact:
+- name: Generate an ID for this run
+  ansible.legacy.set_fact:
     opid: "{{ lookup('community.general.random_string', length=18, special=false) }}"
     config_is_different: "False"
 
+
 - name: Print the ID
-  debug:
-    msg: "{{opid}}"
+  ansible.builtin.debug:
+    msg: "{{ opid }}"
 
-- include: compile_base_config.yaml
+- name: Include always compiling phase
+  ansible.builtin.include_tasks: compile_base_config.yaml
   when: verb in verbs
 
-- include: deploy_base_config.yaml
+- name: Include deploy if selected
+  ansible.builtin.include_tasks: deploy_base_config.yaml
   when: verb == "deploy"
-
diff --git a/roles/base_config/tasks/merge_variables.yaml b/roles/base_config/tasks/merge_variables.yaml
index 235072f5ab9eafaf7e6a44f866c1747388f4a1c3..5ae56c3c5107554e68b574055d42b84627146385 100644
--- a/roles/base_config/tasks/merge_variables.yaml
+++ b/roles/base_config/tasks/merge_variables.yaml
@@ -1,17 +1,17 @@
-## This playbook is used to merge variables that are splitted in group and host vars. 
-# Currently, this is valid for: 
+## This playbook is used to merge variables that are splitted in group and host vars.
+# Currently, this is valid for:
 # system_login_users
 # system_login_classes
 # snmp_communities
 #
-# This playbook should be included in any other playbook that makes use of these variables. 
+# This playbook should be included in any other playbook that makes use of these variables.
 #
 - name: Merge system login user vars
   merge_vars:
     suffix_to_merge: users__to_merge
     merged_var_name: system_login_users
     expected_type: 'list'
-  
+
 - name: Merge system login classes vars
   merge_vars:
     suffix_to_merge: classes__to_merge
diff --git a/roles/base_config/templates/routers/juniper/base_config.j2 b/roles/base_config/templates/routers/juniper/base_config.j2
new file mode 100644
index 0000000000000000000000000000000000000000..c9326bdea0d5eb935ca9c4c2cb0ae6bc8c4d3b86
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/base_config.j2
@@ -0,0 +1,28 @@
+{% include 'class_of_service.j2' %}
+
+{% include 'chassis.j2' %}
+{# #}
+{% include 'forwarding_options.j2' %}
+{#  #}
+{% include 'firewall.j2' %}
+{#  #}
+{% include 'groups.j2' %}
+{#  #}
+{% include 'interfaces.j2' %}
+{#  #}
+{% include 'policy_options.j2' %}
+{#  #}
+{% include 'policy_statements.j2' %}
+{#  #}
+{% include 'routing_options.j2' %}
+{#  #}
+{% include 'services.j2' %}
+{#  #}
+{% include 'snmp.j2' %}
+{#  #}
+{% include 'protocols/protocols_global.j2' %}
+
+{% include 'system/system_global.j2' %}
+
+
+{% include 'routing_instances.j2' %}
diff --git a/roles/base_config/templates/routers/juniper/chassis.j2 b/roles/base_config/templates/routers/juniper/chassis.j2
new file mode 100644
index 0000000000000000000000000000000000000000..842ed653e87b24944f7ba050ae38c52e62275363
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/chassis.j2
@@ -0,0 +1,97 @@
+replace: chassis {
+    dump-on-panic;
+    {% if ansible_net_has_2RE == true  %}
+    redundancy {
+        routing-engine 0 master;
+        routing-engine 1 backup;
+        failover {
+            on-loss-of-keepalives;
+            on-disk-failure;
+        }
+    {% if chassis_graceful_switchover_inactive is sameas true%}
+        inactive: graceful-switchover;
+    {% else %}
+        graceful-switchover;
+    {% endif %}
+    }
+    {% endif %}
+    routing-engine {
+        disk {
+            smart-check;
+        }
+    }
+    aggregated-devices {
+        ethernet {
+            device-count {{ chassis_aggredated_ethernet_count }};
+        }
+    }
+    {% if ansible_net_has_2RE == true %}
+        {% if chassis_fabric_rm is defined %}
+    fabric {
+        redundancy-mode {
+            {{ chassis_fabric_rm }};
+        }
+    }
+        {% endif %}
+    {% endif %}
+    {% if chassis_fpcs is defined %}
+    {% for fpc in chassis_fpcs %}
+    fpc {{ fpc.fpc_id }} {
+        {% if ( fpc.power is defined ) and ( fpc.power == "off" ) %}
+        power off;
+        {% else %}
+        {% for pic in fpc.pics %}
+        pic {{ pic.pic_id }} {
+        {% if pic.pic_mode is defined %}
+            pic-mode {{ pic.pic_mode }};
+        {% endif %}
+        {% if pic.tunnel_services is defined %}
+            tunnel-services {
+                bandwidth {{ pic.tunnel_services }};
+            }
+        {% endif %}
+        {% if pic.inline_services is defined %}
+            inline-services {
+                bandwidth {{ pic.inline_services }};
+            }
+        {% endif %}
+        {% if pic.ports is defined %}
+        {% for port in pic.ports %}
+            port {{ port.id }} {
+                speed {{ port.speed }};
+            }
+        {% endfor %}
+        {% endif %}
+        }
+        {% endfor %}
+        sampling-instance ipfx;
+        inline-services flex-flow-sizing ;
+        {% endif %}
+    }
+    {% endfor %}
+    {% else %}
+    {% for net_module in ansible_net_modules %}
+    {% if 'FPC' in net_module.name %}
+    {% set fpc_name_as_list = net_module.name.split(" ") %}
+    fpc {{ fpc_name_as_list[1] }} {
+        {% if fpc_name_as_list[1] is sameas "0" %}
+        pic 0 {
+              tunnel-services {
+                 bandwidth 10g;
+              }
+              inline-services {
+                 bandwidth 10g;
+              }
+        }
+        {% endif %}
+        sampling-instance ipfx;
+        inline-services flex-flow-sizing ;
+    }
+    {% endif %}
+    {% endfor %}
+    {% endif %}
+    {% if chassis_enhanced_ip is sameas true %}
+    network-services enhanced-ip;
+    {% endif %}
+}
+
diff --git a/roles/base_config/templates/routers/juniper/class_of_service.j2 b/roles/base_config/templates/routers/juniper/class_of_service.j2
new file mode 100644
index 0000000000000000000000000000000000000000..5d656119e58064f57d9e9ff6f2eebaa0a303afa6
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/class_of_service.j2
@@ -0,0 +1,136 @@
+replace: class-of-service {
+   {% if cos_classifiers is defined %}
+   classifiers {
+      {% for classifier in cos_classifiers %}
+      {{ classifier.type }}  {{ classifier.name }} {
+          import {{ classifier.import }};
+          {% for forwarding_class in classifier.forwarding_classes %}
+          forwarding-class {{ forwarding_class.name}} {
+             loss-priority {{ forwarding_class.loss_priority }} code-points [{% for code_point in forwarding_class.code_points %} {{ code_point }} {% endfor %} ]; 
+          } 
+      {% endfor %}
+      }
+      {% endfor %}
+   }
+   {% else %}
+   {{ raise('ERROR: YOU HAVE NO CLASSIFIERS DEFINED')}}
+   {%endif %}
+   {% if cos_drop_profiles is defined %}
+   drop-profiles {
+      {% for drop_profile in cos_drop_profiles %}
+      {{ drop_profile.name }} {
+         interpolate {
+            fill-level [{% for fill_level in drop_profile.fill_levels %} {{ fill_level }} {% endfor %} ]; 
+            drop-probability [{% for drop_probability in drop_profile.drop_probabilities %} {{ drop_probability }} {% endfor %} ]; 
+         }
+      }
+      {% endfor %}
+   }
+   {% else %}
+   {{ raise('ERROR: YOU HAVE NO DROP-PROFILES DEFINED')}}
+   {%endif %}
+   {% if cos_forwarding_classes is defined %} 
+   forwarding-classes {
+
+   {% for fc in cos_forwarding_classes %}
+       class {{ fc.name }} queue-num {{ fc.queue_num }} priority {{ fc.priority }};
+   {% endfor %}
+   }
+   {% endif %}
+
+   {% if cos_interfaces is defined %} 
+   interfaces {
+      {% for interface in cos_interfaces %}
+      {{ interface.regex }} {
+            {% if interface.scheduler_map is defined %}
+            scheduler-map {{ interface.scheduler_map}};
+            {% endif %}
+	    unit * { 
+              classifiers {
+              {% for classifier in interface.classifiers %}
+	        {{ classifier.type }} {{ classifier.name }} ;
+	      {% endfor %}
+              }
+              {% if interface.rewrite_rules is defined %}
+              rewrite-rules {
+              {% for rr in interface.rewrite_rules %}
+	        {{ rr.type }} {{ rr.name }} protocol {{ rr.protocol}};
+	      {% endfor %}
+              }
+              {% endif %}
+            }
+      }    
+      {% endfor %}
+   }
+   {% else %}
+   {{ raise('ERROR: YOU HAVE NO INTERFACES  DEFINED')}}
+   {% endif %}
+   {% if cos_rewrite_rules is defined %} 
+   {% for rewrite_rule in cos_rewrite_rules %} 
+   rewrite-rules { 
+       {{ rewrite_rule.type }} {{ rewrite_rule.name }} {
+       import {{ rewrite_rule.import }}
+       {% if rewrite_rule.forwarding_classes is defined %}
+       {% for fc in rewrite_rule.forwarding_classes %}
+       forwarding-class {{ fc.name }} {
+           {% if fc.loss_priorities is defined %}
+           {% for lp in fc.loss_priorities %}
+           loss-priority {{ lp.type }} code-point {{ lp.code_point }};
+           {% endfor %}
+           {% endif %}
+       } 
+       {% endfor %}
+       {% endif %}
+       }
+   }
+   {% endfor %}
+   {% endif %}
+   {% if cos_scheduler_maps is defined %} 
+   scheduler-maps {
+      {% for scheduler_map in cos_scheduler_maps %}
+      {{ scheduler_map.name }} {
+            {% for mapping in scheduler_map.mappings %}
+               forwarding-class {{ mapping.class }} scheduler {{ mapping.scheduler }} ;
+            {% endfor %}
+      }
+      {% endfor %}
+   }
+   {% else %}
+   {{ raise('ERROR: YOU HAVE NO SCHEDULER-MAP  DEFINED')}}
+   {% endif %}
+   {% if cos_schedulers is defined %} 
+   schedulers {
+      {% for scheduler in cos_schedulers %}
+      {{ scheduler.name }} {
+	   {% if scheduler.transmit_rate.unit == "remainder" %}
+	   transmit-rate { 
+               remainder;
+	   }
+	   {% elif scheduler.transmit_rate.unit == "percent" %}
+	   transmit-rate percent {{ scheduler.transmit_rate.value }};
+	   {% elif scheduler.transmit_rate.unit == "rate" %}
+	   transmit-rate {{ scheduler.transmit_rate.value }};
+            {% else %}
+   {{ raise('ERROR: SCHEDULER TRANSMIT-RATE scheduler.transmit_rate.value NOT VALID')}}
+	   {% endif %}
+	   {% if ((scheduler.buffer_size.unit == "remainder") or (scheduler.buffer_size.unit == "shared")) %}
+            buffer-size {
+               {{ scheduler.buffer_size.unit }};
+            }
+	   {% elif ((scheduler.buffer_size.unit == "percent") or (scheduler.buffer_size.unit == "temporal")) %}
+            buffer-size {{ scheduler.buffer_size.unit }} {{ scheduler.buffer_size.value }};
+            {% else %}
+            {{ raise('ERROR: SCHEDULER TRANSMIT-RATE scheduler.buffer_size.value NOT VALID')}}
+            {% endif %}
+            priority {{ scheduler.priority }};
+            {% if scheduler.drop_profile_map is defined %}
+            drop-profile-map loss-priority {{ scheduler.drop_profile_map.loss_priority }} protocol {{ scheduler.drop_profile_map.protocol }} drop-profile {{ scheduler.drop_profile_map.drop_profile }};
+            {% endif %}
+      }
+      {% endfor %}
+   }
+   {% else %}
+   {{ raise('ERROR: YOU HAVE NO SCHEDULER  DEFINED')}}
+   {% endif %}
+}
+
diff --git a/roles/base_config/templates/routers/juniper/firewall.j2 b/roles/base_config/templates/routers/juniper/firewall.j2
new file mode 100644
index 0000000000000000000000000000000000000000..970686436ca5748fcf9b11024da947740fc40b99
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/firewall.j2
@@ -0,0 +1,77 @@
+
+{##}
+{#We should validate, but raise does not work :-( #}
+{% set supported_from = [ 'destination-address','destination-port','icmp-type','port','prefix-list','protocol','source-address','source-prefix-list','tcp-established' ] %}
+{% set supported_then = [ 'accept','policer','discard','reject' ] %}
+{##}
+
+firewall {
+{% for family, filters in firewall.items() %} 
+{% if family != "policer" %}
+    family {{ family }} {
+    {% for filter, filter_data in filters.items() %}
+replace: filter {{ filter }} {
+            {% if filter_data.options is defined %}
+            {{ filter_data.options }};
+            {% endif %}
+            {% for term in filter_data.terms %}
+            term {{ term.name }} {
+                {% if term.from is defined %}
+                from {
+                {% for from, from_data in term.from.items() %}
+                    {# Stuff that goes in line: like ports, protocols and similar#}
+                    {% if "tcp-established" in from %}
+                        tcp-established;
+                    {% elif ("port" in from) or ("protocol" in from) or ("icmp-type" in from) or ("next-header" in from) or ("hop-limit" in from)%}
+                        {% if (from_data is iterable) and (from_data is not string) %}
+                        {{ from }} [ {% for from_data_element in from_data %}{{ from_data_element }} {% endfor %} ];
+                        {% else %}
+                        {{ from }} {{ from_data }};
+                        {% endif %}
+                    {# Stuff that goes in a list: like addresses, prefix lists etc... #}
+                    {% else %}
+                        {{ from }} {
+                    {% for from_data_element in from_data %}
+                            {{ from_data_element }};
+                    {% endfor %}
+                        }
+                    {% endif %}
+                {% endfor %}
+                }
+                {% endif %}
+                then {
+                {% if (term.then is iterable) and (term.then is not string) %}
+                {% for then_action in term.then %}
+                    {% if then_action is not string %}
+                    {% for action, destination in then_action.items() %}
+                    {{ action }} {{ destination}};
+                    {% endfor %}
+                    {% else %}
+                    {{ then_action }};
+                    {% endif %}
+                {% endfor %}
+                {% else %}
+                    {{ term.then }};
+                {% endif %}
+                }
+            }
+            {% endfor %}
+        }
+    {% endfor %}
+    }
+{% else %}
+      {% for filter, filter_data in filters.items() %}
+replace:   policer {{ filter }} {
+          {% if filter_data.options is defined %}
+          {{ filter_data.options }}; 
+          {% endif %}
+          if-exceeding {
+              bandwidth-limit {{ filter_data.bandwidth_limit }}; 
+              burst-size-limit {{ filter_data.burst_size_limit }}; 
+          }
+          then discard; 
+      }
+      {% endfor %}
+{% endif %}
+{% endfor %}
+}
diff --git a/roles/base_config/templates/routers/juniper/forwarding_options.j2 b/roles/base_config/templates/routers/juniper/forwarding_options.j2
new file mode 100644
index 0000000000000000000000000000000000000000..61533386b92fc19c03d2f167ff0a4f3adfa7314b
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/forwarding_options.j2
@@ -0,0 +1,37 @@
+replace: forwarding-options {
+          sampling {
+              instance {
+                  ipfx {
+                      input {
+                          rate 300;
+                      }
+                    {% for family in forwarding_options_families %}
+                    family {{family.name}} {
+		      output {
+                      {% for server in forwarding_options_flow_servers %}
+                        flow-server {{ server.address }} {
+                          port {{ server.port}};
+		          version-ipfix {
+		            template {
+                              {{family.template}};
+                            }
+		          }
+		        }
+                      {% endfor %}
+                        inline-jflow {
+		          source-address {{ forwarding_options_inline_jflow.source_address }}
+		          flow-export-rate {{ forwarding_options_inline_jflow.flow_export_rate }}
+		        }
+		      }
+                  }
+                  {% endfor %}
+              }
+          }
+  }
+enhanced-hash-key {
+    family mpls {
+        ether-pseudowire zero-control-word;
+    }
+}
+no-hyper-mode;
+}
diff --git a/roles/base_config/templates/routers/juniper/groups.j2 b/roles/base_config/templates/routers/juniper/groups.j2
new file mode 100644
index 0000000000000000000000000000000000000000..b0dd58c89002cd8e5943a1b9e6b5ea08711078da
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/groups.j2
@@ -0,0 +1,76 @@
+{% set hostname_as_a_list= inventory_hostname.split('.')%}
+{% set short_hostname= hostname_as_a_list[:3] | join('.')%}
+replace: groups { 
+NO_TRAPS {
+    interfaces {
+        <*> {
+            unit <*> {
+                no-traps;
+            }
+        }
+    }
+}
+{% if ansible_net_has_2RE == true %}
+re0 {
+    system {
+        host-name {{ short_hostname }}.re0;
+    }
+    interfaces {
+        fxp0 {
+            description "PHY INFRASTRUCTURE MANAGEMENT | re0";
+            speed 1g;
+            link-mode full-duplex;
+            unit 0 {
+                family inet {
+                    address {{re0_fxp_ipv4address| default('172.16.254.3')}}/24;
+                }
+            }
+        }
+    }
+}
+re1 {
+    system {
+        host-name  {{ short_hostname }}.re1;
+    }
+    interfaces {
+        fxp0 {
+            description "PHY INFRASTRUCTURE MANAGEMENT | re1";
+            speed 1g;
+            link-mode full-duplex;
+            unit 0 {
+                family inet {
+                    address {{re1_fxp_ipv4address| default('172.16.254.4')}}/24;
+                }
+            }
+        }
+    }
+}
+{%endif%}
+
+load-balance-adaptive {
+    interfaces {
+        <ae*> {
+            aggregated-ether-options {
+                load-balance {
+                    adaptive;
+                }
+            }
+        }
+    }
+}
+
+}
+
+{% if ansible_net_has_2RE == true %}
+system {
+replace: apply-groups [ re0 re1 ];
+}
+interfaces {
+replace: apply-groups [ re0 re1 load-balance-adaptive ];
+}
+replace: apply-groups [ re0 re1 ];
+{%else%}
+interfaces {
+replace: apply-groups [ load-balance-adaptive ];
+}
+{%endif%}
diff --git a/roles/base_config/templates/routers/juniper/interfaces.j2 b/roles/base_config/templates/routers/juniper/interfaces.j2
new file mode 100644
index 0000000000000000000000000000000000000000..71da808392581340278abe4560d56d43197df2fa
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/interfaces.j2
@@ -0,0 +1,63 @@
+interfaces {
+replace: lo0 {
+    unit 0 {
+       family inet {
+           filter {
+               input ROUTER_access;
+           }
+           address {{lo_ipv4_address}}/32; 
+       }
+       family iso {
+           address {{ lo_iso_address }};
+       }
+       family inet6 {
+           filter {
+               input ROUTER_access_V6;
+           }
+           address {{lo_ipv6_address}}/128;
+       }
+    } 
+}
+replace: dsc {
+    unit 0 {
+        description "PHY INFRASTRUCTURE DISCARD | required for Multicast monitoring";
+        family inet {
+            address 192.0.2.112/32;
+        }
+    }
+}
+
+lt-0/0/0 {
+
+replace: unit 16 {
+        description "SRV_GLOBAL INFRASTRUCTURE ACCESS IAS SRF0000001 | BGP Peering - RE Side";
+        encapsulation ethernet;
+        peer-unit 61;
+        family inet {
+            filter {
+                input bone-in;
+                output bone-out;
+            }
+            address {{ lt_ipv4_network | ipaddr('net') | ipaddr('address')}}/31;
+        }
+        family inet6 {
+            filter {
+                input bone6-in;
+                output bone6-out;
+            }
+            address {{ lt_ipv6_network | ipaddr('net') | ipaddr('1') | ipaddr('address')}}/126;
+        }
+    }
+replace: unit 61 {
+        description "SRV_IAS INFRASTRUCTURE ACCESS GLOBAL SRF0000001 | BGP Peering - IAS Side";
+        encapsulation ethernet;
+        peer-unit 16;
+        family inet {
+            address {{ lt_ipv4_network | ipaddr('net') | ipaddr('1') | ipaddr('address')}}/31;
+        }
+        family inet6 {
+            address {{ lt_ipv6_network | ipaddr('net') | ipaddr('2') | ipaddr('address')}}/126;
+        }
+    }
+}
+}
diff --git a/roles/base_config/templates/routers/juniper/policy_options.j2 b/roles/base_config/templates/routers/juniper/policy_options.j2
new file mode 100644
index 0000000000000000000000000000000000000000..81b017d51cde43f8ca64de00df335d36837e1a54
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/policy_options.j2
@@ -0,0 +1,32 @@
+policy-options {
+    {% for config_item, value in po_memory_limits.items() %}
+    {{ config_item }} {
+        memory-limit {{value}};
+    }
+    {% endfor %}
+    {# prefix-lists #}
+    {% for prefixlist in po_prefixlists %}
+replace: prefix-list {{ prefixlist.name }} {
+    {% if prefixlist.prefixes is defined %}
+    {% for prefix in prefixlist.prefixes %}
+ {{ prefix }};
+    {% endfor %}
+    {% endif %}
+    {% if prefixlist.apply_path is defined %}
+ apply-path {{ prefixlist.apply_path }};
+    {% endif %}
+ }
+    {% endfor %}
+    {# communities #}
+    {% if po_communities is defined %}
+    {% for community in po_communities %}
+replace: community {{ community.name }} members {{ community.members }};
+    {% endfor %}
+    {% endif %}
+    {# as-path #}
+    {% if po_as_path is defined %}
+    {% for as_path in po_as_path %}
+replace: as-path {{ as_path.name }} {{ as_path.regex }};
+    {% endfor %}
+    {% endif %}
+}
diff --git a/roles/base_config/templates/routers/juniper/policy_statements.j2 b/roles/base_config/templates/routers/juniper/policy_statements.j2
new file mode 100644
index 0000000000000000000000000000000000000000..7c81e1d9bfef6f967412d31974651a27296fd6da
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/policy_statements.j2
@@ -0,0 +1,103 @@
+{# TODO: list of from and then keywords as Jinja set #}
+{% set FROM_ONE_LINER = ['community-count', 'route-filter', 'source-address-filter', 'family', 'source-class', 'validation-database'] %}
+
+policy-options {
+{% if po_communities is defined %}
+{% for community in po_communities %}
+replace: community {{ community.name }} members {{ community.members }};
+{% endfor %}
+{% endif %}
+
+{% if po_policy_statements is defined %}
+{% for ps, ps_data in po_policy_statements.items() -%}
+replace: policy-statement {{ ps }} {
+    {% if ps_data.terms is defined %}
+    {% for term in ps_data.terms -%}
+ term {{term.name}} {
+        {% if term.from is defined %}
+ from {
+            {% for from, from_data in term.from.items() -%}
+                {# TODO: check intersection of FROM_ONE_LINER and 'from' #}
+               {%- if ("community-count" in from) or ("route-filter" in from) or ("validation-database" in from) or ("family" in from) or ("source-class" in from) or ("source-address-filter" in from) or ("prefix-list" in from) %}
+                    {% for from_data_element in from_data %}
+    {{ from }} {{ from_data_element }};
+                    {% endfor %} 
+                {% elif (from_data is iterable) and (from_data is not string) %}
+    {{ from }} [ {% for from_data_element in from_data %}{{ from_data_element }} {% endfor %} ];
+                {% else %}
+    {{ from }} {
+                {% for from_data_element in from_data -%}
+    {{ from_data_element }};
+                {%- endfor %}
+ }
+                {% endif -%}
+            {%- endfor %}
+}
+        {% endif %}
+
+        {% if term.then is defined %}
+ then {
+        {% for then, then_data in term.then.items() -%}
+            {% if ("validation-state" in then) or ("next" in then) or ("label-allocation" in then) or ("-class" in then) %}
+                {% for then_data_element in then_data -%}
+  {{ then }} {{ then_data_element }};
+                {% endfor %}
+            {% elif ("community" in then) %}
+                {% for then_data_element in then_data -%}
+  {{ then }} add {{ then_data_element }};
+                {% endfor %}
+            {% elif (then_data is iterable) and (then_data is not string) %}
+  {{ then }} [ {% for then_data_element in then_data -%} {{ then_data_element }} {%- endfor%} ];
+            {% else %}
+  {{ then }};
+            {% endif %}
+        {%- endfor %}
+ }
+        {% endif %}
+}
+    {% endfor %}
+{% endif %}
+
+{% if ps_data.from is defined %}
+ from {
+    {% for from, from_data in ps_data.from.items() %}
+        {% if ("community-count" in from) or ("route-filter" in from) or ("validation-database" in from) or ("family" in from) or ("source-class" in from) or ("source-address-filter" in from) or ("prefix-list" in from) %}
+            {% for from_data_element in from_data %}
+ {{ from }} {{ from_data_element }};
+            {% endfor %} 
+        {% elif (from_data is iterable) and (from_data is not string) %}
+ {{ from }} [ {% for from_data_element in from_data %} {{ from_data_element }} {% endfor %} ];
+        {% else %}
+ {{ from }} {
+            {% for from_data_element in from_data %}
+    {{ from_data_element }};
+            {% endfor %}
+ }
+        {% endif %}           
+    {% endfor %}
+}
+{% endif %}
+
+{% if ps_data.then is defined %}
+ then {
+        {% for then, then_data in ps_data.then.items() -%}
+            {% if ("validation-state" in then) or ("next" in then) or ("label-allocation" in then) or ("-class" in then) %}
+                {% for then_data_element in then_data -%}
+  {{ then }} {{ then_data_element }};
+                {% endfor %}
+            {% elif ("community" in then) %}
+                {% for then_data_element in then_data -%}
+  {{ then }} add {{ then_data_element }};
+                {% endfor %}
+            {% elif (then_data is iterable) and (then_data is not string) %}
+  {{ then }} [ {% for then_data_element in then_data -%} {{ then_data_element }} {%- endfor%} ];
+            {% else %}
+  {{ then }};
+            {% endif %}
+        {%- endfor %}
+ }
+{% endif %}
+}
+{% endfor %}
+{% endif %}
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/bgp.j2 b/roles/base_config/templates/routers/juniper/protocols/bgp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..ef6b9795386da23f4d74c7ef56ed7f16d8eac5b7
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/bgp.j2
@@ -0,0 +1,73 @@
+protocols {
+    bgp {
+    path-selection external-router-id;
+    precision-timers;
+    log-updown;
+    drop-path-attributes 128;
+    {% if protocols_bgp.groups is defined%}
+    {% for group in protocols_bgp.groups %}
+replace:    group {{ group.name }} {
+        type {{ group.type }};
+        description "{{ group.description }}";
+        local-address {{ group.local_address }};
+        {% if group.families is defined%}
+        {% for family in group.families %}
+        family {{ family.name }} {
+             {% for nlri in family.nlris %}
+             {{ nlri}};
+             {% endfor %}
+         }
+        {% endfor %}
+        {% endif %}
+        {% if group.authentication_key is defined %}
+        authentication-key {{ group.authentication_key }};
+        {% endif %}
+        {% if group.import_policies is defined%}
+{#          {% if group.import_policies|length > 1 %} #}
+        import [{% for policy in group.import_policies %} {{ policy }} {% endfor %}];
+{#          {% else %} #}
+{#        import {{ policy }};#}
+{#          {% endif %} #}
+        {% endif %}
+        {% if group.export_policies is defined%}
+{#          {% if group.export_policies|length > 1 %} #}
+        export [{% for policy in group.export_policies %} {{ policy }} {% endfor %}];
+{#          {% else %} #}
+{#        export {{ policy }}; #}
+{#          {% endif %} #}
+        {% endif %}
+        {% if group.neighbors is defined and group.name != "iGEANT" and group.name != "iGEANT6" %}
+        {% for neighbor in group.neighbors %}
+        neighbor {{ neighbor.ip_address }} {
+            description "{{ neighbor.description }}";
+            hold-time {{ neighbor.hold_time }};
+            {% if neighbor.passive == True %}
+            passive ;
+            {% endif %}
+            import ps-deny-all;
+            {% if neighbor.families is defined%}
+            {% for family in neighbor.families %}
+            family {{ family.name }} {
+                   {% for nlri in family.nlris %}
+                   {{ nlri}};
+                   {% endfor %}
+               }
+            {% endfor %}
+            {% endif %}
+            {% if neighbor.authentication_key is defined %}
+            authentication-key {{ neighbor.authentication_key }};
+            {% endif %}
+            {% if neighbor.local_as is defined %}
+            local-as {{ neighbor.local_as }};
+            {% endif %}
+            {% if neighbor.cluster_id is defined %}
+            cluster {{ neighbor.cluster_id }};
+            {% endif %}
+        }
+        {% endfor %}
+        {% endif %}
+    }
+   {% endfor %}
+   {% endif %}
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/global_msdp.j2 b/roles/base_config/templates/routers/juniper/protocols/global_msdp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..5e508e118f4e45e1825c8b5d0fec986886492958
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/global_msdp.j2
@@ -0,0 +1,19 @@
+protocols {
+replace:    msdp {
+    rib-group multicast;
+    active-source-limit {
+        maximum 20000;
+        threshold 20000;
+        log-interval 32700;
+    }
+    local-address {{ lo_ipv4_address }};
+    source 0.0.0.0/0 {
+        active-source-limit {
+            maximum 1000;
+            threshold 900;
+            log-interval 32700;
+        }
+    }
+    {% include 'protocols/internal_msdp.j2' %}
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/igmp.j2 b/roles/base_config/templates/routers/juniper/protocols/igmp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..33bf5d440ab65e8ea77c58b4d087de9bbbad8fb8
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/igmp.j2
@@ -0,0 +1,16 @@
+protocols {
+replace:    igmp {
+    interface all {
+    disable;
+    }
+    interface dsc.0 {
+        version 3;
+        static {
+            group 232.223.222.1 {
+                source 212.201.139.66;
+                source 193.17.9.3;
+            }
+        }
+    }
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/internal_msdp.j2 b/roles/base_config/templates/routers/juniper/protocols/internal_msdp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..a176def2239f7f3735291d7fbdba8df4dcb61217
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/internal_msdp.j2
@@ -0,0 +1,25 @@
+{% if ansible_play_name != 'deploy_base_config' %}
+protocols {
+    msdp {
+replace: {% endif %}    group internal_msdp {
+        mode mesh-group;
+        export [ BOGON_SOURCES ];
+        import [ BOGON_SOURCES ];
+        {% if ansible_play_name != 'deploy_base_config' %}
+          {% if new_router_to_add is defined %}
+              {% set all_the_network_plus_new_router = groups.lab_routers|union([new_router_to_add])%}
+              {% for host in all_the_network_plus_new_router|difference([inventory_hostname]) %}
+                 peer {{ hostvars[host]["lo_ipv4_address"] }};
+              {% endfor %}
+          {% else %}
+              {% set all_the_network_plus_new_router = groups.lab_routers %}
+              {% for host in all_the_network_plus_new_router|difference([inventory_hostname]) %}
+                 peer {{ hostvars[host]["lo_ipv4_address"] }};
+              {% endfor %}
+          {% endif %}
+        {% endif %}
+    }
+{% if ansible_play_name != 'deploy_base_config' %}
+  }
+}
+{% endif %}
diff --git a/roles/base_config/templates/routers/juniper/protocols/isis.j2 b/roles/base_config/templates/routers/juniper/protocols/isis.j2
new file mode 100644
index 0000000000000000000000000000000000000000..e86a24078b89691d956ffb0347d9ea3221bea736
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/isis.j2
@@ -0,0 +1,42 @@
+{##}
+{# Template to render isis stanza: it is used as it is for base config#}
+{# If called by cic_isis playbook, it also includes isis interfaces, isis trunks and additional parameters like isis_disabled_interfaces, #}
+{# isis_policies and isis_additional_interfaces #}
+{##}
+protocols {
+replace:    isis {
+    rib-group {
+        inet unicast-multicast;
+        inet6 unicast-multicastv6;
+    }
+    backup-spf-options {
+        use-post-convergence-lfa;
+        use-source-packet-routing;
+    }
+    overload timeout 300;
+    {% set loopback_as_a_list= lo_ipv4_address.split('.')%}
+    {% set last_octet_filled= '%02d' % (loopback_as_a_list[3]|int) %}
+    source-packet-routing {
+        srgb start-label 10000 index-range 10000;
+        node-segment {
+            ipv4-index 4{{ loopback_as_a_list[2][-1:]  }}{{ last_octet_filled  }};
+            ipv6-index 6{{ loopback_as_a_list[2][-1:]  }}{{ last_octet_filled  }};
+        }
+    }
+    level 1 disable;
+    level 2 wide-metrics-only;
+
+    interface all {
+        passive;
+    }
+    interface fxp0.0 {
+        disable;
+    }
+
+      {# ISIS policies (if defined) #}
+      {% if isis_policies is defined %}
+          export [ {% for policy in isis_policies %} {{ policy }} {% endfor %} ]
+      {% endif %} 
+ }
+}
+
diff --git a/roles/base_config/templates/routers/juniper/protocols/ldp.j2 b/roles/base_config/templates/routers/juniper/protocols/ldp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..33419e2f3531b5d5c3a32319b6decc547dce4eb6
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/ldp.j2
@@ -0,0 +1,8 @@
+protocols {
+replace:    ldp {
+  preference 16;
+  track-igp-metric;
+  deaggregate;
+  interface lo0.0;
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/lldp.j2 b/roles/base_config/templates/routers/juniper/protocols/lldp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..064785a302da9884f32885763a434098ef55415f
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/lldp.j2
@@ -0,0 +1,7 @@
+protocols {
+replace:    lldp {
+  port-id-subtype interface-name;
+  interface all disable;
+  interface fxp0;
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/mld.j2 b/roles/base_config/templates/routers/juniper/protocols/mld.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d43ef829a0a3e67f40cae0d510f1860faaef36ee
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/mld.j2
@@ -0,0 +1,7 @@
+protocols {
+replace:    mld {
+    interface all {
+    disable;
+    }
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/mpls.j2 b/roles/base_config/templates/routers/juniper/protocols/mpls.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f4b337febe8aa89e6bd2f2ad3ebb9ffa68dce1ab
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/mpls.j2
@@ -0,0 +1,8 @@
+protocols {
+replace:    mpls {
+    ipv6-tunneling;
+    explicit-null;
+    icmp-tunneling;
+    interface all; 
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/neighbor-discovery.j2 b/roles/base_config/templates/routers/juniper/protocols/neighbor-discovery.j2
new file mode 100644
index 0000000000000000000000000000000000000000..2717b6de4774d2b74581277564b1ffab0f19408a
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/neighbor-discovery.j2
@@ -0,0 +1,5 @@
+protocols {
+replace:    neighbor-discovery {
+  onlink-subnet-only;
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/pim.j2 b/roles/base_config/templates/routers/juniper/protocols/pim.j2
new file mode 100644
index 0000000000000000000000000000000000000000..aa6599961827b3000d584403e4543dffaf6b207a
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/pim.j2
@@ -0,0 +1,67 @@
+routing-options {
+    rib-groups {
+replace:        multicast {
+            export-rib inet.2;
+            import-rib inet.2;
+        }
+replace:        multicastv6 {
+            import-rib inet6.2;
+        }
+    }
+}
+protocols {
+replace:    pim {
+        rib-group {
+            inet multicast;
+            inet6 multicastv6;
+        }
+        rp {
+            bootstrap {
+                family inet {
+                    priority 0;
+                    import no-bsr;
+                    export no-bsr;
+                }
+                family inet6 {
+                    priority 0;
+                    import no-bsr;
+                    export no-bsr;
+                }
+            }
+            embedded-rp {
+                group-ranges {
+                    ff7e::/16;
+                }
+            }
+{% if inventory_hostname in protocols_pim.rp_routers %}
+            local {
+{% else %}
+            static {
+{% endif %}
+                address {{ protocols_pim.rpip }};
+            }
+        }
+        interface all {
+            mode sparse;
+        }
+        interface fxp0.0 {
+            disable;
+        }
+{% if custom_fact_existing_interfaces is defined %}
+ {% if not custom_fact_existing_interfaces is sameas false  %}
+  {% for interface in custom_fact_existing_interfaces %}
+   {% if interface.name != "fxp0.0" and interface.name != "all" and interface|length > 1 and interface.disable is defined %}
+        interface {{interface.name}} {
+            disable;
+        }
+   {% endif %}
+  {%endfor%}
+ {%endif%}
+{%endif%}
+    }
+}
+policy-options {
+replace:    policy-statement no-bsr {
+        then reject;
+    }
+}
diff --git a/roles/base_config/templates/routers/juniper/protocols/protocols_global.j2 b/roles/base_config/templates/routers/juniper/protocols/protocols_global.j2
new file mode 100644
index 0000000000000000000000000000000000000000..25448e533344aed89f447433407c8fe55d84a57c
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/protocols_global.j2
@@ -0,0 +1,19 @@
+{% include 'protocols/mld.j2' %}
+
+{% include 'protocols/pim.j2' %}
+
+{% include 'protocols/igmp.j2' %}
+
+{% include 'protocols/rsvp.j2' %}
+
+{% include 'protocols/mpls.j2' %}
+
+{% include 'protocols/ldp.j2' %}
+
+{% include 'protocols/lldp.j2' %}
+
+{% include 'protocols/neighbor-discovery.j2' %}
+
+{% include 'protocols/isis.j2' %} 
+
+{% include 'protocols/bgp.j2' %}
diff --git a/roles/base_config/templates/routers/juniper/protocols/rsvp.j2 b/roles/base_config/templates/routers/juniper/protocols/rsvp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d881e5c9f143a3a335e38c41c6939a1d1c6e8b3b
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/protocols/rsvp.j2
@@ -0,0 +1,5 @@
+protocols {
+replace:    rsvp {
+    interface all; 
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/routing_instances.j2 b/roles/base_config/templates/routers/juniper/routing_instances.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d00d5ff1702f20cce40f68266dc8ee524e6ebfb3
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/routing_instances.j2
@@ -0,0 +1,12 @@
+routing-instances {
+replace:    vrf-mgmt {
+        description "L3VPN Management";
+        instance-type vrf;
+        route-distinguisher 20965:991;
+        vrf-target target:20965:991;
+        vrf-table-label;
+        routing-options {
+            autonomous-system 20965;
+        }
+    }
+}
diff --git a/roles/base_config/templates/routers/juniper/routing_options.j2 b/roles/base_config/templates/routers/juniper/routing_options.j2
new file mode 100644
index 0000000000000000000000000000000000000000..5d1d22f3bceae52b828c75075da58c012c8afff6
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/routing_options.j2
@@ -0,0 +1,106 @@
+{% if global_routing_options is defined %}
+replace: routing-options {
+    {% if ansible_net_has_2RE == true  %}
+        nonstop-routing;
+    {% endif %}
+        
+    {% if global_routing_options.interface_routes.rib_group is defined %}
+   interface-routes {
+        rib-group {
+        {% for group in global_routing_options.interface_routes.rib_group %}
+            {{ group.name }} {{group.family}};
+        {% endfor %}        
+    {% endif %}        
+        }
+    }
+    
+    {% if global_routing_options.ribs is defined %}
+    {%- for rib in global_routing_options.ribs %}
+    rib {{ rib.name }} {
+        {% if rib.static_routes is defined %}
+        static {
+            {% for static_route in rib.static_routes %}
+            route {{ static_route.route }} {
+                {% for action in static_route.actions %}
+                {{ action }};
+                {% endfor %}
+            }
+            {% endfor %}
+        }
+        {% endif %}
+        {%- if rib.maximum_prefixes is defined %}
+        maximum-prefixes {{ rib.maximum_prefixes.prefix_num }} threshold {{ rib.maximum_prefixes.threshold }};
+        {% endif -%}
+        }
+    {%- endfor -%}      
+    {% endif %}      
+    {% if global_routing_options.static_routes is defined %}
+    static {
+    {% for static_route in global_routing_options.static_routes %}
+        route {{ static_route.route }} {
+            {% for action in static_route.actions %}
+                {{ action }};
+            {% endfor %}
+            }
+    {% endfor %}
+    }
+    {% endif %}
+    {% if global_routing_options.rib_groups is defined %}
+    rib-groups {
+        {% for rib_group in global_routing_options.rib_groups %}
+        {{ rib_group.name}} {
+            {%- if rib_group.import_rib is defined %} 
+                {%- if rib_group.import_rib | length > 1 %} 
+                import-rib [{%- for group in rib_group.import_rib %} {{ group }} {% endfor -%} ];
+                {% else %}
+                import-rib {{ rib_group.import_rib[0] }};
+                {% endif %}
+            {% endif %}
+            {% if rib_group.export_rib is defined %} 
+                {%- if rib_group.export_rib | length > 1 %}
+                export-rib [{%- for group in rib_group.export_rib %} {{ group }} {% endfor -%} ];
+                {% else %}
+                export-rib {{ rib_group.export_rib[0] }};
+                {% endif %}
+            {% endif -%}
+        }
+        {% endfor %}
+    }
+    {% endif %}
+    router-id {{ lo_ipv4_address }};
+    autonomous-system 20965;
+    forwarding-table {
+        export [ dest-class-usage source-class-usage ];
+        chained-composite-next-hop  {
+                         ingress  {
+                             l2vpn;
+                             l2ckt;
+                             l3vpn;
+                            }
+                        }   
+    }
+    {% if global_routing_options.rpki_validation is defined %}
+    validation {
+        notification-rib [ {% for rib in global_routing_options.rpki_validation.notification_ribs %} {{rib}} {% endfor %}];
+        {% for validator_group in global_routing_options.rpki_validation.validators %}
+        group {{ validator_group.group }}{
+            {% for session in validator_group.sessions %}
+            session {{ session.server }} {
+                port {{ session.port }};
+                local-address {{ lo_ipv4_address }};
+            }
+            {% endfor %}
+        }
+        {% endfor %}
+    }
+    {% endif %}
+    multicast {
+        forwarding-cache {
+            threshold {
+                suppress 20000;
+                reuse 18000;
+            }
+        }
+    }
+}
+{% endif %}
diff --git a/roles/base_config/templates/routers/juniper/services.j2 b/roles/base_config/templates/routers/juniper/services.j2
new file mode 100644
index 0000000000000000000000000000000000000000..5eeab680fc0e8eab6d17f587417bc18b9e5b5b58
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/services.j2
@@ -0,0 +1,106 @@
+services {
+{% if service_version_ipfix is defined %}
+replace:  flow-monitoring {
+            version-ipfix {
+                {% for template in service_version_ipfix.templates %}
+                template {{ template.proto }} {
+                    flow-active-timeout {{ template.flow_active_timeout }};
+                    flow-inactive-timeout {{ template.flow_inactive_timeout }};
+                    nexthop-learning {
+                        {{ template.next_hop_learning }};
+                    }
+                    template-refresh-rate {
+                        seconds {{ template.template_refresh_rate }};
+                    }
+                    option-refresh-rate {
+                        seconds {{ template.option_refresh_rate }};
+                    }
+                    {% if template.label_positions is defined %}
+                    {{ template.protocol_template }} {
+                        label-position [ {%for label_position in template.label_positions %} {{ label_position }}{% endfor %} ] ;
+                    }
+                    {% else %}
+                    {{ template.protocol_template }}; 
+                    {% endif %}
+                }
+            {% endfor %}
+            }
+} 
+{% endif %}
+{% if services_analytics is defined %}
+replace: analytics {
+{% if services_analytics.streaming_servers is defined %}
+    {% for streaming_server_name, streaming_server_conf in services_analytics.streaming_servers.iteritems() %}
+    streaming-server {{ streaming_server_name }} {
+        remote-address {{ streaming_server_conf.remote_address }};
+        remote-port {{ streaming_server_conf.remote_port }};
+    }
+    {% endfor %}
+{% else %}
+{{ raise('ERROR: YOU HAVE NO STREAMING SERVER DEFINED')}}
+{% endif %}
+{% if services_analytics.export_profiles is defined %}
+    {% for export_profile_name, export_profile_conf in services_analytics.export_profiles.iteritems() %}
+    export-profile {{ export_profile_name }} {
+        local-address {{ export_profile_conf.local_address }} ;
+        local-port {{ export_profile_conf.local_port }} ;
+        reporting-rate {{ export_profile_conf.reporting_rate }} ;
+        format {{ export_profile_conf.format }} ;
+        transport {{ export_profile_conf.transport }} ;
+    }
+    {% endfor %}
+{% else %}
+{{ raise('ERROR: YOU HAVE NO EXPORT PROFILE DEFINED')}}
+{% endif %}
+{% if services_analytics.sensors is defined %}
+    {% for sensor_name, sensor_conf in services_analytics.sensors.iteritems() %}
+    sensor {{ sensor_name }} {
+        server-name {{ sensor_conf.server_name}};
+        export-name {{ sensor_conf.export_name}};
+        resource {{ sensor_conf.resource}};
+    }
+    {% endfor %}
+{% else %}
+{{ raise('ERROR: YOU HAVE NO SENSORS DEFINED')}}
+{% endif %}
+}
+{% endif %}
+
+{% if service_rpm is defined %}
+replace:  rpm {
+        {% if service_rpm.traceoptions is defined %}
+        traceoptions {
+            file {{ service_rpm.traceoptions.filename }} size {{ service_rpm.traceoptions.filesize }};
+            {% for flag in service_rpm.traceoptions.flags %} 
+            flag {{ flag }};
+            {% endfor %}
+        }
+        {% endif %}
+        {% if service_rpm.twamp is defined %}
+        twamp {
+        {% if service_rpm.twamp.server is defined %}
+          server {
+              authentication-mode {{ service_rpm.twamp.server.auth_mode }};
+              max-connection-duration {{ service_rpm.twamp.server.max_duration }};
+              maximum-sessions {{ service_rpm.twamp.server.max_sessions }};
+              maximum-sessions-per-connection {{ service_rpm.twamp.server.max_sessions_per_conn }};
+              maximum-connections {{ service_rpm.twamp.server.max_connections }};
+              maximum-connections-per-client {{ service_rpm.twamp.server.max_connections_per_client }};
+              port {{ service_rpm.twamp.server.port }};
+        {% for client_list in service_rpm.twamp.client_lists %}
+              client-list {{ client_list.name }} {
+                address {
+        {% for address in client_list.address %}
+                  {{ address }};
+        {% endfor %}
+                }
+        }
+        {% endfor %}
+}
+        {% endif %}
+}
+        {% endif %}
+
+}
+{% endif %}
+}
diff --git a/roles/base_config/templates/routers/juniper/snmp.j2 b/roles/base_config/templates/routers/juniper/snmp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..832498e33dec07c501f41e966c810f1d22b79bb8
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/snmp.j2
@@ -0,0 +1,58 @@
+replace: snmp {
+    location "{{ snmp_location }}";
+    contact "{{ snmp_contact }}";
+    {% if snmp_views is defined %}
+    {% for snmp_view in snmp_views() %}
+    view {{ snmp_view.name }} {
+      {% for oid_name, oid in snmp_view.oids.items() %}
+      oid {{ oid_name }} {% if oid.state is defined %}{{ oid.state }}{% endif %};
+      {% endfor %}
+    }
+    {% endfor %}
+    {% endif %}
+    {% for community in snmp_communities %}
+    community {{ community.name }} {
+        authorization {{ community.authorization }};
+    {% if community.clients is defined %}
+        clients {
+        {% for client in community.clients %}
+            {{ client.client }};
+        {% endfor %}
+        }
+    {% endif %}
+    {% if community.view is defined %}
+        view {{ community.view }};
+    {% endif %}
+  }
+    {% endfor %}
+    {% if snmp_trap_options is defined %}
+    trap-options {
+        {% for option, value in snmp_trap_options.items() %}
+        {{ option }} {{ value }};
+        {% endfor %}
+    }
+    {% endif %}
+
+    {% for trap_group in snmp_trap_groups %}
+    trap-group {{ trap_group.name }} {
+        {% if trap_group.version is defined %}
+        version {{trap_group.version}};
+        {% endif %}
+        {% if trap_group.categories is defined %}
+        categories {
+        {% for category in trap_group.categories %}
+            {{ category }};
+        {% endfor %}
+        }
+        {% endif %}
+        targets {
+        {% for target in trap_group.targets %}
+            {{ target.target }};
+        {% endfor %}
+        }
+    }
+    {% endfor %}
+    {% if snmp_routing_instance_access is defined %}
+    routing-instance-access;    
+    {% endif %}
+}
diff --git a/roles/base_config/templates/routers/juniper/system/general.j2 b/roles/base_config/templates/routers/juniper/system/general.j2
new file mode 100644
index 0000000000000000000000000000000000000000..0c822dc15035f713b246f318660e7c4ca1b010aa
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/system/general.j2
@@ -0,0 +1,53 @@
+{% set hostname_as_a_list= inventory_hostname.split('.')%}
+{% set short_hostname= hostname_as_a_list[:3] | join('.')%}
+system {
+  {% if ansible_net_has_2RE == false %}
+  replace: host-name {{ short_hostname }}.re0;
+  {% if cfg_backup_router_fxp_address is defined %}
+  replace: archival {
+              configuration {
+                 transfer-on-commit;
+                 archive-sites "scp://{{cfg_backup_username}}@{{cfg_backup_router_fxp_address }}:{{cfg_backup_path}}" password {{cfg_backup_password}};
+                 }
+  }
+  {% endif %}
+  {% endif %}
+  replace: commit {
+    synchronize ;  
+  {% if ansible_net_has_2RE == true %}
+    fast-synchronize ;
+  {% endif %}
+  }
+  {% if ansible_net_has_2RE == true %}
+  switchover-on-routing-crash ;
+  {% endif %}
+  replace: authentication-order [ radius password ];
+  {% if system_root_pwd is defined %}
+  replace:  root-authentication {
+  encrypted-password {{ system_root_pwd }} ;
+  }
+  {% endif %}
+  {% if system_domain_name is defined %}
+  replace:  domain-name {{ system_domain_name }} ;
+  {% endif %}
+  {% if system_time_zone is defined %}
+  replace:  time-zone {{ system_time_zone }} ;
+  {% endif %}
+  dump-on-panic;
+  {% if system_time_zone is defined %}
+  replace:  location country-code {{ site_country_code }} ;
+  {% endif %}
+  {% if system_domain_search is defined %}
+  replace: domain-search [ {% for domain in system_domain_search %}{{ domain }} {% endfor %} ];
+  {% endif %}
+  {% if system_name_servers is defined %}
+  replace: name-server {
+  {%- for name_server in system_name_servers %}
+    {{ name_server }};
+  {%- endfor %}
+  {% endif %}
+  }
+  replace: static-host-mapping {
+   lo0 inet {{ lo_ipv4_address }};
+   }
+}
diff --git a/roles/base_config/templates/routers/juniper/system/login.j2 b/roles/base_config/templates/routers/juniper/system/login.j2
new file mode 100644
index 0000000000000000000000000000000000000000..2fc7e03bb803b11f579fa90b6b2daea28d6cdd31
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/system/login.j2
@@ -0,0 +1,72 @@
+system {
+replace: login {
+     idle-timeout 15;
+{# classes #}
+    {% if system_login_classes is defined %}
+      {% for login_class in system_login_classes %}
+     class {{ login_class.name }} {
+      {% if login_class.idle_timeout is defined %}
+          idle-timeout {{ login_class.idle_timeout }};
+      {% endif %}
+      {% if login_class.login_alarms is defined and login_class.login_alarms is sameas true %}
+          login-alarms;
+      {% endif %}
+      {% if login_class.permissions is defined %}
+          permissions [{% for permission in login_class.permissions %} {{ permission }}{% endfor %} ];
+      {% endif %}
+      {% if login_class.allow_commands is defined %}
+          allow-commands "{{ login_class.allow_commands }}";
+      {% endif %}
+      {% if login_class.deny_commands is defined %}
+          deny-commands "{{ login_class.deny_commands }}";
+      {% endif %}
+      {% if login_class.allow_configuration_regexps is defined %}
+          allow-configuration-regexps [ {% for regex in login_class.allow_configuration_regexps %} "{{ regex }}"{% endfor %} ];
+      {% endif %}
+      {% if login_class.deny_configuration_regexps is defined %}
+          deny-configuration-regexps [ {% for regex in login_class.deny_configuration_regexps %} "{{ regex }}"{% endfor %} ];
+      {% endif %}
+      }
+      {% endfor %}
+    {% endif %}
+{# users #}
+    {% if system_login_users is defined %}
+      {% for login_user in system_login_users %}
+      user {{ login_user.name }} {
+      {% if login_user.full_name is defined %}
+          full-name "{{ login_user.full_name }}";
+      {% endif %}
+      {% if login_user.uid is defined %}
+          uid {{ login_user.uid }};
+      {% endif %}
+          class {{ login_user.class }};
+      {% if ( login_user.authentication is defined ) and ( ( login_user.authentication.ssh_dsa is defined ) or ( login_user.authentication.ssh_rsa is defined ) or ( login_user.authentication.encrypted_password is defined ) ) %}
+          authentication {
+        {% if login_user.authentication.ssh_dsa is defined  %} {% for dsa_key in login_user.authentication.ssh_dsa %}
+            ssh-dsa "{{ dsa_key }}";
+          {% endfor %}
+        {% endif %}
+        {% if login_user.authentication.ssh_rsa is defined  %} {% for rsa_key in login_user.authentication.ssh_rsa %}
+            ssh-rsa "{{ rsa_key }}";
+          {% endfor %}
+        {% endif %}
+        {% if login_user.authentication.encrypted_password is defined  %}
+            encrypted-password "{{ login_user.authentication.encrypted_password }}";
+        {% endif %}
+        }
+       {% endif %}
+      }
+      {% endfor %}
+      {% endif %}
+{# options #}
+    {% if system_login_password_policies is defined %}
+      password {
+      {% for option in system_login_password_policies %}
+        {{ option.option }} {{ option.value }} ;
+      {% endfor %}
+      }
+    {% endif %}
+      message "----------------------------------------------------------------\n\n This is {{ inventory_hostname }} a GEANT Router in Cambridge UK \n Warning: Unauthorized access to this equipment is strictly forbidden and will lead to prosecution \n\n-------------------------------------------------------------\n";
+ }
+}
+
diff --git a/roles/base_config/templates/routers/juniper/system/ntp.j2 b/roles/base_config/templates/routers/juniper/system/ntp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..b60ce08585953f92421eff2b7eb5e5f919aa840a
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/system/ntp.j2
@@ -0,0 +1,25 @@
+system {
+replace: ntp {
+    {% if system_ntp.ntp_keys is defined %}
+      {% for ntp_key in system_ntp.ntp_keys %}
+        authentication-key {{ ntp_key.id }} type {{ ntp_key.type }} value {{ ntp_key.value }} ;
+      {% endfor %}
+    {% endif %}
+    {% if system_ntp.servers is defined %}
+      {% for ntp_server in system_ntp.servers %}
+        server {{ ntp_server.address }} {% if ntp_server.key is defined %} key {{ ntp_server.key }} {% endif %};
+      {% endfor %}
+    {% endif %}
+    {% if '18' in ansible_net_version %}
+      {% if system_ntp.boot_server is defined %}
+        boot-server {{ system_ntp.boot_server }} ;
+      {%- endif %}
+    {% endif %}
+    {% if system_ntp.trusted_keys is defined %}
+      {% for trusted_key in system_ntp.trusted_keys %}
+         trusted-key {{ trusted_key }} ;
+      {% endfor %}
+    {% endif %}
+      source-address {{ system_ntp.source_address }} ;
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/system/radius-server.j2 b/roles/base_config/templates/routers/juniper/system/radius-server.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f054917b088c3ba1071665e4308893c76018301f
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/system/radius-server.j2
@@ -0,0 +1,18 @@
+system {
+{% if system_radius_servers is defined %}
+   replace: radius-server { 
+      {%- for radius_server in system_radius_servers %} 
+      {{ radius_server.host }} {
+         secret "{{ radius_server.secret }}"; 
+      {% if radius_server.timeout is defined %}
+         timeout {{ radius_server.timeout }};
+      {% endif %}
+      {% if radius_server.source_address is defined %}
+         source-address {{ radius_server.source_address }};
+      {% endif %}
+      }
+      {%- endfor %}
+   {% endif %}
+   }
+}
+
diff --git a/roles/base_config/templates/routers/juniper/system/services.j2 b/roles/base_config/templates/routers/juniper/system/services.j2
new file mode 100644
index 0000000000000000000000000000000000000000..0d8a25b7b3c4f395c8bbdb2a0a25f1fa81fd6d12
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/system/services.j2
@@ -0,0 +1,52 @@
+system {
+replace: services {
+    ssh {
+        root-login deny;
+        no-tcp-forwarding;
+        protocol-version v2;
+{% if '18' not in ansible_net_version %}
+        sftp-server;
+{% endif %}
+{% if system_services_ssh_conf is defined %}
+        max-sessions-per-connection {{ system_services_ssh_conf.max_sessions_per_connection }} ;
+    {% if system_services_ssh_conf.ciphers is defined %}
+        ciphers [ {% for cipher in system_services_ssh_conf.ciphers %}"{{cipher}}" {% endfor %}]; 
+    {% endif %}
+    {% if system_services_ssh_conf.key_exchanges is defined %}
+        key-exchange [ {% for key_exchange in system_services_ssh_conf.key_exchanges %}"{{key_exchange}}" {% endfor %}]; 
+    {% endif %}
+        connection-limit {{ system_services_ssh_conf.connection_limit }};
+        rate-limit {{ system_services_ssh_conf.rate_limit }};
+{% endif %}
+    } 
+    {% if system_services_extension_service is defined %}
+    extension-service {
+        request-response {
+            grpc {
+                clear-text {
+                    port {{ system_services_extension_service.request_response.port}};
+                }
+                max-connections {{ system_services_extension_service.request_response.max_connections }};
+            }
+        }
+        {% if system_services_extension_service.notification is defined %}
+        notification {
+            allow-clients {
+                address [ {% for client in system_services_extension_service.notification.allow_clients  %} "{{ client }}"{% endfor %} ];
+            }
+        }
+        {% endif %}
+    }
+    {% endif %}
+    {% if system_services_resource_monitor is defined %}
+    resource-monitor {
+        free-heap-memory-watermark {{ system_services_resource_monitor.free_heap_memory_watermark }};
+        free-nh-memory-watermark {{ system_services_resource_monitor.free_nh_memory_watermark }};
+        free-fw-memory-watermark {{ system_services_resource_monitor.free_fw_memory_watermark }};
+    }
+    {% endif %}
+    netconf {
+        ssh;
+    }
+  }
+}
diff --git a/roles/base_config/templates/routers/juniper/system/syslog.j2 b/roles/base_config/templates/routers/juniper/system/syslog.j2
new file mode 100644
index 0000000000000000000000000000000000000000..e8867b368aa5c69991a636f0f6f30cec26d23bc0
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/system/syslog.j2
@@ -0,0 +1,78 @@
+system {
+  replace: syslog {
+    user * {
+            any emergency;
+        }
+    {% if system_syslog_time_format_options is defined %}
+    time-format {% for syslog_time_format_option in system_syslog_time_format_options %}{{ syslog_time_format_option }} {% endfor %};
+    {% endif %}
+    {% if system_syslog_servers is defined %}
+      {% for syslog_server in system_syslog_servers %}
+      host {{ syslog_server.address }} {
+	 {% for facility  in syslog_server.facilities %}
+         {{ facility.name }} {{ facility.level }};
+	 {% endfor %}
+	 {% if syslog_server.match is defined %}
+         match "{{ syslog_server.match }}"; 
+	 {% endif %}
+         {% if syslog_server.port is defined %}
+	     port {{ syslog_server.port }} 
+         {% endif %}
+         {% if syslog_server.source_address is defined %}
+         source-address {{ syslog_server.source_address }} ;
+         {% endif %}
+	{% if syslog_server.structured_data is defined  %}
+	    {% if syslog_server.structured_data == "default"  %}
+         structured-data;
+	    {% elif syslog_server.structured_data == "brief"  %}
+         structured-data brief;
+	    {% endif %}
+	 {% endif %}
+	 {% if syslog_server.allow_duplicates is defined  %}
+	    {% if syslog_server.allow_duplicates == True  %}
+         allow-duplicates ;
+	    {% endif %}
+	 {% endif %}
+	} 
+      {% endfor %}
+{#    {%- else %} #}
+{#    {{ raise('ERROR: No syslog servers configured') }}#}
+    {% endif %}
+    {% if system_syslog_source_address is defined %}
+    source-address {{ system_syslog_source_address }} ;
+    {% endif %}
+    {% if system_syslog_files is defined %}
+    {% for syslog_file in system_syslog_files %}
+    file {{ syslog_file.filename }} {
+        {% for facility  in syslog_file.facilities %}
+        {{ facility.name }} {{ facility.level }};
+        {% endfor %}
+	{% if syslog_file.match is defined %}
+        match "{{ syslog_file.match }}"; 
+	{% endif %}
+  {% if syslog_file.authorization is defined %}
+   authorization {{ syslog_file.authorization }};
+  {% endif %}
+	{% if syslog_file.archive_options is defined %}
+        archive {% if syslog_file.archive_options.files is defined %} files {{ syslog_file.archive_options.files }} {% endif %} {% if syslog_file.archive_options.size is defined %} size {{ syslog_file.archive_options.size }} {% endif %} 
+	{% endif %}
+	{% if syslog_file.structured_data is defined  %}
+	    {% if syslog_file.structured_data == "default"  %}
+         structured-data ;
+	    {% elif syslog_file.structured_data == "brief"  %}
+         structured-data brief;
+	    {% endif %}
+	{% endif %}
+	{% if syslog_file.allow_duplicates is defined  %}
+	   {% if syslog_file.allow_duplicates == True  %}
+        allow-duplicates ;
+	   {% endif %}
+	{% endif %}
+     }
+    {% endfor %}
+    {% endif %}
+  }
+}
+
+
+
diff --git a/roles/base_config/templates/routers/juniper/system/system_global.j2 b/roles/base_config/templates/routers/juniper/system/system_global.j2
new file mode 100644
index 0000000000000000000000000000000000000000..b8e53953bff44ea31ac6e157fa08cb9d5e455205
--- /dev/null
+++ b/roles/base_config/templates/routers/juniper/system/system_global.j2
@@ -0,0 +1,16 @@
+{% include 'system/general.j2' %}
+
+{% include 'system/login.j2' %}
+
+
+{#{% include 'system/services.j2' %}#}
+
+
+{% include 'system/syslog.j2' %}
+
+
+{% include 'system/ntp.j2' %}
+
+
+{% include 'system/radius-server.j2' %}
+
diff --git a/roles/base_config/templates/routers/nokia/base_config.j2 b/roles/base_config/templates/routers/nokia/base_config.j2
new file mode 100644
index 0000000000000000000000000000000000000000..3f57f98f0cf1a15cc8a23c73aa897ba489eeebc2
--- /dev/null
+++ b/roles/base_config/templates/routers/nokia/base_config.j2
@@ -0,0 +1,36 @@
+<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>
+            <autonomous-system xmlns="urn:nokia.com:sros:ns:yang:sr:conf" xmlns:nokia-attr="urn:nokia.com:sros:ns:yang:sr:attributes">20965</autonomous-system>
+            <router-id xmlns="urn:nokia.com:sros:ns:yang:sr:conf" xmlns:nokia-attr="urn:nokia.com:sros:ns:yang:sr:attributes">{{ lo_ipv4_address }}</router-id>
+            <interface 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">
+                <interface-name>system</interface-name>
+                <admin-state>enable</admin-state>
+                <mac>02:01:ff:00:00:01</mac>
+                <ipv4>
+                    <primary>
+                        <address>{{ lo_ipv4_address }}</address>
+                        <prefix-length>32</prefix-length>
+                    </primary>
+                </ipv4>
+                <ipv6>
+                    <address>
+                        <ipv6-address>{{ lo_ipv6_address }}</ipv6-address>
+                        <prefix-length>128</prefix-length>
+                    </address>
+                </ipv6>
+            </interface>
+            <mpls-labels 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">
+                <static-label-range>256</static-label-range>
+                <sr-labels>
+                    <start>10000</start>
+                    <end>19999</end>
+                </sr-labels>
+            </mpls-labels>
+            {% include 'bgp.j2' %}
+            {% include 'isis.j2' %}
+            {% include 'pim.j2' %}
+       </router>
+   </configure>
+</config>
diff --git a/roles/base_config/templates/routers/nokia/bgp.j2 b/roles/base_config/templates/routers/nokia/bgp.j2
new file mode 100644
index 0000000000000000000000000000000000000000..8c49a1c738a7a29860c5db5091a1ea32e7ef10ba
--- /dev/null
+++ b/roles/base_config/templates/routers/nokia/bgp.j2
@@ -0,0 +1,29 @@
+   <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" alu:operation="replace">
+                <local-as>
+                    <as-number>{{ geant_re_as_number }}</as-number>
+                </local-as>
+                <group>
+                    <group-name>iGEANT-P-ONLY</group-name>
+                    <admin-state>enable</admin-state>
+                    <next-hop-self>true</next-hop-self>
+                    <type>internal</type>
+                    <peer-as>{{ geant_re_as_number }}</peer-as>
+                    <capability-negotiation>true</capability-negotiation>
+                    <local-address>{{ lo_ipv4_address }}</local-address>
+                    <family>
+                        <mcast-ipv4>true</mcast-ipv4>
+                    </family>
+                </group>
+                <group>
+                    <group-name>iGEANT6-P-ONLY</group-name>
+                    <authentication-key>aX1kndQNDTAHyJttsnoyKQiLcy8euS8do68= hash2</authentication-key>
+                    <next-hop-self>true</next-hop-self>
+                    <type>internal</type>
+                    <peer-as>{{ geant_re_as_number }}</peer-as>
+                    <local-address>{{ lo_ipv6_address }}</local-address>
+                    <family>
+                        <mcast-ipv6>true</mcast-ipv6>
+                    </family>
+                </group>
+            {# Here goes the neighbors#}
+            </bgp>
diff --git a/roles/base_config/templates/routers/nokia/chassis_tier1.j2 b/roles/base_config/templates/routers/nokia/chassis_tier1.j2
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/roles/base_config/templates/routers/nokia/chassis_tier2.j2 b/roles/base_config/templates/routers/nokia/chassis_tier2.j2
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/roles/base_config/templates/routers/nokia/isis.j2 b/roles/base_config/templates/routers/nokia/isis.j2
new file mode 100644
index 0000000000000000000000000000000000000000..8071a0d54dcb2d80a69ae0e79a4a23257c5e6939
--- /dev/null
+++ b/roles/base_config/templates/routers/nokia/isis.j2
@@ -0,0 +1,50 @@
+{% set loopback_as_a_list= lo_ipv4_address.split('.')%}
+{% set last_octet_filled= '%02d' % (loopback_as_a_list[3]|int) %}
+
+            <isis 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">
+                <isis-instance>0</isis-instance>
+                <admin-state>enable</admin-state>
+                <advertise-router-capability>area</advertise-router-capability>
+                <ldp-sync>false</ldp-sync>
+                <ipv6-routing>native</ipv6-routing>
+                <level-capability>2</level-capability>
+                <router-id>{{ lo_ipv4_address }}</router-id>
+                <system-id>{{ iso_system_id }}</system-id>
+                <area-address>{{ geant_iso_area_id }}</area-address>
+                <overload-on-boot>
+                    <timeout>300</timeout>
+                </overload-on-boot>
+                <loopfree-alternate>
+                    <remote-lfa>
+                        <node-protect>
+                        </node-protect>
+                    </remote-lfa>
+                    <ti-lfa>
+                        <node-protect>
+                        </node-protect>
+                    </ti-lfa>
+                </loopfree-alternate>
+                <segment-routing>
+                    <admin-state>enable</admin-state>
+                    <prefix-sid-range>
+                        <start-label>10000</start-label>
+                        <max-index>9999</max-index>
+                    </prefix-sid-range>
+                </segment-routing>
+            {#Here go interfaces#}
+                <interface>
+                    <interface-name>system</interface-name>
+                    <admin-state>enable</admin-state>
+                    <passive>true</passive>
+                    <ipv4-node-sid>
+                        <index>4{{ loopback_as_a_list[2][-1:]  }}{{ last_octet_filled  }}</index>
+                    </ipv4-node-sid>
+                    <ipv6-node-sid>
+                        <index>6{{ loopback_as_a_list[2][-1:]  }}{{ last_octet_filled  }}</index>
+                    </ipv6-node-sid>
+                </interface>
+                <level>
+                    <level-number>2</level-number>
+                    <wide-metrics-only>true</wide-metrics-only>
+                </level>
+            </isis>
diff --git a/roles/base_config/templates/routers/nokia/pim.j2 b/roles/base_config/templates/routers/nokia/pim.j2
new file mode 100644
index 0000000000000000000000000000000000000000..ea6f66d65c0f037822c9d7031e02bc0bd2fec605
--- /dev/null
+++ b/roles/base_config/templates/routers/nokia/pim.j2
@@ -0,0 +1,13 @@
+            <pim 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">
+                <ipv4>
+                    <rpf-table>rtable-m</rpf-table>
+                </ipv4>
+                <ipv6>
+                    <admin-state>enable</admin-state>
+                    <rpf-table>rtable-m</rpf-table>
+                </ipv6>
+            {#Here go interfaces#}
+                <interface>
+                    <interface-name>system</interface-name>
+                </interface>
+            </pim>
diff --git a/roles/base_config/vars/main.yml b/roles/base_config/vars/main.yml
index 932875ab1b8493a14216f2c9c553a269fc0110df..6964df98466b9045d6cfb2ef966a9e210d8bfb3a 100644
--- a/roles/base_config/vars/main.yml
+++ b/roles/base_config/vars/main.yml
@@ -1,8 +1,19 @@
-dryrun: "True"
+dry_run: "True"
 is_base_config_run: "True"
-mytemplates:
-  template_name: base_config
-  template_path: "routers/base_config.j2"
 verbs:
   - "compile"
   - "deploy"
+
+wfo_router: "{{ wfo_router_json }}"
+lo_ipv4_address: "{{ wfo_router.router.router_lo_ipv4_address }}"
+lo_ipv6_address: "{{ wfo_router.router.router_lo_ipv6_address }}"
+lo_iso_address: "{{ wfo_router.router.router_lo_iso_address }}"
+snmp_location: "An SNMP location"
+si_ipv4_network: "{{ wfo_router.router.router_si_ipv4_network }}"
+lt_ipv4_network: "{{ wfo_router.router.router_ias_lt_ipv4_network }}"
+lt_ipv6_network: "{{ wfo_router.router.router_ias_lt_ipv6_network }}"
+site_country_code: "{{ wfo_router.router.router_site.site_country_code }}"
+
+mytemplates:
+  template_name: base_config
+  template_path: "routers/{{ wfo_router.router.router_vendor }}/base_config.j2"
diff --git a/roles/iptrunks/meta/main.yml b/roles/iptrunks/meta/main.yml
index c572acc9f8b466bea50f2799b0ca1956418b862c..0f5a7796e91b74c6e8ca44402537ba7084d75ddf 100644
--- a/roles/iptrunks/meta/main.yml
+++ b/roles/iptrunks/meta/main.yml
@@ -1,7 +1,7 @@
 galaxy_info:
-  author: your name
-  description: your role description
-  company: your company (optional)
+  author: Simone Spinelli for GOAT
+  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
@@ -14,9 +14,9 @@ galaxy_info:
   # - GPL-3.0-only
   # - Apache-2.0
   # - CC-BY-4.0
-  license: license (GPL-2.0-or-later, MIT, etc)
+  license: MIT
 
-  min_ansible_version: 2.1
+  min_ansible_version: '2.10'
 
   # If this a Container Enabled role, provide the minimum Ansible Container version.
   # min_ansible_container_version:
@@ -39,7 +39,8 @@ galaxy_info:
   #   - 7
   #   - 99.99
 
-  galaxy_tags: []
+  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.
diff --git a/roles/iptrunks/tasks/iptrunk_modify_trunk.yaml b/roles/iptrunks/tasks/iptrunk_modify_trunk.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b926454ea0ac85d055ac1ab5e8a76f0de16f6c14
--- /dev/null
+++ b/roles/iptrunks/tasks/iptrunk_modify_trunk.yaml
@@ -0,0 +1,42 @@
+- name: Take care of old trunk variable
+  ansible.builtin.set_fact:
+    old_wfo_trunk: "{{ old_wfo_trunk_json }}"
+  when: old_wfo_trunk_json is defined
+
+- name: Verify if metric should be change
+  ansible.builtin.set_fact:
+    trunks[0].config.common.isis_metric = "{{ wfo_trunk.iptrunk.iptrunk_isis_metric }}"
+    modify_metric = true
+  when: old_wfo_trunk is defined and wfo_trunk.iptrunk.iptrunk_isis_metric != old_wfo_trunk.iptrunk.iptrunk_isis_metric
+
+- name: Update ISIS metric [CHECK ONLY]
+  juniper_junos_config:
+    load: 'replace'
+    src: "/var/tmp/ansible_run_{{ opid }}/isis_interface.conf"
+    format: text
+    config_mode: "private"
+    check: true
+    commit: false
+  register: response
+  when: verb == "modify" and (dry_run | ansible.builtin.bool) and (modify_metric | ansible.builtin.bool)
+
+- name: Show DRY diff of "{{ config_object }}"
+  ansible.builtin.debug:
+    msg: "{{ response }}"
+  when: verb == "deploy" and dry_run | ansible.builtin.bool and (modify_metric | ansible.builtin.bool)
+
+- name: Update ISIS metric [FOR REAL]
+  juniper_junos_config:
+    load: 'replace'
+    src: "/var/tmp/ansible_run_{{ opid }}/isis_interface.conf"
+    format: text
+    config_mode: "private"
+    commit: true
+    comment: "{{ commit_comment }}"
+  register: response
+  when: verb == "modify" and not (dry_run | ansible.builtin.bool) and (modify_metric | ansible.builtin.bool)
+
+- name: Show real diff of "{{ config_object }}"
+  ansible.builtin.debug:
+    msg: "{{ response }}"
+  when: verb == "deploy" and not (dry_run | ansible.builtin.bool) and (modify_metric | ansible.builtin.bool)
diff --git a/roles/iptrunks/tasks/iptrunks_compile_object.yaml b/roles/iptrunks/tasks/iptrunks_compile_object.yaml
index 2388f458418da11eb7c5ee9a49b27d60a8718fe0..adf58075d6f8340c2ede288ca001329b2640c8d5 100644
--- a/roles/iptrunks/tasks/iptrunks_compile_object.yaml
+++ b/roles/iptrunks/tasks/iptrunks_compile_object.yaml
@@ -1,20 +1,29 @@
----    
-#- name: Select the trunk based on trunkid    
-  #debug:    
-    ##msg: "Trunk data is:  {{ trunks|  selectattr('id', 'match', trunk_id ) | list }}"    
-    #msg: "{{ trunks }}"    
-    
-- name: Create a folder for all the templates     
-  ansible.builtin.file:    
-    path: "/var/tmp/ansible_run_{{opid}}"    
-    state: directory    
-    mode: '0755'    
-    
-- name: Print the template in "/var/tmp/ansible_run_{{opid}}/{{config_object}}.conf"    
-  template:    
-     src: "{{ config_object }}.j2"    
-     dest: "/var/tmp/ansible_run_{{opid}}/{{config_object}}.conf"    
-     lstrip_blocks: yes    
-     trim_blocks: yes    
-  delegate_to: localhost    
+---
+- name: Set ansible_host to terminal server when router is offline
+  ansible.builtin.set_fact:
+    ansible_host: localhost
+  when:
+    ( local_side.router_access_via_ts | ansible.builtin.bool ) is true
 
+- name: Create a folder for all the templates
+  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 }}/{{ config_object }}.conf"
+  ansible.builtin.template:
+    src: "{{ local_side.router_vendor }}/{{ config_object }}.j2"
+    dest: "/var/tmp/ansible_run_{{ opid }}/{{ config_object }}.conf"
+    lstrip_blocks: true
+    trim_blocks: true
+    mode: '0755'
+  delegate_to: localhost
+
+- name: Set ansible_host to terminal server when router is offline
+  ansible.builtin.set_fact:
+    ansible_host: "{{ local_side.router_site.site_ts_address }}"
+    ansible_port: "{{ local_side.router_ts_port }}"
+  when:
+    ( local_side.router_access_via_ts | ansible.builtin.bool ) is true
diff --git a/roles/iptrunks/tasks/iptrunks_deploy_object.yaml b/roles/iptrunks/tasks/iptrunks_deploy_object.yaml
index 3bc94781b01eb49cfd45a2d007b92a77f3e6f0b2..20231d9b6b260f78e88d8c4931273d7717558904 100644
--- a/roles/iptrunks/tasks/iptrunks_deploy_object.yaml
+++ b/roles/iptrunks/tasks/iptrunks_deploy_object.yaml
@@ -1,31 +1,70 @@
 ---
-- name: Deploy "{{config_object}}" [CHECK ONLY]
+- name: Deploy "{{ config_object }}" on "{{ inventory_hostname }}" [CHECK ONLY][JUNIPER]
   juniper_junos_config:
     load: 'replace'
-    src: "/var/tmp/ansible_run_{{opid}}/{{config_object}}.conf"
+    src: "/var/tmp/ansible_run_{{ opid }}/{{ config_object }}.conf"
     format: text
     config_mode: "private"
-    check: yes
-    commit: no
+    check: true
+    commit: false
   register: response
-  when: verb == "deploy" and dryrun | ansible.builtin.bool
+  when: >
+    verb == "deploy" and
+    local_side.router_vendor == "juniper" and
+    dry_run | ansible.builtin.bool
 
 - name: Show DRY diff of "{{ config_object }}"
-  debug:
-    msg: "{{response}}"
-  when: verb == "deploy" and dryrun | ansible.builtin.bool
+  ansible.builtin.debug:
+    msg: "{{ response }}"
+  when: >
+    verb == "deploy"
+    and dry_run | ansible.builtin.bool and
+    local_side.router_vendor == "juniper"
 
-- name: Deploy "{{config_object}}" [FOR REAL]
+- name: Deploy "{{ config_object }}" on "{{ inventory_hostname }}" [AND COMMIT][JUNIPER]
   juniper_junos_config:
     load: 'replace'
-    src: "/var/tmp/ansible_run_{{opid}}/{{config_object}}.conf"
+    src: "/var/tmp/ansible_run_{{ opid }}/{{ config_object }}.conf"
     format: text
     config_mode: "private"
-    commit: yes
-  register:  response
-  when: verb == "deploy" and not (dryrun | ansible.builtin.bool)
+    commit: true
+    comment: "{{ commit_comment }}"
+  register: response
+  when: >
+    verb == "deploy" and
+    local_side.router_vendor == "juniper" and
+    not (dry_run | ansible.builtin.bool)
 
 - name: Show real diff of "{{ config_object }}"
-  debug:
-    msg: "{{response}}"
-  when: verb == "deploy" and not (dryrun | ansible.builtin.bool)
+  ansible.builtin.debug:
+    msg: "{{ response }}"
+  when: >
+    verb == "deploy" and
+    local_side.router_vendor == "juniper" and
+    not (dry_run | ansible.builtin.bool)
+
+- name: Deploy "{{ config_object }}" on "{{ inventory_hostname }}" [CHECK ONLY][NOKIA]
+  ansible.netcommon.netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', '{{ local_side.router_vendor }}/{{ config_object }}.j2') }}"
+    commit: true
+  diff: true
+  check_mode: true
+  when: >
+    verb == "deploy" and
+    ( dry_run | ansible.builtin.bool ) is true and
+    local_side.router_vendor == "nokia"
+
+- name: Deploy base_config on "{{ inventory_hostname }}" [AND COMMIT][NOKIA]
+  ansible.netcommon.netconf_config:
+    format: xml
+    default_operation: merge
+    content: "{{ lookup('ansible.builtin.template', '{{ local_side.router_vendor }}/{{ config_object }}.j2') }}"
+    commit: true
+  diff: true
+  check_mode: false
+  when: >
+    verb == "deploy" and
+    ( dry_run | ansible.builtin.bool ) is false and
+    local_side.router_vendor == "nokia"
diff --git a/roles/iptrunks/tasks/iptrunks_remove_trunk.yaml b/roles/iptrunks/tasks/iptrunks_remove_trunk.yaml
index f1fbe7cde856c83c2ba886ded21bfb6684e95986..cc7190fca87bc13f832d01ac8b4d600b38b3518a 100644
--- a/roles/iptrunks/tasks/iptrunks_remove_trunk.yaml
+++ b/roles/iptrunks/tasks/iptrunks_remove_trunk.yaml
@@ -1,31 +1,32 @@
 ---
-- name: Deploy "{{config_object}}" [CHECK ONLY]
+- name: Deploy "{{ config_object }}" [CHECK ONLY]
   juniper_junos_config:
     load: merge
-    src: "/var/tmp/ansible_run_{{opid}}/{{config_object}}.conf"
+    src: "/var/tmp/ansible_run_{{ opid }}/{{ config_object }}.conf"
     format: set
     config_mode: "private"
-    check: yes
-    commit: no
+    check: true
+    commit: false
   register: response
-  when: verb == "remove" and dryrun | ansible.builtin.bool
+  when: verb == "terminate" and dry_run | ansible.builtin.bool
 
 - name: Show DRY diff of "{{ config_object }}"
-  debug:
-    msg: "{{response}}"
-  when: verb == "remove" and dryrun | ansible.builtin.bool
+  ansible.builtin.debug:
+    msg: "{{ response }}"
+  when: verb == "terminate" and dry_run | ansible.builtin.bool
 
-- name: Deploy "{{config_object}}" [FOR REAL]
+- name: Deploy "{{ config_object }}" [FOR REAL]
   juniper_junos_config:
     load: merge
-    src: "/var/tmp/ansible_run_{{opid}}/{{config_object}}.conf"
+    src: "/var/tmp/ansible_run_{{ opid }}/{{ config_object }}.conf"
     format: set
     config_mode: "private"
-    commit: yes
-  register:  response
-  when: verb == "remove" and not (dryrun | ansible.builtin.bool)
+    commit: true
+    comment: "{{ commit_comment }}"
+  register: response
+  when: verb == "terminate" and not (dry_run | ansible.builtin.bool)
 
 - name: Show real diff of "{{ config_object }}"
-  debug:
-    msg: "{{response}}"
-  when: verb == "remove" and not (dryrun | ansible.builtin.bool)
+  ansible.builtin.debug:
+    msg: "{{ response }}"
+  when: verb == "terminate" and not (dry_run | ansible.builtin.bool)
diff --git a/roles/iptrunks/tasks/main.yml b/roles/iptrunks/tasks/main.yml
index a0495c238ac09e440416a864d6f0456a0a51e8c3..a8500a3b1369f715e0fdd398ae9c93a458769705 100644
--- a/roles/iptrunks/tasks/main.yml
+++ b/roles/iptrunks/tasks/main.yml
@@ -1,37 +1,73 @@
 ---
-# tasks file for iptrunks 
+# tasks file for iptrunks
 - name: Print the usage
-  debug:
-    msg: 
-    - "Both 'verb' and 'config_object' are required."
-    - "Allowed verbs: 'compile', 'deploy'. Use: -e 'verb=$verb'"
-    - "Allowed objects: 'trunk_interface', 'isis', 'isis_interface', 'ldp_interface', 'lldp_interface'. Use: -e 'config_object=$config_object'"
-    - "'$trunk_id' must be defined for this role to work."
-  when: ((verb is not defined) or (config_object is not defined) or (trunk_id is not defined)) or (verb not in verbs) or (config_object not in config_objects)
-
-- meta: end_play
-  when: >-
-	 ((verb is not defined) or
-	(config_object is not defined) or (trunk_id is not defined)) or (verb not in verbs) or (config_object not in config_objects)
-
-- name: Gather_facts
-  junipernetworks.junos.junos_facts:
-    gather_subset: all
-
-- set_fact:
+  ansible.builtin.debug:
+    msg:
+      - "Both 'verb' and 'config_object' are required."
+      - "Allowed verbs: 'compile', 'deploy', 'modify'. Use: -e 'verb=$verb'"
+      - "Allowed objects: 'all', 'trunk_interface', 'isis', 'isis_interface', 'ldp_interface', 'lldp_interface'. Use: -e 'config_object=$config_object'"
+  when: ((verb is not defined) or (config_object is not defined)) or (verb not in verbs) or (config_object not in config_objects)
+
+- name: Fail if arguments are not correct
+  ansible.builtin.meta: end_play
+  when: ((verb is not defined) or (config_object is not defined)) or (verb not in verbs) or (config_object not in config_objects)
+
+- name: Import routers variables
+  ansible.builtin.include_vars:
+    dir: /opt/ansible_inventory/group_vars/routers
+
+- name: Set an ID for this run
+  ansible.builtin.set_fact:
     opid: "{{ lookup('community.general.random_string', length=18, special=false) }}"
     config_is_different: "False"
-    trunks: "{{ newtrunks }}"
+
+- name: Load local info
+  ansible.builtin.set_fact:
+    local_side: "{{ wfo_trunk_json | community.general.json_query(query) }}"
+  vars:
+    query: "iptrunk.iptrunk_sides[?iptrunk_side_node.router_fqdn == '{{ inventory_hostname }}'] | [0]"
+
+      # - name: Show local info
+      #   debug:
+      #     msg: "{{ local_side }}"
+      #
+      # - name: Stop
+      #   meta: end_play
+
+- name: Load netconf connection config
+  ansible.builtin.set_fact:
+    ansible_connection: "{{ netconf_access[local_side.router_vendor].ansible_connection }}"
+    ansible_network_os: "{{ netconf_access[local_side.router_vendor].ansible_network_os }}"
+
+- name: Load remote info
+  ansible.builtin.set_fact:
+    remote_side: "{{ wfo_trunk_json | community.general.json_query(query) }}"
+  vars:
+    query: "iptrunk.iptrunk_sides[?iptrunk_side_node.router_fqdn != '{{ inventory_hostname }}'] | [0]"
+
+- name: Set ansible_host to terminal server when router is offline
+  ansible.builtin.set_fact:
+    ansible_host: "{{ local_side.router_site.site_ts_address }}"
+    ansible_port: "{{ local_side.router_ts_port }}"
+  when:
+    ( local_side.router_access_via_ts | ansible.builtin.bool ) is true
 
 - name: Print the ID
-  debug:
-    msg: "{{opid}}"
+  ansible.builtin.debug:
+    msg: "{{ opid }}"
 
-- include_tasks: iptrunks_compile_object.yaml
-  when: (verb in verbs) 
+- name: Include compiling the template
+  ansible.builtin.include_tasks: iptrunks_compile_object.yaml
+  when: (verb in verbs)
 
-- include_tasks: iptrunks_deploy_object.yaml
+- name: Include the deployment tasks if specified
+  ansible.builtin.include_tasks: iptrunks_deploy_object.yaml
   when: verb == "deploy"
 
-- include_tasks: iptrunks_remove_trunk.yaml
-  when: verb == "remove"
+- name: Include the removal tasks if specified
+  ansible.builtin.include_tasks: iptrunks_remove_trunk.yaml
+  when: verb == "terminate"
+
+- name: Include the modification tasks if specified
+  ansible.builtin.include_tasks: iptrunk_modify_trunk.yaml
+  when: verb == "modify"
diff --git a/roles/iptrunks/templates/juniper/isis_interface.j2 b/roles/iptrunks/templates/juniper/isis_interface.j2
new file mode 100644
index 0000000000000000000000000000000000000000..a2f40ad302b34eb939c60b158d4fd071ebb042a7
--- /dev/null
+++ b/roles/iptrunks/templates/juniper/isis_interface.j2
@@ -0,0 +1,34 @@
+{##}
+{# Template to update the isis stanza with new interface #}
+{# It is included in isis.j2 when the playbook calling is cic_isis #}
+{##}
+{% if ansible_play_name != 'cic_isis' %}
+protocols {
+    isis {
+{% endif %}
+        {% for trunk in trunks %}
+        {% if inventory_hostname == trunk.config.nodeA.name  %}
+        {% set interface_name= trunk.config.nodeA.ae_name %}
+        {% set isis_metric= trunk.config.common.isis_metric %}
+        {% endif %}
+        {% if inventory_hostname == trunk.config.nodeB.name  %}
+        {% set interface_name= trunk.config.nodeB.ae_name %}
+        {% set isis_metric= trunk.config.common.isis_metric %}
+        {% endif %}
+        {% if interface_name is defined %}
+replace: interface {{ interface_name }}.0 {
+            point-to-point;
+                level 2 {
+                    post-convergence-lfa {
+                        node-protection;
+                    }
+                metric {{ isis_metric }};
+            }   
+        }
+
+        {% endif %}
+        {% endfor %}
+{% if ansible_play_name != 'cic_isis' %}
+    }
+}
+{% endif %}
diff --git a/roles/iptrunks/templates/juniper/ldp_interface.j2 b/roles/iptrunks/templates/juniper/ldp_interface.j2
new file mode 100644
index 0000000000000000000000000000000000000000..a74af1e22db1eecb195dd2e670aeddbc34b8a4fa
--- /dev/null
+++ b/roles/iptrunks/templates/juniper/ldp_interface.j2
@@ -0,0 +1,25 @@
+{##}
+{# Template to update the ldp stanza with new interface #}
+{# It is included in isis.j2 when the playbook calling is cic_isis #}
+{##}
+{% if ansible_play_name != 'cic_isis' %}
+protocols {
+    ldp {
+{% endif %}
+        {% for trunk in trunks %}
+        {% if inventory_hostname == trunk.config.nodeA.name  %}
+        {% set interface_name= trunk.config.nodeA.ae_name %}
+        {% set isis_metric= trunk.config.common.isis_metric %}
+        {% endif %}
+        {% if inventory_hostname == trunk.config.nodeB.name  %}
+        {% set interface_name= trunk.config.nodeB.ae_name %}
+        {% set isis_metric= trunk.config.common.isis_metric %}
+        {% endif %}
+        {% if interface_name is defined %}
+replace: interface {{ interface_name }}.0 ; 
+        {% endif %}
+        {% endfor %}
+{% if ansible_play_name != 'cic_isis' %}
+    }
+}
+{% endif %}
diff --git a/roles/iptrunks/templates/juniper/lldp_interface.j2 b/roles/iptrunks/templates/juniper/lldp_interface.j2
new file mode 100644
index 0000000000000000000000000000000000000000..0270e38ac63cf009db7648f275700ac6c4cbe572
--- /dev/null
+++ b/roles/iptrunks/templates/juniper/lldp_interface.j2
@@ -0,0 +1,29 @@
+{##}
+{# Template to update the isis stanza with new interface #}
+{# It is included in isis.j2 when the playbook calling is cic_isis #}
+{##}
+{% if ansible_play_name != 'cic_isis' %}
+protocols {
+    lldp {
+{% endif %}
+{% for trunk in trunks %}
+    {% if inventory_hostname == trunk.config.nodeA.name  %}
+        {% set local= trunk.config.nodeA %}
+        {% set remote= trunk.config.nodeB %}
+        {% set common= trunk.config.common %}
+    {% endif %}
+    {% if inventory_hostname == trunk.config.nodeB.name  %}
+        {% set local= trunk.config.nodeB %}
+        {% set remote= trunk.config.nodeA %}
+        {% set common= trunk.config.common %}
+    {% endif %}
+
+    {% for member in local.members %}
+    replace: interface {{member}}  ;
+    {% endfor %}
+
+    {% endfor %}
+{% if ansible_play_name != 'cic_isis' %}
+    }
+}
+{% endif %}
diff --git a/roles/iptrunks/templates/juniper/trunk_deprovision.j2 b/roles/iptrunks/templates/juniper/trunk_deprovision.j2
new file mode 100644
index 0000000000000000000000000000000000000000..06bc6d4b2b4abbcb9ce362bd2ba2e8ae1ff0b3aa
--- /dev/null
+++ b/roles/iptrunks/templates/juniper/trunk_deprovision.j2
@@ -0,0 +1,16 @@
+{% for trunk in trunks %}
+    {% if inventory_hostname == trunk.config.nodeA.name  %}
+    {% set local= trunk.config.nodeA %}
+    {% endif %}
+    {% if inventory_hostname == trunk.config.nodeB.name  %}
+    {% set local= trunk.config.nodeB %}
+    {% endif %}
+    {% if local is defined  %}
+delete protocols isis interface {{ local.ae_name }}
+delete interfaces {{ local.ae_name }}
+      {% for iface in local.members %}
+delete interfaces {{ iface }}
+delete protocols lldp interface {{ iface }}
+      {% endfor %}
+    {% endif %}
+{% endfor %}
diff --git a/roles/iptrunks/templates/juniper/trunk_interface.j2 b/roles/iptrunks/templates/juniper/trunk_interface.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f777953bbda222164468b39ad660256f397dc156
--- /dev/null
+++ b/roles/iptrunks/templates/juniper/trunk_interface.j2
@@ -0,0 +1,87 @@
+{##}
+{# Template to deploy a trunk interface, takes care of configuring Aggregated Ethernet and the physical interface(s) contained #}
+{# It is included in isis.j2 when the playbook calling is cic_isis #}
+{##}
+{% for trunk in trunks %}
+    {% if inventory_hostname == trunk.config.nodeA.name  %}
+        {% set local= trunk.config.nodeA %}
+        {% set remote= trunk.config.nodeB %}
+        {% set common= trunk.config.common %}
+    {% endif %}
+    {% if inventory_hostname == trunk.config.nodeB.name  %}
+        {% set local= trunk.config.nodeB %}
+        {% set remote= trunk.config.nodeA %}
+        {% set common= trunk.config.common %}
+    {% endif %}
+
+    {% if local is defined  %}
+    {##}
+    {# I need to sort the source and the destination alfabetically #} 
+    {% set trunk_direction_name = [ local.name.split(".")[1] | upper, remote.name.split(".")[1] | upper ] %}
+    {% set trunk_direction_name_sorted = trunk_direction_name|sort %}
+    {##}
+    interfaces {
+    replace: {{local.ae_name}} {
+            description "LAG INFRASTRUCTURE BACKBONE ${{ local.port_sid }} | {{ trunk_direction_name_sorted[0] }}-{{ trunk_direction_name_sorted[1] }}";
+            mtu 9192;
+            aggregated-ether-options {
+                bfd-liveness-detection {
+                    minimum-interval 3000;
+                    neighbor {{ remote['loopback'] }};
+                    local-address {{local['loopback']}};
+                }
+                minimum-links {{common.minimum_links}};
+                {#link-speed {{common.link_speed}};#}
+                lacp {
+                    active;
+                    periodic fast;
+                }
+            }
+            unit 0 {
+	    description "SRV_GLOBAL INFRASTRUCTURE BACKBONE #{{ trunk_direction_name_sorted[0] }}-{{ trunk_direction_name_sorted[1] }}-IPTRUNK ${{ trunk.id }}| {{ trunk_direction_name_sorted[0] }}-{{ trunk_direction_name_sorted[1] }} | {{ common.description }}";
+                family inet {
+                    accounting {
+                        source-class-usage {
+                            input;
+                        }
+                    }
+                    mtu 9000;
+                    filter {
+                        input bone-in;              
+                        output bone-out;
+                    }
+                    address {{local.ipv4_address}};
+                }
+                family iso;
+                family inet6 {
+                    mtu 9000;
+                    filter {
+                        input bone6-in;
+                        output bone6-out;
+                    }
+                    address {{local.ipv6_address}};
+                }
+                family mpls {
+                    maximum-labels 5;
+                }
+            }
+        }    
+    {% for member in local.members %}
+    replace: {{member}} {
+    description "PHY INFRASTRUCTURE BACKBONE P_{{local.ae_name}} | {{ trunk_direction_name_sorted[0] }}-{{ trunk_direction_name_sorted[1] }} | {{local.members_descriptions[loop.index0]}}";
+            gigether-options {
+                802.3ad {{local.ae_name}};
+            }
+        }
+    {% endfor %}
+    }
+    protocols {
+        lldp {
+        {% for member in local.members %}
+        replace: interface {{member}}  ;
+        {% endfor %}
+    
+        }
+    }
+    {% endif %}
+{% endfor %}
diff --git a/roles/iptrunks/templates/nokia/isis_interface.j2 b/roles/iptrunks/templates/nokia/isis_interface.j2
new file mode 100644
index 0000000000000000000000000000000000000000..699bf525414d5f6aba5ce915129ef75e76558ede
--- /dev/null
+++ b/roles/iptrunks/templates/nokia/isis_interface.j2
@@ -0,0 +1,31 @@
+<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 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">
+                <isis-instance>0</isis-instance>
+                    {% for trunk in trunks %}
+                    {% if inventory_hostname == trunk.config.nodeA.name  %}
+                    {% set interface_name= trunk.config.nodeA.ae_name %}
+                    {% set isis_metric= trunk.config.common.isis_metric %}
+                    {% endif %}
+                    {% if inventory_hostname == trunk.config.nodeB.name  %}
+                    {% set interface_name= trunk.config.nodeB.ae_name %}
+                    {% set isis_metric= trunk.config.common.isis_metric %}
+                    {% endif %}
+                    {% if interface_name is defined %}
+                    <interface 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">
+                        <interface-name>{{ interface_name }}.0</interface-name>
+                        <admin-state>enable</admin-state>
+                        <interface-type>point-to-point</interface-type>
+                        <level>
+                            <level-number>2</level-number>
+                            <metric>{{ isis_metric }}</metric>
+                        </level>
+                    </interface>
+                    {% endif %}
+                    {% endfor %}
+            </isis>
+        </router>
+    </configure>
+</config>
diff --git a/roles/iptrunks/templates/nokia/trunk_interface.j2 b/roles/iptrunks/templates/nokia/trunk_interface.j2
new file mode 100644
index 0000000000000000000000000000000000000000..646bca6f0817fe432be99e1aa146832fa17e4d88
--- /dev/null
+++ b/roles/iptrunks/templates/nokia/trunk_interface.j2
@@ -0,0 +1,87 @@
+<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">
+
+{##}
+{% for trunk in trunks %}
+    {% if inventory_hostname == trunk.config.nodeA.name  %}
+        {% set local= trunk.config.nodeA %}
+        {% set remote= trunk.config.nodeB %}
+        {% set common= trunk.config.common %}
+    {% endif %}
+    {% if inventory_hostname == trunk.config.nodeB.name  %}
+        {% set local= trunk.config.nodeB %}
+        {% set remote= trunk.config.nodeA %}
+        {% set common= trunk.config.common %}
+    {% endif %}
+
+    {% if local is defined  %}
+    {##}
+    {# I need to sort the source and the destination alfabetically #}
+    {% set trunk_direction_name = [ local.name.split(".")[1] | upper, remote.name.split(".")[1] | upper ] %}
+    {% set trunk_direction_name_sorted = trunk_direction_name|sort %}
+{##}
+{% for member in local.members %}
+
+<port 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">
+    <port-id>{{ member }}</port-id>
+    <admin-state>enable</admin-state>
+    <description>PHY INFRASTRUCTURE BACKBONE P_{{local.ae_name}} | {{ trunk_direction_name_sorted[0] }}-{{ trunk_direction_name_sorted[1] }} | {{local.members_descriptions[loop.index0]}}</description>
+    <ethernet>
+        <mode>network</mode>
+        <mtu>9212</mtu>
+        <lldp>
+            <dest-mac>
+                <mac-type>nearest-bridge</mac-type>
+                <receive>true</receive>
+                <transmit>true</transmit>
+                <tx-tlvs>
+                    <port-desc>true</port-desc>
+                    <sys-name>true</sys-name>
+                    <sys-cap>true</sys-cap>
+                </tx-tlvs>
+            </dest-mac>
+        </lldp>
+    </ethernet>
+</port>
+{% endfor %}
+<lag 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">
+    <lag-name>{{local.ae_name}}</lag-name>
+    <admin-state>enable</admin-state>
+    <description>LAG INFRASTRUCTURE BACKBONE ${{ local.port_sid }} | {{ trunk_direction_name_sorted[0] }}-{{ trunk_direction_name_sorted[1] }}</description>
+    <mode>network</mode>
+    <lacp>
+        <mode>active</mode>
+        <administrative-key>{{(local.ae_name|split("-"))[1]}}</administrative-key>
+    </lacp>
+{% for member in local.members %}
+    <port>
+        <port-id>{{member}}</port-id>
+    </port>
+{% endfor %}
+</lag>
+<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>
+    <interface alu:operation="replace">
+        <interface-name>{{local.ae_name}}.0</interface-name>
+        <admin-state>enable</admin-state>
+        <description>SRV_GLOBAL INFRASTRUCTURE BACKBONE #{{ trunk_direction_name_sorted[0] }}-{{ trunk_direction_name_sorted[1] }}-IPTRUNK ${{ trunk.id }}| {{ trunk_direction_name_sorted[0] }}-{{ trunk_direction_name_sorted[1] }} | {{ common.description }}</description>
+        <port>{{local.ae_name}}</port>
+        <ipv4>
+            <primary>
+                <address>{{(local.ipv4_address| split('/'))[0]}}</address>
+                <prefix-length>{{(local.ipv4_address| split('/'))[1]}}</prefix-length>
+            </primary>
+        </ipv4>
+        <ipv6>
+            <address>
+                <ipv6-address>{{(local.ipv6_address| split('/'))[0]}}</ipv6-address>
+                <prefix-length>{{(local.ipv6_address| split('/'))[1]}}</prefix-length>
+            </address>
+        </ipv6>
+    </interface>
+</router>
+    {% endif %}
+{% endfor %}
+
+</configure>
+</config>
diff --git a/roles/iptrunks/vars/main.yml b/roles/iptrunks/vars/main.yml
index 9db90dcf8598896a426b4b0f4d173a3b2e3f5f50..bfc459205d41c3c2f77722a1ece7db335e6f7a06 100644
--- a/roles/iptrunks/vars/main.yml
+++ b/roles/iptrunks/vars/main.yml
@@ -1,16 +1,58 @@
 ---
 # vars file for iptrunks
-dryrun: "True"    
-### Here I am selecting the single trunk I want to deploy    
-newtrunks: "{{ trunks | selectattr('id', 'match', trunk_id ) | list }}"   
+#
+#
+
+dry_run: "True"
+
 verbs:
   - "compile"
   - "deploy"
-  - "remove"
+  - "terminate"
+
 config_objects:
+  - "all"
   - "trunk_interface"
   - "isis"
   - "isis_interface"
   - "ldp_interface"
   - "lldp_interface"
   - "trunk_deprovision"
+
+wfo_trunk: "{{ wfo_trunk_json }}"
+config_object: "{{ object }}"
+
+side_a_ipv4_address: "{{ wfo_trunk.iptrunk.iptrunk_ipv4_network | ansible.utils.ipaddr('net') | ansible.utils.ipaddr('address') }}/31"
+side_a_ipv6_address: "{{ wfo_trunk.iptrunk.iptrunk_ipv6_network | ansible.utils.ipaddr('net') | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}/126"
+side_b_ipv4_address: "{{ wfo_trunk.iptrunk.iptrunk_ipv4_network | ansible.utils.ipaddr('net') | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}/31"
+side_b_ipv6_address: "{{ wfo_trunk.iptrunk.iptrunk_ipv6_network | ansible.utils.ipaddr('net') | ansible.utils.ipaddr('2') | ansible.utils.ipaddr('address') }}/126"
+
+trunks:
+  - id: "{{ wfo_trunk.iptrunk.geant_s_sid }}"
+    config:
+      common:
+        description: "{{ wfo_trunk.iptrunk.iptrunk_description }}"
+        speed: "{{ wfo_trunk.iptrunk.iptrunk_speed }}"
+        is_leased_line: false ## Fix it to use iptrunk_type
+        isis_metric: "{{ wfo_trunk.iptrunk.iptrunk_isis_metric }}"
+        minimum_links: "{{ wfo_trunk.iptrunk.iptrunk_minimum_links }}"
+      nodeA:
+        name: "{{ wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn }}"
+        router_access_via_ts: "{{ wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_access_via_ts }}"
+        loopback: "{{ wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_lo_ipv4_address }}"
+        ae_name: "{{ wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_ae_iface }}"
+        ipv4_address: "{{ side_a_ipv4_address }}"
+        ipv6_address: "{{ side_a_ipv6_address }}"
+        members: "{{ wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members }}"
+        members_descriptions: "{{ wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members_description }}"
+        port_sid: "{{ wfo_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid }}"
+      nodeB:
+        name: "{{ wfo_trunk.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn }}"
+        router_access_via_ts: "{{ wfo_trunk.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_access_via_ts }}"
+        loopback: "{{ wfo_trunk.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_lo_ipv4_address }}"
+        ae_name: "{{ wfo_trunk.iptrunk.iptrunk_sides[1].iptrunk_side_ae_iface }}"
+        ipv4_address: "{{ side_b_ipv4_address }}"
+        ipv6_address: "{{ side_b_ipv6_address }}"
+        members: "{{ wfo_trunk.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members }}"
+        members_descriptions: "{{ wfo_trunk.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members_description }}"
+        port_sid: "{{ wfo_trunk.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid }}"
diff --git a/roles/iptrunks_checks/README.md b/roles/iptrunks_checks/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..dac04c2d977f20299c47ef9e7a51f884969ec0cb
--- /dev/null
+++ b/roles/iptrunks_checks/README.md
@@ -0,0 +1,43 @@
+Role Name
+=========
+
+A small role that allows to perform ping over a trunk and check ISIS status of a specific interface
+
+Requirements
+------------
+
+Juniper.junos
+
+Role Variables
+--------------
+
+- check=(isis|ping): This select the type of check you want to execute
+- wfo_trunk_json=the iptrunk subscription coming from WFO: This allows to understand which interface and which IP addresses to use
+  
+
+
+
+Dependencies
+------------
+
+Juniper.junos ??
+
+Example Playbook
+----------------
+
+```
+ansible-playbook -i rt1.pi.it.geant.net, iptrunk_check.yaml -e check=isis -e wfo_trunk_json={json_structure coming from WFO} 
+```
+```
+ansible-playbook -i rt1.pi.it.geant.net, iptrunk_check.yaml -e check=ping -e wfo_trunk_json={json_structure coming from WFO} 
+```
+
+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/roles/iptrunks_checks/defaults/main.yml b/roles/iptrunks_checks/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1c88a7ad07e7ef602985f29582d98921fd7c5b9c
--- /dev/null
+++ b/roles/iptrunks_checks/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+# defaults file for iptrunks_checks
diff --git a/roles/iptrunks_checks/handlers/main.yml b/roles/iptrunks_checks/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6106d35f860c8c60ad0ae9e40dcd590eee08907f
--- /dev/null
+++ b/roles/iptrunks_checks/handlers/main.yml
@@ -0,0 +1,2 @@
+---
+# handlers file for iptrunks_checks
diff --git a/roles/iptrunks_checks/meta/main.yml b/roles/iptrunks_checks/meta/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0f5a7796e91b74c6e8ca44402537ba7084d75ddf
--- /dev/null
+++ b/roles/iptrunks_checks/meta/main.yml
@@ -0,0 +1,53 @@
+galaxy_info:
+  author: Simone Spinelli for GOAT
+  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:
+
+  #
+  # Provide a list of supported platforms, and for each platform a list of versions.
+  # If you don't wish to enumerate all versions for a particular platform, use 'all'.
+  # To view available platforms and versions (or releases), visit:
+  # https://galaxy.ansible.com/api/v1/platforms/
+  #
+  # platforms:
+  # - name: Fedora
+  #   versions:
+  #   - all
+  #   - 25
+  # - name: SomePlatform
+  #   versions:
+  #   - all
+  #   - 1.0
+  #   - 7
+  #   - 99.99
+
+  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/roles/iptrunks_checks/tasks/check_isis.yaml b/roles/iptrunks_checks/tasks/check_isis.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3ce3528803d6ba42df98687007e2f16005d349c7
--- /dev/null
+++ b/roles/iptrunks_checks/tasks/check_isis.yaml
@@ -0,0 +1,14 @@
+- name: Get status of ISIS
+  juniper_junos_command:
+    commands:
+      - show isis adjacency
+      - show isis interface "{{ trunks[0].config.nodeA.ae_name }}".0
+  register: response
+
+- name: Show status of ISIS djacencies
+  ansible.builtin.debug:
+    msg: "{{ response.results[0].stdout_lines }}"
+
+- name: Show status of ISIS interfaces
+  ansible.builtin.debug:
+    msg: "{{ response.results[1].stdout_lines }}"
diff --git a/roles/iptrunks_checks/tasks/check_ping.yaml b/roles/iptrunks_checks/tasks/check_ping.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..79b07175ec180b09762aefdff818e475347772ca
--- /dev/null
+++ b/roles/iptrunks_checks/tasks/check_ping.yaml
@@ -0,0 +1,16 @@
+- name: Ping "{{ trunks[0].config.nodeB.name }} on {{ side_b_ipv4_address.split('/')[0] }}"
+  juniper_junos_ping:
+    dest: "{{ side_b_ipv4_address.split('/')[0] }}"
+    count: 1000
+    size: 9000
+    rapid: true
+  register: response
+
+- name: Print the packet_loss percentage from the response.
+  ansible.builtin.debug:
+    var: response
+
+- name: If packet loss is not zero, than this check fails
+  ansible.builtin.fail:
+    msg: "{{ response.changed }}"
+  when: response.packet_loss != "0"
diff --git a/roles/iptrunks_checks/tasks/main.yml b/roles/iptrunks_checks/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..72c1874d1ec64b48ab3e86e3f6299d58bb08be38
--- /dev/null
+++ b/roles/iptrunks_checks/tasks/main.yml
@@ -0,0 +1,23 @@
+---
+# tasks file for iptrunks
+- name: Print the usage
+  ansible.builtin.debug:
+    msg:
+      - "Allowed checks: 'ping', 'isis'"
+  when: (check is not defined) or (check not in checks)
+
+- name: Fail if arguments are not correct
+  ansible.builtin.meta: end_play
+  when: (check is not defined) or (check not in checks)
+
+- name: Gather_facts
+  junipernetworks.junos.junos_facts:
+    gather_subset: all
+
+- name: Check ISIS
+  ansible.builtin.include_tasks: check_isis.yaml
+  when: check == "isis"
+
+- name: Check ping
+  ansible.builtin.include_tasks: check_ping.yaml
+  when: check == "ping"
diff --git a/roles/iptrunks_checks/vars/main.yml b/roles/iptrunks_checks/vars/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9ad27885c32b35aaaff6617643e57eefe7c400bf
--- /dev/null
+++ b/roles/iptrunks_checks/vars/main.yml
@@ -0,0 +1,44 @@
+---
+# vars file for iptrunks
+#
+
+checks:
+  - isis
+  - ping
+
+wfo_trunk: "{{ wfo_ip_trunk_json }}"
+
+side_a_ipv4_address: "{{ wfo_trunk.iptrunk.iptrunk_ipv4_network | ansible.utils.ipaddr('net') | ansible.utils.ipaddr('address') }}/31"
+side_a_ipv6_address: "{{ wfo_trunk.iptrunk.iptrunk_ipv6_network | ansible.utils.ipaddr('net') | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}/126"
+side_b_ipv4_address: "{{ wfo_trunk.iptrunk.iptrunk_ipv4_network | ansible.utils.ipaddr('net') | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}/31"
+side_b_ipv6_address: "{{ wfo_trunk.iptrunk.iptrunk_ipv6_network | ansible.utils.ipaddr('net') | ansible.utils.ipaddr('2') | ansible.utils.ipaddr('address') }}/126"
+
+trunks:
+  - id: "{{ wfo_trunk.iptrunk.geant_s_sid }}"
+    config:
+      common:
+        description: "{{ wfo_trunk.iptrunk.iptrunk_description }}"
+        speed: "{{ wfo_trunk.iptrunk.iptrunk_speed }}"
+        is_leased_line: false
+        isis_metric: "{{ wfo_trunk.iptrunk.iptrunk_isis_metric }}"
+        minimum_links: 1
+      nodeA:
+        name: "{{ wfo_trunk.iptrunk.iptrunk_sideA_node.router_fqdn }}"
+        router_access_via_ts: "{{ wfo_trunk.iptrunk.iptrunk_sideA_node.router_access_via_ts }}"
+        loopback: "{{ wfo_trunk.iptrunk.iptrunk_sideA_node.router_lo_ipv4_address }}"
+        ae_name: "{{ wfo_trunk.iptrunk.iptrunk_sideA_ae_iface }}"
+        ipv4_address: "{{ side_a_ipv4_address }}"
+        ipv6_address: "{{ side_a_ipv6_address }}"
+        members: "{{ wfo_trunk.iptrunk.iptrunk_sideA_ae_members }}"
+        members_descriptions: "{{ wfo_trunk.iptrunk.iptrunk_sideA_ae_members_description }}"
+        port_sid: "{{ wfo_trunk.iptrunk.iptrunk_sideA_ae_geant_a_sid }}"
+      nodeB:
+        name: "{{ wfo_trunk.iptrunk.iptrunk_sideB_node.router_fqdn }}"
+        router_access_via_ts: "{{ wfo_trunk.iptrunk.iptrunk_sideB_node.router_access_via_ts }}"
+        loopback: "{{ wfo_trunk.iptrunk.iptrunk_sideB_node.router_lo_ipv4_address }}"
+        ae_name: "{{ wfo_trunk.iptrunk.iptrunk_sideB_ae_iface }}"
+        ipv4_address: "{{ side_b_ipv4_address }}"
+        ipv6_address: "{{ side_b_ipv6_address }}"
+        members: "{{ wfo_trunk.iptrunk.iptrunk_sideB_ae_members }}"
+        members_descriptions: "{{ wfo_trunk.iptrunk.iptrunk_sideB_ae_members_description }}"
+        port_sid: "{{ wfo_trunk.iptrunk.iptrunk_sideB_ae_geant_a_sid }}"