[libvirt] Matching the type of mediated devices in the migration
by Wang, Zhi A
BACKGROUND
As the live migration of mdev is going to be supported in VFIO, a scheme of deciding if a mdev could be migratable between the source machine and the destination machine is needed. Mostly, this email is going to discuss a possible solution which needs fewer modifications of libvirt/VFIO.
The configuration of a mdev is located in the domain XML, which guides libvirt how to find the mdev and generating the command line for QEMU. It basically only includes the UUID of a mdev. The domain XML of the source machine and destination machine are going to be compared before the migration really happens. Each configuration item would be compared and checked by libvirt. If one item of the source machine is different from the item of destination machine, the migration fails. For mdev, there is no any check/match before the migration happens yet.
The user could use the node device list of libvirt to list the host devices and see the capabilities of those devices. The current node device code of libvirt has already been able to extract the supported mdev types from a host PCI device, plus some basic information, like max supported mdev instance of a host PCI device.
THE SOLUTION
To strictly check the mdev type and make sure the migration happens between the compatible mediated devices, three new mandatory elements in the domain XML below the hostdev element would be introduced:
vendorid: The vendor ID of the mdev, which comes from the host PCI device. A user could obtain this information from the host PCI device which supports mdev in the node device list.
productid: The product ID of the mdev, which also comes from the host PCI device. A user could obtain this information from the same approach above.
mdevtype: The type of the mdev. As the creation of the mdev is managed by the user, the user knows the type of the mdev and would be responsible for filling out this information.
These three elements are only needed when the device API of a mdev is "vfio-PCI". Take the example of mdev configuration from https://libvirt.org/formatdomain.html to illustrate the modification:
<devices>
<hostdev mode='subsystem' type='mdev' model='vfio-pci'>
<source>
<address uuid='c2177883-f1bb-47f0-914d-32a22e3a8804'/>
<vendorid>0xdead</vendorid> <!-- The VID of the host PCI device which supports this mdev -->
<productid>0xbeef</productid> <!-- The PID of the host PCI device which supports this mdev -->
<mdevtype>type</mdevtype> <!-- The vendor-specific mdev type string -->
</source>
</hostdev>
With the newly introduced elements above, the flow of the creation of a domain XML with mdev will be like:
1. The user obtains the vendorid/productid from node device list
2. The user fills the vendorid/productid/mdevtype in the domain XML
3. When a migration happens, libvirt check these elements. If one item is different between two domain XML, then migration fails.
POSSIBLE MODIFICATION OF LIBVIRT
1) Introduce three new elements in domain XML parsing and processing functions.
2) Extend the function virDomainDeviceInfoCheckABIStability() which is going to check the host dev part of the domain XMLs between the source machine and the destination machine. So it could fail the migration when it finds out the IDs and the mdev type are different between domain XMLs.
PROS
Minor changes in libvirt could achieve the mdev type match in the migration. Modifying VFIO and other mdev components is not necessary.
Thanks,
Zhi.
6 years, 3 months
[libvirt] [PATCH] Take DryRun code out of virCommand* code flow
by Shi Lei
Since dry-run of cmd is just for tests now, it would be better to remove
dry-run code and move them to testutils. Then the code flow in virCommand*
could be more general. There are 3 steps in this patch:
1. Introduce a new global hook (of virExecHook type) which will be called
in code flow just before the cmd->hook. The global hook is also called in
child process. If it returns 1, the child process will exit with status
in advance and the parent will process io and wait for the child normally.
It prepares for registering dry-run and anything else.
The virCommandSetPreExecHook is modified for registering both types of hooks.
2. Implement virTestSetDryRun with dry-run code in "testutils.c".
It substitutes for virCommandSetDryRun. The virTestSetDryRun invokes
virCommandSetPreExecHook to register a function on the global hook which
will fill in cmdline buffer and call callback for tests.
3. Remove all dryrun code in "vircommand.c" and remove virCommandSetDryRun API.
Diffs from old dry-run:
The new global hook is called in child process. So dryrun-callback for tests
should write to stdout/stderr when they need output something.
Now the opaque argument for dryrun-callback cannot be inout. In "tests/viriscsitest.c",
iface_created in opaque of callback is an inout argument. There's a bit
complicated to transfer it between the child and its parent. So this patch use
a temporary file to do that.
Signed-off-by: Shi Lei <shi_lei(a)massclouds.com>
---
docs/internals/command.html.in | 33 +++++-
src/libvirt_private.syms | 4 +-
src/qemu/qemu_process.c | 8 +-
src/util/vircommand.c | 151 ++++++++++++----------------
src/util/vircommand.h | 18 +++-
src/util/vircommandpriv.h | 19 ++--
tests/networkxml2firewalltest.c | 7 +-
tests/nwfilterebiptablestest.c | 32 +++---
tests/nwfilterxml2firewalltest.c | 6 +-
tests/testutils.c | 210 +++++++++++++++++++++++++++++++++++++++
tests/testutils.h | 2 +
tests/virfirewalltest.c | 71 ++++++-------
tests/viriscsitest.c | 120 ++++++++++++++++------
tests/virkmodtest.c | 10 +-
tests/virnetdevbandwidthtest.c | 6 +-
15 files changed, 482 insertions(+), 215 deletions(-)
diff --git a/docs/internals/command.html.in b/docs/internals/command.html.in
index 43f51a4..44478f0 100644
--- a/docs/internals/command.html.in
+++ b/docs/internals/command.html.in
@@ -398,17 +398,40 @@ virCommandSetWorkingDirectory(cmd, LOCALSTATEDIR);
<h3><a id="hooks">Any additional hooks</a></h3>
<p>
- If anything else is needed, it is possible to request a hook
- function that is called in the child after the fork, as the
+ If anything else is needed, it is possible to request hook
+ functions that are called in the child after the fork, as the
last thing before changing directories, dropping capabilities,
- and executing the new process. If hook(opaque) returns
- non-zero, then the child process will not be run.
+ and executing the new process.
+
+ There are two types of hooks:
+ <ul>
+ <li>Global hook takes effect to all command.
+ Setting global hook if passing NULL to @cmd.
+ </li>
+ <li>Command hook takes effect only to the command.
+ Passing the pointer of the command to @cmd.
+ </li>
+ </ul>
+
+ If hook(opaque) returns -1, then the child process will not be
+ run for error. And if it returns 1, the child process will exit
+ with status in advance and this mode is used for command dryrun.
+
+ Since @hook runs in the child, it should be careful to avoid
+ any functions that are not async-signal-safe.
+
+ For global hook, Passing NULL for @cmd, @hook and @opaque to
+ cancel the effect.
</p>
<pre>
-virCommandSetPreExecHook(cmd, hook, opaque);
+virCommandSetPreExecHook(NULL, hook, opaque); /* global hook */
+virCommandSetPreExecHook(cmd, hook, opaque); /* command hook */
+
+virCommandSetPreExecHook(NULL, NULL, NULL); /* cancel global hook */
</pre>
+
<h3><a id="logging">Logging commands</a></h3>
<p>
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 47ea35f..f4aca6f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1602,7 +1602,10 @@ virCommandDaemonize;
virCommandDoAsyncIO;
virCommandExec;
virCommandFree;
+virCommandGetArgs;
+virCommandGetEnv;
virCommandGetGID;
+virCommandGetInputBuffer;
virCommandGetUID;
virCommandHandshakeNotify;
virCommandHandshakeWait;
@@ -1621,7 +1624,6 @@ virCommandRunAsync;
virCommandRunNul;
virCommandRunRegex;
virCommandSetAppArmorProfile;
-virCommandSetDryRun;
virCommandSetErrorBuffer;
virCommandSetErrorFD;
virCommandSetGID;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ab74938..f7a5dbd 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2656,7 +2656,9 @@ qemuProcessKillManagedPRDaemon(virDomainObjPtr vm)
static int
-qemuProcessStartPRDaemonHook(void *opaque)
+qemuProcessStartPRDaemonHook(void *opaque,
+ virCommandPtr ptr ATTRIBUTE_UNUSED,
+ int *status ATTRIBUTE_UNUSED)
{
virDomainObjPtr vm = opaque;
size_t i, nfds = 0;
@@ -2972,7 +2974,9 @@ struct qemuProcessHookData {
virQEMUDriverConfigPtr cfg;
};
-static int qemuProcessHook(void *data)
+static int qemuProcessHook(void *data,
+ virCommandPtr ptr ATTRIBUTE_UNUSED,
+ int *status ATTRIBUTE_UNUSED)
{
struct qemuProcessHookData *h = data;
qemuDomainObjPrivatePtr priv = h->vm->privateData;
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 8be3fdf..53aee7a 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -138,11 +138,9 @@ struct _virCommand {
int mask;
};
-/* See virCommandSetDryRun for description for this variable */
-static virBufferPtr dryRunBuffer;
-static virCommandDryRunCallback dryRunCallback;
-static void *dryRunOpaque;
-static int dryRunStatus;
+/* See virCommandSetPreExecHook for these variable */
+static virExecHook preExecHook;
+static void *preExecOpaque;
/*
* virCommandFDIsSet:
@@ -717,12 +715,32 @@ virExec(virCommandPtr cmd)
virProcessSetMaxCoreSize(0, cmd->maxCore) < 0)
goto fork_error;
+ if (preExecHook) {
+ int status = 0;
+ ret = preExecHook(preExecOpaque, cmd, &status);
+ if (ret < 0)
+ goto fork_error;
+
+ if (ret == 1) {
+ /* Child skips followed steps and exits with status in advance. */
+ ret = status;
+ goto fork_error;
+ }
+ }
+
if (cmd->hook) {
+ int status = 0;
VIR_DEBUG("Run hook %p %p", cmd->hook, cmd->opaque);
- ret = cmd->hook(cmd->opaque);
+ ret = cmd->hook(cmd->opaque, cmd, &status);
VIR_DEBUG("Done hook %d", ret);
if (ret < 0)
goto fork_error;
+
+ if (ret == 1) {
+ /* Child skips followed steps and exits with status in advance. */
+ ret = status;
+ goto fork_error;
+ }
}
# if defined(WITH_SECDRIVER_SELINUX)
@@ -1733,6 +1751,13 @@ virCommandSetInputBuffer(virCommandPtr cmd, const char *inbuf)
}
+const char *
+virCommandGetInputBuffer(virCommandPtr cmd)
+{
+ return (const char *) cmd->inbuf;
+}
+
+
/**
* virCommandSetOutputBuffer:
* @cmd: the command to modify
@@ -1879,7 +1904,9 @@ virCommandSetErrorFD(virCommandPtr cmd, int *errfd)
/**
* virCommandSetPreExecHook:
- * @cmd: the command to modify
+ * @cmd: the command pointer or NULL.
+ * NonNull, means that it registers a hook for the command
+ * Null, means that it registers the global PreExecHook
* @hook: the hook to run
* @opaque: argument to pass to the hook
*
@@ -1887,13 +1914,30 @@ virCommandSetErrorFD(virCommandPtr cmd, int *errfd)
* directories, dropping capabilities, and executing the new process.
* Force the child to fail if HOOK does not return zero.
*
+ * There are two types of hooks:
+ * 1. Global hook take effect to all command.
+ * Setting global hook if passing NULL to @cmd.
+ * 2. Command hook take effect only to the command.
+ * Passing the pointer of the command to @cmd.
+ *
* Since @hook runs in the child, it should be careful to avoid
* any functions that are not async-signal-safe.
+
+ * For global hook, Passing NULL for @cmd, @hook and @opaque to cancel
+ * the effect.
*/
void
virCommandSetPreExecHook(virCommandPtr cmd, virExecHook hook, void *opaque)
{
- if (!cmd || cmd->has_error)
+ if (!cmd) {
+ /* Global hook */
+ preExecHook = hook;
+ preExecOpaque = opaque;
+ return;
+ }
+
+ /* Command hook */
+ if (cmd->has_error)
return;
if (cmd->hook) {
@@ -2017,11 +2061,6 @@ virCommandProcessIO(virCommandPtr cmd)
size_t inoff = 0;
int ret = 0;
- if (dryRunBuffer || dryRunCallback) {
- VIR_DEBUG("Dry run requested, skipping I/O processing");
- return 0;
- }
-
/* With an input buffer, feed data to child
* via pipe */
if (cmd->inbuf)
@@ -2439,31 +2478,6 @@ virCommandRunAsync(virCommandPtr cmd, pid_t *pid)
goto cleanup;
}
- str = virCommandToString(cmd);
- if (dryRunBuffer || dryRunCallback) {
- dryRunStatus = 0;
- if (!str) {
- /* error already reported by virCommandToString */
- goto cleanup;
- }
-
- if (dryRunBuffer) {
- VIR_DEBUG("Dry run requested, appending stringified "
- "command to dryRunBuffer=%p", dryRunBuffer);
- virBufferAdd(dryRunBuffer, str, -1);
- virBufferAddChar(dryRunBuffer, '\n');
- }
- if (dryRunCallback) {
- dryRunCallback((const char *const*)cmd->args,
- (const char *const*)cmd->env,
- cmd->inbuf, cmd->outbuf, cmd->errbuf,
- &dryRunStatus, dryRunOpaque);
- }
- ret = 0;
- goto cleanup;
- }
-
- VIR_DEBUG("About to run %s", str ? str : cmd->args[0]);
ret = virExec(cmd);
VIR_DEBUG("Command result %d, with PID %d",
ret, (int)cmd->pid);
@@ -2537,16 +2551,6 @@ virCommandWait(virCommandPtr cmd, int *exitstatus)
return -1;
}
- if (dryRunBuffer || dryRunCallback) {
- VIR_DEBUG("Dry run requested, returning status %d",
- dryRunStatus);
- if (exitstatus)
- *exitstatus = dryRunStatus;
- else if (dryRunStatus)
- return -1;
- return 0;
- }
-
if (cmd->pid == -1) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("command is not yet running"));
@@ -2878,48 +2882,21 @@ virCommandDoAsyncIO(virCommandPtr cmd)
cmd->flags |= VIR_EXEC_ASYNC_IO | VIR_EXEC_NONBLOCK;
}
-/**
- * virCommandSetDryRun:
- * @buf: buffer to store stringified commands
- * @callback: callback to process input/output/args
- *
- * Sometimes it's desired to not actually run given command, but
- * see its string representation without having to change the
- * callee. Unit testing serves as a great example. In such cases,
- * the callee constructs the command and calls it via
- * virCommandRun* API. The virCommandSetDryRun allows you to
- * modify this behavior: once called, every call to
- * virCommandRun* results in command string representation being
- * appended to @buf instead of being executed. If @callback is
- * provided, then it is invoked with the argv, env and stdin
- * data string for the command. It is expected to fill the stdout
- * and stderr data strings and exit status variables.
- *
- * The strings stored in @buf are escaped for a shell and
- * separated by a newline. For example:
- *
- * virBuffer buffer = VIR_BUFFER_INITIALIZER;
- * virCommandSetDryRun(&buffer);
- *
- * virCommandPtr echocmd = virCommandNewArgList("/bin/echo", "Hello world", NULL);
- * virCommandRun(echocmd, NULL);
- *
- * After this, the @buffer should contain:
- *
- * /bin/echo 'Hello world'\n
- *
- * To cancel this effect pass NULL for @buf and @callback.
- */
-void
-virCommandSetDryRun(virBufferPtr buf,
- virCommandDryRunCallback cb,
- void *opaque)
+
+const char *const*
+virCommandGetArgs(virCommandPtr cmd)
+{
+ return (const char *const*) cmd->args;
+}
+
+
+const char *const*
+virCommandGetEnv(virCommandPtr cmd)
{
- dryRunBuffer = buf;
- dryRunCallback = cb;
- dryRunOpaque = opaque;
+ return (const char *const*) cmd->env;
}
+
#ifndef WIN32
/**
* virCommandRunRegex:
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index 90bcc6c..9f322d8 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -29,10 +29,22 @@
typedef struct _virCommand virCommand;
typedef virCommand *virCommandPtr;
-/* This will execute in the context of the first child
+/*
+ * virExecHook:
+ * @data: opaque for this hook
+ * @cmd: pointer to virCommand
+ * @status: get status for exit status of the child,
+ * valid only if return code is 1.
+ *
+ * This will execute in the context of the first child
* after fork() but before execve(). As such, it is unsafe to
- * call any function that is not async-signal-safe. */
-typedef int (*virExecHook)(void *data);
+ * call any function that is not async-signal-safe.
+ *
+ * Returns: 0 on success,
+ * -1 on usage error (errno is ENOMEM on OOM),
+ * 1 to notify child exit with status from child in advance
+ */
+typedef int (*virExecHook)(void *data, virCommandPtr cmd, int *status);
pid_t virFork(void) ATTRIBUTE_RETURN_CHECK;
diff --git a/src/util/vircommandpriv.h b/src/util/vircommandpriv.h
index 8930299..f2b6063 100644
--- a/src/util/vircommandpriv.h
+++ b/src/util/vircommandpriv.h
@@ -20,7 +20,7 @@
*/
#ifndef __VIR_COMMAND_PRIV_H_ALLOW__
-# error "vircommandpriv.h may only be included by vircommand.c or test suites"
+# error "vircommandpriv.h may only be included by vircommand.c or testutils.c"
#endif
#ifndef __VIR_COMMAND_PRIV_H__
@@ -28,16 +28,13 @@
# include "vircommand.h"
-typedef void (*virCommandDryRunCallback)(const char *const*args,
- const char *const*env,
- const char *input,
- char **output,
- char **error,
- int *status,
- void *opaque);
+const char *const*
+virCommandGetArgs(virCommandPtr cmd);
-void virCommandSetDryRun(virBufferPtr buf,
- virCommandDryRunCallback cb,
- void *opaque);
+const char *const*
+virCommandGetEnv(virCommandPtr cmd);
+
+const char *
+virCommandGetInputBuffer(virCommandPtr cmd);
#endif /* __VIR_COMMAND_PRIV_H__ */
diff --git a/tests/networkxml2firewalltest.c b/tests/networkxml2firewalltest.c
index 242b645..196c0b1 100644
--- a/tests/networkxml2firewalltest.c
+++ b/tests/networkxml2firewalltest.c
@@ -31,9 +31,6 @@
# define __VIR_FIREWALL_PRIV_H_ALLOW__
# include "virfirewallpriv.h"
-# define __VIR_COMMAND_PRIV_H_ALLOW__
-# include "vircommandpriv.h"
-
# define VIR_FROM_THIS VIR_FROM_NONE
static const char *abs_top_srcdir;
@@ -53,7 +50,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
virNetworkDefPtr def = NULL;
int ret = -1;
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (!(def = virNetworkDefParseFile(xml)))
goto cleanup;
@@ -66,7 +63,6 @@ static int testCompareXMLToArgvFiles(const char *xml,
actualargv = virBufferContentAndReset(&buf);
virTestClearCommandPath(actualargv);
- virCommandSetDryRun(NULL, NULL, NULL);
if (virTestCompareToFile(actualargv, cmdline) < 0)
goto cleanup;
@@ -74,6 +70,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
ret = 0;
cleanup:
+ virTestSetDryRun(NULL, NULL, NULL);
virBufferFreeAndReset(&buf);
VIR_FREE(expectargv);
VIR_FREE(actualargv);
diff --git a/tests/nwfilterebiptablestest.c b/tests/nwfilterebiptablestest.c
index 6073423..186349c 100644
--- a/tests/nwfilterebiptablestest.c
+++ b/tests/nwfilterebiptablestest.c
@@ -29,12 +29,8 @@
#define __VIR_FIREWALL_PRIV_H_ALLOW__
#include "virfirewallpriv.h"
-#define __VIR_COMMAND_PRIV_H_ALLOW__
-#include "vircommandpriv.h"
-
#define VIR_FROM_THIS VIR_FROM_NONE
-
#define VIR_NWFILTER_NEW_RULES_TEARDOWN \
"iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n" \
"iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FP-vnet0\n" \
@@ -104,7 +100,7 @@ testNWFilterEBIPTablesAllTeardown(const void *opaque ATTRIBUTE_UNUSED)
char *actual = NULL;
int ret = -1;
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (ebiptables_driver.allTeardown("vnet0") < 0)
goto cleanup;
@@ -122,7 +118,7 @@ testNWFilterEBIPTablesAllTeardown(const void *opaque ATTRIBUTE_UNUSED)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virBufferFreeAndReset(&buf);
VIR_FREE(actual);
return ret;
@@ -175,7 +171,7 @@ testNWFilterEBIPTablesTearOldRules(const void *opaque ATTRIBUTE_UNUSED)
char *actual = NULL;
int ret = -1;
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (ebiptables_driver.tearOldRules("vnet0") < 0)
goto cleanup;
@@ -193,7 +189,7 @@ testNWFilterEBIPTablesTearOldRules(const void *opaque ATTRIBUTE_UNUSED)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virBufferFreeAndReset(&buf);
VIR_FREE(actual);
return ret;
@@ -224,7 +220,7 @@ testNWFilterEBIPTablesRemoveBasicRules(const void *opaque ATTRIBUTE_UNUSED)
char *actual = NULL;
int ret = -1;
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (ebiptables_driver.removeBasicRules("vnet0") < 0)
goto cleanup;
@@ -242,7 +238,7 @@ testNWFilterEBIPTablesRemoveBasicRules(const void *opaque ATTRIBUTE_UNUSED)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virBufferFreeAndReset(&buf);
VIR_FREE(actual);
return ret;
@@ -258,7 +254,7 @@ testNWFilterEBIPTablesTearNewRules(const void *opaque ATTRIBUTE_UNUSED)
char *actual = NULL;
int ret = -1;
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (ebiptables_driver.tearNewRules("vnet0") < 0)
goto cleanup;
@@ -276,7 +272,7 @@ testNWFilterEBIPTablesTearNewRules(const void *opaque ATTRIBUTE_UNUSED)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virBufferFreeAndReset(&buf);
VIR_FREE(actual);
return ret;
@@ -330,7 +326,7 @@ testNWFilterEBIPTablesApplyBasicRules(const void *opaque ATTRIBUTE_UNUSED)
int ret = -1;
virMacAddr mac = { .addr = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 } };
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (ebiptables_driver.applyBasicRules("vnet0", &mac) < 0)
goto cleanup;
@@ -348,7 +344,7 @@ testNWFilterEBIPTablesApplyBasicRules(const void *opaque ATTRIBUTE_UNUSED)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virBufferFreeAndReset(&buf);
VIR_FREE(actual);
return ret;
@@ -420,7 +416,7 @@ testNWFilterEBIPTablesApplyDHCPOnlyRules(const void *opaque ATTRIBUTE_UNUSED)
}
};
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (ebiptables_driver.applyDHCPOnlyRules("vnet0", &mac, &val, false) < 0)
goto cleanup;
@@ -438,7 +434,7 @@ testNWFilterEBIPTablesApplyDHCPOnlyRules(const void *opaque ATTRIBUTE_UNUSED)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virBufferFreeAndReset(&buf);
VIR_FREE(actual);
return ret;
@@ -493,7 +489,7 @@ testNWFilterEBIPTablesApplyDropAllRules(const void *opaque ATTRIBUTE_UNUSED)
char *actual = NULL;
int ret = -1;
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (ebiptables_driver.applyDropAllRules("vnet0") < 0)
goto cleanup;
@@ -511,7 +507,7 @@ testNWFilterEBIPTablesApplyDropAllRules(const void *opaque ATTRIBUTE_UNUSED)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virBufferFreeAndReset(&buf);
VIR_FREE(actual);
return ret;
diff --git a/tests/nwfilterxml2firewalltest.c b/tests/nwfilterxml2firewalltest.c
index 043b7d1..6ae0ef7 100644
--- a/tests/nwfilterxml2firewalltest.c
+++ b/tests/nwfilterxml2firewalltest.c
@@ -30,8 +30,6 @@
# define __VIR_FIREWALL_PRIV_H_ALLOW__
# include "virfirewallpriv.h"
-# define __VIR_COMMAND_PRIV_H_ALLOW__
-# include "vircommandpriv.h"
# define VIR_FROM_THIS VIR_FROM_NONE
@@ -380,7 +378,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
memset(&inst, 0, sizeof(inst));
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (!vars)
goto cleanup;
@@ -401,7 +399,6 @@ static int testCompareXMLToArgvFiles(const char *xml,
actualargv = virBufferContentAndReset(&buf);
virTestClearCommandPath(actualargv);
- virCommandSetDryRun(NULL, NULL, NULL);
testRemoveCommonRules(actualargv);
@@ -411,6 +408,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
ret = 0;
cleanup:
+ virTestSetDryRun(NULL, NULL, NULL);
virBufferFreeAndReset(&buf);
VIR_FREE(actualargv);
virNWFilterInstReset(&inst);
diff --git a/tests/testutils.c b/tests/testutils.c
index ab938c1..01d9edc 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -48,6 +48,9 @@
#include "virprocess.h"
#include "virstring.h"
+#define __VIR_COMMAND_PRIV_H_ALLOW__
+#include "vircommandpriv.h"
+
#ifdef TEST_OOM
# ifdef TEST_OOM_TRACE
# include <dlfcn.h>
@@ -1414,3 +1417,210 @@ const char
return virtTestCounterStr;
}
+
+
+#define VIR_TEST_DRYRUN_PIPE "/tmp/vir_test_pipe"
+
+/* According to old virCommandDryRunCallback */
+typedef int (*dryRunCallback)(const char *const*args,
+ const char *const*env,
+ const char *input,
+ const void *opaque);
+
+typedef struct _dryRunHookData dryRunHookData;
+typedef dryRunHookData *dryRunHookDataPtr;
+
+struct _dryRunHookData
+{
+ dryRunCallback callback;
+ void *opaque;
+ virBufferPtr buffer;
+ virThreadPtr thread;
+ int readfd;
+};
+
+static dryRunHookData hookdata = { NULL, NULL, NULL, NULL, -1 };
+
+
+/* of virExecHook type */
+static int
+dryRunHookForTest(void *opaque, virCommandPtr cmd, int *status)
+{
+ dryRunHookDataPtr data = opaque;
+
+ virThreadCancel(data->thread);
+ virThreadJoin(data->thread);
+ VIR_FREE(data->thread);
+ if (data->readfd != -1)
+ VIR_FORCE_CLOSE(data->readfd);
+
+ if (!status)
+ return -1;
+
+ *status = 0;
+
+ if (data->buffer) {
+ int fd;
+ int len = 0;
+ int pos = 0;
+ VIR_AUTOFREE(char *) str = NULL;
+ str = virCommandToString(cmd);
+ if (!str)
+ return -1;
+
+ len = strlen(str);
+ if (len == 0)
+ return -1;
+
+ if ((fd = open(VIR_TEST_DRYRUN_PIPE, O_WRONLY)) < 0)
+ return -1;
+
+ while (len > 0) {
+ int size = len > PIPE_BUF ? PIPE_BUF : len;
+ if (safewrite(fd, str + pos, size) != size) {
+ VIR_FORCE_CLOSE(fd);
+ return -1;
+ }
+ pos += size;
+ len -= size;
+ }
+
+ if (safewrite(fd, "\n", 1) != 1) {
+ VIR_FORCE_CLOSE(fd);
+ return -1;
+ }
+
+ VIR_FORCE_CLOSE(fd);
+ }
+
+ if (data->callback) {
+ *status = data->callback(virCommandGetArgs(cmd),
+ virCommandGetEnv(cmd),
+ virCommandGetInputBuffer(cmd),
+ data->opaque);
+ }
+
+ /* For dry-run:
+ * It returns 1 to exit from child in advance */
+ return 1;
+}
+
+
+static void
+dryRunWaitHelper(void *opaque)
+{
+ int *fd = (int *) opaque;
+ while (true) {
+ if ((*fd = open(VIR_TEST_DRYRUN_PIPE, O_RDONLY)) < 0) {
+ fprintf(stderr, "cannot open dryrun pipe for read\n");
+ return;
+ }
+
+ while (true) {
+ int ret;
+ char str[PIPE_BUF];
+ memset(str, 0, sizeof(str));
+ ret = read(*fd, str, PIPE_BUF);
+ if (ret < 0) {
+ fprintf(stderr, "read dryrun pipe error: %d\n", errno);
+ VIR_FORCE_CLOSE(*fd);
+ return;
+ }
+
+ if (ret == 0)
+ break;
+
+ virBufferAdd(hookdata.buffer, str, ret);
+ }
+
+ VIR_FORCE_CLOSE(*fd);
+ }
+
+ /* Never reach here */
+}
+
+
+/**
+ * virTestSetDryRun: (substitute for old virCommandSetDryRun)
+ * @buf: buffer to store stringified commands
+ * @callback: callback to process input/output/args
+ * @opaque: argument passed to callback
+ *
+ * In unit testing, it's desired to not actually run given command,
+ * but see its string representation without having to change the
+ * callee. The callee constructs the command and calls it via
+ * virCommandRun* API. The virTestSetDryRun allows you to
+ * modify this behavior: once called, every call to
+ * virCommandRun* results in command string representation being
+ * appended to @buf instead of being executed. If @callback is
+ * provided, then it is invoked with the argv, env and stdin
+ * data string for the command. It is expected to fill the stdout
+ * and stderr data strings and exit status variables.
+ *
+ * The strings stored in @buf are escaped for a shell and
+ * separated by a newline. For example:
+ *
+ * virBuffer buffer = VIR_BUFFER_INITIALIZER;
+ * virTestSetDryRun(&buffer, NULL, NULL);
+ *
+ * virCommandPtr echocmd = virCommandNewArgList("/bin/echo", "Hello world", NULL);
+ * virCommandRun(echocmd, NULL);
+ *
+ * After this, the @buffer should contain:
+ *
+ * /bin/echo 'Hello world'\n
+ *
+ * To cancel this effect pass NULL for @buf, @callback and @opaque.
+ * virTestSetDryRun(NULL, NULL, NULL);
+ *
+ */
+void
+virTestSetDryRun(virBufferPtr buf, void *callback, void *opaque)
+{
+ if (!buf && !callback && !opaque) {
+ /* Passing NULL for @buf, @callback and @opaque to cancel dry-run */
+ if (hookdata.thread) {
+ virThreadCancel(hookdata.thread);
+ virThreadJoin(hookdata.thread);
+ VIR_FREE(hookdata.thread);
+ }
+
+ hookdata.buffer = NULL;
+ hookdata.callback = NULL;
+ hookdata.opaque = NULL;
+ if (hookdata.readfd != -1)
+ VIR_FORCE_CLOSE(hookdata.readfd);
+
+ virCommandSetPreExecHook(NULL, NULL, NULL);
+ unlink(VIR_TEST_DRYRUN_PIPE);
+ return;
+ }
+
+ if (hookdata.buffer || hookdata.callback || hookdata.opaque || hookdata.thread) {
+ fprintf(stderr, "cannot set dryrun twice buf(%p) cb(%p) opaque(%p) thread(%p)\n",
+ hookdata.buffer, hookdata.callback, hookdata.opaque, hookdata.thread);
+ return;
+ }
+
+ if (hookdata.readfd != -1)
+ VIR_FORCE_CLOSE(hookdata.readfd);
+
+ if (!virFileExists(VIR_TEST_DRYRUN_PIPE)) {
+ if (mkfifo(VIR_TEST_DRYRUN_PIPE, 0600) < 0) {
+ fprintf(stderr, "cannot create dryrun pipe. err: %d\n", errno);
+ return;
+ }
+ }
+
+ if (VIR_ALLOC(hookdata.thread) < 0 ||
+ virThreadCreate(hookdata.thread, true, dryRunWaitHelper, &hookdata.readfd) < 0) {
+ fprintf(stderr, "cannot create thread for dryrun. err: %d\n", errno);
+ VIR_FREE(hookdata.thread);
+ return;
+ }
+
+ hookdata.buffer = buf;
+ hookdata.callback = callback;
+ hookdata.opaque = opaque;
+ virCommandSetPreExecHook(NULL, dryRunHookForTest, &hookdata);
+}
diff --git a/tests/testutils.h b/tests/testutils.h
index 3bd7bf1..82bfa0a 100644
--- a/tests/testutils.h
+++ b/tests/testutils.h
@@ -167,4 +167,6 @@ int testCompareDomXML2XMLFiles(virCapsPtr caps,
unsigned int parseFlags,
testCompareDomXML2XMLResult expectResult);
+void virTestSetDryRun(virBufferPtr buf, void *callback, void *opaque);
+
#endif /* __VIR_TEST_UTILS_H__ */
diff --git a/tests/virfirewalltest.c b/tests/virfirewalltest.c
index e6d6874..1bf41c7 100644
--- a/tests/virfirewalltest.c
+++ b/tests/virfirewalltest.c
@@ -21,14 +21,12 @@
#include <config.h>
#define __VIR_FIREWALL_PRIV_H_ALLOW__
-#define __VIR_COMMAND_PRIV_H_ALLOW__
#include "testutils.h"
#if defined(__linux__)
# include "virbuffer.h"
-# include "vircommandpriv.h"
# include "virfirewallpriv.h"
# include "virmock.h"
# include "virdbuspriv.h"
@@ -213,7 +211,7 @@ testFirewallSingleGroup(const void *opaque)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT)
- virCommandSetDryRun(&cmdbuf, NULL, NULL);
+ virTestSetDryRun(&cmdbuf, NULL, NULL);
else
fwBuf = &cmdbuf;
@@ -249,7 +247,7 @@ testFirewallSingleGroup(const void *opaque)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
@@ -273,7 +271,7 @@ testFirewallRemoveRule(const void *opaque)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT)
- virCommandSetDryRun(&cmdbuf, NULL, NULL);
+ virTestSetDryRun(&cmdbuf, NULL, NULL);
else
fwBuf = &cmdbuf;
@@ -315,7 +313,7 @@ testFirewallRemoveRule(const void *opaque)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
@@ -340,7 +338,7 @@ testFirewallManyGroups(const void *opaque ATTRIBUTE_UNUSED)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT)
- virCommandSetDryRun(&cmdbuf, NULL, NULL);
+ virTestSetDryRun(&cmdbuf, NULL, NULL);
else
fwBuf = &cmdbuf;
@@ -388,19 +386,16 @@ testFirewallManyGroups(const void *opaque ATTRIBUTE_UNUSED)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
-static void
+static int
testFirewallRollbackHook(const char *const*args,
const char *const*env ATTRIBUTE_UNUSED,
const char *input ATTRIBUTE_UNUSED,
- char **output ATTRIBUTE_UNUSED,
- char **error ATTRIBUTE_UNUSED,
- int *status,
- void *opaque ATTRIBUTE_UNUSED)
+ const void *opaque ATTRIBUTE_UNUSED)
{
bool isAdd = false;
while (*args) {
@@ -408,11 +403,11 @@ testFirewallRollbackHook(const char *const*args,
if (STREQ(*args, "-A")) {
isAdd = true;
} else if (isAdd && STREQ(*args, "192.168.122.255")) {
- *status = 127;
- break;
+ return 127;
}
args++;
}
+ return 0;
}
static int
@@ -434,7 +429,7 @@ testFirewallIgnoreFailGroup(const void *opaque ATTRIBUTE_UNUSED)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
- virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
+ virTestSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
} else {
fwBuf = &cmdbuf;
fwError = true;
@@ -484,7 +479,7 @@ testFirewallIgnoreFailGroup(const void *opaque ATTRIBUTE_UNUSED)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
@@ -509,7 +504,7 @@ testFirewallIgnoreFailRule(const void *opaque ATTRIBUTE_UNUSED)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
- virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
+ virTestSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
} else {
fwBuf = &cmdbuf;
fwError = true;
@@ -558,7 +553,7 @@ testFirewallIgnoreFailRule(const void *opaque ATTRIBUTE_UNUSED)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
@@ -581,7 +576,7 @@ testFirewallNoRollback(const void *opaque ATTRIBUTE_UNUSED)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
- virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
+ virTestSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
} else {
fwBuf = &cmdbuf;
fwError = true;
@@ -629,7 +624,7 @@ testFirewallNoRollback(const void *opaque ATTRIBUTE_UNUSED)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
@@ -654,7 +649,7 @@ testFirewallSingleRollback(const void *opaque ATTRIBUTE_UNUSED)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
- virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
+ virTestSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
} else {
fwError = true;
fwBuf = &cmdbuf;
@@ -719,7 +714,7 @@ testFirewallSingleRollback(const void *opaque ATTRIBUTE_UNUSED)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
@@ -743,7 +738,7 @@ testFirewallManyRollback(const void *opaque ATTRIBUTE_UNUSED)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
- virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
+ virTestSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
} else {
fwBuf = &cmdbuf;
fwError = true;
@@ -812,7 +807,7 @@ testFirewallManyRollback(const void *opaque ATTRIBUTE_UNUSED)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
@@ -840,7 +835,7 @@ testFirewallChainedRollback(const void *opaque ATTRIBUTE_UNUSED)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
- virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
+ virTestSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
} else {
fwBuf = &cmdbuf;
fwError = true;
@@ -935,7 +930,7 @@ testFirewallChainedRollback(const void *opaque ATTRIBUTE_UNUSED)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
@@ -967,26 +962,26 @@ static const char *expectedLines[] = {
static size_t expectedLineNum;
static bool expectedLineError;
-static void
+static int
testFirewallQueryHook(const char *const*args,
const char *const*env ATTRIBUTE_UNUSED,
const char *input ATTRIBUTE_UNUSED,
- char **output,
- char **error ATTRIBUTE_UNUSED,
- int *status,
- void *opaque ATTRIBUTE_UNUSED)
+ const void *opaque ATTRIBUTE_UNUSED)
{
if (STREQ(args[0], IPTABLES_PATH) &&
STREQ(args[1], "-L")) {
- if (VIR_STRDUP(*output, TEST_FILTER_TABLE_LIST) < 0)
- *status = 127;
+ if (safewrite(STDOUT_FILENO, TEST_FILTER_TABLE_LIST,
+ strlen(TEST_FILTER_TABLE_LIST)) < 0)
+ return 127;
} else if (STREQ(args[0], IPTABLES_PATH) &&
STREQ(args[1], "-t") &&
STREQ(args[2], "nat") &&
STREQ(args[3], "-L")) {
- if (VIR_STRDUP(*output, TEST_NAT_TABLE_LIST) < 0)
- *status = 127;
+ if (safewrite(STDOUT_FILENO, TEST_NAT_TABLE_LIST,
+ strlen(TEST_NAT_TABLE_LIST)) < 0)
+ return 127;
}
+ return 0;
}
@@ -1044,7 +1039,7 @@ testFirewallQuery(const void *opaque ATTRIBUTE_UNUSED)
goto cleanup;
if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
- virCommandSetDryRun(&cmdbuf, testFirewallQueryHook, NULL);
+ virTestSetDryRun(&cmdbuf, testFirewallQueryHook, NULL);
} else {
fwBuf = &cmdbuf;
fwError = true;
@@ -1118,7 +1113,7 @@ testFirewallQuery(const void *opaque ATTRIBUTE_UNUSED)
cleanup:
virBufferFreeAndReset(&cmdbuf);
fwBuf = NULL;
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virFirewallFree(fw);
return ret;
}
diff --git a/tests/viriscsitest.c b/tests/viriscsitest.c
index 4fd7ff6..11a2a54 100644
--- a/tests/viriscsitest.c
+++ b/tests/viriscsitest.c
@@ -19,6 +19,7 @@
*/
#include <config.h>
+#include <fcntl.h>
#include "testutils.h"
@@ -29,9 +30,6 @@ main(void)
return EXIT_AM_SKIP;
}
#else
-# define __VIR_COMMAND_PRIV_H_ALLOW__
-
-# include "vircommandpriv.h"
# include "viriscsi.h"
# define VIR_FROM_THIS VIR_FROM_NONE
@@ -72,27 +70,40 @@ const char *iscsiadmIfaceIfaceOutput =
struct testIscsiadmCbData {
bool output_version;
- bool iface_created;
+ char *result_path;
};
-static void testIscsiadmCb(const char *const*args,
- const char *const*env ATTRIBUTE_UNUSED,
- const char *input ATTRIBUTE_UNUSED,
- char **output,
- char **error ATTRIBUTE_UNUSED,
- int *status,
- void *opaque)
+static int testIscsiadmCb(const char *const*args,
+ const char *const*env ATTRIBUTE_UNUSED,
+ const char *input ATTRIBUTE_UNUSED,
+ const void *opaque)
{
- struct testIscsiadmCbData *data = opaque;
+ int fd;
+ int iface_created = 0;
+ const struct testIscsiadmCbData *data = opaque;
+
+ if (data) {
+ fd = open(data->result_path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ if (read(fd, &iface_created, sizeof(int)) != sizeof(int)) {
+ VIR_FORCE_CLOSE(fd);
+ return -1;
+ }
+ VIR_FORCE_CLOSE(fd);
+ }
if (args[0] && STREQ(args[0], ISCSIADM) &&
args[1] && STREQ(args[1], "--mode") &&
args[2] && STREQ(args[2], "session") &&
args[3] == NULL) {
if (data->output_version)
- ignore_value(VIR_STRDUP(*output, iscsiadmSessionOutputNonFlash));
+ ignore_value(safewrite(STDOUT_FILENO, iscsiadmSessionOutputNonFlash,
+ strlen(iscsiadmSessionOutputNonFlash)));
else
- ignore_value(VIR_STRDUP(*output, iscsiadmSessionOutput));
+ ignore_value(safewrite(STDOUT_FILENO, iscsiadmSessionOutput,
+ strlen(iscsiadmSessionOutput)));
} else if (args[0] && STREQ(args[0], ISCSIADM) &&
args[1] && STREQ(args[1], "--mode") &&
args[2] && STREQ(args[2], "discovery") &&
@@ -103,7 +114,8 @@ static void testIscsiadmCb(const char *const*args,
args[7] && STREQ(args[7], "--op") &&
args[8] && STREQ(args[8], "nonpersistent") &&
args[9] == NULL) {
- ignore_value(VIR_STRDUP(*output, iscsiadmSendtargetsOutput));
+ ignore_value(safewrite(STDOUT_FILENO, iscsiadmSendtargetsOutput,
+ strlen(iscsiadmSendtargetsOutput)));
} else if (args[0] && STREQ(args[0], ISCSIADM) &&
args[1] && STREQ(args[1], "--mode") &&
args[2] && STREQ(args[2], "node") &&
@@ -127,10 +139,12 @@ static void testIscsiadmCb(const char *const*args,
args[1] && STREQ(args[1], "--mode") &&
args[2] && STREQ(args[2], "iface") &&
args[3] == NULL) {
- if (data->iface_created)
- ignore_value(VIR_STRDUP(*output, iscsiadmIfaceIfaceOutput));
+ if (iface_created)
+ ignore_value(safewrite(STDOUT_FILENO, iscsiadmIfaceIfaceOutput,
+ strlen(iscsiadmIfaceIfaceOutput)));
else
- ignore_value(VIR_STRDUP(*output, iscsiadmIfaceDefaultOutput));
+ ignore_value(safewrite(STDOUT_FILENO, iscsiadmIfaceDefaultOutput,
+ strlen(iscsiadmIfaceDefaultOutput)));
} else if (args[0] && STREQ(args[0], ISCSIADM) &&
args[1] && STREQ(args[1], "--mode") &&
args[2] && STREQ(args[2], "iface") &&
@@ -144,7 +158,18 @@ static void testIscsiadmCb(const char *const*args,
*
* New interface libvirt-iface-03020100 added
*/
- data->iface_created = true;
+ if (data) {
+ iface_created = 1;
+ fd = open(data->result_path, O_WRONLY);
+ if (fd < 0)
+ return -1;
+
+ if (safewrite(fd, &iface_created, sizeof(int)) != sizeof(int)) {
+ VIR_FORCE_CLOSE(fd);
+ return -1;
+ }
+ VIR_FORCE_CLOSE(fd);
+ }
} else if (args[0] && STREQ(args[0], ISCSIADM) &&
args[1] && STREQ(args[1], "--mode") &&
args[2] && STREQ(args[2], "iface") &&
@@ -157,7 +182,7 @@ static void testIscsiadmCb(const char *const*args,
args[9] && STREQ(args[9], "--value") &&
args[10] && STREQ(args[10], "iqn.2004-06.example:example1:initiator") &&
args[11] == NULL &&
- data->iface_created) {
+ iface_created) {
/* Mocking real environment output is not needed for now.
* Example output from real environment:
*
@@ -173,8 +198,9 @@ static void testIscsiadmCb(const char *const*args,
args[7] && STREQ(args[7], "--interface") &&
args[8] && STREQ(args[8], "libvirt-iface-03020100") &&
args[9] == NULL &&
- data->iface_created) {
- ignore_value(VIR_STRDUP(*output, iscsiadmSendtargetsOutput));
+ iface_created) {
+ ignore_value(safewrite(STDOUT_FILENO, iscsiadmSendtargetsOutput,
+ strlen(iscsiadmSendtargetsOutput)));
} else if (args[0] && STREQ(args[0], ISCSIADM) &&
args[1] && STREQ(args[1], "--mode") &&
args[2] && STREQ(args[2], "node") &&
@@ -186,7 +212,7 @@ static void testIscsiadmCb(const char *const*args,
args[8] && STREQ(args[8], "--interface") &&
args[9] && STREQ(args[9], "libvirt-iface-03020100") &&
args[10] == NULL &&
- data->iface_created) {
+ iface_created) {
/* Mocking real environment output is not needed for now.
* Example output from real environment:
*
@@ -198,10 +224,31 @@ static void testIscsiadmCb(const char *const*args,
* portal: 10.20.30.40:3260,1] successful.
*/
} else {
- *status = -1;
+ return -1;
}
+ return 0;
}
+
+static int
+testCreateTempFile(char *path)
+{
+ int iface_created = 0;
+ int fd = -1;
+ if ((fd = mkostemp(path, O_RDWR)) < 0)
+ return -1;
+
+ if (safewrite(fd, &iface_created, sizeof(int)) != sizeof(int)) {
+ VIR_FORCE_CLOSE(fd);
+ unlink(path);
+ return -1;
+ }
+
+ VIR_FORCE_CLOSE(fd);
+ return 0;
+}
+
+
struct testSessionInfo {
const char *device_path;
bool output_version;
@@ -215,10 +262,15 @@ testISCSIGetSession(const void *data)
struct testIscsiadmCbData cbData = { 0 };
char *actual_session = NULL;
int ret = -1;
+ char path[] = "/dev/shm/testiscsi.XXXXXX";
+ if (testCreateTempFile(path) < 0)
+ return -1;
+
+ cbData.result_path = path;
cbData.output_version = info->output_version;
- virCommandSetDryRun(NULL, testIscsiadmCb, &cbData);
+ virTestSetDryRun(NULL, testIscsiadmCb, &cbData);
actual_session = virISCSIGetSession(info->device_path, true);
@@ -233,7 +285,8 @@ testISCSIGetSession(const void *data)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
+ unlink(path);
VIR_FREE(actual_session);
return ret;
}
@@ -254,7 +307,7 @@ testISCSIScanTargets(const void *data)
int ret = -1;
size_t i;
- virCommandSetDryRun(NULL, testIscsiadmCb, NULL);
+ virTestSetDryRun(NULL, testIscsiadmCb, NULL);
if (virISCSIScanTargets(info->portal, NULL,
false, &ntargets, &targets) < 0)
@@ -279,7 +332,7 @@ testISCSIScanTargets(const void *data)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
for (i = 0; i < ntargets; i++)
VIR_FREE(targets[i]);
VIR_FREE(targets);
@@ -300,15 +353,21 @@ testISCSIConnectionLogin(const void *data)
const struct testConnectionInfoLogin *info = data;
struct testIscsiadmCbData cbData = { 0 };
int ret = -1;
+ char path[] = "/dev/shm/testiscsi.XXXXXX";
+
+ if (testCreateTempFile(path) < 0)
+ return -1;
- virCommandSetDryRun(NULL, testIscsiadmCb, &cbData);
+ cbData.result_path = path;
+ virTestSetDryRun(NULL, testIscsiadmCb, &cbData);
if (virISCSIConnectionLogin(info->portal, info->initiatoriqn, info->target) < 0)
goto cleanup;
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
+ unlink(path);
return ret;
}
@@ -362,7 +421,6 @@ mymain(void)
DO_LOGIN_TEST("10.20.30.40:3260,1", NULL, "iqn.2004-06.example:example1:iscsi.test");
DO_LOGIN_TEST("10.20.30.40:3260,1", "iqn.2004-06.example:example1:initiator",
"iqn.2004-06.example:example1:iscsi.test");
-
if (rv < 0)
return EXIT_FAILURE;
return EXIT_SUCCESS;
diff --git a/tests/virkmodtest.c b/tests/virkmodtest.c
index b153e07..408e338 100644
--- a/tests/virkmodtest.c
+++ b/tests/virkmodtest.c
@@ -23,8 +23,6 @@
#ifdef __linux__
# include <stdlib.h>
-# define __VIR_COMMAND_PRIV_H_ALLOW__
-# include "vircommandpriv.h"
# include "virkmod.h"
# include "virstring.h"
@@ -96,7 +94,7 @@ testKModLoad(const void *args)
bool useBlacklist = info->useBlacklist;
virBuffer buf = VIR_BUFFER_INITIALIZER;
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
errbuf = virKModLoad(module, useBlacklist);
if (errbuf) {
@@ -110,7 +108,7 @@ testKModLoad(const void *args)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
VIR_FREE(errbuf);
return ret;
}
@@ -125,7 +123,7 @@ testKModUnload(const void *args)
const char *module = info->module;
virBuffer buf = VIR_BUFFER_INITIALIZER;
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
errbuf = virKModUnload(module);
if (errbuf) {
@@ -139,7 +137,7 @@ testKModUnload(const void *args)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
VIR_FREE(errbuf);
return ret;
}
diff --git a/tests/virnetdevbandwidthtest.c b/tests/virnetdevbandwidthtest.c
index 72bfeff..62cb044 100644
--- a/tests/virnetdevbandwidthtest.c
+++ b/tests/virnetdevbandwidthtest.c
@@ -21,8 +21,6 @@
#include <config.h>
#include "testutils.h"
-#define __VIR_COMMAND_PRIV_H_ALLOW__
-#include "vircommandpriv.h"
#include "virnetdevbandwidth.h"
#include "netdev_bandwidth_conf.c"
@@ -79,7 +77,7 @@ testVirNetDevBandwidthSet(const void *data)
if (!iface)
iface = "eth0";
- virCommandSetDryRun(&buf, NULL, NULL);
+ virTestSetDryRun(&buf, NULL, NULL);
if (virNetDevBandwidthSet(iface, band, info->hierarchical_class, true) < 0)
goto cleanup;
@@ -103,7 +101,7 @@ testVirNetDevBandwidthSet(const void *data)
ret = 0;
cleanup:
- virCommandSetDryRun(NULL, NULL, NULL);
+ virTestSetDryRun(NULL, NULL, NULL);
virNetDevBandwidthFree(band);
virBufferFreeAndReset(&buf);
VIR_FREE(actual_cmd);
--
2.7.4
6 years, 3 months
[libvirt] [PATCH] qemu: fix error message on directory creation
by Eric Blake
Minor copy-and-paste bug present since commit 462c74c3, in Apr 2010.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing this under the trivial rule.
src/qemu/qemu_driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 21e9e87ddd..da8c4e8991 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -656,7 +656,7 @@ qemuStateInitialize(bool privileged,
goto error;
}
if (virFileMakePath(cfg->snapshotDir) < 0) {
- virReportSystemError(errno, _("Failed to create save dir %s"),
+ virReportSystemError(errno, _("Failed to create snapshot dir %s"),
cfg->snapshotDir);
goto error;
}
--
2.17.1
6 years, 3 months
[libvirt] [PATCH 0/3] qemu: Fix few issues from the -blockdev series
by Peter Krempa
All three should appease coverity.
Peter Krempa (3):
qemu: hotplug: Don't generate alias when detaching controllers
qemu: hotplug: Don't leak 'nodename' in qemuDomainChangeMediaBlockdev
qemu: monitor: Fix device matching in
qemuMonitorJSONBlockIoThrottleInfo
src/qemu/qemu_hotplug.c | 6 +-----
src/qemu/qemu_monitor_json.c | 4 ++--
2 files changed, 3 insertions(+), 7 deletions(-)
--
2.16.2
6 years, 3 months
[libvirt] [PATCHv2 00/62] qemu: Add support for -blockdev
by Peter Krempa
In this version everything except blockjobs should work properly.
Similarly to the previous posting, the block job support is not part of
this posting yet so blockjobs will not work.
Changes to v1:
- Added support for floppies via -device so they work with blockdev
- fixed return value from the new media changing API
- fixed handling of the TRAY_MOVED and BLOCK_IO_ERROR events
- fixed two compilation problems with nitpicky compilers
- refactored/fixed setup of backing chain for disk media change
- fixed two regressions when filling stats hash tables without -blockdev
- fixed alias reported in the TRAY_MOVED event to the users
- added helper to retrieve a disk definition from a VM by alias or QOM path
Note that the bump of the capability data needs to be fixed since
jansson support was reverted.
For the quirks of specifying floppies via -device please refer to commit
30/62 qemu: command: Setup floppy drives via -device for blockdev
Peter Krempa (62):
qemu: process: Fix alias for disk-tray-moved event
tests: qemumonitorjson: Simplify debugging of 'blockInfo' test
qemu: Improve errors in qemuDomainBlockResize
qemu: monitor: Remove unsupported function check for 'block_resize'
qemu: monitor: Remove useless 'locked' property from struct
qemuDomainDiskInfo
tests: qemucapabilities: Update capability data for qemu 3.0.0
Revert "qemu: monitor: Add the 'query-nodes' argument for
query-blockstats"
qemu: hotplug: consolidate media change code paths
qemu: hotplug: Prepare disk source in qemuDomainAttachDeviceDiskLive
qemu: monitor: Reuse qemuMonitorJSONQueryBlock in
qemuMonitorJSONBlockIoThrottleInfo
qemu: monitor: Allow using 'id' instead of 'device' for
'block_set_io_throttle'
qemu: monitor: Allow using 'qdev' instead of 'device' for getting disk
throttling
qemu: monitor: Add 'nodename' argument for 'block_resize'
tests: qemu: Drop disk from hostdev-mdev tests
tests: qemuxml2argv: Fork CAPS_LATEST test cases for 'blockdev'
tests: qemu: Add test data for backing chains and indexes
qemu: hotplug: Don't generate alias when detaching disk
util: virqemu: Simplify debugging if building QOM object with missing
args
qemu: caps: Add capability for using the blockdev infrastructure
qemu: process: clear QEMU_CAPS_BLOCKDEV for VMs with SD card
qemu: domain: Don't redetect backing chain when using -blockdev
qemu: process: Don't detect nodenames when we support -blockdev
conf: domain: Format out user provided backing chains in XML
qemu: domain: Add infrastructure to generate block node names
conf: Implement private data formatting and parsing for disks
conf: Allow formatting and parsing of 'index' for disk source image
qemu: Use proper backingIndex when reporting stats for backing chain
qemu: Add field to store QDEV path of a disk in private data
qemu: alias: Generate QDEV name of the block backend for disks
qemu: command: Setup floppy drives via -device for blockdev
qemu: domain: Add field for storing node name for copy-on-read
qemu: proces: assign node names for user defined backing chains
qemu: block: Add generator for the 'copy-on-read' blockdev driver
qemu: domain: Prepare qemuDomainDiskGetBackendAlias for -blockdev
qemu: command: format disk source commandline for -blockdev
qemu: command: Add helper to check if disk throttling is enabled
qemu: process: Setup disk io throttling for -blockdev
qemu: driver: Use QOM backend name for disk IO throttling APIs
qemu: driver: Prepare qemuDomainBlockResize for blockdev
qemu: process: Add lookup via QOM id to
qemuProcessFindDomainDiskByAlias
qemu: monitor: Handle TRAY_MOVED event correctly with -blockdev
qemu: monitor: Handle BLOCK_IO_ERROR event properly with -blockdev
qemu: hotplug: Prepare for blockdev-add/blockdev-del with backing
chains
qemu: monitor: Add APIs for cdrom tray handling for -blockdev
qemu: hotplug: Implement removable media change for -blockdev
qemu: driver: Don't copy disk alias in qemuDomainBlocksStatsGather
qemu: Explicitly find disks for stats totals
qemu: monitor: Retrieve blockstats also by qdev and node-names
qemu: monitor: Add APIs for refreshing disk capacity when using
-blockdev
qemu: driver: Don't pass 'virDomainDiskDefPtr' to
qemuDomainGetStatsOneBlock
qemu: monitor: Extract 'write-threshold' automatically for -blockdev
qemu: Extract exporting of disk block statistics
qemu: Extract exporting of the header for block stats
qemu: Export stats relevant for the frontend separately
qemu: Refactor control flow in qemuDomainGetStatsBlockExportDisk
qemu: Report frontend stats only for the frontend entry
qemu: Export stats relevant for the storage backend
qemu: monitor: Report data also for 'qdev' entry in
qemuMonitorJSONGetBlockInfo
qemu: Use QOM path with query-block when using -blockdev
qemu: driver: Allow using blockdev with qemuDomainBlocksStatsGather
qemu: driver: Prepare qemuDomainGetStatsBlock (bulk disk stats) for
-blockdev
DO NOT APPLY: Enable QEMU_CAPS_BLOCKDEV if 'query-blockstats' works
with -blockdev
docs/formatdomain.html.in | 7 +-
docs/schemas/domaincommon.rng | 19 +
src/conf/domain_conf.c | 89 +++-
src/conf/domain_conf.h | 7 +
src/qemu/qemu_alias.c | 86 ++-
src/qemu/qemu_alias.h | 3 +-
src/qemu/qemu_block.c | 24 +-
src/qemu/qemu_block.h | 2 +
src/qemu/qemu_capabilities.c | 2 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 134 ++++-
src/qemu/qemu_command.h | 3 +
src/qemu/qemu_domain.c | 174 +++++-
src/qemu/qemu_domain.h | 10 +-
src/qemu/qemu_driver.c | 442 ++++++++++-----
src/qemu/qemu_hotplug.c | 208 ++++++--
src/qemu/qemu_hotplug.h | 9 +-
src/qemu/qemu_monitor.c | 104 +++-
src/qemu/qemu_monitor.h | 37 +-
src/qemu/qemu_monitor_json.c | 411 +++++++++++---
src/qemu/qemu_monitor_json.h | 33 +-
src/qemu/qemu_process.c | 138 ++++-
src/qemu/qemu_process.h | 5 +-
src/util/virqemu.c | 5 +-
.../qemucapabilitiesdata/caps_3.0.0.x86_64.replies | 591 +++------------------
tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml | 9 +-
tests/qemuhotplugtest.c | 2 +-
tests/qemumonitorjsontest.c | 34 +-
tests/qemustatusxml2xmldata/modern-in.xml | 6 +
tests/qemuxml2argvdata/disk-aio.x86_64-2.12.0.args | 37 ++
tests/qemuxml2argvdata/disk-aio.x86_64-latest.args | 19 +-
.../disk-backing-chains-index.x86_64-2.12.0.args | 1 +
.../disk-backing-chains-index.x86_64-latest.args | 1 +
.../qemuxml2argvdata/disk-backing-chains-index.xml | 145 +++++
.../disk-backing-chains-noindex.x86_64-2.12.0.args | 58 ++
.../disk-backing-chains-noindex.x86_64-latest.args | 163 ++++++
.../disk-backing-chains-noindex.xml | 145 +++++
.../qemuxml2argvdata/disk-cache.x86_64-2.12.0.args | 50 ++
.../qemuxml2argvdata/disk-cache.x86_64-latest.args | 50 +-
.../disk-cdrom-network.x86_64-2.12.0.args | 41 ++
.../disk-cdrom-network.x86_64-latest.args | 32 +-
.../disk-cdrom-tray.x86_64-2.12.0.args | 39 ++
.../disk-cdrom-tray.x86_64-latest.args | 24 +-
.../qemuxml2argvdata/disk-cdrom.x86_64-2.12.0.args | 35 ++
.../qemuxml2argvdata/disk-cdrom.x86_64-latest.args | 17 +-
.../disk-copy_on_read.x86_64-2.12.0.args | 41 ++
.../disk-copy_on_read.x86_64-latest.args | 19 +-
.../disk-detect-zeroes.x86_64-2.12.0.args | 37 ++
.../disk-detect-zeroes.x86_64-latest.args | 17 +-
.../disk-error-policy.x86_64-2.12.0.args | 41 ++
.../disk-error-policy.x86_64-latest.args | 30 +-
.../disk-floppy-q35-2_11.x86_64-2.12.0.args | 35 ++
.../disk-floppy-q35-2_11.x86_64-latest.args | 14 +-
.../disk-floppy-q35-2_9.x86_64-2.12.0.args | 35 ++
.../disk-floppy-q35-2_9.x86_64-latest.args | 14 +-
.../disk-floppy.x86_64-2.12.0.args | 35 ++
.../disk-floppy.x86_64-latest.args | 21 +-
.../disk-network-gluster.x86_64-2.12.0.args | 44 ++
.../disk-network-gluster.x86_64-latest.args | 32 +-
.../disk-network-iscsi.x86_64-2.12.0.args | 63 +++
.../disk-network-iscsi.x86_64-latest.args | 58 +-
.../disk-network-nbd.x86_64-2.12.0.args | 46 ++
.../disk-network-nbd.x86_64-latest.args | 41 +-
.../disk-network-rbd.x86_64-2.12.0.args | 61 +++
.../disk-network-rbd.x86_64-latest.args | 67 ++-
.../disk-network-sheepdog.x86_64-2.12.0.args | 35 ++
.../disk-network-sheepdog.x86_64-latest.args | 16 +-
.../disk-network-source-auth.x86_64-2.12.0.args | 47 ++
.../disk-network-source-auth.x86_64-latest.args | 30 +-
.../disk-network-tlsx509.x86_64-2.12.0.args | 59 ++
.../disk-network-tlsx509.x86_64-latest.args | 61 ++-
.../disk-readonly-disk.x86_64-2.12.0.args | 34 ++
.../disk-readonly-disk.x86_64-latest.args | 14 +-
.../disk-shared.x86_64-2.12.0.args | 37 ++
.../disk-shared.x86_64-latest.args | 18 +-
...isk-virtio-scsi-reservations.x86_64-2.12.0.args | 43 ++
...isk-virtio-scsi-reservations.x86_64-latest.args | 20 +-
.../floppy-drive-fat.x86_64-2.12.0.args | 33 ++
.../floppy-drive-fat.x86_64-latest.args | 7 +-
.../hostdev-mdev-display-missing-graphics.xml | 6 -
...v-display-spice-egl-headless.x86_64-latest.args | 2 -
.../hostdev-mdev-display-spice-egl-headless.xml | 6 -
...ev-mdev-display-spice-opengl.x86_64-latest.args | 2 -
.../hostdev-mdev-display-spice-opengl.xml | 6 -
...dev-display-vnc-egl-headless.x86_64-latest.args | 2 -
.../hostdev-mdev-display-vnc-egl-headless.xml | 6 -
.../hostdev-mdev-display-vnc.x86_64-latest.args | 2 -
.../qemuxml2argvdata/hostdev-mdev-display-vnc.xml | 6 -
tests/qemuxml2argvdata/hostdev-mdev-display.xml | 6 -
.../hostdev-mdev-invalid-target-address.xml | 5 -
.../qemuxml2argvdata/hostdev-mdev-precreated.args | 3 -
tests/qemuxml2argvdata/hostdev-mdev-precreated.xml | 6 -
.../hostdev-mdev-src-address-invalid.xml | 6 -
tests/qemuxml2argvtest.c | 26 +
.../disk-backing-chains-inactive.xml | 35 ++
.../disk-backing-chains-index-active.xml | 156 ++++++
.../disk-backing-chains-index-inactive.xml | 156 ++++++
.../disk-backing-chains-noindex-active.xml | 156 ++++++
.../disk-backing-chains-noindex-inactive.xml | 156 ++++++
tests/qemuxml2xmloutdata/disk-mirror-inactive.xml | 4 +
.../disk-mirror-old-inactive.xml | 4 +
tests/qemuxml2xmloutdata/hostdev-mdev-display.xml | 6 -
.../qemuxml2xmloutdata/hostdev-mdev-precreated.xml | 6 -
tests/qemuxml2xmltest.c | 2 +
104 files changed, 4259 insertions(+), 1169 deletions(-)
create mode 100644 tests/qemuxml2argvdata/disk-aio.x86_64-2.12.0.args
create mode 120000 tests/qemuxml2argvdata/disk-backing-chains-index.x86_64-2.12.0.args
create mode 120000 tests/qemuxml2argvdata/disk-backing-chains-index.x86_64-latest.args
create mode 100644 tests/qemuxml2argvdata/disk-backing-chains-index.xml
create mode 100644 tests/qemuxml2argvdata/disk-backing-chains-noindex.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-backing-chains-noindex.x86_64-latest.args
create mode 100644 tests/qemuxml2argvdata/disk-backing-chains-noindex.xml
create mode 100644 tests/qemuxml2argvdata/disk-cache.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-cdrom-network.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-cdrom-tray.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-cdrom.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-copy_on_read.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-detect-zeroes.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-error-policy.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-floppy-q35-2_11.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-floppy-q35-2_9.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-floppy.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-network-gluster.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-network-iscsi.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-network-nbd.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-network-rbd.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-network-sheepdog.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-network-source-auth.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-network-tlsx509.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-readonly-disk.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-shared.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/disk-virtio-scsi-reservations.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2argvdata/floppy-drive-fat.x86_64-2.12.0.args
create mode 100644 tests/qemuxml2xmloutdata/disk-backing-chains-index-active.xml
create mode 100644 tests/qemuxml2xmloutdata/disk-backing-chains-index-inactive.xml
create mode 100644 tests/qemuxml2xmloutdata/disk-backing-chains-noindex-active.xml
create mode 100644 tests/qemuxml2xmloutdata/disk-backing-chains-noindex-inactive.xml
--
2.16.2
6 years, 3 months
[libvirt] [PATCH v3 0/3] vsh: Introduce new API for printing tables
by Simon Kobyda
Created new API for priting tables, mainly to solve alignment problems.
Implemented these test to virsh list. In the future, API may be
everywhere in virsh and virt-admin.
Also wrote basic tests for the new API, and corrected tests in virshtest
which are influenced by implementation of the API in virsh list.
Changes in v3:
- changed encoding of 3/3 patch, otherwise it cannot be applied
Changes in v2:
- added tests
- fixed alignment for unicode character which span more spaces
- moved ncolumns check to vshTableRowAppend
- changed arguments for functions vshTablePrint, vshTablePrintToStdout,
vshTablePrintToString
Simon Kobyda (3):
vsh: Add API for printing tables.
virsh: Implement new table API for virsh list
vsh: Added tests
tests/Makefile.am | 8 +
tests/virshtest.c | 14 +-
tests/vshtabletest.c | 247 +++++++++++++++++++++
tools/Makefile.am | 4 +-
tools/virsh-domain-monitor.c | 43 ++--
tools/vsh-table.c | 413 +++++++++++++++++++++++++++++++++++
tools/vsh-table.h | 42 ++++
7 files changed, 744 insertions(+), 27 deletions(-)
create mode 100644 tests/vshtabletest.c
create mode 100644 tools/vsh-table.c
create mode 100644 tools/vsh-table.h
--
2.17.1
6 years, 3 months
[libvirt] [PATCH 0/3] ui: remove deprecated UI frontends
by Daniel P. Berrangé
We deprecated GTK2 and SDL1.2 in the 2.12.0 release, so they are able to
be removed entirely in the 3.1.0 release. The min GTK3 version can also
be bumped up based the distros we aim to support.
Daniel P. Berrangé (3):
ui: remove support for GTK2 in favour of GTK3
ui: increase min required GTK3 version to 3.14.0
ui: remove support for SDL1.2 in favour of SDL2
configure | 111 +----
include/ui/gtk.h | 9 -
qemu-deprecated.texi | 16 -
ui/Makefile.objs | 5 -
ui/gtk-egl.c | 10 +-
ui/gtk.c | 202 +-------
ui/sdl.c | 1027 ----------------------------------------
ui/sdl_zoom.c | 93 ----
ui/sdl_zoom.h | 25 -
ui/sdl_zoom_template.h | 219 ---------
10 files changed, 33 insertions(+), 1684 deletions(-)
delete mode 100644 ui/sdl.c
delete mode 100644 ui/sdl_zoom.c
delete mode 100644 ui/sdl_zoom.h
delete mode 100644 ui/sdl_zoom_template.h
--
2.17.1
6 years, 3 months
[libvirt] [PATCH] qemu: Start domain on a node without cpu affinity
by Roman Bolshakov
libvirt affinity wrappers don't support macOS Thread Affinity API:
https://developer.apple.com/library/archive/releasenotes/Performance/RN-A...
virProcessSetAffinity stub prevents libvirt from starting a qemu domain
on macOS:
$ virsh start vm
error: Failed to start domain vm
error: Process CPU affinity is not supported on this platform: Function not implemented
With the patch a VM can be started on macOS but some affinity-related
commands will return errors:
$ virsh vcpuinfo vm
error: Requested operation is not valid: cpu affinity is not supported
$ virsh vcpupin vm
VCPU: CPU Affinity
----------------------------------
0: 0-7
$ virsh vcpupin vm --live --vcpu 0 --cpulist 7
error: operation failed: Virt type 'qemu' does not support vCPU pinning
$ virsh emulatorpin vm
emulator: CPU Affinity
----------------------------------
*: 0-7
$ virsh emulatorpin vm --live --cpulist 7
error: Requested operation is not valid: cpu affinity is not supported
The patch also fixes virmacmaptest on macOS
Signed-off-by: Roman Bolshakov <r.bolshakov(a)yadro.com>
---
src/qemu/qemu_driver.c | 6 ++++++
src/util/virprocess.c | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 21e9e87ddd..2e225b1ede 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5245,6 +5245,12 @@ qemuDomainPinEmulator(virDomainPtr dom,
if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;
+ if (!qemuDomainHasVcpuPids(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("cpu affinity is not supported"));
+ goto cleanup;
+ }
+
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
goto cleanup;
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 3988f5546c..7eaafd29f2 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -598,7 +598,7 @@ int virProcessSetAffinity(pid_t pid ATTRIBUTE_UNUSED,
{
virReportSystemError(ENOSYS, "%s",
_("Process CPU affinity is not supported on this platform"));
- return -1;
+ return 0;
}
virBitmapPtr
--
2.15.2 (Apple Git-101.1)
6 years, 3 months
[libvirt] [jenkins-ci PATCH v2 00/13] lcitool: Add 'build' action
by Andrea Bolognani
Changes from [v1]:
* rebase on top of master (985ab833be9b) and integrate recent
changes to build rules on the Jenkins side;
* build on more targets.
[v1] https://www.redhat.com/archives/libvir-list/2018-August/msg00393.html
Andrea Bolognani (13):
projects: Add default machines for libvirt-dbus
jobs: Rename git-url -> git_url
jobs: Remove archive_format from defaults
jobs: Move some parameters from jobs to defaults
jobs: Declare empty values consistently
guests: Add build jobs
guests: Add build projects
guests: Add build playbook
lcitool: Make playbook execution generic
lcitool: Add 'build' action
lcitool: Support building arbitrary branches
guests: Support building on more targets
lcitool: Document build action
guests/README.markdown | 19 +++
guests/lcitool | 109 ++++++++++--------
.../build/jobs/autotools-build-job.yml | 15 +++
.../build/jobs/autotools-check-job.yml | 16 +++
.../build/jobs/autotools-rpm-job.yml | 17 +++
.../build/jobs/autotools-syntax-check-job.yml | 12 ++
guests/playbooks/build/jobs/defaults.yml | 37 ++++++
.../build/jobs/generic-build-job.yml | 11 ++
.../build/jobs/generic-check-job.yml | 11 ++
.../playbooks/build/jobs/generic-rpm-job.yml | 11 ++
.../build/jobs/generic-syntax-check-job.yml | 11 ++
guests/playbooks/build/jobs/go-build-job.yml | 11 ++
guests/playbooks/build/jobs/go-check-job.yml | 11 ++
.../build/jobs/perl-modulebuild-build-job.yml | 13 +++
.../build/jobs/perl-modulebuild-check-job.yml | 11 ++
.../build/jobs/perl-modulebuild-rpm-job.yml | 16 +++
guests/playbooks/build/jobs/prepare.yml | 19 +++
.../build/jobs/python-distutils-build-job.yml | 13 +++
.../build/jobs/python-distutils-check-job.yml | 11 ++
.../build/jobs/python-distutils-rpm-job.yml | 12 ++
guests/playbooks/build/main.yml | 16 +++
guests/playbooks/build/projects/libosinfo.yml | 36 ++++++
.../playbooks/build/projects/libvirt-cim.yml | 10 ++
.../playbooks/build/projects/libvirt-dbus.yml | 44 +++++++
.../playbooks/build/projects/libvirt-glib.yml | 38 ++++++
.../build/projects/libvirt-go-xml.yml | 13 +++
.../playbooks/build/projects/libvirt-go.yml | 13 +++
.../playbooks/build/projects/libvirt-perl.yml | 19 +++
.../build/projects/libvirt-python.yml | 13 +++
.../build/projects/libvirt-sandbox.yml | 27 +++++
.../playbooks/build/projects/libvirt-tck.yml | 27 +++++
guests/playbooks/build/projects/libvirt.yml | 55 +++++++++
.../build/projects/osinfo-db-tools.yml | 36 ++++++
guests/playbooks/build/projects/osinfo-db.yml | 23 ++++
.../playbooks/build/projects/virt-manager.yml | 39 +++++++
.../playbooks/build/projects/virt-viewer.yml | 38 ++++++
jobs/autotools.yaml | 3 +-
jobs/defaults.yaml | 8 +-
jobs/generic.yaml | 3 +-
jobs/go.yaml | 3 +-
jobs/perl-modulebuild.yaml | 3 +-
jobs/python-distutils.yaml | 3 +-
projects/libosinfo.yaml | 3 +-
projects/libvirt-cim.yaml | 3 +-
projects/libvirt-dbus.yaml | 18 +--
projects/libvirt-glib.yaml | 3 +-
projects/libvirt-go-xml.yaml | 3 +-
projects/libvirt-go.yaml | 3 +-
projects/libvirt-perl.yaml | 3 +-
projects/libvirt-python.yaml | 3 +-
projects/libvirt-sandbox.yaml | 3 +-
projects/libvirt-tck.yaml | 3 +-
projects/libvirt.yaml | 2 +-
projects/osinfo-db-tools.yaml | 3 +-
projects/osinfo-db.yaml | 2 +-
projects/virt-manager.yaml | 3 +-
projects/virt-viewer.yaml | 3 +-
57 files changed, 832 insertions(+), 82 deletions(-)
create mode 100644 guests/playbooks/build/jobs/autotools-build-job.yml
create mode 100644 guests/playbooks/build/jobs/autotools-check-job.yml
create mode 100644 guests/playbooks/build/jobs/autotools-rpm-job.yml
create mode 100644 guests/playbooks/build/jobs/autotools-syntax-check-job.yml
create mode 100644 guests/playbooks/build/jobs/defaults.yml
create mode 100644 guests/playbooks/build/jobs/generic-build-job.yml
create mode 100644 guests/playbooks/build/jobs/generic-check-job.yml
create mode 100644 guests/playbooks/build/jobs/generic-rpm-job.yml
create mode 100644 guests/playbooks/build/jobs/generic-syntax-check-job.yml
create mode 100644 guests/playbooks/build/jobs/go-build-job.yml
create mode 100644 guests/playbooks/build/jobs/go-check-job.yml
create mode 100644 guests/playbooks/build/jobs/perl-modulebuild-build-job.yml
create mode 100644 guests/playbooks/build/jobs/perl-modulebuild-check-job.yml
create mode 100644 guests/playbooks/build/jobs/perl-modulebuild-rpm-job.yml
create mode 100644 guests/playbooks/build/jobs/prepare.yml
create mode 100644 guests/playbooks/build/jobs/python-distutils-build-job.yml
create mode 100644 guests/playbooks/build/jobs/python-distutils-check-job.yml
create mode 100644 guests/playbooks/build/jobs/python-distutils-rpm-job.yml
create mode 100644 guests/playbooks/build/main.yml
create mode 100644 guests/playbooks/build/projects/libosinfo.yml
create mode 100644 guests/playbooks/build/projects/libvirt-cim.yml
create mode 100644 guests/playbooks/build/projects/libvirt-dbus.yml
create mode 100644 guests/playbooks/build/projects/libvirt-glib.yml
create mode 100644 guests/playbooks/build/projects/libvirt-go-xml.yml
create mode 100644 guests/playbooks/build/projects/libvirt-go.yml
create mode 100644 guests/playbooks/build/projects/libvirt-perl.yml
create mode 100644 guests/playbooks/build/projects/libvirt-python.yml
create mode 100644 guests/playbooks/build/projects/libvirt-sandbox.yml
create mode 100644 guests/playbooks/build/projects/libvirt-tck.yml
create mode 100644 guests/playbooks/build/projects/libvirt.yml
create mode 100644 guests/playbooks/build/projects/osinfo-db-tools.yml
create mode 100644 guests/playbooks/build/projects/osinfo-db.yml
create mode 100644 guests/playbooks/build/projects/virt-manager.yml
create mode 100644 guests/playbooks/build/projects/virt-viewer.yml
--
2.17.1
6 years, 3 months
[libvirt] [PATCH] virsh: Don't break loop of domblkinfo for disks
by Han Han
https://bugzilla.redhat.com/show_bug.cgi?id=1619625
--all option is added to cmdDomblkinfo since commit 62c39193 allowing to
show all block devices info. Remove its 'goto cleanup' part in case it breaks
the loop of domblkinfo for all disks. Remove unnecessary variables and the
condition part after virDomainGetBlockInfo returning fail.
Signed-off-by: Han Han <hhan(a)redhat.com>
---
tools/virsh-domain-monitor.c | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index b9b4f9739b..ee926baae8 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -476,7 +476,6 @@ cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd)
size_t i;
xmlNodePtr *disks = NULL;
char *target = NULL;
- char *protocol = NULL;
if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
@@ -490,7 +489,6 @@ cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd)
human = vshCommandOptBool(cmd, "human");
if (all) {
- bool active = virDomainIsActive(dom) == 1;
int rc;
if (virshDomainGetXML(ctl, cmd, 0, &xmldoc, &ctxt) < 0)
@@ -505,29 +503,18 @@ cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd)
for (i = 0; i < ndisks; i++) {
ctxt->node = disks[i];
- protocol = virXPathString("string(./source/@protocol)", ctxt);
target = virXPathString("string(./target/@dev)", ctxt);
rc = virDomainGetBlockInfo(dom, target, &info, 0);
if (rc < 0) {
- /* If protocol is present that's an indication of a networked
- * storage device which cannot provide statistics, so generate
- * 0 based data and get the next disk. */
- if (protocol && !active &&
- virGetLastErrorCode() == VIR_ERR_INTERNAL_ERROR &&
- virGetLastErrorDomain() == VIR_FROM_STORAGE) {
- memset(&info, 0, sizeof(info));
- vshResetLibvirtError();
- } else {
- goto cleanup;
- }
+ memset(&info, 0, sizeof(info));
+ vshResetLibvirtError();
}
cmdDomblkinfoPrint(ctl, &info, target, human, false);
VIR_FREE(target);
- VIR_FREE(protocol);
}
} else {
if (virDomainGetBlockInfo(dom, device, &info, 0) < 0)
@@ -541,7 +528,6 @@ cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd)
cleanup:
virshDomainFree(dom);
VIR_FREE(target);
- VIR_FREE(protocol);
VIR_FREE(disks);
xmlXPathFreeContext(ctxt);
xmlFreeDoc(xmldoc);
--
2.18.0
6 years, 3 months