def ncclient_call(task: Task, call: str, fmt: str = "xml", *args, **kwargs) -> Result: """ Task to handle a call of NCClient manager object methods :param call: (str) ncclient manager object method to call :param fmt: (str) result formatter to use - xml (default), raw_xml, json, yaml, pprint, py :param arg: (list) any ``*args`` to use with call method :param kwargs: (dict) any ``**kwargs`` to use with call method """ # run sanity check if not HAS_NCCLIENT: return Result( host=task.host, failed=True, exception="No Ncclient found, is it installed?", ) # initiate parameters failed = False task.name = call # get rendered data if any if "__task__" in task.host.data: kwargs.update(task.host.data["__task__"]) # check if filter formed properly - as per # https://ncclient.readthedocs.io/en/latest/manager.html#filter-params # filter should be a tuple of (type, criteria) if kwargs.get("filter"): if isinstance(kwargs["filter"], list): kwargs["filter"] = tuple(kwargs["filter"]) elif isinstance(kwargs["filter"], str): kwargs["filter"] = tuple( [kwargs.pop("ftype", "subtree"), kwargs["filter"]]) # get Ncclient NETCONF connection object manager = task.host.get_connection(CONNECTION_NAME, task.nornir.config) # add generic RPC operation to Ncclient manager object to support RPC call manager._vendor_operations.update(rpc=GenericRPC) log.debug( "nornir_salt:ncclient_call calling '{}' with args: '{}'; kwargs: '{}'". format(call, args, kwargs)) # check if need to call one of helper function if "_call_{}".format(call) in globals(): result, failed = globals()["_call_{}".format(call)](manager, *args, **kwargs) # call manager object method otherwise else: result = getattr(manager, call)(*args, **kwargs) # format results if hasattr(result, "_root"): if fmt == "xml": result = etree.tostring(result._root, pretty_print=True).decode() elif fmt == "raw_xml": result = etree.tostring(result._root, pretty_print=False).decode() elif fmt == "json" and HAS_XMLTODICT: parsed_data = xmltodict.parse(etree.tostring(result._root)) result = json.dumps(parsed_data, sort_keys=True, indent=4) elif fmt == "yaml" and HAS_XMLTODICT and HAS_YAML: parsed_data = xmltodict.parse(etree.tostring(result._root)) result = yaml.dump(parsed_data, default_flow_style=False) elif fmt == "pprint" and HAS_XMLTODICT: parsed_data = xmltodict.parse(etree.tostring(result._root)) result = pprint.pformat(parsed_data, indent=4) elif fmt == "py" and HAS_XMLTODICT: result = xmltodict.parse(etree.tostring(result._root)) else: result = etree.tostring(result._root, pretty_print=True).decode() elif isinstance(result, (list, dict, bool)): pass else: result = str(result) return Result(host=task.host, result=result, failed=failed)
def scrapli_netconf_call(task: Task, call: str, fmt: str = "xml", *args, **kwargs) -> Result: """ Discpatcher function to call one of the supported scrapli_netconf methods or one of helper functions. :param call: (str) Scrapli Netconf connection object method to call :param fmt: (str) result formatter to use - xml (default), raw_xml, json, yaml, pprint, py :param arg: (list) any ``*args`` to use with call method :param kwargs: (dict) any ``**kwargs`` to use with call method """ # initiate local parameteres result = None failed = False task.name = call # get rendered data if any if "__task__" in task.host.data: kwargs.update(task.host.data["__task__"]) log.debug( "nornir_salt:scrapli_netconf_call calling '{}' with args: '{}'; kwargs: '{}'" .format(call, args, kwargs)) # get scrapli-netconf connection object conn = task.host.get_connection("scrapli_netconf", task.nornir.config) # check if need to call one of helper function if "_call_{}".format(call) in globals(): result, failed = globals()["_call_{}".format(call)](conn, *args, **kwargs) # call conn object method otherwise else: result = getattr(conn, call)(*args, **kwargs) # format results if hasattr(result, "result"): if fmt == "xml": result = result.result elif fmt == "raw_xml": result = result.result elif fmt == "json" and HAS_XMLTODICT: parsed_data = xmltodict.parse(result.result) result = json.dumps(parsed_data, sort_keys=True, indent=4) elif fmt == "yaml" and HAS_XMLTODICT and HAS_YAML: parsed_data = xmltodict.parse(result.result) result = yaml.dump(parsed_data, default_flow_style=False) elif fmt == "pprint" and HAS_XMLTODICT: parsed_data = xmltodict.parse(result.result) result = pprint.pformat(parsed_data, indent=4) elif fmt == "py" and HAS_XMLTODICT: result = xmltodict.parse(result.result) else: result = etree.tostring(result._root, pretty_print=True).decode() elif isinstance(result, (list, dict, bool)): pass else: result = str(result) return Result(host=task.host, result=result, failed=failed)