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 }}"