Skip to content

Commit

Permalink
passt: fix tests on s390x
Browse files Browse the repository at this point in the history
1. s390x doesn't have ACPI
2. s390x virtual interface name inside VM is encX
3. Remove unsupported DAC security driver for unprivileged user
   if present
4. Pass 'vm_iface' to 'passt.check_vm_ip' to avoid default value
   with wrong interface naming scheme
5. passt/check_nameserver: remove interface name from ipv6 entry as
   it might be different between host and guest
6. passt/check_default_gw: let us select which entry to choose because
   utils_net.get_default_gateway might return more than one, e.g. with
   multipath routes or when there's more than one interface on the host;
   same for passt/check_connection
7. passt/check_port_listen: only check for partial process user "'passt"
   because on x86_64 there's specializatoin 'passt.avx2' but on s390x it's
   just 'passt'
8. Don't use utils_net.get_host_ip_address because it doesn't let us choose
   which interface to get the ip address from; use utils_net.get_ip_address_by_interface
   instead

Signed-off-by: Sebastian Mitterle <[email protected]>
  • Loading branch information
smitterl committed Oct 16, 2023
1 parent 7d608a6 commit d5aefca
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
type = passt_attach_detach
func_supported_since_libvirt_ver = (9, 0, 0)
host_iface =
host_iface_index =
outside_ip = 'www.redhat.com'
start_vm = no
mtu = 65520
Expand Down Expand Up @@ -45,3 +46,6 @@
conn_check_args_1 = ('TCP6', 'localhost', 31339, 41339, True, None)
conn_check_args_2 = ('UDP4', 'localhost', 2025, 2025, True, None)
conn_check_args_3 = ('UDP6', 'localhost', 2025, 2025, True, None)
s390-virtio:
vm_iface = enc1
iface_attrs = {'model': 'virtio', 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}}
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@
conn_check_args_1 = ('TCP6', server_default_gw_v6, vm_c_iface, 41335, 41335)
conn_check_args_2 = ('UDP4', server_default_gw, None, 21335, 21335)
conn_check_args_3 = ('UDP6', server_default_gw_v6, vm_c_iface, 21335, 21335)
s390-virtio:
vm_c_iface = enc1
iface_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'type_name': 'user', **${portForwards}}
iface_c_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'type_name': 'user'}
6 changes: 6 additions & 0 deletions libvirt/tests/cfg/virtual_network/passt/passt_function.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, 'type_name': 'user', 'backend': {'type': 'passt'}, 'source': {'dev': '${host_iface}'}}
vm_iface = eno1
vm_ping_outside = pass
s390-virtio:
iface_attrs = {'model': 'virtio', 'type_name': 'user', 'backend': {'type': 'passt'}, 'source': {'dev': '${host_iface}'}}
vm_iface = enc1
- ip_portfw:
alias = {'name': 'ua-c87b89ff-b769-4abc-921f-30d42d7aec5b'}
backend = {'type': 'passt'}
Expand Down Expand Up @@ -49,3 +52,6 @@
conn_check_args_7 = ('UDP4', 'localhost', 2025, 2025, True, None)
conn_check_args_8 = ('UDP6', host_ip_v6, 4431, 4432, True, None)
conn_check_args_9 = ('UDP6', '::1', 4431, 4432, False, None)
s390-virtio:
iface_attrs = {'model': 'virtio', 'ips': ${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, 'alias': ${alias}, 'type_name': 'user', 'portForwards': ${portForwards}}
vm_iface = enc1
3 changes: 3 additions & 0 deletions libvirt/tests/cfg/virtual_network/passt/passt_reconnect.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@
conn_check_args_1 = ('TCP6', 'localhost', 31339, 41339, True, None)
conn_check_args_2 = ('UDP4', 'localhost', 2025, 2025, True, None)
conn_check_args_3 = ('UDP6', 'localhost', 2025, 2025, True, None)
s390-virtio:
vm_iface = enc1
iface_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, **${alias}, 'type_name': 'user', **${portForwards}}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
iface_attrs = {'model': 'virtio', 'acpi': {'index': '1'}, **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, **${alias}, 'type_name': 'user', **${portForwards}}
ipv6_prefix = 128
vm_iface = eno1
s390-virtio:
vm_iface = enc1
iface_attrs = {'model': 'virtio', **${ips}, 'backend': ${backend}, 'source': {'dev': '${host_iface}'}, **${alias}, 'type_name': 'user', **${portForwards}}
variants file_size:
- 10M:
bs = 1M
Expand Down
18 changes: 10 additions & 8 deletions libvirt/tests/src/virtual_network/passt/passt_attach_detach.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,18 @@ def run(test, params, env):
scenario = params.get('scenario')
virsh_uri = params.get('virsh_uri')
add_iface = 'yes' == params.get('add_iface', 'no')
host_ip = utils_net.get_host_ip_address(ip_ver='ipv4')
host_ip_v6 = utils_net.get_host_ip_address(ip_ver='ipv6')
host_iface = params.get('host_iface')
host_iface = host_iface if host_iface else utils_net.get_net_if(
state="UP")[0]
host_iface_index = int(params.get('host_iface_index', 0))
host_ip = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv4')
host_ip_v6 = utils_net.get_ip_address_by_interface(host_iface, ip_ver='ipv6')
iface_attrs = eval(params.get('iface_attrs'))
params['socket_dir'] = socket_dir = eval(params.get('socket_dir'))
params['proc_checks'] = proc_checks = eval(params.get('proc_checks', '{}'))
vm_iface = params.get('vm_iface', 'eno1')
mtu = params.get('mtu')
outside_ip = params.get('outside_ip')
host_iface = params.get('host_iface')
host_iface = host_iface if host_iface else utils_net.get_net_if(
state="UP")[0]
log_file = f'/run/user/{user_id}/passt.log'
iface_attrs['backend']['logFile'] = log_file
iface_attrs['source']['dev'] = host_iface
Expand Down Expand Up @@ -124,9 +125,9 @@ def run(test, params, env):
test.fail(f'Logfile of passt "{log_file}" not created')

session = vm.wait_for_serial_login(timeout=60)
passt.check_vm_ip(iface_attrs, session, host_iface)
passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface)
passt.check_vm_mtu(session, vm_iface, mtu)
passt.check_default_gw(session)
passt.check_default_gw(session, host_iface_index)
passt.check_nameserver(session)

ips = {
Expand All @@ -138,7 +139,8 @@ def run(test, params, env):
firewalld.stop()
LOG.debug(f'Service status of firewalld: {firewalld.status()}')
passt.check_connection(vm, vm_iface,
['TCP4', 'TCP6', 'UDP4', 'UDP6'])
['TCP4', 'TCP6', 'UDP4', 'UDP6'],
host_iface_index)

if 'portForwards' in iface_attrs:
passt.check_portforward(vm, host_ip, params)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,46 @@ def run(test, params, env):
root = 'root_user' == params.get('user_type', '')
if root:
vm_name = params.get('main_vm')
vm = env.get_vm(vm_name)
vm_c = env.get_vm(params.get('vm_c_name'))
vm_c_name = params.get('vm_c_name')
virsh_ins = virsh
else:
test_user = params.get('test_user', '')
test_passwd = params.get('test_passwd', '')
vm_name = params.get('unpr_vm_name')
uri = f'qemu+ssh://{test_user}@localhost/session'
virsh_ins = virsh.VirshPersistent(uri=uri)
vm_c_name = params.get('unpr_vm_c_name')

vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name,
virsh_instance=virsh_ins)
vmxml_c = vm_xml.VMXML.new_from_inactive_dumpxml(vm_c_name,
virsh_instance=virsh_ins)
bkxml = vmxml.copy()
bkxml_c = vmxml_c.copy()

if root:
vm = env.get_vm(vm_name)
vm_c = env.get_vm(vm_c_name)
log_dir = params.get('log_dir')
user_id = params.get('user_id')
log_file = f'/run/user/{user_id}/passt.log'
log_file_c = f'/run/user/{user_id}/passt_c.log'
else:
vm_name = params.get('unpr_vm_name')
test_user = params.get('test_user', '')
test_passwd = params.get('test_passwd', '')
user_id = passt.get_user_id(test_user)
unpr_vm_args = {
'username': params.get('username'),
'password': params.get('password'),
}
LOG.debug("Remove 'dac' security driver for unprivileged users")
vmxml.del_seclabel(by_attr=[('model', 'dac')])
vmxml_c.del_seclabel(by_attr=[('model', 'dac')])
vm = libvirt_unprivileged.get_unprivileged_vm(vm_name, test_user,
test_passwd,
**unpr_vm_args)
vm_c = libvirt_unprivileged.get_unprivileged_vm(params.get('unpr_vm_c_name'),
vm_c = libvirt_unprivileged.get_unprivileged_vm(vm_c_name,
test_user,
test_passwd,
**unpr_vm_args)
uri = f'qemu+ssh://{test_user}@localhost/session'
virsh_ins = virsh.VirshPersistent(uri=uri)
host_session = aexpect.ShellSession('su')
remote.VMManager.set_ssh_auth(host_session, 'localhost', test_user,
test_passwd)
Expand All @@ -73,13 +88,6 @@ def run(test, params, env):
iface_attrs['source']['dev'] = host_iface
iface_c_attrs['source']['dev'] = host_iface

vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name,
virsh_instance=virsh_ins)
vmxml_c = vm_xml.VMXML.new_from_inactive_dumpxml(vm_c.name,
virsh_instance=virsh_ins)
bkxml = vmxml.copy()
bkxml_c = vmxml_c.copy()

selinux_status = passt.ensure_selinux_enforcing()
passt.check_socat_installed()

Expand Down
12 changes: 7 additions & 5 deletions libvirt/tests/src/virtual_network/passt/passt_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def run(test, params, env):
"""
libvirt_version.is_libvirt_feature_supported(params)
root = 'root_user' == params.get('user_type', '')
vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name,
virsh_instance=virsh_ins)
bkxml = vmxml.copy()

if root:
vm_name = params.get('main_vm')
vm = env.get_vm(vm_name)
Expand All @@ -42,6 +46,8 @@ def run(test, params, env):
'username': params.get('username'),
'password': params.get('password'),
}
LOG.debug("Remove 'dac' security driver for unprivileged user")
vmxml.del_seclabel(by_attr=[('model', 'dac')])
vm = libvirt_unprivileged.get_unprivileged_vm(vm_name, test_user,
test_passwd,
**unpr_vm_args)
Expand All @@ -68,10 +74,6 @@ def run(test, params, env):
iface_attrs['backend']['logFile'] = log_file
iface_attrs['source']['dev'] = host_iface

vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name,
virsh_instance=virsh_ins)
bkxml = vmxml.copy()

selinux_status = passt.ensure_selinux_enforcing()
passt.check_socat_installed()

Expand All @@ -98,7 +100,7 @@ def run(test, params, env):
test.fail(f'Logfile of passt "{log_file}" not created')

session = vm.wait_for_serial_login(timeout=60)
passt.check_vm_ip(iface_attrs, session, host_iface)
passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface)
passt.check_vm_mtu(session, vm_iface, mtu)
passt.check_default_gw(session)
passt.check_nameserver(session)
Expand Down
2 changes: 1 addition & 1 deletion libvirt/tests/src/virtual_network/passt/passt_reconnect.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def run(test, params, env):
test.fail(f'Logfile of passt "{log_file}" not created')

session = vm.wait_for_serial_login(timeout=60)
passt.check_vm_ip(iface_attrs, session, host_iface)
passt.check_vm_ip(iface_attrs, session, host_iface, vm_iface)
passt.check_vm_mtu(session, vm_iface, mtu)
passt.check_default_gw(session)
passt.check_nameserver(session)
Expand Down
28 changes: 21 additions & 7 deletions provider/virtual_network/passt.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import os
import re
from socket import socket

import aexpect
Expand Down Expand Up @@ -169,15 +170,17 @@ def check_proc(target):
raise exceptions.TestFail(';'.join(failed_check))


def check_vm_ip(iface_attrs, session, host_iface):
def check_vm_ip(iface_attrs, session, host_iface, vm_iface=None):
"""
Check if vm ip and prefix meet expectation
:param iface_attrs: attributes of interface
:param session: shell session instance of vm
:param host_iface: host interface
:param vm_iface: vm interface, will be constructed for x86_64 if None
"""
vm_iface = 'eno' + iface_attrs.get('acpi', {'index': '1'})['index']
if not vm_iface:
vm_iface = 'eno' + iface_attrs.get('acpi', {'index': '1'})['index']
vm_ip, prefix = get_iface_ip_and_prefix(vm_iface, session=session)
LOG.debug(f'VM ip and prefix: {vm_ip}, {prefix}')
if 'ips' in iface_attrs:
Expand Down Expand Up @@ -230,16 +233,20 @@ def check_vm_mtu(session, iface, mtu):
raise exceptions.TestFail(f'Wrong vm mtu: {vm_mtu}, should be {mtu}')


def check_default_gw(session):
def check_default_gw(session, host_iface_index=0):
"""
Check whether default host gateways of host and guest are consistent
:param session: vm shell session instance
:param host_iface_index: in case, there's more than one default gateway on
the host, which one to select
"""
host_gw = utils_net.get_default_gateway(force_dhcp=True)
host_gw = host_gw.split('\n')[host_iface_index]
vm_gw = utils_net.get_default_gateway(session=session, force_dhcp=True)
LOG.debug(f'Host and vm default ipv4 gateway: {host_gw}, {vm_gw}')
host_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6')
host_gw_v6 = host_gw_v6.split('\n')[host_iface_index]
vm_gw_v6 = utils_net.get_default_gateway(session=session, ip_ver='ipv6')
LOG.debug(f'Host and vm default ipv6 gateway: {host_gw_v6}, {vm_gw_v6}')

Expand All @@ -258,8 +265,11 @@ def check_nameserver(session):
:param session: vm shell session instance
"""
get_cmd = 'cat /etc/resolv.conf|grep -vE "#|;"'
on_host = process.run(get_cmd, shell=True).stdout_text.strip()
on_vm = session.cmd_output(get_cmd).strip()
on_host = process.run(get_cmd, shell=True).stdout_text.strip().split('\n')
on_vm = session.cmd_output(get_cmd).strip().split('\n')
if cleanup:
on_host = [re.sub(r'%.*', '', x) for x in on_host]
on_vm = [re.sub(r'%.*', '', x) for x in on_vm]
if on_host == on_vm:
LOG.debug(f'Nameserver on vm is consistent with host:\n{on_host}')
else:
Expand Down Expand Up @@ -320,16 +330,20 @@ def check_protocol_connection(src_sess, tar_sess, protocol, addr,
f'actually is {conneted}')


def check_connection(vm, vm_iface, protocols):
def check_connection(vm, vm_iface, protocols, host_iface_index=0):
"""
Check connection of vm and host
:param vm: vm instance
:param vm_iface: interface of vm
:param protocols: protocols to check
:param host_iface_index: in case, there's more than one default gateway on
the host, which one to select
"""
default_gw = utils_net.get_default_gateway(force_dhcp=True)
default_gw = default_gw.split('\n')[host_iface_index]
default_gw_v6 = utils_net.get_default_gateway(ip_ver='ipv6')
default_gw_v6 = default_gw_v6.split('\n')[host_iface_index]
for protocol in protocols:
host_sess = aexpect.ShellSession('su')
vm_sess = vm.wait_for_serial_login(timeout=60)
Expand Down Expand Up @@ -379,7 +393,7 @@ def check_port_listen(ports, protocol, host_ip=None):
"""
if protocol.lower() not in ('tcp', 'udp'):
raise exceptions.TestError(f'Unsupported protocol: {protocol}')
cmd_listen = process.run(f"ss -{protocol[0].lower()}lpn|egrep 'passt.avx2'",
cmd_listen = process.run(f"ss -{protocol[0].lower()}lpn|egrep 'passt'",
shell=True).stdout_text
for item in ports:
if item in cmd_listen:
Expand Down

0 comments on commit d5aefca

Please sign in to comment.