Initial commit of version 2

This commit is contained in:
Simon Wüllhorst 2016-05-29 18:56:50 +02:00
commit ff7105eedc
23 changed files with 782 additions and 0 deletions

23
cloud/Domaene.py Normal file
View file

@ -0,0 +1,23 @@
from cloud.LocalGraph import LocalGraph
class Domaene(object):
def __init__(self, name, shapes, globalGraph):
self.name = name
self.__shapes__ = shapes
self.__globalGraph__ = globalGraph
self.localGraphs = self.__getLocalGraphsInDomaene__()
def __getLocalGraphsInDomaene__(self):
graphs = []
for localGraph in self.__globalGraph__.localGraphs:
if self.isLocalGraphInDomaene(localGraph) == True:
graphs.append(localGraph)
return graphs
def isLocalGraphInDomaene(self, localGraph):
return self.isPointInDomaene(localGraph.getGeoCenterOfNodeCloud())
def isPointInDomaene(self, point):
for shape in self.__shapes__.shapes:
if point.within(shape):
return True
return False

46
cloud/GlobalGraph.py Normal file
View file

@ -0,0 +1,46 @@
from cloud.LocalGraph import LocalGraph
from cloud.Graph import Graph
from exceptions.HieraException import HieraException
class GlobalGraph(Graph):
def __init__(self, nodes, links, debugPrint = False):
super().__init__(nodes, links)
self.__enableDebugPrinting__ = debugPrint
self.localGraphs = self.__buildLocalGraphs__()
if self.__enableDebugPrinting__:
self.__debugPrint__()
def __buildLocalGraphs__(self):
nodeIDs = self.getListOfNodeIDsOnline()
localGraphs = []
while len(nodeIDs) > 0:
connectedNodes = self.__getConnectedNodes__(nodeIDs[0])
try:
localGraphs.append(self.__createLocalCloudByNodesList__(connectedNodes))
print('Create LocalGraph object #',len(localGraphs), '\r',end = '')
except HieraException:
print('Was not able to add local cloud, because no VPN link was found.')
nodeIDs = [x for x in nodeIDs if x not in connectedNodes]
print('')
return localGraphs
def __getConnectedNodes__(self, nodeID, trace = []):
neighNodeIDs = self.getNeighbourNodeIDsForNodeID(nodeID)
trace_new = trace[:] + [x for x in neighNodeIDs if x not in trace]
for neighNodeID in neighNodeIDs:
if neighNodeID not in trace:
trace_new = trace_new + [x for x in self.__getConnectedNodes__(neighNodeID, trace_new) if x not in trace_new]
return trace_new
def __createLocalCloudByNodesList__(self, nodesIDList):
nodes = {}
links = []
for nodeID in nodesIDList:
nodes[nodeID] = self.__nodes__[nodeID]
links = links + [x for x in self.getLinksByNodeID(nodeID) if x not in links]
return LocalGraph(nodes, links, self.__enableDebugPrinting__)
def __debugPrint__(self):
for localGraph in self.localGraphs:
for node in localGraph.getNodesWithNoDependencies():
print(node.hostname, node.publicIPv6Addresses)

45
cloud/Graph.py Normal file
View file

@ -0,0 +1,45 @@
from oauthlib.oauth1.rfc5849 import endpoints
class Graph(object):
def __init__(self, nodes, links):
self.__nodes__ = nodes
self.__links__ = links
def getListOfNodeIDs(self, getGateways = False):
nodeIDs = []
for k, v in self.__nodes__.items():
if getGateways == True or v.isGateway == False:
nodeIDs.append(k)
return nodeIDs
def getListOfNodeIDsOnline(self, getGateways = False):
onlineNodeIDs = []
nodeIDs = self.getListOfNodeIDs(getGateways)
for nodeID in nodeIDs:
if self.__nodes__[nodeID].isOnline == True:
onlineNodeIDs.append(nodeID)
return onlineNodeIDs
def getNeighbourNodeIDsForNodeID(self, nodeID):
neighNodeIDs = [nodeID]
endpoints = []
for link in self.__links__:
if link.isVpn == False:
endpoints = link.getEndpointNodeIDs(getGateways = False)
if nodeID in endpoints:
neighNodeIDs = neighNodeIDs + [x for x in endpoints if x not in neighNodeIDs]
return neighNodeIDs
def getLinksByNodeID(self, nodeID):
links = []
for link in self.__links__:
endpoints = link.getEndpointNodeIDs()
if nodeID in endpoints:
if link not in links:
links.append(link)
return links
def getLinkCount(self):
return len(self.__links__)
def getNodesCount(self):
return len(self.__nodes__)

52
cloud/Link.py Normal file
View file

@ -0,0 +1,52 @@
class Link(object):
def __init__(self, LinkJsonObject, srcNode, dstNode):
self.__jsonObject__ = LinkJsonObject
self.__srcNode__ = srcNode
self.__dstNode__ = dstNode
self.linkType = self.__getLinkType__()
self.isVpn = self.__getLinkVpnState__()
def __getLinkType__(self):
if self.__srcNode__ != None:
for k, v in self.__srcNode__.interfaces.items():
if self.__jsonObject__['source']['interface_mac'] in v:
return k
if self.__dstNode__ != None:
for k, v in self.__dstNode__.interfaces.items():
if self.__jsonObject__['target']['interface_mac'] in v:
return k
return 'unknown'
def __getLinkVpnState__(self):
if self.__jsonObject__['vpn'] == True:
return True
for node in self.getEndpointNodes(getGateways = True):
if node.isGateway == True:
return True
return False
def getEndpointNodes(self, getGateways = False):
nodes = []
if self.__srcNode__ != None:
if getGateways == True or self.__srcNode__.isGateway == False:
nodes.append(self.__srcNode__)
if self.__dstNode__ != None:
if getGateways == True or self.__dstNode__.isGateway == False:
nodes.append(self.__dstNode__)
return nodes
def getEndpointNodeIDs(self, getGateways = True):
nodeIDs = []
for node in self.getEndpointNodes(getGateways):
nodeIDs.append(node.nodeID)
return nodeIDs
def isNodeIDinLink(self, nodeID):
for endpoint in self.getEndpointNodes():
if endpoint.nodeID == nodeID:
return True
return False
def isNodeInLink(self, node):
return self.isNodeIDinLink(node.nodeID)

118
cloud/LocalGraph.py Normal file
View file

@ -0,0 +1,118 @@
from cloud.Graph import Graph
from shapely.geometry import MultiPoint
from exceptions.HieraException import HieraException
class LocalGraph(Graph):
def __init__(self, nodes, links, debugPrint = False):
super().__init__(nodes, links)
self.__enableDebugPrinting__ = debugPrint
if self.__enableDebugPrinting__:
self.__debugPrint__()
def getNodesWithVpn(self):
nodes = []
for link in self.__links__:
if link.isVpn == True:
nodes = nodes + [x for x in link.getEndpointNodes() if x not in nodes]
return nodes
def getCountOfNodesWithVpn(self):
return len(self.getNodesWithVpn())
def getDeptOfNode(self, node):
return self.getDeptOfNodeByID(node.nodeID, [])
def getDeptOfNodeByID(self, nodeID, trace):
if self.getCountOfNodesWithVpn() == 0:
raise HieraException('No VPN Node in LocalCloud was found!')
new_trace = trace[:]
new_trace.append(nodeID)
lowestDepth = None
currentDept = None
links = self.getLinksByNodeID(nodeID)
endpoints = []
for link in links:
endpoints = endpoints + [x for x in link.getEndpointNodeIDs() if x not in endpoints]
if link.isVpn == True:
return 0
for childNodeID in endpoints:
if childNodeID not in new_trace:
currentDept = self.getDeptOfNodeByID(childNodeID, new_trace + endpoints)
if currentDept != None:
currentDept = currentDept + 1
if lowestDepth == None or currentDept < lowestDepth:
lowestDepth = currentDept
return lowestDepth
def getMaxDepth(self):
maxDepth = 0
for k,v in self.__nodes__.items():
nodeDepth = self.getDeptOfNode(v)
maxDepth = nodeDepth if nodeDepth > maxDepth else maxDepth
return maxDepth
def getAllNodesWithDepthEquals(self, depth):
nodes = []
for k,v in self.__nodes__.items():
if self.getDeptOfNode(v) == depth:
nodes.append(v)
return nodes
def getNodesWithNoDependencies(self):
#TODO: Implement smarter selection
return self.getAllNodesWithDepthEquals(self.getMaxDepth())
def isAutoupdaterEnabledOnAllNodes(self):
for k, v in self.__nodes__.items():
if v.isAutoupdaterEnabled == False:
return False
return True
def getLanLinksInCloud(self):
links = []
for link in self.__links__:
if link.linkType == 'other' and link.isVpn == False:
links.append(link)
return links
def areLanLinksInCloud(self):
for link in self.__links__:
if link.linkType == 'other' and link.isVpn == False:
return True
return False
def getBranchesThatExistsInCloud(self):
branches = []
for k, v in self.__nodes__.items():
if v.autoupdaterBranch not in branches:
branches.append(v.autoupdaterBranch)
return branches
def getGeoCenterOfNodeCloud(self):
geoPoints = []
for k, v in self.__nodes__.items():
if v.geo != None:
geoPoints.append((v.geo['lon'], v.geo['lat']))
return MultiPoint(geoPoints).representative_point()
def __debugPrint__(self):
print('nodes:')
for k,v in self.__nodes__.items():
print('>',v.hostname)
print('nodes with vpn:')
for node in self.getNodesWithVpn():
print('>',node.hostname)
print('nodes with no dependencies:')
for node in self.getNodesWithNoDependencies():
print('>', node.hostname)
print('maxdepth:', self.getMaxDepth())
print('isAutoupdaterEnabledOnAllNodes:', self.isAutoupdaterEnabledOnAllNodes())
print('areLanLinksInCloud:', self.areLanLinksInCloud())
print('BranchesThatExistsInCloud:', self.getBranchesThatExistsInCloud())
print('lan links in cloud:')
for link in self.getLanLinksInCloud():
if link.__srcNode__ != None and link.__dstNode__ != None:
print(' ', link.__srcNode__.hostname, '<--->', link.__dstNode__.hostname)
print('=====')

4
cloud/Node.py Normal file
View file

@ -0,0 +1,4 @@
from cloud.NodeInit import NodeInit
class Node(NodeInit):
def __init__(self, NodeJsonObject):
super().__init__(NodeJsonObject)

54
cloud/NodeInit.py Normal file
View file

@ -0,0 +1,54 @@
class NodeInit(object):
def __init__(self, NodeJsonObject):
self.__jsonObject__ = NodeJsonObject
self.nodeID = self.__jsonObject__['nodeinfo']['node_id']
self.interfaces = self.__getInterfaces__()
self.hostname = self.__jsonObject__['nodeinfo']['hostname']
self.isGateway = self.__jsonObject__['flags']['gateway']
self.geo = self.__getGeo__()
self.isAutoupdaterEnabled = self.__getAutoupdaterStatus__()
self.autoupdaterBranch = self.__getBranch__()
self.isOnline = self.__jsonObject__['flags']['online']
self.publicIPv6Addresses = self.__getPublicAddresses__()
self.domID = self.__getSiteCode__()
def __getInterfaces__(self):
try:
return self.__jsonObject__['nodeinfo']['network']['mesh']['bat0']['interfaces']
except:
return {}
def __getAutoupdaterStatus__(self):
if 'autoupdater' in self.__jsonObject__['nodeinfo']['software']:
return self.__jsonObject__['nodeinfo']['software']['autoupdater']['enabled']
else:
return False
def __getBranch__(self):
if 'autoupdater' in self.__jsonObject__['nodeinfo']['software']:
return self.__jsonObject__['nodeinfo']['software']['autoupdater']['branch']
else:
return None
def __getGeo__(self):
geo = {}
if 'location' in self.__jsonObject__['nodeinfo'] and 'latitude' in self.__jsonObject__['nodeinfo']['location'] and 'longitude' in self.__jsonObject__['nodeinfo']['location']:
geo['lat'] = self.__jsonObject__['nodeinfo']['location']['latitude']
geo['lon'] = self.__jsonObject__['nodeinfo']['location']['longitude']
return geo
return None
def __getPublicAddresses__(self):
addresses = []
if 'addresses' in self.__jsonObject__['nodeinfo']['network']:
for address in self.__jsonObject__['nodeinfo']['network']['addresses']:
#TODO: make more generic
if address.startswith('2a03'):
addresses.append(address)
return addresses
def __getSiteCode__(self):
try:
return self.__jsonObject__['nodeinfo']['system']['site_code']
except:
return None

0
cloud/__init__.py Normal file
View file