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
- 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
- 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
- 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
- Copy the requirements.txt file into the wheelhouse folder.
- Zip the wheelhouse folder which now contains the downloaded modules and requiremments.txt file to your offline machine.
- 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
- Create a requirements.txt as per below example or use
pip freeze > requirements.txt
and edit the file
pysnmp==4.4.12 pyodbc==4.0.30
- mkdir wheelhouse && pip download -r requirements.txt -d wheelhouse
pip install -r wheelhouse/requirements.txt --no-index --find-links wheelhouse
Above is better option
- Download Module wheel file
- Install using the –no-deps option
- Note - you must have pip and python accessible via command line - so add to user's path env
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
Good links
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)