Example #1
0
    def _setup_pty_channel_xml(port_id=0):
        """
        Prepare pty channel devices of VM XML.

        :param port_id: the port id for the channel
        """
        channel_path = ("/dev/pts/%s" % port_id)
        target_name = ('org.linux-kvm.port.%s' % port_id)

        source_dict = {'path': channel_path}
        target_dict = {
            'type': 'virtio',
            'name': target_name,
            'state': 'disconnected'
        }
        address_dict = {'type': 'virtio-serial', 'controller': '0', 'bus': '0'}

        if not port_id:
            address_dict['port'] = '%s' % port_id

        channel_tmp = Channel(type_name=channel_type)
        channel_tmp.source = source_dict
        channel_tmp.target = target_dict
        channel_tmp.address = address_dict

        logging.debug("Channel XML is:%s", channel_tmp)
        vm_xml.add_device(channel_tmp)
    def _check_xml():
        """
        Check defined XML against expectation
        """
        expected_channel = Channel(channel_type)

        try:
            source_dict = channel.source
        except LibvirtXMLNotFoundError:
            source_dict = {}

        if channel_type == 'pty':
            source_dict = {}
        elif channel_type == 'unix':
            if source_mode is None:
                if source_path:
                    source_dict['mode'] = 'connect'
                else:
                    source_dict['mode'] = 'bind'
            if source_path is None:
                source_dict['path'] = _get_autopath()
            if source_autopath:
                del source_dict['autopath']

        target_dict = {}
        if target_type == 'virtio':
            expected_channel.address = {
                'bus': '0',
                'controller': '0',
                'port': '1',
                'type': 'virtio-serial',
            }
            if 'type' in channel.target:
                target_dict['type'] = channel.target['type']
            if 'name' in channel.target:
                target_dict['name'] = channel.target['name']
        elif target_type == 'guestfwd':
            if 'type' in channel.target:
                target_dict['type'] = channel.target['type']
            if 'address' in channel.target:
                target_dict['address'] = channel.target['address']
            if 'port' in channel.target:
                target_dict['port'] = channel.target['port']

        if source_dict:
            expected_channel.source = source_dict
        if target_dict:
            expected_channel.target = target_dict

        current_xml = VMXML.new_from_dumpxml(vm_name)
        channel_elem = current_xml.xmltreefile.find('devices/channel')
        cur_channel = Channel.new_from_element(channel_elem)
        if not (expected_channel == cur_channel):
            raise error.TestFail("Expect generate channel:\n%s\nBut got:\n%s" %
                                 (expected_channel, cur_channel))
    def _check_xml(test):
        """
        Check defined XML against expectation
        """
        expected_channel = Channel(channel_type)

        try:
            source_dict = channel.source
        except LibvirtXMLNotFoundError:
            source_dict = {}

        if channel_type == 'pty':
            source_dict = {}
        elif channel_type == 'unix':
            if source_mode is None:
                if source_path:
                    source_dict['mode'] = 'connect'
                else:
                    source_dict['mode'] = 'bind'
            if source_path is None:
                source_dict['path'] = _get_autopath()
            if source_autopath:
                del source_dict['autopath']

        target_dict = {}
        if target_type == 'virtio':
            expected_channel.address = {
                'bus': '0',
                'controller': '0',
                'port': '1',
                'type': 'virtio-serial',
            }
            if 'type' in channel.target:
                target_dict['type'] = channel.target['type']
            if 'name' in channel.target:
                target_dict['name'] = channel.target['name']
        elif target_type == 'guestfwd':
            if 'type' in channel.target:
                target_dict['type'] = channel.target['type']
            if 'address' in channel.target:
                target_dict['address'] = channel.target['address']
            if 'port' in channel.target:
                target_dict['port'] = channel.target['port']

        if source_dict:
            expected_channel.source = source_dict
        if target_dict:
            expected_channel.target = target_dict

        current_xml = VMXML.new_from_dumpxml(vm_name)
        channel_elem = current_xml.xmltreefile.find('devices/channel')
        cur_channel = Channel.new_from_element(channel_elem)
        if not (expected_channel == cur_channel):
            test.fail("Expect generate channel:\n%s\nBut got:\n%s" %
                      (expected_channel, cur_channel))
def run(test, params, env):
    """
    Test virtio/virtio-transitional model of serial device

    :param test: Test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment
    """
    def get_free_pci_slot():
        """
        Get a free slot from pcie-to-pci-bridge

        :return: The free slot
        """
        used_slot = []
        for dev in pci_devices:
            address = dev.find('address')
            if (address is not None
                    and address.get('bus') == pci_bridge_index):
                used_slot.append(address.get('slot'))
        for slot_index in range(1, 30):
            slot = "%0#4x" % slot_index
            if slot not in used_slot:
                return slot
        return None

    def test_data_transfer(dev_type):
        """
        Test data transfer between guest and host via console/serial device

        :param dev_type: The device type to be tested, console or channel
        """
        vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
        console_xml = vmxml.xmltreefile.find('devices').find(dev_type)
        host_path = console_xml.find('source').get('path')
        guest_path = '/dev/hvc0' if dev_type == 'console' else '/dev/vport0p1'
        test_message = 'virtiochannel'
        cat_cmd = "cat %s" % host_path
        logfile = "test_data_transfer-%s.log" % dev_type
        host_process = aexpect.ShellSession(cat_cmd,
                                            auto_close=False,
                                            output_func=utils_misc.log_line,
                                            output_params=(logfile, ))
        guest_session = vm.wait_for_login()
        guest_session.cmd_output('echo %s > %s' % (test_message, guest_path))
        guest_session.close()
        try:
            host_process.read_until_last_line_matches(test_message, timeout=10)
        except aexpect.exceptions.ExpectError as e:
            test.fail('Did not catch the expected output from host side,'
                      ' the detail of the failure: %s' % str(e))
        finally:
            host_process.close()

    vm_name = params.get("main_vm", "avocado-vt-vm1")
    vm = env.get_vm(params["main_vm"])
    vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
    backup_xml = vmxml.copy()
    add_pcie_to_pci_bridge = params.get("add_pcie_to_pci_bridge")
    guest_src_url = params.get("guest_src_url")
    virtio_model = params['virtio_model']

    # Download and replace image when guest_src_url provided
    if guest_src_url:
        image_name = params['image_path']
        target_path = utils_misc.get_path(data_dir.get_data_dir(), image_name)
        if not os.path.exists(target_path):
            download.get_file(guest_src_url, target_path)
        params["blk_source_name"] = target_path

    # Add pcie-to-pci-bridge when it is required
    if add_pcie_to_pci_bridge:
        pci_controllers = vmxml.get_controllers('pci')
        for controller in pci_controllers:
            if controller.get('model') == 'pcie-to-pci-bridge':
                pci_bridge = controller
                break
        else:
            contr_dict = {
                'controller_type': 'pci',
                'controller_model': 'pcie-to-pci-bridge'
            }
            pci_bridge = libvirt.create_controller_xml(contr_dict,
                                                       "add_controller",
                                                       vm_name)
        pci_bridge_index = '%0#4x' % int(pci_bridge.get("index"))

    try:
        # Update interface to virtio-transitional mode for
        # rhel6 guest to make it works for login
        iface_params = {'model': 'virtio-transitional'}
        libvirt.modify_vm_iface(vm_name, "update_iface", iface_params)
        libvirt.set_vm_disk(vm, params)
        # vmxml will not be updated since set_vm_disk
        # sync with another dumped xml inside the function
        vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

        # Remove all current serial devices
        vmxml.remove_all_device_by_type('serial')
        vmxml.remove_all_device_by_type('channel')
        vmxml.remove_all_device_by_type('console')
        vmxml.del_controller('virtio-serial')
        vmxml.sync()

        # Add virtio-serial with right model
        contr_dict = {
            'controller_type': 'virtio-serial',
            'controller_model': virtio_model
        }
        if add_pcie_to_pci_bridge:
            pci_devices = vmxml.xmltreefile.find('devices').getchildren()
            slot = get_free_pci_slot()
            addr = '{"bus": %s, "slot": %s}' % (pci_bridge_index, slot)
            contr_dict.update({'controller_addr': addr})
        libvirt.create_controller_xml(contr_dict, "add_controller", vm_name)
        # vmxml will not be updated since set_vm_disk
        # sync with another dumped xml inside the function
        vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

        # Add channel and console device attached to virtio-serial bus
        target_dict = {'type': 'virtio', 'name': 'ptychannel'}
        address_dict = {'type': 'virtio-serial', 'controller': '0', 'bus': '0'}
        channel_xml = Channel('pty')
        channel_xml.target = target_dict
        channel_xml.address = address_dict
        console_xml = Console()
        console_xml.target_port = '0'
        console_xml.target_type = 'virtio'
        vmxml.add_device(channel_xml)
        vmxml.add_device(console_xml)
        vmxml.sync()
        if vm.is_alive():
            vm.destroy()
        vm.start(autoconsole=False)

        # Test data transfer via console and channel devices
        test_data_transfer('console')
        test_data_transfer('channel')
    finally:
        vm.destroy()
        backup_xml.sync()
def run(test, params, env):
    """
    Test for basic channel device function.

    1) Define the VM with specified channel device and check result meets
       expectation.
    2) Start the guest and check if start result meets expectation
    3) Test the function of started channel device
    4) Shutdown the VM and clean up environment
    """

    def _setup_channel_xml():
        """
        Prepare channel devices of VM XML according to params.
        """

        source_dict = {}
        target_dict = {}
        if source_mode is not None:
            source_dict['mode'] = source_mode
        if source_path is not None:
            source_dict['path'] = source_path
        if source_autopath is not None:
            source_dict['autopath'] = source_autopath
        if target_type is not None:
            target_dict['type'] = target_type
        if target_name is not None:
            target_dict['name'] = target_name
        if target_state is not None:
            target_dict['state'] = target_state
        if target_address is not None:
            target_dict['address'] = target_address
        if target_port is not None:
            target_dict['port'] = target_port

        if source_dict:
            channel.source = source_dict
        if target_dict:
            channel.target = target_dict

        logging.debug("Channel XML is:%s", channel)
        vm_xml.add_device(channel)

    def _define_and_check():
        """
        Predict the error message when defining and try to define the guest
        with testing XML.
        """
        fail_patts = []

        if target_type not in ['virtio', 'guestfwd', 'spicevmc']:
            fail_patts.append(
                r"target type must be specified for channel device")
            fail_patts.append(
                r"unknown target type '.*' specified for character device")
        if target_type == 'guestfwd':
            if target_address is None:
                fail_patts.append(
                    r"guestfwd channel does not define a target address")
            if target_port is None:
                fail_patts.append(
                    r"guestfwd channel does not define a target port")
            if channel_type == 'unix' and source_path is None:
                fail_patts.append(
                    r"Missing source path attribute for char device")
        vm_xml.undefine()
        res = vm_xml.virsh.define(vm_xml.xml)
        libvirt.check_result(res, expected_fails=fail_patts)
        return not res.exit_status

    def _get_autopath():
        """
        Predict automatic generated source path
        """
        base_path = '/var/lib/libvirt/qemu/channel/target/%s.' % vm_name
        if target_name:
            return base_path + target_name
        else:
            return base_path + '(null)'

    def _check_xml(test):
        """
        Check defined XML against expectation
        """
        expected_channel = Channel(channel_type)

        try:
            source_dict = channel.source
        except LibvirtXMLNotFoundError:
            source_dict = {}

        if channel_type == 'pty':
            source_dict = {}
        elif channel_type == 'unix':
            if source_mode is None:
                if source_path:
                    source_dict['mode'] = 'connect'
                else:
                    source_dict['mode'] = 'bind'
            if source_path is None:
                source_dict['path'] = _get_autopath()
            if source_autopath:
                del source_dict['autopath']

        target_dict = {}
        if target_type == 'virtio':
            expected_channel.address = {
                'bus': '0',
                'controller': '0',
                'port': '1',
                'type': 'virtio-serial',
            }
            if 'type' in channel.target:
                target_dict['type'] = channel.target['type']
            if 'name' in channel.target:
                target_dict['name'] = channel.target['name']
        elif target_type == 'guestfwd':
            if 'type' in channel.target:
                target_dict['type'] = channel.target['type']
            if 'address' in channel.target:
                target_dict['address'] = channel.target['address']
            if 'port' in channel.target:
                target_dict['port'] = channel.target['port']

        if source_dict:
            expected_channel.source = source_dict
        if target_dict:
            expected_channel.target = target_dict

        current_xml = VMXML.new_from_dumpxml(vm_name)
        channel_elem = current_xml.xmltreefile.find('devices/channel')
        cur_channel = Channel.new_from_element(channel_elem)
        if not (expected_channel == cur_channel):
            test.fail("Expect generate channel:\n%s\nBut got:\n%s" %
                      (expected_channel, cur_channel))

    def _start_and_check():
        """
        Predict the error message when starting and try to start the guest.
        """
        fail_patts = []

        if channel_type == 'unix' and source_path and source_mode != 'bind':
            fail_patts.append(r"No such file or directory")

        res = virsh.start(vm_name)
        libvirt.check_result(res, expected_fails=fail_patts)
        return not res.exit_status

    def _check_virtio_guest_channel(test):
        """
        Check virtio guest channel state against expectation.
        """

        def _find_comm_paths(session):
            if source_path is None:
                host_path = _get_autopath()
            else:
                host_path = source_path

            name_port_map = {}
            base_path = '/sys/class/virtio-ports'
            vports = session.cmd_output('ls %s' % base_path).split()
            status = session.cmd_status('ls %s/*/name' % base_path)
            if status == 0:
                for vport in vports:
                    vport_path = os.path.join(base_path, vport)
                    name_path = os.path.join(vport_path, 'name')
                    name = session.cmd_output('cat %s' % name_path).strip()
                    name_port_map[name] = vport

                if expect_name not in name_port_map:
                    test.fail("Expect get vport name %s, got %s" %
                              (expect_name, name_port_map))
                vport = name_port_map[expect_name]
            else:
                active_xml = VMXML.new_from_dumpxml(vm_name)
                port_number = active_xml.xmltreefile.find(
                    '/devices/channel/address').get('port')
                vport = 'vport1p%s' % port_number
            guest_path = '/dev/%s' % vport
            return guest_path, host_path

        def _test_unix_communication(session, guest_path, host_path, test):
            """
            Test unix socket communication between host and guest through
            channel
            """
            nc_session = aexpect.Expect('nc -U "%s"' % host_path)
            try:
                # Test message passing from guest to host
                msg = "What hath God wrought"
                try:
                    session.cmd_status('echo "%s" > %s' % (msg, guest_path),
                                       timeout=1)
                except aexpect.ShellTimeoutError as detail:
                    pass
                nc_session.read_until_last_line_matches(msg, timeout=1)

                # Test message passing from host to guest
                nc_session.sendline(msg)
                try:
                    session.cmd_output('cat %s' % guest_path, timeout=1)
                except aexpect.ShellTimeoutError as detail:
                    if detail.output.strip() != msg:
                        test.fail("Expect receive '%s' in guest, "
                                  "But got %s" %
                                  (msg, detail.output))
            finally:
                nc_session.close()

        if target_name is None:
            expect_name = 'com.redhat.spice.0'
        else:
            expect_name = target_name

        if channel_type == 'unix':
            session = vm.wait_for_login()
            try:
                guest_path, host_path = _find_comm_paths(session)
                _test_unix_communication(session, guest_path, host_path, test)
            finally:
                session.close()

    channel_type = params.get('channel_type', None)
    source_mode = params.get('channel_source_mode', None)
    source_path = params.get('channel_source_path', None)
    source_autopath = params.get('channel_source_autopath', None)
    target_type = params.get('channel_target_type', None)
    target_name = params.get('channel_target_name', None)
    target_state = params.get('channel_target_state', None)
    target_address = params.get('channel_target_address', None)
    target_port = params.get('channel_target_port', None)

    channel = Channel(type_name=channel_type)

    vm_name = params.get("main_vm", "virt-tests-vm1")

    vm = env.get_vm(vm_name)
    vm_xml = VMXML.new_from_inactive_dumpxml(vm_name)
    vm_xml_backup = vm_xml.copy()
    try:
        vm_xml.remove_all_device_by_type('channel')
        _setup_channel_xml()
        logging.debug("Test VM XML is %s" % vm_xml)

        if not _define_and_check():
            logging.debug("Can't define the VM, exiting.")
            return

        _check_xml(test)

        if not _start_and_check():
            logging.debug("Can't start the VM, exiting.")
            return

        if target_type == 'virtio':
            _check_virtio_guest_channel(test)
    finally:
        vm_xml_backup.sync()
Example #6
0
                guest_path, host_path = _find_comm_paths(session)
                _test_unix_communication(session, guest_path, host_path)
            finally:
                session.close()

    channel_type = params.get('channel_type', None)
    source_mode = params.get('channel_source_mode', None)
    source_path = params.get('channel_source_path', None)
    source_autopath = params.get('channel_source_autopath', None)
    target_type = params.get('channel_target_type', None)
    target_name = params.get('channel_target_name', None)
    target_state = params.get('channel_target_state', None)
    target_address = params.get('channel_target_address', None)
    target_port = params.get('channel_target_port', None)

    channel = Channel(type_name=channel_type)

    vm_name = params.get("main_vm", "virt-tests-vm1")

    vm = env.get_vm(vm_name)
    vm_xml = VMXML.new_from_inactive_dumpxml(vm_name)
    vm_xml_backup = vm_xml.copy()
    try:
        vm_xml.remove_all_device_by_type('channel')
        _setup_channel_xml()
        logging.debug("Test VM XML is %s" % vm_xml)

        if not _define_and_check():
            logging.debug("Can't define the VM, exiting.")
            return
Example #7
0
def run(test, params, env):
    """
    Test for basic channel device function.

    1) Define the VM with specified channel device and check result meets
       expectation.
    2) Start the guest and check if start result meets expectation
    3) Test the function of started channel device
    4) Shutdown the VM and clean up environment
    """
    def prepare_channel_xml(to_file, char_type, port_id=0):
        """
        Prepare pty or spicevmc channel devices file to do hotplug.

        :param to_file: the file generated
        :param char_type: the type of the channel
        :param port_id: the port id, if '0' specified, means auto gen
        """
        params = {
            'channel_type_name': char_type,
            'target_type': 'virtio',
            'target_state': 'disconnected',
            'address_type': 'virtio-serial',
            'address_controller': '0',
            'address_bus': '0'
        }

        if char_type == "pty":
            channel_path = ("/dev/pts/%s" % port_id)
            params_tmp = {
                'source_path': channel_path,
                'target_name': 'org.linux-kvm.port.%s' % port_id
            }
            params.update(params_tmp)
            if not port_id:
                params['address_port'] = '%s' % port_id
        elif char_type == "spicevmc":
            params['target_name'] = 'com.redhat.spice.0'
        channel_xml = utlv.create_channel_xml(params, alias=True, address=True)
        shutil.copyfile(channel_xml.xml, to_file)

    def _setup_pty_channel_xml(port_id=0):
        """
        Prepare pty channel devices of VM XML.

        :param port_id: the port id for the channel
        """
        channel_path = ("/dev/pts/%s" % port_id)
        target_name = ('org.linux-kvm.port.%s' % port_id)

        source_dict = {'path': channel_path}
        target_dict = {
            'type': 'virtio',
            'name': target_name,
            'state': 'disconnected'
        }
        address_dict = {'type': 'virtio-serial', 'controller': '0', 'bus': '0'}

        if not port_id:
            address_dict['port'] = '%s' % port_id

        channel_tmp = Channel(type_name=channel_type)
        channel_tmp.source = source_dict
        channel_tmp.target = target_dict
        channel_tmp.address = address_dict

        logging.debug("Channel XML is:%s", channel_tmp)
        vm_xml.add_device(channel_tmp)

    def _setup_channel_xml():
        """
        Prepare channel devices of VM XML according to params.
        """

        source_dict = {}
        target_dict = {}
        if source_mode is not None:
            source_dict['mode'] = source_mode
        if source_path is not None:
            source_dict['path'] = source_path
        if source_autopath is not None:
            source_dict['autopath'] = source_autopath
        if target_type is not None:
            target_dict['type'] = target_type
        if target_name is not None:
            target_dict['name'] = target_name
        if target_state is not None:
            target_dict['state'] = target_state
        if target_address is not None:
            target_dict['address'] = target_address
        if target_port is not None:
            target_dict['port'] = target_port

        if source_dict:
            channel.source = source_dict
        if target_dict:
            channel.target = target_dict

        logging.debug("Channel XML is:%s", channel)
        vm_xml.add_device(channel)

    def _define_and_check():
        """
        Predict the error message when defining and try to define the guest
        with testing XML.
        """
        fail_patts = []

        if not auto_gen_port and \
           target_type not in ['virtio', 'guestfwd', 'spicevmc']:
            fail_patts.append(
                r"target type must be specified for channel device")
            fail_patts.append(
                r"unknown target type '.*' specified for character device")
        if not auto_gen_port and target_type == 'guestfwd':
            if target_address is None:
                fail_patts.append(
                    r"guestfwd channel does not define a target address")
            if target_port is None:
                fail_patts.append(
                    r"guestfwd channel does not define a target port")
            if channel_type == 'unix' and source_path is None:
                fail_patts.append(
                    r"Missing source path attribute for char device")
        vm_xml.undefine()
        res = vm_xml.virsh.define(vm_xml.xml)
        libvirt.check_result(res, expected_fails=fail_patts)
        return not res.exit_status

    def _get_autopath():
        """
        Predict automatic generated source path
        """
        base_path = '/var/lib/libvirt/qemu/channel/target/%s.' % vm_name
        if target_name:
            return base_path + target_name
        else:
            return base_path + '(null)'

    def _check_xml(test):
        """
        Check defined XML against expectation
        """
        expected_channel = Channel(channel_type)

        try:
            source_dict = channel.source
        except LibvirtXMLNotFoundError:
            source_dict = {}

        if channel_type == 'pty':
            source_dict = {}
        elif channel_type == 'unix':
            if source_mode is None:
                if source_path:
                    source_dict['mode'] = 'connect'
                else:
                    source_dict['mode'] = 'bind'
            if source_path is None:
                source_dict['path'] = _get_autopath()
            if source_autopath:
                del source_dict['autopath']

        target_dict = {}
        if target_type == 'virtio':
            expected_channel.address = {
                'bus': '0',
                'controller': '0',
                'port': '1',
                'type': 'virtio-serial',
            }
            if 'type' in channel.target:
                target_dict['type'] = channel.target['type']
            if 'name' in channel.target:
                target_dict['name'] = channel.target['name']
        elif target_type == 'guestfwd':
            if 'type' in channel.target:
                target_dict['type'] = channel.target['type']
            if 'address' in channel.target:
                target_dict['address'] = channel.target['address']
            if 'port' in channel.target:
                target_dict['port'] = channel.target['port']

        if source_dict:
            expected_channel.source = source_dict
        if target_dict:
            expected_channel.target = target_dict

        current_xml = VMXML.new_from_dumpxml(vm_name)
        channel_elem = current_xml.xmltreefile.find('devices/channel')
        cur_channel = Channel.new_from_element(channel_elem)
        if not (expected_channel == cur_channel):
            test.fail("Expect generate channel:\n%s\nBut got:\n%s" %
                      (expected_channel, cur_channel))

    def _start_and_check():
        """
        Predict the error message when starting and try to start the guest.
        """
        fail_patts = []

        if channel_type == 'unix' and source_path and source_mode != 'bind':
            fail_patts.append(r"No such file or directory")

        res = virsh.start(vm_name)
        libvirt.check_result(res, expected_fails=fail_patts)
        return not res.exit_status

    def _check_virtio_guest_channel(test):
        """
        Check virtio guest channel state against expectation.
        """
        def _find_comm_paths(session):
            if source_path is None:
                host_path = _get_autopath()
            else:
                host_path = source_path

            name_port_map = {}
            base_path = '/sys/class/virtio-ports'
            vports = session.cmd_output('ls %s' % base_path).split()
            status = session.cmd_status('ls %s/*/name' % base_path)
            if status == 0:
                for vport in vports:
                    vport_path = os.path.join(base_path, vport)
                    name_path = os.path.join(vport_path, 'name')
                    name = session.cmd_output('cat %s' % name_path).strip()
                    name_port_map[name] = vport

                if expect_name not in name_port_map:
                    test.fail("Expect get vport name %s, got %s" %
                              (expect_name, name_port_map))
                vport = name_port_map[expect_name]
            else:
                active_xml = VMXML.new_from_dumpxml(vm_name)
                port_number = active_xml.xmltreefile.find(
                    '/devices/channel/address').get('port')
                vport = 'vport1p%s' % port_number
            guest_path = '/dev/%s' % vport
            return guest_path, host_path

        def _test_unix_communication(session, guest_path, host_path, test):
            """
            Test unix socket communication between host and guest through
            channel
            """
            nc_session = aexpect.Expect('nc -U "%s"' % host_path)
            try:
                # Test message passing from guest to host
                msg = "What hath God wrought"
                try:
                    session.cmd_status('echo "%s" > %s' % (msg, guest_path),
                                       timeout=1)
                except aexpect.ShellTimeoutError as detail:
                    pass
                nc_session.read_until_last_line_matches(msg, timeout=1)

                # Test message passing from host to guest
                nc_session.sendline(msg)
                try:
                    session.cmd_output('cat %s' % guest_path, timeout=1)
                except aexpect.ShellTimeoutError as detail:
                    if detail.output.strip() != msg:
                        test.fail("Expect receive '%s' in guest, "
                                  "But got %s" % (msg, detail.output))
            finally:
                nc_session.close()

        if target_name is None:
            expect_name = 'com.redhat.spice.0'
        else:
            expect_name = target_name

        if channel_type == 'unix':
            session = vm.wait_for_login()
            try:
                guest_path, host_path = _find_comm_paths(session)
                _test_unix_communication(session, guest_path, host_path, test)
            finally:
                session.close()

    def _verify_attach_channel_device(char_type, port_id):
        """
        Test unix socket communication between host and guest through
        channel
        :param char_type: the type of the channel
        :param port_id: the port id of the channel
        """
        result = virsh.attach_device(vm_name, xml_file)
        if result.stderr:
            test.fail('Failed to attach %s to %s. Result:\n %s' %
                      ('pty', vm_name, result))
        current_xml = VMXML.new_from_dumpxml(vm_name)
        channel_devices = current_xml.get_devices('channel')

        found_dev = False
        for channel_device in channel_devices:
            if channel_device.address['port'] == port_id:
                found_dev = True
            break
        if not found_dev:
            logging.debug("Failed to find channel with port %s", port_id)
        return found_dev

    channel_type = params.get('channel_type', None)
    source_mode = params.get('channel_source_mode', None)
    source_path = params.get('channel_source_path', None)
    source_autopath = params.get('channel_source_autopath', None)
    target_type = params.get('channel_target_type', None)
    target_name = params.get('channel_target_name', None)
    target_state = params.get('channel_target_state', None)
    target_address = params.get('channel_target_address', None)
    target_port = params.get('channel_target_port', None)
    auto_gen_port = params.get('auto_gen_port', 'no') == 'yes'

    channel = Channel(type_name=channel_type)

    vm_name = params.get("main_vm", "virt-tests-vm1")

    vm = env.get_vm(vm_name)
    vm_xml = VMXML.new_from_inactive_dumpxml(vm_name)
    vm_xml_backup = vm_xml.copy()
    try:
        vm_xml.remove_all_device_by_type('channel')
        if auto_gen_port:
            _setup_pty_channel_xml(2)
            _setup_pty_channel_xml(8)

            tmp_dir = os.path.join(data_dir.get_tmp_dir(), "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)

            xml_file = os.path.join(tmp_dir, "xml_%s" % 'pty')
            prepare_channel_xml(xml_file, 'pty')
        else:
            _setup_channel_xml()
        logging.debug("Test VM XML is %s" % vm_xml)

        if not _define_and_check():
            logging.debug("Can't define the VM, exiting.")
            return

        if not auto_gen_port:
            _check_xml(test)

        if not _start_and_check():
            logging.debug("Can't start the VM, exiting.")
            return

        if target_type == 'virtio':
            _check_virtio_guest_channel(test)

        if auto_gen_port:
            found_dev = _verify_attach_channel_device('pty', '1')
            if not found_dev:
                test.fail("Failed to attach a device with a fixed port id")

            xml_file = os.path.join(tmp_dir, "xml_%s" % 'spicevmc')
            prepare_channel_xml(xml_file, 'spicevmc')

            found_dev = _verify_attach_channel_device('spicevmc', '3')
            if not found_dev:
                test.fail("Failed to autogen port id during attach device")
    finally:
        if os.path.exists(tmp_dir):
            shutil.rmtree(tmp_dir)
        vm_xml_backup.sync()