# The group ID for QEMU processes run by the system instance
#group = "root"
+
+
+# What cgroup controllers to make use of with QEMU guests
+#
+# - 'cpu' - use for schedular tunables
+# - 'devices' - use for device whitelisting
+#
+# NB, even if configured here, they won't be used unless
+# the adminsitrator has mounted cgroups. eg
+#
+# mkdir /dev/cgroup
+# mount -t cgroup -o devices,cpu none /dev/cgroup
+#
+# They can be mounted anywhere, and different controlers
+# can be mounted in different locations. libvirt will detect
+# where they are located.
+#
+# cgroup_controllers = [ "cpu", "devices" ]
+
+# This is the basic set of devices allowed / required by
+# all virtual machines.
+#
+# As well as this, any configured block backed disks,
+# all sound device, and all PTY devices are allowed.
+#
+# This will only need setting if newer QEMU suddenly
+# wants some device we don't already know a bout.
+#
+#cgroup_device_acl = [
+# "/dev/null", "/dev/full", "/dev/zero",
+# "/dev/random", "/dev/urandom",
+# "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
+# "/dev/rtc", "/dev/hpet", "/dev/net/tun",
+#]
virConfValuePtr p;
char *user;
char *group;
+ int i;
/* Setup 2 critical defaults */
if (!(driver->vncListen = strdup("127.0.0.1"))) {
}
VIR_FREE(group);
+ p = virConfGetValue (conf, "cgroup_controllers");
+ CHECK_TYPE ("cgroup_controllers", VIR_CONF_LIST);
+ if (p) {
+ virConfValuePtr pp;
+ for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
+ int ctl;
+ if (pp->type != VIR_CONF_STRING) {
+ VIR_ERROR("%s", _("cgroup_device_acl must be a list of strings"));
+ virConfFree(conf);
+ return -1;
+ }
+ ctl = virCgroupControllerTypeFromString(pp->str);
+ if (ctl < 0) {
+ VIR_ERROR("Unknown cgroup controller '%s'", pp->str);
+ virConfFree(conf);
+ return -1;
+ }
+ driver->cgroupControllers |= (1 << ctl);
+ }
+ } else {
+ driver->cgroupControllers =
+ (1 << VIR_CGROUP_CONTROLLER_CPU) |
+ (1 << VIR_CGROUP_CONTROLLER_DEVICES);
+ }
+ for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
+ if (driver->cgroupControllers & (1 << i)) {
+ VIR_INFO("Configured cgroup controller '%s'",
+ virCgroupControllerTypeToString(i));
+ }
+ }
+
+ p = virConfGetValue (conf, "cgroup_device_acl");
+ CHECK_TYPE ("cgroup_device_acl", VIR_CONF_LIST);
+ if (p) {
+ int len = 0;
+ virConfValuePtr pp;
+ for (pp = p->list; pp; pp = pp->next)
+ len++;
+ if (VIR_ALLOC_N(driver->cgroupDeviceACL, 1+len) < 0) {
+ virReportOOMError(NULL);
+ virConfFree(conf);
+ return -1;
+ }
+ for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
+ if (pp->type != VIR_CONF_STRING) {
+ VIR_ERROR("%s", _("cgroup_device_acl must be a list of strings"));
+ virConfFree(conf);
+ return -1;
+ }
+ driver->cgroupDeviceACL[i] = strdup (pp->str);
+ if (driver->cgroupDeviceACL[i] == NULL) {
+ virReportOOMError(NULL);
+ virConfFree(conf);
+ return -1;
+ }
+
+ }
+ driver->cgroupDeviceACL[i] = NULL;
+ }
+
virConfFree (conf);
return 0;
}
static struct qemud_driver *qemu_driver = NULL;
+static int qemuCgroupControllerActive(struct qemud_driver *driver,
+ int controller)
+{
+ if (driver->cgroup == NULL)
+ return 0;
+ if (driver->cgroupControllers & (1 << controller))
+ return 1;
+ return 0;
+}
static int
qemudLogFD(virConnectPtr conn, struct qemud_driver *driver, const char* name)
virCgroupPtr cgroup = NULL;
int rc;
unsigned int i;
- const char *const *deviceACL = defaultDeviceACL;
+ const char *const *deviceACL =
+ driver->cgroupDeviceACL ?
+ (const char *const *)driver->cgroupDeviceACL :
+ defaultDeviceACL;
if (driver->cgroup == NULL)
return 0; /* Not supported, so claim success */
goto cleanup;
}
- rc = virCgroupDenyAllDevices(cgroup);
- if (rc != 0) {
- if (rc == -EPERM) {
- VIR_WARN0("Group devices ACL is not accessible, disabling whitelisting");
- goto done;
- }
-
- virReportSystemError(conn, -rc,
- _("Unable to deny all devices for %s"), vm->def->name);
- goto cleanup;
- }
-
- for (i = 0; i < vm->def->ndisks ; i++) {
- if (vm->def->disks[i]->type != VIR_DOMAIN_DISK_TYPE_BLOCK ||
- vm->def->disks[i]->src == NULL)
- continue;
-
- rc = virCgroupAllowDevicePath(cgroup,
- vm->def->disks[i]->src);
+ if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
+ rc = virCgroupDenyAllDevices(cgroup);
if (rc != 0) {
+ if (rc == -EPERM) {
+ VIR_WARN0("Group devices ACL is not accessible, disabling whitelisting");
+ goto done;
+ }
+
virReportSystemError(conn, -rc,
- _("Unable to allow device %s for %s"),
- vm->def->disks[i]->src, vm->def->name);
+ _("Unable to deny all devices for %s"), vm->def->name);
goto cleanup;
}
- }
- rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_PTY_MAJOR);
- if (rc != 0) {
- virReportSystemError(conn, -rc, "%s",
- _("unable to allow /dev/pts/ devices"));
- goto cleanup;
- }
+ for (i = 0; i < vm->def->ndisks ; i++) {
+ if (vm->def->disks[i]->type != VIR_DOMAIN_DISK_TYPE_BLOCK ||
+ vm->def->disks[i]->src == NULL)
+ continue;
+
+ rc = virCgroupAllowDevicePath(cgroup,
+ vm->def->disks[i]->src);
+ if (rc != 0) {
+ virReportSystemError(conn, -rc,
+ _("Unable to allow device %s for %s"),
+ vm->def->disks[i]->src, vm->def->name);
+ goto cleanup;
+ }
+ }
- if (vm->def->nsounds) {
- rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_SND_MAJOR);
+ rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_PTY_MAJOR);
if (rc != 0) {
virReportSystemError(conn, -rc, "%s",
- _("unable to allow /dev/snd/ devices"));
+ _("unable to allow /dev/pts/ devices"));
goto cleanup;
}
- }
- for (i = 0; deviceACL[i] != NULL ; i++) {
- rc = virCgroupAllowDevicePath(cgroup,
- deviceACL[i]);
- if (rc < 0 &&
- rc != -ENOENT) {
- virReportSystemError(conn, -rc,
- _("unable to allow device %s"),
- deviceACL[i]);
- goto cleanup;
+ if (vm->def->nsounds) {
+ rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_SND_MAJOR);
+ if (rc != 0) {
+ virReportSystemError(conn, -rc, "%s",
+ _("unable to allow /dev/snd/ devices"));
+ goto cleanup;
+ }
+ }
+
+ for (i = 0; deviceACL[i] != NULL ; i++) {
+ rc = virCgroupAllowDevicePath(cgroup,
+ deviceACL[i]);
+ if (rc < 0 &&
+ rc != -ENOENT) {
+ virReportSystemError(conn, -rc,
+ _("unable to allow device %s"),
+ deviceACL[i]);
+ goto cleanup;
+ }
}
}
goto cleanup;
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
- if (driver->cgroup != NULL) {
+ if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s\n"),
struct qemud_driver *driver = dom->conn->privateData;
char *ret;
- if (driver->cgroup == NULL) {
+ if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
__FUNCTION__);
return NULL;
virDomainObjPtr vm = NULL;
int ret = -1;
- if (driver->cgroup == NULL) {
+ if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
__FUNCTION__);
return -1;
int ret = -1;
int rc;
- if (driver->cgroup == NULL) {
+ if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
__FUNCTION__);
return -1;