[libvirt] [PATCH] lxc: Seperate domain config loading
by Osier Yang
This patch seperate the domain config loading just as qemu driver
does, first loading config of running or trasient domains, then
of persistent inactive domains. And only try to reconnect the
monitor of running domains, so that it won't always throws errors
saying can't connect to domain monitor.
And as "virDomainLoadConfig->virDomainAssignDef->virDomainObjAssignDef",
already do things like "vm->newDef = def", removed the codes
in "lxcReconnectVM" that does the same work.
---
src/lxc/lxc_driver.c | 30 +++++++++++++++---------------
1 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 2bb592d..ccf20e4 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1521,6 +1521,10 @@ static int lxcVmStart(virConnectPtr conn,
if (virDomainObjSetDefTransient(driver->caps, vm, false) < 0)
goto cleanup;
+ /* Write domain status to disk. */
+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
+ goto cleanup;
+
rc = 0;
cleanup:
@@ -1586,7 +1590,6 @@ static int lxcDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_BOOTED);
-
cleanup:
if (vm)
virDomainObjUnlock(vm);
@@ -1925,18 +1928,6 @@ lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
goto cleanup;
}
- if ((config = virDomainConfigFile(driver->stateDir,
- vm->def->name)) == NULL)
- goto cleanup;
-
- /* Try and load the live config */
- tmp = virDomainDefParseFile(driver->caps, config, 0);
- VIR_FREE(config);
- if (tmp) {
- vm->newDef = vm->def;
- vm->def = tmp;
- }
-
if (vm->pid != 0) {
vm->def->id = vm->pid;
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
@@ -2029,6 +2020,17 @@ static int lxcStartup(int privileged)
lxc_driver->caps->privateDataAllocFunc = lxcDomainObjPrivateAlloc;
lxc_driver->caps->privateDataFreeFunc = lxcDomainObjPrivateFree;
+ /* Get all the running persistent or transient configs first */
+ if (virDomainLoadAllConfigs(lxc_driver->caps,
+ &lxc_driver->domains,
+ lxc_driver->stateDir,
+ NULL,
+ 1, NULL, NULL) < 0)
+ goto cleanup;
+
+ virHashForEach(lxc_driver->domains.objs, lxcReconnectVM, lxc_driver);
+
+ /* Then inactive persistent configs */
if (virDomainLoadAllConfigs(lxc_driver->caps,
&lxc_driver->domains,
lxc_driver->configDir,
@@ -2036,8 +2038,6 @@ static int lxcStartup(int privileged)
0, NULL, NULL) < 0)
goto cleanup;
- virHashForEach(lxc_driver->domains.objs, lxcReconnectVM, lxc_driver);
-
lxcDriverUnlock(lxc_driver);
lxcAutostartConfigs(lxc_driver);
--
1.7.4
13 years, 10 months
[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, 10 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, 10 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, 10 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, 10 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, 10 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, 10 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, 10 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, 10 months