Skip to content

Commit 05da45b

Browse files
[crmsh-4.5] Dev: bootstrap: more robust implementation for ssh_merge (bsc#1230530) (#1575)
* Do not use legacy `write_remote_file`, which does not work well with `_guess_user_for_ssh`. * Implement deduplication when merging known_hosts
2 parents 21fd822 + 85ace09 commit 05da45b

File tree

2 files changed

+18
-33
lines changed

2 files changed

+18
-33
lines changed

crmsh/bootstrap.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# TODO: Make csync2 usage optional
1313
# TODO: Configuration file for bootstrap?
1414
import codecs
15+
import io
1516
import os
1617
import subprocess
1718
import sys
@@ -25,15 +26,13 @@
2526

2627
import yaml
2728
import socket
28-
from tempfile import mktemp
2929
from string import Template
3030
from lxml import etree
3131

32-
import crmsh.parallax
3332
from . import config, constants
3433
from . import utils
3534
from . import xmlutil
36-
from .cibconfig import mkset_obj, cib_factory
35+
from .cibconfig import cib_factory
3736
from . import corosync
3837
from . import tmpfiles
3938
from . import lock
@@ -855,8 +854,8 @@ def init_ssh_impl(local_user: str, user_node_list: typing.List[typing.Tuple[str,
855854
public_key_list.append(swap_public_ssh_key(node, local_user, remote_user, local_user, remote_user, add=True))
856855
hacluster_public_key_list.append(swap_public_ssh_key(node, 'hacluster', 'hacluster', local_user, remote_user, add=True))
857856
if len(user_node_list) > 1:
858-
shell_script = _merge_authorized_keys(public_key_list)
859-
hacluster_shell_script = _merge_authorized_keys(hacluster_public_key_list)
857+
shell_script = _merge_line_into_file('~/.ssh/authorized_keys', public_key_list).encode('utf-8')
858+
hacluster_shell_script = _merge_line_into_file('~/.ssh/authorized_keys', hacluster_public_key_list).encode('utf-8')
860859
for i, (remote_user, node) in enumerate(user_node_list):
861860
result = utils.su_subprocess_run(
862861
local_user,
@@ -885,16 +884,18 @@ def init_ssh_impl(local_user: str, user_node_list: typing.List[typing.Tuple[str,
885884
change_user_shell('hacluster', node)
886885

887886

888-
def _merge_authorized_keys(keys: typing.List[str]) -> bytes:
889-
shell_script = '''for key in "${keys[@]}"; do
890-
grep -F "$key" ~/.ssh/authorized_keys > /dev/null || sed -i "\\$a $key" ~/.ssh/authorized_keys
891-
done'''
892-
keys_definition = ("keys+=('{}')\n".format(key) for key in keys)
893-
buf = bytearray()
887+
def _merge_line_into_file(path: str, lines: typing.Iterable[str]) -> str:
888+
shell_script = '''[ -e "$path" ] || echo '# created by crmsh' > "$path"
889+
for key in "${keys[@]}"; do
890+
grep -F "$key" "$path" > /dev/null || sed -i "\\$a $key" "$path"
891+
done'''
892+
keys_definition = ("keys+=('{}')\n".format(key) for key in lines)
893+
buf = io.StringIO()
894+
buf.write(f'path={path}\n')
894895
for item in keys_definition:
895-
buf.extend(item.encode('utf-8'))
896-
buf.extend(shell_script.encode('utf-8'))
897-
return buf
896+
buf.write(item)
897+
buf.write(shell_script)
898+
return buf.getvalue()
898899

899900

900901
def _fetch_core_hosts(local_user, remote_user, remote_host) -> typing.Tuple[typing.List[str], typing.List[str]]:
@@ -1832,7 +1833,7 @@ def join_ssh_merge(cluster_node, remote_user):
18321833
rc, _, _ = utils.get_stdout_stderr_as_local_sudoer("ssh {} {} true".format(SSH_OPTION, utils.this_node()))
18331834
assert rc == 0
18341835

1835-
known_hosts_new = set()
1836+
known_hosts_new: set[str] = set()
18361837

18371838
cat_cmd = "[ -e ~/.ssh/known_hosts ] && cat ~/.ssh/known_hosts || true"
18381839
#logger_utils.log_only_to_file("parallax.call {} : {}".format(hosts, cat_cmd))
@@ -1842,10 +1843,9 @@ def join_ssh_merge(cluster_node, remote_user):
18421843
known_hosts_new.update((utils.to_ascii(known_hosts_content) or "").splitlines())
18431844

18441845
if known_hosts_new:
1845-
hoststxt = "\n".join(sorted(known_hosts_new))
1846-
#results = parallax.parallax_copy(hosts, tmpf, known_hosts_path, strict=False)
1846+
script = _merge_line_into_file('~/.ssh/known_hosts', known_hosts_new)
18471847
for host in hosts:
1848-
utils.write_remote_file(hoststxt, "~/.ssh/known_hosts", utils.user_of(host), remote=host)
1848+
utils.get_stdout_or_raise_error(script, remote=host)
18491849

18501850

18511851
def update_expected_votes():

crmsh/utils.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -776,21 +776,6 @@ def str2file(s, fname, mod=0o644):
776776
return False
777777
return True
778778

779-
def write_remote_file(text, tofile, user, remote):
780-
shell_script = f'''cat >> {tofile} << EOF
781-
{text}
782-
EOF
783-
'''
784-
result = subprocess_run_auto_ssh_no_input(
785-
shell_script,
786-
remote,
787-
user,
788-
stdout=subprocess.DEVNULL,
789-
stderr=subprocess.PIPE,
790-
)
791-
if result.returncode != 0:
792-
raise ValueError("Failed to write to {}@{}/{}: {}".format(user, remote, tofile, result.stdout.decode('utf-8')))
793-
794779
def copy_remote_textfile(remote_user, remote_node, remote_text_file, local_path):
795780
"""
796781
scp might lack permissions to copy the file for a non-root user.

0 commit comments

Comments
 (0)