Hello my friend,

Thanks to my friends I have a chance to take part in a project, where we are heavily using Ansible for various tasks in real network. When there are several people working on a joint project, some rules are needed in order playbooks are consistent. We have taken Ansible roles as rules. And I realized that I should have used them for my examples from the very beginning.

Brief description

What are roles? Frankly speaking, for me it was not clear from the very beginning, what it is. I was thanking, probably roles refer to a user type or something similar, like role of the user in configuration of the device based on the privilege level. Well, it was my network background speaking. In reality roles is just a decomposition of the playbook to certain pieces, and structuring them in different folders with certain name conventions. In the official documentations the following info is provided:

– If roles/x/tasks/main.yml exists, tasks listed therein will be added to the play.
– If roles/x/handlers/main.yml exists, handlers listed therein will be added to the play.
– If roles/x/vars/main.yml exists, variables listed therein will be added to the play.
– If roles/x/defaults/main.yml exists, variables listed therein will be added to the play.
– If roles/x/meta/main.yml exists, any role dependencies listed therein will be added to the list of roles (1.3 and later).
– Any copy, script, template or include tasks (in the role) can reference files in roles/x/{files,templates,tasks}/ (dir depends on task) without having to path them relatively or absolutely.

Let’s see how we can use this information to improve our automation scripts

What we are going to test?

We will rebuild the playbook from the article about Ansible as VNF-M to utilise role. If it is possible, some modifications will be done to make usage of those playbooks more usefull.

Software version

The following components are used for the current lab:

  • CentOS 7 with python 2.7.
  • Ansible 2.4.2
  • Nokia (Alcatel-Lucent) SR OS 15.0.R7
  • Cisco IOS XRv

See the previous article to get details how to build the lab

Topology

There is no particular topology necessary for this lab, so we will use the same topology as we did in Ansible as VNF-M article:

As we are using Ansible to deploy virtual Nokia (Alcatel-Lucent) VSR and Cisco IOS XRv routers, there are no particular initial configuration files.

Utilizing roles to create playbook

Read the previous article about Ansible as VNF-M to get understanding, what the scope of the activities is.

What we are going to do in the present article is to combine in the single playbook possibility to deploy/undeploy both Nokia (Alcatel-Lucent) VSR and Cisco IOS XRv by adding corresponding keys. So the playbook is to be capable to understand keyword and act properly. Here we go:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ cat 108_lab.yml
---
- hosts
: linux
connection
: local
tags
: cisco_on
roles
:
- { role
: linux/108_lab, var_vendor: cisco, var_operation: deploy }
- hosts
: linux
connection
: local
tags
: nokia_on
roles
:
- { role
: linux/108_lab, var_vendor: nokia, var_operation: deploy  }
- hosts
: linux
connection
: local
tags
: cisco_off
roles
:
- { role
: linux/108_lab, var_vendor: cisco, var_operation: undeploy }
- hosts
: linux
connection
: local
tags
: nokia_off
roles
:
- { role
: linux/108_lab, var_vendor: nokia, var_operation: undeploy }
...

We have in this playbook four roles, which performs the following operations:

  • Deploy Nokia (Alcatel-Lucent) VSR
  • Deploy Cisco IOS XRv
  • Deploy Nokia (Alcatel-Lucent) VSR
  • Deploy Cisco IOS XRv

If you don’t mention keyword by the launch, all the tasks will be performed sequentially resulting in zero result, as all VMs are deployed and undeployed. To make use of this playbook, we launch it with certain tag:

1
$ ansible-playbook 108_lab.yml --tags nokia_on

Then it matched against tag field, within each entry and will launch only corresponding entry. You see, our role is located in folder “linux/108_lab”, which is located in “roles”. Besides launching the playbook, we also push some variables to it (var_vendor, var_operation), which are used further for launching proper tasks and opening proper files.

Let’s review the structure of the folders:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ls -lR roles/linux/108_lab/
roles/linux/108_lab/:
total 0
drwxrwxr-x. 2 aaa aaa 27 Mar 11 18:31 files
drwxrwxr-x. 2 aaa aaa 51 Mar 12 07:58 tasks
drwxrwxr-x. 2 aaa aaa 80 Mar 11 15:13 templates
drwxrwxr-x. 2 aaa aaa 56 Mar 11 18:25 vars
roles/linux/108_lab/files:
total 4
-rwxr-xr-x. 1 aaa aaa 178 Mar 11 18:31 magic_wand.py
roles/linux/108_lab/tasks:
total 12
-rw-rw-r--. 1 aaa aaa 301 Mar 12 07:58 main.yml
-rw-rw-r--. 1 aaa aaa 912 Mar 11 22:14 off.yml
-rw-rw-r--. 1 aaa aaa 2758 Mar 11 22:14 on.yml
roles/linux/108_lab/templates:
total 8
-rwxrwxrwx. 1 aaa aaa 2949 Mar 11 15:12 template-cisco-iosxr-6.1.2.j2
-rwxrwxrwx. 1 aaa aaa 2640 Mar 11 15:13 template-nokia-sros-15.0R7.j2
roles/linux/108_lab/vars:
total 8
-rwxrwxrwx. 1 aaa aaa 1087 Mar 11 18:20 new_vnf_cisco.yml
-rwxrwxrwx. 1 aaa aaa 1399 Mar 11 15:18 new_vnf_nokia.ym

Following guidelines form official Ansible documentation (link), we create 4 folders in our role folder:

  • “files” to handle all files, we utilize additionally in our script
  • “tasks” to store all tasks, including default
  • “templates” to store all templates we use in this playbook
  • “vars” contain all values, we need to import for our tasks

Let’s review them!

#1. Tasks

Let’s start straight with the task file, which are loaded by default, which is “main.yml”:

1
2
3
4
5
6
7
8
9
10
11
$ cat roles/linux/108_lab/tasks/main.yml
- name
: READING VNF DATA // {{ var_vendor }}
include_vars
:
file
: new_vnf_{{ var_vendor }}.yml
name
: VM1
- name
: PERFORMING ONBOARDING
include_tasks
: on.yml
when
: var_operation == "deploy"
- name
: PERFORMING UNDEPLOYING
include_tasks
: off.yml
when
: var_operation == "undeploy"

The first activity in the tasks imports vendor-dependent variables, by calling file that contains value of “{{ var_vendor }}” value, which is usual operation for parametrisation.

Point out, you don’t need to include absolute or relative path to file. That works for files with variables from “vars” folder in case of roles.

Then depending on operation type, whether we want to deploy or undeploy VM with Nokia (Alcatel-Lucent) VSR or Cisco ISO XRv, we add appropriate tasks. Those files are modifications of “transformer_on.yml” and “transformer_off,yml” we had previously.

For onboarding of VNFs the additional file looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
$ cat roles/linux/108_lab/tasks/on.yml
- name
: COPYING VM IMAGE TO PROPER DIRECTORY
copy
:
src
: "{{ VM1.nfvo.vnfd.vdu.image_path.source }}/default-image-{{ VM1.nfvo.vnfd.vendor }}-{{ VM1.nfvo.vnfd.os }}-{{ VM1.nfvo.vnfd.version }}.qcow2"
dest
: "{{ VM1.nfvo.vnfd.vdu.image_path.destination }}/{{ VM1.nfvo.vnfd.vdu.image_name }}"
become
: yes
- name
: DEFINE VM IN KVM // {{ var_vendor }}
virt
:
name
: "{{ VM1.nfvo.vnfd.hostname }}"
command
: define
xml
: "{{ lookup('template', 'template-cisco-iosxr-6.1.2.j2') }}"
become
: yes
when
: var_vendor == "cisco"
- name
: DEFINE VM IN KVM // {{ var_vendor }}
virt
:
name
: "{{ VM1.nfvo.vnfd.hostname }}"
command
: define
xml
: "{{ lookup('template', 'template-nokia-sros-15.0R7.j2') }}"
become
: yes
when
: var_vendor == "nokia"
- name
: LAUNCHING {{ VM1.nfvo.vnfd.hostname }} ON KVM
virt
:
name
: "{{ VM1.nfvo.vnfd.hostname }}"
state
: running
become
: yes
- name
: UPDATING ANSIBLE HOSTS FOR {{ VM1.nfvo.vnfd.hostname }}
lineinfile
:
path
: /etc/ansible/hosts
regexp
: '{{ VM1.nfvo.vnfd.hostname }}'
line
: '{{ VM1.nfvo.vnfd.hostname }}'
insertafter
: '^\[{{ VM1.nfvo.vnfd.vendor }}\]'
become
: yes
- name
: UPDATING LINUX HOSTS FOR {{ VM1.nfvo.vnfd.hostname }}
lineinfile
:
path
: /etc/hosts
regexp
: '{% for iface in VM1.nfvo.vnfd.vdu.interfaces %}{% if iface.connection_point == "br0" %}{{ iface.address }}{% endif %}{% endfor %}'
line
: '{% for iface in VM1.nfvo.vnfd.vdu.interfaces %}{% if iface.connection_point == "br0" %}{{ iface.address }}{% endif %}{% endfor %} {{ VM1.nfvo.vnfd.hostname }}'
become
: yes
- name
: WAITING FOR {{ VM1.nfvo.vnfd.hostname }} TO BOOT
pause
:
seconds
: "{{ VM1.nfvo.vnfd.vdu.bootup_time }}"
- name
: ONLY FOR {{ VM1.nfvo.vnfd.vendor }} // MAKING ROUTER REACHABLE ON CLI
script
: magic_wand.py
when
: ( VM1.nfvo.vnfd.vendor == "cisco" and VM1.nfvo.vnfd.os == "iosxr" )
- name
: ONLY FOR {{ VM1.nfvo.vnfd.vendor }} // CONFIGURING OOB INTERFACE
telnet
:
host
: "{{ VM1.nfvo.vnfd.vdu.console.address }}"
port
: 3517
user
: cisco
password
: cisco
pause
: 1
login_prompt
: "Username: "
prompts
:
- "[>|#]"
command
:
- configure terminal
- ssh server v2
- ssh server vrf MGMT
- ssh server netconf vrf MGMT
- netconf-yang agent
- ssh
- vrf MGMT
- address-family ipv4 unicast
- interface MgmtEth0/0/CPU0/0
- ipv4 address {% for iface in VM1.nfvo.vnfd.vdu.interfaces %}{% if iface.connection_point == "br0" %}{{ iface.address }}/{{ iface.netmask }}{% endif %}{% endfor %}
- no shutdown
- vrf MGMT
- control-plane
- management-plane
- out-of-band
- vrf MGMT
- interface MgmtEth0/0/CPU0/0
- allow SSH
- allow NETCONF
- commit
- clear
- exit
when
: ( VM1.nfvo.vnfd.vendor == "cisco" and VM1.nfvo.vnfd.os == "iosxr" )

Comparing to previous version, we utilize template for VNF definition in much more elegant way without converting it to YAML. We do it on a cost of creation of two tasks for defining VNF, which compare “var_vendor” value coming from initial call.

One additional change you might spot in the last task (and in the task for updating hosts), where management IPv4 address of VNF is defined through more complex construction than it was previously. In the next sub chapter you will see the difference in variables. The rest of the playbook is the same

Alternatively we can make comparison against “VM1.nfvo.vnfd.vendor” variable.

For dismantling the VNFs we have:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ cat roles/linux/108_lab/tasks/off.yml
- name
: DESTROYING {{ VM1.nfvo.vnfd.hostname }} IN KVM
virt
:
name
: "{{ VM1.nfvo.vnfd.hostname }}"
command
: destroy
become
: yes
- name
: UNDEFINING {{ VM1.nfvo.vnfd.hostname }} IN KVM
virt
:
name
: "{{ VM1.nfvo.vnfd.hostname }}"
command
: undefine
become
: yes
- name
: DELETING {{ VM1.nfvo.vnfd.hostname }} IMAGE FROM LIBRARY
file
:
path
: "{{ VM1.nfvo.vnfd.vdu.image_path.destination }}/{{ VM1.nfvo.vnfd.vdu.image_name }}"
state
: absent
become
: yes
- name
: REMOVING {{ VM1.nfvo.vnfd.hostname }} FROM ANSIBLE HOSTS
lineinfile
:
path
: /etc/ansible/hosts
regexp
: '{{ VM1.nfvo.vnfd.hostname }}'
state
: absent
become
: yes
- name
: REMOVING {{ VM1.nfvo.vnfd.hostname }} FROM LINUX HOSTS
lineinfile
:
path
: /etc/hosts
regexp
: '{% for iface in VM1.nfvo.vnfd.vdu.interfaces %}{% if iface.connection_point == "br0" %}{{ iface.address }}{% endif %}{% endfor %} {{ VM1.nfvo.vnfd.hostname }}'
state
: absent
become
: yes

There is no changes at all comparing to initial Ansible-playbook, besides changes in the hosts file update.

#2. Vars

As you see in the output of the folder listing previously, we have here our VNF description files, which are used for VNF definition. Here is the output of Nokia (Alcatel-Lucent) VSR definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
$ cat roles/linux/108_lab/vars/new_vnf_nokia.yml
---
nfvo
:
vnfd
:
hostname
: VSR7
vendor
: nokia
os
: sros
version
: 15.0R7
vdu
:
vcpus
: 4
memory_b
: 4194304
disk_size_gb
: 1
image_name
: VSR7-nokia-sros-15.0R7.qcow2
image_path
:
source
: ~/temp
destination
: /var/lib/libvirt/images
bootup_time
: 180
license
:
file
: sros15.lic
path
: 192.168.1.1
username
: nokia
password
: nokianokia
chassis
:
type
: VSR-I
slot
:
id
: 0
type
: A
card
:
id
: 0
type
: cpm-v
mda1
:
id
: 1
type
: m20-v
mda2
:
id
: 2
type
: isa-tunnel-v
interfaces
:
- id
: 0
physical_interface
: vnet0
network_name
: Management
connection_point
: br0
mac
: 00:A1:00:15:07:00
address
: 192.168.1.107
netmask
: 24
vnic_type
: virtio
- id
: 1
physical_interface
: vnet1
network_name
: Data1
connection_point
: br1
mac
: 00:A1:00:15:07:01
vnic_type
: virtio
- id
: 2
physical_interface
: vnet2
network_name
: Data2
connection_point
: br2
mac
: 00:A1:00:15:07:02
vnic_type
: virtio
console
:
address
: 0.0.0.0
port
: 2517

You see that description of interfaces looks different now. Such model is called dictionary in Ansible and is actively used for templates, where same set of fields have different values many times. Just in the next sub chapter will see the advantage of such model.

For Cisco, refer to the original article. The changes regarding interfaces are the same

#3. Templates

Here we have templates that are used for definition of VNFs. That’s actually the same XML files we created in the article about Ansible as VNF-M last time, with updates for interface creation part and IP address definition for BOF. Besides those changes we also have changed the extension from “.xml” to “.j2”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
$ cat roles/linux/108_lab/templates/template-nokia-sros-15.0R7.j2
<domain type='kvm'>
<name>{{ VM1.nfvo.vnfd.hostname }}</name>
<uuid></uuid>
<memory>{{ VM1.nfvo.vnfd.vdu.memory_b }}</memory>
<currentMemory>4194304</currentMemory>
<cpu mode='custom' match='minimum'>
<model>SandyBridge</model>
<vendor>Intel</vendor>
<feature policy='require' name='x2apic'/>
</cpu>
<vcpu current='4'>{{ VM1.nfvo.vnfd.vdu.vcpus }}</vcpu>
<os>
<type arch='x86_64' machine='rhel6.0.0'>hvm</type>
<smbios mode='sysinfo'/>
</os>
<sysinfo type='smbios'>
<system>
<entry name='product'>TIMOS:address={% for iface in VM1.nfvo.vnfd.vdu.interfaces %}{% if iface.connection_point == "br0" %}{{ iface.address }}/{{ iface.netmask }}{% endif %}{% endfor %}@active license-file=ftp://{{ VM1.nfvo.vnfd.vdu.license.username }}:{{ VM1.nfvo.vnfd.vdu.license.password }}@{{ VM1.nfvo.vnfd.vdu.license.path }}/{{ VM1.nfvo.vnfd.vdu.license.file }} slot={{ VM1.nfvo.vnfd.vdu.chassis.slot.type }} chassis={{ VM1.nfvo.vnfd.vdu.chassis.type }} card={{ VM1.nfvo.vnfd.vdu.chassis.slot.card.type }} mda/1={{ VM1.nfvo.vnfd.vdu.chassis.slot.card.mda1.type }} mda/2={{ VM1.nfvo.vnfd.vdu.chassis.slot.card.mda2.type }}</entry>
</system>
</sysinfo>
<clock offset='utc'>
<timer name='pit' tickpolicy='delay'/>
<timer name='rtc' tickpolicy='delay'/>
</clock>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none'/>
<source file='{{ VM1.nfvo.vnfd.vdu.image_path.destination }}/{{ VM1.nfvo.vnfd.vdu.image_name }}'/>
<target dev='hda' bus='virtio'/>
</disk>
{% for iface in VM1.nfvo.vnfd.vdu.interfaces %}
<interface type='bridge'>
<mac address='{{ iface.mac}}'/>
<source bridge='{{ iface.connection_point}}'/>
<model type='{{ iface.vnic_type}}'/>
</interface>
{% endfor %}
<console type='tcp'>
<source mode='bind' host='{{ VM1.nfvo.vnfd.vdu.console.address}}' service='{{ VM1.nfvo.vnfd.vdu.console.port}}'/>
<protocol type='{{ VM1.nfvo.vnfd.vdu.console.protocol}}'/>
<target type='virtio' port='0'/>
</console>
</devices>
</domain>

The construct for definition of the interfaces is the traditional “for” cycle from programming, which is very wide distributed for repetitive actions. So we do not need to define explicitly in template the number of interfaces, rather they will be automatically replicated to the number defined in VNF description module.

#4. Files

Here we have just one file, which is used to make Cisco IOS XRv router reachable on console.

Read article about Ansible as VNF-M.

Verification

As all our examples were about Nokia (Alcatel-Lucent) VSR, here we’ll provide example for Cisco IOS XRv. So we deploy it as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ ansible-playbook 108_lab.yml --tags cisco_on
PLAY [linux] ********************************************
TASK [Gathering Facts] **********************************
ok: [localhost]
TASK [linux/108_lab : READING VNF DATA // cisco] ********
ok: [localhost]
TASK [linux/108_lab : PERFORMING ONBOARDING] ************
included: /home/aaa/ansible/roles/linux/108_lab/tasks/on.yml for localhost
TASK [linux/108_lab : COPYING VM IMAGE TO PROPER DIRECTORY] **************
changed: [localhost]
TASK [linux/108_lab : DEFINE VM IN KVM // cisco] ********
changed: [localhost]
TASK [linux/108_lab : DEFINE VM IN KVM // cisco] ********
skipping: [localhost]
TASK [linux/108_lab : LAUNCHING XR7 ON KVM] *************
changed: [localhost]
TASK [linux/108_lab : UPDATING ANSIBLE HOSTS FOR XR7] ***
changed: [localhost]
TASK [linux/108_lab : UPDATING LINUX HOSTS FOR XR7] *****
changed: [localhost]
TASK [linux/108_lab : WAITING FOR XR7 TO BOOT] **********
Pausing for 330 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [localhost]
TASK [linux/108_lab : ONLY FOR cisco // MAKING ROUTER REACHABLE ON CLI] ***********
changed: [localhost]
TASK [linux/108_lab : ONLY FOR cisco // CONFIGURING OOB INTERFACE] *************
changed: [localhost]
TASK [linux/108_lab : PERFORMING UNDEPLOYING] ***********
skipping: [localhost]
PLAY [linux] ********************************************
TASK [Gathering Facts] **********************************
ok: [localhost]
PLAY [linux] ********************************************
TASK [Gathering Facts] **********************************
ok: [localhost]
PLAY [linux] ********************************************
TASK [Gathering Facts] **********************************
ok: [localhost]
PLAY RECAP **********************************************
localhost : ok=14 changed=7 unreachable=0 failed=0

After this Ansible playbook is played we can connect to the newly deployed Cisco IOS XRv:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ ssh cisco@XR7
.
IMPORTANT: READ CAREFULLY
Welcome to the Demo Version of Cisco IOS XRv (the "Software").
The Software is subject to and governed by the terms and conditions
of the End User License Agreement and the Supplemental End User
License Agreement accompanying the product, made available at the
time of your order, or posted on the Cisco website at
www.cisco.com/go/terms (collectively, the "Agreement").
As set forth more fully in the Agreement, use of the Software is
strictly limited to internal use in a non-production environment
solely for demonstration and evaluation purposes. Downloading,
installing, or using the Software constitutes acceptance of the
Agreement, and you are binding yourself and the business entity
that you represent to the Agreement. If you do not agree to all
of the terms of the Agreement, then Cisco is unwilling to license
the Software to you and (a) you may not download, install or use the
Software, and (b) you may return the Software as more fully set forth
in the Agreement.
.
Please login with any configured user/password, or cisco/cisco
.
cisco@xr7's password:
.
RP/0/0/CPU0:ios#

When we don’t need this VNF anymore, we just easily remove it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ ansible-playbook 108_lab.yml --tags cisco_off
PLAY [linux] ********************************************
TASK [Gathering Facts] **********************************
ok: [localhost]
PLAY [linux] ********************************************
TASK [Gathering Facts] **********************************
ok: [localhost]
PLAY [linux] ********************************************
TASK [Gathering Facts] **********************************
ok: [localhost]
TASK [linux/108_lab : READING VNF DATA // cisco] ********
ok: [localhost]
TASK [linux/108_lab : PERFORMING ONBOARDING] ************
skipping: [localhost]
TASK [linux/108_lab : PERFORMING UNDEPLOYING] ***********
included: /home/aaa/ansible/roles/linux/108_lab/tasks/off.yml for localhost
TASK [linux/108_lab : DESTROYING XR7 IN KVM] ************
ok: [localhost]
TASK [linux/108_lab : UNDEFINING XR7 IN KVM] ************
ok: [localhost]
TASK [linux/108_lab : DELETING XR7 IMAGE FROM LIBRARY] **
changed: [localhost]
TASK [linux/108_lab : REMOVING XR7 FROM ANSIBLE HOSTS] **
changed: [localhost]
TASK [linux/108_lab : REMOVING XR7 FROM LINUX HOSTS] ****
changed: [localhost]
PLAY [linux] ********************************************
TASK [Gathering Facts] **********************************
ok: [localhost]
PLAY RECAP **********************************************
localhost : ok=11 changed=3 unreachable=0 failed=0

That’s it! Now we have more convenient script.
Here are the corresponding Ansbile playbooks: 112_lab.tar

Lessons learned

Never step learning, improving your skills and growing further. Each new thing I’ve learned in Ansible helps to create the automation better, easier and therefore useful. Many thanks to @Nikola.Arnoldi for inviting me to the project, where we do cool stuff using Ansbile and I have possibility to master my skills.

And as previously, many thanks to @Nikita.Makaranka on consulting me for json_query and guiding to proper docs.

Guys, you rock!

Conclusion

Once I was asked by one of my colleagues, why do I use the Ansible automation. He tried to use my playbook, but it was not properly documented, so he needed some my assistance. Well, question is fair enough. Each automation is as good as you can use it, so it must be convenient, easy to understand and reliable. On top it must be good documents, so that someone else besides you (or me) can use it. Usage of roles and group_vars allows to create Ansible playbooks more friendly in terms of portability and therefore usability. Jinja2 templates add flexibility and allow the whole structure (VNF in my case) be defined solely by var files. So… Now I think, this VNF manager is more user friendly, but for sure, there is further room for the improvement. Take care and good bye!

P.S.

If you have further questions or you need help with your networks, I’m happy to assist you, just send me message (http://karneliuk.com/contact/). Also don’t forget to share the article on your social media, if you like it.

Support us





BR,

Anton Karneliuk