scrapli 2023.7.30__py3-none-any.whl → 2024.7.30__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scrapli/__init__.py +2 -1
- scrapli/channel/__init__.py +1 -0
- scrapli/channel/async_channel.py +35 -12
- scrapli/channel/base_channel.py +25 -3
- scrapli/channel/sync_channel.py +35 -12
- scrapli/decorators.py +1 -0
- scrapli/driver/__init__.py +1 -0
- scrapli/driver/base/__init__.py +1 -0
- scrapli/driver/base/async_driver.py +19 -13
- scrapli/driver/base/base_driver.py +121 -37
- scrapli/driver/base/sync_driver.py +19 -13
- scrapli/driver/core/__init__.py +1 -0
- scrapli/driver/core/arista_eos/__init__.py +1 -0
- scrapli/driver/core/arista_eos/async_driver.py +3 -0
- scrapli/driver/core/arista_eos/base_driver.py +3 -2
- scrapli/driver/core/arista_eos/sync_driver.py +3 -0
- scrapli/driver/core/cisco_iosxe/__init__.py +1 -0
- scrapli/driver/core/cisco_iosxe/async_driver.py +3 -0
- scrapli/driver/core/cisco_iosxe/base_driver.py +1 -0
- scrapli/driver/core/cisco_iosxe/sync_driver.py +3 -0
- scrapli/driver/core/cisco_iosxr/__init__.py +1 -0
- scrapli/driver/core/cisco_iosxr/async_driver.py +3 -0
- scrapli/driver/core/cisco_iosxr/base_driver.py +1 -0
- scrapli/driver/core/cisco_iosxr/sync_driver.py +3 -0
- scrapli/driver/core/cisco_nxos/__init__.py +1 -0
- scrapli/driver/core/cisco_nxos/async_driver.py +3 -0
- scrapli/driver/core/cisco_nxos/base_driver.py +9 -4
- scrapli/driver/core/cisco_nxos/sync_driver.py +3 -0
- scrapli/driver/core/juniper_junos/__init__.py +1 -0
- scrapli/driver/core/juniper_junos/async_driver.py +3 -0
- scrapli/driver/core/juniper_junos/base_driver.py +1 -0
- scrapli/driver/core/juniper_junos/sync_driver.py +3 -0
- scrapli/driver/generic/__init__.py +1 -0
- scrapli/driver/generic/async_driver.py +45 -3
- scrapli/driver/generic/base_driver.py +2 -1
- scrapli/driver/generic/sync_driver.py +45 -3
- scrapli/driver/network/__init__.py +1 -0
- scrapli/driver/network/async_driver.py +27 -0
- scrapli/driver/network/base_driver.py +1 -0
- scrapli/driver/network/sync_driver.py +27 -0
- scrapli/exceptions.py +1 -0
- scrapli/factory.py +22 -3
- scrapli/helper.py +76 -4
- scrapli/logging.py +1 -0
- scrapli/response.py +1 -0
- scrapli/ssh_config.py +1 -0
- scrapli/transport/base/__init__.py +1 -0
- scrapli/transport/base/async_transport.py +1 -0
- scrapli/transport/base/base_socket.py +1 -0
- scrapli/transport/base/base_transport.py +1 -0
- scrapli/transport/base/sync_transport.py +1 -0
- scrapli/transport/plugins/asyncssh/transport.py +4 -0
- scrapli/transport/plugins/asynctelnet/transport.py +13 -6
- scrapli/transport/plugins/paramiko/transport.py +1 -0
- scrapli/transport/plugins/ssh2/transport.py +6 -3
- scrapli/transport/plugins/system/ptyprocess.py +50 -13
- scrapli/transport/plugins/system/transport.py +27 -6
- scrapli/transport/plugins/telnet/transport.py +13 -7
- {scrapli-2023.7.30.dist-info → scrapli-2024.7.30.dist-info}/METADATA +74 -47
- scrapli-2024.7.30.dist-info/RECORD +74 -0
- {scrapli-2023.7.30.dist-info → scrapli-2024.7.30.dist-info}/WHEEL +1 -1
- scrapli-2023.7.30.dist-info/RECORD +0 -74
- {scrapli-2023.7.30.dist-info → scrapli-2024.7.30.dist-info}/LICENSE +0 -0
- {scrapli-2023.7.30.dist-info → scrapli-2024.7.30.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,12 @@
|
|
1
1
|
"""scrapli.driver.base.sync_driver"""
|
2
|
+
|
2
3
|
from types import TracebackType
|
3
4
|
from typing import Any, Optional, Type, TypeVar
|
4
5
|
|
5
6
|
from scrapli.channel import Channel
|
6
7
|
from scrapli.driver.base.base_driver import BaseDriver
|
7
|
-
from scrapli.exceptions import ScrapliValueError
|
8
|
-
from scrapli.transport import ASYNCIO_TRANSPORTS
|
8
|
+
from scrapli.exceptions import ScrapliConnectionError, ScrapliValueError
|
9
|
+
from scrapli.transport import ASYNCIO_TRANSPORTS, CORE_TRANSPORTS
|
9
10
|
|
10
11
|
_T = TypeVar("_T", bound="Driver")
|
11
12
|
|
@@ -14,7 +15,7 @@ class Driver(BaseDriver):
|
|
14
15
|
def __init__(self, **kwargs: Any):
|
15
16
|
super().__init__(**kwargs)
|
16
17
|
|
17
|
-
if self.transport_name in ASYNCIO_TRANSPORTS:
|
18
|
+
if self.transport_name in CORE_TRANSPORTS and self.transport_name in ASYNCIO_TRANSPORTS:
|
18
19
|
raise ScrapliValueError(
|
19
20
|
"provided transport is *not* an sync transport, must use an sync transport with"
|
20
21
|
" the (sync)Driver(s)"
|
@@ -41,10 +42,22 @@ class Driver(BaseDriver):
|
|
41
42
|
_T: a concrete implementation of the opened Driver object
|
42
43
|
|
43
44
|
Raises:
|
44
|
-
|
45
|
+
ScrapliConnectionError: if an exception occurs during opening
|
45
46
|
|
46
47
|
"""
|
47
|
-
|
48
|
+
try:
|
49
|
+
self.open()
|
50
|
+
except Exception as exc:
|
51
|
+
self.logger.critical(
|
52
|
+
"encountered exception during open in context manager, "
|
53
|
+
"attempting to close transport and channel"
|
54
|
+
)
|
55
|
+
|
56
|
+
self.transport.close()
|
57
|
+
self.channel.close()
|
58
|
+
|
59
|
+
raise ScrapliConnectionError(exc) from exc
|
60
|
+
|
48
61
|
return self
|
49
62
|
|
50
63
|
def __exit__(
|
@@ -94,14 +107,7 @@ class Driver(BaseDriver):
|
|
94
107
|
auth_password=self.auth_password,
|
95
108
|
auth_private_key_passphrase=self.auth_private_key_passphrase,
|
96
109
|
)
|
97
|
-
if
|
98
|
-
self.transport_name
|
99
|
-
in (
|
100
|
-
"telnet",
|
101
|
-
"asynctelnet",
|
102
|
-
)
|
103
|
-
and not self.auth_bypass
|
104
|
-
):
|
110
|
+
if "telnet" in self.transport_name and not self.auth_bypass:
|
105
111
|
self.channel.channel_authenticate_telnet(
|
106
112
|
auth_username=self.auth_username, auth_password=self.auth_password
|
107
113
|
)
|
scrapli/driver/core/__init__.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.arista_eos.async_driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -66,6 +67,7 @@ class AsyncEOSDriver(AsyncNetworkDriver, EOSDriverBase):
|
|
66
67
|
timeout_transport: float = 30.0,
|
67
68
|
timeout_ops: float = 30.0,
|
68
69
|
comms_return_char: str = "\n",
|
70
|
+
comms_roughly_match_inputs: bool = False,
|
69
71
|
ssh_config_file: Union[str, bool] = False,
|
70
72
|
ssh_known_hosts_file: Union[str, bool] = False,
|
71
73
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -146,6 +148,7 @@ class AsyncEOSDriver(AsyncNetworkDriver, EOSDriverBase):
|
|
146
148
|
timeout_transport=timeout_transport,
|
147
149
|
timeout_ops=timeout_ops,
|
148
150
|
comms_return_char=comms_return_char,
|
151
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
149
152
|
ssh_config_file=ssh_config_file,
|
150
153
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
151
154
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.arista_eos.base_driver"""
|
2
|
+
|
2
3
|
import re
|
3
4
|
from typing import Dict
|
4
5
|
|
@@ -31,7 +32,7 @@ PRIVS = {
|
|
31
32
|
),
|
32
33
|
"configuration": (
|
33
34
|
PrivilegeLevel(
|
34
|
-
pattern=r"^[\w.\-@()/: ]{1,63}\(config[\w.\-@/:]{0,
|
35
|
+
pattern=r"^[\w.\-@()/: ]{1,63}\(config[\w.\-@/:]{0,63}\)#\s?$",
|
35
36
|
name="configuration",
|
36
37
|
previous_priv="privilege_exec",
|
37
38
|
deescalate="end",
|
@@ -79,7 +80,7 @@ class EOSDriverBase:
|
|
79
80
|
raise ScrapliValueError(msg)
|
80
81
|
sess_prompt = re.escape(session_name[:6])
|
81
82
|
pattern = (
|
82
|
-
rf"^[a-z0-9.\-@()/: ]{{1,63}}\(config\-s\-{sess_prompt}[a-z0-9_.\-@/:]{{0,
|
83
|
+
rf"^[a-z0-9.\-@()/: ]{{1,63}}\(config\-s\-{sess_prompt}[a-z0-9_.\-@/:]{{0,64}}\)#\s?$"
|
83
84
|
)
|
84
85
|
name = session_name
|
85
86
|
config_session = PrivilegeLevel(
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.arista_eos.sync_driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -66,6 +67,7 @@ class EOSDriver(NetworkDriver, EOSDriverBase):
|
|
66
67
|
timeout_transport: float = 30.0,
|
67
68
|
timeout_ops: float = 30.0,
|
68
69
|
comms_return_char: str = "\n",
|
70
|
+
comms_roughly_match_inputs: bool = False,
|
69
71
|
ssh_config_file: Union[str, bool] = False,
|
70
72
|
ssh_known_hosts_file: Union[str, bool] = False,
|
71
73
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -146,6 +148,7 @@ class EOSDriver(NetworkDriver, EOSDriverBase):
|
|
146
148
|
timeout_transport=timeout_transport,
|
147
149
|
timeout_ops=timeout_ops,
|
148
150
|
comms_return_char=comms_return_char,
|
151
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
149
152
|
ssh_config_file=ssh_config_file,
|
150
153
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
151
154
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.cisco_iosxe.async_driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -66,6 +67,7 @@ class AsyncIOSXEDriver(AsyncNetworkDriver):
|
|
66
67
|
timeout_transport: float = 30.0,
|
67
68
|
timeout_ops: float = 30.0,
|
68
69
|
comms_return_char: str = "\n",
|
70
|
+
comms_roughly_match_inputs: bool = False,
|
69
71
|
ssh_config_file: Union[str, bool] = False,
|
70
72
|
ssh_known_hosts_file: Union[str, bool] = False,
|
71
73
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -143,6 +145,7 @@ class AsyncIOSXEDriver(AsyncNetworkDriver):
|
|
143
145
|
timeout_transport=timeout_transport,
|
144
146
|
timeout_ops=timeout_ops,
|
145
147
|
comms_return_char=comms_return_char,
|
148
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
146
149
|
ssh_config_file=ssh_config_file,
|
147
150
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
148
151
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.cisco_iosxe.sync_driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -66,6 +67,7 @@ class IOSXEDriver(NetworkDriver):
|
|
66
67
|
timeout_transport: float = 30.0,
|
67
68
|
timeout_ops: float = 30.0,
|
68
69
|
comms_return_char: str = "\n",
|
70
|
+
comms_roughly_match_inputs: bool = False,
|
69
71
|
ssh_config_file: Union[str, bool] = False,
|
70
72
|
ssh_known_hosts_file: Union[str, bool] = False,
|
71
73
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -143,6 +145,7 @@ class IOSXEDriver(NetworkDriver):
|
|
143
145
|
timeout_transport=timeout_transport,
|
144
146
|
timeout_ops=timeout_ops,
|
145
147
|
comms_return_char=comms_return_char,
|
148
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
146
149
|
ssh_config_file=ssh_config_file,
|
147
150
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
148
151
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.cisco_iosxr.async_driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -65,6 +66,7 @@ class AsyncIOSXRDriver(AsyncNetworkDriver):
|
|
65
66
|
timeout_transport: float = 30.0,
|
66
67
|
timeout_ops: float = 30.0,
|
67
68
|
comms_return_char: str = "\n",
|
69
|
+
comms_roughly_match_inputs: bool = False,
|
68
70
|
ssh_config_file: Union[str, bool] = False,
|
69
71
|
ssh_known_hosts_file: Union[str, bool] = False,
|
70
72
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -142,6 +144,7 @@ class AsyncIOSXRDriver(AsyncNetworkDriver):
|
|
142
144
|
timeout_transport=timeout_transport,
|
143
145
|
timeout_ops=timeout_ops,
|
144
146
|
comms_return_char=comms_return_char,
|
147
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
145
148
|
ssh_config_file=ssh_config_file,
|
146
149
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
147
150
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.cisco_iosxr.sync_driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -68,6 +69,7 @@ class IOSXRDriver(NetworkDriver):
|
|
68
69
|
timeout_transport: float = 30.0,
|
69
70
|
timeout_ops: float = 30.0,
|
70
71
|
comms_return_char: str = "\n",
|
72
|
+
comms_roughly_match_inputs: bool = False,
|
71
73
|
ssh_config_file: Union[str, bool] = False,
|
72
74
|
ssh_known_hosts_file: Union[str, bool] = False,
|
73
75
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -145,6 +147,7 @@ class IOSXRDriver(NetworkDriver):
|
|
145
147
|
timeout_transport=timeout_transport,
|
146
148
|
timeout_ops=timeout_ops,
|
147
149
|
comms_return_char=comms_return_char,
|
150
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
148
151
|
ssh_config_file=ssh_config_file,
|
149
152
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
150
153
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.cisco_nxos.async_driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -66,6 +67,7 @@ class AsyncNXOSDriver(AsyncNetworkDriver, NXOSDriverBase):
|
|
66
67
|
timeout_transport: float = 30.0,
|
67
68
|
timeout_ops: float = 30.0,
|
68
69
|
comms_return_char: str = "\n",
|
70
|
+
comms_roughly_match_inputs: bool = False,
|
69
71
|
ssh_config_file: Union[str, bool] = False,
|
70
72
|
ssh_known_hosts_file: Union[str, bool] = False,
|
71
73
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -146,6 +148,7 @@ class AsyncNXOSDriver(AsyncNetworkDriver, NXOSDriverBase):
|
|
146
148
|
timeout_transport=timeout_transport,
|
147
149
|
timeout_ops=timeout_ops,
|
148
150
|
comms_return_char=comms_return_char,
|
151
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
149
152
|
ssh_config_file=ssh_config_file,
|
150
153
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
151
154
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.cisco_nxos.base_driver"""
|
2
|
+
|
2
3
|
from typing import Dict
|
3
4
|
|
4
5
|
from scrapli.driver.network.base_driver import PrivilegeLevel
|
@@ -7,7 +8,7 @@ from scrapli.exceptions import ScrapliValueError
|
|
7
8
|
PRIVS = {
|
8
9
|
"exec": (
|
9
10
|
PrivilegeLevel(
|
10
|
-
pattern=r"^[\w.\-]{1,63}
|
11
|
+
pattern=r"^[\w.\-]{1,63}(\(maint\-mode\))?>\s?$",
|
11
12
|
name="exec",
|
12
13
|
previous_priv="",
|
13
14
|
deescalate="",
|
@@ -18,7 +19,7 @@ PRIVS = {
|
|
18
19
|
),
|
19
20
|
"privilege_exec": (
|
20
21
|
PrivilegeLevel(
|
21
|
-
pattern=r"^[\w.\-]{1,63}
|
22
|
+
pattern=r"^[\w.\-]{1,63}(\(maint\-mode\))?#\s?$",
|
22
23
|
name="privilege_exec",
|
23
24
|
previous_priv="exec",
|
24
25
|
deescalate="disable",
|
@@ -30,7 +31,7 @@ PRIVS = {
|
|
30
31
|
),
|
31
32
|
"configuration": (
|
32
33
|
PrivilegeLevel(
|
33
|
-
pattern=r"^[\w.\-]{1,63}\(config[\w.\-@/:\+]{0,32}\)#\s?$",
|
34
|
+
pattern=r"^[\w.\-]{1,63}(\(maint\-mode\))?\(config[\w.\-@/:\+]{0,32}\)#\s?$",
|
34
35
|
name="configuration",
|
35
36
|
previous_priv="privilege_exec",
|
36
37
|
deescalate="end",
|
@@ -46,7 +47,11 @@ PRIVS = {
|
|
46
47
|
# for now doesnt seem to be a reason to differentiate between them, so just have one
|
47
48
|
# giant pattern
|
48
49
|
pattern=(
|
49
|
-
r"(^[\w.\-]{1,63}\-tcl#\s?$)|"
|
50
|
+
r"(^[\w.\-]{1,63}\-tcl#\s?$)|"
|
51
|
+
r"(^[\w.\-]{1,63}\(config\-tcl\)#\s?$)|"
|
52
|
+
r"(^>\s?$)|"
|
53
|
+
r"(^[\w.\-]{1,63}\(maint\-mode\-tcl\)#\s?$)|"
|
54
|
+
r"(^[\w.\-]{1,63}\(maint\-mode\)\(config\-tcl\)#\s?$)"
|
50
55
|
),
|
51
56
|
name="tclsh",
|
52
57
|
previous_priv="privilege_exec",
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.cisco_nxos.sync_driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -66,6 +67,7 @@ class NXOSDriver(NetworkDriver, NXOSDriverBase):
|
|
66
67
|
timeout_transport: float = 30.0,
|
67
68
|
timeout_ops: float = 30.0,
|
68
69
|
comms_return_char: str = "\n",
|
70
|
+
comms_roughly_match_inputs: bool = False,
|
69
71
|
ssh_config_file: Union[str, bool] = False,
|
70
72
|
ssh_known_hosts_file: Union[str, bool] = False,
|
71
73
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -146,6 +148,7 @@ class NXOSDriver(NetworkDriver, NXOSDriverBase):
|
|
146
148
|
timeout_transport=timeout_transport,
|
147
149
|
timeout_ops=timeout_ops,
|
148
150
|
comms_return_char=comms_return_char,
|
151
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
149
152
|
ssh_config_file=ssh_config_file,
|
150
153
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
151
154
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.juniper_junos.async_driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -67,6 +68,7 @@ class AsyncJunosDriver(AsyncNetworkDriver):
|
|
67
68
|
timeout_transport: float = 30.0,
|
68
69
|
timeout_ops: float = 30.0,
|
69
70
|
comms_return_char: str = "\n",
|
71
|
+
comms_roughly_match_inputs: bool = False,
|
70
72
|
ssh_config_file: Union[str, bool] = False,
|
71
73
|
ssh_known_hosts_file: Union[str, bool] = False,
|
72
74
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -144,6 +146,7 @@ class AsyncJunosDriver(AsyncNetworkDriver):
|
|
144
146
|
timeout_transport=timeout_transport,
|
145
147
|
timeout_ops=timeout_ops,
|
146
148
|
comms_return_char=comms_return_char,
|
149
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
147
150
|
ssh_config_file=ssh_config_file,
|
148
151
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
149
152
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.core.juniper_junos.driver"""
|
2
|
+
|
2
3
|
from copy import deepcopy
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Union
|
@@ -67,6 +68,7 @@ class JunosDriver(NetworkDriver):
|
|
67
68
|
timeout_transport: float = 30.0,
|
68
69
|
timeout_ops: float = 30.0,
|
69
70
|
comms_return_char: str = "\n",
|
71
|
+
comms_roughly_match_inputs: bool = False,
|
70
72
|
ssh_config_file: Union[str, bool] = False,
|
71
73
|
ssh_known_hosts_file: Union[str, bool] = False,
|
72
74
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -144,6 +146,7 @@ class JunosDriver(NetworkDriver):
|
|
144
146
|
timeout_transport=timeout_transport,
|
145
147
|
timeout_ops=timeout_ops,
|
146
148
|
comms_return_char=comms_return_char,
|
149
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
147
150
|
ssh_config_file=ssh_config_file,
|
148
151
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
149
152
|
on_init=on_init,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.generic.async_driver"""
|
2
|
+
|
2
3
|
import asyncio
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
|
@@ -16,6 +17,23 @@ if TYPE_CHECKING:
|
|
16
17
|
)
|
17
18
|
|
18
19
|
|
20
|
+
async def generic_on_open(conn: "AsyncGenericDriver") -> None:
|
21
|
+
"""
|
22
|
+
GenericDriver default on-open -- drains initial login by running a simple get_prompt
|
23
|
+
|
24
|
+
Args:
|
25
|
+
conn: GenericDriver object
|
26
|
+
|
27
|
+
Returns:
|
28
|
+
None
|
29
|
+
|
30
|
+
Raises:
|
31
|
+
N/A
|
32
|
+
|
33
|
+
"""
|
34
|
+
await conn.get_prompt()
|
35
|
+
|
36
|
+
|
19
37
|
class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
20
38
|
def __init__(
|
21
39
|
self,
|
@@ -35,10 +53,11 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
35
53
|
timeout_ops: float = 30.0,
|
36
54
|
comms_prompt_pattern: str = r"^\S{0,48}[#>$~@:\]]\s*$",
|
37
55
|
comms_return_char: str = "\n",
|
56
|
+
comms_roughly_match_inputs: bool = False,
|
38
57
|
ssh_config_file: Union[str, bool] = False,
|
39
58
|
ssh_known_hosts_file: Union[str, bool] = False,
|
40
59
|
on_init: Optional[Callable[..., Any]] = None,
|
41
|
-
on_open: Optional[Callable[..., Any]] =
|
60
|
+
on_open: Optional[Callable[..., Any]] = generic_on_open,
|
42
61
|
on_close: Optional[Callable[..., Any]] = None,
|
43
62
|
transport: str = "system",
|
44
63
|
transport_options: Optional[Dict[str, Any]] = None,
|
@@ -64,6 +83,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
64
83
|
timeout_ops=timeout_ops,
|
65
84
|
comms_prompt_pattern=comms_prompt_pattern,
|
66
85
|
comms_return_char=comms_return_char,
|
86
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
67
87
|
ssh_config_file=ssh_config_file,
|
68
88
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
69
89
|
on_init=on_init,
|
@@ -101,6 +121,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
101
121
|
strip_prompt: bool = True,
|
102
122
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
103
123
|
eager: bool = False,
|
124
|
+
eager_input: bool = False,
|
104
125
|
timeout_ops: Optional[float] = None,
|
105
126
|
) -> Response:
|
106
127
|
"""
|
@@ -117,6 +138,8 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
117
138
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
118
139
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
119
140
|
it can make scrapli less reliable!
|
141
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
142
|
+
this should be left alone unless you know what you are doing!
|
120
143
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
121
144
|
the duration of the operation, value is reset to initial value after operation is
|
122
145
|
completed
|
@@ -141,7 +164,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
141
164
|
failed_when_contains=failed_when_contains,
|
142
165
|
)
|
143
166
|
raw_response, processed_response = await self.channel.send_input(
|
144
|
-
channel_input=command, strip_prompt=strip_prompt, eager=eager
|
167
|
+
channel_input=command, strip_prompt=strip_prompt, eager=eager, eager_input=eager_input
|
145
168
|
)
|
146
169
|
return self._post_send_command(
|
147
170
|
raw_response=raw_response, processed_response=processed_response, response=response
|
@@ -153,6 +176,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
153
176
|
*,
|
154
177
|
strip_prompt: bool = True,
|
155
178
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
179
|
+
eager_input: bool = False,
|
156
180
|
timeout_ops: Optional[float] = None,
|
157
181
|
) -> Response:
|
158
182
|
"""
|
@@ -162,6 +186,8 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
162
186
|
command: string to send to device in privilege exec mode
|
163
187
|
strip_prompt: strip prompt or not, defaults to True (yes, strip the prompt)
|
164
188
|
failed_when_contains: string or list of strings indicating failure if found in response
|
189
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
190
|
+
this should be left alone unless you know what you are doing!
|
165
191
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
166
192
|
the duration of the operation, value is reset to initial value after operation is
|
167
193
|
completed
|
@@ -177,6 +203,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
177
203
|
command=command,
|
178
204
|
strip_prompt=strip_prompt,
|
179
205
|
failed_when_contains=failed_when_contains,
|
206
|
+
eager_input=eager_input,
|
180
207
|
timeout_ops=timeout_ops,
|
181
208
|
)
|
182
209
|
return response
|
@@ -189,6 +216,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
189
216
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
190
217
|
stop_on_failed: bool = False,
|
191
218
|
eager: bool = False,
|
219
|
+
eager_input: bool = False,
|
192
220
|
timeout_ops: Optional[float] = None,
|
193
221
|
) -> MultiResponse:
|
194
222
|
"""
|
@@ -203,6 +231,8 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
203
231
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
204
232
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
205
233
|
it can make scrapli less reliable!
|
234
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
235
|
+
this should be left alone unless you know what you are doing!
|
206
236
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
207
237
|
the duration of the operation, value is reset to initial value after operation is
|
208
238
|
completed. Note that this is the timeout value PER COMMAND sent, not for the total
|
@@ -223,6 +253,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
223
253
|
failed_when_contains=failed_when_contains,
|
224
254
|
timeout_ops=timeout_ops,
|
225
255
|
eager=eager,
|
256
|
+
eager_input=eager_input,
|
226
257
|
)
|
227
258
|
responses.append(response)
|
228
259
|
if stop_on_failed and response.failed is True:
|
@@ -238,6 +269,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
238
269
|
failed_when_contains=failed_when_contains,
|
239
270
|
timeout_ops=timeout_ops,
|
240
271
|
eager=False,
|
272
|
+
eager_input=eager_input,
|
241
273
|
)
|
242
274
|
responses.append(response)
|
243
275
|
|
@@ -251,6 +283,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
251
283
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
252
284
|
stop_on_failed: bool = False,
|
253
285
|
eager: bool = False,
|
286
|
+
eager_input: bool = False,
|
254
287
|
timeout_ops: Optional[float] = None,
|
255
288
|
) -> MultiResponse:
|
256
289
|
"""
|
@@ -265,6 +298,8 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
265
298
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
266
299
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
267
300
|
it can make scrapli less reliable!
|
301
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
302
|
+
this should be left alone unless you know what you are doing!
|
268
303
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
269
304
|
the duration of the operation, value is reset to initial value after operation is
|
270
305
|
completed. Note that this is the timeout value PER COMMAND sent, not for the total
|
@@ -285,6 +320,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
285
320
|
failed_when_contains=failed_when_contains,
|
286
321
|
stop_on_failed=stop_on_failed,
|
287
322
|
eager=eager,
|
323
|
+
eager_input=eager_input,
|
288
324
|
timeout_ops=timeout_ops,
|
289
325
|
)
|
290
326
|
|
@@ -530,7 +566,13 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
530
566
|
"""
|
531
567
|
if initial_input is not None:
|
532
568
|
self.channel.write(channel_input=f"{initial_input}{self.comms_return_char}")
|
533
|
-
return await self.read_callback(
|
569
|
+
return await self.read_callback(
|
570
|
+
callbacks=callbacks,
|
571
|
+
initial_input=None,
|
572
|
+
read_output=read_output,
|
573
|
+
read_delay=read_delay,
|
574
|
+
read_timeout=read_timeout,
|
575
|
+
)
|
534
576
|
|
535
577
|
original_transport_timeout = self.timeout_transport
|
536
578
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.generic.base_driver"""
|
2
|
+
|
2
3
|
import re
|
3
4
|
from typing import (
|
4
5
|
TYPE_CHECKING,
|
@@ -337,7 +338,7 @@ class BaseGenericDriver:
|
|
337
338
|
raise ScrapliTypeError(f"`{caller}` expects a string path to a file, got {type(file)}")
|
338
339
|
resolved_file = resolve_file(file)
|
339
340
|
|
340
|
-
with open(resolved_file,
|
341
|
+
with open(resolved_file, encoding="utf-8") as f:
|
341
342
|
commands = f.read().splitlines()
|
342
343
|
|
343
344
|
return commands
|