SRX Performance Testing

For a project, I had to gather data in order to measure the SRX performance under different traffic loads. This was done for a SRX chassis system in cluster mode. The following commands were utilized in order to capture metrics when the system was subjected to traffic load:

show system uptime 
show system statistics
 
show chassis routing-engine 
show chassis fpc 
show chassis cluster status 
show chassis cluster information 
show chassis cluster interfaces 
 
show security monitoring 
show security monitoring performance spu 
show security flow statistics

show interfaces reth0 statistics
show security monitoring fpc node all <fpc-slot>

Github with scripts to execute the above commands and save it in a file.

Ansible – Cisco Config Implementation

The goal of this article is to explain configuration implementation on Cisco IOS after the config has been generated as shown in Ansible Config Generator III:

config-implementation.yml

---
- hosts: switch
  gather_facts: true
  connection: local
 
  tasks:
  - name: OBTAIN LOGIN CREDENTIALS
    include_vars: secrets.yml
 
  - name: DEFINE PROVIDER
    set_fact:
      provider:
        host: "{{ inventory_hostname }}"
        username: "{{ creds['username'] }}"
        password: "{{ creds['password'] }}"
        auth_pass: "{{ creds['auth_pass'] }}"
 
  - name: CONFIGURE INTERFACE
    ios_config:
      provider: "{{ provider }}"
      authorize: yes
      lines:
        - "{{ lookup('file', './config-output/{{ inventory_hostname }}.conf') }}"

The “hosts” file contains the switch names:

[switch]
switch-1
switch-2
switch-3
switch-4

secrets.yml

---
creds:
  username: cisco
  password: ciscopassword
  auth_pass: ciscoauthpassword

“./config-output/” directory contains the following files:

switch-1.conf
switch-2.conf
switch-3.conf
switch-4.conf

The inventory file (hosts) contains the switches in which the configuration from corresponding file name will be added. “switch-1.conf” file contents will be utilized to configure “switch-1” so on and so forth.

~/ansible_play/config-output$ cat switch-1.conf 
            
int Gi1/1                   
switchport access vlan 195
            
int Gi1/10                   
switchport access vlan 188
 
~/ansible_play/config-output$ cat switch-2.conf 
            
int Gi1/2                   
switchport access vlan 295
            
int Gi1/20                   
switchport access vlan 288
 
~/ansible_play/config-output$ cat switch-3.conf 
            
int Gi1/3                   
switchport access vlan 395
            
int Gi1/30                   
switchport access vlan 388
 
~/ansible_play/config-output$ cat switch-4.conf 
            
int Gi1/4                   
switchport access vlan 495
            
int Gi1/40                   
switchport access vlan 488

Ansible – Config Generator III

For Part I & Part II of this series.

The goal of this playbook is to be able to generate unique configuration for each switch. In this case, we are configuring a port to work as an access-port for a specific vlan. The port and vlan variable is different for each switch.

config-gen.yml

---
- hosts: 127.0.0.1
  connection: local
  gather_facts: no

  tasks:
  - name: GET DATA
    include_vars: ./host_vars/file.yml

  - name: GENERATE CONFIG
    template:
      src: ./templates/accessvlan.j2
      dest: ./config-output/{{ item.switch }}.conf
    with_items: "{{ file_vlan }}"

file.yml

---
file_vlan:
- { switch: switch-1, port: Gi1/8,  vlan: 395 }
- { switch: switch-1, port: Gi1/23, vlan: 388 }
- { switch: switch-2, port: Gi1/8,  vlan: 395 }
- { switch: switch-2, port: Gi1/23, vlan: 388 }
- { switch: switch-3, port: Gi1/9,  vlan: 395 }
- { switch: switch-3, port: Gi1/24, vlan: 388 }
- { switch: switch-4, port: Gi1/9,  vlan: 395 }
- { switch: switch-4, port: Gi1/24, vlan: 388 }

accessvlan.j2

{% for grouper, host in file_vlan|groupby('switch') %}
{% if item.switch == grouper %}
{% for item in host %}            
int {{ item.port }}                   
switchport access vlan {{ item.vlan }}
{% endfor %}
{% endif %}
{% endfor %}

When the “config-gen.yml” playbook is executed:

ansible-playbook config-gen.yml

we get the following output files:

~/ansible_play/config-output$ cat switch-1.conf 
            
int Gi1/1                   
switchport access vlan 195
            
int Gi1/10                   
switchport access vlan 188
 
~/ansible_play/config-output$ cat switch-2.conf 
            
int Gi1/2                   
switchport access vlan 295
            
int Gi1/20                   
switchport access vlan 288
 
~/ansible_play/config-output$ cat switch-3.conf 
            
int Gi1/3                   
switchport access vlan 395
            
int Gi1/30                   
switchport access vlan 388
 
~/ansible_play/config-output$ cat switch-4.conf 
            
int Gi1/4                   
switchport access vlan 495
            
int Gi1/40                   
switchport access vlan 488

Ansible – Config Generator – II

For the first part of this series, check this – 1st part of this series.

---
- hosts: local
  connection: local
  gather_facts: no

  tasks:
  - name: GET DATA
    include_vars: ./host_vars/file.yml

  - name: GENERATE CONFIG
    template:
      src: ./SVI.j2
      dest: ./{{ item.vlan }}.conf
    with_items: "{{ file_vlan }}"

 

This is the file.yml that is being referenced in the “include_vars”

---
file_vlan:
- { vrf: NET1, vlan: 502, vlanname: VLAN-502-NAME, net: 10.80.120.128/29 }
- { vrf: NET1, vlan: 503, vlanname: VLAN-503-NAME, net: 10.80.120.136/29 }

Compared to the 1st part of this series, we are moving the contents of the “with_items” to a separate YAML file and calling it based on the variable name “file_vlan” that is part of the file content.

Ansible – Config Generator – I

Before proceeding, make sure to install “netaddr” as this is required for “ipaddr()” used in the Jinja2 configuration template.

pip install netaddr

aggr.yml is the playbook that will be utilized for generating L3 SVI configuration:

---
- hosts: local
  connection: local
  gather_facts: no

tasks:
- name: GENERATE CONFIG
  template:
  src: ./SVI.j2
  dest: ./{{ item.vlan }}.conf
  with_items:
  - { vrf: NET1, vlan: 502, vlanname: VLAN-502-NAME, net: 10.80.120.128/29 }
  - { vrf: NET1, vlan: 503, vlanname: VLAN-503-NAME, net: 10.80.120.136/29 }

This is the SVI.j2 Jinja2 template that is being utilized to generate the final configuration:

###### A-Side ######
vlan {{ item.vlan }}
 name {{ item.vlanname }}

interface Vlan {{ item.vlan }}
 description {{ item.vlanname }}
 mtu 9100
 vrf member {{ item.vrf }}
 no ip redirects
 ip address {{ item.net | ipaddr('2') }}
 hsrp version 2
 hsrp 1
 authentication md5 key-string password{{ item.vlan }}
 preempt delay minimum 120
 priority 120
 timers 1 3
 ip {{ item.net | ipaddr('1') | ipaddr('address') }}

###### B-Side ######
vlan {{ item.vlan }}
 name {{ item.vlanname }}

interface Vlan {{ item.vlan }}
 description {{ item.vlanname }}
 mtu 9100
 vrf member {{ item.vrf }}
 no ip redirects
 ip address {{ item.net | ipaddr('3') }}
 hsrp version 2
 hsrp 1
 authentication md5 key-string password{{ item.vlan }}
 preempt delay minimum 120
 priority 110
 timers 1 3
 ip {{ item.net | ipaddr('1') | ipaddr('address') }}

In my setup, the play-book (aggr.yml), source template SVI.j2 file and the destination file exist in the same folder.

Reference Github.

Ansible – Encrypting Password

Basic Ansible automation playbook provides a method for accessing Cisco IOS devices and executing “show commands”. The “secrets.yml” file contains the username and password in plain-text. ansible-vault can be utilized to encrypt the “secrets.yml” file.

Encrypt a file using ansible-vault:

ansible-vault encrypt secrets.yml

View the contents of an encrypted file:

ansible-vault view secrets.yml

Decrypt a file using ansible-vault:

ansible-vault decrypt secrets.yml

Ansible – Basic Playbook

The goal of this post is to provide you with a simple way to utilize Ansible 2.x and obtain data from Cisco IOS devices by running “show” commands. Github Reference.

Ansible Installation:

Before starting, make sure you have ansible installed.

Create a working directory:

mkdir ansible_play
cd ansible_play

Create the following 4 files within the “ansible_play” directory:

ansible.cfg
hosts
secrets.yml
show_code.yml

Among the 4 files provided in this example, the “hosts” and “secrets.yml” file would have to be altered to suit your requirements. The other 2 files, “ansible.cfg” and “show_code.yml” can be used as-is.

The contents of the above files will be like this:

$ cat ansible.cfg

[defaults]
hostfile = ./hosts
host_key_checking=False
timeout = 5

For now, use the contents as provided above for the “ansible.cfg” file.

$ cat hosts

[ios]
switch1

The hosts file will have the switches/routers that you would like to use for running the ansible-playbook. In my case, I am using “switch1”. The 1st line “[ios]” is the name of the hosts that will be referenced in the ansible-playbook.

$ cat secrets.yml

---
creds:
  username: cisco
  password: ciscopassword
  auth_pass: ciscoauth

This file contains the login information required to access the devices in the hosts file.

$ cat show_code.yml

---
- hosts: ios
  gather_facts: no
  connection: local
 
  tasks:
  - name: OBTAIN LOGIN CREDENTIALS
    include_vars: secrets.yml
 
  - name: DEFINE PROVIDER
    set_fact:
      provider:
        host: "{{ inventory_hostname }}"
        username: "{{ creds['username'] }}"
        password: "{{ creds['password'] }}"
        auth_pass: "{{ creds['auth_pass'] }}"
 
  - name: SHOW VERSION
    ios_command:
      provider: "{{ provider }}"
      commands:
        - show version | i Version
    register: write
 
  - debug: var=write.stdout_lines

Executing the ansible playbook:

$ ansible-playbook show_code.yml

PLAY [ios] *********************************************************************

TASK [OBTAIN LOGIN CREDENTIALS] ************************************************
ok: [switch1]

TASK [DEFINE PROVIDER] *********************************************************
ok: [switch1]

TASK [SHOW VERSION] ************************************************************
ok: [switch1]

TASK [debug] *******************************************************************
ok: [switch1] => {
    "write.stdout_lines": [
        [
            "Cisco IOS Software, Catalyst 4500 L3 Switch  Software (cat4500e-ENTSERVICESK9-M), Version 15.2(2)E3, RELEASE SOFTWARE (fc3)"
        ]
    ]
}

PLAY RECAP *********************************************************************
switch1               : ok=4    changed=0    unreachable=0    failed=0

 

 

Ansible – Installation

If you have root access to your box, you can utilize the following link in order to install Ansible. I would recommend Ansible 2.1 & later version if your goal is to utilize Ansible as a Network Automation tool.

Creating a Virtual Environment with Ansible:

If you don’t have root access to the bastion host that is used to access the network infrastructure, you can utilize ansible in virtual environment.

pip install --upgrade pip virtualenv virtualenvwrapper
virtualenv ansible2.1
source ansible2.1/bin/activate
pip install ansible==2.2.1

Whenever required, the virtual environment can be accessed using:
source ansible2.1/bin/activate

root@ansible:~$ source ansible2.1/bin/activate

(ansible2.1)root@ansible:~$ ansible --version
ansible 2.1.0.0
  config file = 
  configured module search path = Default w/o overrides

F5 – Automating CLI Execution

Purpose:
This is a really simple way to automate CLI command execution on multiple F5 devices using Bash & TCL scripting. The scripts have been tested on a linux and a mac machine.

How to use it:
There is a bash script (F5_Bash_v1) that is utilized to collect the username/password for F5 access. A text file (F5_Host.txt) that stores the management IP address of multiple F5 devices and a TCL script (F5_Out_v1.exp) that is used to execute CLI commands on the F5 devices.

The bash script is the master script that obtains the username/password and executes the TCL script for multiple F5 devices.

Setup:
On a linux machine that is utilized to connect to the F5 device:

#Create a directory
mkdir F5_Check

Within the “F5_Check” directory, create the following 3 files:
F5_Host.txt
F5_Bash_v1
F5_Out_v1.exp

File Content: F5_Host.txt contains the management IP of the F5 devices.
Example:

$ cat F5_Host.txt
10.12.12.200
10.12.12.201
10.12.12.202
10.12.12.203

File Content: F5_Bash_v1

#!/bin/bash
# Collect the username and password for F5 access
echo -n "Enter the username "
read -s -e user
echo -ne '\n'
echo -n "Enter the password "
read -s -e password
echo -ne '\n'

# Feed the expect script a device list & the collected username & passwords
for device in `cat ~/F5_Check/F5_Host.txt`; do
./F5_Out_v1.exp $device $password $user ;
done

File Content: F5_Out_v1.exp

#!/usr/bin/expect -f

# Set variables
set hostname [lindex $argv 0]
set password [lindex $argv 1]
set username [lindex $argv 2]

# Log results
log_file -a ~/F5_Check/F5LOG.log

# Announce which device we are working on and the time
send_user "\n"
send_user ">>>>>  Working on $hostname @ [exec date] <<<<<\n"
send_user "\n"

# SSH access to device
spawn ssh $username@$hostname

expect {
"no)? " {
send "yes\n"
expect "*assword: "
sleep 1
send "$password\r"
}
"*assword: " {
sleep 1
send "$password\r"
}
}

expect "(tmos)#"
send "sys\n"
expect "(tmos.sys)#"

send "show software\n"
expect "#"
send "exit\n"
expect "#"
send "quit\n"

expect ":~\$"
exit