It occurred to me that there is essentially quite a lot of repetition within our labs, and as such if we rebuild we’re creating the same tasks over and over again.

Step forward: automation, or specifically ansible.

To do this, we’re not looking to ‘fully’ automate at this point. I’m still picking up ansible hence our ansible setup with grow with the blog – but being able to get some basics present would be useful.

Tweaking the ESXi Environment

  • We’re going to add a new port-group ‘Management’, using our WAN vSwitch – with the port-group assigned vlan 200.
  • Routers, R1 and R2 (as seen in the ipsla lab) have their 1st NIC moved into the Management port-group we’ve just created.

This gives us an out-of-band vlan, which in the real world would be connected via some level of console server.

Building our Ansible Server

The basic build is essentially a simple linux install:

  • Ubuntu 18.04 LTS Server
  • 16Gb Disk
  • 2 Gb RAM
  • 2x NICS – first, in our ‘Management’ vlan, the second in a natted vlan for updates

Once we’ve gotten through the build, we need to install ansible, and our ansible JunOS modules:

  • apt-get install ansible
  • apt-get install python-pip
  • apt-get install sshpass
  • apt-get install udhcpd
  • pip install ncclient
  • pip instal junos-eznc
  • ansible-galaxy install Juniper.junos
  • pip install juniper-netconify

(the latter not strictly necessary but useful for netconf && opengear)

Connecting the dots – Ansible talks to R1

Configuring our Ansible Server

At this point we need to get the Ansible server able to talk to R1, to do first, firstly we’ll edit our netplan file (/etc/netplan/50-cloud-init.yaml ) to apply to our ‘Management’ interface (ens33 in our case) and restart netplan.

            addresses: []
            dhcp4: false

Next, we need (going forward) to assign a static address to R1 via udhcpd by adding the following lines to /etc/udhcpd.conf – the mac address we find from ESXI’s NIC1 mac under the virtual machine settings.

start	#default:
end	#default:
static_lease 00:0C:29:B3:6F:39

Configuring R1

I said at the beginning, this is not zero-touch provisioning – we do need to put some management config onto R1 after running request system zeroize to wipe the configuration. Specifically, we set hostname, root, management vrf, dhcp on fxp0, enable netconf and ssh and finally create an ansible user.

  • set system host-name local-r1
  • set system root-authentication plain-text-password (password1)
  • set system management-interface
  • set interface fxp0.0 family inet dhcp
  • set system services netconf ssh
  • set system login user ansible class super-user authentication plain-text-password (ansible1)
  • commit

Verifying R1 has an address

ansible@local-r1> show interfaces fxp0.0
Logical interface fxp0.0 (Index 7) (SNMP ifIndex 13)
    Flags: Up SNMP-Traps 0x4000000 Encapsulation: ENET2
    Input packets : 702
    Output packets: 538
    Protocol inet, MTU: 1500
    Max nh cache: 100000, New hold nh limit: 100000, Curr nh cnt: 1,
    Curr new hold cnt: 0, NH drop cnt: 0
      Flags: Sendbcast-pkt-to-re, Is-Primary
      Addresses, Flags: Is-Default Is-Preferred Is-Primary
        Destination: 192.168.0/24, Local:, Broadcast:

Testing Connectivity from Ansible to R1

To test Ansible talking to R1, we need to SSH in from the Ansible Server first to get round strict host key checking, plus we’ll be using a password in this example.

We’ll need to create a directory tree similar to the below

labs# tree 
└── eem-lab
    ├── apply_common.yaml
    ├── group_vars
    │   └── eem_lab
    └── host_vars
        └── eem-lab-r1

Into group_vars/eem_lab we’ll add our standard username/password for our lab group:

ansible_user: ansible
ansible_ssh_pass: ansible1

Into host_vars/eem-lab-r1 we map our name to our ip


Finally into /etc/ansible/hosts we add a section for our eem-lab


Ansible now knows that for hosts under eem_lab, use the ansible user and pass, and also that eem-lab-r1 maps to

Our First Command

eem-lab# ansible eem_lab -m raw -a “show system uptime”

eem-lab-r1 | SUCCESS | rc=0 >>
Current time: 2019-02-11 23:36:50 UTC
Time Source:  LOCAL CLOCK 
System booted: 2019-02-11 20:38:06 UTC (02:58:44 ago)Protocols started: 2019-02-11 20:43:30 UTC (02:53:20 ago)
Last configured: 2019-02-11 21:17:33 UTC (02:19:17 ago) by root
11:36PM  up 2:59, 2 users, load averages: 0.57, 0.92, 0.83
Shared connection to closed.

Our First Playbook

Our test playbook will run 2 commands to set packet mode on the device, so lets create the file apply_common.yaml

- name: Apply Common Settings
  hosts: eem-lab-r1
  connection: local
  gather_facts: no

    - name: Set packet mode
          - delete security        
          - set security forwarding-options family mpls mode packet-based

Now run this via: ansible-playbook apply_common.yaml

eem-lab# ansible-playbook apply_common.yaml 
ansible-playbook 2.5.1
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.7.15rc1 (default, Nov 12 2018, 14:31:15) [GCC 7.3.0]
Using /etc/ansible/ansible.cfg as config file

PLAYBOOK: apply_common.yaml *********************************************************************************************************************************************************************************************************
1 plays in apply_common.yaml

PLAY [Apply Common Settings] ********************************************************************************************************************************************************************************************************
META: ran handlers

TASK [Set packet mode] **************************************************************************************************************************************************************************************************************

changed: [eem-lab-r1] => {
    "changed": true, 
    "invocation": {
        "module_args": {
            "backup": false, 
            "comment": "configured by junos_config", 
            "confirm": 0, 
            "confirm_commit": false, 
            "host": null, 
            "lines": [
                "delete security", 
                "set security forwarding-options family mpls mode packet-based"
            "password": null, 
            "port": null, 
            "provider": {
                "host": null, 
                "password": null, 
                "port": null, 
                "ssh_keyfile": null, 
                "timeout": null, 
                "transport": "netconf", 
                "username": null
            "replace": null, 
            "rollback": null, 
            "src": null, 
            "src_format": null, 
            "ssh_keyfile": null, 
            "timeout": null, 
            "transport": null, 
            "update": "merge", 
            "username": null, 
            "zeroize": false
META: ran handlers
META: ran handlers

PLAY RECAP **************************************************************************************************************************************************************************************************************************
eem-lab-r1                 : ok=1    changed=1    unreachable=0    failed=0   

Voila, applied – now to rework labs to make provisioning that bit faster.


No responses yet

Leave a Reply

Your email address will not be published. Required fields are marked *

About This Site

This may be a good place to introduce yourself and your site or include some credits.