Skip to content

Ansible on Fedora

The goal of this post is to describe the steps needed to install and configure Ansible to connect to a Nokia 7×50 via NETCONF.

I’ve just installed an empty Fedora server and configured the network interfaces.

Installation of Ansible is pretty straightforward, just use yum:

sudo yum install -y ansible

Check which version:

[larsg@fc-server ~]$ ansible --version
ansible 2.5.5
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/larsg/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.15 (default, May 16 2018, 17:50:09) [GCC 8.1.1 20180502 (Red Hat 8.1.1-1)]
To be able to use NETCONF for configuration of the 7750-SR we need to install ncclient.
sudo yum install python-pip
sudo pip install ncclient
We need to add the SRs to the hosts file, to be able to configure them via Ansible

sudo vi /etc/ansible/hosts
[nokia]
r1
r2
This creates the "group" nokia and puts r1 and r2 in this group.

I then add some entries in the hosts file to be able to use the names instead of IP’s.

sudo vi /etc/hosts
10.23.16.41 r1
10.23.16.42 r2
For Ansible to connect to the SRs we need the host key saved in ~/.ssh/known_hosts. The easiest way to do this is to connect to the device using SSH and answering yes to saving the host key.
[larsg@fc-server ansible]$ ssh r1
The authenticity of host 'r1 (10.23.16.41)' can't be established.
RSA key fingerprint is SHA256:kdE6JrRgpflIzPW6R67/lBGkWLYW7e9mRiGPWOejDO0.
RSA key fingerprint is MD5:98:f5:24:1e:b0:16:eb:00:00:69:4c:9c:b4:3e:ee:ca.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'r1,10.23.16.41' (RSA) to the list of known hosts.'
If i don’t do this, i get the following error in Ansible:
An exception occurred during task execution. To see the full traceback, use -vvv.
The error was: SSHUnknownHostError: Unknown host key [98:f5:24:1e:b0:16:eb:00:00:69:4c:9c:b4:3e:ee:ca] for [r1]
fatal: [r1]: FAILED! > {"changed": false, "msg": "error connecting to the device: Unknown host key [98:f5:24:1e:b0:16:eb:00:00:69:4c:9c:b4:3e:ee:ca] for [r1]"}
to retry, use: --limit @/home/larsg/ansible/fil1.retry

The SR also needs to be configured to allow NETCONF, below is the minimum configuration needed:

configure system security profile "administrative" netconf base-op-authorization lock
configure system security user admin access netconf
configure system netconf no shutdown
Now it’s time to create an Ansible playbook. This will be a very simple playbook with the XML directly in the playbook configuration.
[larsg@fc-server ansible]$ cat nokia-01.yml
---
- hosts: r1
  gather_facts: no
  connection: local

  tasks:
    - name: READ PARAMETERS
      include_vars:
        file: nodes/{{ inventory_hostname }}.yml

    - name: NETCONF TEST
      netconf_config:
        host: "{{ inventory_hostname }}"
        username: admin
        password: admin
        datastore: running
        xml: |
           <?xml version="1.0" encoding="UTF-8"?>
            <config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
             <configure xmlns="urn:alcatel-lucent.com:sros:ns:yang:conf-r13">
              <system>
               <name>
                 <system-name>{{ global_var.system_name }}</system-name>
                </name>   
               </system>
              </configure>
            </config>
...
The playbook works with the host “r1” , if i put “nokia” here instead it connects to both R1 and R2. The playbook also has two tasks. First we read parameters from the directory “nodes”, we look for a file named r1.yml in this example.
[larsg@fc-server ansible]$ cat nodes/r1.yml
global_var:
 system_name: r1
We then run the task NETCONF TEST using netconf_config module from Ansible. The XML part is where the magic happens. In this simple example we set the system name of the SR to what ever system_name is set to in the nodes/r1.yml file.

Now it’s time to run this very simple playbook and see what happens.

[larsg@fc-server ansible]$ ansible-playbook nokia-01.yml

PLAY [r1] *********************************************************************************

TASK [READ PARAMETERS] ********************************************************************
ok: [r1]

TASK [NETCONF TEST] ***********************************************************************
changed: [r1]

PLAY RECAP ********************************************************************************
r1                         : ok=2    changed=1    unreachable=0    failed=0   
Everything worked fine, the system name is set to R1.

To see more detailed output, add a couple of -v ‘s to ansible-playbook command.

[larsg@fc-server ansible]$ ansible-playbook nokia-01.yml -vvv
ansible-playbook 2.5.5
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/larsg/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.7.15 (default, May 16 2018, 17:50:09) [GCC 8.1.1 20180502 (Red Hat 8.1.1-1)]
Using /etc/ansible/ansible.cfg as config file
Parsed /etc/ansible/hosts inventory source with ini plugin

PLAYBOOK: nokia-01.yml ************************************************************************
1 plays in nokia-01.yml

PLAY [r1] *************************************************************************************
META: ran handlers

TASK [READ PARAMETERS] ************************************************************************
task path: /home/larsg/ansible/nokia-01.yml:8
ok: [r1] => {
    "ansible_facts": {
        "global_var": {
            "system_name": "r1"
        }
    },
    "ansible_included_var_files": [
        "/home/larsg/ansible/nodes/r1.yml"
    ],
    "changed": false
}

TASK [NETCONF TEST] ***************************************************************************
task path: /home/larsg/ansible/nokia-01.yml:12
Using module file /usr/lib/python2.7/site-packages/ansible/modules/network/netconf/netconf_config.py
<r1> ESTABLISH LOCAL CONNECTION FOR USER: larsg
<-snip>
changed: [r1] => {
    "changed": true,
    "invocation": {
        "module_args": {
            "allow_agent": true,
            "datastore": "running",
            "host": "r1",
            "hostkey_verify": true,
            "look_for_keys": true,
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": 830,
            "save": false,
            "src": null,
            "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <config xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n  
             <configure xmlns=\"urn:alcatel-lucent.com:sros:ns:yang:conf-r13\">\n   <system>\n    <name>\n      <system-name>r1  
             </system-name>\n     </name>   \n    </system>\n   </configure>\n </config>\n"
        }
    },
    "server_capabilities": [
        "urn:alcatel-lucent.com:sros:ns:yang:conf-ifgrphandler-r13?module=alu-conf-ifgrphandler-r13&revision=2014-10-20",
       <cut some output>
    ]
}
META: ran handlers
META: ran handlers

PLAY RECAP **********************************************************************************
r1                         : ok=2    changed=1    unreachable=0    failed=0   
Without datastore running:

TASK [NETCONF TEST] **************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv.
The error was:   Writing to or reading from candidate datastore not supported in the specified namespace
fatal: [r1]: FAILED! => {"changed": false, "msg": "error editing configuration: \n            Writing to or reading from candidate datastore not supported in the specified namespace\n        "}
        to retry, use: --limit @/home/larsg/ansible/nokia-01.retry