mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
Place every QEMU guest in a private cgroup
* src/qemu_driver.c: Place guest in cgroup upon startup. Remove cgroup upon shutdown
This commit is contained in:
parent
946c489c68
commit
38f6f47be9
@ -34,6 +34,7 @@
|
|||||||
#include "domain_event.h"
|
#include "domain_event.h"
|
||||||
#include "threads.h"
|
#include "threads.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
|
#include "cgroup.h"
|
||||||
|
|
||||||
#define qemudDebug(fmt, ...) do {} while(0)
|
#define qemudDebug(fmt, ...) do {} while(0)
|
||||||
|
|
||||||
@ -77,6 +78,7 @@ struct qemud_driver {
|
|||||||
unsigned int qemuVersion;
|
unsigned int qemuVersion;
|
||||||
int nextvmid;
|
int nextvmid;
|
||||||
|
|
||||||
|
virCgroupPtr cgroup;
|
||||||
virDomainObjList domains;
|
virDomainObjList domains;
|
||||||
|
|
||||||
brControl *brctl;
|
brControl *brctl;
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
#include "node_device_conf.h"
|
#include "node_device_conf.h"
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
|
#include "cgroup.h"
|
||||||
|
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_QEMU
|
#define VIR_FROM_THIS VIR_FROM_QEMU
|
||||||
@ -418,6 +419,7 @@ static int
|
|||||||
qemudStartup(int privileged) {
|
qemudStartup(int privileged) {
|
||||||
char *base = NULL;
|
char *base = NULL;
|
||||||
char driverConf[PATH_MAX];
|
char driverConf[PATH_MAX];
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (VIR_ALLOC(qemu_driver) < 0)
|
if (VIR_ALLOC(qemu_driver) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -498,6 +500,13 @@ qemudStartup(int privileged) {
|
|||||||
|
|
||||||
VIR_FREE(base);
|
VIR_FREE(base);
|
||||||
|
|
||||||
|
rc = virCgroupForDriver("qemu", &qemu_driver->cgroup, privileged, 1);
|
||||||
|
if (rc < 0) {
|
||||||
|
char buf[1024];
|
||||||
|
VIR_WARN("Unable to create cgroup for driver: %s",
|
||||||
|
virStrerror(-rc, buf, sizeof(buf)));
|
||||||
|
}
|
||||||
|
|
||||||
if ((qemu_driver->caps = qemudCapsInit()) == NULL)
|
if ((qemu_driver->caps = qemudCapsInit()) == NULL)
|
||||||
goto out_of_memory;
|
goto out_of_memory;
|
||||||
|
|
||||||
@ -649,6 +658,8 @@ qemudShutdown(void) {
|
|||||||
if (qemu_driver->brctl)
|
if (qemu_driver->brctl)
|
||||||
brShutdown(qemu_driver->brctl);
|
brShutdown(qemu_driver->brctl);
|
||||||
|
|
||||||
|
virCgroupFree(&qemu_driver->cgroup);
|
||||||
|
|
||||||
qemuDriverUnlock(qemu_driver);
|
qemuDriverUnlock(qemu_driver);
|
||||||
virMutexDestroy(&qemu_driver->lock);
|
virMutexDestroy(&qemu_driver->lock);
|
||||||
VIR_FREE(qemu_driver);
|
VIR_FREE(qemu_driver);
|
||||||
@ -1377,6 +1388,93 @@ error:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qemuSetupCgroup(virConnectPtr conn,
|
||||||
|
struct qemud_driver *driver,
|
||||||
|
virDomainObjPtr vm)
|
||||||
|
{
|
||||||
|
virCgroupPtr cgroup = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (driver->cgroup == NULL)
|
||||||
|
return 0; /* Not supported, so claim success */
|
||||||
|
|
||||||
|
rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 1);
|
||||||
|
if (rc != 0) {
|
||||||
|
virReportSystemError(conn, -rc,
|
||||||
|
_("Unable to create cgroup for %s"),
|
||||||
|
vm->def->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
virCgroupFree(&cgroup);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (cgroup) {
|
||||||
|
virCgroupRemove(cgroup);
|
||||||
|
virCgroupFree(&cgroup);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int qemuRemoveCgroup(virConnectPtr conn,
|
||||||
|
struct qemud_driver *driver,
|
||||||
|
virDomainObjPtr vm)
|
||||||
|
{
|
||||||
|
virCgroupPtr cgroup;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (driver->cgroup == NULL)
|
||||||
|
return 0; /* Not supported, so claim success */
|
||||||
|
|
||||||
|
rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0);
|
||||||
|
if (rc != 0) {
|
||||||
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Unable to find cgroup for %s\n"),
|
||||||
|
vm->def->name);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = virCgroupRemove(cgroup);
|
||||||
|
virCgroupFree(&cgroup);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qemuAddToCgroup(struct qemud_driver *driver,
|
||||||
|
virDomainDefPtr def)
|
||||||
|
{
|
||||||
|
virCgroupPtr cgroup = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (driver->cgroup == NULL)
|
||||||
|
return 0; /* Not supported, so claim success */
|
||||||
|
|
||||||
|
rc = virCgroupForDomain(driver->cgroup, def->name, &cgroup, 0);
|
||||||
|
if (rc != 0) {
|
||||||
|
virReportSystemError(NULL, -rc,
|
||||||
|
_("unable to find cgroup for domain %s"),
|
||||||
|
def->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = virCgroupAddTask(cgroup, getpid());
|
||||||
|
if (rc != 0) {
|
||||||
|
virReportSystemError(NULL, -rc,
|
||||||
|
_("unable to add domain %s task %d to cgroup"),
|
||||||
|
def->name, getpid());
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virCgroupFree(&cgroup);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int qemudDomainSetSecurityLabel(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm)
|
static int qemudDomainSetSecurityLabel(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm)
|
||||||
{
|
{
|
||||||
if (vm->def->seclabel.label != NULL)
|
if (vm->def->seclabel.label != NULL)
|
||||||
@ -1588,14 +1686,17 @@ static int qemuDomainSetAllDeviceOwnership(virConnectPtr conn,
|
|||||||
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
|
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
|
||||||
struct gemudHookData {
|
struct qemudHookData {
|
||||||
virConnectPtr conn;
|
virConnectPtr conn;
|
||||||
virDomainObjPtr vm;
|
virDomainObjPtr vm;
|
||||||
struct qemud_driver *driver;
|
struct qemud_driver *driver;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int qemudSecurityHook(void *data) {
|
static int qemudSecurityHook(void *data) {
|
||||||
struct gemudHookData *h = (struct gemudHookData *) data;
|
struct qemudHookData *h = data;
|
||||||
|
|
||||||
|
if (qemuAddToCgroup(h->driver, h->vm->def) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (qemudDomainSetSecurityLabel(h->conn, h->driver, h->vm) < 0) {
|
if (qemudDomainSetSecurityLabel(h->conn, h->driver, h->vm) < 0) {
|
||||||
qemudReportError(h->conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(h->conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -1668,7 +1769,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
int logfile;
|
int logfile;
|
||||||
|
|
||||||
struct gemudHookData hookData;
|
struct qemudHookData hookData;
|
||||||
hookData.conn = conn;
|
hookData.conn = conn;
|
||||||
hookData.vm = vm;
|
hookData.vm = vm;
|
||||||
hookData.driver = driver;
|
hookData.driver = driver;
|
||||||
@ -1689,6 +1790,9 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0)
|
driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* Ensure no historical cgroup for this VM is lieing around bogus settings */
|
||||||
|
qemuRemoveCgroup(conn, driver, vm);
|
||||||
|
|
||||||
if ((vm->def->ngraphics == 1) &&
|
if ((vm->def->ngraphics == 1) &&
|
||||||
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
|
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
|
||||||
vm->def->graphics[0]->data.vnc.autoport) {
|
vm->def->graphics[0]->data.vnc.autoport) {
|
||||||
@ -1729,6 +1833,9 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
&qemuCmdFlags) < 0)
|
&qemuCmdFlags) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (qemuSetupCgroup(conn, driver, vm) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (qemuPrepareHostDevices(conn, vm->def) < 0)
|
if (qemuPrepareHostDevices(conn, vm->def) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -1855,6 +1962,7 @@ cleanup:
|
|||||||
VIR_FREE(vm->def->seclabel.label);
|
VIR_FREE(vm->def->seclabel.label);
|
||||||
VIR_FREE(vm->def->seclabel.imagelabel);
|
VIR_FREE(vm->def->seclabel.imagelabel);
|
||||||
}
|
}
|
||||||
|
qemuRemoveCgroup(conn, driver, vm);
|
||||||
if ((vm->def->ngraphics == 1) &&
|
if ((vm->def->ngraphics == 1) &&
|
||||||
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
|
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
|
||||||
vm->def->graphics[0]->data.vnc.autoport)
|
vm->def->graphics[0]->data.vnc.autoport)
|
||||||
@ -1866,10 +1974,11 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
|
static void qemudShutdownVMDaemon(virConnectPtr conn,
|
||||||
struct qemud_driver *driver,
|
struct qemud_driver *driver,
|
||||||
virDomainObjPtr vm) {
|
virDomainObjPtr vm) {
|
||||||
int ret;
|
int ret;
|
||||||
|
int retries = 0;
|
||||||
|
|
||||||
if (!virDomainIsActive(vm))
|
if (!virDomainIsActive(vm))
|
||||||
return;
|
return;
|
||||||
@ -1909,6 +2018,16 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
VIR_WARN("Failed to restore all device ownership for %s",
|
VIR_WARN("Failed to restore all device ownership for %s",
|
||||||
vm->def->name);
|
vm->def->name);
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if ((ret = qemuRemoveCgroup(conn, driver, vm)) < 0) {
|
||||||
|
if (ret == -EBUSY && (retries++ < 5)) {
|
||||||
|
usleep(200*1000);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
VIR_WARN("Failed to remove cgroup for %s",
|
||||||
|
vm->def->name);
|
||||||
|
}
|
||||||
|
|
||||||
if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
|
if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
|
||||||
VIR_WARN(_("Failed to remove domain status for %s"),
|
VIR_WARN(_("Failed to remove domain status for %s"),
|
||||||
vm->def->name);
|
vm->def->name);
|
||||||
|
Loading…
Reference in New Issue
Block a user