From fd8b367d52aa6bc2cbb45b5f151766643f5082ac Mon Sep 17 00:00:00 2001 From: fluzzi Date: Wed, 30 Mar 2022 19:51:54 -0300 Subject: [PATCH] adding threading nodes automation --- README.md | 26 ++++++++++++++++++- conn/__init__.py | 4 +-- conn/core.py | 66 +++++++++++++++++++++++++++++++++++++++++++++--- setup.py | 2 +- 4 files changed, 91 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9782bb2..755f2f2 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,32 @@ device = conf.getitem("router@office") router = conn.node("unique name", **device, config=conf) result = router.run("show ip int brief") print(result) -router.interact() ``` +### Running parallel tasks on multiple devices +``` +import conn +conf = conn.configfile() +#You can get the nodes from the config from a folder and fitlering in it +nodes = conf.getitem("@office", ["router1", "router2", "router3"]) +#You can also get each node individually: +nodes = {} +nodes["router1"] = conf.getitem("router1@office") +nodes["router2"] = conf.getitem("router2@office") +nodes["router10"] = conf.getitem("router10@datacenter") +#Also, you can create the nodes manually: +nodes = {} +nodes["router1"] = {"host": "1.1.1.1", "user": "username", "password": "password1"} +nodes["router2"] = {"host": "1.1.1.2", "user": "username", "password": "password2"} +nodes["router3"] = {"host": "1.1.1.2", "user": "username", "password": "password3"} +#Finally you run some tasks on the nodes +mynodes = conn.nodes(nodes, config = conf) +result = mynodes.test(["show ip int br"], "1.1.1.2") +for i in result: + print("---" + i + "---") + print(result[i]) + print() +``` + ## Connection manager usage ``` usage: conn [-h] [--add | --del | --mod | --show | --debug] [node|folder] diff --git a/conn/__init__.py b/conn/__init__.py index 18974cc..21c45d2 100644 --- a/conn/__init__.py +++ b/conn/__init__.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -from .core import node +from .core import node,nodes from .configfile import configfile from .connapp import connapp __version__ = "2.0" -__all__ = ["node", "configfile", "connapp"] +__all__ = ["node", "nodes", "configfile", "connapp"] diff --git a/conn/core.py b/conn/core.py index c41c123..455fa49 100755 --- a/conn/core.py +++ b/conn/core.py @@ -9,6 +9,7 @@ import ast from time import sleep import datetime import sys +import threading #functions and classes @@ -186,14 +187,14 @@ class node: match results: case 0: self.child.close() - self.test = True + self.result = True output = output + self.child.before.decode() + self.child.after.decode() output = output.lstrip() self.output = output return True case 1 | 2: self.child.close() - self.test = False + self.result = False if results == 1: output = output + self.child.before.decode() + self.child.after.decode() elif results == 2: @@ -202,7 +203,7 @@ class node: self.output = output return False else: - self.test = None + self.result = None self.output = connect return connect @@ -284,5 +285,64 @@ class node: self.child = child return True +class nodes: + def __init__(self, nodes: dict, config = ''): + self.nodelist = [] + self.config = config + for n in nodes: + self.nodelist.append(node(n, **nodes[n], config = config)) + + def splitlist(self, lst, n): + for i in range(0, len(lst), n): + yield lst[i:i + n] + + + def run(self, commands,*, folder = None, prompt = None, stdout = None, parallel = 10): + args = {} + args["commands"] = commands + if folder != None: + args["folder"] = folder + if prompt != None: + args["prompt"] = prompt + if stdout != None: + args["stdout"] = stdout + output = {} + tasks = [] + for n in self.nodelist: + tasks.append(threading.Thread(target=n.run, kwargs=args)) + taskslist = list(self.splitlist(tasks, parallel)) + for t in taskslist: + for i in t: + i.start() + for i in t: + i.join() + for i in self.nodelist: + output[i.id] = i.output + self.output = output + return output + + def test(self, commands, expected, *, prompt = None, parallel = 10): + args = {} + args["commands"] = commands + args["expected"] = expected + if prompt != None: + args["prompt"] = prompt + output = {} + result = {} + tasks = [] + for n in self.nodelist: + tasks.append(threading.Thread(target=n.test, kwargs=args)) + taskslist = list(self.splitlist(tasks, parallel)) + for t in taskslist: + for i in t: + i.start() + for i in t: + i.join() + for i in self.nodelist: + result[i.id] = i.result + output[i.id] = i.output + self.output = output + self.result = result + return result # script diff --git a/setup.py b/setup.py index 149d3fc..8c33a8c 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup, find_packages import pathlib -VERSION = '2.0.6' +VERSION = '2.0.7' DESCRIPTION = 'Conn is a SSH/Telnet connection manager and automation module' here = pathlib.Path(__file__).parent.resolve()