Skip to content

Commit 489a1e6

Browse files
committed
add case for migrating guest with bridge interface
xxxx-299038: [bridge] migrate guest with bridge type interface Signed-off-by: nanli <[email protected]>
1 parent e002d4d commit 489a1e6

File tree

2 files changed

+337
-0
lines changed

2 files changed

+337
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
- virtual_network.migrate_with_bridge_type_interface:
2+
type = migrate_with_bridge_type_interface
3+
start_vm = "yes"
4+
only_pty = True
5+
take_regular_screendumps = no
6+
ssh_timeout = 60
7+
migration_setup = "yes"
8+
storage_type = 'nfs'
9+
setup_local_nfs = 'yes'
10+
virsh_migrate_dest_state = running
11+
virsh_migrate_src_state = running
12+
virsh_migrate_options = "--live --p2p --verbose"
13+
virsh_migrate_connect_uri = "qemu:///system"
14+
migrate_vm_back = "yes"
15+
bridge_name = "br0"
16+
remote_ip = "www.google.com"
17+
ping_count = 3
18+
ping_timeout = 10
19+
server_user = "root"
20+
virsh_options = ""
21+
iface_model = "virtio"
22+
iface_queues = "5"
23+
new_queues = "3"
24+
disk_type = "file"
25+
disk_source_protocol = "netfs"
26+
ssh_remote_auth = True
27+
unprivileged_user = ""
28+
#migrate_dest_host = "EXAMPLE.DEST.HOST"
29+
#migrate_source_host = "EXAMPLE.SOURCE.HOST"
30+
migrate_dest_host = "dell-per750-63.lab.eng.pek2.redhat.com"
31+
migrate_source_host = "dell-per750-62.lab.eng.pek2.redhat.com"
32+
migrate_main_vm = "${main_vm}"
33+
vm_ping_outside = "pass"
34+
expected_xpath = "//interface/driver[@queues='${iface_queues}']"
35+
variants:
36+
- linux_bridge:
37+
bridge_type = "linux"
38+
iface_type = "bridge"
39+
iface_source = "{'bridge':'${bridge_name}', 'type':'${iface_type}', 'model':'${iface_model}', 'driver':{'queues':'${iface_queues}'}}"
40+
- ovs_bridge:
41+
bridge_type = "ovs"
42+
ovs_bridge_name = "ovsbr0"
43+
network_dict = {'bridge': {'name': '${ovs_bridge_name}'}, 'forward': {'mode': 'bridge'}, 'name': 'ovs-net', 'virtualport_type': 'openvswitch'}
44+
iface_type = "network"
45+
iface_source = "{'network': 'ovs-net', 'type':'${iface_type}', 'model':'${iface_model}', 'driver':{'queues':'${iface_queues}'}}"
46+
variants:
47+
- precopy_migration:
48+
migration_type = "precopy"
49+
virsh_migrate_extra = ""
50+
- postcopy_migration:
51+
migration_type = "postcopy"
52+
virsh_migrate_extra = "--postcopy"
53+
- cancel_migration:
54+
migration_type = "cancel"
55+
cancel_migration = "yes"
56+
virsh_migrate_extra = ""
57+
variants:
58+
- start_with_interface:
59+
interface_timing = "start"
60+
- hotplug_interface:
61+
interface_timing = "hotplug"
62+
hotplug = "yes"
63+
attach_interface = "yes"
64+
iface_model = "virtio"
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
import re
2+
3+
4+
from virttest import libvirt_version
5+
from virttest import libvirt_vm
6+
from virttest import migration
7+
from virttest import remote
8+
from virttest import utils_net
9+
from virttest import utils_package
10+
from virttest import virsh
11+
from provider.guest_os_booting import guest_os_booting_base as guest_os
12+
13+
from virttest.libvirt_xml import vm_xml
14+
from virttest.utils_test import libvirt
15+
from virttest.utils_libvirt import libvirt_network
16+
from virttest.utils_libvirt import libvirt_vmxml
17+
from provider.virtual_network import network_base
18+
from provider.interface import interface_base
19+
from provider.migration import base_steps
20+
21+
22+
23+
def run(test, params, env):
24+
"""
25+
Test migration with bridge type interface
26+
1. Setup bridge and virtual network according to bridge type
27+
2. Migrate to target host
28+
3. Check on target host for network functions:
29+
- Guest ping outside
30+
- Check for multiqueue
31+
- Check multiqueues in VM live XML (should have <driver ... queues='5'>)
32+
4. Migrate back from dst to src
33+
34+
:param test: test object
35+
:param params: Dictionary with the test parameters
36+
:param env: Dictionary with test environment.
37+
"""
38+
def check_multiqueue_in_guest(vm_session):
39+
"""
40+
Check multiqueue configuration inside the guest
41+
"""
42+
test.log.info("Checking multiqueue configuration in guest")
43+
# Get network interface name
44+
guest_iface_info = vm_session.cmd_output("ip --color=never l").strip()
45+
iface_name = re.findall(
46+
r"^\d+: (\S+?)[@:].*state UP.*$", guest_iface_info, re.MULTILINE)[0]
47+
if not iface_name:
48+
test.fail("Failed to get network interface name in guest")
49+
50+
maximum, current = utils_net.get_channel_info(vm_session, iface_name)
51+
if maximum.get("Combined", 0) != iface_queues:
52+
test.fail("Expected Pre-set maximums Combined: 5, but got: %d" % maximum)
53+
if current.get("Combined", 0) != iface_queues:
54+
test.fail("Expected Current hardware settings Combined: 5, but got: %d" % current)
55+
56+
test.log.info("Setting combined queues to 3 for %s", iface_name)
57+
utils_net.set_channel(vm_session, iface_name, "combined", new_queues)
58+
59+
_, verify_current = utils_net.get_channel_info(vm_session, iface_name).get("Combined", 0)
60+
if verify_current != new_queues:
61+
test.fail("Failed to set combined queues, current value: %d" % verify_current)
62+
63+
def setup_vm_interface():
64+
"""
65+
Setup VM interface according to configuration
66+
"""
67+
test.log.info("Setting up VM interface")
68+
69+
# Get interface configuration from params
70+
if interface_timing == "hotplug":
71+
# Hot-plug interface using helper function
72+
iface_xml = libvirt.modify_vm_iface(vm_name, "get_xml", iface_dict)
73+
if not vm.is_alive():
74+
vm.start()
75+
vm.wait_for_login()
76+
result = virsh.attach_device(vm_name, iface_xml, flagstr="--live", debug=True)
77+
if result.exit_status:
78+
test.fail("Failed to hotplug interface: %s" % result.stderr_text)
79+
else:
80+
# Add interface to XML using setup_attrs pattern
81+
vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
82+
vmxml.remove_all_device_by_type('interface')
83+
84+
iface = interface_base.create_iface(iface_dict['type'], iface_dict)
85+
vmxml.add_device(iface)
86+
vmxml.sync()
87+
88+
89+
def setup_test():
90+
"""
91+
Setup test environment for migration with bridge type interface
92+
"""
93+
test.log.info("Setting up test environment")
94+
if bridge_type == "linux":
95+
pass
96+
# utils_net.create_linux_bridge_tmux(bridge_name)
97+
# utils_net.create_linux_bridge_tmux(bridge_name, session=remote_session)
98+
99+
elif bridge_type == "ovs":
100+
# Create OVS bridge
101+
status, stdout = utils_net.create_ovs_bridge(ovs_bridge_name, ip_options='-color=never')
102+
if status:
103+
test.fail("Failed to create ovs bridge on local. Status: %s, Stdout: %s" % (status, stdout))
104+
105+
# Create same bridge on remote host
106+
status, stdout = utils_net.create_ovs_bridge(ovs_bridge_name, session=remote_session, ip_options='-color=never')
107+
if status:
108+
test.fail("Failed to create ovs bridge on remote. Status: %s, Stdout: %s" % (status, stdout))
109+
110+
# Create virtual network for OVS bridge
111+
libvirt_network.create_or_del_network(network_dict, remote_args=remote_virsh_dargs)
112+
test.log.info("dest: network created")
113+
libvirt_network.create_or_del_network(network_dict)
114+
test.log.info("localhost: network created")
115+
116+
# Setup NFS shared storage for migration
117+
migration_test.migrate_pre_setup(dest_uri, params)
118+
119+
libvirt.set_vm_disk(vm, params)
120+
setup_vm_interface()
121+
122+
test.log.debug("Guest xml after starting:\n%s", vm_xml.VMXML.new_from_dumpxml(vm_name))
123+
124+
def run_test():
125+
"""
126+
Run the main test: migration and verification
127+
"""
128+
test.log.info("Starting migration test")
129+
130+
# Check local guest network connection before migration
131+
if vm.serial_console is not None:
132+
vm.cleanup_serial_console()
133+
vm.create_serial_console()
134+
vm_session = vm.wait_for_serial_login(timeout=240)
135+
136+
if not utils_package.package_install('dhcp-client', session=vm_session):
137+
test.error("Failed to install dhcp-client on guest.")
138+
utils_net.restart_guest_network(vm_session)
139+
140+
test.log.info("Checking VM network connectivity before migration")
141+
ips = {'outside_ip': remote_ip}
142+
network_base.ping_check(params, ips, vm_session)
143+
144+
test.log.info("Migrating VM to target host")
145+
migration_obj = base_steps.MigrationBase(test, vm, params)
146+
migration_obj.setup_connection()
147+
migration_obj.run_migration()
148+
149+
test.log.info("Checking VM network connectivity on target host")
150+
vm.connect_uri = dest_uri
151+
if vm.serial_console is not None:
152+
vm.cleanup_serial_console()
153+
vm.create_serial_console()
154+
vm_session_after_mig = vm.wait_for_serial_login(timeout=240)
155+
vm_session_after_mig.cmd("dhclient -r; dhclient")
156+
157+
test.log.info("Testing guest ping to outside")
158+
ips = {'outside_ip': remote_ip}
159+
network_base.ping_check(params, ips, vm_session_after_mig)
160+
161+
test.log.info("Checking multiqueue in guest")
162+
check_multiqueue_in_guest(vm_session_after_mig)
163+
164+
test.log.info("Checking multiqueue in VM XML")
165+
libvirt_vmxml.check_guest_xml_by_xpaths(
166+
vm_xml.VMXML.new_from_dumpxml(vm_name, virsh_instance=virsh_session_remote),
167+
expected_xpath)
168+
169+
if migrate_vm_back:
170+
test.log.info("Migrating VM back to source host")
171+
migration_obj = base_steps.MigrationBase(test, vm, params)
172+
migration_obj.run_migration_back()
173+
174+
def teardown_test():
175+
"""
176+
Cleanup test environment
177+
"""
178+
test.log.info("Cleaning up test environment")
179+
vm.connect_uri = bk_uri
180+
migration_test.cleanup_vm(vm, dest_uri)
181+
182+
# Recovery VM XML configuration
183+
test.log.info("Recovery VM XML configuration")
184+
orig_config_xml.sync()
185+
186+
# Cleanup bridges
187+
if bridge_type == "linux":
188+
pass
189+
# utils_net.delete_linux_bridge_tmux(bridge_name)
190+
# utils_net.delete_linux_bridge_tmux(bridge_name, session=remote_session)
191+
elif bridge_type == "ovs":
192+
utils_net.delete_ovs_bridge(ovs_bridge_name, ip_options='-color=never')
193+
utils_net.delete_ovs_bridge(ovs_bridge_name, session=remote_session, ip_options='-color=never')
194+
195+
# Cleanup networks
196+
libvirt_network.create_or_del_network(network_dict, is_del=True, remote_args=remote_virsh_dargs)
197+
libvirt_network.create_or_del_network(network_dict, is_del=True)
198+
199+
if migrate_vm_back:
200+
ssh_connection = None
201+
if 'ssh_connection' in locals():
202+
ssh_connection.auto_recover = True
203+
migration_test.migrate_pre_setup(src_uri, params, cleanup=True)
204+
205+
# Remove local NFS image
206+
test.log.info("Remove local NFS image")
207+
source_file = params.get("source_file")
208+
if source_file:
209+
libvirt.delete_local_disk("file", path=source_file)
210+
211+
# Initialize migration test
212+
migration_test = migration.MigrationTest()
213+
migration_test.check_parameters(params)
214+
215+
libvirt_version.is_libvirt_feature_supported(params)
216+
217+
# Params to update disk using shared storage
218+
params["disk_type"] = params.get("disk_type", "file")
219+
params["disk_source_protocol"] = params.get("disk_source_protocol", "netfs")
220+
params["mnt_path_name"] = params.get("nfs_mount_dir")
221+
222+
# Local variables
223+
server_ip = params.get("server_ip")
224+
server_user = params.get("server_user")
225+
server_pwd = params.get("server_pwd")
226+
remote_ip = params.get("remote_ip")
227+
bridge_name = params.get("bridge_name")
228+
bridge_type = params.get("bridge_type")
229+
ovs_bridge_name = params.get("ovs_bridge_name")
230+
network_dict = eval(params.get("network_dict", "{}"))
231+
interface_timing = params.get("interface_timing")
232+
iface_queues = params.get("iface_queues")
233+
new_queues = params.get("new_queues")
234+
235+
migrate_vm_back = "yes" == params.get("migrate_vm_back")
236+
237+
remote_virsh_dargs = {'remote_ip': server_ip, 'remote_user': server_user,
238+
'remote_pwd': server_pwd, 'unprivileged_user': params.get("unprivileged_user"),
239+
'ssh_remote_auth': params.get("ssh_remote_auth")}
240+
241+
# params for migration connection
242+
params["virsh_migrate_desturi"] = libvirt_vm.complete_uri(
243+
params.get("migrate_dest_host"))
244+
params["virsh_migrate_connect_uri"] = libvirt_vm.complete_uri(
245+
params.get("migrate_source_host"))
246+
src_uri = params.get("virsh_migrate_connect_uri")
247+
dest_uri = params.get("virsh_migrate_desturi")
248+
expected_xpath = params.get("expected_xpath")
249+
iface_dict = eval(params.get("iface_dict", "{}"))
250+
251+
vm_name = guest_os.get_vm(params)
252+
vm = env.get_vm(vm_name)
253+
vm.verify_alive()
254+
bk_uri = vm.connect_uri
255+
256+
# For safety reasons, we'd better back up xmlfile
257+
new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
258+
orig_config_xml = new_xml.copy()
259+
260+
# Create remote session and virsh instance
261+
remote_session = remote.remote_login("ssh", server_ip, "22",
262+
server_user, server_pwd, r'[$#%]')
263+
virsh_session_remote = virsh.VirshPersistent(**remote_virsh_dargs)
264+
265+
try:
266+
setup_test()
267+
run_test()
268+
finally:
269+
teardown_test()
270+
if remote_session:
271+
remote_session.close()
272+
if virsh_session_remote:
273+
virsh_session_remote.close_session()

0 commit comments

Comments
 (0)