Change in vdsm[ovirt-3.6]: hostdev: change ownership for passthrough USB devices
mpolednik at redhat.com
mpolednik at redhat.com
Tue Sep 22 14:04:44 UTC 2015
Martin Polednik has uploaded a new change for review.
Change subject: hostdev: change ownership for passthrough USB devices
......................................................................
hostdev: change ownership for passthrough USB devices
In order co correctly passthrough an USB device while qemu doesn't run
under root user, permission must be set for
/dev/bus/usb/${bus}/${device} node so qemu can access it. This patch
dynamically changes the ownership of the node and later reverts it
and triggers relevant udev rules.
Change-Id: I1f72f63186187254cd4aded0a2e6c396001ca28b
Bug-Url: https://bugzilla.redhat.com/1248105
Signed-off-by: Martin Polednik <mpolednik at redhat.com>
---
M vdsm/hostdev.py
M vdsm/supervdsmServer
2 files changed, 57 insertions(+), 2 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/27/46527/1
diff --git a/vdsm/hostdev.py b/vdsm/hostdev.py
index 01e22fe..0638557 100644
--- a/vdsm/hostdev.py
+++ b/vdsm/hostdev.py
@@ -173,28 +173,38 @@
def detach_detachable(device_name):
libvirt_device, device_params = _get_device_ref_and_params(device_name)
+ capability = CAPABILITY_TO_XML_ATTR[device_params['capability']]
- if CAPABILITY_TO_XML_ATTR[device_params['capability']] == 'pci':
+ if capability == 'pci':
try:
iommu_group = device_params['iommu_group']
except KeyError:
raise NoIOMMUSupportException('hostdev passthrough without iommu')
supervdsm.getProxy().appropriateIommuGroup(iommu_group)
libvirt_device.detachFlags(None)
+ elif capability == 'usb':
+ supervdsm.getProxy().appropriateUSBDevice(
+ device_params['address']['bus'],
+ device_params['address']['device'])
return device_params
def reattach_detachable(device_name):
libvirt_device, device_params = _get_device_ref_and_params(device_name)
+ capability = CAPABILITY_TO_XML_ATTR[device_params['capability']]
- if CAPABILITY_TO_XML_ATTR[device_params['capability']] == 'pci':
+ if capability == 'pci':
try:
iommu_group = device_params['iommu_group']
except KeyError:
raise NoIOMMUSupportException
supervdsm.getProxy().rmAppropriateIommuGroup(iommu_group)
libvirt_device.reAttach()
+ elif capability == 'usb':
+ supervdsm.getProxy().rmAppropriateUSBDevice(
+ device_params['address']['bus'],
+ device_params['address']['device'])
def change_numvfs(device_name, numvfs):
diff --git a/vdsm/supervdsmServer b/vdsm/supervdsmServer
index 0dc0670..fddd0f6 100755
--- a/vdsm/supervdsmServer
+++ b/vdsm/supervdsmServer
@@ -91,6 +91,10 @@
_UDEV_RULE_FILE_NAME_VFIO = os.path.join(
_UDEV_RULE_FILE_DIR, _UDEV_RULE_FILE_PREFIX + "iommu_group_%s" +
_UDEV_RULE_FILE_EXT)
+_UDEV_RULE_FILE_NAME_USB = os.path.join(
+ _UDEV_RULE_FILE_DIR, _UDEV_RULE_FILE_PREFIX + "usb_%s_%s" +
+ _UDEV_RULE_FILE_EXT)
+_USB_DEVICE_PATH = '/dev/bus/usb/%03d/%03d'
RUN_AS_TIMEOUT = config.getint("irs", "process_pool_timeout")
@@ -388,6 +392,47 @@
self._udevTrigger(subsystem_matches=('vfio',))
@logDecorator
+ def appropriateUSBDevice(self, bus, device):
+ rule_file = _UDEV_RULE_FILE_NAME_USB % (bus, device)
+ rule = ('SUBSYSTEM=="usb", ATTRS{{busnum}}=="{}", '
+ 'ATTRS{{devnum}}=="{}", OWNER:="{}", GROUP:="{}"\n').format(
+ bus, device, QEMU_PROCESS_USER, QEMU_PROCESS_GROUP)
+
+ self.log.debug("Creating rule %s: %r", rule_file, rule)
+
+ with open(rule_file, "w") as rf:
+ rf.write(rule)
+
+ self._udevTrigger(attr_matches=(('busnum', int(bus)),
+ ('devnum', int(device))))
+
+ @logDecorator
+ def rmAppropriateUSBDevice(self, bus, device):
+ rule_file = _UDEV_RULE_FILE_NAME_USB % (bus, device)
+ self.log.debug("Removing rule %s", rule_file)
+ try:
+ os.remove(rule_file)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ raise
+
+ self.log.warning('Rule %s missing', rule_file)
+
+ self.log.debug('Changing ownership (to root:root) of device '
+ 'bus: %s, device:: %s', bus, device)
+ device_path = _USB_DEVICE_PATH % (int(bus), int(device))
+ cmd = [EXT_CHOWN, 'root:root', device_path]
+ rc, out, err = utils.execCmd(cmd)
+ if err:
+ raise OSError(errno.EINVAL, 'Could not change ownership'
+ 'out %s\nerr %s' % (out, err))
+
+ # It's possible that the device was in input class or had rule
+ # matched against it, trigger to make sure everything is fine.
+ self._udevTrigger(attr_matches=(('busnum', int(bus)),
+ ('devnum', int(device))))
+
+ @logDecorator
def ksmTune(self, tuningParams):
'''
Set KSM tuning parameters for MOM, which runs without root privilege
--
To view, visit https://gerrit.ovirt.org/46527
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I1f72f63186187254cd4aded0a2e6c396001ca28b
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: ovirt-3.6
Gerrit-Owner: Martin Polednik <mpolednik at redhat.com>
More information about the vdsm-patches
mailing list