Skip to content

Commit

Permalink
Merge pull request #1261 from nicholasyang2022/ssh-agent
Browse files Browse the repository at this point in the history
[crmsh-4.6] Dev: bootstrap: implement ssh-agent support (jsc#PED-5774)
  • Loading branch information
liangxin1300 authored Nov 23, 2023
2 parents 373ddb9 + 6a49af9 commit 50296e9
Show file tree
Hide file tree
Showing 22 changed files with 877 additions and 284 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/crmsh-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,18 @@ jobs:
$DOCKER_SCRIPT `$GET_INDEX_OF user_access`
- uses: codecov/codecov-action@v3

functional_test_ssh_agent:
runs-on: ubuntu-20.04
timeout-minutes: 40
steps:
- uses: actions/checkout@v3
- name: functional test for user access
run: |
echo '{ "exec-opts": ["native.cgroupdriver=systemd"] }' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker.service
$DOCKER_SCRIPT `$GET_INDEX_OF ssh_agent` && $DOCKER_SCRIPT -d && $DOCKER_SCRIPT -u `$GET_INDEX_OF ssh_agent`
- uses: codecov/codecov-action@v3

original_regression_test:
runs-on: ubuntu-20.04
timeout-minutes: 40
Expand Down
4 changes: 2 additions & 2 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ coverage:
codecov:
token: 16b01c29-3b23-4923-b33a-4d26a49d80c4
notify:
after_n_builds: 22
after_n_builds: 23
comment:
after_n_builds: 22
after_n_builds: 23
431 changes: 280 additions & 151 deletions crmsh/bootstrap.py

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crmsh/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ def get(self, value):
'pager': opt_program('PAGER', ('less', 'more', 'pg')),
'user': opt_string(''),
'hosts': opt_list([]), # 'alice@host1, bob@host2'
'no_generating_ssh_key': opt_boolean('no'),
'skill_level': opt_choice('expert', ('operator', 'administrator', 'expert')),
'sort_elements': opt_boolean('yes'),
'check_frequency': opt_choice('always', ('always', 'on-verify', 'never')),
Expand Down
10 changes: 4 additions & 6 deletions crmsh/healthcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,10 @@ def fix_cluster(self, nodes: typing.Iterable[str], ask: typing.Callable[[str], N
remote_nodes = set(nodes)
remote_nodes.remove(local_node)
remote_nodes = list(remote_nodes)
local_user = crmsh.utils.user_pair_for_ssh(remote_nodes[0])[0]
crmsh.bootstrap.init_ssh_impl(
local_user,
None,
[(crmsh.utils.user_pair_for_ssh(node)[1], node) for node in remote_nodes],
)
crmsh.bootstrap.configure_ssh_key('hacluster')
crmsh.bootstrap.swap_key_for_hacluster(remote_nodes)
for node in remote_nodes:
crmsh.bootstrap.change_user_shell('hacluster', node)


def main_check_local(args) -> int:
Expand Down
30 changes: 18 additions & 12 deletions crmsh/prun/prun.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,17 @@ def pcopy_to_remote(
script = "put {} '{}' '{}'\n".format(flags, src, dst)
ssh = None
try:
ssh = tempfile.NamedTemporaryFile('w', encoding='utf-8', delete=False)
os.fchmod(ssh.fileno(), 0o700)
# sftp -S does not parse args, it accepts only a single executable. So we create one.
ssh.write(f'''#!/bin/sh
if local_sudoer == crmsh.userdir.getuser():
tasks = [_build_copy_task('', script, host) for host in hosts]
else:
ssh = tempfile.NamedTemporaryFile('w', encoding='utf-8', delete=False)
os.fchmod(ssh.fileno(), 0o700)
ssh.write(f'''#!/bin/sh
exec sudo -u {local_sudoer} ssh "$@"''')
# It is necessary to close the file before executing, or we will get an EBUSY.
ssh.close()
tasks = [_build_copy_task("-S '{}'".format(ssh.name), script, host) for host in hosts]
ssh.close()
tasks = [_build_copy_task("-S '{}'".format(ssh.name), script, host) for host in hosts]
runner = Runner(concurrency)
for task in tasks:
runner.add_task(task)
Expand Down Expand Up @@ -209,13 +212,16 @@ def pfetch_from_remote(
local_sudoer, _ = UserOfHost.instance().user_pair_for_ssh(hosts[0])
ssh = None
try:
ssh = tempfile.NamedTemporaryFile('w', encoding='utf-8', delete=False)
os.fchmod(ssh.fileno(), 0o700)
ssh.write(f'''#!/bin/sh
exec sudo -u {local_sudoer} ssh "$@"''')
# It is necessary to close the file before executing
ssh.close()
tasks = [_build_fetch_task("-S '{}'".format(ssh.name), host, src, dst, flags) for host in hosts]
if local_sudoer == crmsh.userdir.getuser():
tasks = [_build_fetch_task('', host, src, dst, flags) for host in hosts]
else:
ssh = tempfile.NamedTemporaryFile('w', encoding='utf-8', delete=False)
os.fchmod(ssh.fileno(), 0o700)
ssh.write(f'''#!/bin/sh
exec sudo -u {local_sudoer} ssh "$@"''')
# It is necessary to close the file before executing
ssh.close()
tasks = [_build_fetch_task("-S '{}'".format(ssh.name), host, src, dst, flags) for host in hosts]
runner = Runner(concurrency)
for task in tasks:
runner.add_task(task)
Expand Down
10 changes: 9 additions & 1 deletion crmsh/report/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import pwd
import datetime

import crmsh.user_of_host
from crmsh import log, sh
from crmsh import utils as crmutils
from crmsh.report import constants, utillib
Expand Down Expand Up @@ -56,7 +57,14 @@ def collect_ratraces():
"""
# since the "trace_dir" attribute been removed from cib after untrace
# need to parse crmsh log file to extract custom trace ra log directory on each node
shell = sh.cluster_shell()
if crmsh.user_of_host.instance().use_ssh_agent():
shell = sh.ClusterShell(
sh.LocalShell(additional_environ={'SSH_AUTH_SOCK': os.environ.get('SSH_AUTH_SOCK', '')}),
crmsh.user_of_host.instance(),
forward_ssh_agent=True,
)
else:
shell = sh.cluster_shell()
log_contents = ""
cmd = "grep 'INFO: Trace for .* is written to ' {}*|grep -v 'collect'".format(log.CRMSH_LOG_FILE)
for node in crmutils.list_cluster_nodes():
Expand Down
2 changes: 1 addition & 1 deletion crmsh/report/utillib.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ def get_distro_info():
res = re.search("PRETTY_NAME=\"(.*)\"", read_from_file(constants.OSRELEASE))
elif which("lsb_release"):
logger.debug("Using lsb_release to get distribution info")
out = sh.cluster_shell().get_stdout_or_raise_error("lsb_release -d")
out = sh.LocalShell().get_stdout_or_raise_error("lsb_release -d")
res = re.search("Description:\s+(.*)", out)
return res.group(1) if res else "Unknown"

Expand Down
Loading

0 comments on commit 50296e9

Please sign in to comment.