コード例 #1
0
def send_command(
    task: Task,
    command: str,
    strip_prompt: bool = True,
    failed_when_contains: Optional[Union[str, List[str]]] = None,
) -> Result:
    """
    Send a single command to device using scrapli

    Args:
        task: nornir task object
        command: string to send to device in privilege exec mode
        strip_prompt: True/False strip prompt from returned output
        failed_when_contains: string or list of strings indicating failure if found in response

    Returns:
        Result: scrapli nornir result object; almost identical to a "normal" nornir result object,
            but contains an additional attribute "scrapli_response" that contains the original
            response from scrapli

    Raises:
        N/A

    """
    scrapli_conn = task.host.get_connection("scrapli", task.nornir.config)
    scrapli_response = scrapli_conn.send_command(
        command=command,
        strip_prompt=strip_prompt,
        failed_when_contains=failed_when_contains)

    result = ScrapliResult(
        host=task.host,
        result=process_command_result(scrapli_response=scrapli_response),
        scrapli_response=scrapli_response,
        changed=False,
    )
    return result
コード例 #2
0
def netconf_get_config(
    task: Task,
    source: str = "running",
    filters: Optional[Union[str, List[str]]] = None,
    filter_type: str = "subtree",
) -> Result:
    """
    Get config from the device with scrapli_netconf

    Args:
        task: nornir task object
        source: configuration source to get; typically one of running|startup|candidate
        filters: string or list of strings of filters to apply to configuration
        filter_type: type of filter; subtree|xpath

    Returns:
        Result: nornir result object with Result.result value set the string result of the
            get_config operation

    Raises:
        N/A

    """
    scrapli_conn = task.host.get_connection("scrapli_netconf",
                                            task.nornir.config)
    scrapli_response = scrapli_conn.get_config(source=source,
                                               filters=filters,
                                               filter_type=filter_type)

    result = ScrapliResult(
        host=task.host,
        result=process_command_result(scrapli_response=scrapli_response),
        scrapli_response=scrapli_response,
        changed=False,
    )
    return result
コード例 #3
0
def send_configs_from_file(
    task: Task,
    file: str,
    dry_run: bool = False,
    strip_prompt: bool = True,
    failed_when_contains: Optional[Union[str, List[str]]] = None,
    stop_on_failed: bool = False,
    privilege_level: str = "",
) -> Result:
    """
    Send configs from a file to device using scrapli

    Args:
        task: nornir task object
        file: string path to file
        dry_run: Whether to apply changes or not; if dry run, will ensure that it is possible to
            enter config mode, but will NOT send any configs
        strip_prompt: True/False strip prompt from returned output
        failed_when_contains: string or list of strings indicating failure if found in response
        stop_on_failed: True/False stop executing commands if a command fails, returns results as of
            current execution
        privilege_level: name of configuration privilege level/type to acquire; this is platform
            dependent, so check the device driver for specifics. Examples of privilege_name
            would be "configuration_exclusive" for IOSXRDriver, or "configuration_private" for
            JunosDriver. You can also pass in a name of a configuration session such as
            "my-config-session" if you have registered a session using the
            "register_config_session" method of the EOSDriver or NXOSDriver.

    Returns:
        Result: nornir result object with Result.result value set to returned scrapli Response
            object

    Raises:
        NornirScrapliNoConfigModeGenericDriver: If attempting to use this task function against a
            host that is using the "generic" platform type

    """
    if task.host.platform == "generic":
        raise NornirScrapliNoConfigModeGenericDriver(
            "No config mode for 'generic' platform type")

    scrapli_conn = task.host.get_connection("scrapli", task.nornir.config)

    if dry_run:
        # if dry run, try to acquire config mode then back out; do not send any configurations!
        scrapli_conn.acquire_priv("configuration")
        scrapli_conn.acquire_priv(scrapli_conn.default_desired_privilege_level)
        return ScrapliResult(host=task.host,
                             result=None,
                             scrapli_response=None,
                             changed=False)

    scrapli_response = scrapli_conn.send_configs_from_file(
        file=file,
        strip_prompt=strip_prompt,
        failed_when_contains=failed_when_contains,
        stop_on_failed=stop_on_failed,
        privilege_level=privilege_level,
    )

    result = ScrapliResult(
        host=task.host,
        result=process_config_result(scrapli_response=scrapli_response),
        scrapli_response=scrapli_response,
        changed=True,
    )
    return result
コード例 #4
0
def send_config(
    task: Task,
    config: str,
    dry_run: Optional[bool] = None,
    strip_prompt: bool = True,
    failed_when_contains: Optional[Union[str, List[str]]] = None,
    stop_on_failed: bool = False,
    privilege_level: str = "",
    timeout_ops: Optional[float] = None,
) -> Result:
    """
    Send a config to device using scrapli

    Args:
        task: nornir task object
        config: string configuration to send to the device, supports sending multi-line strings
        dry_run: Whether to apply changes or not; if dry run, will ensure that it is possible to
            enter config mode, but will NOT send any configs
        strip_prompt: True/False strip prompt from returned output
        failed_when_contains: string or list of strings indicating failure if found in response
        stop_on_failed: True/False stop executing commands if a command fails, returns results as of
            current execution
        privilege_level: name of configuration privilege level/type to acquire; this is platform
            dependent, so check the device driver for specifics. Examples of privilege_name
            would be "configuration_exclusive" for IOSXRDriver, or "configuration_private" for
            JunosDriver. You can also pass in a name of a configuration session such as
            "my-config-session" if you have registered a session using the
            "register_config_session" method of the EOSDriver or NXOSDriver.
        timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
            the duration of the operation, value is reset to initial value after operation is
            completed. Note that this is the timeout value PER CONFIG sent, not for the total
            of the configs being sent!

    Returns:
        Result: nornir result object with Result.result value set to returned scrapli Response
            object

    Raises:
        NornirScrapliNoConfigModeGenericDriver: If attempting to use this task function against a
            host that is using the "generic" platform type

    """
    if task.host.platform == "generic":
        raise NornirScrapliNoConfigModeGenericDriver(
            "No config mode for 'generic' platform type")

    scrapli_conn = task.host.get_connection("scrapli", task.nornir.config)

    _task_dry_run = dry_run if dry_run is not None else task.global_dry_run

    if _task_dry_run:
        # if dry run, try to acquire config mode then back out; do not send any configurations!
        scrapli_conn.acquire_priv("configuration")
        scrapli_conn.acquire_priv(scrapli_conn.default_desired_privilege_level)
        return ScrapliResult(host=task.host,
                             result=None,
                             scrapli_response=None,
                             changed=False)

    scrapli_response = scrapli_conn.send_config(
        config=config,
        strip_prompt=strip_prompt,
        failed_when_contains=failed_when_contains,
        stop_on_failed=stop_on_failed,
        privilege_level=privilege_level,
        timeout_ops=timeout_ops,
    )

    result = ScrapliResult(
        host=task.host,
        result=process_config_result(scrapli_response=scrapli_response),
        scrapli_response=scrapli_response,
        changed=True,
    )
    return result
コード例 #5
0
ファイル: print_table_result.py プロジェクト: w4h1w2/fastcli
def print_table_result(
    result: ScrapliResult,
    failed: bool = False,
    severity_level: int = logging.INFO,
    parser: str = "textfsm",
    to_dict: bool = True,
    fail_to_string: bool = False,
) -> None:
    """
    Prints the :obj:`nornir.core.task.Result` from a previous task to screen

    Arguments:
        result: from a previous task
        failed: if `True` assume the task failed
        severity_level: Print only errors with this severity level or higher
        parser: textfsm|genie -- parser to parse output with
        to_dict: output structured data in dict form instead --
        basically put k:v instead of just
            lists of lists of values for textfsm output;
            ignored if parser == "genie"
        fail_to_string: fallback to printing unstructured output
        or have tasks skipped (because
            print_result won't print empty lists which scrapli
            returns if parsing fails)

    """
    updated_agg_result = AggregatedResult(result.name)
    # breakpoint()
    console = Console()
    table = Table(
        "Hostname", "Version", "Platform", "Image ID", "Image Type",
        "Uptime", "System Image", "Compiled Date")
    for hostname, multi_result in result.items():
        updated_multi_result = MultiResult(result.name)
        for individual_result in multi_result:
            scrapli_responses = getattr(
                individual_result, "scrapli_response", None)
            if isinstance(scrapli_responses, Response):
                scrapli_responses = [scrapli_responses]
            if not scrapli_responses:
                updated_multi_result.append(individual_result)
                continue
            for scrapli_response in scrapli_responses:
                parser_method = getattr(
                    scrapli_response, f"{parser}_parse_output")
                updated_result = Result(
                    host=individual_result.host,
                    changed=individual_result.changed,
                    diff=individual_result.diff,
                    exception=individual_result.exception,
                    failed=individual_result.failed,
                    name=individual_result.name,
                    severity_level=individual_result.severity_level,
                    stderr=individual_result.stderr,
                    stdout=individual_result.stdout,
                )

                if parser == "textfsm":
                    structured_result = parser_method(to_dict=to_dict)
                else:
                    structured_result = parser_method()

                if not structured_result and fail_to_string:
                    updated_result.result = scrapli_response.result
                else:
                    updated_result.result = structured_result
                updated_multi_result.append(updated_result)
            try:
                version = structured_result['version']
                table.add_row(f'[green]{version["hostname"]}[/green]',
                              f'[blue]{version["version"]}[/blue]',
                              f'[magenta]{version["platform"]}[/magenta]',
                              f'[cyan]{version["image_id"]}[/cyan]',
                              f'[orange1]{version["image_type"]}[/orange1]',
                              f'[bright_green]{version["uptime"]}[/bright_green]',
                              f'[magenta]{version["system_image"]}[/magenta]',
                              f'[yellow]{version["compiled_date"]}[/yellow]')
            except KeyError:
                print("This command is not supported in Table format!")
        if updated_multi_result:
            updated_agg_result[hostname] = updated_multi_result  # noqa

    LOCK.acquire()
    try:
        console.print(table)
    finally:
        LOCK.release()
コード例 #6
0
def print_structured_result(
    result: ScrapliResult,
    failed: bool = False,
    severity_level: int = logging.INFO,
    parser: str = "textfsm",
    to_dict: bool = True,
    fail_to_string: bool = False,
) -> None:
    """
    Prints the :obj:`nornir.core.task.Result` from a previous task to screen

    Arguments:
        result: from a previous task
        failed: if `True` assume the task failed
        severity_level: Print only errors with this severity level or higher
        parser: textfsm|genie -- parser to parse output with
        to_dict: output structured data in dict form instead -- basically put k:v instead of just
            lists of lists of values for textfsm output; ignored if parser == "genie"
        fail_to_string: fallback to printing unstructured output or have tasks skipped (because
            print_result won't print empty lists which scrapli returns if parsing fails)

    """
    updated_agg_result = AggregatedResult(result.name)
    for hostname, multi_result in result.items():
        updated_multi_result = MultiResult(result.name)
        for individual_result in multi_result:
            scrapli_responses = getattr(individual_result, "scrapli_response",
                                        None)
            if isinstance(scrapli_responses, Response):
                scrapli_responses = [scrapli_responses]
            if not scrapli_responses:
                updated_multi_result.append(individual_result)
                continue
            for scrapli_response in scrapli_responses:
                parser_method = getattr(scrapli_response,
                                        f"{parser}_parse_output")
                updated_result = Result(
                    host=individual_result.host,
                    changed=individual_result.changed,
                    diff=individual_result.diff,
                    exception=individual_result.exception,
                    failed=individual_result.failed,
                    name=individual_result.name,
                    severity_level=individual_result.severity_level,
                    stderr=individual_result.stderr,
                    stdout=individual_result.stdout,
                )

                if parser == "textfsm":
                    structured_result = parser_method(to_dict=to_dict)
                else:
                    structured_result = parser_method()

                if not structured_result and fail_to_string:
                    updated_result.result = scrapli_response.result
                else:
                    updated_result.result = structured_result
                updated_multi_result.append(updated_result)
        if updated_multi_result:
            updated_agg_result[hostname] = updated_multi_result  # noqa

    LOCK.acquire()
    try:
        _print_result(result=updated_agg_result,
                      attrs=None,
                      failed=failed,
                      severity_level=severity_level)
    finally:
        LOCK.release()