rtems-proxy 0.6.0__tar.gz → 0.6.2__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-0.6.0 → rtems_proxy-0.6.2}/PKG-INFO +1 -1
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy/__main__.py +13 -5
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy/_version.py +2 -2
- rtems_proxy-0.6.2/src/rtems_proxy/copy.py +56 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy/rsync.sh.jinja +10 -2
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy/telnet.py +21 -18
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy.egg-info/PKG-INFO +1 -1
- rtems_proxy-0.6.0/src/rtems_proxy/copy.py +0 -56
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.copier-answers.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.devcontainer/devcontainer.json +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/CONTRIBUTING.md +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/ISSUE_TEMPLATE/issue.md +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/actions/install_requirements/action.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/dependabot.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/pages/index.html +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/pages/make_switcher.py +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/workflows/_check.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/workflows/_dist.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/workflows/_pypi.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/workflows/_release.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/workflows/_test.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/workflows/_tox.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.github/workflows/ci.yml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.gitignore +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.pre-commit-config.yaml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.vscode/extensions.json +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.vscode/launch.json +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.vscode/settings.json +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.vscode/tasks.json +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/Dockerfile +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/LICENSE +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/README.md +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/proxy-start.sh +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/pyproject.toml +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/requirements.txt +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/setup.cfg +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy/__init__.py +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy/globals.py +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy/utils.py +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy.egg-info/SOURCES.txt +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy.egg-info/dependency_links.txt +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy.egg-info/entry_points.txt +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy.egg-info/requires.txt +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/src/rtems_proxy.egg-info/top_level.txt +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/tests/conftest.py +0 -0
- {rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/tests/test_cli.py +0 -0
|
@@ -7,7 +7,7 @@ from ruamel.yaml import YAML
|
|
|
7
7
|
from . import __version__
|
|
8
8
|
from .copy import copy_rtems
|
|
9
9
|
from .globals import GLOBALS
|
|
10
|
-
from .telnet import ioc_connect
|
|
10
|
+
from .telnet import ioc_connect, report
|
|
11
11
|
|
|
12
12
|
__all__ = ["main"]
|
|
13
13
|
|
|
@@ -40,6 +40,9 @@ def start(
|
|
|
40
40
|
copy: bool = typer.Option(
|
|
41
41
|
True, "--copy/--no-copy", help="copy binaries before connecting"
|
|
42
42
|
),
|
|
43
|
+
connect: bool = typer.Option(
|
|
44
|
+
True, "--connect/--no-connect", help="connect to the IOC console"
|
|
45
|
+
),
|
|
43
46
|
reboot: bool = typer.Option(
|
|
44
47
|
True, "--reboot/--no-reboot", help="reboot the IOC first"
|
|
45
48
|
),
|
|
@@ -55,16 +58,21 @@ def start(
|
|
|
55
58
|
it detects that EPICS_HOST_ARCH==RTEMS-beatnik
|
|
56
59
|
|
|
57
60
|
args:
|
|
58
|
-
copy:
|
|
59
|
-
|
|
61
|
+
copy: Copy the RTEMS binaries to the IOCs TFTP and NFS directories first
|
|
62
|
+
connect: Connect to the IOC console after rebooting
|
|
63
|
+
reboot: Reboot the IOC once the binaries are copied and the connection is
|
|
64
|
+
made. Ignored if connect is False.
|
|
60
65
|
"""
|
|
61
|
-
|
|
66
|
+
report(
|
|
62
67
|
f"Remote control startup of RTEMS IOC {GLOBALS.IOC_NAME}"
|
|
63
68
|
f" at {GLOBALS.RTEMS_IOC_IP}"
|
|
64
69
|
)
|
|
65
70
|
if copy:
|
|
66
71
|
copy_rtems()
|
|
67
|
-
|
|
72
|
+
if connect:
|
|
73
|
+
ioc_connect(GLOBALS.RTEMS_CONSOLE, reboot=reboot)
|
|
74
|
+
else:
|
|
75
|
+
report("IOC console connection disabled. ")
|
|
68
76
|
|
|
69
77
|
|
|
70
78
|
@cli.command()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
functions for moving IOC assets into position for a remote IOC to access
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
import shutil
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from .globals import GLOBALS
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def copy_rtems():
|
|
13
|
+
"""
|
|
14
|
+
Copy RTEMS binaries to a location where the RTEMS IOC can access them
|
|
15
|
+
|
|
16
|
+
IMPORTANT: local_root and nfs_root are different perspectives on the same
|
|
17
|
+
folder.
|
|
18
|
+
local_root: where the IOC files will be placed from the
|
|
19
|
+
perspective of this IOC proxy service. This IOC proxy will
|
|
20
|
+
populate the folder for use by the RTEMS crate.
|
|
21
|
+
nfs_root: where the IOC files will be found from the perspective of a
|
|
22
|
+
a client to the nfsv2-tftp service. i.e. where the RTEMS crate
|
|
23
|
+
will look for them using NFS.
|
|
24
|
+
"""
|
|
25
|
+
local_root = GLOBALS.RTEMS_TFTP_PATH
|
|
26
|
+
nfs_root = Path("/iocs") / GLOBALS.IOC_NAME
|
|
27
|
+
|
|
28
|
+
# where to copy the Generic IOC folder to. This will contain the IOC binary
|
|
29
|
+
# and the files
|
|
30
|
+
dest_ioc = local_root / "ioc"
|
|
31
|
+
# where to copy the generated runtime assets to. This will contain
|
|
32
|
+
# st.cmd and ioc.db
|
|
33
|
+
dest_runtime = local_root / "runtime"
|
|
34
|
+
|
|
35
|
+
# TODO - perhaps do protocol files in this fashion for linux IOCs too,
|
|
36
|
+
# in which case this needs to go somewhere generic
|
|
37
|
+
protocol_folder = GLOBALS.RUNTIME / "protocol"
|
|
38
|
+
protocol_folder.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
protocol_files = GLOBALS.SUPPORT.glob("**/*.proto*")
|
|
40
|
+
for proto_file in protocol_files:
|
|
41
|
+
dest = protocol_folder / proto_file.name
|
|
42
|
+
shutil.copy(proto_file, dest)
|
|
43
|
+
|
|
44
|
+
# copy all the files needed for runtime into the PVC that is being shared
|
|
45
|
+
# over nfs/tftp by the nfsv2-tftp service
|
|
46
|
+
for folder in ["bin", "dbd"]:
|
|
47
|
+
shutil.copytree(
|
|
48
|
+
GLOBALS.IOC.readlink() / folder, dest_ioc / folder, dirs_exist_ok=True
|
|
49
|
+
)
|
|
50
|
+
shutil.copytree(GLOBALS.RUNTIME, dest_runtime, dirs_exist_ok=True)
|
|
51
|
+
|
|
52
|
+
# because we moved the ioc files we need to fix up startup script paths
|
|
53
|
+
startup = dest_runtime / "st.cmd"
|
|
54
|
+
cmd_txt = startup.read_text()
|
|
55
|
+
cmd_txt = re.sub("/epics/", f"{str(nfs_root)}/", cmd_txt)
|
|
56
|
+
startup.write_text(cmd_txt)
|
|
@@ -43,8 +43,16 @@ echo "
|
|
|
43
43
|
|
|
44
44
|
while true; do
|
|
45
45
|
inotifywait -e modify,create,delete,move -r $RTEMS_TFTP_PATH
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
echo 'rsyncing files to server'
|
|
47
|
+
date
|
|
48
|
+
for i in 1 2 3 ; do
|
|
49
|
+
# repeat because inotify fires on the first change of several
|
|
50
|
+
# don't copy the huge ioc binary file with symbols
|
|
51
|
+
rsync -rim --exclude bin/RTEMS-beatnik/ioc --delete /$RTEMS_TFTP_PATH/ \
|
|
52
|
+
"rsync://$RTEMS_TFTP_IP:12002/files/$IOC_NAME/"
|
|
53
|
+
sleep 1
|
|
54
|
+
done
|
|
55
|
+
echo 'rsync complete'
|
|
48
56
|
done
|
|
49
57
|
" > /tmp/rsync-background.sh
|
|
50
58
|
chmod +x /tmp/rsync-background.sh
|
|
@@ -48,18 +48,12 @@ class TelnetRTEMS:
|
|
|
48
48
|
signal.signal(signal.SIGINT, self.terminate)
|
|
49
49
|
signal.signal(signal.SIGTERM, self.terminate)
|
|
50
50
|
|
|
51
|
-
def report(self, message):
|
|
52
|
-
"""
|
|
53
|
-
print a message that is noticeable amongst all the other output
|
|
54
|
-
"""
|
|
55
|
-
print(f"\n>>>> {message} <<<<\n")
|
|
56
|
-
|
|
57
51
|
def terminate(self, signum, frame):
|
|
58
52
|
"""
|
|
59
53
|
Allow the user to terminate the connection with ctrl-c while the
|
|
60
54
|
pexpect child is running (but not once interactive telnet is started)
|
|
61
55
|
"""
|
|
62
|
-
|
|
56
|
+
report("Terminating")
|
|
63
57
|
exit(0)
|
|
64
58
|
|
|
65
59
|
def connect(self):
|
|
@@ -83,7 +77,7 @@ class TelnetRTEMS:
|
|
|
83
77
|
# if we timeout looking for failed connection that is good
|
|
84
78
|
pass
|
|
85
79
|
else:
|
|
86
|
-
|
|
80
|
+
report("Cannot connect to remote IOC, connection in use?")
|
|
87
81
|
raise CannotConnect
|
|
88
82
|
|
|
89
83
|
def check_prompt(self, retries=5) -> RtemsState:
|
|
@@ -108,16 +102,16 @@ class TelnetRTEMS:
|
|
|
108
102
|
# current state unknown. wait and retry
|
|
109
103
|
sleep(15)
|
|
110
104
|
else:
|
|
111
|
-
|
|
105
|
+
report("Currently in bootloader")
|
|
112
106
|
return RtemsState.MOT
|
|
113
107
|
else:
|
|
114
|
-
|
|
108
|
+
report("Currently in IOC shell")
|
|
115
109
|
return RtemsState.IOC
|
|
116
110
|
|
|
117
|
-
|
|
111
|
+
report("Retrying get current status")
|
|
118
112
|
retries -= 1
|
|
119
113
|
|
|
120
|
-
|
|
114
|
+
report("Current state UNKNOWN")
|
|
121
115
|
raise CannotConnect("Current state of remote IOC unknown")
|
|
122
116
|
|
|
123
117
|
def reboot(self, into: RtemsState):
|
|
@@ -127,7 +121,7 @@ class TelnetRTEMS:
|
|
|
127
121
|
"""
|
|
128
122
|
assert self._child, "must call connect before reboot"
|
|
129
123
|
|
|
130
|
-
|
|
124
|
+
report(f"Rebooting into {into.name}")
|
|
131
125
|
current_state = self.check_prompt()
|
|
132
126
|
if current_state == RtemsState.MOT:
|
|
133
127
|
self._child.sendline("reset")
|
|
@@ -162,8 +156,6 @@ class TelnetRTEMS:
|
|
|
162
156
|
self.reboot(RtemsState.IOC)
|
|
163
157
|
self._child.expect(self.IOC_STARTED, timeout=50)
|
|
164
158
|
|
|
165
|
-
self.report("press enter for IOC shell prompt")
|
|
166
|
-
|
|
167
159
|
def get_boot_prompt(self):
|
|
168
160
|
"""
|
|
169
161
|
Get to the bootloader prompt, if the IOC shell is running then exit
|
|
@@ -177,7 +169,7 @@ class TelnetRTEMS:
|
|
|
177
169
|
self.reboot(RtemsState.MOT)
|
|
178
170
|
self._child.expect(self.MOT_PROMPT, timeout=20)
|
|
179
171
|
|
|
180
|
-
|
|
172
|
+
report("press enter for bootloader prompt")
|
|
181
173
|
|
|
182
174
|
def close(self):
|
|
183
175
|
if self._child:
|
|
@@ -188,6 +180,13 @@ class TelnetRTEMS:
|
|
|
188
180
|
self.close()
|
|
189
181
|
|
|
190
182
|
|
|
183
|
+
def report(message):
|
|
184
|
+
"""
|
|
185
|
+
print a message that is noticeable amongst all the other output
|
|
186
|
+
"""
|
|
187
|
+
print(f"\n>>>> {message} <<<<\n")
|
|
188
|
+
|
|
189
|
+
|
|
191
190
|
def ioc_connect(host_and_port: str, reboot: bool = False):
|
|
192
191
|
"""
|
|
193
192
|
Entrypoint to make a connection to an RTEMS IOC over telnet.
|
|
@@ -201,10 +200,14 @@ def ioc_connect(host_and_port: str, reboot: bool = False):
|
|
|
201
200
|
|
|
202
201
|
try:
|
|
203
202
|
telnet.connect()
|
|
204
|
-
|
|
203
|
+
if reboot:
|
|
204
|
+
telnet.get_epics_prompt()
|
|
205
|
+
else:
|
|
206
|
+
report("Auto reboot disabled. Skipping reboot")
|
|
205
207
|
except (CannotConnect, pexpect.exceptions.TIMEOUT):
|
|
206
|
-
|
|
208
|
+
report("Connection failed. Exiting")
|
|
207
209
|
telnet.close()
|
|
208
210
|
else:
|
|
209
211
|
telnet.close()
|
|
212
|
+
report("Connecting to IOC console, hit enter for a prompt")
|
|
210
213
|
run_command(telnet.command)
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
functions for moving IOC assets into position for a remote IOC to access
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import re
|
|
6
|
-
import shutil
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
|
|
9
|
-
from .globals import GLOBALS
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def copy_rtems():
|
|
13
|
-
"""
|
|
14
|
-
Copy RTEMS binaries to a location where the RTEMS IOC can access them
|
|
15
|
-
"""
|
|
16
|
-
# root of pvc mount into which we copy the IOC files for the RTEMS IOC to access
|
|
17
|
-
root = GLOBALS.RTEMS_TFTP_PATH
|
|
18
|
-
# root of the path that the RTEMS IOC expects to find the IOC files
|
|
19
|
-
RTEMS_TFTP_PATH = Path("/iocs") / GLOBALS.IOC_NAME
|
|
20
|
-
# where to copy the Generic IOC folder to (at present only holds the dbd folder)
|
|
21
|
-
ioc_dest = root / "ioc"
|
|
22
|
-
# where to copy the generated runtime assets to (st.cmd and ioc.db)
|
|
23
|
-
dest_runtime = root / "runtime"
|
|
24
|
-
|
|
25
|
-
# TODO - perhaps do this for linux IOCs too - in which case this needs
|
|
26
|
-
# to go somewhere generic
|
|
27
|
-
protocol_folder = GLOBALS.RUNTIME / "protocol"
|
|
28
|
-
protocol_folder.mkdir(parents=True, exist_ok=True)
|
|
29
|
-
protocol_files = GLOBALS.SUPPORT.glob("**/*.proto*")
|
|
30
|
-
for proto_file in protocol_files:
|
|
31
|
-
dest = protocol_folder / proto_file.name
|
|
32
|
-
shutil.copy(proto_file, dest)
|
|
33
|
-
|
|
34
|
-
# move all the files needed for runtime into the PVC that is being shared
|
|
35
|
-
# over nfs/tftp by the nfsv2-tftp service
|
|
36
|
-
ioc_src = GLOBALS.IOC.readlink()
|
|
37
|
-
dbd_src = ioc_src / "dbd"
|
|
38
|
-
dbd_dest = ioc_dest / "dbd"
|
|
39
|
-
binary = Path("bin/RTEMS-beatnik/ioc.boot")
|
|
40
|
-
bin_rtems_src = ioc_src / binary
|
|
41
|
-
bin_rtems_dest = ioc_dest / binary
|
|
42
|
-
bin_rtems_dest.parent.mkdir(parents=True, exist_ok=True)
|
|
43
|
-
|
|
44
|
-
shutil.copytree(dbd_src, dbd_dest, symlinks=True, dirs_exist_ok=True)
|
|
45
|
-
shutil.copy(bin_rtems_src, bin_rtems_dest)
|
|
46
|
-
shutil.copytree(GLOBALS.RUNTIME, dest_runtime, dirs_exist_ok=True)
|
|
47
|
-
|
|
48
|
-
# because we moved the ioc files we need to fix up startup script paths
|
|
49
|
-
startup = dest_runtime / "st.cmd"
|
|
50
|
-
cmd_txt = startup.read_text()
|
|
51
|
-
cmd_txt = re.sub("/epics/", f"{str(RTEMS_TFTP_PATH)}/", cmd_txt)
|
|
52
|
-
# also fix up the protocol path to point to protocol_folder
|
|
53
|
-
cmd_txt = (
|
|
54
|
-
cmd_txt + f'\nepicsEnvSet("STREAM_PROTOCOL_PATH", "{str(protocol_folder)}")\n'
|
|
55
|
-
)
|
|
56
|
-
startup.write_text(cmd_txt)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rtems_proxy-0.6.0 → rtems_proxy-0.6.2}/.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
|