Adds optional parameter virtio_scsi_queues to kvm options. Option is ignored
if set to "1" and the maximum number of queues is limited to "8". Effectively
it adds the attribute num_queues to virtio-scsi-pci controller.

Reviewed-by: Luka Blaskovic <[email protected]>
Signed-off-by: Marko Sikiric <[email protected]>
---
 lib/hypervisor/hv_base.py         |  6 +++++-
 lib/hypervisor/hv_kvm/__init__.py | 23 +++++++++++++++++++----
 man/gnt-instance.rst              |  7 +++++++
 src/Ganeti/Constants.hs           |  4 ++++
 4 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/lib/hypervisor/hv_base.py b/lib/hypervisor/hv_base.py
index 8aaa062..1efd782 100644
--- a/lib/hypervisor/hv_base.py
+++ b/lib/hypervisor/hv_base.py
@@ -121,7 +121,9 @@ _NET_PORT_CHECK = (lambda x: 0 < x < 65535, "invalid port 
number",
 # Check if number of queues is in safe range
 _VIRTIO_NET_QUEUES_CHECK = (lambda x: 0 < x < 9, "invalid number of queues",
                             None, None)
-
+# Check in number of queues is in safe range
+_VIRTIO_SCSI_QUEUES_CHECK = (lambda x: 0 < x < 9,"invalid number of queues",
+                            None, None)
 # Check that an integer is non negative
 _NONNEGATIVE_INT_CHECK = (lambda x: x >= 0, "cannot be negative", None, None)
 
@@ -136,6 +138,8 @@ REQ_NET_PORT_CHECK = (True, ) + _NET_PORT_CHECK
 OPT_NET_PORT_CHECK = (False, ) + _NET_PORT_CHECK
 REQ_VIRTIO_NET_QUEUES_CHECK = (True, ) + _VIRTIO_NET_QUEUES_CHECK
 OPT_VIRTIO_NET_QUEUES_CHECK = (False, ) + _VIRTIO_NET_QUEUES_CHECK
+REQ_VIRTIO_SCSI_QUEUES_CHECK = (True, ) + _VIRTIO_SCSI_QUEUES_CHECK
+OPT_VIRTIO_SCSI_QUEUES_CHECK = (False, ) + _VIRTIO_SCSI_QUEUES_CHECK
 REQ_CPU_MASK_CHECK = (True, ) + _CPU_MASK_CHECK
 OPT_CPU_MASK_CHECK = (False, ) + _CPU_MASK_CHECK
 REQ_MULTI_CPU_MASK_CHECK = (True, ) + _MULTI_CPU_MASK_CHECK
diff --git a/lib/hypervisor/hv_kvm/__init__.py 
b/lib/hypervisor/hv_kvm/__init__.py
index fa7f7b3..796d73e 100644
--- a/lib/hypervisor/hv_kvm/__init__.py
+++ b/lib/hypervisor/hv_kvm/__init__.py
@@ -478,6 +478,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
       hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
     constants.HV_VHOST_NET: hv_base.NO_CHECK,
     constants.HV_VIRTIO_NET_QUEUES: hv_base.OPT_VIRTIO_NET_QUEUES_CHECK,
+    constants.HV_VIRTIO_SCSI_QUEUES: hv_base.OPT_VIRTIO_SCSI_QUEUES_CHECK,
     constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
     constants.HV_KVM_USER_SHUTDOWN: hv_base.NO_CHECK,
     constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
@@ -533,6 +534,9 @@ class KVMHypervisor(hv_base.BaseHypervisor):
   _DEVICE_DRIVER_SUPPORTED = \
     staticmethod(lambda drv, devlist:
                  re.compile(r"^name \"%s\"" % drv, re.M).search(devlist))
+  _DEVICE_DRIVER_QUEUES = \
+    staticmethod(lambda drv, devinfo:
+                 re.compile(r"^%s\.num_queues" % drv, re.M).search(devinfo))
   # match  -drive.*boot=on|off on different lines, but in between accept only
   # dashes not preceeded by a new line (which would mean another option
   # different than -drive is starting)
@@ -1205,10 +1209,21 @@ class KVMHypervisor(hv_base.BaseHypervisor):
       # In case a SCSI disk is given, QEMU adds
       # a SCSI contorller (LSI Logic / Symbios Logic 53c895a)
       # automatically. Here, we add it explicitly with the default id.
-      kvm_cmd.extend([
-        "-device",
-        "%s,id=scsi" % hvp[constants.HV_KVM_SCSI_CONTROLLER_TYPE]
-        ])
+      # Also multiqueue option is added if set and supported.
+      num_queues = hvp[constants.HV_VIRTIO_SCSI_QUEUES]
+      scsi_cont = hvp[constants.HV_KVM_SCSI_CONTROLLER_TYPE]
+      optlist = ("%s,id=scsi" % scsi_cont)
+      if num_queues > 1:
+        result = utils.RunCmd([kvm] + ["-device", "%s,?" % scsi_cont])
+        if result.failed:
+          raise errors.HypervisorError("Unable to get KVM device options")
+        if self._DEVICE_DRIVER_QUEUES(scsi_cont, result.output):
+          optlist += (",num_queues=%d" % num_queues)
+        else:
+          raise errors.HypervisorError(\
+                       "Device driver does not support multiqueue")
+
+      kvm_cmd.extend(["-device", optlist])
 
     kvm_cmd.extend(["-balloon", "virtio"])
     kvm_cmd.extend(["-daemonize"])
diff --git a/man/gnt-instance.rst b/man/gnt-instance.rst
index 7794df7..dec0c48 100644
--- a/man/gnt-instance.rst
+++ b/man/gnt-instance.rst
@@ -343,6 +343,13 @@ scsi\_controller\_type
     - megasas
     - virtio-scsi-pci
 
+virtio\_scsi\_queues
+    Valid for the KVM hypervisor.
+
+    This optional parameter enables each virtual CPU to have a separate
+    queue and interrupt to use without affecting other vCPUs. It adds
+    the attribute num\_queues to the SCSI controller if supported. It is
+    ignored if set to to 1 and the maximum number of queues is limited to 
``8``.
 
 disk\_type
     Valid for the Xen HVM and KVM hypervisors.
diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
index cb345d8..2cfbbd7 100644
--- a/src/Ganeti/Constants.hs
+++ b/src/Ganeti/Constants.hs
@@ -1821,6 +1821,8 @@ hvVhostNet = "vhost_net"
 hvVirtioNetQueues :: String
 hvVirtioNetQueues = "virtio_net_queues"
 
+hvVirtioScsiQueues :: String
+hvVirtioScsiQueues = "virtio_scsi_queues"
 hvVifScript :: String
 hvVifScript = "vif_script"
 
@@ -1946,6 +1948,7 @@ hvsParameterTypes = Map.fromList
   , (hvVga,                             VTypeString)
   , (hvVhostNet,                        VTypeBool)
   , (hvVirtioNetQueues,                 VTypeInt)
+  , (hvVirtioScsiQueues,                VTypeInt)
   , (hvVifScript,                       VTypeString)
   , (hvVifType,                         VTypeString)
   , (hvViridian,                        VTypeBool)
@@ -4036,6 +4039,7 @@ hvcDefaults =
           , (hvKvmFlag,                         PyValueEx "")
           , (hvVhostNet,                        PyValueEx False)
           , (hvVirtioNetQueues,                 PyValueEx (1 :: Int))
+          , (hvVirtioScsiQueues,                PyValueEx (1 :: Int))
           , (hvKvmUseChroot,                    PyValueEx False)
           , (hvKvmUserShutdown,                 PyValueEx False)
           , (hvMemPath,                         PyValueEx "")
-- 
2.5.0

Reply via email to