[libvirt] cont command failing via JSON monitor on restore
by Jim Fehlig
libvirt 0.8.7
qemu 0.13
I'm looking into a problem with qemu save/restore via JSON monitor. On
restore, the vm is left in a paused state with following error returned
for 'cont' command
An incoming migration is expected before this command can be executed
I was trying to debug the issue in gdb, but stepping through the code
introduces enough delay between qemudStartVMDaemon() and doStartCPUs()
that the latter succeeds. Any suggestions on how to determine when it
is safe to call doStartCPUs() to prevent the above error? I don't see
this issue with the text monitor btw.
Thanks,
Jim
13 years, 9 months
[libvirt] [PATCH] update domain status forcibly even if attach a device failed
by Wen Congyang
Steps to reproduce this bug:
1. virsh attach-disk domain --source diskimage --target sdb --sourcetype file --driver qemu --subdriver qcow2
error: Failed to attach disk
error: operation failed: adding scsi-disk,bus=scsi0.0,scsi-id=1,drive=drive-scsi0-0-1,id=scsi0-0-1 device failed: Property 'scsi-disk.drive' can't find value 'drive-scsi0-0-1'
2. service libvirtd restart
Stopping libvirtd daemon: [ OK ]
Starting libvirtd daemon: [ OK ]
3. virsh attach-disk domain --source diskimage --target sdb --sourcetype file --driver qemu --subdriver raw
error: Failed to attach disk
error: operation failed: adding lsi,id=scsi0,bus=pci.0,addr=0x6 device failed: Duplicate ID 'scsi0' for device
The reason is that we create a new scsi controller but we do not update
/var/run/libvirt/qemu/domain.xml.
Signed-off-by: Wen Congyang <wency(a)cn.fujitsu.com>
---
src/qemu/qemu_driver.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 82a2210..5dff64a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6638,7 +6638,11 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
goto endjob;
}
- if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
+ /* update domain status forcibly because the domain status may be changed
+ * even if we attach the device failed. For example, a new controller may
+ * be created.
+ */
+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
ret = -1;
endjob:
--
1.7.1
13 years, 9 months
[libvirt] xen:/// vs. xen://FQDN/ vs xen+unix:/// discrepancy
by Philipp Hahn
Hello,
I regularly observe the problem, that depending on the libvirt-URL I get
different information:
root@xen4# virsh -c xen://xen4.domain.name/ list
Id Name State
----------------------------------
root@xen4# virsh -c xen:/// list
Id Name State
----------------------------------
0 Domain-0 running
1 dos4 idle
root@xen4# virsh -c xen+unix:/// list
Id Name State
----------------------------------
root@xen4# xm li
Name ID Mem VCPUs State
Time(s)
Domain-0 0 2044 2 r----- 419.7
dos4 1 4 1 -b---- 33.4
Has somebody observed the same problem and/or can give me any advise on where
to look for the problem?
I'm running a Debian-Lenny based OS with libvirt-0.8.2 on Xen-3.4.3 with a
2.6.32 kernel.
Sincerely
Philipp Hahn
--
Philipp Hahn Open Source Software Engineer hahn(a)univention.de
Univention GmbH Linux for Your Business fon: +49 421 22 232- 0
Mary-Somerville-Str.1 28359 Bremen fax: +49 421 22 232-99
http://www.univention.de
13 years, 9 months
[libvirt] [PATCH] RFC: support "vram" and "heads" for qxl vga
by Osier Yang
qemu command line to specify "vram":
-global qxl.vram_size=uint
qemu command line to specify "heads", (no need of '-device' for
the first 'head'):
-device qxl,id=qxl-N (N is natural number)
This patch is just about the command line building, still left work
on the command line parsing (hacking on "qemuBuildCommandLine"), as
I'm even not sure if it's the right way to build the command line.
Any advise/idea is appreciated.
---
src/qemu/qemu_capabilities.c | 5 ++++-
src/qemu/qemu_capabilities.h | 3 ++-
src/qemu/qemu_command.c | 14 ++++++++++++++
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index cc5552c..78bcb4c 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -942,9 +942,12 @@ qemuCapsComputeCmdFlags(const char *help,
* two features. The benefits of JSON mode now outweigh
* the downside.
*/
- if (version >= 13000)
+ if (version >= 13000)
flags |= QEMUD_CMD_FLAG_MONITOR_JSON;
+ if (strstr(help, "-global"))
+ flags |= QEMUD_CMD_FLAG_GLOBAL;
+
return flags;
}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index a130a4f..b1feb87 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -91,7 +91,8 @@ enum qemuCapsFlags {
QEMUD_CMD_FLAG_CCID_EMULATED = (1LL << 54), /* -device ccid-card-emulated */
QEMUD_CMD_FLAG_CCID_PASSTHRU = (1LL << 55), /* -device ccid-card-passthru */
QEMUD_CMD_FLAG_CHARDEV_SPICEVMC = (1LL << 56), /* newer -chardev spicevmc */
- QEMUD_CMD_FLAG_DEVICE_SPICEVMC = (1LL << 57), /* older -device spicevmc*/
+ QEMUD_CMD_FLAG_DEVICE_SPICEVMC = (1LL << 57), /* older -device spicevmc */
+ QEMUD_CMD_FLAG_GLOBAL = (1LL << 58), /* Is -global available */
};
virCapsPtr qemuCapsInit(virCapsPtr old_caps);
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1687203..92af6cb 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3964,6 +3964,20 @@ qemuBuildCommandLine(virConnectPtr conn,
}
virCommandAddArgList(cmd, "-vga", vgastr, NULL);
+
+ if (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_QXL) {
+ if (def->videos[0]->vram &&
+ (qemuCmdFlags & QEMUD_CMD_FLAG_GLOBAL)) {
+ virCommandAddArgFormat(cmd, "-global qxl.vram_size=%u",
+ def->videos[0]->vram);
+ }
+
+ if (def->videos[0]->heads > 0) {
+ for (i = 0; i < def->videos[0]->heads - 1; i++) {
+ virCommandAddArgFormat(cmd, "-device %s,id=qxl-%d", vgastr, i+1);
+ }
+ }
+ }
}
} else {
--
1.7.4
13 years, 9 months
[libvirt] [PATCH 2/2] Ignore backing file errors in FS storage pool (v3)
by Philipp Hahn
Currently a single storage volume with a broken backing file will disable the
whole storage pool. This can happen when the backing file is on some
unavailable network storage or if the backing volume is deleted, while the
storage volumes using it are not.
Since the storage pool then can not be re-activated, re-creating the missing
or
deleting the now useless volumes using libvirt only is impossible.
To "fix" this case, all errors detected during storage pool activation are now
(silently) ignored. Errors are still logged by the called functions, which
have
more knowledge on the detailed error condition.
To reproduce:
dir=$(mktemp -d)
virsh pool-create-as tmp dir '' '' '' '' "$dir"
virsh vol-create-as --format qcow2 tmp back 1G
virsh vol-create-as --format qcow2 --backing-vol-format qcow2 --backing-vol
back tmp cow 1G
virsh vol-delete --pool tmp back
virsh pool-refresh tmp
After the last step, the pool will be gone (because it was not persistent). As
long as the now broken image stays in the directory, you will not be able to
re-create or re-start the pool.
Signed-off-by: Philipp Hahn <hahn(a)univention.de>
---
src/storage/storage_backend_fs.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
13 years, 9 months
[libvirt] [PATCH 0/6] new virsh command "blkiotune" support
by Gui Jianfeng
Hi All,
This series implements a new command "blkiotune" for virsh.
A lot of code borrows from memtune.
You are able to tune blkio cgroup tunables by this command as follows.
Show tunables
#virsh blkiotune My_guest
weight : 900
Tune tunables(Set IO weight)
#virsh blkiotune My_guest --weight 500
#virsh blkiotune My_guest
weight : 500
Thanks,
Gui
13 years, 9 months
[libvirt] [PATCH 0/3] Support domain snapshots with current QMP whithout savevm command
by Jiri Denemark
This is quite hacky since it involves falling back to HMP when savevm
command is not found in QMP, which is something qemu monitor code was
not designed to support. Hence, I'm providing 2 version of the first
patch: 1.1/3 and 1.2/3.
- 1.1/3 version only touches JSON monitor code but involves copy&paste
of the snapshot code from text monitor
- 1.2/3 touches more files but doesn't require duplicating the text
monitor snapshot implementation into qemu_monitor_json.c. However, it
results in somewhat funky call graphs:
-> qemuMonitorJSONCreateSnapshot
-> qemuMonitorTextCreateSnapshot
-> qemuMonitorCommand (a macro expanding to qemuMonitorCommandWithFd)
-> qemuMonitorJSONHumanCommandWithFd
-> qemuMonitorJSONCommandWithFd
The possibility to call qemuMonitorTextCreateSnapshot directly on JSON
monitor is implemented by generalizing qemuMonitorCommandWithFd, which
now either calls to qemuMonitorJSONHumanCommandWithFd or
qemuMonitorTextCommandWithFd (former qemuMonitorCommandWithFd)
depending on the monitor type.
I prefer version 2 since it reuses text monitor implementation, but
other may prefer version 1, which is a bit more local...
Jiri Denemark (3):
qemu: Fallback to HMP when savevm QMP command is not found
qemu: Refactor qemuDomainSnapshotCreateXML
qemu: Stop guest CPUs before creating a snapshot
--
1.7.4.1
13 years, 9 months
[libvirt] [PATCH v2] Make LXC container startup/shutdown/I/O more robust
by Daniel P. Berrange
The current LXC I/O controller looks for HUP to detect
when a guest has quit. This isn't reliable as during
initial bootup it is possible that 'init' will close
the console and let mingetty re-open it. The shutdown
of containers was also flakey because it only killed
the libvirt I/O controller and expected container
processes to gracefully follow.
Change the I/O controller such that when it see HUP
or an I/O error, it uses kill($PID, 0) to see if the
process has really quit.
Change the container shutdown sequence to use the
virCgroupKillPainfully function to ensure every
really goes away
This change makes the use of the 'cpu', 'cpuacct'
and 'memory' cgroups controllers compulsory with
LXC
* docs/drvlxc.html.in: Document that certain cgroups
controllers are now mandatory
* src/lxc/lxc_controller.c: Check if PID is still
alive before quitting on I/O error/HUP
* src/lxc/lxc_driver.c: Use virCgroupKillPainfully
---
docs/drvlxc.html.in | 18 +++++
src/lxc/lxc_controller.c | 42 +++++++++---
src/lxc/lxc_driver.c | 155 ++++++++++++++++++----------------------------
3 files changed, 110 insertions(+), 105 deletions(-)
diff --git a/docs/drvlxc.html.in b/docs/drvlxc.html.in
index 35058c4..3e715b1 100644
--- a/docs/drvlxc.html.in
+++ b/docs/drvlxc.html.in
@@ -9,6 +9,24 @@ light-weight "application container" which does not have it's own root image. Y
start it using
</p>
+<h2>Cgroups Requirements</h2>
+
+<p>
+The libvirt LXC driver requires that certain cgroups controllers are
+mounted on the host OS. The minimum required controllers are 'cpuacct',
+'memory' and 'devices', while recommended extra controllers are
+'cpu', 'freezer' and 'blkio'. The /etc/cgconfig.conf & cgconfig
+init service used to mount cgroups at host boot time. To manually
+mount them use. NB, the blkio controller in some kernels will not
+allow creation of nested sub-directories which will prevent correct
+operation of the libvirt LXC driver. On such kernels the blkio controller
+must not be mounted.
+</p>
+
+<pre>
+ # mount -t cgroup cgroup /dev/cgroup -o cpuacct,memory,devices,cpu,freezer,blkio
+</pre>
+
<h3>Example config version 1</h3>
<p></p>
<pre>
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index d2b113c..61e21c3 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -32,6 +32,7 @@
#include <sys/personality.h>
#include <unistd.h>
#include <paths.h>
+#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <getopt.h>
@@ -120,12 +121,10 @@ static int lxcSetContainerResources(virDomainDefPtr def)
virReportSystemError(-rc,
_("Unable to set memory limit for domain %s"),
def->name);
- /* Don't fail if we can't set memory due to lack of kernel support */
- if (rc != -ENOENT)
- goto cleanup;
+ goto cleanup;
}
- if(def->mem.hard_limit) {
+ if (def->mem.hard_limit) {
rc = virCgroupSetMemoryHardLimit(cgroup, def->mem.hard_limit);
if (rc != 0) {
virReportSystemError(-rc,
@@ -135,7 +134,7 @@ static int lxcSetContainerResources(virDomainDefPtr def)
}
}
- if(def->mem.soft_limit) {
+ if (def->mem.soft_limit) {
rc = virCgroupSetMemorySoftLimit(cgroup, def->mem.soft_limit);
if (rc != 0) {
virReportSystemError(-rc,
@@ -145,7 +144,7 @@ static int lxcSetContainerResources(virDomainDefPtr def)
}
}
- if(def->mem.swap_hard_limit) {
+ if (def->mem.swap_hard_limit) {
rc = virCgroupSetSwapHardLimit(cgroup, def->mem.swap_hard_limit);
if (rc != 0) {
virReportSystemError(-rc,
@@ -324,6 +323,18 @@ ignorable_epoll_accept_errno(int errnum)
|| errnum == EWOULDBLOCK);
}
+static bool
+lxcPidGone(pid_t container)
+{
+ waitpid(container, NULL, WNOHANG);
+
+ if (kill(container, 0) < 0 &&
+ errno == ESRCH)
+ return true;
+
+ return false;
+}
+
/**
* lxcControllerMain
* @monitor: server socket fd to accept client requests
@@ -341,7 +352,8 @@ ignorable_epoll_accept_errno(int errnum)
static int lxcControllerMain(int monitor,
int client,
int appPty,
- int contPty)
+ int contPty,
+ pid_t container)
{
int rc = -1;
int epollFd;
@@ -447,7 +459,13 @@ static int lxcControllerMain(int monitor,
++numActive;
}
} else if (epollEvent.events & EPOLLHUP) {
- VIR_DEBUG("EPOLLHUP from fd %d", epollEvent.data.fd);
+ if (lxcPidGone(container))
+ goto cleanup;
+ curFdOff = epollEvent.data.fd == appPty ? 0 : 1;
+ if (fdArray[curFdOff].active) {
+ fdArray[curFdOff].active = 0;
+ --numActive;
+ }
continue;
} else {
lxcError(VIR_ERR_INTERNAL_ERROR,
@@ -486,7 +504,9 @@ static int lxcControllerMain(int monitor,
--numActive;
fdArray[curFdOff].active = 0;
} else if (-1 == rc) {
- goto cleanup;
+ if (lxcPidGone(container))
+ goto cleanup;
+ continue;
}
}
@@ -584,7 +604,7 @@ lxcControllerRun(virDomainDefPtr def,
int rc = -1;
int control[2] = { -1, -1};
int containerPty = -1;
- char *containerPtyPath;
+ char *containerPtyPath = NULL;
pid_t container = -1;
virDomainFSDefPtr root;
char *devpts = NULL;
@@ -706,7 +726,7 @@ lxcControllerRun(virDomainDefPtr def,
if (lxcControllerClearCapabilities() < 0)
goto cleanup;
- rc = lxcControllerMain(monitor, client, appPty, containerPty);
+ rc = lxcControllerMain(monitor, client, appPty, containerPty, container);
cleanup:
VIR_FREE(devptmx);
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 5b6f784..7aaa5cd 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -952,36 +952,16 @@ cleanup:
* @driver: pointer to driver structure
* @vm: pointer to VM to clean up
*
- * waitpid() on the container process. kill and wait the tty process
- * This is called by both lxcDomainDestroy and lxcSigHandler when a
- * container exits.
- *
- * Returns 0 on success or -1 in case of error
+ * Cleanout resources associated with the now dead VM
+ *
*/
-static int lxcVmCleanup(lxc_driver_t *driver,
+static void lxcVmCleanup(lxc_driver_t *driver,
virDomainObjPtr vm)
{
- int rc = 0;
- int waitRc;
- int childStatus = -1;
virCgroupPtr cgroup;
int i;
lxcDomainObjPrivatePtr priv = vm->privateData;
- while (((waitRc = waitpid(vm->pid, &childStatus, 0)) == -1) &&
- errno == EINTR)
- ; /* empty */
-
- if ((waitRc != vm->pid) && (errno != ECHILD)) {
- virReportSystemError(errno,
- _("waitpid failed to wait for container %d: %d"),
- vm->pid, waitRc);
- rc = -1;
- } else if (WIFEXITED(childStatus)) {
- VIR_DEBUG("container exited with rc: %d", WEXITSTATUS(childStatus));
- rc = -1;
- }
-
/* now that we know it's stopped call the hook if present */
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
char *xml = virDomainDefFormat(vm->def, 0);
@@ -1021,8 +1001,6 @@ static int lxcVmCleanup(lxc_driver_t *driver,
vm->def->id = -1;
vm->newDef = NULL;
}
-
- return rc;
}
/**
@@ -1181,11 +1159,10 @@ error:
static int lxcVmTerminate(lxc_driver_t *driver,
- virDomainObjPtr vm,
- int signum)
+ virDomainObjPtr vm)
{
- if (signum == 0)
- signum = SIGINT;
+ virCgroupPtr group = NULL;
+ int rc;
if (vm->pid <= 0) {
lxcError(VIR_ERR_INTERNAL_ERROR,
@@ -1193,18 +1170,29 @@ static int lxcVmTerminate(lxc_driver_t *driver,
return -1;
}
- if (kill(vm->pid, signum) < 0) {
- if (errno != ESRCH) {
- virReportSystemError(errno,
- _("Failed to kill pid %d"),
- vm->pid);
- return -1;
- }
+ if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
+ return -1;
+
+ rc = virCgroupKillPainfully(group);
+ if (rc < 0) {
+ virReportSystemError(-rc, "%s",
+ _("Failed to kill container PIDs"));
+ rc = -1;
+ goto cleanup;
}
+ if (rc == 1) {
+ lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Some container PIDs refused to die"));
+ rc = -1;
+ goto cleanup;
+ }
+ lxcVmCleanup(driver, vm);
- vm->state = VIR_DOMAIN_SHUTDOWN;
+ rc = 0;
- return lxcVmCleanup(driver, vm);
+cleanup:
+ virCgroupFree(&group);
+ return rc;
}
static void lxcMonitorEvent(int watch,
@@ -1228,7 +1216,7 @@ static void lxcMonitorEvent(int watch,
goto cleanup;
}
- if (lxcVmTerminate(driver, vm, SIGINT) < 0) {
+ if (lxcVmTerminate(driver, vm) < 0) {
virEventRemoveHandle(watch);
} else {
event = virDomainEventNewFromObj(vm,
@@ -1473,6 +1461,31 @@ static int lxcVmStart(virConnectPtr conn,
char **veths = NULL;
lxcDomainObjPrivatePtr priv = vm->privateData;
+ if (!lxc_driver->cgroup) {
+ lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("The 'cpuacct', 'devices' & 'memory' cgroups controllers must be mounted"));
+ return -1;
+ }
+
+ if (!virCgroupMounted(lxc_driver->cgroup,
+ VIR_CGROUP_CONTROLLER_CPUACCT)) {
+ lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to find 'cpuacct' cgroups controller mount"));
+ return -1;
+ }
+ if (!virCgroupMounted(lxc_driver->cgroup,
+ VIR_CGROUP_CONTROLLER_DEVICES)) {
+ lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to find 'devices' cgroups controller mount"));
+ return -1;
+ }
+ if (!virCgroupMounted(lxc_driver->cgroup,
+ VIR_CGROUP_CONTROLLER_MEMORY)) {
+ lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to find 'memory' cgroups controller mount"));
+ return -1;
+ }
+
if ((r = virFileMakePath(driver->logDir)) != 0) {
virReportSystemError(r,
_("Cannot create log directory '%s'"),
@@ -1543,7 +1556,7 @@ static int lxcVmStart(virConnectPtr conn,
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
lxcMonitorEvent,
vm, NULL)) < 0) {
- lxcVmTerminate(driver, vm, 0);
+ lxcVmTerminate(driver, vm);
goto cleanup;
}
@@ -1711,55 +1724,6 @@ cleanup:
return dom;
}
-/**
- * lxcDomainShutdown:
- * @dom: pointer to domain to shutdown
- *
- * Sends SIGINT to container root process to request it to shutdown
- *
- * Returns 0 on success or -1 in case of error
- */
-static int lxcDomainShutdown(virDomainPtr dom)
-{
- lxc_driver_t *driver = dom->conn->privateData;
- virDomainObjPtr vm;
- virDomainEventPtr event = NULL;
- int ret = -1;
-
- lxcDriverLock(driver);
- vm = virDomainFindByUUID(&driver->domains, dom->uuid);
- if (!vm) {
- char uuidstr[VIR_UUID_STRING_BUFLEN];
- virUUIDFormat(dom->uuid, uuidstr);
- lxcError(VIR_ERR_NO_DOMAIN,
- _("No domain with matching uuid '%s'"), uuidstr);
- goto cleanup;
- }
-
- if (!virDomainObjIsActive(vm)) {
- lxcError(VIR_ERR_OPERATION_INVALID,
- "%s", _("Domain is not running"));
- goto cleanup;
- }
-
- ret = lxcVmTerminate(driver, vm, 0);
- event = virDomainEventNewFromObj(vm,
- VIR_DOMAIN_EVENT_STOPPED,
- VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
- if (!vm->persistent) {
- virDomainRemoveInactive(&driver->domains, vm);
- vm = NULL;
- }
-
-cleanup:
- if (vm)
- virDomainObjUnlock(vm);
- if (event)
- lxcDomainEventQueue(driver, event);
- lxcDriverUnlock(driver);
- return ret;
-}
-
static int
lxcDomainEventRegister(virConnectPtr conn,
@@ -1927,7 +1891,7 @@ static int lxcDomainDestroy(virDomainPtr dom)
goto cleanup;
}
- ret = lxcVmTerminate(driver, vm, SIGKILL);
+ ret = lxcVmTerminate(driver, vm);
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
@@ -2056,7 +2020,7 @@ lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
lxcMonitorEvent,
vm, NULL)) < 0) {
- lxcVmTerminate(driver, vm, 0);
+ lxcVmTerminate(driver, vm);
goto cleanup;
}
} else {
@@ -2123,8 +2087,11 @@ static int lxcStartup(int privileged)
rc = virCgroupForDriver("lxc", &lxc_driver->cgroup, privileged, 1);
if (rc < 0) {
char buf[1024];
- VIR_WARN("Unable to create cgroup for driver: %s",
- virStrerror(-rc, buf, sizeof(buf)));
+ VIR_DEBUG("Unable to create cgroup for LXC driver: %s",
+ virStrerror(-rc, buf, sizeof(buf)));
+ /* Don't abort startup. We will explicitly report to
+ * the user when they try to start a VM
+ */
}
/* Call function to load lxc driver configuration information */
@@ -2844,7 +2811,7 @@ static virDriver lxcDriver = {
lxcDomainLookupByName, /* domainLookupByName */
lxcDomainSuspend, /* domainSuspend */
lxcDomainResume, /* domainResume */
- lxcDomainShutdown, /* domainShutdown */
+ NULL, /* domainShutdown */
NULL, /* domainReboot */
lxcDomainDestroy, /* domainDestroy */
lxcGetOSType, /* domainGetOSType */
--
1.7.4
13 years, 9 months
[libvirt] [PATCH] Add XML config switch to enable/disable vhost-net support
by Laine Stump
This patch is in response to
https://bugzilla.redhat.com/show_bug.cgi?id=643050
The existing libvirt support for the vhost-net backend to the virtio
network driver happens automatically - if the vhost-net device is
available, it is always enabled, otherwise the standard userland
virtio backend is used.
This patch makes it possible to force whether or not vhost-net is used
with a bit of XML. Adding a <driver> element to the interface XML, eg:
<interface type="network">
<model type="virtio"/>
<driver name="vhost"/>
will force use of vhost-net (if it's not available, the domain will
fail to start). if driver name="qemu", vhost-net will not be used even
if it is available.
If there is no <driver name='xxx'/> in the config, libvirt will revert
to the pre-existing automatic behavior - use vhost-net if it's
available, and userland backend if vhost-net isn't available.
---
Note that I don't really like the "name='vhost|qemu'" nomenclature,
but am including it here just to get the patches on the list. I could
live with it this way, or with any of the following (anyone have a
strong opinion?) (note that in all cases, nothing specified means "try
to use vhost, but fallback to userland if necessary")
vhost='on|off'
vhost='required|disabled'
mode='vhost|qemu'
mode='kernel|user'
backend='kernel|user'
(So far the strongest opinion has been for the current "name='vhost|qemu'")
Oh, and also - sorry Eric, but I didn't have the brain cells left
tonight to add this new bit to the documentation, and I really want to
get the patch up/in now, so that will have to wait for a followup next
week :-)
docs/schemas/domain.rng | 13 ++++++++
src/conf/domain_conf.c | 27 +++++++++++++++++-
src/conf/domain_conf.h | 10 ++++++
src/qemu/qemu_command.c | 71 +++++++++++++++++++++++++++++++++++++++--------
src/qemu/qemu_command.h | 3 --
5 files changed, 108 insertions(+), 16 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index a524e4b..6d0654d 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1005,6 +1005,19 @@
</element>
</optional>
<optional>
+ <element name="driver">
+ <optional>
+ <attribute name="name">
+ <choice>
+ <value>qemu</value>
+ <value>vhost</value>
+ </choice>
+ </attribute>
+ </optional>
+ <empty/>
+ </element>
+ </optional>
+ <optional>
<ref name="address"/>
</optional>
<optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b4df38c..04ed502 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -184,6 +184,10 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
"internal",
"direct")
+VIR_ENUM_IMPL(virDomainNetBackend, VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
+ "qemu",
+ "vhost")
+
VIR_ENUM_IMPL(virDomainChrChannelTarget,
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST,
"guestfwd",
@@ -2289,6 +2293,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
char *address = NULL;
char *port = NULL;
char *model = NULL;
+ char *backend = NULL;
char *filter = NULL;
char *internal = NULL;
char *devaddr = NULL;
@@ -2371,6 +2376,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
script = virXMLPropString(cur, "path");
} else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
model = virXMLPropString(cur, "type");
+ } else if (xmlStrEqual (cur->name, BAD_CAST "driver")) {
+ backend = virXMLPropString(cur, "name");
} else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) {
filter = virXMLPropString(cur, "filter");
VIR_FREE(filterparams);
@@ -2558,6 +2565,18 @@ virDomainNetDefParseXML(virCapsPtr caps,
model = NULL;
}
+ if ((backend != NULL) &&
+ (def->model && STREQ(def->model, "virtio"))) {
+ int b;
+ if ((b = virDomainNetBackendTypeFromString(backend)) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unkown interface <driver name='%s'> has been specified"),
+ backend);
+ goto error;
+ }
+ def->backend = b;
+ def->backend_specified = 1;
+ }
if (filter != NULL) {
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_ETHERNET:
@@ -2584,6 +2603,7 @@ cleanup:
VIR_FREE(script);
VIR_FREE(bridge);
VIR_FREE(model);
+ VIR_FREE(backend);
VIR_FREE(filter);
VIR_FREE(type);
VIR_FREE(internal);
@@ -6275,9 +6295,14 @@ virDomainNetDefFormat(virBufferPtr buf,
if (def->ifname)
virBufferEscapeString(buf, " <target dev='%s'/>\n",
def->ifname);
- if (def->model)
+ if (def->model) {
virBufferEscapeString(buf, " <model type='%s'/>\n",
def->model);
+ if (STREQ(def->model, "virtio") && def->backend_specified) {
+ virBufferVSprintf(buf, " <driver name='%s'/>\n",
+ virDomainNetBackendTypeToString(def->backend));
+ }
+ }
if (def->filter) {
virBufferEscapeString(buf, " <filterref filter='%s'",
def->filter);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a459a22..451ccad 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -292,6 +292,13 @@ enum virDomainNetType {
VIR_DOMAIN_NET_TYPE_LAST,
};
+/* the backend driver used for virtio interfaces */
+enum virDomainNetBackendType {
+ VIR_DOMAIN_NET_BACKEND_TYPE_QEMU, /* userland */
+ VIR_DOMAIN_NET_BACKEND_TYPE_VHOST, /* kernel */
+
+ VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
+};
/* the mode type for macvtap devices */
enum virDomainNetdevMacvtapType {
@@ -310,6 +317,8 @@ struct _virDomainNetDef {
enum virDomainNetType type;
unsigned char mac[VIR_MAC_BUFLEN];
char *model;
+ enum virDomainNetBackendType backend;
+ int backend_specified : 1;
union {
struct {
char *dev;
@@ -1264,6 +1273,7 @@ VIR_ENUM_DECL(virDomainControllerModel)
VIR_ENUM_DECL(virDomainFS)
VIR_ENUM_DECL(virDomainFSAccessMode)
VIR_ENUM_DECL(virDomainNet)
+VIR_ENUM_DECL(virDomainNetBackend)
VIR_ENUM_DECL(virDomainChrDevice)
VIR_ENUM_DECL(virDomainChrChannelTarget)
VIR_ENUM_DECL(virDomainChrConsoleTarget)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 86c5bb5..9eb54a1 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -302,24 +302,61 @@ cleanup:
}
-int
+static int
qemuOpenVhostNet(virDomainNetDefPtr net,
- unsigned long long qemuCmdFlags)
+ unsigned long long qemuCmdFlags,
+ int *vhostfd)
{
- /* If qemu supports vhost-net mode (including the -netdev command
- * option), the nic model is virtio, and we can open
- * /dev/vhost_net, assume that vhost-net mode is available and
- * return the fd to /dev/vhost_net. Otherwise, return -1.
- */
+ *vhostfd = -1; /* assume we won't use vhost */
+ /* If the config says explicitly to not use vhost, return now */
+ if (net->backend_specified &&
+ (net->backend == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU)) {
+ return 0;
+ }
+
+ /* If qemu doesn't support vhost-net mode (including the -netdev command
+ * option), don't try to open the device.
+ */
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_VNET_HOST &&
qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV &&
- qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE &&
- net->model && STREQ(net->model, "virtio")))
- return -1;
+ qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
+ if (net->backend_specified &&
+ (net->backend == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST)) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("vhost-net is not supported with "
+ "this QEMU binary"));
+ return -1;
+ }
+ return 0;
+ }
- return open("/dev/vhost-net", O_RDWR, 0);
+ /* If the nic model isn't virtio, don't try to open. */
+ if (!(net->model && STREQ(net->model, "virtio"))) {
+ if (net->backend_specified &&
+ (net->backend == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST)) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("vhost-net is only supported for "
+ "virtio network interfaces"));
+ return -1;
+ }
+ return 0;
+ }
+
+ *vhostfd = open("/dev/vhost-net", O_RDWR, 0);
+
+ /* If the config says explicitly to use vhost and we couldn't open it,
+ * report an error.
+ */
+ if ((*vhostfd < 0) && net->backend_specified &&
+ (net->backend == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST)) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("vhost-net was requested for an interface, "
+ "but is unavailable"));
+ return -1;
+ }
+ return 0;
}
@@ -3278,7 +3315,10 @@ qemuBuildCommandLine(virConnectPtr conn,
net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
/* Attempt to use vhost-net mode for these types of
network device */
- int vhostfd = qemuOpenVhostNet(net, qemuCmdFlags);
+ int vhostfd;
+
+ if (qemuOpenVhostNet(net, qemuCmdFlags, &vhostfd) < 0)
+ goto error;
if (vhostfd >= 0) {
virCommandTransferFD(cmd, vhostfd);
@@ -4618,6 +4658,13 @@ qemuParseCommandLineNet(virCapsPtr caps,
} else if (STREQ(keywords[i], "model")) {
def->model = values[i];
values[i] = NULL;
+ } else if (STREQ(keywords[i], "vhost")) {
+ if ((values[i] == NULL) || STREQ(values[i], "on")) {
+ def->backend = VIR_DOMAIN_NET_BACKEND_TYPE_VHOST;
+ } else if (STREQ(keywords[i], "off")) {
+ def->backend = VIR_DOMAIN_NET_BACKEND_TYPE_QEMU;
+ }
+ def->backend_specified = 1;
}
}
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 4c42a10..5439184 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -116,9 +116,6 @@ int qemuNetworkIfaceConnect(virConnectPtr conn,
unsigned long long qemCmdFlags)
ATTRIBUTE_NONNULL(1);
-int qemuOpenVhostNet(virDomainNetDefPtr net,
- unsigned long long qemuCmdFlags);
-
int qemuPhysIfaceConnect(virConnectPtr conn,
struct qemud_driver *driver,
virDomainNetDefPtr net,
--
1.7.3.4
13 years, 9 months
[libvirt] [RFC PATCH 0/5] Allow data upload/download to/from storage volumes
by Daniel P. Berrange
This patch series introduces two new APIs to allow data upload/download
to/from storage volumes, using the streams APIs. Mostly I wrote this so
I had an easier way to test the streams handling in my RPC patch series
than using QEMU tunnelled migration code. Cole has expressed an interest
in this kind of functionality in the past to allow virt-manager to upload
kernel/initrd to remote hosts for provisioning guests.
Most of the code here is pretty boring & trivial. The first patch is the
one that is remotely interesting. One might argue we should just spawn
'dd' instead of this, but dd has some annoying aspects (you can't control
its write offset in units smaller than the block size) and this could be
useful more broadly.
13 years, 9 months