rtems-proxy 2.0.0__tar.gz → 2.1.0__tar.gz
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.
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/PKG-INFO +1 -1
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/requirements.txt +1 -1
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/rtems-proxy.code-workspace +0 -3
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/__main__.py +19 -5
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/_version.py +3 -3
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/configure.py +1 -1
- rtems_proxy-2.1.0/src/rtems_proxy/connect.py +102 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/copy.py +29 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/globals.py +1 -1
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/telnet.py +33 -90
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy.egg-info/PKG-INFO +1 -1
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy.egg-info/SOURCES.txt +1 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.copier-answers.yml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.devcontainer/devcontainer.json +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/CONTRIBUTING.md +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/ISSUE_TEMPLATE/issue.md +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/copilot-instructions.md +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/pages/index.html +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/pages/make_switcher.py +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/workflows/_container.yml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/workflows/_dist.yml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/workflows/_pypi.yml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/workflows/_release.yml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/workflows/_test.yml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/workflows/_tox.yml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/workflows/ci.yml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.gitignore +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.gitleaks.toml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.pre-commit-config.yaml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.python-version +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.vscode/extensions.json +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.vscode/launch.json +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.vscode/settings.json +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.vscode/tasks.json +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/Dockerfile +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/LICENSE +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/README.md +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/pyproject.toml +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/renovate.json +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/setup.cfg +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/__init__.py +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/rsync.sh.jinja +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/trace.py +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy/utils.py +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy.egg-info/dependency_links.txt +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy.egg-info/entry_points.txt +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy.egg-info/requires.txt +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/src/rtems_proxy.egg-info/top_level.txt +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/tests/conftest.py +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/tests/test_cli.py +0 -0
- {rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/uv.lock +0 -0
|
@@ -11,9 +11,9 @@ from rtems_proxy.utils import run_command
|
|
|
11
11
|
|
|
12
12
|
from . import __version__
|
|
13
13
|
from .configure import Configure
|
|
14
|
-
from .
|
|
14
|
+
from .connect import ioc_connect, motboot_connect, report
|
|
15
|
+
from .copy import check_new_version, copy_rtems, save_current_version
|
|
15
16
|
from .globals import GLOBALS
|
|
16
|
-
from .telnet import ioc_connect, motboot_connect, report
|
|
17
17
|
|
|
18
18
|
__all__ = ["main"]
|
|
19
19
|
|
|
@@ -52,6 +52,9 @@ def start(
|
|
|
52
52
|
reboot: bool = typer.Option(
|
|
53
53
|
True, "--reboot/--no-reboot", help="reboot the IOC first"
|
|
54
54
|
),
|
|
55
|
+
configure: bool = typer.Option(
|
|
56
|
+
True, "--configure/--no-configure", help="configure motBoot when rebooting"
|
|
57
|
+
),
|
|
55
58
|
raise_errors: bool = typer.Option(
|
|
56
59
|
True, "--raise-errors/--no-raise-errors", help="raise errors instead of exiting"
|
|
57
60
|
),
|
|
@@ -78,11 +81,23 @@ def start(
|
|
|
78
81
|
)
|
|
79
82
|
if copy:
|
|
80
83
|
copy_rtems()
|
|
84
|
+
|
|
85
|
+
# always reboot if the IOC definition has changed
|
|
86
|
+
if check_new_version():
|
|
87
|
+
report("IOC definition has changed, forcing reboot to pick up changes")
|
|
88
|
+
reboot = True
|
|
89
|
+
|
|
81
90
|
if connect:
|
|
82
91
|
assert GLOBALS.RTEMS_CONSOLE, "No RTEMS console defined"
|
|
83
92
|
ioc_connect(
|
|
84
|
-
GLOBALS.RTEMS_CONSOLE,
|
|
93
|
+
GLOBALS.RTEMS_CONSOLE,
|
|
94
|
+
reboot=reboot,
|
|
95
|
+
attach=True,
|
|
96
|
+
raise_errors=raise_errors,
|
|
97
|
+
configure=configure,
|
|
85
98
|
)
|
|
99
|
+
# now we have rebooted into the IOC we can save the current version
|
|
100
|
+
save_current_version()
|
|
86
101
|
else:
|
|
87
102
|
report("IOC console connection disabled. ")
|
|
88
103
|
|
|
@@ -189,9 +204,8 @@ def configure(
|
|
|
189
204
|
else:
|
|
190
205
|
assert GLOBALS.RTEMS_CONSOLE, "No RTEMS console defined"
|
|
191
206
|
|
|
192
|
-
config = Configure(None, debug=debug)
|
|
193
207
|
telnet = motboot_connect(GLOBALS.RTEMS_CONSOLE, use_console=use_console)
|
|
194
|
-
config = Configure(telnet, debug=debug, dry_run=
|
|
208
|
+
config = Configure(telnet, debug=debug, dry_run=False)
|
|
195
209
|
config.apply_settings()
|
|
196
210
|
telnet.close()
|
|
197
211
|
if attach:
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '2.
|
|
32
|
-
__version_tuple__ = version_tuple = (2,
|
|
31
|
+
__version__ = version = '2.1.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 1, 0)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'gb348b0264'
|
|
@@ -35,7 +35,7 @@ class Configure:
|
|
|
35
35
|
else:
|
|
36
36
|
self.telnet.sendline(f"gevE {variable}")
|
|
37
37
|
self.telnet.expect(r"\(Blank line terminates input.\)")
|
|
38
|
-
self.telnet.sendline(value
|
|
38
|
+
self.telnet.sendline(value)
|
|
39
39
|
self.telnet.sendline("")
|
|
40
40
|
self.telnet.expect(r"\?")
|
|
41
41
|
self.telnet.sendline("Y")
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
from time import sleep
|
|
2
|
+
|
|
3
|
+
import pexpect
|
|
4
|
+
|
|
5
|
+
from .configure import Configure
|
|
6
|
+
from .telnet import CannotConnectError, RtemsState, TelnetRTEMS
|
|
7
|
+
from .utils import run_command
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def report(message):
|
|
11
|
+
"""
|
|
12
|
+
print a message that is noticeable amongst all the other output
|
|
13
|
+
"""
|
|
14
|
+
print(f"\n>>>> {message} <<<<\n")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def ioc_connect(
|
|
18
|
+
host_and_port: str,
|
|
19
|
+
reboot: bool = False,
|
|
20
|
+
configure: bool = True,
|
|
21
|
+
attach: bool = True,
|
|
22
|
+
raise_errors: bool = False,
|
|
23
|
+
):
|
|
24
|
+
"""
|
|
25
|
+
Entrypoint to make a connection to an RTEMS IOC over telnet.
|
|
26
|
+
Once connected, enters an interactive user session with the IOC.
|
|
27
|
+
|
|
28
|
+
args:
|
|
29
|
+
host_and_port: 'hostname:port' of the IOC to connect to
|
|
30
|
+
reboot: reboot the IOC to pick up new binaries/startup/epics db
|
|
31
|
+
"""
|
|
32
|
+
telnet = TelnetRTEMS(host_and_port, reboot)
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
telnet.connect()
|
|
36
|
+
|
|
37
|
+
# this will untangle a partially executed gevEdit command
|
|
38
|
+
for _ in range(3):
|
|
39
|
+
telnet.sendline("\r")
|
|
40
|
+
|
|
41
|
+
current = telnet.check_prompt(retries=6, timeout=10)
|
|
42
|
+
match current:
|
|
43
|
+
case RtemsState.MOT:
|
|
44
|
+
report("At MOTBoot prompt")
|
|
45
|
+
reboot = True
|
|
46
|
+
case RtemsState.UNKNOWN:
|
|
47
|
+
report("Current IOC state unknown, attempting reboot ...")
|
|
48
|
+
reboot = True
|
|
49
|
+
case RtemsState.IOC:
|
|
50
|
+
report("At IOC shell prompt")
|
|
51
|
+
|
|
52
|
+
if reboot:
|
|
53
|
+
if configure:
|
|
54
|
+
report("Rebooting to configure motBoot settings")
|
|
55
|
+
telnet.get_boot_prompt(retries=10)
|
|
56
|
+
sleep(1)
|
|
57
|
+
cfg = Configure(telnet)
|
|
58
|
+
cfg.apply_settings()
|
|
59
|
+
else:
|
|
60
|
+
report("Rebooting into IOC shell")
|
|
61
|
+
|
|
62
|
+
telnet.get_epics_prompt(retries=10)
|
|
63
|
+
else:
|
|
64
|
+
report("Auto reboot disabled. Skipping reboot")
|
|
65
|
+
|
|
66
|
+
except (CannotConnectError, pexpect.exceptions.TIMEOUT):
|
|
67
|
+
report("Connection failed, Exiting.")
|
|
68
|
+
telnet.close()
|
|
69
|
+
raise
|
|
70
|
+
|
|
71
|
+
except Exception as e:
|
|
72
|
+
# flush any remaining buffered output to stdout
|
|
73
|
+
telnet.flush_remaining_output()
|
|
74
|
+
report(f"An error occurred: {e}")
|
|
75
|
+
telnet.close()
|
|
76
|
+
if raise_errors:
|
|
77
|
+
raise
|
|
78
|
+
|
|
79
|
+
telnet.close()
|
|
80
|
+
if attach:
|
|
81
|
+
report("Connecting to IOC console, hit enter for a prompt")
|
|
82
|
+
run_command(telnet.command)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def motboot_connect(
|
|
86
|
+
host_and_port: str, reboot: bool = False, use_console: bool = False
|
|
87
|
+
) -> TelnetRTEMS:
|
|
88
|
+
"""
|
|
89
|
+
Connect to the MOTBoot bootloader prompt, rebooting if needed.
|
|
90
|
+
|
|
91
|
+
Returns a TelnetRTEMS object that is connected to the MOTBoot bootloader
|
|
92
|
+
"""
|
|
93
|
+
telnet = TelnetRTEMS(host_and_port, ioc_reboot=reboot, use_console=use_console)
|
|
94
|
+
telnet.connect()
|
|
95
|
+
|
|
96
|
+
# this will untangle a partially executed gevEdit command
|
|
97
|
+
for _ in range(3):
|
|
98
|
+
telnet.sendline("\r")
|
|
99
|
+
|
|
100
|
+
telnet.get_boot_prompt()
|
|
101
|
+
|
|
102
|
+
return telnet
|
|
@@ -9,6 +9,35 @@ from pathlib import Path
|
|
|
9
9
|
from .globals import GLOBALS
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
def save_current_version():
|
|
13
|
+
"""
|
|
14
|
+
Save the current version string to a file in the NFS root so that the IOC
|
|
15
|
+
can report its version on startup
|
|
16
|
+
|
|
17
|
+
We use the env IOC_ORIGINAL_LOCATION as a proxy for the version string
|
|
18
|
+
"""
|
|
19
|
+
version_file = Path(GLOBALS.RTEMS_NFS_ROOT_PATH) / "rtems_proxy_version.txt"
|
|
20
|
+
with open(version_file, "w") as vf:
|
|
21
|
+
vf.write(str(GLOBALS.IOC_ORIGINAL_LOCATION) + "\n")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def check_new_version():
|
|
25
|
+
"""
|
|
26
|
+
Check if the version string saved in the NFS root matches the current
|
|
27
|
+
version string.
|
|
28
|
+
|
|
29
|
+
We use the env IOC_ORIGINAL_LOCATION as a proxy for the version string
|
|
30
|
+
"""
|
|
31
|
+
version_file = Path(GLOBALS.RTEMS_NFS_ROOT_PATH) / "rtems_proxy_version.txt"
|
|
32
|
+
if not version_file.exists():
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
with open(version_file) as vf:
|
|
36
|
+
saved_version = vf.read().strip()
|
|
37
|
+
|
|
38
|
+
return saved_version != str(GLOBALS.IOC_ORIGINAL_LOCATION)
|
|
39
|
+
|
|
40
|
+
|
|
12
41
|
def copy_rtems(debug: bool = False):
|
|
13
42
|
"""
|
|
14
43
|
Copy RTEMS IOC binary and startup assets to a location where the RTEMS IOC
|
|
@@ -22,7 +22,7 @@ class _Globals:
|
|
|
22
22
|
self.RTEMS_TFTP_ROOT_PATH = Path("/ioc_tftp")
|
|
23
23
|
""" root folder of a mounted PVC in which to place IOC binaries """
|
|
24
24
|
self.RTEMS_NFS_ROOT_PATH = Path("/ioc_nfs")
|
|
25
|
-
""" root folder of a mounted NFS folder in which to place IOC
|
|
25
|
+
""" root folder of a mounted NFS folder in which to place IOC runtime files """
|
|
26
26
|
|
|
27
27
|
########################################################################
|
|
28
28
|
## Beamline level config from global.env in services/values.yaml
|
|
@@ -5,8 +5,6 @@ from time import sleep
|
|
|
5
5
|
|
|
6
6
|
import pexpect
|
|
7
7
|
|
|
8
|
-
from .utils import run_command
|
|
9
|
-
|
|
10
8
|
|
|
11
9
|
class CannotConnectError(Exception):
|
|
12
10
|
pass
|
|
@@ -78,6 +76,7 @@ class TelnetRTEMS:
|
|
|
78
76
|
logfile=sys.stdout,
|
|
79
77
|
echo=False,
|
|
80
78
|
codec_errors="ignore",
|
|
79
|
+
timeout=5,
|
|
81
80
|
)
|
|
82
81
|
try:
|
|
83
82
|
# first check for connection refusal
|
|
@@ -89,7 +88,7 @@ class TelnetRTEMS:
|
|
|
89
88
|
report("Cannot connect to remote IOC, connection in use?")
|
|
90
89
|
raise CannotConnectError
|
|
91
90
|
|
|
92
|
-
def check_prompt(self, retries) -> RtemsState:
|
|
91
|
+
def check_prompt(self, retries, timeout=15) -> RtemsState:
|
|
93
92
|
"""
|
|
94
93
|
Determine if we are currently seeing an IOC shell prompt or
|
|
95
94
|
bootloader. Because there is a possibility that we are in the middle
|
|
@@ -104,24 +103,33 @@ class TelnetRTEMS:
|
|
|
104
103
|
self._child.sendline(self.IOC_CHECK)
|
|
105
104
|
self._child.expect(self.IOC_RESPONSE, timeout=1)
|
|
106
105
|
except pexpect.exceptions.TIMEOUT:
|
|
107
|
-
|
|
108
|
-
# see if we are in the bootloader
|
|
109
|
-
self._child.sendline()
|
|
110
|
-
self._child.expect(self.MOT_PROMPT, timeout=1)
|
|
111
|
-
except pexpect.exceptions.TIMEOUT:
|
|
112
|
-
# current state unknown. wait and retry
|
|
113
|
-
sleep(15)
|
|
114
|
-
else:
|
|
115
|
-
report("Currently in bootloader")
|
|
116
|
-
return RtemsState.MOT
|
|
106
|
+
pass
|
|
117
107
|
else:
|
|
118
|
-
report("Currently in IOC shell")
|
|
119
108
|
return RtemsState.IOC
|
|
120
109
|
|
|
110
|
+
try:
|
|
111
|
+
# see if we are in the bootloader
|
|
112
|
+
self._child.sendline()
|
|
113
|
+
self._child.expect(self.MOT_PROMPT, timeout=1)
|
|
114
|
+
except pexpect.exceptions.TIMEOUT:
|
|
115
|
+
pass
|
|
116
|
+
else:
|
|
117
|
+
return RtemsState.MOT
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
# current state unknown. check for mot start prompt
|
|
121
|
+
# in case we are in a boot loop
|
|
122
|
+
self._child.expect(self.CONTINUE, timeout=timeout)
|
|
123
|
+
except pexpect.exceptions.TIMEOUT:
|
|
124
|
+
pass
|
|
125
|
+
else:
|
|
126
|
+
# send escape to get into the bootloader
|
|
127
|
+
self._child.sendline(chr(27))
|
|
128
|
+
return RtemsState.MOT
|
|
129
|
+
|
|
121
130
|
report(f"Retry {retry + 1} of get current status")
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
raise CannotConnectError("Current state of remote IOC unknown")
|
|
132
|
+
return RtemsState.UNKNOWN
|
|
125
133
|
|
|
126
134
|
def reboot(self, into: RtemsState):
|
|
127
135
|
"""
|
|
@@ -145,6 +153,8 @@ class TelnetRTEMS:
|
|
|
145
153
|
# send space to boot the IOC
|
|
146
154
|
self._child.send(" ")
|
|
147
155
|
|
|
156
|
+
self.ioc_rebooted = True
|
|
157
|
+
|
|
148
158
|
def get_epics_prompt(self, retries=5):
|
|
149
159
|
"""
|
|
150
160
|
Get to the IOC shell prompt, if the IOC is not already running, reboot
|
|
@@ -153,27 +163,26 @@ class TelnetRTEMS:
|
|
|
153
163
|
"""
|
|
154
164
|
assert self._child, "must call connect before get_epics_prompt"
|
|
155
165
|
|
|
156
|
-
current = self.check_prompt(retries=
|
|
166
|
+
current = self.check_prompt(retries=retries)
|
|
157
167
|
|
|
158
168
|
if current != RtemsState.IOC or (self._ioc_reboot and not self.ioc_rebooted):
|
|
159
169
|
sleep(0.5)
|
|
160
|
-
report("Rebooting the IOC")
|
|
161
170
|
|
|
171
|
+
report("Rebooting into IOC shell")
|
|
162
172
|
self.reboot(RtemsState.IOC)
|
|
163
|
-
self.ioc_rebooted = True
|
|
164
173
|
|
|
165
|
-
current = self.check_prompt(retries=
|
|
174
|
+
current = self.check_prompt(retries=retries)
|
|
166
175
|
if current != RtemsState.IOC:
|
|
167
176
|
raise CannotConnectError("Failed to reboot into IOC shell")
|
|
168
177
|
|
|
169
|
-
def get_boot_prompt(self):
|
|
178
|
+
def get_boot_prompt(self, retries=5):
|
|
170
179
|
"""
|
|
171
180
|
Get to the bootloader prompt, if the IOC shell is running then exit
|
|
172
181
|
and send appropriate commands to get to the bootloader
|
|
173
182
|
"""
|
|
174
183
|
assert self._child, "must call connect before get_boot_prompt"
|
|
175
184
|
|
|
176
|
-
current = self.check_prompt(retries=
|
|
185
|
+
current = self.check_prompt(retries=retries)
|
|
177
186
|
if current != RtemsState.MOT:
|
|
178
187
|
# get out of the IOC and return to MOT
|
|
179
188
|
self.reboot(RtemsState.MOT)
|
|
@@ -185,8 +194,9 @@ class TelnetRTEMS:
|
|
|
185
194
|
"""
|
|
186
195
|
Send a command to the telnet session
|
|
187
196
|
"""
|
|
197
|
+
# always pause a little to allow the previous expect to complete
|
|
188
198
|
assert self._child, "must call connect before send"
|
|
189
|
-
self._child.sendline(command)
|
|
199
|
+
self._child.sendline(command + "\r")
|
|
190
200
|
|
|
191
201
|
def expect(self, pattern, timeout=10) -> None:
|
|
192
202
|
"""
|
|
@@ -221,70 +231,3 @@ def report(message):
|
|
|
221
231
|
print a message that is noticeable amongst all the other output
|
|
222
232
|
"""
|
|
223
233
|
print(f"\n>>>> {message} <<<<\n")
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
def ioc_connect(
|
|
227
|
-
host_and_port: str,
|
|
228
|
-
reboot: bool = False,
|
|
229
|
-
attach: bool = True,
|
|
230
|
-
raise_errors: bool = False,
|
|
231
|
-
):
|
|
232
|
-
"""
|
|
233
|
-
Entrypoint to make a connection to an RTEMS IOC over telnet.
|
|
234
|
-
Once connected, enters an interactive user session with the IOC.
|
|
235
|
-
|
|
236
|
-
args:
|
|
237
|
-
host_and_port: 'hostname:port' of the IOC to connect to
|
|
238
|
-
reboot: reboot the IOC to pick up new binaries/startup/epics db
|
|
239
|
-
"""
|
|
240
|
-
telnet = TelnetRTEMS(host_and_port, reboot)
|
|
241
|
-
|
|
242
|
-
try:
|
|
243
|
-
telnet.connect()
|
|
244
|
-
|
|
245
|
-
# this will untangle a partially executed gevEdit command
|
|
246
|
-
for _ in range(3):
|
|
247
|
-
telnet.sendline("\r")
|
|
248
|
-
|
|
249
|
-
if reboot:
|
|
250
|
-
telnet.get_epics_prompt(retries=10)
|
|
251
|
-
else:
|
|
252
|
-
report("Auto reboot disabled. Skipping reboot")
|
|
253
|
-
|
|
254
|
-
except (CannotConnectError, pexpect.exceptions.TIMEOUT):
|
|
255
|
-
report("Connection failed, Exiting.")
|
|
256
|
-
telnet.close()
|
|
257
|
-
raise
|
|
258
|
-
|
|
259
|
-
except Exception as e:
|
|
260
|
-
# flush any remaining buffered output to stdout
|
|
261
|
-
telnet.flush_remaining_output()
|
|
262
|
-
report(f"An error occurred: {e}")
|
|
263
|
-
telnet.close()
|
|
264
|
-
if raise_errors:
|
|
265
|
-
raise
|
|
266
|
-
|
|
267
|
-
telnet.close()
|
|
268
|
-
if attach:
|
|
269
|
-
report("Connecting to IOC console, hit enter for a prompt")
|
|
270
|
-
run_command(telnet.command)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
def motboot_connect(
|
|
274
|
-
host_and_port: str, reboot: bool = False, use_console: bool = False
|
|
275
|
-
) -> TelnetRTEMS:
|
|
276
|
-
"""
|
|
277
|
-
Connect to the MOTBoot bootloader prompt, rebooting if needed.
|
|
278
|
-
|
|
279
|
-
Returns a TelnetRTEMS object that is connected to the MOTBoot bootloader
|
|
280
|
-
"""
|
|
281
|
-
telnet = TelnetRTEMS(host_and_port, ioc_reboot=reboot, use_console=use_console)
|
|
282
|
-
telnet.connect()
|
|
283
|
-
|
|
284
|
-
# this will untangle a partially executed gevEdit command
|
|
285
|
-
for _ in range(3):
|
|
286
|
-
telnet.sendline("\r")
|
|
287
|
-
|
|
288
|
-
telnet.get_boot_prompt()
|
|
289
|
-
|
|
290
|
-
return telnet
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rtems_proxy-2.0.0 → rtems_proxy-2.1.0}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|