Ansible Juniper galaxy

Dernière modification le 15 avril 2020

Appliqué à Juniper Junos, il existe trois façon d’utiliser Ansible. Depuis la version 2.7.10, des modules réseau agnostiques sont disponibles. L’utilisation des modules cli_command et cli_config à la place de eos_config, ios_config, et junos_config permettent de réaliser des playbooks agnostiques.

Depuis la version 2.1, Ansible est livré avec de nombreux modules réseau spécifiques pour les constructeurs, dont ceux de Juniper s’appuyant sur la librairie Python ncclient, et supportés par la communauté Ansible. En version 2.8, les modules disponibles pour Junos sont les suivants :

  • junos_banner: Manage multiline banners on Juniper JUNOS devices.
  • junos_command: Run arbitrary commands on an Juniper JUNOS device.
  • junos_config: Manage configuration on devices running Juniper JUNOS.
  • junos_facts: Collect facts from remote devices running Juniper Junos.
  • junos_interface: Manage Interface on Juniper JUNOS network devices.
  • junos_l2_interface: Manage Layer-2 interface on Juniper JUNOS network devices.
  • junos_l3_interface: Manage L3 interfaces on Juniper JUNOS network devices.
  • junos_lacp: Manage Global Link Aggregation Control Protocol (LACP) on Juniper Junos devices.
  • junos_lacp_interfaces: Manage Link Aggregation Control Protocol (LACP) attributes of interfaces on Juniper JUNOS devices.
  • junos_lag_interfaces: Manage Link Aggregation on Juniper JUNOS devices.
  • junos_lldp_global: Manage link layer discovery protocol (LLDP) attributes on Juniper JUNOS devices.
  • junos_lldp_interfaces: Manage link layer discovery protocol (LLDP) attributes of interfaces on Juniper JUNOS devices.
  • junos_logging: Manage logging on network devices.
  • junos_netconf: Configures the Junos Netconf system service.
  • junos_package: Installs packages on remote devices running Junos.
  • junos_ping: Tests reachability using ping from devices running Juniper JUNOS.
  • junos_rpc: Runs an arbitrary RPC over NetConf on an Juniper JUNOS device.
  • junos_scp: Transfer files from or to remote devices running Junos.
  • junos_static_route: Manage static IP routes on Juniper JUNOS network devices.
  • junos_system: Manage the system attributes on Juniper JUNOS devices.
  • junos_user: Manage local user accounts on Juniper JUNOS devices.
  • junos_vlan: Manage VLANs on Juniper JUNOS network devices.
  • junos_vrf: Manage the VRF definitions on Juniper JUNOS devices.

Certains constructeurs produisent et supportent leurs propres modules, souvent plus avancés et qui ont ma préférence, disponibles sous forme de rôles dans la Galaxy Ansible. Il faut noter qu’il est possible de mixer les deux catégories de modules dans un même playbook. Les rôles Juniper proposés dans Juniper.junos, s’appuyant sur le microframework PyEZ, sont les suivants :

  • juniper_junos_command: Execute one or more CLI commands on a Junos device.
  • juniper_junos_config: Manipulate the configuration of a Junos device.
  • juniper_junos_facts: Retrieve facts from a Junos device.
  • juniper_junos_jsnapy: Execute JSNAPy tests on a Junos device.
  • juniper_junos_ping: Execute ping from a Junos device.
  • juniper_junos_pmtud: Perform path MTU discovery from a Junos device to a destination.
  • juniper_junos_rpc: Execute one or more NETCONF RPCs on a Junos device.
  • juniper_junos_software: Install software on a Junos device.
  • juniper_junos_srx_cluster: Add or remove SRX chassis cluster configuration.
  • juniper_junos_system: Initiate operational actions on the Junos system.
  • juniper_junos_table: Retrieve data from a Junos device using a PyEZ table/view.

Ces modules nécessitent des dépendances dont les versions minimums sont les suivantes :

  • Python ≥ 2.7
  • Ansible ≥ 2.3
  • Junos py-junos-eznc ≥ 2.1.7
  • jxmlease ≥ 1.0.1

Voici un exemple d’une architecture Clos Network constituée de 2 switchs Spine et 2 switchs Leaf et lancée à l’aide de Vagrant et VirtualBox headless. Des rôles Ansible constituent une IPFabric eBGP et contrôlent le bon aboutissement opérationnel de l’infrastructure. Les rôles suivants remettent les switchs en situation minimum à l’aide de la configuration « rescue » et réalisent une IPFabric en OSPF avec un contrôle de bon fonctionnement associé. Cette architecture virtuelle est le reflet exact d’une architecture physique utilisée en lab.

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Gilbert MOISIO 2019

## Define port mapping to build the Fabric
spine_port_map = {  1 => [1,3],
                    2 => [2,4] }

leaf_port_map  = {  1 => [1,2],
                    2 => [3,4] }

Vagrant.configure("2") do |config|

  config.ssh.insert_key = false

#######################
# Spine configuration #
#######################
  (1..2).each do |id|
    re_name  = ( "spine0" + id.to_s ).to_sym
    config.vm.define re_name do |vqfx|
      vqfx.vm.host_name = "spine0#{id}"
      vqfx.vm.box = "gmoisio/vQFX-re"
      vqfx.vm.box_version = "18.4"
# Do not remove / No VMtools installed
      vqfx.vm.synced_folder ".", "/vagrant", disabled: true
# Management port (em1 / em2)
      vqfx.vm.network "private_network", auto_config: false, nic_type: "82540EM", virtualbox__intnet: "vqfx_internal_#{id}"
      vqfx.vm.network "private_network", auto_config: false, nic_type: "82540EM", virtualbox__intnet: "reserved-bridge"
# (em3, em4)
      (1..2).each do |seg_id|
        vqfx.vm.network "private_network", auto_config: false, nic_type: "82540EM", virtualbox__intnet: "non_used"
      end
# (em5, em6)
      (0..1).each do |seg_id|
        vqfx.vm.network "private_network", auto_config: false, nic_type: "82540EM", virtualbox__intnet: "seg#{spine_port_map[id][seg_id]}"
      end
    end
  end

#######################
# Leaf configuration  #
#######################
  (1..2).each do |id|
    re_name  = ( "leaf0" + id.to_s ).to_sym
    config.vm.define re_name do |vqfx|
      vqfx.vm.host_name = "leaf0#{id}"
      vqfx.vm.box = "gmoisio/vQFX-re"
      vqfx.vm.box_version = "18.4"
# Do not remove / No VMtools installed
      vqfx.vm.synced_folder ".", "/vagrant", disabled: true
# Management port (em1 / em2)
      vqfx.vm.network "private_network", auto_config: false, nic_type: "82540EM", virtualbox__intnet: "vqfx_internal_#{id}"
      vqfx.vm.network "private_network", auto_config: false, nic_type: "82540EM", virtualbox__intnet: "reserved-bridge"
# (em3, em4)
      (1..2).each do |seg_id|
        vqfx.vm.network "private_network", auto_config: false, nic_type: "82540EM", virtualbox__intnet: "non_used"
      end
# (em5, em6)
      (0..1).each do |seg_id|
        vqfx.vm.network "private_network", auto_config: false, nic_type: "82540EM", virtualbox__intnet: "seg#{leaf_port_map[id][seg_id]}"
      end
    end
  end

#######################
# Box provisioning    #
#######################
  config.vm.provision "ansible" do |ansible|
    ansible.compatibility_mode = "2.0"
    ansible.groups = {
                "qfx"          => ["spine01", "spine02", "leaf01", "leaf02"],
                "spine"        => ["spine01", "spine02"],
                "leaf"         => ["leaf01", "leaf02"],
                "all:children" => ["qfx"]
            }
    ansible.playbook = "site.yml"
    ansible.tags = "ospf"
  end

end