Update integrationSplynx.py

This commit is contained in:
Robert Chacón 2024-07-30 16:12:24 -06:00 committed by GitHub
parent 352bafce96
commit 35381756a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -14,247 +14,243 @@ if find_ipv6_using_mikrotik() == True:
from integrationCommon import NetworkGraph, NetworkNode, NodeType from integrationCommon import NetworkGraph, NetworkNode, NodeType
def buildHeaders(): def buildHeaders():
credentials = splynx_api_key() + ':' + splynx_api_secret() """
credentials = base64.b64encode(credentials.encode()).decode() Build authorization headers for Splynx API requests using API key and secret.
return {'Authorization' : "Basic %s" % credentials} """
credentials = splynx_api_key() + ':' + splynx_api_secret()
credentials = base64.b64encode(credentials.encode()).decode()
return {'Authorization': "Basic %s" % credentials}
def spylnxRequest(target, headers): def spylnxRequest(target, headers):
# Sends a REST GET request to Spylnx and returns the """
# result in JSON Send a GET request to the Splynx API and return the JSON response.
url = splynx_api_url() + "/api/2.0/" + target """
r = requests.get(url, headers=headers, timeout=120) url = splynx_api_url() + "/api/2.0/" + target
return r.json() r = requests.get(url, headers=headers, timeout=120)
return r.json()
def getTariffs(headers): def getTariffs(headers):
data = spylnxRequest("admin/tariffs/internet", headers) """
tariff = [] Retrieve tariff data from Splynx API and calculate download/upload speeds for each tariff.
downloadForTariffID = {} """
uploadForTariffID = {} data = spylnxRequest("admin/tariffs/internet", headers)
for tariff in data: downloadForTariffID = {}
tariffID = tariff['id'] uploadForTariffID = {}
speed_download = round((int(tariff['speed_download']) / 1000)) for tariff in data:
speed_upload = round((int(tariff['speed_upload']) / 1000)) tariffID = tariff['id']
downloadForTariffID[tariffID] = speed_download speed_download = round((int(tariff['speed_download']) / 1000))
uploadForTariffID[tariffID] = speed_upload speed_upload = round((int(tariff['speed_upload']) / 1000))
return (tariff, downloadForTariffID, uploadForTariffID) downloadForTariffID[tariffID] = speed_download
uploadForTariffID[tariffID] = speed_upload
return (data, downloadForTariffID, uploadForTariffID)
def buildSiteBandwidths(): def buildSiteBandwidths():
# Builds a dictionary of site bandwidths from the integrationSplynxBandwidths.csv file. """
siteBandwidth = {} Build a dictionary of site bandwidths by reading data from a CSV file.
if os.path.isfile("integrationSplynxBandwidths.csv"): """
with open('integrationSplynxBandwidths.csv') as csv_file: siteBandwidth = {}
csv_reader = csv.reader(csv_file, delimiter=',') if os.path.isfile("integrationSplynxBandwidths.csv"):
next(csv_reader) with open('integrationSplynxBandwidths.csv') as csv_file:
for row in csv_reader: csv_reader = csv.reader(csv_file, delimiter=',')
name, download, upload = row next(csv_reader)
download = int(float(download)) for row in csv_reader:
upload = int(float(upload)) name, download, upload = row
siteBandwidth[name] = {"download": download, "upload": upload} download = int(float(download))
return siteBandwidth upload = int(float(upload))
siteBandwidth[name] = {"download": download, "upload": upload}
return siteBandwidth
def getCustomers(headers): def getCustomers(headers):
data = spylnxRequest("admin/customers/customer", headers) """
#addressForCustomerID = {} Retrieve all customer data from Splynx API.
#customerIDs = [] """
#for customer in data: return spylnxRequest("admin/customers/customer", headers)
# customerIDs.append(customer['id'])
# addressForCustomerID[customer['id']] = customer['street_1']
return data
def getCustomersOnline(headers): def getCustomersOnline(headers):
data = spylnxRequest("admin/customers/customers-online", headers) """
return data Retrieve data of currently online customers from Splynx API.
"""
return spylnxRequest("admin/customers/customers-online", headers)
def getRouters(headers): def getRouters(headers):
data = spylnxRequest("admin/networking/routers", headers) """
routerIdList = [] Retrieve router data from Splynx API and build dictionaries for router IPs and names.
ipForRouter = {} """
nameForRouterID = {} data = spylnxRequest("admin/networking/routers", headers)
for router in data: routerIdList = []
routerID = router['id'] ipForRouter = {}
if router['id'] not in routerIdList: nameForRouterID = {}
routerIdList.append(router['id']) for router in data:
ipForRouter[routerID] = router['ip'] routerID = router['id']
nameForRouterID[routerID] = router['title'] if router['id'] not in routerIdList:
print("Router IPs found: " + str(len(ipForRouter))) routerIdList.append(router['id'])
return (ipForRouter, nameForRouterID, routerIdList) ipForRouter[routerID] = router['ip']
nameForRouterID[routerID] = router['title']
print("Router IPs found: " + str(len(ipForRouter)))
return (ipForRouter, nameForRouterID, routerIdList)
def getSectors(headers): def getSectors(headers):
data = spylnxRequest("admin/networking/routers-sectors", headers) """
sectorForRouter = {} Retrieve sector data from Splynx API and build a dictionary mapping routers to their sectors.
for sector in data: """
routerID = sector['router_id'] data = spylnxRequest("admin/networking/routers-sectors", headers)
if routerID not in sectorForRouter: sectorForRouter = {}
newList = [] for sector in data:
newList.append(sector) routerID = sector['router_id']
sectorForRouter[routerID] = newList if routerID not in sectorForRouter:
else: newList = []
newList = sectorForRouter[routerID] newList.append(sector)
newList.append(sector) sectorForRouter[routerID] = newList
sectorForRouter[routerID] = newList else:
newList = sectorForRouter[routerID]
newList.append(sector)
sectorForRouter[routerID] = newList
print("Router Sectors found: " + str(len(sectorForRouter))) print("Router Sectors found: " + str(len(sectorForRouter)))
return sectorForRouter return sectorForRouter
def combineAddress(json): def combineAddress(json):
# Combines address fields into a single string """
# The API docs seem to indicate that there isn't a "state" field? Combine address fields into a single string. If address fields are empty, use ID and name.
if json["street_1"]=="" and json["city"]=="" and json["zip_code"]=="": """
return str(json["id"]) + "/" + json["name"] if json["street_1"] == "" and json["city"] == "" and json["zip_code"] == "":
else: return str(json["id"]) + "/" + json["name"]
return json["street_1"] + " " + json["city"] + " " + json["zip_code"] else:
return json["street_1"] + " " + json["city"] + " " + json["zip_code"]
def getAllServices(headers): def getAllServices(headers):
services = spylnxRequest("admin/customers/customer/0/internet-services?main_attributes%5Bstatus%5D=active", headers) """
return services Retrieve all active internet services from Splynx API.
"""
return spylnxRequest("admin/customers/customer/0/internet-services?main_attributes%5Bstatus%5D=active", headers)
def getAllIPs(headers): def getAllIPs(headers):
ipv4ByCustomerID = {} """
ipv6ByCustomerID = {} Retrieve all used IPv4 and IPv6 addresses from Splynx API and map them to customer IDs.
allIPv4 = spylnxRequest("admin/networking/ipv4-ip?main_attributes%5Bis_used%5D=1", headers) """
allIPv6 = spylnxRequest("admin/networking/ipv6-ip", headers) ipv4ByCustomerID = {}
for ipv4 in allIPv4: ipv6ByCustomerID = {}
if ipv4['customer_id'] not in ipv4ByCustomerID: allIPv4 = spylnxRequest("admin/networking/ipv4-ip?main_attributes%5Bis_used%5D=1", headers)
ipv4ByCustomerID[ipv4['customer_id']] = [] allIPv6 = spylnxRequest("admin/networking/ipv6-ip", headers)
temp = ipv4ByCustomerID[ipv4['customer_id']] for ipv4 in allIPv4:
temp.append(ipv4['ip']) if ipv4['customer_id'] not in ipv4ByCustomerID:
ipv4ByCustomerID[ipv4['customer_id']] = temp ipv4ByCustomerID[ipv4['customer_id']] = []
for ipv6 in allIPv6: temp = ipv4ByCustomerID[ipv4['customer_id']]
if ipv6['is_used'] == 1: temp.append(ipv4['ip'])
if ipv6['customer_id'] not in ipv6ByCustomerID: ipv4ByCustomerID[ipv4['customer_id']] = temp
ipv6ByCustomerID[ipv6['customer_id']] = [] for ipv6 in allIPv6:
temp = ipv6ByCustomerID[ipv6['customer_id']] if ipv6['is_used'] == 1:
temp.append(ipv6['ip']) if ipv6['customer_id'] not in ipv6ByCustomerID:
ipv6ByCustomerID[ipv6['customer_id']] = temp ipv6ByCustomerID[ipv6['customer_id']] = []
return (ipv4ByCustomerID, ipv6ByCustomerID) temp = ipv6ByCustomerID[ipv6['customer_id']]
temp.append(ipv6['ip'])
ipv6ByCustomerID[ipv6['customer_id']] = temp
return (ipv4ByCustomerID, ipv6ByCustomerID)
def createShaper(): def createShaper():
net = NetworkGraph() """
Main function to fetch data from Splynx, build the network graph, and shape devices.
"""
net = NetworkGraph()
print("Fetching data from Spylnx") print("Fetching data from Spylnx")
headers = buildHeaders() headers = buildHeaders()
tariff, downloadForTariffID, uploadForTariffID = getTariffs(headers) tariff, downloadForTariffID, uploadForTariffID = getTariffs(headers)
customers = getCustomers(headers) customers = getCustomers(headers)
customersOnline = getCustomersOnline(headers) customersOnline = getCustomersOnline(headers)
ipForRouter, nameForRouterID, routerIdList = getRouters(headers) ipForRouter, nameForRouterID, routerIdList = getRouters(headers)
sectorForRouter = getSectors(headers) sectorForRouter = getSectors(headers)
allServices = getAllServices(headers) allServices = getAllServices(headers)
ipv4ByCustomerID, ipv6ByCustomerID = getAllIPs(headers) ipv4ByCustomerID, ipv6ByCustomerID = getAllIPs(headers)
siteBandwidth = buildSiteBandwidths() siteBandwidth = buildSiteBandwidths()
#Go through all online customers, create Nodes allParentNodes = []
allParentNodes = [] custIDtoParentNode = {}
custIDtoParentNode = {} parentNodeIDCounter = 30000
parentNodeIDCounter = 30000
for customer in customersOnline:
download = 1000
upload = 1000
nodeName = customer['nas_id'] + "_" + customer['call_to'] + "_" + customer['port']
if nodeName not in allParentNodes: # Create nodes for sites and assign bandwidth
if nodeName in siteBandwidth: for customer in customersOnline:
# Use the CSV bandwidth values download = 1000
download = siteBandwidth[nodeName]["download"] upload = 1000
upload = siteBandwidth[nodeName]["upload"] nodeName = customer['nas_id'] + "_" + customer['call_to'] + "_" + customer['port']
node = NetworkNode(id=parentNodeIDCounter, displayName=nodeName, type=NodeType.site, if nodeName not in allParentNodes:
parentId=None, download=download, upload=upload, address=None) if nodeName in siteBandwidth:
net.addRawNode(node) download = siteBandwidth[nodeName]["download"]
upload = siteBandwidth[nodeName]["upload"]
pnEntry = {} node = NetworkNode(id=parentNodeIDCounter, displayName=nodeName, type=NodeType.site,
pnEntry['name'] = nodeName parentId=None, download=download, upload=upload, address=None)
pnEntry['id'] = parentNodeIDCounter net.addRawNode(node)
custIDtoParentNode[customer['customer_id']] = pnEntry
parentNodeIDCounter += 1 pnEntry = {}
pnEntry['name'] = nodeName
pnEntry['id'] = parentNodeIDCounter
custIDtoParentNode[customer['customer_id']] = pnEntry
#customerIDtoParentNodeID = {} parentNodeIDCounter += 1
allServicesDict = {}
for serviceItem in allServices:
if (serviceItem['status'] == 'active'):
if serviceItem["customer_id"] not in allServicesDict:
allServicesDict[serviceItem["customer_id"]] = []
temp = allServicesDict[serviceItem["customer_id"]]
temp.append(serviceItem)
allServicesDict[serviceItem["customer_id"]] = temp
#It's not very clear how a service is meant to handle multiple allServicesDict = {}
#devices on a shared tariff. Creating each service as a combined for serviceItem in allServices:
#entity including the customer, to be on the safe side. if serviceItem['status'] == 'active':
for customerJson in customers: if serviceItem["customer_id"] not in allServicesDict:
if customerJson['status'] == 'active': allServicesDict[serviceItem["customer_id"]] = []
if customerJson['id'] in allServicesDict: temp = allServicesDict[serviceItem["customer_id"]]
servicesForCustomer = allServicesDict[customerJson['id']] temp.append(serviceItem)
for service in servicesForCustomer: allServicesDict[serviceItem["customer_id"]] = temp
combinedId = "c_" + str(customerJson["id"]) + "_s_" + str(service["id"])
tariff_id = service['tariff_id']
parentID = None # Create nodes for customers and their devices
if customerJson['id'] in custIDtoParentNode: for customerJson in customers:
parentID = custIDtoParentNode[customerJson['id']]['id'] if customerJson['status'] == 'active':
if customerJson['id'] in allServicesDict:
servicesForCustomer = allServicesDict[customerJson['id']]
for service in servicesForCustomer:
combinedId = "c_" + str(customerJson["id"]) + "_s_" + str(service["id"])
tariff_id = service['tariff_id']
customer = NetworkNode( parentID = None
type=NodeType.client, if customerJson['id'] in custIDtoParentNode:
id=combinedId, parentID = custIDtoParentNode[customerJson['id']]['id']
parentId = parentID,
displayName=customerJson["name"],
address=combineAddress(customerJson),
customerName=customerJson["name"],
download=downloadForTariffID[tariff_id],
upload=uploadForTariffID[tariff_id],
)
net.addRawNode(customer)
ipv4 = [] customer = NetworkNode(
ipv6 = [] type=NodeType.client,
routerID = service['router_id'] id=combinedId,
parentId=parentID,
displayName=customerJson["name"],
address=combineAddress(customerJson),
customerName=customerJson["name"],
download=downloadForTariffID[tariff_id],
upload=uploadForTariffID[tariff_id]
)
net.addRawNode(customer)
# If not "Taking IPv4" (Router will assign IP), then use router's set IP ipv4 = ipv4ByCustomerID.get(customerJson["id"], [])
taking_ipv4 = int(service['taking_ipv4']) ipv6 = ipv6ByCustomerID.get(customerJson["id"], [])
if taking_ipv4 == 0:
if routerID in ipForRouter:
ipv4 = [ipForRouter[routerID]]
elif taking_ipv4 == 1: device = NetworkNode(
ipv4 = [service['ipv4']] id=combinedId + "_d" + str(service["id"]),
if len(ipv4) == 0: displayName=service["id"],
#Only do this if single service for a customer type=NodeType.device,
if len(servicesForCustomer) == 1: parentId=combinedId,
if customerJson['id'] in ipv4ByCustomerID: mac=service["mac"],
ipv4 = ipv4ByCustomerID[customerJson['id']] ipv4=ipv4,
ipv6=ipv6
)
net.addRawNode(device)
# If not "Taking IPv6" (Router will assign IP), then use router's set IP net.prepareTree()
if isinstance(service['taking_ipv6'], str): net.plotNetworkGraph(False)
taking_ipv6 = int(service['taking_ipv6']) if net.doesNetworkJsonExist():
else: print("network.json already exists. Leaving in-place.")
taking_ipv6 = service['taking_ipv6'] else:
if taking_ipv6 == 0: net.createNetworkJson()
ipv6 = [] net.createShapedDevices()
elif taking_ipv6 == 1:
ipv6 = [service['ipv6']]
device = NetworkNode(
id=combinedId+"_d" + str(service["id"]),
displayName=service["id"],
type=NodeType.device,
parentId=combinedId,
mac=service["mac"],
ipv4=ipv4,
ipv6=ipv6
)
net.addRawNode(device)
net.prepareTree()
net.plotNetworkGraph(False)
if net.doesNetworkJsonExist():
print("network.json already exists. Leaving in-place.")
else:
net.createNetworkJson()
net.createShapedDevices()
def importFromSplynx(): def importFromSplynx():
#createNetworkJSON() """
createShaper() Entry point for the script to initiate the Splynx data import and shaper creation process.
"""
createShaper()
if __name__ == '__main__': if __name__ == '__main__':
importFromSplynx() importFromSplynx()