[virt-tools-list] [PATCH v3 1/3] addhardware: differentiate duplicate usb devices by bus/addr

Guannan Ren gren at redhat.com
Tue Apr 30 14:53:10 UTC 2013


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




More information about the virt-tools-list mailing list