def __init__( self, transport: Union[AsyncTransport, Transport], base_channel_args: BaseChannelArgs, ): """ BaseChannel Object -- provides convenience methods to both sync and async Channels Args: transport: initialized scrapli Transport/AsyncTransport object base_channel_args: BaseChannelArgs object Returns: None Raises: N/A """ self.transport = transport self._base_channel_args = base_channel_args self.logger = get_instance_logger( instance_name="scrapli.channel", host=self.transport._base_transport_args.host, port=self.transport._base_transport_args.port, uid=self.transport._base_transport_args.logging_uid, ) self.channel_log: Optional[BinaryIO] = None self._auth_telnet_login_pattern = r"^(.*username:)|(.*login:)\s?$" self._auth_password_pattern = r"(.*@.*)?password:\s?$" self._auth_passphrase_pattern = r"enter passphrase for key"
def __init__(self, host: str, port: int, timeout: float): """ Socket object Args: host: host to connect to port: port to connect to timeout: timeout in seconds Returns: None Raises: N/A """ self.logger = get_instance_logger(instance_name="scrapli.socket", host=host, port=port) self.host = host self.port = port self.timeout = timeout self.sock: Optional[socket.socket] = None
def __init__( self, transport: Union[AsyncTransport, Transport], base_channel_args: BaseChannelArgs, ): """ BaseChannel Object -- provides convenience methods to both sync and async Channels Args: transport: initialized scrapli Transport/AsyncTransport object base_channel_args: BaseChannelArgs object Returns: None Raises: N/A """ self.transport = transport self._base_channel_args = base_channel_args self.logger = get_instance_logger( instance_name="scrapli.channel", host=self.transport._base_transport_args.host, port=self.transport._base_transport_args.port, uid=self.transport._base_transport_args.logging_uid, ) self.channel_log: Optional[BinaryIO] = None
def __init__(self, config_sources: List[str], ignore_version: bool = False) -> None: """ Base class for all CFG platforms Args: config_sources: list of allowed config sources ignore_version: ignore platform version check or not Returns: None Raises: N/A """ self.logger = get_instance_logger(instance_name="scrapli_cfg.platform", host=self.conn.host, port=self.conn.port) self.config_sources = config_sources self.candidate_config = "" self.ignore_version = ignore_version self._get_version_command = "" self._version_string = "" # bool indicated if a `on_prepare` callable has been executed or not self._prepared = False
def __init__(self, base_transport_args: BaseTransportArgs) -> None: self._base_transport_args = base_transport_args self.logger = get_instance_logger( instance_name="scrapli.transport", host=self._base_transport_args.host, port=self._base_transport_args.port, uid=self._base_transport_args.logging_uid, )
def __init__( self, transport: Union[AsyncTransport, Transport], base_channel_args: BaseChannelArgs, ): """ BaseChannel Object -- provides convenience methods to both sync and async Channels Args: transport: initialized scrapli Transport/AsyncTransport object base_channel_args: BaseChannelArgs object Returns: None Raises: N/A """ self.transport = transport self._base_channel_args = base_channel_args self.logger = get_instance_logger( instance_name="scrapli.channel", host=self.transport._base_transport_args.host, port=self.transport._base_transport_args.port, uid=self.transport._base_transport_args.logging_uid, ) self.channel_log: Optional[BinaryIO] = None if self._base_channel_args.channel_log: if isinstance(self._base_channel_args.channel_log, BytesIO): self.channel_log = self._base_channel_args.channel_log else: channel_log_destination = "scrapli_channel.log" if isinstance(self._base_channel_args.channel_log, str): channel_log_destination = self._base_channel_args.channel_log self.logger.info( f"channel log enabled, logging channel output to '{channel_log_destination}'" ) self.channel_log = open(channel_log_destination, "wb")
def __init__(self, base_transport_args: BaseTransportArgs) -> None: """ Scrapli's transport base class Args: base_transport_args: base transport args dataclass Returns: None Raises: N/A """ self._base_transport_args = base_transport_args self.logger = get_instance_logger( instance_name="scrapli.transport", host=self._base_transport_args.host, port=self._base_transport_args.port, uid=self._base_transport_args.logging_uid, )
def __init__( self, host: str, port: int = 22, auth_username: str = "", auth_password: str = "", auth_private_key: str = "", auth_private_key_passphrase: str = "", auth_strict_key: bool = True, auth_bypass: bool = False, timeout_socket: float = 15.0, timeout_transport: float = 30.0, timeout_ops: float = 30.0, comms_prompt_pattern: str = r"^[a-z0-9.\-@()/:]{1,48}[#>$]\s*$", comms_return_char: str = "\n", comms_ansi: bool = False, ssh_config_file: Union[str, bool] = False, ssh_known_hosts_file: Union[str, bool] = False, on_init: Optional[Callable[..., Any]] = None, on_open: Optional[Callable[..., Any]] = None, on_close: Optional[Callable[..., Any]] = None, transport: str = "system", transport_options: Optional[Dict[str, Any]] = None, channel_log: Union[str, bool, BytesIO] = False, channel_lock: bool = False, logging_uid: str = "", ) -> None: r""" BaseDriver Object BaseDriver is the root for all Scrapli driver classes. The synchronous and asyncio driver base driver classes can be used to provide a semi-pexpect like experience over top of whatever transport a user prefers. Generally, however, the base driver classes should not be used directly. It is best to use the GenericDriver (or AsyncGenericDriver) or NetworkDriver (or AsyncNetworkDriver) sub-classes of the base drivers. Args: host: host ip/name to connect to port: port to connect to auth_username: username for authentication auth_private_key: path to private key for authentication auth_private_key_passphrase: passphrase for decrypting ssh key if necessary auth_password: password for authentication auth_strict_key: strict host checking or not auth_bypass: bypass "in channel" authentication -- only supported with telnet, asynctelnet, and system transport plugins timeout_socket: timeout for establishing socket/initial connection in seconds timeout_transport: timeout for ssh|telnet transport in seconds timeout_ops: timeout for ssh channel operations comms_prompt_pattern: raw string regex pattern -- preferably use `^` and `$` anchors! this is the single most important attribute here! if this does not match a prompt, scrapli will not work! IMPORTANT: regex search uses multi-line + case insensitive flags. multi-line allows for highly reliably matching for prompts however we do NOT strip trailing whitespace for each line, so be sure to add '\\s?' or similar if your device needs that. This should be mostly sorted for you if using network drivers (i.e. `IOSXEDriver`). Lastly, the case insensitive is just a convenience factor so i can be lazy. comms_return_char: character to use to send returns to host comms_ansi: True/False strip comms_ansi characters from output, generally the default value of False should be fine ssh_config_file: string to path for ssh config file, True to use default ssh config file or False to ignore default ssh config file ssh_known_hosts_file: string to path for ssh known hosts file, True to use default known file locations. Only applicable/needed if `auth_strict_key` is set to True on_init: callable that accepts the class instance as its only argument. this callable, if provided, is executed as the last step of object instantiation -- its purpose is primarily to provide a mechanism for scrapli community platforms to have an easy way to modify initialization arguments/object attributes without needing to create a class that extends the driver, instead allowing the community platforms to simply build from the GenericDriver or NetworkDriver classes, and pass this callable to do things such as appending to a username (looking at you RouterOS!!). Note that this is *always* a synchronous function (even for asyncio drivers)! on_open: callable that accepts the class instance as its only argument. this callable, if provided, is executed immediately after authentication is completed. Common use cases for this callable would be to disable paging or accept any kind of banner message that prompts a user upon connection on_close: callable that accepts the class instance as its only argument. this callable, if provided, is executed immediately prior to closing the underlying transport. Common use cases for this callable would be to save configurations prior to exiting, or to logout properly to free up vtys or similar transport: name of the transport plugin to use for the actual telnet/ssh/netconf connection. Available "core" transports are: - system - telnet - asynctelnet - ssh2 - paramiko - asyncssh Please see relevant transport plugin section for details. Additionally third party transport plugins may be available. transport_options: dictionary of options to pass to selected transport class; see docs for given transport class for details of what to pass here channel_lock: True/False to lock the channel (threading.Lock/asyncio.Lock) during any channel operations, defaults to False channel_log: True/False or a string path to a file of where to write out channel logs -- these are not "logs" in the normal logging module sense, but only the output that is read from the channel. In other words, the output of the channel log should look similar to what you would see as a human connecting to a device logging_uid: unique identifier (string) to associate to log messages; useful if you have multiple connections to the same device (i.e. one console, one ssh, or one to each supervisor module, etc.) Returns: None Raises: N/A """ self.logger = get_instance_logger( instance_name="scrapli.driver", host=host, port=port, uid=logging_uid ) self._base_channel_args = BaseChannelArgs( comms_prompt_pattern=comms_prompt_pattern, comms_return_char=comms_return_char, comms_ansi=comms_ansi, timeout_ops=timeout_ops, channel_log=channel_log, channel_lock=channel_lock, ) # transport options is unused in most transport plugins, but when used will be a dict of # user provided arguments, defaults to None to not be mutable argument, so if its still # None at this point turn it into an empty dict to pass into the transports transport_options = transport_options or {} self._base_transport_args = BaseTransportArgs( transport_options=transport_options, host=host, port=port, timeout_socket=timeout_socket, timeout_transport=timeout_transport, logging_uid=logging_uid, ) self.host, self.port = self._setup_host(host=host, port=port) self.auth_username = auth_username self.auth_password = auth_password self.auth_private_key_passphrase = auth_private_key_passphrase self.auth_private_key, self.auth_strict_key, self.auth_bypass = self._setup_auth( auth_private_key=auth_private_key, auth_strict_key=auth_strict_key, auth_bypass=auth_bypass, ) self.ssh_config_file, self.ssh_known_hosts_file = self._setup_ssh_file_args( transport=transport, ssh_config_file=ssh_config_file, ssh_known_hosts_file=ssh_known_hosts_file, ) self._setup_callables(on_init=on_init, on_open=on_open, on_close=on_close) self.transport_name = transport if self.transport_name in ("asyncssh", "ssh2", "paramiko"): # for mostly(?) historical reasons these transports use the `ssh_config` module to get # port/username/key file. asyncssh may not need this at all anymore as asyncssh core # has added ssh config file support since scrapli's inception self._update_ssh_args_from_ssh_config() transport_class, self._plugin_transport_args = self._transport_factory() self.transport = transport_class( base_transport_args=self._base_transport_args, plugin_transport_args=self._plugin_transport_args, ) if self.on_init: self.on_init(self)