mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Update integrationSplynx.py
This commit is contained in:
parent
352bafce96
commit
35381756a0
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user