Permalink
Browse files

virt: kvm_vm.py: checking max ports for usb controller

The usb controller has a limitation of max port which it can provide.
For EHCI controller, the limitation is 6;
For UHCI controller, the limitation is 2.

This patch checks how many devices are attached to an usb controller,
if no free port left on the VM, an exception will be raised.

Changes from V1:
 - Add vm name member in VMUSBControllerPortFullError class.
 - Coding style clean up.

Signed-off-by: Qingtang Zhou <qzhou@redhat.com>
  • Loading branch information...
zhouqt authored and lmr committed Nov 21, 2011
1 parent 730224b commit 6c861c855f6654ed91060b07dbb3c4efd926c6fb
Showing with 49 additions and 4 deletions.
  1. +2 −0 client/tests/kvm/base.cfg.sample
  2. +4 −0 client/tests/kvm/subtests.cfg.sample
  3. +28 −4 client/virt/kvm_vm.py
  4. +15 −0 client/virt/virt_vm.py
@@ -15,6 +15,8 @@ monitor_type = human
usbs = usb1
# USB controller type, can be ehci/uhci
usb_type_usb1 = uhci
+# Max ports on a controller.
+usb_max_port_usb1 = 2
## These configure is used for multifunction support.
# usbs = usb1 usb2
## UHCI's multifunction configure.
@@ -161,6 +161,7 @@ variants:
- ehci:
usbs = usb1
usb_type_usb1 = ehci
+ usb_max_port_usb1 = 6
- keyboard:
extra_params += " -device usb-kbd,id=kbd1"
- mouse:
@@ -170,6 +171,7 @@ variants:
- storage:
usbs = usb1
usb_type_usb1 = ehci
+ usb_max_port_usb1 = 6
images += " stg"
image_name_stg = "usbdevice"
image_format_stg = "qcow2"
@@ -194,6 +196,7 @@ variants:
- ehci:
usbs = usb1
usb_type_usb1 = ehci
+ usb_max_port_usb1 = 6
- keyboard:
extra_params += " -device usb-kbd,id=kbd1"
- mouse:
@@ -203,6 +206,7 @@ variants:
- storage:
usbs = usb1
usb_type_usb1 = ehci
+ usb_max_port_usb1 = 6
images += " stg"
image_name_stg = "usbdevice"
image_format_stg = "qcow2"
View
@@ -63,6 +63,17 @@ def __init__(self, name, params, root_dir, address_cache, state=None):
# We need this to get to the blkdebug files
self.virt_dir = os.path.abspath(os.path.join(root_dir, "..", "..", "virt"))
self.address_cache = address_cache
+ # This usb_dev_dict member stores usb controller and device info,
+ # It's dict, each key is an id of usb controller,
+ # and key's value is a list, contains usb devices' ids which
+ # attach to this controller.
+ # A filled usb_dev_dict may look like:
+ # { "usb1" : ["stg1", "stg2", "stg3", "stg4", "stg5", "stg6"],
+ # "usb2" : ["stg7", "stg8"],
+ # ...
+ # }
+ # This structure can used in usb hotplug/unplug test.
+ self.usb_dev_dict = {}
def verify_alive(self):
@@ -229,7 +240,7 @@ def add_cdrom(help, filename, index=None, format=None):
def add_drive(help, filename, index=None, format=None, cache=None,
werror=None, rerror=None, serial=None, snapshot=False,
- boot=False, blkdebug=None, bus=None):
+ boot=False, blkdebug=None, bus=None, port=None):
name = None;
dev = "";
if format == "ahci":
@@ -243,7 +254,7 @@ def add_drive(help, filename, index=None, format=None, cache=None,
if bus:
dev += ",bus=%s" % bus
dev += ",drive=%s" % name
- dev += ",port=%d" % (int(index) + 1)
+ dev += ",port=%d" % (int(port) + 1)
format = "none"
index = None
if blkdebug is not None:
@@ -409,6 +420,9 @@ def add_usb(help, usb_id, usb_type, multifunction=False,
else:
# Okay, for the archaic qemu which has not device parameter,
# just return a usb uhci controller.
+ # If choose this kind of usb controller, it has no name/id,
+ # and only can be created once, so give it a special name.
+ self.usb_dev_dict["OLDVERSION_usb0"] = []
return " -usb"
if multifunction is True:
@@ -418,6 +432,8 @@ def add_usb(help, usb_id, usb_type, multifunction=False,
if firstport:
cmd += ",firstport=%s" % firstport
+ # register this usb controller.
+ self.usb_dev_dict[usb_id] = []
return cmd
# End of command line option wrappers
@@ -488,12 +504,20 @@ def add_usb(help, usb_id, usb_type, multifunction=False,
have_ahci = True
bus = None
+ port = None
if image_params.get("drive_format") == "usb2":
+ # Find an available USB port.
for usb in params.objects("usbs"):
usb_params = params.object_params(usb)
- if usb_params.get("usb_type") == "ehci":
+ max_port = int(usb_params.get("usb_max_port", 6))
+ if (usb_params.get("usb_type") == "ehci" and
+ len(self.usb_dev_dict.get(usb)) < max_port):
bus = "%s.0" % usb
+ self.usb_dev_dict[usb].append(image_name)
+ port = self.usb_dev_dict[usb].index(image_name)
break
+ if bus is None:
+ raise virt_vm.VMUSBControllerPortFullError(self.name)
qemu_cmd += add_drive(help,
virt_vm.get_image_filename(image_params, root_dir),
@@ -507,7 +531,7 @@ def add_usb(help, usb_id, usb_type, multifunction=False,
image_params.get("image_boot") == "yes",
virt_vm.get_image_blkdebug_filename(image_params,
self.virt_dir),
- bus)
+ bus, port)
redirs = []
for redir_name in params.objects("redirs"):
View
@@ -207,6 +207,21 @@ class VMStatusError(VMError):
class VMRemoveError(VMError):
pass
+class VMUSBError(VMError):
+ pass
+
+class VMUSBControllerError(VMUSBError):
+ pass
+
+class VMUSBControllerPortFullError(VMUSBControllerError):
+ def __init__(self, name):
+ VMUSBControllerError.__init__(self, name)
+ self.name = name
+
+ def __str__(self):
+ return ("No available USB Controller port left for VM %s." % self.name)
+
+
def get_image_blkdebug_filename(params, root_dir):
"""
Generate an blkdebug file path from params and root_dir.

0 comments on commit 6c861c8

Please sign in to comment.