Python: add utility function for retrieving port redirection

Slightly different versions for the same utility code are currently
present on different locations.  This unifies them all, giving
preference to the version from virtiofs_submounts.py, because of the
last tweaks added to it.

While at it, this adds a "qemu.utils" module to host the utility
function and a test.

Signed-off-by: Cleber Rosa <crosa@redhat.com>
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
Message-Id: <20210412044644.55083-4-crosa@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
[Squashed in below fix. --js]
Signed-off-by: John Snow <jsnow@redhat.com>
Signed-off-by: Cleber Rosa <crosa@redhat.com>
Message-Id: <20210601154546.130870-2-crosa@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
This commit is contained in:
Cleber Rosa 2021-04-12 00:46:36 -04:00 committed by John Snow
parent c028691e65
commit 976218cbe7
5 changed files with 79 additions and 33 deletions

33
python/qemu/utils.py Normal file
View File

@ -0,0 +1,33 @@
"""
QEMU utility library
This offers miscellaneous utility functions, which may not be easily
distinguishable or numerous to be in their own module.
"""
# Copyright (C) 2021 Red Hat Inc.
#
# Authors:
# Cleber Rosa <crosa@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
#
import re
from typing import Optional
def get_info_usernet_hostfwd_port(info_usernet_output: str) -> Optional[int]:
"""
Returns the port given to the hostfwd parameter via info usernet
:param info_usernet_output: output generated by hmp command "info usernet"
:return: the port number allocated by the hostfwd option
"""
for line in info_usernet_output.split('\r\n'):
regex = r'TCP.HOST_FORWARD.*127\.0\.0\.1\s+(\d+)\s+10\.'
match = re.search(regex, line)
if match is not None:
return int(match[1])
return None

View File

@ -0,0 +1,29 @@
# Test for the hmp command "info usernet"
#
# Copyright (c) 2021 Red Hat, Inc.
#
# Author:
# Cleber Rosa <crosa@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2 or
# later. See the COPYING file in the top-level directory.
from avocado_qemu import Test
from qemu.utils import get_info_usernet_hostfwd_port
class InfoUsernet(Test):
def test_hostfwd(self):
self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22')
self.vm.launch()
res = self.vm.command('human-monitor-command',
command_line='info usernet')
port = get_info_usernet_hostfwd_port(res)
self.assertIsNotNone(port,
('"info usernet" output content does not seem to '
'contain the redirected port'))
self.assertGreater(port, 0,
('Found a redirected port that is not greater than'
' zero'))

View File

@ -18,6 +18,8 @@ from avocado.utils import process
from avocado.utils import archive
from avocado.utils import ssh
from qemu.utils import get_info_usernet_hostfwd_port
class LinuxSSH(Test):
@ -70,18 +72,14 @@ class LinuxSSH(Test):
def setUp(self):
super(LinuxSSH, self).setUp()
def get_portfwd(self):
res = self.vm.command('human-monitor-command',
command_line='info usernet')
line = res.split('\r\n')[2]
port = re.split(r'.*TCP.HOST_FORWARD.*127\.0\.0\.1 (\d+)\s+10\..*',
line)[1]
self.log.debug("sshd listening on port:" + port)
return port
def ssh_connect(self, username, password):
self.ssh_logger = logging.getLogger('ssh')
port = self.get_portfwd()
res = self.vm.command('human-monitor-command',
command_line='info usernet')
port = get_info_usernet_hostfwd_port(res)
if not port:
self.cancel("Failed to retrieve SSH port")
self.log.debug("sshd listening on port:" + port)
self.ssh_session = ssh.Session(self.VM_IP, port=int(port),
user=username, password=password)
for i in range(10):

View File

@ -9,6 +9,8 @@ from avocado_qemu import LinuxTest, BUILD_DIR
from avocado_qemu import wait_for_console_pattern
from avocado.utils import ssh
from qemu.utils import get_info_usernet_hostfwd_port
def run_cmd(args):
subp = subprocess.Popen(args,
@ -73,27 +75,14 @@ class VirtiofsSubmountsTest(LinuxTest):
:avocado: tags=accel:kvm
"""
def get_portfwd(self):
port = None
def ssh_connect(self, username, keyfile):
self.ssh_logger = logging.getLogger('ssh')
res = self.vm.command('human-monitor-command',
command_line='info usernet')
for line in res.split('\r\n'):
match = \
re.search(r'TCP.HOST_FORWARD.*127\.0\.0\.1\s+(\d+)\s+10\.',
line)
if match is not None:
port = int(match[1])
break
port = get_info_usernet_hostfwd_port(res)
self.assertIsNotNone(port)
self.assertGreater(port, 0)
self.log.debug('sshd listening on port: %d', port)
return port
def ssh_connect(self, username, keyfile):
self.ssh_logger = logging.getLogger('ssh')
port = self.get_portfwd()
self.ssh_session = ssh.Session('127.0.0.1', port=port,
user=username, key=keyfile)
for i in range(10):

View File

@ -21,6 +21,7 @@ import datetime
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
from qemu.accel import kvm_available
from qemu.machine import QEMUMachine
from qemu.utils import get_info_usernet_hostfwd_port
import subprocess
import hashlib
import argparse
@ -227,7 +228,7 @@ class BaseVM(object):
"-o", "UserKnownHostsFile=" + os.devnull,
"-o",
"ConnectTimeout={}".format(self._config["ssh_timeout"]),
"-p", self.ssh_port, "-i", self._ssh_tmp_key_file]
"-p", str(self.ssh_port), "-i", self._ssh_tmp_key_file]
# If not in debug mode, set ssh to quiet mode to
# avoid printing the results of commands.
if not self.debug:
@ -305,12 +306,8 @@ class BaseVM(object):
# Init console so we can start consuming the chars.
self.console_init()
usernet_info = guest.qmp("human-monitor-command",
command_line="info usernet")
self.ssh_port = None
for l in usernet_info["return"].splitlines():
fields = l.split()
if "TCP[HOST_FORWARD]" in fields and "22" in fields:
self.ssh_port = l.split()[3]
command_line="info usernet").get("return")
self.ssh_port = get_info_usernet_hostfwd_port(usernet_info)
if not self.ssh_port:
raise Exception("Cannot find ssh port from 'info usernet':\n%s" % \
usernet_info)