[libvirt] RFC: APIs for managing a subset of a domain's disks
by Eric Blake
Consider the case of a guest that has multiple virtual disks, some
residing on shared storage (such as the OS proper) and some on local
storage (scratch space, where the OS has faster response if the virtual
disk does not have to go over the network, and possibly one where the
guest can still work even if the disk is hot-unplugged). During
migration, you'd want different handling of the two disks (the
destination can already see the shared disk, but must either copy the
contents or recreate a blank scratch volume for the local disk).
Or, consider the case where a guest has one disk as qcow2 (it is not
modified frequently, and benefits from sharing a common backing file
with other guests), while another disk is raw (for better read-write
performance). Right now, 'virsh snapshot' fails, because it only works
if all disks are qcow2; and in fact it may be the case that it is
desirable to only take a snapshot of a subset of the domain's disks.
So, I think we need some way to request an operation on a subset of VM
disks, in a manner that can be shared between migration and volume
management APIs. And I'm not sure it makes sense to add two more
parameters to migration commands (an array of disks, and the size of
that array), nor to modify the snapshot XML to describe which disks
belong to the snapshot.
So I'm thinking we need some sort of API set to manage a stateful set of
disk operations. Maybe the trick is to define that every VM has a
(possibly empty) set of selected disks, with APIs to manage moving a
single disk in or out of the set, an API for listing the entire set,
then a single flag to migration that states that live block migration is
attempted for all disks currently in the VMs selected disk set.
Being stateful, this would have to be represented in XML (so that if
libvirtd is restarted, it remembers which disks are selected); I'm
thinking of adding a new selected='yes|no' attribute to <disk>, as in:
<disk type='file' device='disk' selected='yes'/>
<driver name='qemu' type='raw'/>
...
</disk>
where if the attribute is absent, it defaults to no. For hypervisors
where the state is maintained by libvirtd (qemu, lxc), the XML works;
for other hypervisors, the notion of a subset of selected disks would
have to just fail unless there is some hypervisor-specific way to track
that information alongside a domain.
For my API proposal, I'm including an unused flags argument to all the
virDomainDiskSet* commands (experience has taught me well). In fact, we
could even use that flags parameter, to maintain parallel sets (set 0 is
the set of disks to migrate, set 1 is the set of disks to snapshot,
...), although I don't think we need that complexity yet (besides, it
would affect the proposed XML).
/* Add disk to the domain's set of selected disks; flags ignored for
now; return 0 on success, 1 if already in the set, -1 on failure */
int virDomainDiskSetAdd(virDomainPtr dom, char *disk, unsigned int flags);
/* Remove disk from the domain's set of selected disks; flags ignored
for now; return 0 on success, 1 if already absent from the set, -1 on
failure */
int virDomainDiskSetRemove(virDomainPtr dom, char *disk, unsigned int
flags);
/* Add all disks to the domain's set of selected disks; flags ignored
for now; return 0 on success, -1 on failure */
int virDomainDiskSetAddAll(virDomainPtr dom, unsigned int flags);
/* Remove all disks from the domain's set of selected disks; flags
ignored for now; return 0 on success, -1 on failure */
int virDomainDiskSetRemoveAll(virDomainPtr dom, unsigned int flags);
/* Return the size of the domain's currently selected disk set, or -1 on
failure; flags ignored for now */
int virDomainDiskSetSize(virDomainPtr dom, unsigned int flags);
/* Populate up to n entries of the array with the names of the domain's
selected disk set, and return how many entries were populated, or -1 on
failure; flags ignored for now */
int virDomainDiskSetList(virDomainPtr dom, char **array, int n, unsigned
int flags)
With API in place for tracking a subset of selected disks, we can then
extend existing APIs with new flags:
/* Old way - domain migration without any disks migrated */
virDomainMigrate(dom, dconn, flags | 0, dname, uri, bandwidth)
/* New way - domain migration, including all disks in the domain's
selected disk set being copied to the destination */
virDomainMigrate(dom, dconn, flags | VIR_MIGRATE_WITH_DISK_SET, dname,
uri, bandwidth)
/* Old way - snapshot of all disks */
virDomainSnapshotCreateXML(dom, xml, 0)
/* New way - snapshot of just disks in selected disk set */
virDomainSnapshotCreateXML(dom, xml, VIR_DOMAIN_SAVE_DISK_SET)
I'd also like to see some collaboration between virDomainSave (for
memory) and virDomainSmapshotCreateXML (for disks); unfortunately,
virDomainSave doesn't take a flags argument. Maybe this calls for a new
API, and possibly a new version of the header to a 'virsh save' image to
track the location of snapshotted disks alongside the saved memory state:
/* Save the RAM state of domain to the base file "to". If "xml" is
NULL, no disks are snapshotted. Otherwise, "xml" is a snapshot XML that
describes how disk state will also be saved; if flags includes
VIR_DOMAIN_SAVE_DISK_SET, then the domain's selected disk set is
snapshotted, otherwise all disks are snapshotted. If flags contains
VIR_DOMAIN_SAVE_LIVE, then the guest is resumed after snapshot is
completed; otherwise the guest is halted. */
int virDomainSaveFlags(virDomainPtr dom, const char *to, const char
*xml, unsigned int flags);
Thoughts before I start implementing some of this for post-0.9.1?
--
Eric Blake eblake(a)redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org
14 years
[libvirt] [RFC PATCH] NUMA tuning support
by Osier Yang
Hi, All,
This is a simple implenmentation for NUMA tuning support based on binary
program 'numactl', currently only supports to bind memory to specified nodes,
using option "--membind", perhaps it need to support more, but I'd like
send it early so that could make sure if the principle is correct.
Ideally, NUMA tuning support should be added in qemu-kvm first, such
as they could provide command options, then what we need to do in libvirt
is just to pass the options to qemu-kvm, but unfortunately qemu-kvm doesn't
support it yet, what we could do currently is only to use numactl,
it forks process, a bit expensive than qemu-kvm supports NUMA tuning
inside with libnuma, but it shouldn't affects much I guess.
The NUMA tuning XML is like:
<numatune>
<membind nodeset='+0-4,8-12'/>
</numatune>
Any thoughts/feedback is appreciated.
Regards
Osier
[PATCH 1/5] build: Define NUMACTL for numa tuning use
[PATCH 2/5] docs: Define XML schema for numa tuning and add docs
[PATCH 3/5] conf: Support NUMA tuning XML
[PATCH 4/5] qemu: Build command line for NUMA tuning
[PATCH 5/5] tests: Add tests for guest use NUMA tuning
14 years
[libvirt] libvirt: TLS client certificate handling
by Doug Goldstein
Trying to setup qemu+tls here and I'm running into a few oddities
(well that I feel are oddities) that I wanted clarification on before
I submitted patches. The documentation I am following is:
[1] http://libvirt.org/remote.html#Remote_certificates
[2] http://wiki.libvirt.org/page/TLSSetup
[3] http://wiki.libvirt.org/page/VNCTLSSetup
All my storage is on iSCSI. I have 3 VM servers. 2 which every user
can access and 1 which only a subset of users can access via the
"tls_allowed_dn_list" parameter. Now how I envision this is that each
of the 3 machines have their server certs & client certs in
/etc/pki/libvirt, while each of the clients have their certs in
$HOME/.pki/libvirt. That way a user, who doesn't have root or sudo
access on the machine they are on could access the 2 VM servers they
are allowed to access. However, if you look at the code, the only time
$HOME/.pki/libvirt is used is when getuid() != 0 (this is correct) but
the user either had to not specify a server to connect to and is using
/session or you're auto-probing the local auto-spawned daemon for the
remote URI. Effectively this means my approach can't happen. To
complicate matters further, the documentation tells you to chown the
client cert & key as root:root and set the permissions to 400. Which
effectively means users can never use qemu+tls.
I propose that we change the code for getuid() != 0 to always try
$HOME/.pki/libvirt/ first and then try the system certificate. If
everyone agrees, then I'll submit patches shortly.
Additionally I wanted to note that as per [3], the default path for
libvirt's user keys in $HOME differs from all other applications out
there so I would also make it check
$HOME/.pki/libvirt/private/clientkey.pem as well as
$HOME/.pki/libvirt/clientkey.pem so that we'd match other application
configurations.
--
Doug Goldstein
14 years
[libvirt] [PATCH 00/22] Extend remote generator to generate function bodies too
by Matthias Bolte
Richard W.M. Jones suggested [1] that the code that directly deals with the
XDR protocol should be generated. The remote_generate_stubs.pl script
already generates all the headers, just the bodies in the daemon and remote
driver are manually written. But most of the functions just follow simple
patterns. So I extended the generator to exploit this patterns and move
11 kLOC code from manually written to generated code.
During this I came a cross many small variations and problems in the XDR
protocol. For example, NWFilterDefineXML has a flags parameter in the public
API, but it's not transferred in the XDR protocol. Another things is the
variations in the usage of unsigned VS signed types. This comes in two forms.
public API VS XDR procotol and in between different functions. For example,
some functions use int for the flags paramater and some use unsigned int.
This results in quite a lot of special case handling in the generator.
cfg.mk | 10 +-
daemon/Makefile.am | 46 +-
daemon/qemu_dispatch_args.h | 2 +-
daemon/qemu_dispatch_bodies.c | 6 +
daemon/qemu_dispatch_prototypes.h | 2 +-
daemon/qemu_dispatch_ret.h | 2 +-
daemon/qemu_dispatch_table.h | 2 +-
daemon/remote.c | 5765 +----------------------------------
daemon/remote_dispatch_args.h | 2 +-
daemon/remote_dispatch_bodies.c | 5933 +++++++++++++++++++++++++++++++++++
daemon/remote_dispatch_prototypes.h | 80 +-
daemon/remote_dispatch_ret.h | 2 +-
daemon/remote_dispatch_table.h | 158 +-
daemon/remote_generate_stubs.pl | 195 --
daemon/remote_generator.pl | 1198 +++++++
po/POTFILES.in | 1 +
src/Makefile.am | 13 +-
src/remote/qemu_client_bodies.c | 4 +
src/remote/qemu_protocol.c | 2 +-
src/remote/qemu_protocol.h | 2 +-
src/remote/qemu_protocol.x | 2 +-
src/remote/remote_client_bodies.c | 4664 +++++++++++++++++++++++++++
src/remote/remote_driver.c | 4907 +----------------------------
src/remote/remote_protocol.c | 26 +-
src/remote/remote_protocol.h | 26 +-
src/remote/remote_protocol.x | 34 +-
src/remote_protocol-structs | 26 +-
27 files changed, 12093 insertions(+), 11017 deletions(-)
[1] https://www.redhat.com/archives/libvir-list/2011-April/msg00884.html
Matthias
14 years
[libvirt] [PATCH] Balloon dom0 in libxl driver
by Markus Groß
Creating a domU on a freshly booted dom0 does not work,
because the libxl driver does not allocate memory for the domU.
After creating a domain with xl libvirt is able to create domains too.
This patch reserves enough memory for the domU first.
---
src/libxl/libxl_driver.c | 48 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 247d78e..d4ca025 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -498,6 +498,46 @@ cleanup:
return ret;
}
+static int
+libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config)
+{
+ uint32_t needed_mem;
+ uint32_t free_mem;
+ int i;
+ int ret = -1;
+ int tries = 3;
+ int wait_secs = 10;
+
+ if ((ret = libxl_domain_need_memory(&priv->ctx, &d_config->b_info,
+ &d_config->dm_info,
+ &needed_mem)) >= 0) {
+ for (i = 0; i < tries; ++i) {
+ if ((ret = libxl_get_free_memory(&priv->ctx, &free_mem)) < 0)
+ break;
+
+ if (free_mem >= needed_mem) {
+ ret = 0;
+ break;
+ }
+
+ if ((ret = libxl_set_memory_target(&priv->ctx, 0,
+ free_mem - needed_mem,
+ /* relative */ 1, 0)) < 0)
+ break;
+
+ ret = libxl_wait_for_free_memory(&priv->ctx, 0, needed_mem,
+ wait_secs);
+ if (ret == 0 || ret != ERROR_NOMEM)
+ break;
+
+ if ((ret = libxl_wait_for_memory_target(&priv->ctx, 0, 1)) < 0)
+ break;
+ }
+ }
+
+ return ret;
+}
+
/*
* Start a domain through libxenlight.
*
@@ -521,8 +561,12 @@ libxlVmStart(libxlDriverPrivatePtr driver,
if (libxlBuildDomainConfig(driver, def, &d_config) < 0 )
return -1;
- //TODO: Balloon dom0 ??
- //ret = freemem(&d_config->b_info, &d_config->dm_info);
+ if (libxlFreeMem(priv, &d_config) < 0) {
+ libxlError(VIR_ERR_INTERNAL_ERROR,
+ _("libxenlight failed to get free memory for domain '%s'"),
+ d_config.c_info.name);
+ goto error;
+ }
ret = libxl_domain_create_new(&priv->ctx, &d_config,
NULL, &child_console_pid, &domid);
--
1.7.4.3
14 years
[libvirt] [PATCH] virsh: check actual access to the cert
by Doug Goldstein
Instead of calling stat(), check that we'll actually be able to access
and read the file.
Signed-off-by: Doug Goldstein <cardoe(a)gentoo.org>
---
src/remote/remote_driver.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 9965d38..c4e43aa 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1140,8 +1140,7 @@ static gnutls_certificate_credentials_t x509_cred;
static int
check_cert_file(const char *type, const char *file)
{
- struct stat sb;
- if (stat(file, &sb) < 0) {
+ if (access(file, F_OK|R_OK)) {
virReportSystemError(errno,
_("Cannot access %s '%s'"),
type, file);
--
1.7.5.rc3
14 years
[libvirt] [PATCH] maint: avoid comparisons to bool constants
by Eric Blake
HACKING already mentions that comparisons against literal 'true'
are unsafe; for consistency, also shorten comparisons against 'false'.
* src/conf/domain_conf.c (virDomainNetDefParseXML): Simplify.
* src/nwfilter/nwfilter_gentech_driver.c
(virNWFilterDomainFWUpdateCB): Likewise.
* tools/virsh.c (cmdVolDownload, vshCommandRun, vshPrintExtra):
Likewise.
---
src/conf/domain_conf.c | 2 +-
src/nwfilter/nwfilter_gentech_driver.c | 2 +-
tools/virsh.c | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 70ea350..a936ea4 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2581,7 +2581,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
xmlStrEqual(cur->name, BAD_CAST "source")) {
dev = virXMLPropString(cur, "dev");
mode = virXMLPropString(cur, "mode");
- } else if ((virtPortParsed == false) &&
+ } else if (!virtPortParsed &&
(def->type == VIR_DOMAIN_NET_TYPE_DIRECT) &&
xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
if (virVirtualPortProfileParamsParseXML(cur, &virtPort))
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index f89fb79..3e8961d 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -1032,7 +1032,7 @@ virNWFilterDomainFWUpdateCB(void *payload,
cb->err = virNWFilterUpdateInstantiateFilter(cb->conn,
net,
&skipIface);
- if (cb->err == 0 && skipIface == true) {
+ if (cb->err == 0 && skipIface) {
/* filter tree unchanged -- no update needed */
cb->err = virHashAddEntry(cb->skipInterfaces,
net->ifname,
diff --git a/tools/virsh.c b/tools/virsh.c
index e32680c..2b16714 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -7318,7 +7318,7 @@ cmdVolDownload (vshControl *ctl, const vshCmd *cmd)
cleanup:
VIR_FORCE_CLOSE(fd);
- if (ret == false && created)
+ if (!ret && created)
unlink(file);
if (vol)
virStorageVolFree(vol);
@@ -11697,11 +11697,11 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
if (enable_timing)
GETTIMEOFDAY(&after);
- if (ret == false)
+ if (!ret)
virshReportError(ctl);
/* try to automatically catch disconnections */
- if ((ret == false) &&
+ if (!ret &&
((disconnected != 0) ||
((last_error != NULL) &&
(((last_error->code == VIR_ERR_SYSTEM_ERROR) &&
@@ -12105,7 +12105,7 @@ vshPrintExtra(vshControl *ctl, const char *format, ...)
va_list ap;
char *str;
- if (ctl && ctl->quiet == true)
+ if (ctl && ctl->quiet)
return;
va_start(ap, format);
--
1.7.4.4
14 years
[libvirt] [PATCH 1/3] command: Add virCommandEnvAddFormat
by Cole Robinson
Similar to virCommandArgAddFormat. We will use this shortly.
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/command.c | 30 ++++++++++++++++++++++++++++++
src/util/command.h | 7 +++++++
3 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1b22be6..d89b191 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -99,6 +99,7 @@ virCommandAddArgList;
virCommandAddArgPair;
virCommandAddArgSet;
virCommandAddEnvBuffer;
+virCommandAddEnvFormat;
virCommandAddEnvPair;
virCommandAddEnvPass;
virCommandAddEnvPassCommon;
diff --git a/src/util/command.c b/src/util/command.c
index 862a913..f382cc5 100644
--- a/src/util/command.c
+++ b/src/util/command.c
@@ -259,6 +259,36 @@ virCommandNonblockingFDs(virCommandPtr cmd)
}
/*
+ * Add an environment variable to the child created by a printf-style format
+ */
+void
+virCommandAddEnvFormat(virCommandPtr cmd, const char *format, ...)
+{
+ char *env;
+ va_list list;
+
+ if (!cmd || cmd->has_error)
+ return;
+
+ va_start(list, format);
+ if (virVasprintf(&env, format, list) < 0) {
+ cmd->has_error = ENOMEM;
+ va_end(list);
+ return;
+ }
+ va_end(list);
+
+ /* Arg plus trailing NULL. */
+ if (VIR_RESIZE_N(cmd->env, cmd->maxenv, cmd->nenv, 1 + 1) < 0) {
+ VIR_FREE(env);
+ cmd->has_error = ENOMEM;
+ return;
+ }
+
+ cmd->env[cmd->nenv++] = env;
+}
+
+/*
* Add an environment variable to the child
* using separate name & value strings
*/
diff --git a/src/util/command.h b/src/util/command.h
index ff8ccf5..69e9169 100644
--- a/src/util/command.h
+++ b/src/util/command.h
@@ -98,6 +98,13 @@ void virCommandDaemonize(virCommandPtr cmd);
void virCommandNonblockingFDs(virCommandPtr cmd);
/*
+ * Add an environment variable to the child created by a printf-style format
+ */
+void
+virCommandAddEnvFormat(virCommandPtr cmd, const char *format, ...)
+ ATTRIBUTE_NONNULL(2) ATTRIBUTE_FMT_PRINTF(2, 3);
+
+/*
* Add an environment variable to the child
* using separate name & value strings
*/
--
1.7.4.4
14 years
[libvirt] [PATCH v3] Add warning message to XML definition files stored on disk
by Michal Privoznik
Users often edit XML file stored in configuration directory
thinking of modifying a domain/network/pool/etc. Thus it is wise
to let them know they are using the wrong way and give them hint.
---
diff to v2:
- remove redundant flag VIR_XML_EMIT_WARNING
- remove enum, pass const string instead
- don't translate warning message
diff to v1:
- instead of pointing users to web, write down the actual virsh command
- write to passed FD instead of buffer
src/conf/domain_conf.c | 2 ++
src/conf/network_conf.c | 2 ++
src/conf/nwfilter_conf.c | 4 ++++
src/conf/storage_conf.c | 2 ++
src/libvirt_private.syms | 1 +
src/util/util.c | 37 +++++++++++++++++++++++++++++++++++++
src/util/util.h | 4 ++++
7 files changed, 52 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index eae178b..e98af0f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -8561,6 +8561,8 @@ int virDomainSaveXML(const char *configDir,
goto cleanup;
}
+ virEmitXMLWarning(fd, def->name, "edit");
+
towrite = strlen(xml);
if (safewrite(fd, xml, towrite) < 0) {
virReportSystemError(errno,
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 08f7b77..4eb46fa 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -925,6 +925,8 @@ int virNetworkSaveXML(const char *configDir,
goto cleanup;
}
+ virEmitXMLWarning(fd, def->name, "net-edit");
+
towrite = strlen(xml);
if (safewrite(fd, xml, towrite) < 0) {
virReportSystemError(errno,
diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
index 5ba2972..eb75bad 100644
--- a/src/conf/nwfilter_conf.c
+++ b/src/conf/nwfilter_conf.c
@@ -2249,6 +2249,8 @@ int virNWFilterSaveXML(const char *configDir,
goto cleanup;
}
+ virEmitXMLWarning(fd, def->name, "nwfilter-edit");
+
towrite = strlen(xml);
if (safewrite(fd, xml, towrite) < 0) {
virReportSystemError(errno,
@@ -2645,6 +2647,8 @@ virNWFilterObjSaveDef(virNWFilterDriverStatePtr driver,
goto cleanup;
}
+ virEmitXMLWarning(fd, def->name, "nwfilter-edit");
+
towrite = strlen(xml);
if (safewrite(fd, xml, towrite) != towrite) {
virReportSystemError(errno,
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index aeb1596..9be4cae 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1551,6 +1551,8 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
goto cleanup;
}
+ virEmitXMLWarning(fd, def->name, "pool-edit");
+
towrite = strlen(xml);
if (safewrite(fd, xml, towrite) != towrite) {
virReportSystemError(errno,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ea4bf74..e2e706d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -901,6 +901,7 @@ virArgvToString;
virAsprintf;
virBuildPathInternal;
virDirCreate;
+virEmitXMLWarning;
virEnumFromString;
virEnumToString;
virEventAddHandle;
diff --git a/src/util/util.c b/src/util/util.c
index 9041ab6..3b151f4 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -3207,3 +3207,40 @@ bool virIsDevMapperDevice(const char *devname ATTRIBUTE_UNUSED)
return false;
}
#endif
+
+int virEmitXMLWarning(int fd,
+ const char *name,
+ const char *cmd) {
+ size_t len;
+ const char *prologue = "<!--\n\
+WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE \n\
+OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:\n\
+virsh ";
+ const char *epilogue = "\n\
+or other application using the libvirt API.\n\
+-->\n\n";
+
+ if (fd < 0 || !name || !cmd)
+ return -1;
+
+ len = strlen(prologue);
+ if (safewrite(fd, prologue, len) != len)
+ return -1;
+
+ len = strlen(cmd);
+ if (safewrite(fd, cmd, len) != len)
+ return -1;
+
+ if (safewrite(fd, " ", 1) != 1)
+ return -1;
+
+ len = strlen(name);
+ if (safewrite(fd, name, len) != len)
+ return -1;
+
+ len = strlen(epilogue);
+ if (safewrite(fd, epilogue, len) != len)
+ return -1;
+
+ return 0;
+}
diff --git a/src/util/util.h b/src/util/util.h
index d320c40..9d8df06 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -299,4 +299,8 @@ int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL;
char *virTimestamp(void);
bool virIsDevMapperDevice(const char *devname) ATTRIBUTE_NONNULL(1);
+
+int virEmitXMLWarning(int fd,
+ const char *name,
+ const char *cmd) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
#endif /* __VIR_UTIL_H__ */
--
1.7.4.4
14 years
[libvirt] [PATCH] qemu: Don't flag domain running when qemu dies
by Michal Privoznik
When we try to stop domain's CPUs and qemu crash meanwhile, a cleanup
of domain is performed and domain gets into state VIR_DOMAIN_SHUTOFF.
But this is later overwritten and thus results in domain marked as
running but with negative ID.
---
src/qemu/qemu_process.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 7691cbe..539e4f3 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1919,7 +1919,7 @@ int qemuProcessStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm)
qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorStopCPUs(priv->mon);
qemuDomainObjExitMonitorWithDriver(driver, vm);
- if (ret < 0) {
+ if (ret < 0 && vm->state == VIR_DOMAIN_PAUSED) {
vm->state = oldState;
}
return ret;
--
1.7.4.4
14 years