Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
"""
Utils to run commands on remote server
Copyright (C) 2010-2020 Cr@ns <roots@crans.org>
Authors : Daniel Stan <daniel.stan@crans.org>
Vincent Le Gallic <legallic@crans.org>
Alexandre Iooss <erdnaxe@crans.org>
SPDX-License-Identifier: GPL-3.0-or-later
"""
from functools import lru_cache
import json
import logging
from paramiko.client import SSHClient
from paramiko.ssh_exception import SSHException
from .locale import _
# Local logger
log = logging.getLogger(__name__)
@lru_cache()
def create_ssh_client(host):
"""
Create a SSH client with paramiko module
"""
# Create SSH client with system host keys and agent
client = SSHClient()
client.load_system_host_keys()
try:
client.connect(host)
except SSHException:
log.error(_("An error occured during SSH connection, debug with -vv"))
raise
return client
def remote_command(options, command, arg=None, stdin_contents=None):
"""
Execute remote command and return output
"""
if "host" not in options.serverdata:
log.error("Missing parameter `host` in active server configuration")
exit(1)
client = create_ssh_client(str(options.serverdata['host']))
# Build command
if "remote_cmd" not in options.serverdata:
log.error("Missing parameter `remote_cmd` in active server configuration")
exit(1)
remote_cmd = options.serverdata['remote_cmd'] + " " + command
if arg:
remote_cmd += " " + arg
# Run command and timeout after 10s
log.info(_("Running command `%s`") % remote_cmd)
stdin, stdout, stderr = client.exec_command(remote_cmd, timeout=10)
# Write
if stdin_contents is not None:
log.info(_("Writing to stdin: %s") % stdin_contents)
stdin.write(json.dumps(stdin_contents))
stdin.flush()
# If the server is not expected to exit, then exit now
if stdin_contents:
return
# Return code == 0 if success
ret = stdout.channel.recv_exit_status()
if ret != 0:
err = ""
if stderr.channel.recv_stderr_ready():
err = stderr.read()
log.error(_("Wrong server return code %s, error is %s") % (ret, err))
exit(ret)
# Decode directly read buffer
try:
answer = json.load(stdout)
except ValueError:
log.error(_("Error while parsing JSON"))
exit(42)
log.debug(_("Server returned %s") % answer)
return answer