mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-25 07:05:28 +00:00
Change default cgroup layout for QEMU/LXC and honour XML config
Historically QEMU/LXC guests have been placed in a cgroup layout that is $LOCATION-OF-LIBVIRTD/libvirt/{qemu,lxc}/$VMNAME This is bad for a number of reasons - The cgroup hierarchy gets very deep which seriously impacts kernel performance due to cgroups scalability limitations. - It is hard to setup cgroup policies which apply across services and virtual machines, since all VMs are underneath the libvirtd service. To address this the default cgroup location is changed to be /system/$VMNAME.{lxc,qemu}.libvirt This puts virtual machines at the same level in the hierarchy as system services, allowing consistent policy to be setup across all of them. This also honours the new resource partition location from the XML configuration, for example <resource> <partition>/virtualmachines/production</partitions> </resource> will result in the VM being placed at /virtualmachines/production/$VMNAME.{lxc,qemu}.libvirt NB, with the exception of the default, /system, path which is intended to always exist, libvirt will not attempt to auto-create the partitions in the XML. It is the responsibility of the admin/app to configure the partitions. Later libvirt APIs will provide a way todo this. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
8d4adf3efa
commit
db44eb1b5f
@ -523,29 +523,88 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virCgroupPtr virLXCCgroupCreate(virDomainDefPtr def)
|
virCgroupPtr virLXCCgroupCreate(virDomainDefPtr def, bool startup)
|
||||||
{
|
{
|
||||||
virCgroupPtr driver = NULL;
|
|
||||||
virCgroupPtr cgroup = NULL;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
virCgroupPtr parent = NULL;
|
||||||
|
virCgroupPtr cgroup = NULL;
|
||||||
|
|
||||||
rc = virCgroupNewDriver("lxc", true, false, -1, &driver);
|
if (!def->resource && startup) {
|
||||||
if (rc != 0) {
|
virDomainResourceDefPtr res;
|
||||||
virReportSystemError(-rc, "%s",
|
|
||||||
_("Unable to get cgroup for driver"));
|
if (VIR_ALLOC(res) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = virCgroupNewDomainDriver(driver, def->name, true, &cgroup);
|
if (!(res->partition = strdup("/system"))) {
|
||||||
|
virReportOOMError();
|
||||||
|
VIR_FREE(res);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
def->resource = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def->resource &&
|
||||||
|
def->resource->partition) {
|
||||||
|
if (def->resource->partition[0] != '/') {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("Resource partition '%s' must start with '/'"),
|
||||||
|
def->resource->partition);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/* We only auto-create the default partition. In other
|
||||||
|
* cases we expec the sysadmin/app to have done so */
|
||||||
|
rc = virCgroupNewPartition(def->resource->partition,
|
||||||
|
STREQ(def->resource->partition, "/system"),
|
||||||
|
-1,
|
||||||
|
&parent);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
virReportSystemError(-rc,
|
virReportSystemError(-rc,
|
||||||
_("Unable to create cgroup for domain %s"),
|
_("Unable to initialize %s cgroup"),
|
||||||
|
def->resource->partition);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = virCgroupNewDomainPartition(parent,
|
||||||
|
"lxc",
|
||||||
|
def->name,
|
||||||
|
true,
|
||||||
|
&cgroup);
|
||||||
|
if (rc != 0) {
|
||||||
|
virReportSystemError(-rc,
|
||||||
|
_("Unable to create cgroup for %s"),
|
||||||
|
def->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = virCgroupNewDriver("lxc",
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
-1,
|
||||||
|
&parent);
|
||||||
|
if (rc != 0) {
|
||||||
|
virReportSystemError(-rc,
|
||||||
|
_("Unable to create cgroup for %s"),
|
||||||
def->name);
|
def->name);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = virCgroupNewDomainDriver(parent,
|
||||||
|
def->name,
|
||||||
|
true,
|
||||||
|
&cgroup);
|
||||||
|
if (rc != 0) {
|
||||||
|
virReportSystemError(-rc,
|
||||||
|
_("Unable to create cgroup for %s"),
|
||||||
|
def->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
virCgroupFree(&driver);
|
virCgroupFree(&parent);
|
||||||
return cgroup;
|
return cgroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,7 +615,7 @@ virCgroupPtr virLXCCgroupJoin(virDomainDefPtr def)
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!(cgroup = virLXCCgroupCreate(def)))
|
if (!(cgroup = virLXCCgroupCreate(def, true)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
rc = virCgroupAddTask(cgroup, getpid());
|
rc = virCgroupAddTask(cgroup, getpid());
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
# include "lxc_fuse.h"
|
# include "lxc_fuse.h"
|
||||||
# include "virusb.h"
|
# include "virusb.h"
|
||||||
|
|
||||||
virCgroupPtr virLXCCgroupCreate(virDomainDefPtr def);
|
virCgroupPtr virLXCCgroupCreate(virDomainDefPtr def, bool startup);
|
||||||
virCgroupPtr virLXCCgroupJoin(virDomainDefPtr def);
|
virCgroupPtr virLXCCgroupJoin(virDomainDefPtr def);
|
||||||
int virLXCCgroupSetup(virDomainDefPtr def,
|
int virLXCCgroupSetup(virDomainDefPtr def,
|
||||||
virCgroupPtr cgroup,
|
virCgroupPtr cgroup,
|
||||||
|
@ -1049,7 +1049,7 @@ int virLXCProcessStart(virConnectPtr conn,
|
|||||||
|
|
||||||
virCgroupFree(&priv->cgroup);
|
virCgroupFree(&priv->cgroup);
|
||||||
|
|
||||||
if (!(priv->cgroup = virLXCCgroupCreate(vm->def)))
|
if (!(priv->cgroup = virLXCCgroupCreate(vm->def, true)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!virCgroupHasController(priv->cgroup,
|
if (!virCgroupHasController(priv->cgroup,
|
||||||
@ -1464,7 +1464,7 @@ virLXCProcessReconnectDomain(virDomainObjPtr vm,
|
|||||||
if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
|
if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!(priv->cgroup = virLXCCgroupCreate(vm->def)))
|
if (!(priv->cgroup = virLXCCgroupCreate(vm->def, false)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (virLXCUpdateActiveUsbHostdevs(driver, vm->def) < 0)
|
if (virLXCUpdateActiveUsbHostdevs(driver, vm->def) < 0)
|
||||||
|
@ -215,20 +215,78 @@ int qemuSetupHostUsbDeviceCgroup(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
|
|||||||
|
|
||||||
|
|
||||||
int qemuInitCgroup(virQEMUDriverPtr driver,
|
int qemuInitCgroup(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm)
|
virDomainObjPtr vm,
|
||||||
|
bool startup)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc = -1;
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
virCgroupPtr driverGroup = NULL;
|
virCgroupPtr parent = NULL;
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
|
|
||||||
virCgroupFree(&priv->cgroup);
|
virCgroupFree(&priv->cgroup);
|
||||||
|
|
||||||
|
if (!vm->def->resource && startup) {
|
||||||
|
virDomainResourceDefPtr res;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(res) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(res->partition = strdup("/system"))) {
|
||||||
|
virReportOOMError();
|
||||||
|
VIR_FREE(res);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->def->resource = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm->def->resource &&
|
||||||
|
vm->def->resource->partition) {
|
||||||
|
if (vm->def->resource->partition[0] != '/') {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("Resource partition '%s' must start with '/'"),
|
||||||
|
vm->def->resource->partition);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/* We only auto-create the default partition. In other
|
||||||
|
* cases we expec the sysadmin/app to have done so */
|
||||||
|
rc = virCgroupNewPartition(vm->def->resource->partition,
|
||||||
|
STREQ(vm->def->resource->partition, "/system"),
|
||||||
|
cfg->cgroupControllers,
|
||||||
|
&parent);
|
||||||
|
if (rc != 0) {
|
||||||
|
if (rc == -ENXIO ||
|
||||||
|
rc == -EPERM ||
|
||||||
|
rc == -EACCES) { /* No cgroups mounts == success */
|
||||||
|
VIR_DEBUG("No cgroups present/configured/accessible, ignoring error");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
virReportSystemError(-rc,
|
||||||
|
_("Unable to initialize %s cgroup"),
|
||||||
|
vm->def->resource->partition);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = virCgroupNewDomainPartition(parent,
|
||||||
|
"qemu",
|
||||||
|
vm->def->name,
|
||||||
|
true,
|
||||||
|
&priv->cgroup);
|
||||||
|
if (rc != 0) {
|
||||||
|
virReportSystemError(-rc,
|
||||||
|
_("Unable to create cgroup for %s"),
|
||||||
|
vm->def->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
rc = virCgroupNewDriver("qemu",
|
rc = virCgroupNewDriver("qemu",
|
||||||
cfg->privileged,
|
cfg->privileged,
|
||||||
true,
|
true,
|
||||||
cfg->cgroupControllers,
|
cfg->cgroupControllers,
|
||||||
&driverGroup);
|
&parent);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
if (rc == -ENXIO ||
|
if (rc == -ENXIO ||
|
||||||
rc == -EPERM ||
|
rc == -EPERM ||
|
||||||
@ -243,18 +301,22 @@ int qemuInitCgroup(virQEMUDriverPtr driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = virCgroupNewDomainDriver(driverGroup, vm->def->name, true, &priv->cgroup);
|
rc = virCgroupNewDomainDriver(parent,
|
||||||
|
vm->def->name,
|
||||||
|
true,
|
||||||
|
&priv->cgroup);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
virReportSystemError(-rc,
|
virReportSystemError(-rc,
|
||||||
_("Unable to create cgroup for %s"),
|
_("Unable to create cgroup for %s"),
|
||||||
vm->def->name);
|
vm->def->name);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
rc = 0;
|
rc = 0;
|
||||||
cleanup:
|
cleanup:
|
||||||
virCgroupFree(&driverGroup);
|
virCgroupFree(&parent);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -273,7 +335,7 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
|
|||||||
(const char *const *)cfg->cgroupDeviceACL :
|
(const char *const *)cfg->cgroupDeviceACL :
|
||||||
defaultDeviceACL;
|
defaultDeviceACL;
|
||||||
|
|
||||||
if (qemuInitCgroup(driver, vm) < 0)
|
if (qemuInitCgroup(driver, vm, true) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!priv->cgroup)
|
if (!priv->cgroup)
|
||||||
|
@ -37,7 +37,8 @@ int qemuSetupHostUsbDeviceCgroup(virUSBDevicePtr dev,
|
|||||||
const char *path,
|
const char *path,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
int qemuInitCgroup(virQEMUDriverPtr driver,
|
int qemuInitCgroup(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm);
|
virDomainObjPtr vm,
|
||||||
|
bool startup);
|
||||||
int qemuSetupCgroup(virQEMUDriverPtr driver,
|
int qemuSetupCgroup(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virBitmapPtr nodemask);
|
virBitmapPtr nodemask);
|
||||||
|
@ -3005,7 +3005,7 @@ qemuProcessReconnect(void *opaque)
|
|||||||
if (qemuUpdateActiveUsbHostdevs(driver, obj->def) < 0)
|
if (qemuUpdateActiveUsbHostdevs(driver, obj->def) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (qemuInitCgroup(driver, obj) < 0)
|
if (qemuInitCgroup(driver, obj, false) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* XXX: Need to change as long as lock is introduced for
|
/* XXX: Need to change as long as lock is introduced for
|
||||||
|
Loading…
Reference in New Issue
Block a user