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:
Daniel P. Berrange 2012-11-28 16:13:27 +00:00
parent 95fef5f407
commit 313669d1c1
2 changed files with 109 additions and 13 deletions

View File

@ -414,8 +414,8 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
virDomainHostdevDefPtr hostdev = def->hostdevs[i];
usbDevice *usb;
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
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)
@ -429,6 +429,22 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
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,

View File

@ -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"),