diff --git a/ansible/group_vars/switches/junos b/ansible/group_vars/switches/junos index ad2df5672..4ec8a1f47 100644 --- a/ansible/group_vars/switches/junos +++ b/ansible/group_vars/switches/junos @@ -7,6 +7,22 @@ # For Juniper switches, this defines a 'provider' argument to the junos_* # modules. switch_junos_provider: - host: "{{ ansible_host }}" + host: "{{ ansible_host|default(inventory_hostname) }}" username: "{{ ansible_user }}" - password: "{{ ansible_ssh_pass }}" + password: "{{ ansible_ssh_pass|default(omit) }}" + ssh_keyfile: "{{ ansible_ssh_private_keyfile|default(omit) }}" + timeout: "{{ switch_junos_timeout|default(omit) }}" + +############################################################################### +# Configuration format. + +# Format of configuration in junos_switch_config and +# junos_switch_interface_config. May be one of 'set', 'text' or 'json'. +switch_junos_config_format: text + +############################################################################### +# Timeout. + +# Timeout in seconds for communicating with the network device either for +# connecting or sending commands. +switch_junos_timeout: 10 diff --git a/ansible/physical-network.yml b/ansible/physical-network.yml index 0f5c98719..d5eb86a36 100644 --- a/ansible/physical-network.yml +++ b/ansible/physical-network.yml @@ -38,9 +38,11 @@ roles: - role: ssh-known-host - - role: juniper-switch - juniper_switch_delegate_to: localhost - juniper_switch_type: "{{ switch_type }}" - juniper_switch_provider: "{{ switch_juniper_provider }}" - juniper_switch_config: "{{ switch_config }}" - juniper_switch_interface_config: "{{ switch_interface_config }}" + - role: junos-switch + junos_switch_delegate_to: localhost + junos_switch_venv: "{{ lookup('env', 'VIRTUAL_ENV') }}" + junos_switch_type: "{{ switch_type }}" + junos_switch_provider: "{{ switch_junos_provider }}" + junos_switch_config_format: "{{ switch_junos_config_format }}" + junos_switch_config: "{{ switch_config }}" + junos_switch_interface_config: "{{ switch_interface_config }}" diff --git a/ansible/roles/juniper-switch/tasks/main.yml b/ansible/roles/juniper-switch/tasks/main.yml deleted file mode 100644 index c828363be..000000000 --- a/ansible/roles/juniper-switch/tasks/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: Ensure Juniper switches are configured - junos_config: - provider: "{{ juniper_switch_provider }}" - src: junos-config.j2 - delegate_to: "{{ juniper_switch_delegate_to }}" diff --git a/ansible/roles/juniper-switch/README.md b/ansible/roles/junos-switch/README.md similarity index 67% rename from ansible/roles/juniper-switch/README.md rename to ansible/roles/junos-switch/README.md index aa94ff4bd..ed0652dfc 100644 --- a/ansible/roles/juniper-switch/README.md +++ b/ansible/roles/junos-switch/README.md @@ -1,5 +1,5 @@ -Juniper Switch -============== +JunOS Switch +============ This role configures Juniper switches using the `junos` Ansible modules. It provides a fairly minimal abstraction of the configuration interface provided @@ -9,21 +9,25 @@ configuration options. Requirements ------------ -The switches should be configured to allow SSH access. +The switches should be configured to allow access to NETCONF via SSH. Role Variables -------------- -`juniper_switch_delegate_to` is the host on which to execute the `junos` Ansible +`junos_switch_delegate_to` is the host on which to execute the `junos` Ansible modules. -`juniper_switch_provider` is authentication provider information passed as the +`junos_switch_provider` is authentication provider information passed as the `provider` argument to the `junos` modules. -`juniper_switch_config` is a list of configuration lines to apply to the switch, +`junos_switch_config_format` is the format of configuration in +`junos_switch_config` and `junos_switch_interface_config`. May be one of `set`, +`text` or `json`. + +`junos_switch_config` is a list of configuration lines to apply to the switch, and defaults to an empty list. -`juniper_switch_interface_config` contains interface configuration. It is a dict +`junos_switch_interface_config` contains interface configuration. It is a dict mapping switch interface names to configuration dicts. Each dict may contain the following items: @@ -48,19 +52,19 @@ passwords. It applies global configuration for LLDP, and enables two hosts: junos-switches gather_facts: no roles: - - role: juniper-switch - juniper_switch_delegate_to: localhost - juniper_switch_provider: + - role: junos-switch + junos_switch_delegate_to: localhost + junos_switch_provider: host: "{{ switch_host }}" username: "{{ switch_user }}" password: "{{ switch_password }}" - juniper_switch_config: + junos_switch_config: - "protocols {" - " lldp {" - " interface all;" - " }" - "}" - juniper_switch_interface_config: + junos_switch_interface_config: xe-1/1/1: description: server-1 config: diff --git a/ansible/roles/juniper-switch/defaults/main.yml b/ansible/roles/junos-switch/defaults/main.yml similarity index 74% rename from ansible/roles/juniper-switch/defaults/main.yml rename to ansible/roles/junos-switch/defaults/main.yml index ca3990b0f..33f0674ed 100644 --- a/ansible/roles/juniper-switch/defaults/main.yml +++ b/ansible/roles/junos-switch/defaults/main.yml @@ -5,6 +5,10 @@ junos_switch_delegate_to: # Authentication provider information. junos_switch_provider: +# Format of configuration in junos_switch_config and +# junos_switch_interface_config. May be one of 'set', 'text' or 'json'. +junos_switch_config_format: text + # List of configuration lines to apply to the switch. junos_switch_config: [] diff --git a/ansible/roles/junos-switch/tasks/main.yml b/ansible/roles/junos-switch/tasks/main.yml new file mode 100644 index 000000000..7506f89c4 --- /dev/null +++ b/ansible/roles/junos-switch/tasks/main.yml @@ -0,0 +1,26 @@ +--- +# NOTE: We are installing this into the system python packages because it does +# not seem to be possible to use ansible_python_interpreter in combination with +# delegate_to. This should be investigated in future as modification of system +# packages via pip is not ideal. +- name: Ensure python dependencies are installed + pip: + name: "{{ item }}" + delegate_to: "{{ junos_switch_delegate_to }}" + with_items: + - junos-eznc + - jxmlease + become: True + +- name: Ensure Juniper switches are configured + junos_config: + provider: "{{ junos_switch_provider }}" + src: "{{ junos_switch_src }}" + src_format: "{{ junos_switch_config_format }}" + delegate_to: "{{ junos_switch_delegate_to }}" + vars: + junos_switch_config_format_to_src: + set: junos-config-set.j2 + text: junos-config.j2 + json: junos-config.json.j2 + junos_switch_src: "{{ junos_switch_config_format_to_src[junos_switch_config_format] }}" diff --git a/ansible/roles/junos-switch/templates/junos-config-set.j2 b/ansible/roles/junos-switch/templates/junos-config-set.j2 new file mode 100644 index 000000000..d68d4d47c --- /dev/null +++ b/ansible/roles/junos-switch/templates/junos-config-set.j2 @@ -0,0 +1,20 @@ +#jinja2: trim_blocks: True,lstrip_blocks: True + +{% for line in junos_switch_config %} +{{ line }} +{% endfor %} + +{% for interface, config in junos_switch_interface_config.items() %} +{% if config.description is defined %} +set interfaces {{ interface }} description "{{ config.description }}"; +{% endif %} +{% for line in config.config %} +{% if line.startswith('set') %} +set interfaces {{ interface }} {{ line[4:] }} +{% elif line.startswith('delete') %} +delete interfaces {{ interface }} {{ line[7:] }} +{% else %} +{{ interface_config_lines_must_start_with_set_or_delete }} +{% endif %} +{% endfor %} +{% endfor %} diff --git a/ansible/roles/juniper-switch/templates/junos-config.j2 b/ansible/roles/junos-switch/templates/junos-config.j2 similarity index 64% rename from ansible/roles/juniper-switch/templates/junos-config.j2 rename to ansible/roles/junos-switch/templates/junos-config.j2 index 82c6da51f..928b2b709 100644 --- a/ansible/roles/juniper-switch/templates/junos-config.j2 +++ b/ansible/roles/junos-switch/templates/junos-config.j2 @@ -1,11 +1,12 @@ #jinja2: trim_blocks: True,lstrip_blocks: True -{% for line in juniper_switch_config %} +{% for line in junos_switch_config %} {{ line }} {% endfor %} +{% if junos_switch_interface_config %} interfaces { -{% for interface, config in juniper_switch_interface_config.items() %} +{% for interface, config in junos_switch_interface_config.items() %} {{ interface }} { {% if config.description is defined %} description "{{ config.description }}"; @@ -16,3 +17,4 @@ interfaces { } {% endfor %} } +{% endif %} diff --git a/ansible/roles/junos-switch/templates/junos-config.json.j2 b/ansible/roles/junos-switch/templates/junos-config.json.j2 new file mode 100644 index 000000000..d31979ee1 --- /dev/null +++ b/ansible/roles/junos-switch/templates/junos-config.json.j2 @@ -0,0 +1,12 @@ +{% set config = junos_switch_interface_config %} +{% if junos_switch_interface_config %} +{% set _ = config.setdefault('interfaces', []) %} +{% endif %} +{% for interface, config in junos_switch_interface_config.items() %} +{% set _ = config['interfaces'].append({'name': interface}) %} +{% if config.description is defined %} +{% set config['interfaces'][-1]['description'] = config.description %} +{% endif %} +{% set _ = config['interfaces'][-1].update(config.config) %} +{% endif %} +{{ config | to_nice_json }}