def __addAllLinksToGraph(self, links: List[Tuple[str, str]]) -> None: for (nm1, nm2) in links: if nm1 not in self.devices: raise DiagramGraphError('Device ' + nm1 + ' not found in Graph devices') elif nm2 not in self.devices: raise DiagramGraphError('Device ' + nm2 + ' not found in Graph devices') else: self.devices[nm1].addNeighbor(self.devices[nm2])
def findRouterLinksAndSubnetRoots( self, tree: DiagramTree, router: DiagramNode, ) -> Tuple[DiagramTree, Set[Name]]: """Traverse through routers then attached Subnets to build DiagramTree""" tree.visited.add(router.deviceName) tree.addRouter(router.deviceName) for neighbor in router.neighbors: if neighbor.deviceName not in tree.visited: tree.addPrimaryLink(router.deviceName, neighbor.deviceName) if neighbor.isRouter(): tree = self.findRouterLinksAndSubnetRoots(tree, neighbor) elif neighbor.isSwitch(): subnet = DiagramSubnet() (tree, subnet) = self.findSwitchLinksAndHosts( tree, subnet, neighbor) tree.addSubnet(subnet) else: raise DiagramGraphError( 'Device type ROUTER cannot be neighbors with ' + neighbor.deviceName, self) else: if not tree.isRedundantLink(router.deviceName, neighbor.deviceName): tree.addSecondaryLink(router.deviceName, neighbor.deviceName) return tree
def getDiagramTree(self) -> DiagramTree: """Traverse DiagramGraph to deduce DiagramTree""" tree: DiagramTree = DiagramTree() # build connections if self.root: if self.root.isRouter(): tree = self.findRouterLinksAndSubnetRoots(tree, self.root) elif self.root.isSwitch(): subnet = DiagramSubnet() (tree, _) = self.findSwithLinksAndHosts(tree, subnet, self.root) tree.addSubnet(subnet) else: raise DiagramGraphError( 'Root node must be type ROUTER or SWITCH', self) for dvcname, dvc in self.devices.items(): if (dvcname not in tree.visited) or not tree.visited: tree.addFreeNode(dvc) for (dvc1, dvc2) in self.links: if ((dvc1, dvc2) not in tree.redundantLinks): tree.addUnusedLink(dvc1, dvc2) return tree
def addFreeNode(self, node: DiagramNode) -> None: if node.isRouter(): self.freeNodes['routers'].append(node.deviceName) elif node.isSwitch(): self.freeNodes['switches'].append(node.deviceName) elif node.isHost(): self.freeNodes['hosts'].append(node.deviceName) else: raise DiagramGraphError( 'Device type ' + node.deviceType.name + ' not recognized for ' + node.deviceName, self)
def addNeighbor(self, nbr: 'DiagramNode') -> None: tc.inputTypeCheck(nbr, 'nbr', DiagramNode) if self.isHost() and len(self.neighbors) == 1: raise DiagramGraphError( 'Device type HOST cannot have second neighbor ' + nbr.deviceName, self) if nbr.isHost() and len(nbr.neighbors) == 1: raise DiagramGraphError( 'Device type HOST cannot have second neighbor ' + self.deviceName, self) if self.isHost() and not nbr.isSwitch(): raise DiagramGraphError( 'Device type HOST cannot be neighbors with ' + nbr.deviceType.name, self) if nbr.isHost() and not self.isSwitch(): raise DiagramGraphError( 'Device type ' + self.deviceType.name + ' cannot be neighbors with HOST', self) if self.isRouter() and not nbr.isSwitch() and not nbr.isRouter(): raise DiagramGraphError( 'Device type ROUTER cannot be neighbors with ' + nbr.deviceType.name, self) if not self.isSwitch() and not self.isRouter() and nbr.isRouter(): raise DiagramGraphError( 'Device type ' + self.deviceType.name + ' cannot be neighbors with ROUTER', self) self.__addNeighbor(nbr)
def __init__(self, device: Name): tc.inputTypeCheck(device, 'device', str) self.deviceName: Name = device self.neighbors: Set[DiagramNode] = set() if device.startswith('r'): self.deviceType: DeviceType = DeviceType.ROUTER elif device.startswith('s'): self.deviceType: DeviceType = DeviceType.SWITCH elif device.startswith('h'): self.deviceType: DeviceType = DeviceType.HOST else: errorMsg = 'Device name "' + self.deviceName + '" cannot be mapped to a device type' raise DiagramGraphError(errorMsg)
def __getRootNode(self, root: str, routers: List[RouterConfig], switches: List[SwitchConfig], hosts: List[HostConfig]) -> DiagramNode: if root is not None and root in self.devices: print('__INFO___ network was provided root: ' + root) return self.devices[root] else: if len(routers) > 0: print('__INFO___ network selected router as root: ' + routers[0]) return self.devices[routers[0]] elif len(switches) > 0: print( '__WARN___ network has no routers; selected switch as root: ' + switches[0]) return self.devices[switches[0]] elif len(hosts) > 0: print('__WARN___ network has no routers or switches') else: raise DiagramGraphError('network is missing devices')
def findSwitchLinksAndHosts( self, tree: DiagramTree, subnet: DiagramSubnet, switch: DiagramNode ) -> Tuple[DiagramTree, DiagramSubnet, Set[Name]]: """Traverse through switches to build DiagramSubnet""" # add switch tree.visited.add(switch.deviceName) subnet.addSwitch(switch.deviceName) # operate on descendants for neighbor in switch.neighbors: if neighbor.deviceName not in tree.visited: if neighbor.isRouter(): # let the router algorithm find this link pass elif neighbor.isSwitch(): tree.addPrimaryLink(switch.deviceName, neighbor.deviceName) (tree, subnet) = self.findSwitchLinksAndHosts( tree, subnet, neighbor) elif neighbor.isHost(): tree.addPrimaryLink(switch.deviceName, neighbor.deviceName) # mark visited here since there should be nothing to recurse tree.visited.add(neighbor.deviceName) subnet.addHost(neighbor.deviceName) else: raise DiagramGraphError( 'Device type SWITCH cannot be neighbors with ' + neighbor.deviceName, self) else: if not tree.isRedundantLink(neighbor.deviceName, switch.deviceName): tree.addSecondaryLink(switch.deviceName, neighbor.deviceName) return (tree, subnet)