Skip to content

Commit

Permalink
Signed-off-by: James Dunne <james.dunne1@gmail.com>
Browse files Browse the repository at this point in the history
  • Loading branch information
dunneja committed Nov 11, 2022
1 parent 1655969 commit d6c5904
Show file tree
Hide file tree
Showing 23 changed files with 990 additions and 580 deletions.
674 changes: 674 additions & 0 deletions COPYING

Large diffs are not rendered by default.

28 changes: 9 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- This GUI tool was designed to test HP & Xerox Printer Connectivity, and to collect HP/Xerox printer mib information.

## Table of Contents

* [General Info](#general-information)
* [Technologies Used](#technologies-used)
* [Features](#features)
Expand All @@ -11,15 +12,18 @@
* [Contact](#contact)

## General Information

- This project was developed for the requirements of a large customer with an inconsistent fleet configuration.
- The purpose of this project is to enable the customer to perform discovery on HP & Xerox Devices on the existing printer estate.
- Due to the technical challenges around device configurations, a tool was required to enable the team to feed in 30,000 IP's, and 1500+ SNMP Community strings from a CSV file based on a location identifier.
- Some printers had ICMP turned off. All printers allowed HTTP(s) Connections.
- Some printers had ICMP turned off.
- All printers allowed HTTP(s) Connections.
- Printers hostname was unique - DNS FQDN naming convention partly used the printer vendor name. This could be used to identify printer type during discovery.
- This tool tests printer connectivity via ICMP, HTTP/s and DNS, it also collects device information via SNMP and outputs results to a csv file for analysis.

## Technologies Used
- Python - version 3.10.4 - https://docs.python.org/3/

- Python - version >=3.10.5 - https://docs.python.org/3/
- Modules - https://docs.python.org/3/tutorial/modules.html
- csv - https://docs.python.org/3/library/csv.html#module-csv
- os - https://docs.python.org/3/library/os.html#module-os
Expand Down Expand Up @@ -82,6 +86,7 @@ The tool provides the following capabilities:
- Easier to view thousands of entries when not on a desktop.

## Screenshots

![Example screenshot](./screenshots/Nagini-SS-01.png)

![Example screenshot](./screenshots/Nagini-SS-02.png)
Expand All @@ -97,26 +102,10 @@ The tool provides the following capabilities:
![Example screenshot](./screenshots/Nagini-SS-07.png)

## Setup
The project dependencies as are follows;

- Python - version 3.10.4 - https://docs.python.org/3/
- Modules - https://docs.python.org/3/tutorial/modules.html
- csv - https://docs.python.org/3/library/csv.html#module-csv
- os - https://docs.python.org/3/library/os.html#module-os
- os.path - https://docs.python.org/3/library/os.path.html
- datetime - https://docs.python.org/3/library/datetime.html
- pysnmp - https://pypi.org/project/pysnmp/
- sys - https://docs.python.org/3/library/sys.html
- re - https://docs.python.org/3/library/re.html#module-re
- clipboard - https://pypi.org/project/clipboard/
- PySimpleGUI - https://www.pysimplegui.org/en/latest/
- requests - https://pypi.org/project/requests/
- pysnmp - https://pysnmp.readthedocs.io/en/latest/
- urllib3 - https://pypi.org/project/urllib3/

* Setup the project from source files;

- Download and install Python >=3.10.4 from https://www.python.org/downloads/
- Download and install Python >=3.10.5 from https://www.python.org/downloads/

- Ensure Python is added to environment SYS Path.

Expand All @@ -143,4 +132,5 @@ The project dependencies as are follows;
- I'm not responsible for how this tool is used.

## Contact

Created by James Dunne - <james.dunne1@gmail.com>
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# ----------------------------------------------------------------------------
# Filename : __init__.py
# Author : James Dunne <james.dunne1@gmail.com>
# License : LGPL-3.0-only
# License : GPL-3.0
# Comment : This file is part of Nagini.
# ----------------------------------------------------------------------------
from gui import nagini_main
Expand Down
2 changes: 1 addition & 1 deletion __main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# ----------------------------------------------------------------------------
# Filename : __main__.py
# Author : James Dunne <james.dunne1@gmail.com>
# License : LGPL-3.0-only
# License : GPL-3.0
# Comment : This file is part of Nagini.
# ----------------------------------------------------------------------------
from nagini import nagini
Expand Down
4 changes: 2 additions & 2 deletions core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
# ----------------------------------------------------------------------------
# Filename : __init__.py
# Author : James Dunne <james.dunne1@gmail.com>
# License : LGPL-3.0-only
# License : GPL-3.0
# Comment : This file is part of Nagini.
# ----------------------------------------------------------------------------
from core.nagini_connc import prn_conn_chk
from core.nagini_datac import prn_data_col
from core.nagini_snmpc import prn_snmp_chk
from core.nagini_snmpc import prn_snmp_chk
64 changes: 34 additions & 30 deletions core/nagini_connc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# ----------------------------------------------------------------------------
# Filename : nagini_connc.py
# Author : James Dunne <james.dunne1@gmail.com>
# License : LGPL-3.0-only
# License : GPL-3.0
# Comment : This file is part of Nagini.
# ----------------------------------------------------------------------------

Expand All @@ -26,33 +26,37 @@ class prn_conn_chk():
Class to check printer web service operation status.
"""
def __init__(self, csv_file, config_file):
self.config_file = config_file # Define config file.
self.csv_file = csv_file # Define CSV file Variable.
nagini_global.env_chk(self.config_file, self.csv_file) # Check file and directories exist.
self.results = {} # Dictionary for results to be stored.
self.output = [] # List for Results Dictionary to be stored.
self.config_file = config_file # Define config file.
self.csv_file = csv_file # Define CSV file Variable.
# Check file and directories exist.
nagini_global.env_chk(self.config_file, self.csv_file)
self.results = {} # Dictionary for results to be stored.
self.output = [] # List for Results Dictionary to be stored.
self.printers = nagini_csv.csv_import(self.csv_file) # Feed csv.
prn_count = 1 # Set the Printer count to 1.
prn_qty = len(self.printers) # Count total printers.
prn_count = 1 # Set the Printer count to 1.
prn_qty = len(self.printers) # Count total printers.
# Write csv header fields to csv file in output directory.
# Usage: <function>(output_dir, filename, fileformat, header type)
nagini_csv.csv_header('output', 'prn_connchk_output', '.csv', 'prn_connc')
nagini_csv.csv_header(
'output', 'prn_connchk_output', '.csv', 'prn_connc')
for printer in self.printers: # Loop through printers.
self.trigram = printer['Trigram'] # Define Trigram.
self.dev_ip = printer['PrinterIP'] # Define Printer IP.
self.trigram = printer['Trigram'] # Define Trigram.
self.dev_ip = printer['PrinterIP'] # Define Printer IP.
# start looping through all class methods per printer.
print('---------------------------------------------------------------' +
'-------------------------------------------------------')
'-------------------------------------------------------')
print(f' Printer {prn_count} of {prn_qty}')
print(f' Starting Printer Connection Checks on Host: {str(self.dev_ip)}')
#print('---------------------------------------------------------------')
prn_count += 1 # Increase Printer Count by 1.
self.results['IP Address'] = self.dev_ip # Append IP to Dict.
self.results['TRIGRAM'] = self.trigram # Append TRI to Dict.
self.prn_web_chk(self.dev_ip) # Call Webchk method.
self.output.append(self.results) # Append results to Dict.
print(
f' Starting Printer Connection Checks on Host: {str(self.dev_ip)}')
# print('---------------------------------------------------------------')
prn_count += 1 # Increase Printer Count by 1.
self.results['IP Address'] = self.dev_ip # Append IP to Dict.
self.results['TRIGRAM'] = self.trigram # Append TRI to Dict.
self.prn_web_chk(self.dev_ip) # Call Webchk method.
self.output.append(self.results) # Append results to Dict.
# Write output to csv file.
nagini_csv.prn_connchk_csv_output(self.output, 'output', 'prn_connchk_output', '.csv')
nagini_csv.prn_connchk_csv_output(
self.output, 'output', 'prn_connchk_output', '.csv')
# Clear results dict.
self.results.clear()
# Clear output list.
Expand All @@ -76,11 +80,11 @@ def prn_web_chk(self, dev_ip):
try:
self.ping_chk(self.dev_ip)
print("---------------------------------------------------------------" +
'-------------------------------------------------------')
'-------------------------------------------------------')
print(f' Starting HTTPS requests on URL: {str(remote_device_url)}')
print("---------------------------------------------------------------"+
'-------------------------------------------------------')
#verify flag here forces the ignoring of self signed ssl certs.
print("---------------------------------------------------------------" +
'-------------------------------------------------------')
# verify flag here forces the ignoring of self signed ssl certs.
response = requests.get(
remote_device_url, verify=False, timeout=60)
if response.status_code == 200: # Finds the OK response.
Expand Down Expand Up @@ -123,7 +127,7 @@ def prn_web_chk(self, dev_ip):
self.results['HTTPS Check'] = str('Offline')
self.results['Model'] = 'None'
emsg = (f'HTTPS Connection Error: Unable to Connect to remote device '
f'{self.dev_ip}')
f'{self.dev_ip}')
nagini_log.logw('conn_log', emsg)

def ping_chk(self, host):
Expand All @@ -133,10 +137,10 @@ def ping_chk(self, host):
request even if the host name is valid.
"""
print("---------------------------------------------------------------" +
'-------------------------------------------------------')
'-------------------------------------------------------')
print(f' Starting ICMP PING requests on Host: {str(host)}')
print("---------------------------------------------------------------" +
'-------------------------------------------------------')
'-------------------------------------------------------')
# Option for the number of packets as a function of
param = '-n' if platform.system().lower() == 'windows' else '-c'
# Building the command. Ex: "ping -c 1 <dev_ip>"
Expand All @@ -150,7 +154,7 @@ def ping_chk(self, host):
print(" * Printer Ping Result: Ping Successful!")
self.results['Ping Check'] = str('Online')
self.dns_lookup(host)
else:
else:
print(" * Printer Ping Result: No Response!")
self.results['Ping Check'] = str('Offline')
self.dns_lookup(host)
Expand All @@ -161,10 +165,10 @@ def dns_lookup(self, dev_ip):
"""
try:
print("---------------------------------------------------------------" +
'-------------------------------------------------------')
'-------------------------------------------------------')
print(f' Starting DNS Lookup on Host: {dev_ip}')
print("---------------------------------------------------------------" +
'-------------------------------------------------------')
'-------------------------------------------------------')
self.dns = socket.gethostbyaddr(dev_ip)
print(f' * DNS Hostname: {self.dns[0]}')
self.results['DNS Resolution'] = str(self.dns[0])
Expand Down
34 changes: 19 additions & 15 deletions core/nagini_datac.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# ----------------------------------------------------------------------------
# Filename : nagini_datac.py
# Author : James Dunne <james.dunne1@gmail.com>
# License : LGPL-3.0-only
# License : GPL-3.0
# Comment : This file is part of Nagini.
# ----------------------------------------------------------------------------
# Tested Models: Phaser / VersaLink / WorkCentre / DocuCentre / AperosPort-V
Expand All @@ -19,8 +19,8 @@
from functions import nagini_csv as nagini_csv # CSV functions.
from functions import nagini_dir as nagini_dir # Directory I/O Functions.
from functions import nagini_log as nagini_log # Logging Function.
from functions import nagini_snmp as nagini_snmp # SNMP functions.
from functions import nagini_global # Global functions shared.
from functions import nagini_snmp as nagini_snmp # SNMP functions.
from functions import nagini_global # Global functions shared.

class prn_data_col():
"""
Expand All @@ -30,22 +30,24 @@ def __init__(self, csv_file, config_file, vendor):
# Define config file.
self.config_file = config_file
# Set csv filename.
self.csv_file = csv_file
self.csv_file = csv_file
# Printer vendor name.
self.vendor = vendor
self.vendor = vendor
# Read the config_file contents.
config = configparser.ConfigParser()
config.read(self.config_file)
# '1.3.6.1.2.1.1.5.0' # Hostname.
self.snmp_hostname_oid = config.get(self.vendor, 'snmp_hostname_oid')
# Syslc.
self.sys_location_oid = config.get(self.vendor, 'sys_location_oid')
self.mac_addr_oid = config.get(self.vendor, 'mac_addr_oid') # Mac Address.
# Mac Address.
self.mac_addr_oid = config.get(self.vendor, 'mac_addr_oid')
self.mono_oid = config.get(self.vendor, 'mono_oid') # Mono.
self.color_oid = config.get(self.vendor, 'color_oid') # Color.
self.total_oid = config.get(self.vendor, 'total_oid') # Total counts.
# Device desc oid.
self.hr_Device_Descr_oid = config.get(self.vendor, 'hr_Device_Descr_oid')
self.hr_Device_Descr_oid = config.get(
self.vendor, 'hr_Device_Descr_oid')
# Sys firmware oid.
self.sys_Descr_oid = config.get(self.vendor, 'sys_Descr_oid')
# Serialnumber oid.
Expand All @@ -65,20 +67,21 @@ def main(self):
prn_qty = len(self.printers) # Count total printers.
# Write csv header fields to csv file in output directory.
# Usage: <function>(output_dir, filename, fileformat)
nagini_csv.csv_header('output', 'prn_datacol_output', '.csv', 'prn_datac')
nagini_csv.csv_header(
'output', 'prn_datacol_output', '.csv', 'prn_datac')
# Loop through csv file and call methods from class.
for printer in self.printers:
self.trigram = printer['Trigram']
self.dev_ip = printer['PrinterIP']
self.snmp_cs = printer['SNMPGet']
# start looping through all class methods per printer.
print('---------------------------------------------------------------' +
'-------------------------------------------------------')
'-------------------------------------------------------')
print(f' Printer {prn_count} of {prn_qty}')
print(
f' Starting Printer SNMP interrogation on IP: {str(self.dev_ip)}')
print('---------------------------------------------------------------' +
'-------------------------------------------------------')
'-------------------------------------------------------')
prn_count += 1 # Increase Printer Count by 1.
# Call methods from the prndatacollector class.
self.prn_desc() # Retrieves Printer Description.
Expand Down Expand Up @@ -108,7 +111,7 @@ def main(self):
# Clear prnoutput list.
self.prn_output.clear()
nagini_global.end_msg()

def prn_desc(self):
"""
Method to collect printer description from SNMP OID.
Expand All @@ -118,7 +121,7 @@ def prn_desc(self):
prn_hrdd = nagini_snmp.get(
self.dev_ip, [self.hr_Device_Descr_oid], hlapi.CommunityData(self.snmp_cs))
# find the vendor string in the hrDeviceDescr string as provided.
if (str(prn_hrdd).find(self.vendor) != -1):
if (str(prn_hrdd).find(self.vendor) != -1):
print(
f' * Device Description: {prn_hrdd[self.hr_Device_Descr_oid]}')
self.prn_info['Description'] = str(
Expand Down Expand Up @@ -164,7 +167,8 @@ def mac_addr(self):
"""
try:
# Using SNMPv2c, we retrieve the mac address of the remote device.
prn_mac = nagini_snmp.snmpmac(self.dev_ip, self.snmp_cs, self.mac_addr_oid)
prn_mac = nagini_snmp.snmpmac(
self.dev_ip, self.snmp_cs, self.mac_addr_oid)
print(f' * Printer MAC Address: {str(prn_mac)}')
self.prn_info['MAC Address'] = str(prn_mac)
except RuntimeError:
Expand Down Expand Up @@ -200,7 +204,7 @@ def color_c(self):
"""
Method to collect printer color count value from SNMP OID.
"""
try:
try:
# Using SNMPv2c, we retrieve the color count of the remote device.
prn_cc = nagini_snmp.get(
self.dev_ip, [self.color_oid], hlapi.CommunityData(self.snmp_cs))
Expand All @@ -216,7 +220,7 @@ def total_c(self):
try:
# Using SNMPv2c, we retrieve total impressions of the remote device.
prn_tc = nagini_snmp.get(
self.dev_ip, [self.total_oid], hlapi.CommunityData(self.snmp_cs))
self.dev_ip, [self.total_oid], hlapi.CommunityData(self.snmp_cs))
print(f' * Total Count: {str(prn_tc[self.total_oid])}')
self.prn_info['Totalcount'] = str(prn_tc[self.total_oid])
except RuntimeError:
Expand Down
Loading

0 comments on commit d6c5904

Please sign in to comment.