def run(test, params, env): """ Verify hotplug feature for char device """ vm_name = params.get("main_vm", "vm1") status_error = "yes" == params.get("status_error", "no") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") dup_charid = "yes" == params.get("dup_charid", "no") dup_devid = "yes" == params.get("dup_devid", "no") diff_devid = "yes" == params.get("diff_devid", "no") tmp_dir = os.path.join(test.tmpdir, "hotplug_serial") if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) os.chmod(tmp_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() # add controller for each char device devices = vm_xml.get_devices() controllers = vm_xml.get_devices(device_type="controller") for dev in controllers: if dev.type == "virtio-serial": devices.remove(dev) controller = Controller("controller") controller.type = "virtio-serial" controller.index = 0 devices.append(controller) vm_xml.set_devices(devices) vm_xml.sync() # start and login vm vm = env.get_vm(vm_name) vm.start() session = vm.wait_for_login() def prepare_channel_xml(to_file, char_type, id=0): params = {} mode = '' if char_type == "file": channel_type = char_type channel_path = os.path.join(tmp_dir, char_type) elif char_type == "socket": channel_type = 'unix' channel_path = os.path.join(tmp_dir, char_type) mode = 'bind' elif char_type == "pty": channel_type = char_type channel_path = ("/dev/pts/%s" % id) params = {'channel_type_name': channel_type, 'source_path': channel_path, 'source_mode': mode, 'target_type': 'virtio', 'target_name': char_type} channel_xml = utlv.create_channel_xml(params, alias=True, address=True) shutil.copyfile(channel_xml.xml, to_file) def hotplug_device(type, char_dev, id=0): tmp_file = os.path.join(tmp_dir, char_dev) if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += "file,path=%s,id=file" % tmp_file dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" elif char_dev == "socket": char_add_opt += "socket,path=%s,server,nowait,id=socket" % tmp_file dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" elif char_dev == "pty": char_add_opt += ("pty,path=/dev/pts/%s,id=pty" % id) dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if result.exit_status: test.error('Failed to add chardev %s to %s. Result:\n %s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") if result.exit_status: test.error('Failed to add device %s to %s. Result:\n %s' % (char_dev, vm_name, result)) elif type == "attach": xml_file = os.path.join(tmp_dir, "xml_%s" % char_dev) if char_dev in ["file", "socket"]: prepare_channel_xml(xml_file, char_dev) elif char_dev == "pty": prepare_channel_xml(xml_file, char_dev, id) result = virsh.attach_device(vm_name, xml_file) # serial device was introduced by the following commit, # http://libvirt.org/git/? # p=libvirt.git;a=commit;h=b63ea467617e3cbee4282ab2e5e780b4119cef3d if "unknown device type" in result.stderr: test.cancel('Failed to attach %s to %s. Result:\n %s' % (char_dev, vm_name, result)) return result def dup_hotplug(type, char_dev, id, dup_charid=False, dup_devid=False, diff_devid=False): tmp_file = os.path.join(tmp_dir, char_dev) if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": if dup_charid: char_add_opt += "file,path=%s,id=file" % tmp_file if dup_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" if diff_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file1" elif char_dev == "socket": if dup_charid: char_add_opt += "socket,path=%s,server,nowait,id=socket" % tmp_file if dup_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" if diff_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket1" elif char_dev == "pty": if dup_charid: char_add_opt += "pty,path=/dev/pts/%s,id=pty" % id if dup_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" if diff_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty1" if dup_charid: result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if dup_devid or diff_devid: result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif type == "attach": if dup_devid: result = hotplug_device(type, char_dev, id) return result def confirm_hotplug_result(char_dev, id=0): tmp_file = os.path.join(tmp_dir, char_dev) serial_file = os.path.join("/dev/virtio-ports", char_dev) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() if not h_o.count("name = \"%s\"" % char_dev): test.fail("Cann't find device(%s) from:\n%s" % (char_dev, h_o)) if char_dev == "file": session.cmd("echo test > %s" % serial_file) with open(tmp_file, "r") as f: r_o = f.read() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) r_o = sock.recv(1024) elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): test.fail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) session.cmd("echo test >> /tmp/file &") while True: r_o = p.stdout.readline() if r_o or p.poll(): break time.sleep(0.2) p.kill() if not r_o.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, r_o) test.fail(err_info) def unhotplug_serial_device(type, char_dev): if type == "qmp": del_dev_opt = "device_del %s" % char_dev del_char_opt = "chardev-remove %s" % char_dev result = virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") if result.exit_status: test.error('Failed to del device %s from %s.Result:\n%s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif type == "attach": xml_file = os.path.join(tmp_dir, "xml_%s" % char_dev) result = virsh.detach_device(vm_name, xml_file) def confirm_unhotplug_result(char_dev): serial_file = os.path.join("/dev/virtio-ports", char_dev) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = \"%s\"" % char_dev): test.fail("Still can get serial device(%s) from: '%s'" % (char_dev, uh_o)) if os.path.exists(serial_file): test.fail("File '%s' still exists after unhotplug" % serial_file) # run test case try: if char_dev in ['file', 'socket']: # if char_dev is file or socket, it doesn't need pts index pts_id = 0 else: pts_id = str(utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1) if os.path.exists("/dev/pts/%s" % pts_id): test.error('invalid pts index(%s) provided.' % pts_id) if status_error: hotplug_device(hotplug_type, char_dev, pts_id) ret = dup_hotplug(hotplug_type, char_dev, pts_id, dup_charid, dup_devid, diff_devid) dup_o = ret.stdout.strip() if hotplug_type == "qmp": # although it has failed, ret.exit_status will be returned 0. err_o1 = "Duplicate ID" err_o2 = "Parsing chardev args failed" err_o3 = "Property 'virtserialport.chardev' can't" if (err_o1 not in dup_o) and (err_o2 not in dup_o) and (err_o3 not in dup_o): test.fail("Expect fail, but run successfully:\n%s" % ret) else: if "chardev already exists" not in dup_o: logging.info("Expect fail,but run successfully:\n%s" % ret) else: if char_dev != "all": #1.hotplug serial device hotplug_device(hotplug_type, char_dev, pts_id) #2.confirm hotplug result confirm_hotplug_result(char_dev, pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") hotplug_device(hotplug_type, "pty", pts_id) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: vm_xml_backup.sync() if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir)
def run(test, params, env): """ Stress test for the hotplug feature of serial device """ vm_name = params.get("main_vm", "vm1") status_error = "yes" == params.get("status_error", "no") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") load_type = params.get("load_type", "") load_params = params.get("load_params", "") test_count = int(params.get("test_count", 5)) test_type = params.get("test_type", "multi") tmp_dir = os.path.join(test.tmpdir, "hotplug_serial_load") if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) os.chmod(tmp_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) load_vms = [] if load_type in ['cpu', 'memory', 'io']: params["stress_args"] = load_params load_vms.append(libvirt_vm.VM(vm_name, params, test.bindir, env.get("address_cache"))) vm = env.get_vm(vm_name) session = vm.wait_for_login() def prepare_channel_xml(to_file, char_type, index=1, id=0): params = {} mode = '' if char_type == "file": channel_type = char_type channel_path = ("%s/%s%s" % (tmp_dir, char_type, index)) elif char_type == "socket": channel_type = 'unix' channel_path = ("%s/%s%s" % (tmp_dir, char_type, index)) mode = 'bind' elif char_type == "pty": channel_type = char_type channel_path = ("/dev/pts/%s" % id) params = {'channel_type_name': channel_type, 'source_path': channel_path, 'source_mode': mode, 'target_type': 'virtio', 'target_name': char_type + str(index)} channel_xml = utlv.create_channel_xml(params, alias=True, address=True) shutil.copyfile(channel_xml.xml, to_file) def hotplug_device(hotplug_type, char_dev, index=1, id=0): if hotplug_type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += ("file,path=%s/file%s,id=file%s" % (tmp_dir, index, index)) dev_add_opt += ("file%s,name=file%s,bus=virtio-serial0.0,id=file%s" % (index, index, index)) elif char_dev == "socket": char_add_opt += ("socket,path=%s/socket%s,server,nowait,id=socket%s" % (tmp_dir, index, index)) dev_add_opt += ("socket%s,name=socket%s,bus=virtio-serial0.0,id=socket%s" % (index, index, index)) elif char_dev == "pty": char_add_opt += "pty,path=/dev/pts/%s,id=pty%s" % (id, index) dev_add_opt += ("pty%s,name=pty%s,bus=virtio-serial0.0,id=pty%s" % (index, index, index)) virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif hotplug_type == "attach": xml_file = "%s/xml_%s%s" % (tmp_dir, char_dev, index) if char_dev in ["file", "socket"]: prepare_channel_xml(xml_file, char_dev, index) elif char_dev == "pty": prepare_channel_xml(xml_file, char_dev, index, id) virsh.attach_device(vm_name, xml_file, flagstr="--live") def confirm_hotplug_result(char_dev, index=1, id=0): result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() chardev_c = h_o.count("chardev = %s%s" % (char_dev, index)) name_c = h_o.count("name = \"%s%s\"" % (char_dev, index)) if chardev_c == 0 and name_c == 0: raise error.TestFail("Cannot get serial device info: '%s'" % h_o) tmp_file = "%s/%s%s" % (tmp_dir, char_dev, index) serial_file = "/dev/virtio-ports/%s%s" % (char_dev, index) if char_dev == "file": session.cmd("echo test > %s" % serial_file) f = open(tmp_file, "r") output = f.read() f.close() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) output = sock.recv(1024) sock.close() elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): raise error.TestFail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) while True: output = p.stdout.readline() if output or p.poll(): break time.sleep(0.2) p.kill() if not output.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, output) raise error.TestFail(err_info) def unhotplug_serial_device(hotplug_type, char_dev, index=1): if hotplug_type == "qmp": del_dev_opt = "device_del %s%s" % (char_dev, index) del_char_opt = "chardev-remove %s%s" % (char_dev, index) virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif hotplug_type == "attach": xml_file = "%s/xml_%s%s" % (tmp_dir, char_dev, index) virsh.detach_device(vm_name, xml_file, flagstr="--live") def confirm_unhotplug_result(char_dev, index=1): serial_file = "/dev/virtio-ports/%s%s" % (char_dev, index) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = %s%s" % (char_dev, index)): raise error.TestFail("Still can get serial device info: '%s'" % uh_o) if not session.cmd_status("test -e %s" % serial_file): raise error.TestFail("File '%s' still exists after unhotplug" % serial_file) # run test case try: # increase workload if load_type in ['cpu', 'memory']: utils_test.load_stress("stress_in_vms", load_vms, params) else: utils_test.load_stress("iozone_in_vms", load_vms, params) if test_type == "multi": for i in range(test_count): if char_dev == "pty": ptsid = utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1 else: ptsid = 0 hotplug_device(hotplug_type, char_dev, i + 1, id=ptsid) confirm_hotplug_result(char_dev, i + 1, id=ptsid) unhotplug_serial_device(hotplug_type, char_dev, i + 1) confirm_unhotplug_result(char_dev, i + 1) elif test_type == "circle": if char_dev != "all": for i in range(test_count): if char_dev == "pty": ptsid = utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1 else: ptsid = 0 #1.hotplug serial device hotplug_device(hotplug_type, char_dev, id=ptsid) #2.confirm hotplug result confirm_hotplug_result(char_dev, id=ptsid) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: for i in range(test_count): #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") ptsid = utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1 hotplug_device(hotplug_type, "pty", id=ptsid) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", id=ptsid) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: session.close() if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir)
def run(test, params, env): """ Verify hotplug feature for char device """ vm_name = params.get("main_vm", "vm1") status_error = "yes" == params.get("status_error", "no") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") dup_charid = "yes" == params.get("dup_charid", "no") dup_devid = "yes" == params.get("dup_devid", "no") diff_devid = "yes" == params.get("diff_devid", "no") xml_file = params.get("xml_file", "/tmp/xml_file") vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() # add controller for each char device devices = vm_xml.get_devices() controllers = vm_xml.get_devices(device_type="controller") for dev in controllers: if dev.type == "virtio-serial": devices.remove(dev) controller = Controller("controller") controller.type = "virtio-serial" controller.index = 0 devices.append(controller) vm_xml.set_devices(devices) vm_xml.sync() # start and login vm vm = env.get_vm(vm_name) vm.start() session = vm.wait_for_login() def create_channel_xml(vm_name, char_type, id=0): """ Create a XML contains channel information. """ channel_type = char_type if char_type == "file": channel_path = ("/tmp/%s" % char_type) channel_source = {'path': channel_path} channel_target = {'type': 'virtio', 'name': 'file'} if char_type == "socket": channel_type = 'unix' channel_path = ("/tmp/%s" % char_type) channel_source = {'mode': 'bind', 'path': channel_path} channel_target = {'type': 'virtio', 'name': 'socket'} if char_type == "pty": channel_path = ("/dev/pts/%s" % id) channel_source = {'path': channel_path} channel_target = {'type': 'virtio', 'name': 'pty'} channel_alias = {'name': char_type} channel_address = {'type': 'virtio-serial', 'controller': '0', 'bus': '0'} channel_params = {'type_name': channel_type, 'source': channel_source, 'target': channel_target, 'alias': channel_alias, 'address': channel_address} channelxml = channel.Channel.new_from_dict(channel_params) logging.debug("Channel XML:\n%s", channelxml) xmlf = open(channelxml.xml) try: xml_lines = xmlf.read() finally: xmlf.close() return xml_lines def hotplug_device(type, char_dev, id=0): tmp_file = "/tmp/%s" % char_dev if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += "file,path=/tmp/file,id=file" dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" elif char_dev == "socket": char_add_opt += "socket,path=/tmp/socket,server,nowait,id=socket" dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" elif char_dev == "pty": char_add_opt += ("pty,path=/dev/pts/%s,id=pty" % id) dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to add chardev %s to %s. Result:\n %s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to add device %s to %s. Result:\n %s' % (char_dev, vm_name, result)) elif type == "attach": if char_dev in ["file", "socket"]: xml_info = create_channel_xml(vm_name, char_dev) elif char_dev == "pty": xml_info = create_channel_xml(vm_name, char_dev, id) f = open(xml_file, "w") f.write(xml_info) f.close() if os.path.exists(tmp_file): os.chmod(tmp_file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) result = virsh.attach_device(vm_name, xml_file) return result def dup_hotplug(type, char_dev, id, dup_charid=False, dup_devid=False, diff_devid=False): if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": if dup_charid: char_add_opt += "file,path=/tmp/file,id=file" if dup_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" if diff_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file1" elif char_dev == "socket": if dup_charid: char_add_opt += "socket,path=/tmp/socket,server,nowait,id=socket" if dup_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" if diff_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket1" elif char_dev == "pty": if dup_charid: char_add_opt += "pty,path=/dev/pts/%s,id=pty" % id if dup_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" if diff_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty1" if dup_charid: result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if dup_devid or diff_devid: result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif type == "attach": if dup_devid: result = hotplug_device(type, char_dev, id) return result def confirm_hotplug_result(char_dev, id=0): tmp_file = "/tmp/%s" % char_dev serial_file = "/dev/virtio-ports/%s" % char_dev result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() if not h_o.count("name = \"%s\"" % char_dev): raise error.TestFail("Cann't find device(%s) from:\n%s" % (char_dev, h_o)) if char_dev == "file": session.cmd("echo test > %s" % serial_file) f = open(tmp_file, "r") r_o = f.read() f.close() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) r_o = sock.recv(1024) elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): raise error.TestFail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) session.cmd("echo test >> /tmp/file &") while True: r_o = p.stdout.readline() if r_o or p.poll(): break time.sleep(0.2) p.kill() if not r_o.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, r_o) raise error.TestFail(err_info) def unhotplug_serial_device(type, char_dev): if type == "qmp": del_dev_opt = "device_del %s" % char_dev del_char_opt = "chardev-remove %s" % char_dev result = virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to del device %s from %s.Result:\n%s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif type == "attach": result = virsh.detach_device(vm_name, xml_file) def confirm_unhotplug_result(char_dev): serial_file = "/dev/virtio-ports/%s" % char_dev result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = \"%s\"" % char_dev): raise error.TestFail("Still can get serial device(%s) from: '%s'" % (char_dev, uh_o)) if os.path.exists(serial_file): raise error.TestFail("File '%s' still exists after unhotplug" % serial_file) # run test case try: if char_dev in ['file', 'socket']: # if char_dev is file or socket, it doesn't need pts index pts_id = 0 else: pts_id = str(utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1) if os.path.exists("/dev/pts/%s" % pts_id): raise error.TestError('invalid pts index(%s) provided.' % pts_id) if status_error: hotplug_device(hotplug_type, char_dev, pts_id) ret = dup_hotplug(hotplug_type, char_dev, pts_id, dup_charid, dup_devid, diff_devid) dup_o = ret.stdout.strip() if hotplug_type == "qmp": # although it has failed, ret.exit_status will be returned 0. err_o1 = "Duplicate ID" err_o2 = "Parsing chardev args failed" err_o3 = "Property 'virtserialport.chardev' can't" if (err_o1 not in dup_o) and (err_o2 not in dup_o) and (err_o3 not in dup_o): raise error.TestFail("Expect fail, but run successfully:\n%s" % ret) else: if "chardev already exists" not in dup_o: logging.info("Expect fail,but run successfully:\n%s" % ret) else: if char_dev != "all": #1.hotplug serial device hotplug_device(hotplug_type, char_dev, pts_id) #2.confirm hotplug result confirm_hotplug_result(char_dev, pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") hotplug_device(hotplug_type, "pty", pts_id) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: vm_xml_backup.sync() if os.path.exists(xml_file): os.remove(xml_file)
def run(test, params, env): """ Verify hotplug feature for char device """ vm_name = params.get("main_vm", "vm1") status_error = "yes" == params.get("status_error", "no") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") dup_charid = "yes" == params.get("dup_charid", "no") dup_devid = "yes" == params.get("dup_devid", "no") diff_devid = "yes" == params.get("diff_devid", "no") tmp_dir = os.path.join(test.tmpdir, "hotplug_serial") if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) os.chmod(tmp_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() # add controller for each char device devices = vm_xml.get_devices() controllers = vm_xml.get_devices(device_type="controller") for dev in controllers: if dev.type == "virtio-serial": devices.remove(dev) controller = Controller("controller") controller.type = "virtio-serial" controller.index = 0 devices.append(controller) vm_xml.set_devices(devices) vm_xml.sync() # start and login vm vm = env.get_vm(vm_name) vm.start() session = vm.wait_for_login() def prepare_channel_xml(to_file, char_type, id=0): params = {} mode = '' if char_type == "file": channel_type = char_type channel_path = os.path.join(tmp_dir, char_type) elif char_type == "socket": channel_type = 'unix' channel_path = os.path.join(tmp_dir, char_type) mode = 'bind' elif char_type == "pty": channel_type = char_type channel_path = ("/dev/pts/%s" % id) params = {'channel_type_name': channel_type, 'source_path': channel_path, 'source_mode': mode, 'target_type': 'virtio', 'target_name': char_type} channel_xml = utlv.create_channel_xml(params, alias=True, address=True) shutil.copyfile(channel_xml.xml, to_file) def hotplug_device(type, char_dev, id=0): tmp_file = os.path.join(tmp_dir, char_dev) if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += "file,path=%s,id=file" % tmp_file dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" elif char_dev == "socket": char_add_opt += "socket,path=%s,server,nowait,id=socket" % tmp_file dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" elif char_dev == "pty": char_add_opt += ("pty,path=/dev/pts/%s,id=pty" % id) dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to add chardev %s to %s. Result:\n %s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to add device %s to %s. Result:\n %s' % (char_dev, vm_name, result)) elif type == "attach": xml_file = os.path.join(tmp_dir, "xml_%s" % char_dev) if char_dev in ["file", "socket"]: prepare_channel_xml(xml_file, char_dev) elif char_dev == "pty": prepare_channel_xml(xml_file, char_dev, id) result = virsh.attach_device(vm_name, xml_file) # serial device was introduced by the following commit, # http://libvirt.org/git/? # p=libvirt.git;a=commit;h=b63ea467617e3cbee4282ab2e5e780b4119cef3d if "unknown device type" in result.stderr: raise error.TestNAError('Failed to attach %s to %s. Result:\n %s' % (char_dev, vm_name, result)) return result def dup_hotplug(type, char_dev, id, dup_charid=False, dup_devid=False, diff_devid=False): tmp_file = os.path.join(tmp_dir, char_dev) if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": if dup_charid: char_add_opt += "file,path=%s,id=file" % tmp_file if dup_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" if diff_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file1" elif char_dev == "socket": if dup_charid: char_add_opt += "socket,path=%s,server,nowait,id=socket" % tmp_file if dup_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" if diff_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket1" elif char_dev == "pty": if dup_charid: char_add_opt += "pty,path=/dev/pts/%s,id=pty" % id if dup_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" if diff_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty1" if dup_charid: result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if dup_devid or diff_devid: result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif type == "attach": if dup_devid: result = hotplug_device(type, char_dev, id) return result def confirm_hotplug_result(char_dev, id=0): tmp_file = os.path.join(tmp_dir, char_dev) serial_file = os.path.join("/dev/virtio-ports", char_dev) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() if not h_o.count("name = \"%s\"" % char_dev): raise error.TestFail("Cann't find device(%s) from:\n%s" % (char_dev, h_o)) if char_dev == "file": session.cmd("echo test > %s" % serial_file) f = open(tmp_file, "r") r_o = f.read() f.close() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) r_o = sock.recv(1024) elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): raise error.TestFail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) session.cmd("echo test >> /tmp/file &") while True: r_o = p.stdout.readline() if r_o or p.poll(): break time.sleep(0.2) p.kill() if not r_o.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, r_o) raise error.TestFail(err_info) def unhotplug_serial_device(type, char_dev): if type == "qmp": del_dev_opt = "device_del %s" % char_dev del_char_opt = "chardev-remove %s" % char_dev result = virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to del device %s from %s.Result:\n%s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif type == "attach": xml_file = os.path.join(tmp_dir, "xml_%s" % char_dev) result = virsh.detach_device(vm_name, xml_file) def confirm_unhotplug_result(char_dev): serial_file = os.path.join("/dev/virtio-ports", char_dev) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = \"%s\"" % char_dev): raise error.TestFail("Still can get serial device(%s) from: '%s'" % (char_dev, uh_o)) if os.path.exists(serial_file): raise error.TestFail("File '%s' still exists after unhotplug" % serial_file) # run test case try: if char_dev in ['file', 'socket']: # if char_dev is file or socket, it doesn't need pts index pts_id = 0 else: pts_id = str(utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1) if os.path.exists("/dev/pts/%s" % pts_id): raise error.TestError('invalid pts index(%s) provided.' % pts_id) if status_error: hotplug_device(hotplug_type, char_dev, pts_id) ret = dup_hotplug(hotplug_type, char_dev, pts_id, dup_charid, dup_devid, diff_devid) dup_o = ret.stdout.strip() if hotplug_type == "qmp": # although it has failed, ret.exit_status will be returned 0. err_o1 = "Duplicate ID" err_o2 = "Parsing chardev args failed" err_o3 = "Property 'virtserialport.chardev' can't" if (err_o1 not in dup_o) and (err_o2 not in dup_o) and (err_o3 not in dup_o): raise error.TestFail("Expect fail, but run successfully:\n%s" % ret) else: if "chardev already exists" not in dup_o: logging.info("Expect fail,but run successfully:\n%s" % ret) else: if char_dev != "all": #1.hotplug serial device hotplug_device(hotplug_type, char_dev, pts_id) #2.confirm hotplug result confirm_hotplug_result(char_dev, pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") hotplug_device(hotplug_type, "pty", pts_id) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: vm_xml_backup.sync() if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir)
def run(test, params, env): """ Stress test for the hotplug feature of serial device """ vm_name = params.get("main_vm", "vm1") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") load_type = params.get("load_type", "") load_params = params.get("load_params", "") test_count = int(params.get("test_count", 5)) test_type = params.get("test_type", "multi") tmp_dir = os.path.join(data_dir.get_tmp_dir(), "hotplug_serial_load") if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) os.chmod(tmp_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) load_vms = [] if load_type in ['cpu', 'memory', 'io']: params["stress_args"] = load_params load_vms.append( libvirt_vm.VM(vm_name, params, test.bindir, env.get("address_cache"))) vm = env.get_vm(vm_name) session = vm.wait_for_login() def prepare_channel_xml(to_file, char_type, index=1, id=0): params = {} mode = '' if char_type == "file": channel_type = char_type channel_path = ("%s/%s%s" % (tmp_dir, char_type, index)) elif char_type == "socket": channel_type = 'unix' channel_path = ("%s/%s%s" % (tmp_dir, char_type, index)) mode = 'bind' elif char_type == "pty": channel_type = char_type channel_path = ("/dev/pts/%s" % id) params = { 'channel_type_name': channel_type, 'source_path': channel_path, 'source_mode': mode, 'target_type': 'virtio', 'target_name': char_type + str(index) } channel_xml = utlv.create_channel_xml(params, alias=True, address=True) shutil.copyfile(channel_xml.xml, to_file) def hotplug_device(hotplug_type, char_dev, index=1, id=0): if hotplug_type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += ("file,path=%s/file%s,id=file%s" % (tmp_dir, index, index)) dev_add_opt += ( "file%s,name=file%s,bus=virtio-serial0.0,id=file%s" % (index, index, index)) elif char_dev == "socket": char_add_opt += ( "socket,path=%s/socket%s,server,nowait,id=socket%s" % (tmp_dir, index, index)) dev_add_opt += ( "socket%s,name=socket%s,bus=virtio-serial0.0,id=socket%s" % (index, index, index)) elif char_dev == "pty": char_add_opt += "pty,path=/dev/pts/%s,id=pty%s" % (id, index) dev_add_opt += ( "pty%s,name=pty%s,bus=virtio-serial0.0,id=pty%s" % (index, index, index)) virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif hotplug_type == "attach": xml_file = "%s/xml_%s%s" % (tmp_dir, char_dev, index) if char_dev in ["file", "socket"]: prepare_channel_xml(xml_file, char_dev, index) elif char_dev == "pty": prepare_channel_xml(xml_file, char_dev, index, id) virsh.attach_device(vm_name, xml_file, flagstr="--live") def confirm_hotplug_result(char_dev, index=1, id=0): result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() chardev_c = h_o.count("chardev = %s%s" % (char_dev, index)) name_c = h_o.count("name = \"%s%s\"" % (char_dev, index)) if chardev_c == 0 and name_c == 0: test.fail("Cannot get serial device info: '%s'" % h_o) tmp_file = "%s/%s%s" % (tmp_dir, char_dev, index) serial_file = "/dev/virtio-ports/%s%s" % (char_dev, index) if char_dev == "file": session.cmd("echo test > %s" % serial_file) with open(tmp_file, "r") as f: output = f.read() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) output = sock.recv(1024) sock.close() elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): test.fail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) while True: output = p.stdout.readline() if output or p.poll(): break time.sleep(0.2) p.kill() if not output.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, output) test.fail(err_info) def unhotplug_serial_device(hotplug_type, char_dev, index=1): if hotplug_type == "qmp": del_dev_opt = "device_del %s%s" % (char_dev, index) del_char_opt = "chardev-remove %s%s" % (char_dev, index) virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif hotplug_type == "attach": xml_file = "%s/xml_%s%s" % (tmp_dir, char_dev, index) virsh.detach_device(vm_name, xml_file, flagstr="--live") def confirm_unhotplug_result(char_dev, index=1): serial_file = "/dev/virtio-ports/%s%s" % (char_dev, index) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = %s%s" % (char_dev, index)): test.fail("Still can get serial device info: '%s'" % uh_o) if not session.cmd_status("test -e %s" % serial_file): test.fail("File '%s' still exists after unhotplug" % serial_file) # run test case try: # increase workload if load_type in ['cpu', 'memory']: utils_test.load_stress("stress_in_vms", load_vms, params) else: utils_test.load_stress("iozone_in_vms", load_vms, params) if test_type == "multi": for i in range(test_count): if char_dev == "pty": ptsid = utils_misc.aton( utils_misc.get_dev_pts_max_id()) + 1 else: ptsid = 0 hotplug_device(hotplug_type, char_dev, i + 1, id=ptsid) confirm_hotplug_result(char_dev, i + 1, id=ptsid) unhotplug_serial_device(hotplug_type, char_dev, i + 1) confirm_unhotplug_result(char_dev, i + 1) elif test_type == "circle": if char_dev != "all": for i in range(test_count): if char_dev == "pty": ptsid = utils_misc.aton( utils_misc.get_dev_pts_max_id()) + 1 else: ptsid = 0 #1.hotplug serial device hotplug_device(hotplug_type, char_dev, id=ptsid) #2.confirm hotplug result confirm_hotplug_result(char_dev, id=ptsid) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: for i in range(test_count): #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") ptsid = utils_misc.aton( utils_misc.get_dev_pts_max_id()) + 1 hotplug_device(hotplug_type, "pty", id=ptsid) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", id=ptsid) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: session.close() if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir)