[libvirt] [PATCH v2] graphics: add support for action_if_connected in qemu
by Michal Privoznik
This option accepts 3 values:
-keep, to keep current client connected (Spice+VNC)
-disconnect, to disconnect client (Spice)
-fail, to fail setting password if there is a client connected (Spice)
---
diff to v1:
-doc added
docs/formatdomain.html.in | 13 +++++++++++--
docs/schemas/domain.rng | 16 ++++++++++++++++
src/conf/domain_conf.c | 44 +++++++++++++++++++++++++++++++++++++++++---
src/conf/domain_conf.h | 11 +++++++++++
src/libvirt_private.syms | 2 ++
src/qemu/qemu_hotplug.c | 11 ++++++++---
6 files changed, 89 insertions(+), 8 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index f8baffd..25e97a5 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1762,7 +1762,11 @@ qemu-kvm -net nic,model=? /dev/null
in clear text. The <code>keymap</code> attribute specifies the keymap
to use. It is possible to set a limit on the validity of the password
be giving an timestamp <code>passwdValidTo='2010-04-09T15:51:00'</code>
- assumed to be in UTC. NB, this may not be supported by all hypervisors.<br/>
+ assumed to be in UTC. <span class="since">Since 0.8.6</span>
+ The <code>connected</code> attribute allows control of connected client
+ during password changes. VNC accepts <code>keep</code> value only.
+ <span class="since">since 0.9.2</span>
+ NB, this may not be supported by all hypervisors.<br/>
<br/>
Rather than using listen/port, QEMU supports a <code>socket</code>
attribute for listening on a unix domain socket path.
@@ -1781,7 +1785,12 @@ qemu-kvm -net nic,model=? /dev/null
in clear text. The <code>keymap</code> attribute specifies the keymap
to use. It is possible to set a limit on the validity of the password
be giving an timestamp <code>passwdValidTo='2010-04-09T15:51:00'</code>
- assumed to be in UTC. NB, this may not be supported by all hypervisors.
+ assumed to be in UTC.<span class="since">Since 0.8.6</span>
+ The <code>connected</code> attribute allows control of connected client
+ during password changes. SPICE accepts <code>keep</code> to keep client
+ connected, <code>disconnect</code> to disconnect client and
+ <code>fail</code> to fail changing password. <span class="since">Since 0.9.2</span>
+ NB, this may not be supported by all hypervisors.
<span class="since">"spice" since 0.8.6</span>.
</p>
<p>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index c270815..f0efe60 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1227,6 +1227,13 @@
<data type="dateTime"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="connected">
+ <choice>
+ <value>keep</value>
+ </choice>
+ </attribute>
+ </optional>
</group>
<group>
<attribute name="type">
@@ -1270,6 +1277,15 @@
<data type="dateTime"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="connected">
+ <choice>
+ <value>fail</value>
+ <value>disconnect</value>
+ <value>keep</value>
+ </choice>
+ </attribute>
+ </optional>
<interleave>
<zeroOrMore>
<element name="channel">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index fbef61e..571fcf4 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -313,6 +313,13 @@ VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST,
"desktop",
"spice")
+VIR_ENUM_IMPL(virDomainGraphicsAuthConnected,
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_LAST,
+ "default",
+ "fail",
+ "disconnect",
+ "keep")
+
VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelName,
VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST,
"main",
@@ -3803,9 +3810,12 @@ error:
static int
-virDomainGraphicsAuthDefParseXML(xmlNodePtr node, virDomainGraphicsAuthDefPtr def)
+virDomainGraphicsAuthDefParseXML(xmlNodePtr node,
+ virDomainGraphicsAuthDefPtr def,
+ int type)
{
char *validTo = NULL;
+ char *connected = virXMLPropString(node, "connected");
def->passwd = virXMLPropString(node, "passwd");
@@ -3846,6 +3856,28 @@ virDomainGraphicsAuthDefParseXML(xmlNodePtr node, virDomainGraphicsAuthDefPtr de
def->expires = 1;
}
+ if (connected) {
+ int action = virDomainGraphicsAuthConnectedTypeFromString(connected);
+ if (action < 0) {
+ virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown connected value %s"),
+ connected);
+ VIR_FREE(connected);
+ return -1;
+ }
+ VIR_FREE(connected);
+
+ /* VNC supports connected='keep' only */
+ if (type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+ action != VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP) {
+ virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("VNC supports connected='keep' only"));
+ return -1;
+ }
+
+ def->connected = action;
+ }
+
return 0;
}
@@ -3915,7 +3947,8 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) {
!def->data.vnc.listenAddr[0])
VIR_FREE(def->data.vnc.listenAddr);
- if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth) < 0)
+ if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth,
+ def->type) < 0)
goto error;
} else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
char *fullscreen = virXMLPropString(node, "fullscreen");
@@ -4051,7 +4084,8 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) {
!def->data.spice.listenAddr[0])
VIR_FREE(def->data.spice.listenAddr);
- if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth) < 0)
+ if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth,
+ def->type) < 0)
goto error;
cur = node->children;
@@ -7995,6 +8029,10 @@ virDomainGraphicsAuthDefFormatAttr(virBufferPtr buf,
strftime(strbuf, sizeof(strbuf), "%Y-%m-%dT%H:%M:%S", tm);
virBufferAsprintf(buf, " passwdValidTo='%s'", strbuf);
}
+
+ if (def->connected)
+ virBufferEscapeString(buf, " connected='%s'",
+ virDomainGraphicsAuthConnectedTypeToString(def->connected));
}
static int
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8c94d4d..d090b9a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -631,12 +631,22 @@ enum virDomainGraphicsType {
VIR_DOMAIN_GRAPHICS_TYPE_LAST,
};
+enum virDomainGraphicsAuthConnectedType {
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_DEFAULT = 0,
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_FAIL,
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_DISCONNECT,
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP,
+
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_LAST
+};
+
typedef struct _virDomainGraphicsAuthDef virDomainGraphicsAuthDef;
typedef virDomainGraphicsAuthDef *virDomainGraphicsAuthDefPtr;
struct _virDomainGraphicsAuthDef {
char *passwd;
unsigned int expires: 1; /* Whether there is an expiry time set */
time_t validTo; /* seconds since epoch */
+ int connected; /* action if connected */
};
enum virDomainGraphicsSpiceChannelName {
@@ -1514,6 +1524,7 @@ VIR_ENUM_DECL(virDomainHostdevSubsys)
VIR_ENUM_DECL(virDomainInput)
VIR_ENUM_DECL(virDomainInputBus)
VIR_ENUM_DECL(virDomainGraphics)
+VIR_ENUM_DECL(virDomainGraphicsAuthConnected)
VIR_ENUM_DECL(virDomainGraphicsSpiceChannelName)
VIR_ENUM_DECL(virDomainGraphicsSpiceChannelMode)
VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 321df2a..bb331a3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -263,6 +263,8 @@ virDomainFindByID;
virDomainFindByName;
virDomainFindByUUID;
virDomainGetRootFilesystem;
+virDomainGraphicsAuthConnectedTypeFromString;
+virDomainGraphicsAuthConnectedTypeToString;
virDomainGraphicsDefFree;
virDomainGraphicsSpiceChannelModeTypeFromString;
virDomainGraphicsSpiceChannelModeTypeToString;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 3cf7d35..c0c4a15 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1017,10 +1017,12 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
return -1;
}
- /* If a password lifetime was, or is set, then we must always run,
- * even if new password matches old password */
+ /* If a password lifetime was, or is set, or action if connected has
+ * changed, then we must always run, even if new password matches
+ * old password */
if (olddev->data.vnc.auth.expires ||
dev->data.vnc.auth.expires ||
+ olddev->data.vnc.auth.connected != dev->data.vnc.auth.connected ||
STRNEQ_NULLABLE(olddev->data.vnc.auth.passwd, dev->data.vnc.auth.passwd)) {
VIR_DEBUG("Updating password on VNC server %p %p", dev->data.vnc.auth.passwd, driver->vncPassword);
ret = qemuDomainChangeGraphicsPasswords(driver, vm, VIR_DOMAIN_GRAPHICS_TYPE_VNC,
@@ -1032,6 +1034,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
dev->data.vnc.auth.passwd = NULL;
olddev->data.vnc.auth.validTo = dev->data.vnc.auth.validTo;
olddev->data.vnc.auth.expires = dev->data.vnc.auth.expires;
+ olddev->data.vnc.auth.connected = dev->data.vnc.auth.connected;
} else {
ret = 0;
}
@@ -1060,6 +1063,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
* even if new password matches old password */
if (olddev->data.spice.auth.expires ||
dev->data.spice.auth.expires ||
+ olddev->data.spice.auth.connected != dev->data.spice.auth.connected ||
STRNEQ_NULLABLE(olddev->data.spice.auth.passwd, dev->data.spice.auth.passwd)) {
VIR_DEBUG("Updating password on SPICE server %p %p", dev->data.spice.auth.passwd, driver->spicePassword);
ret = qemuDomainChangeGraphicsPasswords(driver, vm, VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
@@ -1071,6 +1075,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
dev->data.spice.auth.passwd = NULL;
olddev->data.spice.auth.validTo = dev->data.spice.auth.validTo;
olddev->data.spice.auth.expires = dev->data.spice.auth.expires;
+ olddev->data.spice.auth.connected = dev->data.spice.auth.connected;
} else {
VIR_DEBUG("Not updating since password didn't change");
ret = 0;
@@ -1755,7 +1760,7 @@ qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver,
ret = qemuMonitorSetPassword(priv->mon,
type,
auth->passwd ? auth->passwd : defaultPasswd,
- NULL);
+ auth->connected ? virDomainGraphicsAuthConnectedTypeToString(auth->connected) : NULL);
if (ret == -2) {
if (type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
--
1.7.5.rc3
13 years, 6 months
[libvirt] [PATCH] Fix virTypedParameter alias comments
by Matthias Bolte
Remove the Domain prefix from the comments.
---
include/libvirt/libvirt.h.in | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index cbd8dbb..8058229 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2538,7 +2538,7 @@ int virDomainInjectNMI(virDomainPtr domain, unsigned int flags);
/**
- * virDomainSchedParameterType:
+ * virSchedParameterType:
*
* A scheduler parameter field type. Provided for backwards
* compatibility; virTypedParameterType is the preferred enum since
@@ -2563,9 +2563,9 @@ typedef enum {
#define VIR_DOMAIN_SCHED_FIELD_LENGTH VIR_TYPED_PARAM_FIELD_LENGTH
/**
- * virDomainSchedParameter:
+ * virSchedParameter:
*
- * a virDomainSchedParameter is the set of scheduler parameters.
+ * a virSchedParameter is the set of scheduler parameters.
* Provided for backwards compatibility; virTypedParameter is the
* preferred alias since 0.9.2.
*/
@@ -2582,7 +2582,7 @@ typedef struct _virTypedParameter virSchedParameter;
typedef virSchedParameter *virSchedParameterPtr;
/**
- * virDomainBlkioParameterType:
+ * virBlkioParameterType:
*
* A blkio parameter field type. Provided for backwards
* compatibility; virTypedParameterType is the preferred enum since
@@ -2607,9 +2607,9 @@ typedef enum {
#define VIR_DOMAIN_BLKIO_FIELD_LENGTH VIR_TYPED_PARAM_FIELD_LENGTH
/**
- * virDomainBlkioParameter:
+ * virBlkioParameter:
*
- * a virDomainBlkioParameter is the set of blkio parameters.
+ * a virBlkioParameter is the set of blkio parameters.
* Provided for backwards compatibility; virTypedParameter is the
* preferred alias since 0.9.2.
*/
@@ -2626,7 +2626,7 @@ typedef struct _virTypedParameter virBlkioParameter;
typedef virBlkioParameter *virBlkioParameterPtr;
/**
- * virDomainMemoryParameterType:
+ * virMemoryParameterType:
*
* A memory parameter field type. Provided for backwards
* compatibility; virTypedParameterType is the preferred enum since
@@ -2651,9 +2651,9 @@ typedef enum {
#define VIR_DOMAIN_MEMORY_FIELD_LENGTH VIR_TYPED_PARAM_FIELD_LENGTH
/**
- * virDomainMemoryParameter:
+ * virMemoryParameter:
*
- * a virDomainMemoryParameter is the set of scheduler parameters.
+ * a virMemoryParameter is the set of scheduler parameters.
* Provided for backwards compatibility; virTypedParameter is the
* preferred alias since 0.9.2.
*/
--
1.7.0.4
13 years, 6 months
[libvirt] [PATCH] openvz: Automatically disable on non-Linux systems
by Matthias Bolte
As OpenVZ is Linux specific.
---
configure.ac | 20 +++++++++++++++++++-
1 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/configure.ac b/configure.ac
index 55ae791..b2ba930 100644
--- a/configure.ac
+++ b/configure.ac
@@ -255,7 +255,7 @@ AC_ARG_WITH([qemu],
AC_ARG_WITH([uml],
AC_HELP_STRING([--with-uml], [add UML support @<:@default=check@:>@]),[],[with_uml=check])
AC_ARG_WITH([openvz],
- AC_HELP_STRING([--with-openvz], [add OpenVZ support @<:@default=yes@:>@]),[],[with_openvz=yes])
+ AC_HELP_STRING([--with-openvz], [add OpenVZ support @<:@default=check@:>@]),[],[with_openvz=check])
AC_ARG_WITH([vmware],
AC_HELP_STRING([--with-vmware], [add VMware support @<:@default=yes@:>@]),[],[with_vmware=yes])
AC_ARG_WITH([libssh2],
@@ -348,16 +348,34 @@ AC_PATH_PROG([EBTABLES_PATH], [ebtables], /sbin/ebtables, [/usr/sbin:$PATH])
AC_DEFINE_UNQUOTED([EBTABLES_PATH], "$EBTABLES_PATH", [path to ebtables binary])
+dnl
+dnl Checks for the OpenVZ driver
+dnl
+
+if test "$with_openvz" = "check"; then
+ with_openvz=$with_linux
+fi
+
+if test "$with_openvz" = "yes" && test "$with_linux" = "no"; then
+ AC_MSG_ERROR([The OpenVZ driver can be enabled on Linux only.])
+fi
+
if test "$with_openvz" = "yes"; then
AC_DEFINE_UNQUOTED([WITH_OPENVZ], 1, [whether OpenVZ driver is enabled])
fi
AM_CONDITIONAL([WITH_OPENVZ], [test "$with_openvz" = "yes"])
+
+dnl
+dnl Checks for the VMware Workstation/Player driver
+dnl
+
if test "$with_vmware" = "yes"; then
AC_DEFINE_UNQUOTED([WITH_VMWARE], 1, [whether VMware driver is enabled])
fi
AM_CONDITIONAL([WITH_VMWARE], [test "$with_vmware" = "yes"])
+
dnl
dnl check for XDR
dnl
--
1.7.0.4
13 years, 6 months
[libvirt] ssh from host to guest on default network
by Kay Williams
Hello,
I am looking for an reliable, scriptable method to 1) install a kvm guest using the default network and 2) ssh from the host to the guest to perform machine maintenance (e.g. yum update).
Ideally, this would be done by providing a host name for the guest during install (e.g. virt-install --name <myname> ...), and then by ssh'ing to the machine using the provided hostname (e.g. ssh <myname>) and a username/password or preconfigured certificate.
The trouble I am having is with ssh'ing from the host to guest machine.
1. I can't (easily) use the guest hostname, as the host isn't automatically configured to resolve guest names.
2. I can't (easily) use the guest IP address (e.g. read from /var/lib/libvirt/dnsmasq/default.leases), as the IP addresses are dynamic and can change when the guest is reinstalled (which I am doing a fair amount, at least in testing).
3. I can't (easily) assign the guest a static IP address, as the default network configuration assumes all IP addresses in the range can be dynamically allocated, and thus a statically assigned IP might conflict.
I can work around these issues in a variety of unfortunate ways. But I wonder if there is something elegant I am missing.
If not, this would be a very nice feature for the future....
Thanks,
Kay
13 years, 6 months
[libvirt] [PATCH] Add support for 'passthru' mode for direct network interfaces
by D. Herrendoerfer
Hi all,
starting with kernel 2.6.38 macvtap supports a 'passthru' mode for
attaching virtual functions
of a SRIOV capable network card directly to a VM.
This patch adds the capability to configure such a device.
Signed-off-by: Dirk Herrendoerfer <d.herrendoerfer at
herrendoerfer.name>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 7163c6e..e2a66ae 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -2351,7 +2351,7 @@
</define>
<define name="bridgeMode">
<data type="string">
- <param name="pattern">(vepa|bridge|private)</param>
+ <param name="pattern">(vepa|bridge|private|passthru)</param>
</data>
</define>
<define name="addrMAC">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6b733d4..104d50d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -376,7 +376,8 @@ VIR_ENUM_IMPL(virDomainSeclabel,
VIR_DOMAIN_SECLABEL_LAST,
VIR_ENUM_IMPL(virDomainNetdevMacvtap,
VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST,
"vepa",
"private",
- "bridge")
+ "bridge",
+ "passthru" )
VIR_ENUM_IMPL(virVirtualPort, VIR_VIRTUALPORT_TYPE_LAST,
"none",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 6ea30b9..5833d72 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -335,6 +335,7 @@ enum virDomainNetdevMacvtapType {
VIR_DOMAIN_NETDEV_MACVTAP_MODE_VEPA,
VIR_DOMAIN_NETDEV_MACVTAP_MODE_PRIVATE,
VIR_DOMAIN_NETDEV_MACVTAP_MODE_BRIDGE,
+ VIR_DOMAIN_NETDEV_MACVTAP_MODE_PASSTHRU,
VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST,
};
diff --git a/src/util/macvtap.c b/src/util/macvtap.c
index a7af0cb..1b274cc 100644
--- a/src/util/macvtap.c
+++ b/src/util/macvtap.c
@@ -473,6 +473,9 @@ macvtapModeFromInt(enum virDomainNetdevMacvtapType
mode)
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_BRIDGE:
return MACVLAN_MODE_BRIDGE;
+ case VIR_DOMAIN_NETDEV_MACVTAP_MODE_PASSTHRU:
+ return MACVLAN_MODE_PASSTHRU;
+
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_VEPA:
default:
return MACVLAN_MODE_VEPA;
@@ -546,7 +549,7 @@ configMacvtapTap(int tapfd, int vnet_hdr)
* be NULL if this function is supposed to choose a name
* @macaddress: The MAC address for the macvtap device
* @linkdev: The interface name of the NIC to connect to the
external bridge
- * @mode: int describing the mode for 'bridge', 'vepa' or 'private'.
+ * @mode: int describing the mode for 'bridge', 'vepa', 'private' or
'passthru'.
* @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
* @vmuuid: The UUID of the VM the macvtap belongs to
* @virtPortProfile: pointer to object holding the virtual port
profile data
diff --git a/src/util/macvtap.h b/src/util/macvtap.h
index 54205c7..c45dd13 100644
--- a/src/util/macvtap.h
+++ b/src/util/macvtap.h
@@ -92,6 +92,7 @@ void delMacvtap(const char *ifname,
# define MACVTAP_MODE_PRIVATE_STR "private"
# define MACVTAP_MODE_VEPA_STR "vepa"
# define MACVTAP_MODE_BRIDGE_STR "bridge"
+# define MACVTAP_MODE_PASSTHRU_STR "passthru"
int vpAssociatePortProfileId(const char *macvtap_ifname,
const unsigned char *macvtap_macaddr,
13 years, 6 months
[libvirt] [PATCH RFC] Add domainSave/Restore to libxl driver
by Markus Groß
This patch adds save/restore functionality to the libxl driver.
It is a v2 of this patch:
https://www.redhat.com/archives/libvir-list/2011-April/msg00338.html
v2:
* header is now padded and has a version field
* the correct restore function from libxl is used
* only create the restore event once in libxlVmStart
However I ran into a reproducible segfault.
Assume you saved a vm with:
# virsh save domU foo.img
If you restore the save image,
destroy the vm and restore it again, a segfault occurs:
# virsh restore foo.img
# virsh destroy domU
# virsh restore foo.img
# segfault
If you restart libvirt between the restores no segfault occurs:
# virsh restore foo.img
# virsh destroy domU
# restart libvirt
# virsh restore foo.img
According to a gdb backtrace a memcpy from the function xc_domain_restore
is causing the segfault.
Then I saved a vm with the xl tool (which also uses the libxenlight interface)
and restored it twice. No segfault occured.
So I figured something must went wrong in libvirt.
However I was unable to identify the responsible part of code.
Now I am hoping that a review will possibly solve this issue.
Here is the gdb backtrace:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x42ba1950 (LWP 23813)]
0x00007f1bc17d906b in memcpy () from /lib/libc.so.6
(gdb) bt
#0 0x00007f1bc17d906b in memcpy () from /lib/libc.so.6
#1 0x00007f1bc2b49346 in xc_domain_restore () from /usr/lib/libxenguest.so.4.0
#2 0x00007f1bc31a80f3 in ?? () from /usr/lib/libxenlight.so.1.0
#3 0x00007f1bc31a105e in ?? () from /usr/lib/libxenlight.so.1.0
#4 0x000000000049389a in libxlVmStart (driver=0x7f1bb8003e80, vm=0x7f1bb8053400, start_paused=false, restore_fd=20) at libxl/libxl_driver.c:531
#5 0x00000000004945c5 in libxlDomainRestore (conn=<value optimized out>, from=<value optimized out>) at libxl/libxl_driver.c:1745
#6 0x00007f1bc1f85a4b in virDomainRestore (conn=0x20a4d40, from=0x7f1bb804d260 "/root/tt.img") at libvirt.c:2330
#7 0x000000000042c5b8 in remoteDispatchDomainRestore (server=<value optimized out>, client=<value optimized out>, conn=0xaf0, hdr=<value optimized out>, rerr=0x42ba0e20,
args=0xffffffff, ret=0x42ba0f00) at remote.c:2616
#8 0x0000000000431cb7 in remoteDispatchClientRequest (server=0x209fe90, client=0x20a4ad0, msg=0x20b1aa0) at dispatch.c:524
#9 0x000000000041dd53 in qemudWorker (data=0x20a8018) at libvirtd.c:1622
#10 0x00007f1bc1cb9fc7 in start_thread () from /lib/libpthread.so.0
#11 0x00007f1bc182b64d in clone () from /lib/libc.so.6
#12 0x0000000000000000 in ?? ()
Cheers,
Markus
---
src/libxl/libxl_conf.h | 14 +++
src/libxl/libxl_driver.c | 228 ++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 225 insertions(+), 17 deletions(-)
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index 8c87786..e7dd3a1 100644
--- a/src/libxl/libxl_conf.h
+++ b/src/libxl/libxl_conf.h
@@ -1,5 +1,6 @@
/*---------------------------------------------------------------------------*/
/* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ * Copyright (C) 2011 Univention GmbH.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,6 +18,7 @@
*
* Authors:
* Jim Fehlig <jfehlig(a)novell.com>
+ * Markus Groß <gross(a)univention.de>
*/
/*---------------------------------------------------------------------------*/
@@ -85,6 +87,18 @@ struct _libxlDomainObjPrivate {
int eventHdl;
};
+#define LIBXL_SAVE_MAGIC "libvirt-xml\n \0 \r"
+#define LIBXL_SAVE_VERSION 1
+
+typedef struct _libxlSavefileHeader libxlSavefileHeader;
+typedef libxlSavefileHeader *libxlSavefileHeaderPtr;
+struct _libxlSavefileHeader {
+ char magic[sizeof(LIBXL_SAVE_MAGIC)-1];
+ uint32_t version;
+ uint32_t xmlLen;
+ /* 24 bytes used, pad up to 64 bytes */
+ uint32_t unused[10];
+};
# define libxlError(code, ...) \
virReportErrorHelper(VIR_FROM_LIBXL, code, __FILE__, \
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 247d78e..56a62c9 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -29,6 +29,7 @@
#include <sys/utsname.h>
#include <math.h>
#include <libxl.h>
+#include <fcntl.h>
#include "internal.h"
#include "logging.h"
@@ -60,11 +61,10 @@
static libxlDriverPrivatePtr libxl_driver = NULL;
-
/* Function declarations */
static int
-libxlVmStart(libxlDriverPrivatePtr driver,
- virDomainObjPtr vm, bool start_paused);
+libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
+ bool start_paused, int restore_fd);
/* Function definitions */
@@ -188,7 +188,7 @@ libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED,
virResetLastError();
if (vm->autostart && !virDomainObjIsActive(vm) &&
- libxlVmStart(driver, vm, false) < 0) {
+ libxlVmStart(driver, vm, false, -1) < 0) {
err = virGetLastError();
VIR_ERROR(_("Failed to autostart VM '%s': %s"),
vm->def->name,
@@ -378,7 +378,7 @@ static void libxlEventHandler(int watch,
break;
case SHUTDOWN_reboot:
libxlVmReap(driver, vm, 0);
- libxlVmStart(driver, vm, 0);
+ libxlVmStart(driver, vm, 0, -1);
break;
default:
VIR_INFO("Unhandled shutdown_reason %d", info.shutdown_reason);
@@ -504,8 +504,8 @@ cleanup:
* virDomainObjPtr should be locked on invocation
*/
static int
-libxlVmStart(libxlDriverPrivatePtr driver,
- virDomainObjPtr vm, bool start_paused)
+libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
+ bool start_paused, int restore_fd)
{
libxl_domain_config d_config;
virDomainDefPtr def = vm->def;
@@ -524,12 +524,23 @@ libxlVmStart(libxlDriverPrivatePtr driver,
//TODO: Balloon dom0 ??
//ret = freemem(&d_config->b_info, &d_config->dm_info);
- ret = libxl_domain_create_new(&priv->ctx, &d_config,
- NULL, &child_console_pid, &domid);
+ if (restore_fd < 0)
+ ret = libxl_domain_create_new(&priv->ctx, &d_config,
+ NULL, &child_console_pid, &domid);
+ else
+ ret = libxl_domain_create_restore(&priv->ctx, &d_config, NULL,
+ &child_console_pid, &domid,
+ restore_fd);
+
if (ret) {
- libxlError(VIR_ERR_INTERNAL_ERROR,
- _("libxenlight failed to create new domain '%s'"),
- d_config.c_info.name);
+ if (restore_fd < 0)
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxenlight failed to create new domain '%s'"),
+ d_config.c_info.name);
+ else
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxenlight failed to restore domain '%s'"),
+ d_config.c_info.name);
goto error;
}
@@ -562,7 +573,9 @@ libxlVmStart(libxlDriverPrivatePtr driver,
goto error;
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
- VIR_DOMAIN_EVENT_STARTED_BOOTED);
+ restore_fd < 0 ?
+ VIR_DOMAIN_EVENT_STARTED_BOOTED :
+ VIR_DOMAIN_EVENT_STARTED_RESTORED);
libxlDomainEventQueue(driver, event);
libxl_domain_config_destroy(&d_config);
@@ -1046,7 +1059,8 @@ libxlDomainCreateXML(virConnectPtr conn, const char *xml,
goto cleanup;
def = NULL;
- if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0) < 0) {
+ if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0,
+ -1) < 0) {
virDomainRemoveInactive(&driver->domains, vm);
vm = NULL;
goto cleanup;
@@ -1566,6 +1580,186 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
}
static int
+libxlDomainSave(virDomainPtr dom, const char * to)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ libxlDomainObjPrivatePtr priv;
+ virDomainEventPtr event = NULL;
+ libxlSavefileHeader hdr;
+ libxl_domain_suspend_info s_info;
+ char *xml;
+ uint32_t xml_len;
+ int fd;
+ int ret = -1;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ libxlError(VIR_ERR_NO_DOMAIN,
+ _("No domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+
+ if (vm->state != VIR_DOMAIN_PAUSED) {
+ memset(&s_info, 0, sizeof(s_info));
+
+ if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR,
+ getuid(), getgid(), 0)) < 0) {
+ virReportSystemError(-fd,
+ _("Failed to create domain save file '%s'"),
+ to);
+ goto cleanup;
+ }
+
+ if ((xml = virDomainDefFormat(vm->def, 0)) == NULL)
+ goto cleanup;
+ xml_len = strlen(xml) + 1;
+
+ memset(&hdr, 0, sizeof(hdr));
+ memcpy(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic));
+ hdr.version = LIBXL_SAVE_VERSION;
+ hdr.xmlLen = xml_len;
+
+ if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+ libxlError(VIR_ERR_OPERATION_FAILED,
+ _("Failed to write save file header"));
+ goto cleanup;
+ }
+
+ if (safewrite(fd, xml, xml_len) != xml_len) {
+ libxlError(VIR_ERR_OPERATION_FAILED,
+ _("Failed to write xml description"));
+ goto cleanup;
+ }
+
+ if (libxl_domain_suspend(&priv->ctx, &s_info, dom->id, fd) != 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to save domain '%d' with libxenlight"),
+ dom->id);
+ goto cleanup;
+ }
+
+ event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_STOPPED_SAVED);
+
+ if (libxlVmReap(driver, vm, 1) != 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to destroy domain '%d'"), dom->id);
+ goto cleanup;
+ }
+
+ if (!vm->persistent) {
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ }
+ ret = 0;
+ }
+cleanup:
+ VIR_FREE(xml);
+ if (VIR_CLOSE(fd) < 0)
+ virReportSystemError(errno, "%s", _("cannot close file"));
+ if (vm)
+ virDomainObjUnlock(vm);
+ if (event)
+ libxlDomainEventQueue(driver, event);
+ libxlDriverUnlock(driver);
+ return ret;
+}
+
+static int
+libxlDomainRestore(virConnectPtr conn, const char * from)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ virDomainDefPtr def = NULL;
+ virDomainObjPtr vm = NULL;
+ libxlSavefileHeader hdr;
+ char *xml = NULL;
+ int fd;
+ int ret = -1;
+
+ libxlDriverLock(driver);
+
+ if ((fd = virFileOpenAs(from, O_RDONLY, 0, getuid(), getgid(), 0)) < 0) {
+ libxlError(VIR_ERR_OPERATION_FAILED,
+ "%s", _("cannot read domain image"));
+ goto cleanup;
+ }
+
+ if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+ libxlError(VIR_ERR_OPERATION_FAILED,
+ "%s", _("failed to read libxl header"));
+ goto cleanup;
+ }
+
+ if (memcmp(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic))) {
+ libxlError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect"));
+ goto cleanup;
+ }
+
+ if (hdr.version > LIBXL_SAVE_VERSION) {
+ libxlError(VIR_ERR_OPERATION_FAILED,
+ _("image version is not supported (%d > %d)"),
+ hdr.version, LIBXL_SAVE_VERSION);
+ goto cleanup;
+ }
+
+ if (hdr.xmlLen <= 0) {
+ libxlError(VIR_ERR_OPERATION_FAILED,
+ _("invalid XML length: %d"), hdr.xmlLen);
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) {
+ libxlError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML"));
+ goto cleanup;
+ }
+
+ if (!(def = virDomainDefParseString(driver->caps, xml,
+ VIR_DOMAIN_XML_INACTIVE)))
+ goto cleanup;
+
+ if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
+ goto cleanup;
+
+ if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, true)))
+ goto cleanup;
+
+ def = NULL;
+
+ if ((ret = libxlVmStart(driver, vm, false, fd)) < 0 &&
+ !vm->persistent) {
+ virDomainRemoveInactive(&driver->domains, vm);
+ vm = NULL;
+ }
+
+cleanup:
+ VIR_FREE(xml);
+ virDomainDefFree(def);
+ if (VIR_CLOSE(fd) < 0)
+ virReportSystemError(errno, "%s", _("cannot close file"));
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxlDriverUnlock(driver);
+ return ret;
+}
+
+static int
libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
unsigned int flags)
{
@@ -2036,7 +2230,7 @@ libxlDomainCreateWithFlags(virDomainPtr dom,
goto cleanup;
}
- ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0);
+ ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1);
cleanup:
if (vm)
@@ -2672,8 +2866,8 @@ static virDriver libxlDriver = {
NULL, /* domainSetBlkioParameters */
NULL, /* domainGetBlkioParameters */
libxlDomainGetInfo, /* domainGetInfo */
- NULL, /* domainSave */
- NULL, /* domainRestore */
+ libxlDomainSave, /* domainSave */
+ libxlDomainRestore, /* domainRestore */
NULL, /* domainCoreDump */
libxlDomainSetVcpus, /* domainSetVcpus */
libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */
--
1.7.1
13 years, 6 months
[libvirt] [PATCH] Remove unused 'target' field in virDomainHostdevDef
by Daniel P. Berrange
The virDomainHostdevDef struct contains a 'char *target'
field. This is set to 'NULL' when parsing XML and never
used / set anywhere else. Clearly it is bogus & unused
* src/conf/domain_conf.c, src/conf/domain_conf.h: Remove
target from virDomainHostdevDef
---
src/conf/domain_conf.c | 2 --
src/conf/domain_conf.h | 1 -
2 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 00c8058..f2e2aca 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -893,7 +893,6 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def)
if (!def)
return;
- VIR_FREE(def->target);
virDomainDeviceInfoClear(&def->info);
VIR_FREE(def);
}
@@ -4774,7 +4773,6 @@ virDomainHostdevDefParseXML(const xmlNodePtr node,
virReportOOMError();
return NULL;
}
- def->target = NULL;
mode = virXMLPropString(node, "mode");
if (mode) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 60e1704..da34770 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -792,7 +792,6 @@ struct _virDomainHostdevDef {
int dummy;
} caps;
} source;
- char* target;
int bootIndex;
virDomainDeviceInfo info; /* Guest address */
};
--
1.7.4.4
13 years, 7 months
[libvirt] [PATCH 0/3 v2] More graceful handling of QEMU monitor failures
by Daniel P. Berrange
An update of
https://www.redhat.com/archives/libvir-list/2011-May/msg00657.html
Currently when libvirt has a serious error doing I/O and/or parsing
of the QEMU monitor, it will kill off the guest. Application developers
have expressed a desire for more graceful handling of this scenario.
In particular to allow the guest OS to continue to run, without any
further monitor interactons, and then kill/restart it at a time which
is convenient to the guest admin/apps.
New in this posting:
- Change the name of the event to 'CONTROL_ERROR' and use the
generic callback, instead of passing a type field
- Add python dispatch code
- Add 3rd patch to improve qemu monitor error reporting
13 years, 7 months
[libvirt] [PATCH] Fix virExecWithHook Prototype
by Richard Laager
This was necessary to get libvirt to build on Solaris 11 Express and
seems correct (as it makes this match the definition in util.c):
diff --git a/src/util/util.h b/src/util/util.h
index d320c40..31ec089 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -70,7 +70,7 @@ int virExecDaemonize(const char *const*argv,
int virExecWithHook(const char *const*argv,
const char *const*envp,
const fd_set *keepfd,
- int *retpid,
+ pid_t *retpid,
int infd,
int *outfd,
int *errfd,
13 years, 7 months