When there are multiple usb devices with same vendor/product in the host device list, the bus/addr is going to be used when attaching one of usb devices. Currently is_dup flag is only useful to VirtualHostDeviceUSB. I put get_nodedevs_number() in connection.py, so the startup hooks can use it. --- tests/nodedev-xml/devxml/usbdev2.xml | 2 ++ tests/nodedev.py | 10 +++------- virtManager/addhardware.py | 23 ++++++++++++++++++++--- virtManager/connection.py | 15 +++++++++++++++ virtinst/VirtualHostDevice.py | 9 +++++---- 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/tests/nodedev-xml/devxml/usbdev2.xml b/tests/nodedev-xml/devxml/usbdev2.xml index 1c8ed82..cf0b50a 100644 --- a/tests/nodedev-xml/devxml/usbdev2.xml +++ b/tests/nodedev-xml/devxml/usbdev2.xml @@ -1,5 +1,7 @@ <hostdev mode='subsystem' type='usb' managed='yes'> <source> + <vendor id='0x0781'/> + <product id='0x5151'/> <address bus='1' device='4'/> </source> </hostdev> diff --git a/tests/nodedev.py b/tests/nodedev.py index 18b162f..9ea2e05 100644 --- a/tests/nodedev.py +++ b/tests/nodedev.py @@ -53,12 +53,12 @@ class TestNodeDev(unittest.TestCase): for attr in vals.keys(): self.assertEqual(vals[attr], getattr(dev, attr)) - def _testNode2DeviceCompare(self, nodename, devfile, nodedev=None): + def _testNode2DeviceCompare(self, nodename, devfile, nodedev=None, is_dup=False): devfile = os.path.join("tests/nodedev-xml/devxml", devfile) if not nodedev: nodedev = self._nodeDevFromName(nodename) - dev = VirtualHostDevice.device_from_node(conn, nodedev=nodedev) + dev = VirtualHostDevice.device_from_node(conn, nodedev=nodedev, is_dup=is_dup) utils.diff_compare(dev.get_xml_config() + "\n", devfile) def testSystemDevice(self): @@ -202,11 +202,7 @@ class TestNodeDev(unittest.TestCase): devfile = "usbdev2.xml" nodedev = self._nodeDevFromName(nodename) - # Force xml building to use bus, addr - nodedev.product_id = None - nodedev.vendor_id = None - - self._testNode2DeviceCompare(nodename, devfile, nodedev=nodedev) + self._testNode2DeviceCompare(nodename, devfile, nodedev=nodedev, is_dup=True) def testNodeDev2PCI(self): nodename = "pci_1180_592" diff --git a/virtManager/addhardware.py b/virtManager/addhardware.py index af36560..e8b4826 100644 --- a/virtManager/addhardware.py +++ b/virtManager/addhardware.py @@ -281,7 +281,7 @@ class vmmAddHardware(vmmGObjectUI): # Host device list # model = [ Description, nodedev name ] host_dev = self.widget("host-device") - host_dev_model = Gtk.ListStore(str, str) + host_dev_model = Gtk.ListStore(str, str, str, object) host_dev.set_model(host_dev_model) host_col = Gtk.TreeViewColumn() @@ -577,7 +577,7 @@ class vmmAddHardware(vmmGObjectUI): if dev.name == subdev.parent: prettyname = dev.pretty_name(subdev) - model.append([prettyname, dev.name]) + model.append([prettyname, dev.name, devtype, dev]) if len(model) == 0: model.append([_("No Devices Available"), None]) @@ -1403,15 +1403,32 @@ class vmmAddHardware(vmmGObjectUI): def validate_page_hostdev(self): ret = self.get_config_host_device_info() nodedev_name = ret and ret[1] or None + is_dup = False if nodedev_name is None: return self.err.val_err(_("Physical Device Required"), _("A device must be selected.")) + devtype = ret[2] + nodedev = ret[3] + if devtype == "usb_device": + vendor = nodedev.vendor_id + product = nodedev.product_id + count = self.conn.get_nodedevs_number(devtype, vendor, product) + if not count: + raise RuntimeError(_("Could not find USB device " + "(vendorId: %s, productId: %s) " + % (vendor, product))) + + if count > 1: + is_dup = True + try: self._dev = virtinst.VirtualHostDevice.device_from_node( conn=self.conn.vmm, - name=nodedev_name) + name=nodedev_name, + nodedev=nodedev, + is_dup=is_dup) except Exception, e: return self.err.val_err(_("Host device parameter error"), e) diff --git a/virtManager/connection.py b/virtManager/connection.py index e6058e3..3b943ec 100644 --- a/virtManager/connection.py +++ b/virtManager/connection.py @@ -712,6 +712,21 @@ class vmmConnection(vmmGObject): return retdevs + def get_nodedevs_number(self, devtype, vendor, product): + count = 0 + devs = self.get_nodedevs(devtype) + + for dev in devs: + if vendor == dev.vendor_id and \ + product == dev.product_id: + count += 1 + + logging.debug("There are %d node devices with " + "vendorId: %s, productId: %s", + count, vendor, product) + + return count + def get_net_by_name(self, name): for net in self.nets.values(): if net.get_name() == name: diff --git a/virtinst/VirtualHostDevice.py b/virtinst/VirtualHostDevice.py index f5740d0..d927641 100644 --- a/virtinst/VirtualHostDevice.py +++ b/virtinst/VirtualHostDevice.py @@ -28,7 +28,7 @@ class VirtualHostDevice(VirtualDevice): _virtual_device_type = VirtualDevice.VIRTUAL_DEV_HOSTDEV - def device_from_node(conn, name=None, nodedev=None): + def device_from_node(conn, name=None, nodedev=None, is_dup=False): """ Convert the passed device name to a VirtualHostDevice instance, with proper error reporting. Name can be any of the @@ -54,7 +54,7 @@ class VirtualHostDevice(VirtualDevice): if isinstance(nodeinst, NodeDeviceParser.PCIDevice): return VirtualHostDevicePCI(conn, nodedev=nodeinst) elif isinstance(nodeinst, NodeDeviceParser.USBDevice): - return VirtualHostDeviceUSB(conn, nodedev=nodeinst) + return VirtualHostDeviceUSB(conn, nodedev=nodeinst, is_dup=is_dup) elif isinstance(nodeinst, NodeDeviceParser.NetDevice): parentname = nodeinst.parent try: @@ -196,11 +196,12 @@ class VirtualHostDevice(VirtualDevice): class VirtualHostDeviceUSB(VirtualHostDevice): - def __init__(self, conn, nodedev=None): + def __init__(self, conn, nodedev=None, is_dup=False): VirtualHostDevice.__init__(self, conn, nodedev) self.mode = "subsystem" self.type = "usb" + self.is_dup = is_dup self._set_from_nodedev(self._nodedev) @@ -215,7 +216,7 @@ class VirtualHostDeviceUSB(VirtualHostDevice): self.vendor = nodedev.vendor_id self.product = nodedev.product_id - if not (self.vendor or self.product): + if self.is_dup: self.bus = nodedev.bus self.device = nodedev.device -- 1.8.1.4 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list