Cisco Live 2017

I’m back in San Francisco after a solid few days of conference sessions, heat, crowds, and getting to meet all sort of new faces. This year I concentrated on Nexus 9000 and VXLAN sessions as we are refreshing our TOR solution in the datacenter.

Attended Sessions

  • BRKARC-3222 – Cisco Nexus 9000 Architecture
  • BRKDCN-3020 – Network Analytics using Nexus 3000/9000 Switches
  • BRKDCN-3378 – Building Data Center Networks with VXLAN EVPN Overlays
  • BRKINI-2005 – Engineering Fast IO to the Network
  • BRKIPM-2264 – Multicast Troubleshooting
  • BRKRST-3320 – Troubleshooting BGP
  • BRKDCN-2015 – Nexus Standalone Container Networking

I also picked up a new addition to the library, Building Data Centers with VXLAN BGP EVPN.

Advertisements

Force-Directed Network Diagram with Arista eAPI and D3.js

2016-05-23_force_direction_1Overview

The Arista eAPI give you the ability to interact with a switch over standard HTTPS and return structured JSON. Here a section of Python code to populate a database table to automatically generate a network diagram based on LLDP neighbor relationships.

 

Requirements

Arista EOS
Python 2.7
Postgresql
pyeapi

Database Tables

CREATE TABLE report.control
(
  id serial NOT NULL,
  "switchName" text NOT NULL,
  "interfaceName" text NOT NULL,
  "interfaceType" text,
  monitor boolean,
  description text NOT NULL,
  "remoteSwitchName" text,
  "remoteSwitchPort" text,
  "lineProtocolStatus" text,
  "interfaceStatus" text,
  site text,
  CONSTRAINT pk_report_control PRIMARY KEY ("switchName", "interfaceName")
)

Sample Python Code

Populating our database table with Switch and Interface information.

import pyeapi
pyeapi.load_config('nodes.conf')

def control_insert_lldp(switchName, interfaceName, remoteSwitchName, remoteSwitchPort):
    try:
        conn = psycopg2.connect(conn_string)
        cursor = conn.cursor()
        sql = '''
        UPDATE report.control
        SET "remoteSwitchName" = %s, "remoteSwitchPort" = %s
        WHERE "switchName" = %s AND "interfaceName" = %s
        '''
        data = (remoteSwitchName, remoteSwitchPort, switchName, interfaceName, )
        cursor.execute(sql, data, )
    except psycopg2.IntegrityError:
        conn.rollback()
    else:
        conn.commit()
    return 0

for switch in switches:
 node = pyeapi.connect_to(switch['deviceName'])
 try:
 output = node.enable('show lldp neighbors')
 neighbors = output[0]['result']['lldpNeighbors']
 for neighbor in neighbors:
 neighborDevice = removedomain(neighbor['neighborDevice'])
 control_insert_lldp(hostname, neighbor['port'], neighborDevice, neighbor['neighborPort'])
 except Exception as e:
 print(e)

Getting a list of switches from our database table.

def network_switches():
    conn = psycopg2.connect(conn_string)
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    sql = '''
    SELECT
    DISTINCT(control."switchName") as "name",
      site."siteDescription" as group
    FROM
      report.control
    WHERE
      "remoteSwitchName" != ''
    ORDER BY
      control."switchName"
    '''
    cursor.execute(sql, )
    results = cursor.fetchall()
    return results

Returning a LLDP neighbor value if we have one for each switch interface.

def network_lldp_neighbors(switchName):
    conn = psycopg2.connect(conn_string)
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    sql = '''
    SELECT
      DISTINCT(control."remoteSwitchName") as "remoteName"
    FROM
      report.control
    WHERE
      "switchName" = %s AND
      "remoteSwitchName" != ''
    ORDER BY "remoteSwitchName"
    '''
    data = (switchName, )
    cursor.execute(sql, data, )
    results = cursor.fetchall()
    return results

Create a JSON string for D3.js Force-Directed Graph.

def d3_lldp(element):
    links = []
    value = 1
    nodes = network_switches()
    idCount = 0
    for row in nodes:
        row['id'] = idCount
        # row['group'] = 1
        idCount += 1

    for node in nodes:
        lldpswitches = network_lldp_neighbors(node['name'])
        source = node['id']

        for connection in lldpswitches:
            for row in nodes:
                if row['name'] == connection['remoteName']:
                    target = row['id']
                    result = {'source': source, 'target': target, 'value': value}
                    links.append(result)

    result = {'nodes': nodes, 'links': links}
    return json.dumps(result)

Arista ACE Training

Last week I had the opportunity to attend Arista ACE 2.1 training down at the HQ offices in Santa Clara. I was very fortunate to be in a class that was lead by Gary Donahue, the author of Arista Warrior. He is an excellent presenter and a extremely personable individual. If you ever have a chance to be in a class of his, sign up for it.

Photo Apr 18, 12 00 12 PM

The training was very hands on, with labs that covered Zero Touch Provisioning (ZTP), Multi-Chassis LAG (MLAG), Virtual Extensible LAN (VXLAN), and my favorite topic, the wonderful EAPI. Coming from a Cisco CCNA/CCNP background, these topics helped fill knowledge gaps on the Arista family of hardware.

At the end of the class, Gary was signing copies of his book so I left with a author signed copy of Arista Warrior. Not a bad addition to the growing collection of O’Reilly books around the house.

Photo Apr 25, 8 14 33 PM

rConfig on CentOS 6.6

I’ve used RANCID in the past, but I wanted to use a more modern configuration management tool at my current organization. I’ve been following the rConfig project for a while now and recently setup an instance of it on our network.

Here is a short guide on how to get rConfig up and running on a CentOS instance.

# CentOS not getting DHCP address on eth0 under VMware
/etc/sysconfig/network-scripts/ifcfg-eth0
edit and set to yes

# Install some tools
# I prefer vim over vi
sudo yum install net-tools
sudo yum install wget
sudo yum install zip unzip
sudo yum install vim-common vim-minimal vim-enhanced vim-X11

# Install Apache
sudo yum install httpd

#Install MySQL
yum install mysql mysql-server
service mysqld start

#Install PHP
yum install php php-common
yum install php-common php-cli php-mysql php-devel

# Service Restarts
service httpd restart
chkconfig httpd on
service mysqld restart
chkconfig mysqld on

# Adjust firewall to allow for inbound http
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT
sudo service iptables save

# Use wget to get the rConfig zip from http://www.rconfig.com/index.php/download-menu
download, unzip to /home/rconfig

# Change ownership
chown -R apache /home/rconfig
mv /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.original
cp /home/rconfig/www/install/httpd.conf.new /etc/httpd/conf/httpd.conf

# Adjust permissions
vim /etc/selinux/config
"SELINUX=enforcing" to "SELINUX=disabled"

# Test that Apache and MySQL autostart
reboot

# Setup rConfig via the web interface
http://ipaddress/install/preinstall.php

# Create your rConfig user
mysql
CREATE USER 'rconfig_user'@'localhost' IDENTIFIED BY 'some-password';
GRANT ALL PRIVILEGES ON * . * TO 'rconfig_user'@'localhost';
FLUSH PRIVILEGES;

# Change rconfig_user password
SET PASSWORD FOR 'rconfig_user'@'localhost' = PASSWORD('some-password');

# Setup NTP
yum install ntp ntpdate ntp-doc
chkconfig ntpd on
ntpdate pool.ntp.org
/etc/init.d/ntpd start

 

GNS3 and VRRP Timers

While testing out a VRRP solution, I noticed that it was not performing as expected. The VRRP address was unresponsive so I started to investigate. Turning on console logging, I saw a large amount of flapping between Backup and Master states.

...
*Mar  1 02:37:23.739: VRRP: Grp 1 Event - Master down timer expired
*Mar  1 02:37:23.739: %VRRP-6-STATECHANGE: Vl20 Grp 1 state Backup -> Master
*Mar  1 02:37:25.095: %VRRP-6-STATECHANGE: Vl20 Grp 1 state Master -> Backup
...

It turns out that running 8 routers in GNS3 on my laptop was slightly under-powered platform and resulting in over a 2 second maximum response time from a VRRP peer.

Sending 8000, 100-byte ICMP Echos to 10.10.20.1, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!..!!!..........................
......................................................!!!!!!!!!!!!!!!!
!!....................................................................
.....................!!!......................!!!!!!!!!!!.!!!!!!!!!!!!
..!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!.!!!!!!!!!!.!!!!!!!!!!.!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.
Success rate is 74 percent (611/818), round-trip min/avg/max = 4/705/1996 ms
Server-A#

After adjusting the advertise timers, everything started to perform as expected.

R1#
interface Vlan20
 ip address 10.10.20.2 255.255.255.0
 vrrp 1 ip 10.10.20.1
 vrrp 1 timers advertise 10
 vrrp 1 priority 110
 
R2#
interface Vlan20
 ip address 10.10.20.3 255.255.255.0
 vrrp 1 ip 10.10.20.1
 vrrp 1 timers advertise 10

 

CCNP Achieved

I passed CCNP Route 642-813 in January before the exam changed thus completing all three exams. Route was the most challenging of the three exams for me because I am now taking the lead on projects that involve routing, which is part of why I wanted to peruse the certification. Exciting times and I’ve started to take a peek at the CCIE 5.0 exam.

url

CCNP TSHOOT 642-832 Passed

I passed the CCNP TSHOOT exam yesterday and I have to say that this exam was my favorite out of all the Cisco ones that I have taken so far. The exam format of solving trouble tickets was a welcome change that I felt was really applicable to an Engineer’s daily tasks.

The official Cisco Press TSHOOT book, Bull’s Eye exam preparation strategies, and building the official lab topology out in GNS3 helped me prepare for the exam. I did update my GNS3 version to 1.0+ and needed to convert my project files to the new 1.0+ JSON format with gns3-converter.