Table of Contents

Python

Python

Network Config Templating using Ansible

https://pynet.twb-tech.com/blog/ansible/ansible-cfg-template.html https://pynet.twb-tech.com/blog/ansible/ansible-cfg-template-p2.html https://pynet.twb-tech.com/blog/ansible/ansible-cfg-template-p3.html

Modules

Update Python Modules

Install Modules without internet access

New version on this how to

  1. Install the module on your online machine - e.g. here we are installing the “requests” module

python -m pip install requests

Collecting requests
  Downloading requests-2.28.2-py3-none-any.whl (62 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 62.8/62.8 kB 3.5 MB/s eta 0:00:00
Collecting charset-normalizer<4,>=2
  Downloading charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl (96 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 96.0/96.0 kB ? eta 0:00:00
Collecting idna<4,>=2.5
  Downloading idna-3.4-py3-none-any.whl (61 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 61.5/61.5 kB ? eta 0:00:00
Collecting urllib3<1.27,>=1.21.1
  Downloading urllib3-1.26.14-py2.py3-none-any.whl (140 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 140.6/140.6 kB 8.7 MB/s eta 0:00:00
Collecting certifi>=2017.4.17
  Downloading certifi-2022.12.7-py3-none-any.whl (155 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 155.3/155.3 kB ? eta 0:00:00
Installing collected packages: charset-normalizer, urllib3, idna, certifi, requests
Successfully installed certifi-2022.12.7 charset-normalizer-3.0.1 idna-3.4 requests-2.28.2 urllib3-1.26.14
  1. Now run the following command:
pip freeze > requirements.txt

This will output the modules installed and the exact versions. Edit this file to only have the modules you need - for example the 4 which were installed above

So my requirements.txt file should look like:

certifi==2022.12.7
charset-normalizer==3.0.1
idna==3.4
requests==2.28.2
urllib3==1.26.14
  1. Now run this command which will create a wheelhouse folder and download an offline version of the modules in the requirements file
mkdir wheelhouse && pip download -r requirements.txt -d wheelhouse
  1. Copy the requirements.txt file into the wheelhouse folder.
  2. Zip the wheelhouse folder which now contains the downloaded modules and requiremments.txt file to your offline machine.
  1. Install as follows:
pip install -r wheelhouse/requirements.txt --no-index --find-links wheelhouse  

Previous How to

Reference: https://stackoverflow.com/questions/11091623/how-to-install-packages-offline

pysnmp==4.4.12
pyodbc==4.0.30

Above is better option

Example

pip install idna-2.8-py2.py3-none-any.whl --no-deps

Example Path

C:\Users\3porourke1\AppData\Local\Programs\Python\Python38-32\;C:\Users\3porourke1\AppData\Local\Programs\Python\Python38-32\Scripts\

How to install Python and Confplate

1a) Download & Install Python https://www.python.org/downloads/ Make sure Python.exe is runable from command line (see screen shot on how to add Python tp Path.

1b) Add Python to the Path

C:\Users\<your username>\AppData\Local\Programs\Python\Python38

2) Download & Install PIP (The Python Package Installer) - More Detailed here: https://www.liquidweb.com/kb/install-pip-windows/ a) Download the PIP Python file “get-pip.py” from https://bootstrap.pypa.io/get-pip.py b) Install PIP by running the command “python get-pip.py” c) Add your Python Scripts to your Path e.g. C:\Users\admin.LAB2\AppData\Local\Programs\Python\Python38-32\Scripts

Note - when adding to Path - you need to reboot or open a New Command Window (cmd.exe) for the change to take effect. d) Install Nija - “pip install Jinja2” e) Download the Config Template Python Script “ConfPlate-master.zip” from https://github.com/ktbyers/ConfPlate/blob/master/confplate.py

Note: if you need PIP to download files via a Web Proxy: https://pip.pypa.io/en/stable/user_guide/#using-a-proxy-server

Logging

SNMP

Script - SNMP routers for voice stats and insert into a DB

Reference Code: https://www.ictshore.com/sdn/python-snmp-tutorial/

from pysnmp import hlapi
from datetime import datetime
import pyodbc 
 
now = datetime.now()
current_datetime = now.strftime('%Y-%M-%d %H:%M')
print("Current DateTime =", current_datetime)
 
 
def get(target, oids, credentials, port=161, engine=hlapi.SnmpEngine(), context=hlapi.ContextData()):
    handler = hlapi.getCmd(
        engine,
        credentials,
        hlapi.UdpTransportTarget((target, port), timeout=2.0, retries=0),
        context,
        *construct_object_types(oids)
    )
    return fetch(handler, 1)[0]
 
def construct_object_types(list_of_oids):
    object_types = []
    for oid in list_of_oids:
        object_types.append(hlapi.ObjectType(hlapi.ObjectIdentity(oid)))
    return object_types
 
def fetch(handler, count):
    result = []
    for i in range(count):
        try:
            error_indication, error_status, error_index, var_binds = next(handler)
            if not error_indication and not error_status:
                items = {}
                for var_bind in var_binds:
                    items[str(var_bind[0])] = cast(var_bind[1])
                result.append(items)
            else:
                raise RuntimeError('Got SNMP error: {0}'.format(error_indication))
        except StopIteration:
            break
    return result    
 
 
def cast(value):
    try:
        return int(value)
    except (ValueError, TypeError):
        try:
            return float(value)
        except (ValueError, TypeError):
            try:
                return str(value)
            except (ValueError, TypeError):
                pass
    return value
 
#snmp v3
#hlapi.UsmUserData('testuser', authKey='authenticationkey', privKey='encryptionkey', authProtocol=hlapi.usmHMACSHAAuthProtocol, privProtocol=hlapi.usmAesCfb128Protocol)
 
 
conn = pyodbc.connect('Driver={SQL Server};'
                      'Server=localhost;'
                      'Database=stats_db;'
                      'Trusted_Connection=yes;')
 
cursor = conn.cursor()
oid='1.3.6.1.2.1.1.5.0'
communitystring='purple'
rows = cursor.execute('SELECT id, ip_address FROM inventory WHERE (type = 1 OR type = 2) AND active = \'Y\'')
 
for row in list(rows):
#for row in rows:
    try:
        voicestats_dict = get(row[1], [oid], hlapi.CommunityData(communitystring))
        for key in voicestats_dict:
            print (row[1],":", voicestats_dict[key])
            sql = "INSERT INTO snmp_stats (DateTime, router_id,oid, value) VALUES (?, ?, ?, ?)"
            val = (current_datetime, row[0], key, voicestats_dict[key])
            cursor.execute(sql, val)
            conn.commit()
    except: 
        print(row[1], ": Error", )

Example Wheelhouse file

wheelhouse.zip

CUCM Example to get number of members of each Device pool

# Author: Gerry O'Rourke
# Date: 13/06/2024
# Simple Script to Gather Which Device Pools have how many members
 
# Import the requests module
import requests
from requests.auth import HTTPBasicAuth
import urllib3  #
urllib3.disable_warnings()  # Suppress cert warnings
 
# Define the URL to which the request is made
 
# Example Header 
# Cookie: JSESSIONID=E6A763744109DDB05AF4053919B8D201; com.cisco.ccm.admin.servlets.RequestToken.REQUEST_TOKEN_KEY=4968301074955380751; JSESSIONIDSSO=39E11835B1D6C61323D98040B9190D91
 
# Login into CUCM from a Browser and get the below cookie value
cookie_value = "JSESSIONID=AE300DB52D11CDCCDDFC36E236EBC941; com.cisco.ccm.admin.servlets.RequestToken.REQUEST_TOKEN_KEY=-3398037942865486169; JSESSIONIDSSO=A367EF12F888597FA470F56A6D70A19F"
cucmHeaders = {"Cookie": cookie_value}
 
# Make the GET request with basic authentication and ignoring SSL certificate verification
# To get the Device IDs run the command 'run sql select name,pkid from devicepool' on the CUCM Server
 
DevicePoolNames = ["DP-1", "DP-2"]
DevicePoolIDs = ["0584f54e-f28b-2e4d-981d-332d7175a84e", "06913808-0226-399e-2ad3-29954e660a64"]
 
for idx, DevicePoolID in enumerate(DevicePoolIDs) :
    url = "https://cucm-pub.example.com/ccmadmin/devicePoolEdit.do?key=" + DevicePoolID
    response = requests.get(url, headers=cucmHeaders, verify=False)
    # Check if the request was successful
    if response.status_code == 200:
        # Process the response content
        # data = response.json()  # Assuming the response is in JSON format
        data = response.text  
        #print("Success:", data)
 
        for line in data.splitlines():
            if "<title>Cisco Unified CM Console</title>" in line:
                print("Refresh Cookie!")
                exit(0)
            elif "not found in the database" in line:
                print("ID Invalid! Exiting!")
                exit(0)
            elif "members**)" in line:
                print (DevicePoolNames[idx], end="")
                print(line)
 
    else:
        # Handle errors
        print("Failed to retrieve data. Status code:", response.status_code)
        print("Response:", response.text)