python-compute/node_agent/cli/vmexec.py

85 lines
2.4 KiB
Python
Raw Normal View History

2023-07-22 23:59:49 +03:00
"""
Execute shell commands on guest via guest agent.
Usage: na-vmexec [options] <machine> <command>
Options:
2023-09-02 00:52:28 +03:00
-c, --config <file> config file [default: /etc/node-agent/config.yaml]
-l, --loglvl <lvl> logging level
-s, --shell <shell> guest shell [default: /bin/sh]
2023-07-22 23:59:49 +03:00
-t, --timeout <sec> QEMU timeout in seconds to stop polling command status [default: 60]
2023-09-02 00:52:28 +03:00
-p, --pid <PID> PID on guest to poll output
2023-07-22 23:59:49 +03:00
"""
import logging
2023-08-24 22:36:12 +03:00
import pathlib
import sys
2023-07-22 23:59:49 +03:00
2023-08-31 20:37:41 +03:00
import libvirt
2023-07-22 23:59:49 +03:00
from docopt import docopt
2023-08-24 22:36:12 +03:00
from ..session import LibvirtSession
2023-09-02 00:52:28 +03:00
from ..vm import GuestAgent
from ..exceptions import GuestAgentError, VMNotFound
2023-07-22 23:59:49 +03:00
logger = logging.getLogger(__name__)
levels = logging.getLevelNamesMapping()
2023-08-31 20:37:41 +03:00
libvirt.registerErrorHandler(lambda userdata, err: None, ctx=None)
2023-07-22 23:59:49 +03:00
class Color:
RED = '\033[31m'
GREEN = '\033[32m'
YELLOW = '\033[33m'
NONE = '\033[0m'
2023-08-24 22:36:12 +03:00
# TODO: Add STDIN support e.g.: cat something.sh | na-vmexec vmname bash
2023-07-22 23:59:49 +03:00
def cli():
args = docopt(__doc__)
config = pathlib.Path(args['--config']) or None
2023-07-29 15:10:30 +03:00
loglvl = None
2023-07-28 01:01:32 +03:00
machine = args['<machine>']
2023-07-22 23:59:49 +03:00
2023-07-29 15:10:30 +03:00
if args['--loglvl']:
loglvl = args['--loglvl'].upper()
2023-07-22 23:59:49 +03:00
if loglvl in levels:
logging.basicConfig(level=levels[loglvl])
2023-08-31 20:37:41 +03:00
with LibvirtSession() as session:
2023-07-22 23:59:49 +03:00
shell = args['--shell']
cmd = args['<command>']
try:
2023-08-31 20:37:41 +03:00
ga = session.get_guest_agent(machine)
2023-07-22 23:59:49 +03:00
exited, exitcode, stdout, stderr = ga.shellexec(
2023-08-24 22:36:12 +03:00
cmd, executable=shell, capture_output=True, decode_output=True,
timeout=int(args['--timeout']))
2023-09-02 00:52:28 +03:00
except GuestAgentError as gaerr:
errmsg = f'{Color.RED}{gaerr}{Color.NONE}'
if str(gaerr).startswith('Polling command pid='):
2023-08-24 22:36:12 +03:00
errmsg = (errmsg + Color.YELLOW +
2023-09-02 00:52:28 +03:00
'\n[NOTE: command may still running on guest '
'pid={ga.last_pid}]' + Color.NONE)
2023-07-22 23:59:49 +03:00
sys.exit(errmsg)
except VMNotFound as err:
2023-08-24 22:36:12 +03:00
sys.exit(f'{Color.RED}VM {machine} not found{Color.NONE}')
2023-07-22 23:59:49 +03:00
if not exited:
2023-09-02 00:52:28 +03:00
print(Color.YELLOW +
'[NOTE: command may still running on guest pid={ga.last_pid}]' +
Color.NONE, file=sys.stderr)
2023-07-22 23:59:49 +03:00
if stderr:
2023-09-02 00:52:28 +03:00
print(stderr.strip(), file=sys.stderr)
2023-07-22 23:59:49 +03:00
if stdout:
2023-09-02 00:52:28 +03:00
print(stdout.strip(), file=sys.stdout)
2023-07-29 15:10:30 +03:00
sys.exit(exitcode)
2023-07-22 23:59:49 +03:00
2023-08-24 22:36:12 +03:00
2023-07-22 23:59:49 +03:00
if __name__ == '__main__':
cli()