[libvirt] F10: how to save snapshot back to image?
by Gerry Reno
In Fedora 10 I've managed to get libvirt to call the emulator with
custom arguments so I can invoke -snapshot. I just replaced the
emulator in /usr/bin with my own script which adds the argument and then
calls the original emulator. This works fine. And the snapshot works
fine. I can make lots of changes and when I shutdown and restart then
all the changes are forgotten. Now after I'm satisfied with some
changes I want to save the snapshot back to the image file. I've tried
"Ctrl-Alt-s", but this does not work. I tried finding the QEMU console,
but Serial Console is grayed out in the menu. I don't know if that
would help anyway since this was a raw image and not qcow2 so I don't
think 'savevm' and 'loadvm' would work with raw.
Can someone tell me how to save these snapshots back to the image file?
Thanks.
Regards,
Gerry
15 years, 6 months
[libvirt] PATCH: Allow LXC to use private /dev/pts instance
by Daniel P. Berrange
One of the current flaws in the LXC driver is that when doing the better-
chroot-than-chroot mode setup, /dev/pts leaks the parent OS TTYs into
the container.
As of 2.6.29 it is possible to create new instances of /dev/pts by passing
the 'newinstance' flag to mount. In this way /dev/pts inside the container
will be totally independant of the parent OS.
This is a kind of fun / tricky thing to get right, because the monitor
process (libvirt_lxc) actually needs 2 ttys, one in the host's /dev/pts
(which virsh console connects to), and the other in the container's
/dev/pts (which acts as its stdin/out/err).
This means that libvirt_lxc has to mount the new devpts instance on
the containers root filesystem before starting the container itself.
To avoid this then appearing in the host OS, we make libvirt_lxc
call unshare(CLONE_NEWNS). This also has the nice advantage of adding
a guarentee that this new devpts instance is cleaned up with libvirt_lxc
exits.
Now in the container startup sequence, instead of mounting a devpts
instance, it just moves the instance that libvirt_lxc previously
setup into its desired location.
I have arranged this so that if the host OS kernel lacks support for
the 'newinstance' flag with devpts, it'll just use a regular shared
instance. If this happens, then /var/log/libvirt/lxc/$NAME.log
should warn you
16:55:00.454: warning : kernel does not support private devpts, using shared devpts
Also the previous patch to pivot_root() setup added a chroot() call. For
some wierd reason, with this all the host OS's mounts are still visible
in the container's /proc/mounts, even though they are not actually
accessible (since we pivot'd onto a new root)
This change seemed to fix that problem with no ill-effects.
- if (chroot(oldroot) < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("failed to chroot into tmpfs"));
- goto err;
- }
-
- if (chdir("/new") < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("failed to chdir into /new on tmpfs"));
+ if (chdir(newroot) < 0) {
+ virReportSystemError(NULL, errno,
+ _("failed to chroot into %s"), newroot);
goto err;
}
There was also a call added to umount the .oldroot location, but
this was being done too early, because later methods still needed
to access various bits under /.oldroot - eg to mount other (non-root)
filesystems from the host OS in the container.
So I'm removing this chunk:
if (chdir("/") < 0)
goto err;
- if (umount2(".oldroot", MNT_DETACH) < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("failed to lazily unmount old root"));
- goto err;
- }
-
This showed up a different problem though. Our call later on which
would unmount /.oldroot was failing because there were some open
file descriptors on /var/ still.
This was because we didn't setup stdin/out until after we'd dealt
with all the mounts. So my patch also makes sure that the first
thing we do is close all open file descriptors and move stdin/out/err
immdiately onto the TTY allocated for this container. That ensures
all the mounts are able to be released.
I've tested this patch on 2.6.27 (lacking 'newinstance') and on
2.6.29 (with 'newinstance' for devpts). It seemed to work correctly
in both cases, but would appreciate someone else confirming....
domain_conf.c | 15 ++++
domain_conf.h | 2
libvirt_private.syms | 1
lxc_container.c | 175 +++++++++++++++++++++++++++++++--------------------
lxc_container.h | 1
lxc_controller.c | 87 +++++++++++++++++++++++--
util.c | 22 ++++--
util.h | 4 +
8 files changed, 230 insertions(+), 77 deletions(-)
Daniel
Index: src/domain_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/domain_conf.c,v
retrieving revision 1.75
diff -u -p -r1.75 domain_conf.c
--- src/domain_conf.c 3 Apr 2009 14:10:17 -0000 1.75
+++ src/domain_conf.c 15 Apr 2009 15:44:52 -0000
@@ -3855,6 +3857,21 @@ const char *virDomainDefDefaultEmulator(
return emulator;
}
+virDomainFSDefPtr virDomainGetRootFilesystem(virDomainDefPtr def)
+{
+ int i;
+
+ for (i = 0 ; i < def->nfss ; i++) {
+ if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
+ continue;
+
+ if (STREQ(def->fss[i]->dst, "/"))
+ return def->fss[i];
+ }
+
+ return NULL;
+}
+
void virDomainObjLock(virDomainObjPtr obj)
{
Index: src/domain_conf.h
===================================================================
RCS file: /data/cvs/libvirt/src/domain_conf.h,v
retrieving revision 1.40
diff -u -p -r1.40 domain_conf.h
--- src/domain_conf.h 3 Mar 2009 16:53:13 -0000 1.40
+++ src/domain_conf.h 15 Apr 2009 15:44:52 -0000
@@ -635,6 +635,8 @@ const char *virDomainDefDefaultEmulator(
virDomainDefPtr def,
virCapsPtr caps);
+virDomainFSDefPtr virDomainGetRootFilesystem(virDomainDefPtr def);
+
void virDomainObjLock(virDomainObjPtr obj);
void virDomainObjUnlock(virDomainObjPtr obj);
Index: src/libvirt_private.syms
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt_private.syms,v
retrieving revision 1.28
diff -u -p -r1.28 libvirt_private.syms
--- src/libvirt_private.syms 3 Apr 2009 10:55:51 -0000 1.28
+++ src/libvirt_private.syms 15 Apr 2009 15:44:52 -0000
@@ -78,6 +78,7 @@ virDomainDiskQSort;
virDomainFindByID;
virDomainFindByName;
virDomainFindByUUID;
+virDomainGetRootFilesystem;
virDomainGraphicsTypeFromString;
virDomainGraphicsDefFree;
virDomainInputDefFree;
Index: src/lxc_container.c
===================================================================
RCS file: /data/cvs/libvirt/src/lxc_container.c,v
retrieving revision 1.23
diff -u -p -r1.23 lxc_container.c
--- src/lxc_container.c 14 Apr 2009 17:51:12 -0000 1.23
+++ src/lxc_container.c 15 Apr 2009 15:44:52 -0000
@@ -306,13 +306,13 @@ static int lxcContainerPivotRoot(virDoma
/* Create a tmpfs root since old and new roots must be
* on separate filesystems */
- if (mount("", oldroot, "tmpfs", 0, NULL) < 0) {
+ if (mount("tmprootfs", oldroot, "tmpfs", 0, NULL) < 0) {
virReportSystemError(NULL, errno,
_("failed to mount empty tmpfs at %s"),
oldroot);
goto err;
}
-
+
/* Create a directory called 'new' in tmpfs */
if (virAsprintf(&newroot, "%s/new", oldroot) < 0) {
virReportOOMError(NULL);
@@ -336,15 +336,9 @@ static int lxcContainerPivotRoot(virDoma
/* Now we chroot into the tmpfs, then pivot into the
* root->src bind-mounted onto '/new' */
- if (chroot(oldroot) < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("failed to chroot into tmpfs"));
- goto err;
- }
-
- if (chdir("/new") < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("failed to chdir into /new on tmpfs"));
+ if (chdir(newroot) < 0) {
+ virReportSystemError(NULL, errno,
+ _("failed to chroot into %s"), newroot);
goto err;
}
@@ -360,12 +354,6 @@ static int lxcContainerPivotRoot(virDoma
if (chdir("/") < 0)
goto err;
- if (umount2(".oldroot", MNT_DETACH) < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("failed to lazily unmount old root"));
- goto err;
- }
-
VIR_FREE(oldroot);
VIR_FREE(newroot);
@@ -377,50 +365,77 @@ err:
return -1;
}
-static int lxcContainerPopulateDevices(void)
+
+static int lxcContainerMountBasicFS(virDomainFSDefPtr root)
{
- int i;
- int rc;
const struct {
- int maj;
- int min;
- mode_t mode;
- const char *path;
- } devs[] = {
- { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL, 0666, "/dev/null" },
- { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO, 0666, "/dev/zero" },
- { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL, 0666, "/dev/full" },
- { LXC_DEV_MAJ_TTY, LXC_DEV_MIN_CONSOLE, 0600, "/dev/console" },
- { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/dev/random" },
- { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/dev/urandom" },
+ const char *src;
+ const char *dst;
+ const char *type;
+ } mnts[] = {
+ { "/dev", "/dev", "tmpfs" },
+ { "/proc", "/proc", "proc" },
+ { "/sys", "/sys", "sysfs" },
+#if WITH_SELINUX
+ { "none", "/selinux", "selinuxfs" },
+#endif
};
+ int i, rc;
+ char *devpts;
- if ((rc = virFileMakePath("/dev")) < 0) {
- virReportSystemError(NULL, rc, "%s",
- _("cannot create /dev/"));
+ if (virAsprintf(&devpts, "/.oldroot%s/dev/pts", root->src) < 0) {
+ virReportOOMError(NULL);
return -1;
}
- if (mount("none", "/dev", "tmpfs", 0, NULL) < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("failed to mount /dev tmpfs"));
- return -1;
+
+ for (i = 0 ; i < ARRAY_CARDINALITY(mnts) ; i++) {
+ if (virFileMakePath(mnts[i].dst) < 0) {
+ virReportSystemError(NULL, errno,
+ _("failed to mkdir %s"),
+ mnts[i].src);
+ return -1;
+ }
+ if (mount(mnts[i].src, mnts[i].dst, mnts[i].type, 0, NULL) < 0) {
+ virReportSystemError(NULL, errno,
+ _("failed to mount %s on %s"),
+ mnts[i].type, mnts[i].type);
+ return -1;
+ }
}
- /* Move old devpts into container, since we have to
- connect to the master ptmx which was opened in
- the parent.
- XXX This sucks, we need to figure out how to get our
- own private devpts for isolation
- */
+
if ((rc = virFileMakePath("/dev/pts") < 0)) {
virReportSystemError(NULL, rc, "%s",
_("cannot create /dev/pts"));
return -1;
}
- if (mount("devpts", "/dev/pts", "devpts", 0, NULL) < 0) {
+
+ VIR_DEBUG("Trying to move %s to %s", devpts, "/dev/pts");
+ if ((rc = mount(devpts, "/dev/pts", NULL, MS_MOVE, NULL)) < 0) {
virReportSystemError(NULL, errno, "%s",
_("failed to mount /dev/pts in container"));
return -1;
}
+ VIR_FREE(devpts);
+
+ return 0;
+}
+
+static int lxcContainerPopulateDevices(void)
+{
+ int i;
+ const struct {
+ int maj;
+ int min;
+ mode_t mode;
+ const char *path;
+ } devs[] = {
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL, 0666, "/dev/null" },
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO, 0666, "/dev/zero" },
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL, 0666, "/dev/full" },
+ { LXC_DEV_MAJ_TTY, LXC_DEV_MIN_CONSOLE, 0600, "/dev/console" },
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/dev/random" },
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/dev/urandom" },
+ };
/* Populate /dev/ with a few important bits */
for (i = 0 ; i < ARRAY_CARDINALITY(devs) ; i++) {
@@ -434,6 +449,23 @@ static int lxcContainerPopulateDevices(v
}
}
+ if (access("/dev/pts/ptmx", W_OK) == 0) {
+ if (symlink("/dev/pts/ptmx", "/dev/ptmx") < 0) {
+ virReportSystemError(NULL, errno, "%s",
+ _("failed to create symlink /dev/ptmx to /dev/pts/ptmx"));
+ return -1;
+ }
+ } else {
+ dev_t dev = makedev(LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX);
+ if (mknod("/dev/ptmx", 0, dev) < 0 ||
+ chmod("/dev/ptmx", 0666)) {
+ virReportSystemError(NULL, errno, "%s",
+ _("failed to make device /dev/ptmx"));
+ return -1;
+ }
+ }
+
+
return 0;
}
@@ -493,6 +525,7 @@ static int lxcContainerUnmountOldFS(void
return -1;
}
while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
+ VIR_DEBUG("Got %s", mntent.mnt_dir);
if (!STRPREFIX(mntent.mnt_dir, "/.oldroot"))
continue;
@@ -513,6 +546,7 @@ static int lxcContainerUnmountOldFS(void
lxcContainerChildMountSort);
for (i = 0 ; i < nmounts ; i++) {
+ VIR_DEBUG("Umount %s", mounts[i]);
if (umount(mounts[i]) < 0) {
virReportSystemError(NULL, errno,
_("failed to unmount '%s'"),
@@ -534,22 +568,23 @@ static int lxcContainerUnmountOldFS(void
static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
virDomainFSDefPtr root)
{
+ /* Gives us a private root, leaving all parent OS mounts on /.oldroot */
if (lxcContainerPivotRoot(root) < 0)
return -1;
- if (virFileMakePath("/proc") < 0 ||
- mount("none", "/proc", "proc", 0, NULL) < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("failed to mount /proc"));
+ /* Mounts the core /proc, /sys, /dev, /dev/pts filesystems */
+ if (lxcContainerMountBasicFS(root) < 0)
return -1;
- }
+ /* Populates device nodes in /dev/ */
if (lxcContainerPopulateDevices() < 0)
return -1;
+ /* Sets up any non-root mounts from guest config */
if (lxcContainerMountNewFS(vmDef) < 0)
return -1;
+ /* Gets rid of all remaining mounts from host OS, including /.oldroot itself */
if (lxcContainerUnmountOldFS() < 0)
return -1;
@@ -595,18 +630,9 @@ static int lxcContainerSetupExtraMounts(
return 0;
}
-static int lxcContainerSetupMounts(virDomainDefPtr vmDef)
+static int lxcContainerSetupMounts(virDomainDefPtr vmDef,
+ virDomainFSDefPtr root)
{
- int i;
- virDomainFSDefPtr root = NULL;
-
- for (i = 0 ; i < vmDef->nfss ; i++) {
- if (vmDef->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
- continue;
- if (STREQ(vmDef->fss[i]->dst, "/"))
- root = vmDef->fss[i];
- }
-
if (root)
return lxcContainerSetupPivotRoot(vmDef, root);
else
@@ -630,6 +656,8 @@ static int lxcContainerChild( void *data
lxc_child_argv_t *argv = data;
virDomainDefPtr vmDef = argv->config;
int ttyfd;
+ char *ttyPath;
+ virDomainFSDefPtr root;
if (NULL == vmDef) {
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -637,16 +665,28 @@ static int lxcContainerChild( void *data
return -1;
}
- if (lxcContainerSetupMounts(vmDef) < 0)
- return -1;
+ root = virDomainGetRootFilesystem(vmDef);
- ttyfd = open(argv->ttyPath, O_RDWR|O_NOCTTY);
+ if (root) {
+ if (virAsprintf(&ttyPath, "%s%s", root->src, argv->ttyPath) < 0) {
+ virReportOOMError(NULL);
+ return -1;
+ }
+ } else {
+ if (!(ttyPath = strdup(argv->ttyPath))) {
+ virReportOOMError(NULL);
+ return -1;
+ }
+ }
+
+ ttyfd = open(ttyPath, O_RDWR|O_NOCTTY);
if (ttyfd < 0) {
virReportSystemError(NULL, errno,
- _("failed to open %s"),
- argv->ttyPath);
+ _("failed to open tty %s"),
+ ttyPath);
return -1;
}
+ VIR_FREE(ttyPath);
if (lxcContainerSetStdio(argv->monitor, ttyfd) < 0) {
close(ttyfd);
@@ -654,6 +694,9 @@ static int lxcContainerChild( void *data
}
close(ttyfd);
+ if (lxcContainerSetupMounts(vmDef, root) < 0)
+ return -1;
+
/* Wait for interface devices to show up */
if (lxcContainerWaitForContinue(argv->monitor) < 0)
return -1;
Index: src/lxc_container.h
===================================================================
RCS file: /data/cvs/libvirt/src/lxc_container.h,v
retrieving revision 1.9
diff -u -p -r1.9 lxc_container.h
--- src/lxc_container.h 21 Oct 2008 16:46:47 -0000 1.9
+++ src/lxc_container.h 15 Apr 2009 15:44:52 -0000
@@ -39,6 +39,7 @@ enum {
#define LXC_DEV_MAJ_TTY 5
#define LXC_DEV_MIN_CONSOLE 1
+#define LXC_DEV_MIN_PTMX 2
#define LXC_DEV_MAJ_PTY 136
Index: src/lxc_controller.c
===================================================================
RCS file: /data/cvs/libvirt/src/lxc_controller.c,v
retrieving revision 1.15
diff -u -p -r1.15 lxc_controller.c
--- src/lxc_controller.c 3 Feb 2009 13:09:00 -0000 1.15
+++ src/lxc_controller.c 15 Apr 2009 15:44:52 -0000
@@ -33,6 +33,7 @@
#include <fcntl.h>
#include <signal.h>
#include <getopt.h>
+#include <sys/mount.h>
#include "virterror_internal.h"
#include "logging.h"
@@ -440,6 +441,9 @@ lxcControllerRun(virDomainDefPtr def,
int containerPty;
char *containerPtyPath;
pid_t container = -1;
+ virDomainFSDefPtr root;
+ char *devpts = NULL;
+ char *devptmx = NULL;
if (socketpair(PF_UNIX, SOCK_STREAM, 0, control) < 0) {
virReportSystemError(NULL, errno, "%s",
@@ -447,14 +451,83 @@ lxcControllerRun(virDomainDefPtr def,
goto cleanup;
}
- if (virFileOpenTty(&containerPty,
- &containerPtyPath,
- 0) < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("failed to allocate tty"));
- goto cleanup;
+ root = virDomainGetRootFilesystem(def);
+
+ /*
+ * If doing a chroot style setup, we need to prepare
+ * a private /dev/pts for the child now, which they
+ * will later move into position.
+ *
+ * This is complex because 'virsh console' needs to
+ * use /dev/pts from the host OS, and the guest OS
+ * needs to use /dev/pts from the guest.
+ *
+ * This means that we (libvirt_lxc) need to see and
+ * use both /dev/pts instances. We're running in the
+ * host OS context though and don't want to expose
+ * the guest OS /dev/pts there.
+ *
+ * Thus we call unshare(CLONE_NS) so that we can see
+ * the guest's new /dev/pts, without it becoming
+ * visible to the host OS.
+ */
+ if (root) {
+ VIR_DEBUG0("Setting up private /dev/pts");
+ if (unshare(CLONE_NEWNS) < 0) {
+ virReportSystemError(NULL, errno, "%s",
+ _("cannot unshare mount namespace"));
+ goto cleanup;
+ }
+
+ if (virAsprintf(&devpts, "%s/dev/pts", root->src) < 0 ||
+ virAsprintf(&devptmx, "%s/dev/pts/ptmx", root->src) < 0) {
+ virReportOOMError(NULL);
+ goto cleanup;
+ }
+
+ if (virFileMakePath(devpts) < 0) {
+ virReportSystemError(NULL, errno,
+ _("failed to make path %s"),
+ devpts);
+ goto cleanup;
+ }
+
+ VIR_DEBUG("Mouting 'devpts' on %s", devpts);
+ if (mount("devpts", devpts, "devpts", 0, "newinstance,ptmxmode=0666") < 0) {
+ virReportSystemError(NULL, errno,
+ _("failed to mount devpts on %s"),
+ devpts);
+ goto cleanup;
+ }
+
+ if (access(devptmx, R_OK) < 0) {
+ VIR_WARN0("kernel does not support private devpts, using shared devpts");
+ VIR_FREE(devptmx);
+ }
}
+ if (devptmx) {
+ VIR_DEBUG("Opening tty on private %s", devptmx);
+ if (virFileOpenTtyAt(devptmx,
+ &containerPty,
+ &containerPtyPath,
+ 0) < 0) {
+ virReportSystemError(NULL, errno, "%s",
+ _("failed to allocate tty"));
+ goto cleanup;
+ }
+ } else {
+ VIR_DEBUG0("Opening tty on shared /dev/ptmx");
+ if (virFileOpenTty(&containerPty,
+ &containerPtyPath,
+ 0) < 0) {
+ virReportSystemError(NULL, errno, "%s",
+ _("failed to allocate tty"));
+ goto cleanup;
+ }
+ }
+
+
if (lxcSetContainerResources(def) < 0)
goto cleanup;
@@ -476,6 +549,8 @@ lxcControllerRun(virDomainDefPtr def,
rc = lxcControllerMain(monitor, client, appPty, containerPty);
cleanup:
+ VIR_FREE(devptmx);
+ VIR_FREE(devpts);
if (control[0] != -1)
close(control[0]);
if (control[1] != -1)
Index: src/util.c
===================================================================
RCS file: /data/cvs/libvirt/src/util.c,v
retrieving revision 1.99
diff -u -p -r1.99 util.c
--- src/util.c 2 Apr 2009 18:42:33 -0000 1.99
+++ src/util.c 15 Apr 2009 15:44:52 -0000
@@ -1050,14 +1050,25 @@ int virFileBuildPath(const char *dir,
}
-#ifdef __linux__
int virFileOpenTty(int *ttymaster,
char **ttyName,
int rawmode)
{
+ return virFileOpenTtyAt("/dev/ptmx",
+ ttymaster,
+ ttyName,
+ rawmode);
+}
+
+#ifdef __linux__
+int virFileOpenTtyAt(const char *ptmx,
+ int *ttymaster,
+ char **ttyName,
+ int rawmode)
+{
int rc = -1;
- if ((*ttymaster = posix_openpt(O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0)
+ if ((*ttymaster = open(ptmx, O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0)
goto cleanup;
if (unlockpt(*ttymaster) < 0)
@@ -1100,9 +1111,10 @@ cleanup:
}
#else
-int virFileOpenTty(int *ttymaster ATTRIBUTE_UNUSED,
- char **ttyName ATTRIBUTE_UNUSED,
- int rawmode ATTRIBUTE_UNUSED)
+int virFileOpenTtyAt(const char *ptmx ATTRIBUTE_UNUSED,
+ int *ttymaster ATTRIBUTE_UNUSED,
+ char **ttyName ATTRIBUTE_UNUSED,
+ int rawmode ATTRIBUTE_UNUSED)
{
return -1;
}
Index: src/util.h
===================================================================
RCS file: /data/cvs/libvirt/src/util.h,v
retrieving revision 1.46
diff -u -p -r1.46 util.h
--- src/util.h 1 Apr 2009 10:26:22 -0000 1.46
+++ src/util.h 15 Apr 2009 15:44:52 -0000
@@ -103,6 +103,10 @@ int virFileBuildPath(const char *dir,
int virFileOpenTty(int *ttymaster,
char **ttyName,
int rawmode);
+int virFileOpenTtyAt(const char *ptmx,
+ int *ttymaster,
+ char **ttyName,
+ int rawmode);
char* virFilePid(const char *dir,
const char *name);
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 6 months
[libvirt] PATCH: Add a tool virt-xml-validate
by Daniel P. Berrange
While we install our RNG schemas into the filesystem, and users could
use xmllint to validate them, it is a little tedious to use this way.
This patch adds a nice simple command
virt-xml-validate XML-FILE [SCHEMA-NAME]
You can use it on any XML file format that libvirt knows about
# virt-xml-validate ~/rhel5xen.xml
/home/berrange/rhel5xen.xml validates
#$ echo $?
0
I normally figures out the SCHEMA-NAME from the top level element name,
but you can override it if desired
# virt-xml-validate ~/bug.xml
virt-xml-validate: cannot determine schema type for /home/berrange/bug.xml
# virt-xml-validate ~/bug.xml domain
/home/berrange/bug.txt:1: parser error : Start tag expected, '<' not found
From bugzilla(a)redhat.com Fri Feb 27 01:12:11 2009
^
I've included a man page in the command.
This patch also fixes numerous bugs in the virsh man page source
The 'src/' directory is getting over large, so I decided we should have
a separate 'tools' directory for command line programs included in the
main libvirt source. We could consider moving virsh here perhaps.
.hgignore | 12 ++
Makefile.am | 2
b/tools/.cvsignore | 4
b/tools/.gitignore | 4
b/tools/Makefile.am | 14 ++
b/tools/virt-xml-validate.in | 151 ++++++++++++++++++++++++++
configure.in | 1
docs/Makefile.am | 2
docs/virsh.pod | 80 ++++++++++++--
libvirt.spec.in | 4
virsh.1 | 241 ++++++++++++++++++++++++++-----------------
11 files changed, 408 insertions(+), 107 deletions(-)
Daniel
diff -r f861822d43db .hgignore
--- a/.hgignore Thu Apr 16 10:34:11 2009 +0100
+++ b/.hgignore Thu Apr 16 12:44:17 2009 +0100
@@ -46,12 +46,19 @@ docs/examples/info1
docs/examples/python/Makefile
docs/examples/python/Makefile.in
docs/examples/suspend
+docs/schemas/Makefile
+docs/schemas/Makefile.in
examples/domain-events/events-c/*.exe
examples/domain-events/events-c/.deps
examples/domain-events/events-c/.libs
examples/domain-events/events-c/Makefile
examples/domain-events/events-c/Makefile.in
examples/domain-events/events-c/event-test
+examples/hellolibvirt/.deps
+examples/hellolibvirt/.libs
+examples/hellolibvirt/Makefile
+examples/hellolibvirt/Makefile.in
+examples/hellolibvirt/hellolibvirt
gnulib/lib/*.la
gnulib/lib/*.lo
gnulib/lib/.deps
@@ -260,6 +267,7 @@ tests/qemuxml2argvtest
tests/qemuxml2xmltest
tests/qparamtest
tests/reconnect
+tests/seclabeltest
tests/sexpr2xmldata/Makefile
tests/sexpr2xmldata/Makefile.in
tests/sexpr2xmltest
@@ -274,4 +282,8 @@ tests/xmconfigtest
tests/xml2sexprdata/Makefile
tests/xml2sexprdata/Makefile.in
tests/xml2sexprtest
+tools/Makefile
+tools/Makefile.in
+tools/virt-xml-validate
+tools/virt-xml-validate.1
update.log
diff -r f861822d43db Makefile.am
--- a/Makefile.am Thu Apr 16 10:34:11 2009 +0100
+++ b/Makefile.am Thu Apr 16 12:44:17 2009 +0100
@@ -3,7 +3,7 @@
LCOV = lcov
GENHTML = genhtml
-SUBDIRS = gnulib/lib include src qemud proxy docs gnulib/tests \
+SUBDIRS = gnulib/lib include src qemud tools proxy docs gnulib/tests \
python tests po examples/domain-events/events-c examples/hellolibvirt
ACLOCAL_AMFLAGS = -I m4 -I gnulib/m4
diff -r f861822d43db configure.in
--- a/configure.in Thu Apr 16 10:34:11 2009 +0100
+++ b/configure.in Thu Apr 16 12:44:17 2009 +0100
@@ -1342,6 +1342,7 @@ AC_OUTPUT(Makefile src/Makefile include/
include/libvirt/Makefile include/libvirt/libvirt.h \
python/Makefile python/tests/Makefile \
qemud/Makefile \
+ tools/Makefile \
tests/Makefile proxy/Makefile \
tests/xml2sexprdata/Makefile \
tests/sexpr2xmldata/Makefile \
diff -r f861822d43db docs/Makefile.am
--- a/docs/Makefile.am Thu Apr 16 10:34:11 2009 +0100
+++ b/docs/Makefile.am Thu Apr 16 12:44:17 2009 +0100
@@ -66,7 +66,7 @@ EXTRA_DIST= \
all: web $(top_builddir)/NEWS $(man_MANS)
virsh.1: virsh.pod
- pod2man -c "Virtualization Support" $(srcdir)/virsh.pod > $@-t
+ pod2man -c "Virtualization Support" -r "$(PACKAGE)-$(VERSION)" $(srcdir)/virsh.pod > $@-t
mv $@-t $@
cp $@ $(top_builddir)
diff -r f861822d43db docs/virsh.pod
--- a/docs/virsh.pod Thu Apr 16 10:34:11 2009 +0100
+++ b/docs/virsh.pod Thu Apr 16 12:44:17 2009 +0100
@@ -150,13 +150,13 @@ B<virsh> list
Name is the name of the domain. ID the domain numeric id.
State is the run state (see below).
-=over 4
-
B<STATES>
The State field lists 6 states for a domain, and which ones the
current domain is in.
+=over 4
+
=item B<running>
The domain is currently running on a CPU
@@ -198,12 +198,16 @@ crashed.
Prints the available amount of memory on the machine or within a
NUMA cell if I<cellno> is provided.
+=back
+
=head1 DOMAIN COMMANDS
The following commands manipulate domains directly, as stated
previously most commands take domain-id as the first parameter. The
I<domain-id> can be specified as an short integer, a name or a full UUID.
+=over 4
+
=item B<autostart> optional I<--disable> I<domain-id>
Configure a domain to be automatically started at boot.
@@ -401,7 +405,9 @@ and I<cpulist> is a comma separated list
Output the IP address and port number for the VNC display. If the information
is not available the processes will provide an exit code of 1.
-=head1 DEVICES COMMANDS
+=back
+
+=head1 DEVICE COMMANDS
The following commands manipulate devices associated to domains.
The domain-id can be specified as an short integer, a name or a full UUID.
@@ -409,6 +415,8 @@ To better understand the values allowed
reading the documentation at L<http://libvirt.org/format.html> on the
format of the device sections to get the most accurate set of accepted values.
+=over 4
+
=item B<attach-device> I<domain-id> I<FILE>
Attach a device to the domain, using a device definition in an XML file.
@@ -449,7 +457,9 @@ I<type> can be either I<network> to indi
It is recommended to use the I<mac> option to distinguish between the interfaces
if more than one are present on the domain.
-=head1 VIRTUAL NETWORKS COMMANDS
+=back
+
+=head1 VIRTUAL NETWORK COMMANDS
The following commands manipulate networks. Libvirt has the capability to
define virtual networks which can then be used by domains and linked to
@@ -458,6 +468,8 @@ see the documentation at L<http://libvir
of the command for virtual networks are similar to the one used for domains,
but the way to name a virtual network is either by its name or UUID.
+=over 4
+
=item B<net-autostart> I<network> optional I<--disable>
Configure a virtual network to be automatically started at boot.
@@ -517,18 +529,55 @@ Undefine the configuration for an inacti
Convert a network name to network UUID.
+=back
+
=head1 ENVIRONMENT
+The following environment variables can be set to alter the behaviour
+of C<virsh>
+
+=over 4
+
=item VIRSH_DEFAULT_CONNECT_URI
The hypervisor to connect to by default. Set this to a URI, in the same
format as accepted by the B<connect> option.
-=head1 SEE ALSO
+=item LIBVIRT_DEBUG=LEVEL
-L<virt-install(1)>, L<xm(1)>, L<virt-top(1)>, L<virt-mem(1)>, L<virt-df(1)>, L<http://www.libvirt.org/>
+Turn on verbose debugging of all libvirt API calls. Valid levels are
-=head1 AUTHOR
+=over 4
+
+=item * LIBVIRT_DEBUG=1
+
+Messages at level DEBUG or above
+
+=item * LIBVIRT_DEBUG=2
+
+Messages at level INFO or above
+
+=item * LIBVIRT_DEBUG=3
+
+Messages at level WARNING or above
+
+=item * LIBVIRT_DEBUG=4
+
+Messages at level ERROR or above
+
+=back
+
+For further information about debugging options consult C<http://libvirt.org/logging.html>
+
+=back
+
+=head1 BUGS
+
+Report any bugs discovered to the libvirt community via the mailing
+list C<http://libvirt.org/contact.html> or bug tracker C<http://libvirt.org/bugs.html>.
+Alternatively report bugs to your software distributor / vendor.
+
+=head1 AUTHORS
Andrew Puch <apuch @ redhat.com>
Daniel Veillard <veillard @ redhat.com>
@@ -537,12 +586,19 @@ L<virt-install(1)>, L<xm(1)>, L<virt-top
Sean Dague <sean at dague dot net>
Daniel Stekloff <dsteklof at us dot ibm dot com>
+=head1 COPYRIGHT
-=head1 BUGS
+Copyright (C) 2005, 2007-2009 Red Hat, Inc.
-Bugs can be filed in Red Hat bugzilla under the Virtualization Tools/libvirt
-L<https://bugzilla.redhat.com/>
+=head1 LICENSE
-L<https://bugzilla.redhat.com/buglist.cgi?product=Virtualization+Tools&comp...>
+virsh is distributed under the terms of the GNU LGPL v2+.
+This is free software; see the source for copying conditions. There
+is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE
-=end
+=head1 SEE ALSO
+
+L<virt-install(1)>, L<virt-xml-validate(1)>, L<virt-top(1)>, L<virt-mem(1)>, L<virt-df(1)>, L<http://www.libvirt.org/>
+
+=cut
diff -r f861822d43db libvirt.spec.in
--- a/libvirt.spec.in Thu Apr 16 10:34:11 2009 +0100
+++ b/libvirt.spec.in Thu Apr 16 12:44:17 2009 +0100
@@ -372,8 +372,10 @@ fi
%defattr(-, root, root)
%doc AUTHORS ChangeLog NEWS README COPYING.LIB TODO
-%doc %{_mandir}/man1/virsh.1*
+%{_mandir}/man1/virsh.1*
+%{_mandir}/man1/virt-xml-validate.1*
%{_bindir}/virsh
+%{_bindir}/virt-xml-validate
%{_libdir}/lib*.so.*
%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/
diff -r f861822d43db tools/.cvsignore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/.cvsignore Thu Apr 16 12:44:17 2009 +0100
@@ -0,0 +1,4 @@
+virt-xml-validate
+virt-xml-validate.1
+Makefile
+Makefile.in
diff -r f861822d43db tools/.gitignore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/.gitignore Thu Apr 16 12:44:17 2009 +0100
@@ -0,0 +1,4 @@
+virt-xml-validate
+virt-xml-validate.1
+Makefile
+Makefile.in
diff -r f861822d43db tools/Makefile.am
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/Makefile.am Thu Apr 16 12:44:17 2009 +0100
@@ -0,0 +1,14 @@
+
+bin_SCRIPTS = \
+ virt-xml-validate
+
+virt-xml-validate: virt-xml-validate.in Makefile
+ sed -e 's,@SCHEMADIR@,$(pkgdatadir)/schemas,' < $< > $@ || (rm $@ && exit 1)
+ chmod +x $@
+
+man1_MANS = virt-xml-validate.1
+
+CLEANFILES = $(bin_SCRIPTS) $(man1_MANS)
+
+%.1: %
+ pod2man -c "Virtualization Support" -r "$(PACKAGE)-$(VERSION)" $< $@
diff -r f861822d43db tools/virt-xml-validate.in
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/virt-xml-validate.in Thu Apr 16 12:44:17 2009 +0100
@@ -0,0 +1,151 @@
+#!/bin/sh
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+set -e
+
+XMLFILE=$1
+TYPE=$2
+
+if [ -z "$XMLFILE" ]; then
+ echo "syntax: $0 XMLFILE [TYPE]"
+ exit 1
+fi
+
+if [ ! -f "$XMLFILE" ]; then
+ echo "$0: document $XMLFILE does not exist"
+ exit 2
+fi
+
+if [ -z "$TYPE" ]; then
+ ROOT=`xmllint --format $XMLFILE 2>/dev/null| head -2 | tail -1`
+ case $ROOT in
+ *domain*)
+ TYPE="domain"
+ ;;
+ *network*)
+ TYPE="network"
+ ;;
+ *pool*)
+ TYPE="storagepool"
+ ;;
+ *volume*)
+ TYPE="storagevol"
+ ;;
+ *capabilities*)
+ TYPE="capability"
+ ;;
+ *device*)
+ TYPE="nodedev"
+ ;;
+ *)
+ echo "$0: cannot determine schema type for $XMLFILE"
+ exit 3
+ esac
+fi
+
+SCHEMA="@SCHEMADIR(a)/${TYPE}.rng"
+
+if [ ! -f "$SCHEMA" ]; then
+ echo "$0: schema $SCHEMA does not exist"
+ exit 4
+fi
+
+xmllint --noout --relaxng $SCHEMA $XMLFILE
+
+exit 0
+
+: <<=cut
+=pod
+
+=head1 NAME
+
+ virt-xml-validate - validate libvirt XML files against a schema
+
+=head1 SYNOPSIS
+
+ virt-xml-validate XML-FILE [SCHEMA-NAME]
+
+=head1 DESCRIPTION
+
+Validates a libvirt XML for compliance with the published schema.
+The first compulsory argument is the path to the XML file to be
+validated. The optional second argument is the name of the schema
+to validate against. If omitted, the schema name will be inferred
+from the name of the root element in the XML document.
+
+Valid schema names currently include
+
+=over 4
+
+=item C<domain>
+
+The schema for the XML format used by guest domains configuration
+
+=item C<network>
+
+The schema for the XML format used by virtual network configuration
+
+=item C<storagepool>
+
+The schema for the XML format used by storage pool configuration
+
+=item C<storagevol>
+
+The schema for the XML format used by storage volume descriptions
+
+=item C<nodedev>
+
+The schema for the XML format used by node device descriptions
+
+=item C<capability>
+
+The schema for the XML format used to declare driver capabilities
+
+=back
+
+=head1 EXIT STATUS
+
+Upon successful validation, an exit status of 0 will be set. Upon
+failure a non-zero status will be set.
+
+=head1 AUTHOR
+
+Daniel P.Berrange
+
+=head1 BUGS
+
+Report any bugs discovered to the libvirt community via the
+mailing list C<http://libvirt.org/contact.html> or bug tracker C<http://libvirt.org/bugs.html>.
+Alternatively report bugs to your software distributor / vendor.
+
+=head1 COPYRIGHT
+
+Copyright 2009 by Red Hat, Inc
+Copyright 2009 by Daniel P. Berrange
+
+=head1 LICENSE
+
+virt-xml-validate is distributed under the terms of the GNU GPL v2+.
+This is free software; see the source for copying conditions. There
+is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE
+
+=head1 SEE ALSO
+
+C<virsh(1)>, online XML format descriptions C<http://libvirt.org/format.html>
+
+=cut
diff -r f861822d43db virsh.1
--- a/virsh.1 Thu Apr 16 10:34:11 2009 +0100
+++ b/virsh.1 Thu Apr 16 12:44:17 2009 +0100
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32
+.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.07)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -25,11 +25,11 @@
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
-.\" double quote, and \*(R" will give a right double quote. | will give a
-.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
-.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
-.\" expand to `' in nroff, nothing in troff, for use with C<>.
-.tr \(*W-|\(bv\*(Tr
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
@@ -48,22 +48,25 @@
. ds R" ''
'br\}
.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
-.if \nF \{\
+.ie \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
-.\"
-.\" For nroff, turn off justification. Always turn off hyphenation; it makes
-.\" way too many mistakes in technical documents.
-.hy 0
-.if n .na
+.el \{\
+. de IX
+..
+.\}
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
@@ -129,7 +132,11 @@
.\" ========================================================================
.\"
.IX Title "VIRSH 1"
-.TH VIRSH 1 "2008-04-15" "perl v5.8.8" "Virtualization Support"
+.TH VIRSH 1 "2009-04-16" "libvirt-0.6.2" "Virtualization Support"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
.SH "NAME"
virsh \- management user interface
.SH "SYNOPSIS"
@@ -144,7 +151,7 @@ domains. It can also be used to list cur
The basic structure of most virsh usage is:
.PP
.Vb 1
-\& virsh <command> <domain-id> [OPTIONS]
+\& virsh <command> <domain\-id> [OPTIONS]
.Ve
.PP
Where \fIcommand\fR is one of the commands listed below, \fIdomain-id\fR
@@ -222,7 +229,7 @@ this is used to connect to the local Xen
allow to connect locally as root to the daemon supervising QEmu and \s-1KVM\s0 domains
.IP "qemu:///session" 4
.IX Item "qemu:///session"
-allow to connect locally as a normal user to the his own set of QEmu and \s-1KVM\s0 domains
+allow to connect locally as a normal user to his own set of QEmu and \s-1KVM\s0 domains
.RE
.RS 4
.Sp
@@ -261,54 +268,53 @@ An example format for the list is as fol
\&\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
.Sp
.Vb 2
-\& 0 Domain-0 running
+\& 0 Domain\-0 running
\& 2 fedora paused
.Ve
.Sp
Name is the name of the domain. \s-1ID\s0 the domain numeric id.
- State is the run state (see below).
+State is the run state (see below).
+.Sp
+\&\fB\s-1STATES\s0\fR
+.Sp
+The State field lists 6 states for a domain, and which ones the
+current domain is in.
+.RS 4
+.IP "\fBrunning\fR" 4
+.IX Item "running"
+The domain is currently running on a \s-1CPU\s0
+.IP "\fBidle\fR" 4
+.IX Item "idle"
+The domain is idle, and not running or runnable. This can be caused
+because the domain is waiting on \s-1IO\s0 (a traditional wait state) or has
+gone to sleep because there was nothing else for it to do.
+.IP "\fBpaused\fR" 4
+.IX Item "paused"
+The domain has been paused, usually occurring through the administrator
+running \fBvirsh suspend\fR. When in a paused state the domain will still
+consume allocated resources like memory, but will not be eligible for
+scheduling by the hypervisor.
+.IP "\fBshutdown\fR" 4
+.IX Item "shutdown"
+The domain is in the process of shutting down, i.e. the guest operating system
+has been notified and should be in the process of stopping its operations
+gracefully.
+.IP "\fBcrashed\fR" 4
+.IX Item "crashed"
+The domain has crashed, which is always a violent ending. Usually
+this state can only occur if the domain has been configured not to
+restart on crash.
+.IP "\fBdying\fR" 4
+.IX Item "dying"
+The domain is in process of dying, but hasn't completely shutdown or
+crashed.
+.RE
+.RS 4
+.RE
.IP "\fBfreecell\fR optional \fIcellno\fR" 4
.IX Item "freecell optional cellno"
Prints the available amount of memory on the machine or within a
\&\s-1NUMA\s0 cell if \fIcellno\fR is provided.
-.RS 4
-.Sp
-.RS 4
-\&\fB\s-1STATES\s0\fR
-.Sp
-The State field lists 6 states for a Xen Domain, and which ones the
-current Domain is in.
-.RE
-.IP "\fBr \- running\fR" 4
-.IX Item "r - running"
-The domain is currently running on a \s-1CPU\s0
-.IP "\fBb \- blocked\fR" 4
-.IX Item "b - blocked"
-The domain is blocked, and not running or runnable. This can be caused
-because the domain is waiting on \s-1IO\s0 (a traditional wait state) or has
-gone to sleep because there was nothing else for it to do.
-.IP "\fBp \- paused\fR" 4
-.IX Item "p - paused"
-The domain has been paused, usually occurring through the administrator
-running \fBxm pause\fR. When in a paused state the domain will still
-consume allocated resources like memory, but will not be eligible for
-scheduling by the Xen hypervisor.
-.IP "\fBs \- shutdown\fR" 4
-.IX Item "s - shutdown"
-The domain is in the process of shutting down, i.e. the guest operating system
-has been notified and should be in the process of stopping its operations
-gracefully.
-.IP "\fBc \- crashed\fR" 4
-.IX Item "c - crashed"
-The domain has crashed, which is always a violent ending. Usually
-this state can only occur if the domain has been configured not to
-restart on crash. See xmdomain.cfg for more info.
-.IP "\fBd \- dying\fR" 4
-.IX Item "d - dying"
-The domain is in process of dying, but hasn't completely shutdown or
-crashed.
-.RE
-.RS 4
.SH "DOMAIN COMMANDS"
.IX Header "DOMAIN COMMANDS"
The following commands manipulate domains directly, as stated
@@ -324,7 +330,7 @@ The option \fI\-\-disable\fR disable aut
Connect the virtual serial console for the guest.
.IP "\fBcreate\fR \fI\s-1FILE\s0\fR" 4
.IX Item "create FILE"
-Create a domain from an \s-1XML\s0 <file> an easy way to create one if you have a pre-existing xen guest created via \fBxm\fR create <\s-1XMLFILE\s0>.
+Create a domain from an \s-1XML\s0 <file>. An easy way to create the \s-1XML\s0 <file> is to use the \fBdumpxml\fR command to obtain the definition of a pre-existing guest.
.Sp
\&\fBExample\fR
.Sp
@@ -335,7 +341,7 @@ Define a domain from an \s-1XML\s0 <file
but not started.
.IP "\fBdestroy\fR \fIdomain-id\fR" 4
.IX Item "destroy domain-id"
-Immediately terminate the domain domain\-id. This doesn't give the domain
+Immediately terminate the domain domain-id. This doesn't give the domain
\&\s-1OS\s0 any chance to react, and it the equivalent of ripping the power
cord out on a physical machine. In most cases you will want to use
the \fBshutdown\fR command instead.
@@ -369,6 +375,18 @@ Dumps the core of a domain to a file for
.IP "\fBdumpxml\fR \fIdomain-id\fR" 4
.IX Item "dumpxml domain-id"
Output the domain information as an \s-1XML\s0 dump to stdout, this format can be used by the \fBcreate\fR command.
+.IP "\fBedit\fR \fIdomain-id\fR" 4
+.IX Item "edit domain-id"
+Edit the \s-1XML\s0 configuration file for a domain.
+.Sp
+This is equivalent to:
+ virsh dumpxml domain > domain.xml
+ edit domain.xml
+ virsh define domain.xml
+except that it does some error checking.
+.Sp
+The editor used can be supplied by the \f(CW$EDITOR\fR environment
+variable, or if that is not defined defaults to \f(CW\*(C`vi\*(C'\fR.
.IP "\fBmigrate\fR optional \fI\-\-live\fR \fIdomain-id\fR \fIdesturi\fR \fImigrateuri\fR" 4
.IX Item "migrate optional --live domain-id desturi migrateuri"
Migrate domain to another host. Add \-\-live for live migration. The \fIdesturi\fR
@@ -381,9 +399,8 @@ command run from the console. The comma
executed the reboot action, which may be significantly before the
domain actually reboots.
.Sp
-For xen vm the behavior of what happens to a domain when it reboots is set by the
-\&\fIon_reboot\fR parameter of the xmdomain.cfg file when the domain was
-created.
+The exact behavior of a domain when it reboots is set by the
+\&\fIon_reboot\fR parameter in the domain's \s-1XML\s0 definition.
.IP "\fBrestore\fR \fIstate-file\fR" 4
.IX Item "restore state-file"
Restores a domain from an \fBvirsh save\fR state file. See \fIsave\fR for more info.
@@ -397,12 +414,16 @@ other domains to use. \fBvirsh restore\
This is roughly equivalent to doing a hibernate on a running computer,
with all the same limitations. Open network connections may be
severed upon restore, as \s-1TCP\s0 timeouts may have expired.
+.IP "\fBschedinfo\fR optional \fI\-\-set\fR \fBparameter=value\fR \fIdomain-id\fR" 4
+.IX Item "schedinfo optional --set parameter=value domain-id"
+.PD 0
.IP "\fBschedinfo\fR optional \fI\-\-weight\fR \fBnumber\fR optional \fI\-\-cap\fR \fBnumber\fR \fIdomain-id\fR" 4
.IX Item "schedinfo optional --weight number optional --cap number domain-id"
-Allows to show (and set) the domain scheduler parameters. This is currently
-only defined for \s-1XEN_CREDIT\s0 scheduler, and the optional weight and cap
-arguments allows to set the associated parameters in that scheduler if
-provided.
+.PD
+Allows to show (and set) the domain scheduler parameters.
+.Sp
+\&\fBNote\fR: The weight and cap parameters are defined only for the
+\&\s-1XEN_CREDIT\s0 scheduler and are now \fI\s-1DEPRECATED\s0\fR.
.IP "\fBsetmem\fR \fIdomain-id\fR \fBkilobytes\fR" 4
.IX Item "setmem domain-id kilobytes"
Change the current memory allocation in the guest domain. This should take
@@ -431,9 +452,8 @@ to perform graceful shutdown, so there i
succeed, and may take a variable length of time depending on what
services must be shutdown in the domain.
.Sp
-For a xen guest vm the behavior of what happens to a domain when it reboots is set by the
-\&\fIon_shutdown\fR parameter of the xmdomain.cfg file when the domain was
-created.
+The exact behavior of a domain when it shuts down is set by the
+\&\fIon_shutdown\fR parameter in the domain's \s-1XML\s0 definition.
.IP "\fBstart\fR \fIdomain-name\fR" 4
.IX Item "start domain-name"
Start a (previously defined) inactive domain.
@@ -466,10 +486,8 @@ and \fIcpulist\fR is a comma separated l
.IX Item "vncdisplay domain-id"
Output the \s-1IP\s0 address and port number for the \s-1VNC\s0 display. If the information
is not available the processes will provide an exit code of 1.
-.RE
-.RS 4
-.SH "DEVICES COMMANDS"
-.IX Header "DEVICES COMMANDS"
+.SH "DEVICE COMMANDS"
+.IX Header "DEVICE COMMANDS"
The following commands manipulate devices associated to domains.
The domain-id can be specified as an short integer, a name or a full \s-1UUID\s0.
To better understand the values allowed as options for the command
@@ -509,10 +527,8 @@ Detach a network interface from a domain
\&\fItype\fR can be either \fInetwork\fR to indicate a physical network device or \fIbridge\fR to indicate a bridge to a device.
It is recommended to use the \fImac\fR option to distinguish between the interfaces
if more than one are present on the domain.
-.RE
-.RS 4
-.SH "VIRTUAL NETWORKS COMMANDS"
-.IX Header "VIRTUAL NETWORKS COMMANDS"
+.SH "VIRTUAL NETWORK COMMANDS"
+.IX Header "VIRTUAL NETWORK COMMANDS"
The following commands manipulate networks. Libvirt has the capability to
define virtual networks which can then be used by domains and linked to
actual network devices. For more detailed information about this feature
@@ -538,6 +554,18 @@ effect immediately.
.IP "\fBnet-dumpxml\fR \fInetwork\fR" 4
.IX Item "net-dumpxml network"
Output the virtual network information as an \s-1XML\s0 dump to stdout.
+.IP "\fBnet-edit\fR \fInetwork\fR" 4
+.IX Item "net-edit network"
+Edit the \s-1XML\s0 configuration file for a network.
+.Sp
+This is equivalent to:
+ virsh net-dumpxml network > network.xml
+ edit network.xml
+ virsh define network.xml
+except that it does some error checking.
+.Sp
+The editor used can be supplied by the \f(CW$EDITOR\fR environment
+variable, or if that is not defined defaults to \f(CW\*(C`vi\*(C'\fR.
.IP "\fBnet-list\fR optional \fI\-\-inactive\fR or \fI\-\-all\fR" 4
.IX Item "net-list optional --inactive or --all"
Returns the list of active networks, if \fI\-\-all\fR is specified this will also
@@ -555,34 +583,63 @@ Undefine the configuration for an inacti
.IP "\fBnet-uuid\fR \fInetwork-name\fR" 4
.IX Item "net-uuid network-name"
Convert a network name to network \s-1UUID\s0.
-.RE
-.RS 4
.SH "ENVIRONMENT"
.IX Header "ENVIRONMENT"
+The following environment variables can be set to alter the behaviour
+of \f(CW\*(C`virsh\*(C'\fR
.IP "\s-1VIRSH_DEFAULT_CONNECT_URI\s0" 4
.IX Item "VIRSH_DEFAULT_CONNECT_URI"
The hypervisor to connect to by default. Set this to a \s-1URI\s0, in the same
format as accepted by the \fBconnect\fR option.
+.IP "LIBVIRT_DEBUG=LEVEL" 4
+.IX Item "LIBVIRT_DEBUG=LEVEL"
+Turn on verbose debugging of all libvirt \s-1API\s0 calls. Valid levels are
+.RS 4
+.IP "\(bu" 4
+LIBVIRT_DEBUG=1
+.Sp
+Messages at level \s-1DEBUG\s0 or above
+.IP "\(bu" 4
+LIBVIRT_DEBUG=2
+.Sp
+Messages at level \s-1INFO\s0 or above
+.IP "\(bu" 4
+LIBVIRT_DEBUG=3
+.Sp
+Messages at level \s-1WARNING\s0 or above
+.IP "\(bu" 4
+LIBVIRT_DEBUG=4
+.Sp
+Messages at level \s-1ERROR\s0 or above
.RE
.RS 4
-.SH "SEE ALSO"
-.IX Header "SEE ALSO"
-\&\fIxm\fR\|(1), \fIxmdomain.cfg\fR\|(5), \fIxentop\fR\|(1) , <http://www.libvirt.org/>
-.SH "AUTHOR"
-.IX Header "AUTHOR"
+.Sp
+For further information about debugging options consult \f(CW\*(C`http://libvirt.org/logging.html\*(C'\fR
+.RE
+.SH "BUGS"
+.IX Header "BUGS"
+Report any bugs discovered to the libvirt community via the mailing
+list \f(CW\*(C`http://libvirt.org/contact.html\*(C'\fR or bug tracker \f(CW\*(C`http://libvirt.org/bugs.html\*(C'\fR.
+Alternatively report bugs to your software distributor / vendor.
+.SH "AUTHORS"
+.IX Header "AUTHORS"
.Vb 2
\& Andrew Puch <apuch @ redhat.com>
\& Daniel Veillard <veillard @ redhat.com>
-.Ve
-.Sp
-.Vb 3
-\& Based on the xm man paged by
+\&
+\& Based on the xm man page by:
\& Sean Dague <sean at dague dot net>
\& Daniel Stekloff <dsteklof at us dot ibm dot com>
.Ve
-.SH "BUGS"
-.IX Header "BUGS"
-Bugs can be view on the RedHat buzilla page under the libvirt
-<https://bugzilla.redhat.com/>
-.Sp
-<https://bugzilla.redhat.com/bugzilla/buglist.cgi?product=Fedora+Core&comp...>
+.SH "COPYRIGHT"
+.IX Header "COPYRIGHT"
+Copyright (C) 2005, 2007\-2009 Red Hat, Inc.
+.SH "LICENSE"
+.IX Header "LICENSE"
+virsh is distributed under the terms of the \s-1GNU\s0 \s-1LGPL\s0 v2+.
+This is free software; see the source for copying conditions. There
+is \s-1NO\s0 warranty; not even for \s-1MERCHANTABILITY\s0 or \s-1FITNESS\s0 \s-1FOR\s0 A \s-1PARTICULAR\s0
+\&\s-1PURPOSE\s0
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIvirt\-install\fR\|(1), \fIvirt\-xml\-validate\fR\|(1), \fIvirt\-top\fR\|(1), \fIvirt\-mem\fR\|(1), \fIvirt\-df\fR\|(1), <http://www.libvirt.org/>
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 6 months
[libvirt] PATCH: Use virDomainDefPtr to build QEMU args instead of virDomainObjPtr
by Daniel P. Berrange
This is a fairly simple NFC patch which changes the QEMU driver to use
the virDomainDefPtr object when building command line arguments instead
of the virDomainObjPtr. The command line building only needs the config,
and none of the state, so virDomainDefPtr was more applicable.
This was a pre-requisite for another patch I wrote, but have since
thrown away. I think this one is worth applying anyway as a general
cleanup.
Daniel
diff -r bd965abde333 src/qemu_conf.c
--- a/src/qemu_conf.c Tue Apr 14 13:00:20 2009 +0100
+++ b/src/qemu_conf.c Thu Apr 16 10:34:10 2009 +0100
@@ -756,7 +756,7 @@ static int qemudBuildCommandLineChrDevSt
*/
int qemudBuildCommandLine(virConnectPtr conn,
struct qemud_driver *driver,
- virDomainObjPtr vm,
+ virDomainDefPtr def,
unsigned int qemuCmdFlags,
const char ***retargv,
const char ***retenv,
@@ -782,7 +782,7 @@ int qemudBuildCommandLine(virConnectPtr
uname_normalize(&ut);
- virUUIDFormat(vm->def->uuid, uuid);
+ virUUIDFormat(def->uuid, uuid);
/* Migration is very annoying due to wildly varying syntax & capabilities
* over time of KVM / QEMU codebases
@@ -811,9 +811,9 @@ int qemudBuildCommandLine(virConnectPtr
}
}
- emulator = vm->def->emulator;
+ emulator = def->emulator;
if (!emulator)
- emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps);
+ emulator = virDomainDefDefaultEmulator(conn, def, driver->caps);
if (!emulator)
return -1;
@@ -824,8 +824,8 @@ int qemudBuildCommandLine(virConnectPtr
* 3. The qemu binary has the -no-kqemu flag
*/
if ((qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
- STREQ(ut.machine, vm->def->os.arch) &&
- vm->def->virtType == VIR_DOMAIN_VIRT_QEMU)
+ STREQ(ut.machine, def->os.arch) &&
+ def->virtType == VIR_DOMAIN_VIRT_QEMU)
disableKQEMU = 1;
/* Need to explicitly disable KVM if
@@ -834,8 +834,8 @@ int qemudBuildCommandLine(virConnectPtr
* 3. The qemu binary has the -no-kvm flag
*/
if ((qemuCmdFlags & QEMUD_CMD_FLAG_KVM) &&
- STREQ(ut.machine, vm->def->os.arch) &&
- vm->def->virtType == VIR_DOMAIN_VIRT_QEMU)
+ STREQ(ut.machine, def->os.arch) &&
+ def->virtType == VIR_DOMAIN_VIRT_QEMU)
disableKVM = 1;
/*
@@ -850,7 +850,7 @@ int qemudBuildCommandLine(virConnectPtr
* 1. guest OS is i686
* 2. emulator is qemu-system-x86_64
*/
- if (STREQ(vm->def->os.arch, "i686") &&
+ if (STREQ(def->os.arch, "i686") &&
((STREQ(ut.machine, "x86_64") &&
strstr(emulator, "kvm")) ||
strstr(emulator, "x86_64")))
@@ -931,10 +931,10 @@ int qemudBuildCommandLine(virConnectPtr
* is set post-startup using the balloon driver. If balloon driver
* is not supported, then they're out of luck anyway
*/
- snprintf(memory, sizeof(memory), "%lu", vm->def->maxmem/1024);
- snprintf(vcpus, sizeof(vcpus), "%lu", vm->def->vcpus);
- snprintf(domid, sizeof(domid), "%d", vm->def->id);
- pidfile = virFilePid(driver->stateDir, vm->def->name);
+ snprintf(memory, sizeof(memory), "%lu", def->maxmem/1024);
+ snprintf(vcpus, sizeof(vcpus), "%lu", def->vcpus);
+ snprintf(domid, sizeof(domid), "%d", def->id);
+ pidfile = virFilePid(driver->stateDir, def->name);
if (!pidfile)
goto error;
@@ -955,9 +955,9 @@ int qemudBuildCommandLine(virConnectPtr
* a machine in the capabilities data for QEMU. So this
* check is just here as a safety in case the unexpected
* happens */
- if (vm->def->os.machine) {
+ if (def->os.machine) {
ADD_ARG_LIT("-M");
- ADD_ARG_LIT(vm->def->os.machine);
+ ADD_ARG_LIT(def->os.machine);
}
if (cpu) {
ADD_ARG_LIT("-cpu");
@@ -975,7 +975,7 @@ int qemudBuildCommandLine(virConnectPtr
if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
ADD_ARG_LIT("-name");
- ADD_ARG_LIT(vm->def->name);
+ ADD_ARG_LIT(def->name);
}
if (qemuCmdFlags & QEMUD_CMD_FLAG_UUID) {
ADD_ARG_LIT("-uuid");
@@ -993,7 +993,7 @@ int qemudBuildCommandLine(virConnectPtr
* if you ask for nographic. So we have to make sure we override
* these defaults ourselves...
*/
- if (!vm->def->graphics)
+ if (!def->graphics)
ADD_ARG_LIT("-nographic");
ADD_ARG_LIT("-monitor");
@@ -1002,19 +1002,19 @@ int qemudBuildCommandLine(virConnectPtr
ADD_ARG_LIT("-pidfile");
ADD_ARG(pidfile);
- if (vm->def->localtime)
+ if (def->localtime)
ADD_ARG_LIT("-localtime");
if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) &&
- vm->def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
+ def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART)
ADD_ARG_LIT("-no-reboot");
- if (!(vm->def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
+ if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
ADD_ARG_LIT("-no-acpi");
- if (!vm->def->os.bootloader) {
- for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
- switch (vm->def->os.bootDevs[i]) {
+ if (!def->os.bootloader) {
+ for (i = 0 ; i < def->os.nBootDevs ; i++) {
+ switch (def->os.bootDevs[i]) {
case VIR_DOMAIN_BOOT_CDROM:
boot[i] = 'd';
break;
@@ -1032,29 +1032,29 @@ int qemudBuildCommandLine(virConnectPtr
break;
}
}
- boot[vm->def->os.nBootDevs] = '\0';
+ boot[def->os.nBootDevs] = '\0';
ADD_ARG_LIT("-boot");
ADD_ARG_LIT(boot);
- if (vm->def->os.kernel) {
+ if (def->os.kernel) {
ADD_ARG_LIT("-kernel");
- ADD_ARG_LIT(vm->def->os.kernel);
+ ADD_ARG_LIT(def->os.kernel);
}
- if (vm->def->os.initrd) {
+ if (def->os.initrd) {
ADD_ARG_LIT("-initrd");
- ADD_ARG_LIT(vm->def->os.initrd);
+ ADD_ARG_LIT(def->os.initrd);
}
- if (vm->def->os.cmdline) {
+ if (def->os.cmdline) {
ADD_ARG_LIT("-append");
- ADD_ARG_LIT(vm->def->os.cmdline);
+ ADD_ARG_LIT(def->os.cmdline);
}
} else {
ADD_ARG_LIT("-bootloader");
- ADD_ARG_LIT(vm->def->os.bootloader);
+ ADD_ARG_LIT(def->os.bootloader);
}
- for (i = 0 ; i < vm->def->ndisks ; i++) {
- virDomainDiskDefPtr disk = vm->def->disks[i];
+ for (i = 0 ; i < def->ndisks ; i++) {
+ virDomainDiskDefPtr disk = def->disks[i];
if (disk->driverName != NULL &&
!STREQ(disk->driverName, "qemu")) {
@@ -1071,8 +1071,8 @@ int qemudBuildCommandLine(virConnectPtr
/* If QEMU supports boot=on for -drive param... */
if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_BOOT) {
- for (i = 0 ; i < vm->def->os.nBootDevs ; i++) {
- switch (vm->def->os.bootDevs[i]) {
+ for (i = 0 ; i < def->os.nBootDevs ; i++) {
+ switch (def->os.bootDevs[i]) {
case VIR_DOMAIN_BOOT_CDROM:
bootCD = 1;
break;
@@ -1086,11 +1086,11 @@ int qemudBuildCommandLine(virConnectPtr
}
}
- for (i = 0 ; i < vm->def->ndisks ; i++) {
+ for (i = 0 ; i < def->ndisks ; i++) {
virBuffer opt = VIR_BUFFER_INITIALIZER;
char *optstr;
int bootable = 0;
- virDomainDiskDefPtr disk = vm->def->disks[i];
+ virDomainDiskDefPtr disk = def->disks[i];
int idx = virDiskNameToIndex(disk->dst);
const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
@@ -1159,10 +1159,10 @@ int qemudBuildCommandLine(virConnectPtr
ADD_ARG(optstr);
}
} else {
- for (i = 0 ; i < vm->def->ndisks ; i++) {
+ for (i = 0 ; i < def->ndisks ; i++) {
char dev[NAME_MAX];
char file[PATH_MAX];
- virDomainDiskDefPtr disk = vm->def->disks[i];
+ virDomainDiskDefPtr disk = def->disks[i];
if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
@@ -1200,14 +1200,14 @@ int qemudBuildCommandLine(virConnectPtr
}
}
- if (!vm->def->nnets) {
+ if (!def->nnets) {
ADD_ARG_LIT("-net");
ADD_ARG_LIT("none");
} else {
int vlan = 0;
- for (i = 0 ; i < vm->def->nnets ; i++) {
+ for (i = 0 ; i < def->nnets ; i++) {
char nic[100];
- virDomainNetDefPtr net = vm->def->nets[i];
+ virDomainNetDefPtr net = def->nets[i];
if (snprintf(nic, sizeof(nic),
"nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d%s%s",
@@ -1306,13 +1306,13 @@ int qemudBuildCommandLine(virConnectPtr
}
}
- if (!vm->def->nserials) {
+ if (!def->nserials) {
ADD_ARG_LIT("-serial");
ADD_ARG_LIT("none");
} else {
- for (i = 0 ; i < vm->def->nserials ; i++) {
+ for (i = 0 ; i < def->nserials ; i++) {
char buf[4096];
- virDomainChrDefPtr serial = vm->def->serials[i];
+ virDomainChrDefPtr serial = def->serials[i];
if (qemudBuildCommandLineChrDevStr(serial, buf, sizeof(buf)) < 0)
goto error;
@@ -1322,13 +1322,13 @@ int qemudBuildCommandLine(virConnectPtr
}
}
- if (!vm->def->nparallels) {
+ if (!def->nparallels) {
ADD_ARG_LIT("-parallel");
ADD_ARG_LIT("none");
} else {
- for (i = 0 ; i < vm->def->nparallels ; i++) {
+ for (i = 0 ; i < def->nparallels ; i++) {
char buf[4096];
- virDomainChrDefPtr parallel = vm->def->parallels[i];
+ virDomainChrDefPtr parallel = def->parallels[i];
if (qemudBuildCommandLineChrDevStr(parallel, buf, sizeof(buf)) < 0)
goto error;
@@ -1339,8 +1339,8 @@ int qemudBuildCommandLine(virConnectPtr
}
ADD_ARG_LIT("-usb");
- for (i = 0 ; i < vm->def->ninputs ; i++) {
- virDomainInputDefPtr input = vm->def->inputs[i];
+ for (i = 0 ; i < def->ninputs ; i++) {
+ virDomainInputDefPtr input = def->inputs[i];
if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
ADD_ARG_LIT("-usbdevice");
@@ -1348,21 +1348,21 @@ int qemudBuildCommandLine(virConnectPtr
}
}
- if (vm->def->graphics &&
- vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ if (def->graphics &&
+ def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
virBuffer opt = VIR_BUFFER_INITIALIZER;
char *optstr;
if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) {
- if (vm->def->graphics->data.vnc.listenAddr)
- virBufferAdd(&opt, vm->def->graphics->data.vnc.listenAddr, -1);
+ if (def->graphics->data.vnc.listenAddr)
+ virBufferAdd(&opt, def->graphics->data.vnc.listenAddr, -1);
else if (driver->vncListen)
virBufferAdd(&opt, driver->vncListen, -1);
virBufferVSprintf(&opt, ":%d",
- vm->def->graphics->data.vnc.port - 5900);
+ def->graphics->data.vnc.port - 5900);
- if (vm->def->graphics->data.vnc.passwd ||
+ if (def->graphics->data.vnc.passwd ||
driver->vncPassword)
virBufferAddLit(&opt, ",password");
@@ -1387,7 +1387,7 @@ int qemudBuildCommandLine(virConnectPtr
}
} else {
virBufferVSprintf(&opt, "%d",
- vm->def->graphics->data.vnc.port - 5900);
+ def->graphics->data.vnc.port - 5900);
}
if (virBufferError(&opt))
goto no_memory;
@@ -1396,22 +1396,22 @@ int qemudBuildCommandLine(virConnectPtr
ADD_ARG_LIT("-vnc");
ADD_ARG(optstr);
- if (vm->def->graphics->data.vnc.keymap) {
+ if (def->graphics->data.vnc.keymap) {
ADD_ARG_LIT("-k");
- ADD_ARG_LIT(vm->def->graphics->data.vnc.keymap);
+ ADD_ARG_LIT(def->graphics->data.vnc.keymap);
}
- } else if (vm->def->graphics &&
- vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+ } else if (def->graphics &&
+ def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
char *xauth = NULL;
char *display = NULL;
- if (vm->def->graphics->data.sdl.xauth &&
+ if (def->graphics->data.sdl.xauth &&
virAsprintf(&xauth, "XAUTHORITY=%s",
- vm->def->graphics->data.sdl.xauth) < 0)
+ def->graphics->data.sdl.xauth) < 0)
goto no_memory;
- if (vm->def->graphics->data.sdl.display &&
+ if (def->graphics->data.sdl.display &&
virAsprintf(&display, "DISPLAY=%s",
- vm->def->graphics->data.sdl.display) < 0) {
+ def->graphics->data.sdl.display) < 0) {
VIR_FREE(xauth);
goto no_memory;
}
@@ -1420,19 +1420,19 @@ int qemudBuildCommandLine(virConnectPtr
ADD_ENV(xauth);
if (display)
ADD_ENV(display);
- if (vm->def->graphics->data.sdl.fullscreen)
+ if (def->graphics->data.sdl.fullscreen)
ADD_ARG_LIT("-full-screen");
}
/* Add sound hardware */
- if (vm->def->nsounds) {
+ if (def->nsounds) {
int size = 100;
char *modstr;
if (VIR_ALLOC_N(modstr, size+1) < 0)
goto no_memory;
- for (i = 0 ; i < vm->def->nsounds && size > 0 ; i++) {
- virDomainSoundDefPtr sound = vm->def->sounds[i];
+ for (i = 0 ; i < def->nsounds && size > 0 ; i++) {
+ virDomainSoundDefPtr sound = def->sounds[i];
const char *model = virDomainSoundModelTypeToString(sound->model);
if (!model) {
VIR_FREE(modstr);
@@ -1442,7 +1442,7 @@ int qemudBuildCommandLine(virConnectPtr
}
strncat(modstr, model, size);
size -= strlen(model);
- if (i < (vm->def->nsounds - 1))
+ if (i < (def->nsounds - 1))
strncat(modstr, ",", size--);
}
ADD_ARG_LIT("-soundhw");
@@ -1450,11 +1450,11 @@ int qemudBuildCommandLine(virConnectPtr
}
/* Add host passthrough hardware */
- for (i = 0 ; i < vm->def->nhostdevs ; i++) {
+ for (i = 0 ; i < def->nhostdevs ; i++) {
int ret;
char* usbdev;
char* pcidev;
- virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
+ virDomainHostdevDefPtr hostdev = def->hostdevs[i];
/* USB */
if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
diff -r bd965abde333 src/qemu_conf.h
--- a/src/qemu_conf.h Tue Apr 14 13:00:20 2009 +0100
+++ b/src/qemu_conf.h Thu Apr 16 10:34:10 2009 +0100
@@ -124,7 +124,7 @@ int qemudExtractVersionInfo
int qemudBuildCommandLine (virConnectPtr conn,
struct qemud_driver *driver,
- virDomainObjPtr dom,
+ virDomainDefPtr def,
unsigned int qemuCmdFlags,
const char ***retargv,
const char ***retenv,
diff -r bd965abde333 src/qemu_driver.c
--- a/src/qemu_driver.c Tue Apr 14 13:00:20 2009 +0100
+++ b/src/qemu_driver.c Thu Apr 16 10:34:10 2009 +0100
@@ -1390,7 +1390,7 @@ static int qemudStartVMDaemon(virConnect
goto cleanup;
vm->def->id = driver->nextvmid++;
- if (qemudBuildCommandLine(conn, driver, vm,
+ if (qemudBuildCommandLine(conn, driver, vm->def,
qemuCmdFlags, &argv, &progenv,
&tapfds, &ntapfds, migrateFrom) < 0)
goto cleanup;
diff -r bd965abde333 tests/qemuxml2argvtest.c
--- a/tests/qemuxml2argvtest.c Tue Apr 14 13:00:20 2009 +0100
+++ b/tests/qemuxml2argvtest.c Thu Apr 16 10:34:10 2009 +0100
@@ -34,7 +34,6 @@ static int testCompareXMLToArgvFiles(con
const char **tmp = NULL;
int ret = -1, len, flags;
virDomainDefPtr vmdef = NULL;
- virDomainObj vm;
if (virtTestLoadFile(cmd, &expectargv, MAX_FILE) < 0)
goto fail;
@@ -43,20 +42,17 @@ static int testCompareXMLToArgvFiles(con
VIR_DOMAIN_XML_INACTIVE)))
goto fail;
- memset(&vm, 0, sizeof vm);
- vm.def = vmdef;
if (extraFlags & QEMUD_CMD_FLAG_DOMID)
- vm.def->id = 6;
+ vmdef->id = 6;
else
- vm.def->id = -1;
- vm.pid = -1;
+ vmdef->id = -1;
flags = QEMUD_CMD_FLAG_VNC_COLON |
QEMUD_CMD_FLAG_NO_REBOOT |
extraFlags;
if (qemudBuildCommandLine(NULL, &driver,
- &vm, flags, &argv, &qenv,
+ vmdef, flags, &argv, &qenv,
NULL, NULL, migrateFrom) < 0)
goto fail;
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 6 months
[libvirt] PATCH: Fix remote driver create/destroy methods to update ID field
by Daniel P. Berrange
If you have an existing virDomainPtr object, and start it using the
virDomainCreate(virDomainPtr dom) method, then internal cached 'id'
field in the virDomainPtr object is never updated. Even more annoyingly
the remote protocol for the 'create' method doesn't even bother to
return the ID of the newly started guest. Thre is a similar problem
with the virDomainDestroy method, not resetting the cached 'id' back
to -1.
We can't guarentee that the 'id' field is up2date wrt to changes made
by another libvirt client, but we can at least make sure its accurate
wrt to changes this client is making. For the destroy method the fix
is trivial. For the create method, after a successful creation, we do
a lookup based on UUID to fetch the real live ID, since the create
method didn't return it for us.
This fixes a significant number of problems identified by the TCK on
the QEMU driver usage.
Regards,
Daniel
diff -r 9ff786a7908d src/remote_internal.c
--- a/src/remote_internal.c Fri Apr 17 12:05:11 2009 +0100
+++ b/src/remote_internal.c Fri Apr 17 12:06:21 2009 +0100
@@ -1939,6 +1939,7 @@ remoteDomainDestroy (virDomainPtr domain
goto done;
rv = 0;
+ domain->id = -1;
done:
remoteDriverUnlock(priv);
@@ -2735,6 +2736,8 @@ remoteDomainCreate (virDomainPtr domain)
{
int rv = -1;
remote_domain_create_args args;
+ remote_domain_lookup_by_uuid_args args2;
+ remote_domain_lookup_by_uuid_ret ret2;
struct private_data *priv = domain->conn->privateData;
remoteDriverLock(priv);
@@ -2746,6 +2749,16 @@ remoteDomainCreate (virDomainPtr domain)
(xdrproc_t) xdr_void, (char *) NULL) == -1)
goto done;
+ memcpy (args2.uuid, domain->uuid, VIR_UUID_BUFLEN);
+ memset (&ret2, 0, sizeof ret2);
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID,
+ (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args, (char *) &args2,
+ (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret2) == -1)
+ goto done;
+
+ domain->id = ret2.dom.id;
+ xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret2);
+
rv = 0;
done:
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 6 months
[libvirt] PATCH: Improve error reporting for operations on inactive domains
by Daniel P. Berrange
If you try todo an operation on an inactive QEMU guest which is not
applicable, eg ask to pause an inactive guest, then you currently get
a useless message
# virsh suspend demo
error: Failed to suspend domain demo
error: invalid domain pointer in no domain with matching id -1
There are two issues here
- The QEMU driver is mistakenly doing a lookup-by-id when locating the
guest in question. It should in fact do lookup-by-uuid for all APIs
since that's the best unique identifier.
- It was using VIR_ERR_INVALID_DOMAIN code instead of VIR_ERR_NO_DOMAIN
code, hence the 'invalid domain pointer' bogus message.
This patch changes all QEMU APIs to lookup based on UUID, and use the
correct VIR_ERR_NO_DOMAIN code when reporting failures.
You now get to see the real useful error message later in the API where
it validates whether the guest is running or not
# virsh suspend demo
error: Failed to suspend domain demo
error: operation failed: domain is not running
One thing I'm wondering, is whether we should introduce an explicit error
code for operations that are not applicable.
eg, instead of giving VIR_ERR_OPERATION_FAILED, we could give back a code
like VIR_ERR_OPERATION_INVALID. This would let callers distinguish
real failure of the operation, vs the fact that it simply isn't applicable
for inactive guests.
Daniel
diff -r 5b88ef324d90 src/qemu_driver.c
--- a/src/qemu_driver.c Fri Apr 17 12:06:21 2009 +0100
+++ b/src/qemu_driver.c Fri Apr 17 12:32:54 2009 +0100
@@ -1984,7 +1984,8 @@ static virDomainPtr qemudDomainLookupByI
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching id %d"), id);
goto cleanup;
}
@@ -2008,7 +2009,10 @@ static virDomainPtr qemudDomainLookupByU
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuid);
goto cleanup;
}
@@ -2032,7 +2036,8 @@ static virDomainPtr qemudDomainLookupByN
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching name '%s'"), name);
goto cleanup;
}
@@ -2182,11 +2187,14 @@ static int qemudDomainSuspend(virDomainP
virDomainEventPtr event = NULL;
qemuDriverLock(driver);
- vm = virDomainFindByID(&driver->domains, dom->id);
- qemuDriverUnlock(driver);
-
- if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemuDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
if (!virDomainIsActive(vm)) {
@@ -2232,12 +2240,14 @@ static int qemudDomainResume(virDomainPt
virDomainEventPtr event = NULL;
qemuDriverLock(driver);
- vm = virDomainFindByID(&driver->domains, dom->id);
- qemuDriverUnlock(driver);
-
- if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id %d"), dom->id);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemuDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
if (!virDomainIsActive(vm)) {
@@ -2281,12 +2291,14 @@ static int qemudDomainShutdown(virDomain
int ret = -1;
qemuDriverLock(driver);
- vm = virDomainFindByID(&driver->domains, dom->id);
- qemuDriverUnlock(driver);
-
- if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id %d"), dom->id);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemuDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -2312,10 +2324,12 @@ static int qemudDomainDestroy(virDomainP
virDomainEventPtr event = NULL;
qemuDriverLock(driver);
- vm = virDomainFindByID(&driver->domains, dom->id);
- if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id %d"), dom->id);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -2349,8 +2363,10 @@ static char *qemudDomainGetOSType(virDom
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -2375,9 +2391,8 @@ static unsigned long qemudDomainGetMaxMe
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
-
- virUUIDFormat(dom->uuid, uuidstr);
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -2401,9 +2416,8 @@ static int qemudDomainSetMaxMemory(virDo
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
-
- virUUIDFormat(dom->uuid, uuidstr);
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -2525,9 +2539,8 @@ static int qemudDomainSetMemory(virDomai
qemuDriverUnlock(driver);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
-
- virUUIDFormat(dom->uuid, uuidstr);
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -2566,8 +2579,10 @@ static int qemudDomainGetInfo(virDomainP
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -2713,11 +2728,13 @@ static int qemudDomainSave(virDomainPtr
header.version = QEMUD_SAVE_VERSION;
qemuDriverLock(driver);
- vm = virDomainFindByID(&driver->domains, dom->id);
-
- if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id %d"), dom->id);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -2850,9 +2867,8 @@ static int qemudDomainSetVcpus(virDomain
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
-
- virUUIDFormat(dom->uuid, uuidstr);
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -3045,9 +3061,8 @@ static int qemudDomainGetMaxVcpus(virDom
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
-
- virUUIDFormat(dom->uuid, uuidstr);
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -3080,9 +3095,8 @@ static int qemudDomainGetSecurityLabel(v
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
-
- virUUIDFormat(dom->uuid, uuidstr);
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -3294,8 +3308,10 @@ static char *qemudDomainDumpXML(virDomai
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -3496,8 +3512,10 @@ static int qemudDomainStart(virDomainPtr
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -3586,8 +3604,10 @@ static int qemudDomainUndefine(virDomain
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -3979,9 +3999,11 @@ static int qemudDomainAttachDevice(virDo
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) {
- qemuDriverUnlock(driver);
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ qemuDriverUnlock(driver);
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -4129,9 +4151,11 @@ static int qemudDomainDetachDevice(virDo
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) {
- qemuDriverUnlock(driver);
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ qemuDriverUnlock(driver);
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -4182,8 +4206,10 @@ static int qemudDomainGetAutostart(virDo
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -4208,8 +4234,10 @@ static int qemudDomainSetAutostart(virDo
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -4283,11 +4311,13 @@ qemudDomainBlockStats (virDomainPtr dom,
virDomainDiskDefPtr disk = NULL;
qemuDriverLock(driver);
- vm = virDomainFindByID(&driver->domains, dom->id);
- qemuDriverUnlock(driver);
- if (!vm) {
- qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id %d"), dom->id);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemuDriverUnlock(driver);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
if (!virDomainIsActive (vm)) {
@@ -4418,12 +4448,14 @@ qemudDomainInterfaceStats (virDomainPtr
int ret = -1;
qemuDriverLock(driver);
- vm = virDomainFindByID(&driver->domains, dom->id);
- qemuDriverUnlock(driver);
-
- if (!vm) {
- qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id %d"), dom->id);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemuDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -4486,8 +4518,10 @@ qemudDomainBlockPeek (virDomainPtr dom,
qemuDriverUnlock(driver);
if (!vm) {
- qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- "%s", _("no domain with matching uuid"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -4554,12 +4588,14 @@ qemudDomainMemoryPeek (virDomainPtr dom,
int fd = -1, ret = -1;
qemuDriverLock(driver);
- vm = virDomainFindByID(&driver->domains, dom->id);
- qemuDriverUnlock(driver);
-
- if (!vm) {
- qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id %d"), dom->id);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemuDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -4887,10 +4923,12 @@ qemudDomainMigratePerform (virDomainPtr
int paused = 0;
qemuDriverLock(driver);
- vm = virDomainFindByID(&driver->domains, dom->id);
- if (!vm) {
- qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id %d"), dom->id);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
@@ -5018,8 +5056,8 @@ qemudDomainMigrateFinish2 (virConnectPtr
qemuDriverLock(driver);
vm = virDomainFindByName(&driver->domains, dname);
if (!vm) {
- qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching name %s"), dname);
+ qemudReportError (dconn, NULL, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching name '%s'"), dname);
goto cleanup;
}
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 6 months
[libvirt] [PATCH 1/1] lxc: only do CLONE_NEWUSER when kernel supports it
by Serge E. Hallyn
I was trying to get the lxc driver to work on ubuntu jaunty. This
patch gets me further than I was getting before. Like I say below,
it's probably not the right way though.
-serge
>From 2513f8a7e0654e84570fe0ef2204dabe276b9e4e Mon Sep 17 00:00:00 2001
From: root <root(a)jaunty.(none)>
Date: Fri, 17 Apr 2009 16:41:01 -0500
Subject: [PATCH 1/1] lxc: only do CLONE_NEWUSER when kernel supports it
The ubuntu jaunty kernel is not compiled with USER_NS. Since
libvirt-lxc always does clone(CLONE_NEWUSER) it gets -EINVAL
and mysteriously claims to be unable to contact hypervisor.
This patch isn't the right thing to do, but I'm not sure what
is. User namespaces do (since recently) isolate the in-kernel
keyring. So the right thing might be to add a flag to the
xml definition file to specify whether to use a user namespace.
This patch doesn't do that, rather it always does CLONE_NEWUSER
if the kernel supports it, and never if not.
Signed-off-by: Serge Hallyn <serue(a)us.ibm.com>
---
src/lxc_container.c | 15 +++++++++++++--
src/lxc_container.h | 1 +
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/lxc_container.c b/src/lxc_container.c
index 67c66bd..8069af7 100644
--- a/src/lxc_container.c
+++ b/src/lxc_container.c
@@ -666,6 +666,11 @@ static int lxcContainerChild( void *data )
return lxcContainerExecInit(vmDef);
}
+int userns_supported(void)
+{
+ return lxcContainerAvailable(LXC_CONTAINER_FEATURE_USER) == 0;
+}
+
/**
* lxcContainerStart:
* @driver: pointer to driver structure
@@ -694,7 +699,10 @@ int lxcContainerStart(virDomainDefPtr def,
}
stacktop = stack + stacksize;
- flags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWUSER|CLONE_NEWIPC|SIGCHLD;
+ flags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|SIGCHLD;
+
+ if (userns_supported())
+ flags |= CLONE_NEWUSER;
if (def->nets != NULL)
flags |= CLONE_NEWNET;
@@ -719,13 +727,16 @@ static int lxcContainerDummyChild(void *argv ATTRIBUTE_UNUSED)
int lxcContainerAvailable(int features)
{
- int flags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWUSER|
+ int flags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|
CLONE_NEWIPC|SIGCHLD;
int cpid;
char *childStack;
char *stack;
int childStatus;
+ if (features & LXC_CONTAINER_FEATURE_USER)
+ flags |= CLONE_NEWUSER;
+
if (features & LXC_CONTAINER_FEATURE_NET)
flags |= CLONE_NEWNET;
diff --git a/src/lxc_container.h b/src/lxc_container.h
index 5d037b0..b99e83e 100644
--- a/src/lxc_container.h
+++ b/src/lxc_container.h
@@ -28,6 +28,7 @@
enum {
LXC_CONTAINER_FEATURE_NET = (1 << 0),
+ LXC_CONTAINER_FEATURE_USER = (1 << 1),
};
#define LXC_DEV_MAJ_MEMORY 1
--
1.6.0.4
15 years, 6 months
[libvirt] [PATCH] Fix typo in manpage
by Mark McLoughlin
Hey,
Just committed this simple patch.
Cheers,
Mark.
Subject: [PATCH] Fix typo in manpage
It's "service libvirtd start", not "service start libvirtd".
Reported-by: Robert P. J. Day <rpjday(a)crashcourse.ca>
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
---
docs/virsh.pod | 2 +-
virsh.1 | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/virsh.pod b/docs/virsh.pod
index 2438984..6434d78 100644
--- a/docs/virsh.pod
+++ b/docs/virsh.pod
@@ -34,7 +34,7 @@ the program.
All B<virsh> operations rely upon the libvirt library.
For any virsh commands to run xend/qemu, or what ever virtual library that libvirt supports. For this reason you should start xend/qemu as a service when your system first boots using xen/qemu. This can usually be done using the command
-B<service start libvirtd> .
+B<service libvirtd start> .
Most B<virsh> commands require root privileges to run due to the
communications channels used to talk to the hypervisor. Running as
diff --git a/virsh.1 b/virsh.1
index 2197c20..45ea614 100644
--- a/virsh.1
+++ b/virsh.1
@@ -171,7 +171,7 @@ the program.
.IX Header "NOTES"
All \fBvirsh\fR operations rely upon the libvirt library.
For any virsh commands to run xend/qemu, or what ever virtual library that libvirt supports. For this reason you should start xend/qemu as a service when your system first boots using xen/qemu. This can usually be done using the command
-\&\fBservice start libvirtd\fR .
+\&\fBservice libvirtd start\fR .
.PP
Most \fBvirsh\fR commands require root privileges to run due to the
communications channels used to talk to the hypervisor. Running as
--
1.6.0.6
15 years, 6 months
[libvirt] [PATCH] src/bridge.c compile error
by Anton Protopopov
Hi.
The absense of SIOCBRADDBR causes compile error:
> bridge.c:143: error: conflicting types for 'brAddBridge'
> bridge.h:50: error: previous declaration of 'brAddBridge' was here
See attached patch for fix.
By the way, what functionality do one loose if his system isn't supporting
SIOCBRADDBR?
15 years, 6 months