def InitNornir( config_file: str = "", dry_run: bool = False, **kwargs: Any, ) -> Nornir: """ Arguments: config_file(str): Path to the configuration file (optional) dry_run(bool): Whether to simulate changes or not configure_logging: Whether to configure logging or not. This argument is being deprecated. Please use logging.enabled parameter in the configuration instead. **kwargs: Extra information to pass to the :obj:`nornir.core.configuration.Config` object Returns: :obj:`nornir.core.Nornir`: fully instantiated and configured """ ConnectionPluginRegister.auto_register() if config_file: config = Config.from_file(config_file, **kwargs) else: config = Config.from_dict(**kwargs) data = GlobalState(dry_run=dry_run) config.logging.configure() return Nornir( inventory=load_inventory(config), runner=load_runner(config), config=config, data=data, )
def setup_class(cls): ConnectionPluginRegister.deregister_all() ConnectionPluginRegister.register("dummy", DummyConnectionPlugin) ConnectionPluginRegister.register("dummy2", DummyConnectionPlugin) ConnectionPluginRegister.register("dummy_no_overrides", DummyConnectionPlugin) ConnectionPluginRegister.register(FailedConnectionPlugin.name, FailedConnectionPlugin)
def cli(ctx, pg_bar, print_result, print_stat, *args, **kwargs): ConnectionPluginRegister.auto_register() # 'None' = None kwargs.update({k: v for k, v in zip(kwargs, _json_loads(kwargs.values()))}) current_func_params = next(ctx.obj["queue_functions_generator"]) # try to pass not all arguments, but only the necessary ones if kwargs == list(current_func_params.values())[0]: function, parameters = list(current_func_params.items())[0] else: param_iterator = iter(current_func_params.values()) params = list(next(param_iterator).items()) function, parameters = list(current_func_params)[0], { key: value for key, value in kwargs.items() if (key, value) not in params } # get the current Nornir object from Commands chain or from temp.pkl file try: nr = ctx.obj["nornir"] except KeyError: nr = _pickle_to_hidden_file("temp.pkl", mode="rb", dump=False) nr.config.logging.configure() # pg_bar option if pg_bar: with tqdm( total=len(nr.inventory.hosts), desc="processing: ", ) as pb: result = nr.run( task=multiple_progress_bar, method=function, pg_bar=pb, **parameters, ) print() else: result = nr.run( task=function, **parameters, ) ctx.obj["result"] = result # print_result option if print_result: pr(result) print() # print statistic if print_stat: ps(nr, result)
def default_nr_init(pytester): """Create initial Nornir files and expose the location as nornir_config_file fixture.""" hosts_path = pytester.path / f"hosts{YAML_EXTENSION}" config = f"""inventory: plugin: SimpleInventory options: host_file: {hosts_path}""" arguments = { "nr-config": config, "hosts": """ R1: hostname: 1.1.1.1 R2: hostname: 2.2.2.2 R3: hostname: 3.3.3.3 L1: hostname: 11.11.11.11 L2: hostname: 22.22.22.22 S1: hostname: 111.111.111.111 S2: hostname: 222.222.222.222""", } pytester.makefile(YAML_EXTENSION, **arguments) # We need to have the test tmpdir in sys.path, so NUTS can import the test # modules (e.g. basic_task.py). pytester.syspathinsert() yield # Cleanup Nornir's PluginRegisters. # This is necessary as InitNornir is initiated for every test case, but the # PluginRegisters are (somehow) shared. This results in a # PluginAlreadyRegistered Exception as the plugins are registered multiple # times. ConnectionPluginRegister.deregister_all() InventoryPluginRegister.deregister_all() RunnersPluginRegister.deregister_all()
def _get_trusted_untrusted(task): ConnectionPluginRegister.auto_register() # Get parameters in format: # [ { 'description': 'NNI', # 'mac_address': 'xxxx-yyyy-zzzz', # 'mtu': '', # 'name': 'Ethernet0/0/1'},] intfs = task.run( task=netmiko_send_command, name="interfaces list", command_string="disp int", use_textfsm=True, textfsm_template=os.path.join( os.getcwd(), "nornir_cli/custom_commands/templates/disp_int.template"), ) # Get trusted interfaces task.host["trusted"] = [ i["name"] for i in intfs.result if "NNI" in i["description"] ] # Get untrusted interfaces task.host["untrusted"] = [ i["name"] for i in intfs.result if "NNI" not in i["description"] and not i["mtu"] ] # Render j2 template template = task.run( task=template_file, path="nornir_cli/custom_commands/templates", template="dhcp_snooping.j2", ) # Configure commands from j2 template task.host["template"] = template.result task.run( task=netmiko_send_config, name="Configure dhcp snooping", config_commands=template.result, cmd_verify=False, exit_config_mode=False, )
def open_connection( self, connection: str, configuration: Config, hostname: Optional[str] = None, username: Optional[str] = None, password: Optional[str] = None, port: Optional[int] = None, platform: Optional[str] = None, extras: Optional[Dict[str, Any]] = None, default_to_host_attributes: bool = True, ) -> ConnectionPlugin: """ Open a new connection. If ``default_to_host_attributes`` is set to ``True`` arguments will default to host attributes if not specified. Raises: AttributeError: if it's unknown how to establish a connection for the given type Returns: An already established connection """ conn_name = connection existing_conn = self.connections.get(conn_name) if existing_conn is not None: raise ConnectionAlreadyOpen(conn_name) plugin = ConnectionPluginRegister.get_plugin(conn_name) conn_obj = plugin() if default_to_host_attributes: conn_params = self.get_connection_parameters(conn_name) hostname = hostname if hostname is not None else conn_params.hostname username = username if username is not None else conn_params.username password = password if password is not None else conn_params.password port = port if port is not None else conn_params.port platform = platform if platform is not None else conn_params.platform extras = extras if extras is not None else conn_params.extras conn_obj.open( hostname=hostname, username=username, password=password, port=port, platform=platform, extras=extras, configuration=configuration, ) self.connections[conn_name] = conn_obj return conn_obj
def test_register_already_registered_same(self): ConnectionPluginRegister.register("dummy", DummyConnectionPlugin) assert ConnectionPluginRegister.available[ "dummy"] == DummyConnectionPlugin
19 Dec 2020 Ported to nornir 3 by paketb0te """ # Imports from rich import print as rprint from nornir import InitNornir from nornir.core.task import Task from nornir.core.plugins.connections import ConnectionPluginRegister from nornir_netmiko.tasks import netmiko_send_command from netaddr import EUI # Register Plugins ConnectionPluginRegister.register("connection-name", netmiko_send_command) def get_interface_info(task: Task, target: EUI) -> None: """ Get MAC addresses of all interfaces and compare to target. If present, identify Device and Interface """ interfaces = task.run(task=netmiko_send_command, command_string="show interfaces", use_genie=True).result for intf in interfaces: mac_addr = EUI(interfaces[intf]["mac_address"]) if target == mac_addr: print_info(task, intf, target)
from nornir_pyez.plugins.tasks import pyez_get_config import os from nornir import InitNornir from nornir_utils.plugins.functions import print_result from rich import print from nornir.core.plugins.connections import ConnectionPluginRegister from nornir_pyez.plugins.connections import Pyez ConnectionPluginRegister.register("pyez", Pyez) script_dir = os.path.dirname(os.path.realpath(__file__)) nr = InitNornir(config_file=f"{script_dir}/config.yml") # xpath = 'interfaces/interface' # xml = '<interfaces></interfaces>' # database = 'committed' response = nr.run(task=pyez_get_config) # response is an AggregatedResult, which behaves like a list # there is a response object for each device in inventory devices = [] for dev in response: print(response[dev].result)
def test_nonexistent_plugin(self): with pytest.raises(PluginNotRegistered): ConnectionPluginRegister.get_plugin("nonexistent_dummy")
def test_get_plugin(self): assert ConnectionPluginRegister.get_plugin( "dummy") == DummyConnectionPlugin assert (ConnectionPluginRegister.get_plugin("another_dummy") == AnotherDummyConnectionPlugin) assert len(ConnectionPluginRegister.available) == 2
def test_deregister_all(self): ConnectionPluginRegister.deregister_all() assert ConnectionPluginRegister.available == {}
def test_deregister_nonexistent(self): with pytest.raises(PluginNotRegistered): ConnectionPluginRegister.deregister("nonexistent_dummy")
def test_deregister_existing(self): ConnectionPluginRegister.deregister("dummy") assert len(ConnectionPluginRegister.available) == 1 assert "dummy" not in ConnectionPluginRegister.available
def test_register_already_registered_new(self): with pytest.raises(PluginAlreadyRegistered): ConnectionPluginRegister.register("dummy", AnotherDummyConnectionPlugin)
def test_register_new(self): ConnectionPluginRegister.register("new_dummy", DummyConnectionPlugin) assert "new_dummy" in ConnectionPluginRegister.available
def teardown_method(self, method): ConnectionPluginRegister.deregister_all() ConnectionPluginRegister.auto_register()
def setup_method(self, method): ConnectionPluginRegister.deregister_all() ConnectionPluginRegister.register("dummy", DummyConnectionPlugin) ConnectionPluginRegister.register("another_dummy", AnotherDummyConnectionPlugin)
def cli(ctx, pg_bar, show_result, *args, **kwargs): ConnectionPluginRegister.auto_register() # 'None' = None kwargs.update({k: v for k, v in zip(kwargs, _json_loads(kwargs.values()))}) current_func_params = next(ctx.obj["queue_functions_generator"]) # try to pass not all arguments, but only the necessary ones if kwargs == list(current_func_params.values())[0]: function, parameters = list(current_func_params.items())[0] else: param_iterator = iter(current_func_params.values()) params = list(next(param_iterator).items()) function, parameters = list(current_func_params)[0], { key: value for key, value in kwargs.items() if (key, value) not in params } # get the current Nornir object from Commands chain or from temp.pkl file try: nr = ctx.obj["nornir"] except KeyError: nr = _pickle_to_hidden_file("temp.pkl", mode="rb", dump=False) nr.config.logging.configure() # pg_bar option if pg_bar: with tqdm( total=len(nr.inventory.hosts), desc="processing: ", ) as pb: task = nr.run( task=multiple_progress_bar, method=function, pg_bar=pb, **parameters, ) print() else: task = nr.run( task=function, **parameters, ) # show_result option if show_result: print_result(task, severity_level=logging.DEBUG) print() # show statistic ch_sum = 0 for host in nr.inventory.hosts: f, ch = (task[host].failed, task[host].changed) ch_sum += int(ch) click.secho( f"{host:<50}: ok={not f:<15} changed={ch:<15} failed={f:<15}", fg=_get_color(f, ch), bold=True, ) print() f_sum = len(nr.data.failed_hosts) ok_sum = len(nr.inventory.hosts) - f_sum for state, summary, color in zip(("OK", "CHANGED", "FAILED"), (ok_sum, ch_sum, f_sum), ("green", "yellow", "red")): click.secho( f"{state:<8}: {summary}", fg=color, bold=True, ) print()