Thursday, 19 May 2022

Paramiko - config grab with Cisco IOS

import time
import paramiko
import getpass
from datetime import datetime

routers = ["192.168.0.1"]
username = raw_input("Please enter your username: ")
password = getpass.getpass("Please enter your password: ")

now_time = datetime.now()
str_now_time = str(now_time)

sshcon = paramiko.SSHClient()
sshcon.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for target in routers:
f = open("{0}-{1}-txt".format(target,str_now_time) , "w")
print ('Attempting to connect to {0}'.format(target))
sshcon.connect(hostname=target,username=username,password=password,look_for_keys=False)
remote_connection = sshcon.invoke_shell()
remote_connection.send("ter len 0\n")
time.sleep(5)
remote_connection.send("show run\n")
time.sleep(5)
output = remote_connection.recv(65535)
# print(output)
print ('Writing config to file')
f.write(output)
sshcon.close
print("Job completed successfully")

Friday, 19 November 2021

Making a Raspberrypi Stop Motion Video

This guide explains how to make a stop motion video using a raspberrypi with the camera module. As part of this exercise I also wanted to transfer the file over to another remote PC in an automated fashion.
The reason I wanted to do this was the using video made the filesize umanageable. With stop motion you can alter the interval, duration of process etc.

High level steps:

1. pi1 takes a picture every 10 seconds 
2. pi1 copies the picture to pi2
3. pi1 deletes the local copy and takes another picture and repeats the process.
4. On pi2 there is a scheduled cronjob that creates a video from the still images and then deletes the images files.

On pi1:

Create a folder to store our images:
mkdir /home/pi/camera

Create a script to capture the images:

sudo nano /home/pi/camera.sh

Add the following to the camera.sh shell script. The script itself runs through a for loop, you can see in this example it runs through 3600 iterations.  Within the loop the script takes a picture and outputs it to a file with a filename called picture-i (where i is the number where we are in the loop). The script then pauses for 10 seconds. This means that this script would take roughly 10 hours to work through the loop until it stops - you can obviously modify the values to suit your needs.  The script then writes the file to pi2 using scp - you need to have already setup ssh login without password for this to work. The script then deletes the local file and returns to the start of the loop. The deletion of the local file is purely to save space - it is not compulsory:

#!/bin/bash

#DATE=$(date +"%Y-%m-%d_%H%M%S")

for ((i=1; i<=3600; i++))

do

        DATE=$(date +"%Y-%m-%d_%H-%M-%S")

        echo "*** Taking Picture $i ***" 

        raspistill -o /home/pi/camera/picture-$i.jpg

        sleep 10


        echo "*** Writing file $i to remote server ***"

        scp /home/pi/camera/*.jpg pi@pi2:/home/pi/camera

        rm /home/pi/camera/*.jpg

done

Press CTRL + X, followed by Y to close the file and save it:

Make the script executable:
sudo chmod +x camera.sh

Now we move to pi2

Create a folder to store our images:
mkdir /home/pi/camera

Back on pi1 if we execute the script we should the .jpg files appearing in our folder on pi2.
cd /home/pi/camera
./camera.sh

We now need a method to create the video from the still images and delete the images to save space.

Create a script to make the video:
sudo nano /home/pi/make-video.sh

Add the following:
!/bin/bash

#DATE=$(date +"%Y-%m-%d_%H%M%S")

ffmpeg -framerate 25 -i /home/pi/camera/picture-%d.jpg /home/pi/Video-$(date +%d-%m-%Y-%H-%M).mp4

rm /home/pi/camera/*.jpg


Press CTRL + X, followed by Y to close the file and save it:

Make the script executable:
sudo chmod +x make-video.sh

Executing this script uses ffmpeg to create a video file at 25fps using the current date and time in the filename. It then removes all .jpg files from the folder.

Finally we create a cronjob to create the video periodically:

crontab -e

Add the following:
0 8 * * * sh /home/pi/camera/make-video.sh

This will run the script at 8am every day.

You can also create a cronjob on p1 to automate the other script.

crontab -e

Add the following:

15 8 * * * sh /home/pi/camera/camera.sh

Thursday, 18 February 2021

BIG-IP

! Load factory default cofig
tmsh load /sys config default

! Run management interface setup utility
config# config



Tuesday, 2 February 2021

F5 BIGIP Ansible

See here for more info:

https://github.com/F5Networks/f5-ansible/blob/devel/examples/0000-getting-started/playbook.yaml

Directory structure looks like this:

├── inventory

│   └── hosts

└── playbook.yaml

"hosts" file contains a single entry "localhost" (the F5 IP address is defined within the script).


<save the below to playbook.yaml>

 ---


- name: Create a VIP, pool and pool members

  hosts: all

  connection: local


  vars:

    provider:

      password: admin

      server: 192.168.1.245

      user: admin

      validate_certs: no

      server_port: 443


  tasks:

    - name: Create a pool

      bigip_pool:

        provider: "{{ provider }}"

        lb_method: ratio-member

        name: web

        slow_ramp_time: 120

      delegate_to: localhost


    - name: Add members to pool

      bigip_pool_member:

        provider: "{{ provider }}"

        description: "webserver {{ item.name }}"

        host: "{{ item.host }}"

        name: "{{ item.name }}"

        pool: web

        port: 80

      with_items:

        - host: 10.10.10.10

          name: web01

        - host: 10.10.10.20

          name: web02

      delegate_to: localhost


    - name: Create a VIP

      bigip_virtual_server:

        provider: "{{ provider }}"

        description: foo-vip

        destination: 172.16.10.108

        name: vip-1

        pool: web

        port: 80

        snat: Automap

        profiles:

          - http

          - clientssl

      delegate_to: localhost


Friday, 9 November 2018

Script to create tenant / app profile / EPG

#   Note that this script expects HTTP port 80 on the APIC, which is off by default.
# To enable HTTP in the APIC, navigate to FABRIC, FABRIC POLICIES Pod Policies     Policies   Management Acces    default  then enable HTTP
import requests
import json

def get_cookies(apic):
    username = 'admin'
    password = 'ciscoapic'
    url = apic + '/api/aaaLogin.json'
    auth = dict(aaaUser=dict(attributes=dict(name=username, pwd=password)))
    authenticate = requests.post(url, data=json.dumps(auth), verify=False)
    return authenticate.cookies

def add_tenant(apic,cookies):
    jsondata = {"fvTenant":{"attributes":{"dn":"uni/tn-acme","name":"acme","rn":"tn-acme","status":"created"},"children":[]}}
    result = requests.post('{0}://{1}/api/node/mo/uni/tn-acme.json'.format(protocol,host), cookies=cookies, data=json.dumps(jsondata), verify=False)
    print result.status_code
    print result.text

def get_tenants(apic,cookies):
    uri = '/api/class/fvTenant.json'
    url = apic + uri
    req = requests.get(url, cookies=cookies, verify=False)
    response = req.text
    return response

def add_application_profile(apic,cookies):
    jsondata = {"fvAp":{"attributes":{"dn":"uni/tn-acme/ap-Accounting","name":"Accounting","rn":"ap-Accounting","status":"created"},"children":[]}}
    result = requests.post("{0}://{1}/api/node/mo/uni/tn-acme/ap-Accounting.json".format(protocol, host), cookies=cookies, data=json.dumps(jsondata), verify=False)
    print result.status_code
    print result.text

def add_EPG1(apic,cookies):
    jsondata = {"fvAEPg":{"attributes":{"dn":"uni/tn-acme/ap-Accounting/epg-Payroll","name":"Payroll","rn":"epg-Payroll","status":"created"},"children":[{"fvCrtrn":{"attributes":{"dn":"uni/tn-acme/ap-Accounting/epg-Payroll/crtrn","name":"default","rn":"crtrn","status":"created,modified"},"children":[]}}]}}
    result = requests.post("{0}://{1}/api/node/mo/uni/tn-acme/ap-Accounting/epg-Payroll.json".format(protocol, host), cookies=cookies, data=json.dumps(jsondata), verify=False)
    print result.status_code
    print result.text

def add_EPG2(apic,cookies):
    jsondata = {"fvAEPg":{"attributes":{"dn":"uni/tn-acme/ap-Accounting/epg-Bills","name":"Bills","rn":"epg-Bills","status":"created"},"children":[{"fvCrtrn":{"attributes":{"dn":"uni/tn-acme/ap-Accounting/epg-Bills/crtrn","name":"default","rn":"crtrn","status":"created,modified"},"children":[]}}]}}
    result = requests.post("{0}://{1}/api/node/mo/uni/tn-acme/ap-Accounting/epg-Bills.json".format(protocol, host), cookies=cookies, data=json.dumps(jsondata), verify=False)
    print result.status_code
    print result.text

if __name__ == "__main__":
    protocol = 'http'
    host = '192.168.10.1'
    apic = '{0}://{1}'.format(protocol, host)
    cookies = get_cookies(apic)
    add_tenant(apic,cookies)
    add_application_profile(apic,cookies)
    add_EPG1(apic,cookies)
    add_EPG2(apic,cookies)
    rsp = get_tenants(apic,cookies)

rsp_dict = json.loads(rsp)
tenants = rsp_dict['imdata']

for tenant in tenants:
    print tenant['fvTenant']['attributes']['name']

Monday, 5 November 2018

Python

Integers and Floats

Integer = number
int (pi) ==3
Float = decimal number
float(answer) == 42.0

Strings

String = text

"Hello World"

"hello" .capitalize() == "Hello"

"hello" .replace("e" ,"a" ) == "hallo"
"hello" .isalpha() == True
"123" .isdigit() == True 
"some,csv,values" .split(",") == ["some", "csv", "values"]


name = "Martin"machine = "Hal"print ("Nice to meet you {0}. I am {1}".format(name,machine))

Boolean and None

python_course = True
int (python_course) == 1

If Statements

number = 5
if number == 5:
      print ("Number is 5")
else:
      print ("Number is NOT 5")

Lists (mutable, ordered)

student_names = ["John", "Paul", "George","Ringo"]
student_names[0] == "John"
! List values start at 1
student_names[-1] == "Ringo"
! Minus sign reads values from the right of the list
len(student_names) == 4
del student_names[2]
! Remove George from list

Dictionaries (mutable, associative array)

Device = {"hostname":"router1","OS":"v15.5,"location":"London")

Tuple (sequence of immutable objects)

Credentials = ("hostname","username","password")

Sets (unordered collection of unique and immutable objects) 

Loops

for name in student_names
     print ("Student name is {0}" .format(name))

For Loop

student_names = ["John", "Paul", "George","Ringo"]
for name in student_names:
  if name == "John":
  print("Found him! " + name)
  break 



Challenges:

Challenge 1:

#!/usr/bin/env python2.7

def devices():
 routers = ["router1","router2","router3"]
 print routers

def security():
 credentials = {"router1":"passw0rd1","router2":"passw0rd1","router3":"passw0rd1"}
 print credentials

def combined():
 devices()
 security()

if __name__ == "__main__":
 print "The routers are:"
 devices()
 
 print "The credentials are:"
 security()

 print "All data is:"
 combined()

Wednesday, 27 June 2018

ACI Deep Dive


  • TEP address pool should not overlap with internal address space
  • /16 address space is default for TEP pool

Switch discovery
  • LLDP between switch and APIC
  • DHCP request from switch for lo0
  • ISIS between leaf and spine
  • IFM = inter fabric messaging (secured with x.509 certificates) 
  • VXLAN tunnels built for connectivity to all other leaf / spine switches


Useful Commands

! Show switches in fabric
#acidiag fnvread
#acidiag verifyapic
#acidiag avread

! NXOS like interface
#vsh
#vsh_lc
#show cli list

! overlay-1 is the "underlay"

#show ip interface vrf overlay-1
#show ip route vrf overlay-1

https://<apic-ip>/visore

#moquery

! query faults - uses http port 777
#icurl


#show system internal epm endpoint mac aaaa.bbbb.cccc

! Leaf command to ping (vrf aware unlike native linux)
#iping

! TCPDUMP can be used for control plane traffic only
#tcpdump -i eth0 

ELAM - data plane traffic capture

! See denied packet between EPGs
#show logging ip access-list internal packet-log deny
#show logging ip access-list cache deny

vzAny - contract for an EPG to consume everything in a VRF

! Like BGP debug
#show bgp event-history events