mirror of https://gitee.com/openkylin/libvirt.git
Add support for storage host device passthrough with LXC
This extends support for host device passthrough with LXC to cover storage devices. In this case all we need todo is a mknod in the container's /dev and whitelist the device in cgroups Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
95fef5f407
commit
313669d1c1
|
@ -414,21 +414,37 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
|
|||
virDomainHostdevDefPtr hostdev = def->hostdevs[i];
|
||||
usbDevice *usb;
|
||||
|
||||
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
||||
continue;
|
||||
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
||||
continue;
|
||||
if (hostdev->missing)
|
||||
continue;
|
||||
switch (hostdev->mode) {
|
||||
case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
|
||||
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
||||
continue;
|
||||
if (hostdev->missing)
|
||||
continue;
|
||||
|
||||
if ((usb = usbGetDevice(hostdev->source.subsys.u.usb.bus,
|
||||
hostdev->source.subsys.u.usb.device,
|
||||
NULL)) == NULL)
|
||||
goto cleanup;
|
||||
if ((usb = usbGetDevice(hostdev->source.subsys.u.usb.bus,
|
||||
hostdev->source.subsys.u.usb.device,
|
||||
NULL)) == NULL)
|
||||
goto cleanup;
|
||||
|
||||
if (usbDeviceFileIterate(usb, virLXCSetupHostUsbDeviceCgroup,
|
||||
cgroup) < 0)
|
||||
goto cleanup;
|
||||
if (usbDeviceFileIterate(usb, virLXCSetupHostUsbDeviceCgroup,
|
||||
cgroup) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
|
||||
switch (hostdev->source.caps.type) {
|
||||
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
|
||||
if (virCgroupAllowDevicePath(cgroup,
|
||||
hostdev->source.caps.u.storage.block,
|
||||
VIR_CGROUP_DEVICE_RW |
|
||||
VIR_CGROUP_DEVICE_MKNOD) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rc = virCgroupAllowDeviceMajor(cgroup, 'c', LXC_DEV_MAJ_PTY,
|
||||
|
|
|
@ -1385,6 +1385,64 @@ cleanup:
|
|||
}
|
||||
|
||||
|
||||
static int lxcContainerSetupHostdevCapsStorage(virDomainDefPtr vmDef ATTRIBUTE_UNUSED,
|
||||
virDomainHostdevDefPtr def ATTRIBUTE_UNUSED,
|
||||
const char *dstprefix ATTRIBUTE_UNUSED,
|
||||
virSecurityManagerPtr securityDriver ATTRIBUTE_UNUSED)
|
||||
{
|
||||
char *src = NULL;
|
||||
int ret = -1;
|
||||
struct stat sb;
|
||||
mode_t mode;
|
||||
|
||||
if (def->source.caps.u.storage.block == NULL) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Missing storage host block path"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virAsprintf(&src, "%s/%s", dstprefix, def->source.caps.u.storage.block) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (stat(src, &sb) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to access %s"),
|
||||
src);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!S_ISBLK(sb.st_mode)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Storage source %s must be a block device"),
|
||||
def->source.caps.u.storage.block);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
mode = 0700 | S_IFBLK;
|
||||
|
||||
VIR_DEBUG("Creating dev %s (%d,%d)",
|
||||
def->source.caps.u.storage.block,
|
||||
major(sb.st_rdev), minor(sb.st_rdev));
|
||||
if (mknod(def->source.caps.u.storage.block, mode, sb.st_rdev) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to create device %s"),
|
||||
def->source.caps.u.storage.block);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int lxcContainerSetupHostdevSubsys(virDomainDefPtr vmDef,
|
||||
virDomainHostdevDefPtr def,
|
||||
const char *dstprefix,
|
||||
|
@ -1403,6 +1461,24 @@ static int lxcContainerSetupHostdevSubsys(virDomainDefPtr vmDef,
|
|||
}
|
||||
|
||||
|
||||
static int lxcContainerSetupHostdevCaps(virDomainDefPtr vmDef,
|
||||
virDomainHostdevDefPtr def,
|
||||
const char *dstprefix,
|
||||
virSecurityManagerPtr securityDriver)
|
||||
{
|
||||
switch (def->source.subsys.type) {
|
||||
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
|
||||
return lxcContainerSetupHostdevCapsStorage(vmDef, def, dstprefix, securityDriver);
|
||||
|
||||
default:
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Unsupported host device mode %s"),
|
||||
virDomainHostdevCapsTypeToString(def->source.subsys.type));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int lxcContainerSetupAllHostdevs(virDomainDefPtr vmDef,
|
||||
const char *dstprefix,
|
||||
virSecurityManagerPtr securityDriver)
|
||||
|
@ -1417,6 +1493,10 @@ static int lxcContainerSetupAllHostdevs(virDomainDefPtr vmDef,
|
|||
if (lxcContainerSetupHostdevSubsys(vmDef, def, dstprefix, securityDriver) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
|
||||
if (lxcContainerSetupHostdevCaps(vmDef, def, dstprefix, securityDriver) < 0)
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Unsupported host device mode %s"),
|
||||
|
|
Loading…
Reference in New Issue