Re: [PATCH v5 0/8] Implement detach device related APIs for test driver

2022-03-02 Thread Luke Yue
On Mon, 2022-02-07 at 15:38 +0800, Luke Yue wrote:
> diff to v4:
> - Rebase to current master
> 
> diff to v3:
> - Add virDomainDeviceDefOperationsCallbacks to xmlopt for de-
> duplicating purpose
> - Add virDomainDeviceTypeFlags for de-duplicating purpose
> - Remove the memballoon helper function
> - Squash test_driver commits
> - Move test device xmls to generichotplugdata
> - Reimplement tests with internal APIs
> 
> link to v4:
> https://listman.redhat.com/archives/libvir-list/2021-December/msg00108.html
> link to v3:
> https://listman.redhat.com/archives/libvir-list/2021-November/msg00288.html
> link to CI: https://gitlab.com/lukedyue/libvirt/-/pipelines/464756840
> 
> Luke Yue (8):
>   conf: Introduce virDomainInputDefRemove and fix memory leak
>   conf: Introduce virDomainDeviceDefOperationsCallbacks to xmlopt
>   conf: Add virDomainDeviceTypeFlags and use it in various drivers
>   conf: Add tpm helpers for future use
>   domain_driver: extract DetachXXXDeviceConfig related functions and
> use
>     them
>   test_driver: Implement virDomainDetachDeviceFlags
>   examples: xml: test: add xml for testing devices related APIs
>   tests: Add generichotplugtest
> 
>  examples/xml/test/meson.build |   1 +
>  examples/xml/test/testdomfc5.xml  |  54 ++
>  examples/xml/test/testnodeinline.xml  |  54 ++
>  src/bhyve/bhyve_domain.c  |   2 +-
>  src/ch/ch_conf.c  |   2 +-
>  src/conf/domain_conf.c    | 572
> +-
>  src/conf/domain_conf.h    | 135 -
>  src/conf/virconftypes.h   |   2 +
>  src/hyperv/hyperv_driver.c    |   3 +-
>  src/libvirt_private.syms  |  21 +
>  src/libxl/libxl_conf.c    |   3 +-
>  src/libxl/libxl_domain.c  |   8 +
>  src/libxl/libxl_domain.h  |   1 +
>  src/libxl/libxl_driver.c  |  73 +--
>  src/lxc/lxc_conf.c    |   3 +-
>  src/lxc/lxc_domain.c  |   7 +
>  src/lxc/lxc_domain.h  |   1 +
>  src/lxc/lxc_driver.c  |  62 +-
>  src/openvz/openvz_conf.c  |   2 +-
>  src/qemu/qemu_conf.c  |   3 +-
>  src/qemu/qemu_domain.c    |  39 ++
>  src/qemu/qemu_domain.h    |   6 +
>  src/qemu/qemu_driver.c    | 206 +--
>  src/qemu/qemu_process.c   |   2 +-
>  src/security/virt-aa-helper.c |   2 +-
>  src/test/test_driver.c    | 197 +-
>  src/vbox/vbox_common.c    |   2 +-
>  src/vmware/vmware_driver.c    |   2 +-
>  src/vmx/vmx.c |   2 +-
>  src/vz/vz_driver.c    |   2 +-
>  tests/bhyveargv2xmltest.c |   2 +-
>  .../generichotplug-controller.xml |   1 +
>  .../generichotplug-disk-cdrom.xml |   5 +
>  .../generichotplug-filesystem.xml |   6 +
>  .../generichotplug-hostdev.xml    |   5 +
>  .../generichotplug-input.xml  |   1 +
>  .../generichotplug-interface.xml  |   6 +
>  .../generichotplug-lease.xml  |   5 +
>  .../generichotplug-memballoon.xml |   3 +
>  .../generichotplug-memory.xml |   6 +
>  .../generichotplugdata/generichotplug-rng.xml |   4 +
>  .../generichotplug-shmem.xml  |   4 +
>  .../generichotplug-sound.xml  |   3 +
>  .../generichotplugdata/generichotplug-tpm.xml |   5 +
>  .../generichotplug-vsock.xml  |   3 +
>  .../generichotplug-watchdog.xml   |   1 +
>  tests/generichotplugtest.c    | 178 ++
>  tests/meson.build |   1 +
>  tests/testutils.c |   2 +-
>  49 files changed, 1378 insertions(+), 332 deletions(-)
>  create mode 100644 tests/generichotplugdata/generichotplug-
> controller.xml
>  create mode 100644 tests/generichotplugdata/generichotplug-disk-
> cdrom.xml
>  create mode 100644 tests/generichotplugdata/generichotplug-
> filesystem.xml
>  create mode 100644 tests/generichotplugdata/generichotplug-
> hostdev.xml
>  create mode 100644 tests/generichotplugdata/generichotplug-input.xml
>  create mode 100644 tests/generichotplugdata/generichotplug-
> interface.xml
>  create mode 100644 tests/generichotplugdata/generichotplug-lease.xml
>  create mode 100644 tests/generichotplugdata/generichotplug-
> memballoo

[PATCH v5 8/8] tests: Add generichotplugtest

2022-02-06 Thread Luke Yue
For testing hypervisor independent device detach / attach / update
functions, currently only detaching included.

Signed-off-by: Luke Yue 
---
The test would show error messages with expected to fail tests even
with VIR_TEST_DEBUG=0, really don't know what I missed to make it quiet :(
I would really appreciate it if anyone could tell me what I should do, thanks.
---
 tests/generichotplugtest.c | 178 +
 tests/meson.build  |   1 +
 2 files changed, 179 insertions(+)
 create mode 100644 tests/generichotplugtest.c

diff --git a/tests/generichotplugtest.c b/tests/generichotplugtest.c
new file mode 100644
index 00..443fc907d3
--- /dev/null
+++ b/tests/generichotplugtest.c
@@ -0,0 +1,178 @@
+#include 
+
+#include "internal.h"
+#include "testutils.h"
+
+enum {
+ATTACH,
+DETACH,
+UPDATE
+};
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+struct genericHotplugTestData {
+const char *device_filename;
+const char *device_alias;
+bool fail;
+bool alias;
+bool keep;
+int action;
+unsigned int flags;
+virDomainPtr dom;
+};
+
+static int
+testGenericHotplug(const void *data)
+{
+int ret = 0;
+g_autofree char *domain_xml = 
g_strdup_printf("test://%s/../examples/xml/test/testnode.xml",
+  abs_srcdir);
+struct genericHotplugTestData *test = (struct genericHotplugTestData *) 
data;
+g_autofree char *device_filename = NULL;
+g_autofree char *device_alias = NULL;
+g_autofree char *device_xml = NULL;
+bool fail = test->fail;
+bool alias = test->alias;
+unsigned int flags = test->flags;
+virConnectPtr conn = virConnectOpen(domain_xml);
+virDomainPtr dom = NULL;
+
+if (!test->dom) {
+dom = virDomainLookupByName(conn, "fc5");
+test->dom = dom;
+}
+
+if (alias) {
+device_alias = g_strdup_printf("%s", test->device_alias);
+} else {
+device_filename = 
g_strdup_printf("%s/generichotplugdata/generichotplug-%s.xml",
+  abs_srcdir, test->device_filename);
+
+if (virTestLoadFile(device_filename, &device_xml) < 0)
+return -1;
+}
+
+switch (test->action) {
+case ATTACH:
+ret = virDomainAttachDeviceFlags(test->dom, device_xml, flags);
+break;
+
+case DETACH:
+if (alias) {
+ret = virDomainDetachDeviceAlias(test->dom, device_alias, flags);
+} else {
+ret = virDomainDetachDeviceFlags(test->dom, device_xml, flags);
+}
+break;
+
+case UPDATE:
+ret = virDomainUpdateDeviceFlags(test->dom, device_xml, flags);
+break;
+}
+
+if (!test->keep) {
+virDomainDestroy(test->dom);
+virDomainFree(test->dom);
+test->dom = NULL;
+} else {
+test->dom = dom;
+}
+virConnectClose(conn);
+
+return ((ret < 0 && fail) || (!ret && !fail)) ? 0 : -1;
+}
+
+static int
+mymain(void)
+{
+int ret = 0;
+struct genericHotplugTestData data = {0};
+unsigned int test_flags = VIR_DOMAIN_AFFECT_LIVE | 
VIR_DOMAIN_AFFECT_CONFIG;
+
+#define DO_TEST(ACTION, dev, dev_alias, alias_, fail_, keep_, flags_) \
+do { \
+const char *name = (alias_) ? \
+   "Generic " #ACTION " alias " dev_alias : \
+   "Generic " #ACTION " " dev; \
+data.action = ACTION; \
+data.device_filename = dev; \
+data.device_alias = dev_alias; \
+data.alias = alias_; \
+data.fail = fail_; \
+data.flags = flags_; \
+data.keep = keep_; \
+if (virTestRun(name, testGenericHotplug, &data) < 0) \
+ret = -1; \
+} while (0)
+
+#define DO_TEST_DETACH(dev, dev_alias, alias, fail, keep, flags) \
+DO_TEST(DETACH, dev, dev_alias, alias, fail, keep, flags)
+
+/* Every detach test is followed by a repeated one that is expected
+to fail, cause the previous one should detach the device successfully */
+DO_TEST_DETACH("controller", "", false, false, true, test_flags);
+DO_TEST_DETACH("controller", "", false, true, false, test_flags);
+
+DO_TEST_DETACH("disk-cdrom", "", false, false, true, test_flags);
+DO_TEST_DETACH("disk-cdrom", "", false, true, false, test_flags);
+
+DO_TEST_DETACH("filesystem", "", false, false, true, test_flags);
+DO_TEST_DETACH("filesystem", "", false, true, false, test_flags);
+
+DO_TEST_DETACH("hostdev", "", false, false, true, test_flags);
+DO_TEST_DETACH("hostdev", "", false, true, false, test_flags);
+
+DO_TEST_DETACH

[PATCH v5 5/8] domain_driver: extract DetachXXXDeviceConfig related functions and use them

2022-02-06 Thread Luke Yue
libxl / LXC / QEMU drivers share some common codes in their
DomainDetachDeviceConfig functions, so extract them to domain_conf and
use them with xmlopt etc to deduplicate the bigger function.

At the same time, this will enable test driver to test these functions
in the future.

Signed-off-by: Luke Yue 
---
Compare to the v3, I remove the random comments, and align the
error messages, also add virDomainDetachChrDeviceConfig by using xmlopt. Then
I got a lot of choices here:

1. Just cleanup these functions and using them in drivers, just like what I did
   in the previous patch.
2. Add a bigger de-duplicated function to de-duplicate the function in libxl /
   LXC / QEMU drivers, and this is what I choose in this patch.
3. Merge all the functions into the bigger one, instead of splitting them
   This would still de-duplicate the functions in libxl / LXC / QEMU drivers.

I choose the second here as I think there would be a situation that both
these single device detach functions and the bigger function would be used
in drivers.
---
 src/conf/domain_conf.c   | 487 +++
 src/conf/domain_conf.h   |  78 +++
 src/libvirt_private.syms |  18 ++
 src/libxl/libxl_driver.c |  73 +-
 src/lxc/lxc_driver.c |  62 +
 src/qemu/qemu_driver.c   | 207 +
 6 files changed, 610 insertions(+), 315 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 27643cab16..ab2e1f2e36 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31576,3 +31576,490 @@ virDomainObjGetMessages(virDomainObj *vm,
 
 return rv;
 }
+
+
+int
+virDomainDetachDiskDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+virDomainDiskDef *disk;
+virDomainDiskDef *det_disk;
+
+disk = dev->data.disk;
+if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
+virReportError(VIR_ERR_DEVICE_MISSING,
+   _("no matching disk device %s was found"),
+   disk->dst);
+return -1;
+}
+
+virDomainDiskDefFree(det_disk);
+
+return 0;
+}
+
+
+int
+virDomainDetachNetDeviceConfig(virDomainDef *vmdef,
+   virDomainDeviceDef *dev)
+{
+virDomainNetDef *net;
+int idx;
+
+net = dev->data.net;
+if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching net device was found"));
+return -1;
+}
+
+virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDetachSoundDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+virDomainSoundDef *sound;
+int idx;
+
+sound = dev->data.sound;
+if ((idx = virDomainSoundDefFind(vmdef, sound)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching sound device was found"));
+return -1;
+}
+
+virDomainSoundDefFree(virDomainSoundDefRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDetachHostdevDeviceConfig(virDomainDef *vmdef,
+   virDomainDeviceDef *dev)
+{
+virDomainHostdevDef *hostdev;
+virDomainHostdevDef *det_hostdev;
+int idx;
+
+hostdev = dev->data.hostdev;
+if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching hostdev device was found"));
+return -1;
+}
+
+virDomainHostdevDefFree(virDomainHostdevRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDetachLeaseDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+virDomainLeaseDef *lease;
+virDomainLeaseDef *det_lease;
+
+lease = dev->data.lease;
+if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
+virReportError(VIR_ERR_DEVICE_MISSING,
+   _("no matching lease %s in lockspace %s was found"),
+   lease->key, NULLSTR(lease->lockspace));
+return -1;
+}
+
+virDomainLeaseDefFree(det_lease);
+
+return 0;
+}
+
+
+int
+virDomainDetachControllerDeviceConfig(virDomainDef *vmdef,
+  virDomainDeviceDef *dev)
+{
+virDomainControllerDef *cont;
+int idx;
+
+cont = dev->data.controller;
+if ((idx = virDomainControllerFind(vmdef, cont->type, cont->idx)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching controller device was found"));
+return -1;
+}
+
+virDomainControllerDefFree(virDomainControllerRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDetachFSDeviceConfig(virDom

[PATCH v5 6/8] test_driver: Implement virDomainDetachDeviceFlags

2022-02-06 Thread Luke Yue
Introduce testDomainChgDevice for further development (just like what we
did for IOThread). And introduce testDomainDetachDeviceLiveAndConfig for
detaching devices.

Also as we implement testDomainChgDevice for both DetachDeviceFlags and
DetachDeviceAlias, we could easily implement virDomainDetachDeviceAlias
and virDomainDetachDevice.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 149 +
 1 file changed, 149 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 2380c37ddb..65ab412b36 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -10014,6 +10014,152 @@ testConnectGetAllDomainStats(virConnectPtr conn,
 return ret;
 }
 
+
+static int
+testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev,
+unsigned int flags,
+unsigned int parse_flags,
+virDomainXMLOption *xmlopt)
+{
+/* Though the function called virDomainDetachDeviceConfig, for
+test driver, it could be for both live and config */
+return virDomainDetachDeviceConfig(vmdef, dev, NULL, flags,
+   parse_flags, xmlopt);
+}
+
+static int
+testDomainDoChgDevice(testDriver *driver,
+  virDomainDeviceAction action,
+  const char *xml,
+  const char *alias,
+  virDomainDef *def,
+  unsigned int flags)
+{
+virDomainDeviceDef *dev = NULL;
+unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
+int ret = -1;
+
+if (action == VIR_DOMAIN_DEVICE_ACTION_DETACH)
+parse_flags |= VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
+
+if (xml) {
+if (!(dev = virDomainDeviceDefParse(xml, def, driver->xmlopt,
+driver->caps, parse_flags)))
+goto cleanup;
+} else if (alias) {
+dev = g_new0(virDomainDeviceDef, 1);
+if (virDomainDefFindDevice(def, alias, dev, true) < 0)
+goto cleanup;
+}
+
+if (dev == NULL)
+goto cleanup;
+
+switch (action) {
+case VIR_DOMAIN_DEVICE_ACTION_ATTACH:
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+   _("attaching devices is not supported"));
+goto cleanup;
+break;
+
+case VIR_DOMAIN_DEVICE_ACTION_DETACH:
+if (testDomainDetachDeviceLiveAndConfig(def, dev, flags, parse_flags,
+driver->xmlopt) < 0)
+goto cleanup;
+break;
+
+case VIR_DOMAIN_DEVICE_ACTION_UPDATE:
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+   _("updating devices is not supported"));
+goto cleanup;
+break;
+}
+
+ret = 0;
+
+ cleanup:
+if (xml) {
+virDomainDeviceDefFree(dev);
+} else {
+g_free(dev);
+}
+return ret;
+}
+
+static int
+testDomainChgDevice(virDomainPtr dom,
+virDomainDeviceAction action,
+const char *xml,
+const char *alias,
+unsigned int flags)
+{
+testDriver *driver = dom->conn->privateData;
+virDomainObj *vm = NULL;
+virDomainDef *def;
+virDomainDef *persistentDef;
+
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
+goto cleanup;
+
+if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+goto cleanup;
+
+if (def) {
+if (testDomainDoChgDevice(driver, action, xml,
+  alias, def, flags) < 0) {
+goto cleanup;
+}
+}
+
+if (persistentDef) {
+if (testDomainDoChgDevice(driver, action, xml,
+  alias, persistentDef, flags) < 0) {
+goto cleanup;
+}
+}
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+testDomainDetachDeviceFlags(virDomainPtr dom,
+const char *xml,
+unsigned int flags)
+{
+return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
+   xml, NULL, flags);
+}
+
+static int
+testDomainDetachDeviceAlias(virDomainPtr dom,
+const char *alias,
+unsigned int flags)
+{
+return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
+   NULL, alias, flags);
+}
+
+static int
+testDomainDetachDevice(virDomainPtr dom,
+  

[PATCH v5 1/8] conf: Introduce virDomainInputDefRemove and fix memory leak

2022-02-06 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.c   | 12 
 src/conf/domain_conf.h   |  2 ++
 src/libvirt_private.syms |  1 +
 src/qemu/qemu_driver.c   |  3 ++-
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d66496c9b7..c8c2f13f8b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16734,6 +16734,18 @@ virDomainInputDefFind(const virDomainDef *def,
 }
 
 
+virDomainInputDef *
+virDomainInputDefRemove(virDomainDef *def,
+size_t idx)
+{
+virDomainInputDef *ret = def->inputs[idx];
+
+VIR_DELETE_ELEMENT(def->inputs, idx, def->ninputs);
+
+return ret;
+}
+
+
 bool
 virDomainVsockDefEquals(const virDomainVsockDef *a,
 const virDomainVsockDef *b)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index b2922e8cff..c0167eee85 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3888,6 +3888,8 @@ virDomainShmemDef *virDomainShmemDefRemove(virDomainDef 
*def, size_t idx)
 ssize_t virDomainInputDefFind(const virDomainDef *def,
   const virDomainInputDef *input)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+virDomainInputDef *virDomainInputDefRemove(virDomainDef *def, size_t idx)
+ATTRIBUTE_NONNULL(1);
 bool virDomainVsockDefEquals(const virDomainVsockDef *a,
  const virDomainVsockDef *b)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 398cc79ee3..abdc8eaef7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -480,6 +480,7 @@ virDomainInputBusTypeToString;
 virDomainInputDefFind;
 virDomainInputDefFree;
 virDomainInputDefGetPath;
+virDomainInputDefRemove;
 virDomainInputSourceGrabToggleTypeFromString;
 virDomainInputSourceGrabToggleTypeToString;
 virDomainInputSourceGrabTypeFromString;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 698f57f00e..864ea10685 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7502,7 +7502,8 @@ qemuDomainDetachDeviceConfig(virDomainDef *vmdef,
_("matching input device not found"));
 return -1;
 }
-VIR_DELETE_ELEMENT(vmdef->inputs, idx, vmdef->ninputs);
+
+virDomainInputDefFree(virDomainInputDefRemove(vmdef, idx));
 break;
 
 case VIR_DOMAIN_DEVICE_VSOCK:
-- 
2.35.1



[PATCH v5 3/8] conf: Add virDomainDeviceTypeFlags and use it in various drivers

2022-02-06 Thread Luke Yue
Declare and use virDomainDeviceDefOperationsCallbacks in test / QEMU /
LXC / libxl drivers to store detachable devices that driver support,
this would be useful in future.

Also add test driver's memballoon device detach function and QEMU
driver's char device detach function to their xmlopt.

Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.h   | 31 ++
 src/libxl/libxl_conf.c   |  3 ++-
 src/libxl/libxl_domain.c |  8 +++
 src/libxl/libxl_domain.h |  1 +
 src/lxc/lxc_conf.c   |  3 ++-
 src/lxc/lxc_domain.c |  7 ++
 src/lxc/lxc_domain.h |  1 +
 src/qemu/qemu_conf.c |  2 +-
 src/qemu/qemu_domain.c   | 39 +
 src/qemu/qemu_domain.h   |  6 +
 src/test/test_driver.c   | 47 +++-
 11 files changed, 144 insertions(+), 4 deletions(-)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 14fb9777de..3bb1092b60 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -90,6 +90,37 @@ typedef enum {
 VIR_DOMAIN_DEVICE_LAST
 } virDomainDeviceType;
 
+typedef enum {
+VIR_DOMAIN_DEVICE_FLAG_NONE = (1 << VIR_DOMAIN_DEVICE_NONE),
+VIR_DOMAIN_DEVICE_FLAG_DISK = (1 << VIR_DOMAIN_DEVICE_DISK),
+VIR_DOMAIN_DEVICE_FLAG_LEASE = (1 << VIR_DOMAIN_DEVICE_LEASE),
+VIR_DOMAIN_DEVICE_FLAG_FS = (1 << VIR_DOMAIN_DEVICE_FS),
+VIR_DOMAIN_DEVICE_FLAG_NET = (1 << VIR_DOMAIN_DEVICE_NET),
+VIR_DOMAIN_DEVICE_FLAG_INPUT = (1 << VIR_DOMAIN_DEVICE_INPUT),
+VIR_DOMAIN_DEVICE_FLAG_SOUND = (1 << VIR_DOMAIN_DEVICE_SOUND),
+VIR_DOMAIN_DEVICE_FLAG_VIDEO = (1 << VIR_DOMAIN_DEVICE_VIDEO),
+VIR_DOMAIN_DEVICE_FLAG_HOSTDEV = (1 << VIR_DOMAIN_DEVICE_HOSTDEV),
+VIR_DOMAIN_DEVICE_FLAG_WATCHDOG = (1 << VIR_DOMAIN_DEVICE_WATCHDOG),
+VIR_DOMAIN_DEVICE_FLAG_CONTROLLER = (1 << VIR_DOMAIN_DEVICE_CONTROLLER),
+VIR_DOMAIN_DEVICE_FLAG_GRAPHICS = (1 << VIR_DOMAIN_DEVICE_GRAPHICS),
+VIR_DOMAIN_DEVICE_FLAG_HUB = (1 << VIR_DOMAIN_DEVICE_HUB),
+VIR_DOMAIN_DEVICE_FLAG_REDIRDEV = (1 << VIR_DOMAIN_DEVICE_REDIRDEV),
+VIR_DOMAIN_DEVICE_FLAG_SMARTCARD = (1 << VIR_DOMAIN_DEVICE_SMARTCARD),
+VIR_DOMAIN_DEVICE_FLAG_CHR = (1 << VIR_DOMAIN_DEVICE_CHR),
+VIR_DOMAIN_DEVICE_FLAG_MEMBALLOON = (1 << VIR_DOMAIN_DEVICE_MEMBALLOON),
+VIR_DOMAIN_DEVICE_FLAG_NVRAM = (1 << VIR_DOMAIN_DEVICE_NVRAM),
+VIR_DOMAIN_DEVICE_FLAG_RNG = (1 << VIR_DOMAIN_DEVICE_RNG),
+VIR_DOMAIN_DEVICE_FLAG_SHMEM = (1 << VIR_DOMAIN_DEVICE_SHMEM),
+VIR_DOMAIN_DEVICE_FLAG_TPM = (1 << VIR_DOMAIN_DEVICE_TPM),
+VIR_DOMAIN_DEVICE_FLAG_PANIC = (1 << VIR_DOMAIN_DEVICE_PANIC),
+VIR_DOMAIN_DEVICE_FLAG_MEMORY = (1 << VIR_DOMAIN_DEVICE_MEMORY),
+VIR_DOMAIN_DEVICE_FLAG_IOMMU = (1 << VIR_DOMAIN_DEVICE_IOMMU),
+VIR_DOMAIN_DEVICE_FLAG_VSOCK = (1 << VIR_DOMAIN_DEVICE_VSOCK),
+VIR_DOMAIN_DEVICE_FLAG_AUDIO = (1 << VIR_DOMAIN_DEVICE_AUDIO),
+
+VIR_DOMAIN_DEVICE_FLAG_LAST = (1 << VIR_DOMAIN_DEVICE_LAST)
+} virDomainDeviceTypeFlags;
+
 struct _virDomainDeviceDef {
 int type; /* enum virDomainDeviceType */
 union {
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 032f7196c2..aaf4a134a9 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -2486,5 +2486,6 @@ libxlCreateXMLConf(libxlDriverPrivate *driver)
 return virDomainXMLOptionNew(&libxlDomainDefParserConfig,
  &libxlDomainXMLPrivateDataCallbacks,
  &libxlDriverDomainXMLNamespace,
- NULL, NULL, NULL);
+ NULL, NULL,
+ &libxlDriverDeviceDefOpsCallbacks);
 }
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 577985b5ea..e20adfd846 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -1599,3 +1599,11 @@ virXMLNamespace libxlDriverDomainXMLNamespace = {
 .prefix = "xen",
 .uri = "http://libvirt.org/schemas/domain/xen/1.0";,
 };
+
+
+virDomainDeviceDefOperationsCallbacks libxlDriverDeviceDefOpsCallbacks = {
+.detachFlags = VIR_DOMAIN_DEVICE_FLAG_DISK |
+   VIR_DOMAIN_DEVICE_FLAG_NET |
+   VIR_DOMAIN_DEVICE_FLAG_HOSTDEV |
+   VIR_DOMAIN_DEVICE_FLAG_CONTROLLER,
+};
diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h
index 981bfc2bca..1534597cd9 100644
--- a/src/libxl/libxl_domain.h
+++ b/src/libxl/libxl_domain.h
@@ -68,6 +68,7 @@ struct _libxlDomainObjPrivate {
 extern virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks;
 extern virDomainDefParserConfig libxlDomainDefParserConfig;
 extern virXMLNamespace libxlDriverDomainXMLNamespace;
+extern virDomainDeviceDefOperationsCallbacks libxlDriverDeviceDefOpsCallbacks;
 ex

[PATCH v5 7/8] examples: xml: test: add xml for testing devices related APIs

2022-02-06 Thread Luke Yue
Also add some device xml to generichotplugdata for testing purpose, and
add the forgotten testdomfc5.xml to meson.build.

Signed-off-by: Luke Yue 
---
 examples/xml/test/meson.build |  1 +
 examples/xml/test/testdomfc5.xml  | 54 +++
 examples/xml/test/testnodeinline.xml  | 54 +++
 .../generichotplug-controller.xml |  1 +
 .../generichotplug-disk-cdrom.xml |  5 ++
 .../generichotplug-filesystem.xml |  6 +++
 .../generichotplug-hostdev.xml|  5 ++
 .../generichotplug-input.xml  |  1 +
 .../generichotplug-interface.xml  |  6 +++
 .../generichotplug-lease.xml  |  5 ++
 .../generichotplug-memballoon.xml |  3 ++
 .../generichotplug-memory.xml |  6 +++
 .../generichotplugdata/generichotplug-rng.xml |  4 ++
 .../generichotplug-shmem.xml  |  4 ++
 .../generichotplug-sound.xml  |  3 ++
 .../generichotplugdata/generichotplug-tpm.xml |  5 ++
 .../generichotplug-vsock.xml  |  3 ++
 .../generichotplug-watchdog.xml   |  1 +
 18 files changed, 167 insertions(+)
 create mode 100644 tests/generichotplugdata/generichotplug-controller.xml
 create mode 100644 tests/generichotplugdata/generichotplug-disk-cdrom.xml
 create mode 100644 tests/generichotplugdata/generichotplug-filesystem.xml
 create mode 100644 tests/generichotplugdata/generichotplug-hostdev.xml
 create mode 100644 tests/generichotplugdata/generichotplug-input.xml
 create mode 100644 tests/generichotplugdata/generichotplug-interface.xml
 create mode 100644 tests/generichotplugdata/generichotplug-lease.xml
 create mode 100644 tests/generichotplugdata/generichotplug-memballoon.xml
 create mode 100644 tests/generichotplugdata/generichotplug-memory.xml
 create mode 100644 tests/generichotplugdata/generichotplug-rng.xml
 create mode 100644 tests/generichotplugdata/generichotplug-shmem.xml
 create mode 100644 tests/generichotplugdata/generichotplug-sound.xml
 create mode 100644 tests/generichotplugdata/generichotplug-tpm.xml
 create mode 100644 tests/generichotplugdata/generichotplug-vsock.xml
 create mode 100644 tests/generichotplugdata/generichotplug-watchdog.xml

diff --git a/examples/xml/test/meson.build b/examples/xml/test/meson.build
index 89ebf03a7b..4a7e357d47 100644
--- a/examples/xml/test/meson.build
+++ b/examples/xml/test/meson.build
@@ -3,6 +3,7 @@ install_data(
 'testdev.xml',
 'testnodeinline.xml',
 'testdomfc4.xml',
+'testdomfc5.xml',
 'testdomfv0.xml',
 'testnode.xml',
 'testnetdef.xml',
diff --git a/examples/xml/test/testdomfc5.xml b/examples/xml/test/testdomfc5.xml
index a8afc211f6..3b9edb9da9 100644
--- a/examples/xml/test/testdomfc5.xml
+++ b/examples/xml/test/testdomfc5.xml
@@ -29,6 +29,12 @@
   
   
 
+
+  
+  
+  
+  
+
 
   
   
@@ -36,6 +42,7 @@
 
   
   
+  
   
 
 
@@ -47,5 +54,52 @@
   
 
 
+
+  
+
+
+  
+/dev/sdf1
+  
+
+
+  testarea
+  testkey
+  
+
+
+
+  
+  
+  
+  
+
+
+  
+  
+
+
+  
+524287
+0
+  
+
+
+  
+  4
+
+
+
+
+  
+
+
+  
+
+  
+
+
+  
+
   
 
diff --git a/examples/xml/test/testnodeinline.xml 
b/examples/xml/test/testnodeinline.xml
index 9165d9302d..1124146f73 100644
--- a/examples/xml/test/testnodeinline.xml
+++ b/examples/xml/test/testnodeinline.xml
@@ -117,6 +117,12 @@
 
 
   
+  
+
+
+
+
+  
   
 
 
@@ -124,6 +130,7 @@
   
 
 
+
 
   
   
@@ -135,6 +142,53 @@
 
   
   
+  
+
+  
+  
+
+  /dev/sdf1
+
+  
+  
+testarea
+testkey
+
+  
+  
+  
+
+
+
+
+  
+  
+
+
+  
+  
+
+  524287
+  0
+
+  
+  
+
+4
+  
+  
+  
+  
+
+  
+  
+
+  
+
+  
+  
+
+  
 
   
   
diff --git a/tests/generichotplugdata/generichotplug-controller.xml 
b/tests/generichotplugdata/generichotplug-controller.xml
new file mode 100644
index 00..d855bfa17f
--- /dev/null
+++ b/tests/generichotplugdata/generichotplug-controller.xml
@@ -0,0 +1 @@
+
diff --git a/tests/generichotplugdata/generichotplug-disk-cdrom.xml 
b/tests/generichotplugdata/generichotplug-disk-cdrom.xml
new file mode 100644
index 00..edc90556bb
--- /dev/null
+++ b/tests/generichotplugdata/generichotplug-disk-cdrom.xml
@@ -0

[PATCH v5 4/8] conf: Add tpm helpers for future use

2022-02-06 Thread Luke Yue
Signed-off-by: Luke Yue 
---
As persistent_state and is bool type and its default value is false, so I
guess it's fine that it's not explicitly assigned with false.

link to context: 
https://listman.redhat.com/archives/libvir-list/2021-November/msg00874.html
---
 src/conf/domain_conf.c   | 67 
 src/conf/domain_conf.h   |  6 
 src/libvirt_private.syms |  2 ++
 3 files changed, 75 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e19e3deb17..27643cab16 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16768,6 +16768,73 @@ virDomainVsockDefEquals(const virDomainVsockDef *a,
 }
 
 
+static bool
+virDomainTPMDefEquals(const virDomainTPMDef *a,
+  const virDomainTPMDef *b)
+{
+if (a->type != b->type)
+return false;
+
+if (a->model != b->model && a->model != VIR_DOMAIN_TPM_MODEL_DEFAULT)
+return false;
+
+if (a->version != b->version && a->version != VIR_DOMAIN_TPM_MODEL_DEFAULT)
+return false;
+
+if (a->type == VIR_DOMAIN_TPM_TYPE_PASSTHROUGH) {
+if (STRNEQ_NULLABLE(a->data.passthrough.source->data.file.path,
+b->data.passthrough.source->data.file.path))
+return false;
+} else {
+if (a->data.emulator.hassecretuuid != b->data.emulator.hassecretuuid)
+return false;
+
+if (a->data.emulator.hassecretuuid == true &&
+memcmp(a->data.emulator.secretuuid,
+   b->data.emulator.secretuuid,
+   VIR_UUID_BUFLEN))
+return false;
+
+if (a->data.emulator.persistent_state !=
+b->data.emulator.persistent_state)
+return false;
+}
+
+if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+!virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
+return false;
+
+return true;
+}
+
+
+ssize_t
+virDomainTPMDefFind(const virDomainDef *def,
+const virDomainTPMDef *tpm)
+{
+size_t i;
+
+for (i = 0; i < def->ntpms; i++) {
+if (virDomainTPMDefEquals(tpm, def->tpms[i]))
+return i;
+}
+
+return -1;
+}
+
+
+virDomainTPMDef *
+virDomainTPMDefRemove(virDomainDef *def,
+  size_t idx)
+{
+virDomainTPMDef *ret = def->tpms[idx];
+
+VIR_DELETE_ELEMENT(def->tpms, idx, def->ntpms);
+
+return ret;
+}
+
+
 char *
 virDomainDefGetDefaultEmulator(virDomainDef *def,
virCaps *caps)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3bb1092b60..89031639cb 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3941,6 +3941,12 @@ bool virDomainVsockDefEquals(const virDomainVsockDef *a,
  const virDomainVsockDef *b)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
 
+ssize_t virDomainTPMDefFind(const virDomainDef *def,
+const virDomainTPMDef *tpm)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+virDomainTPMDef *virDomainTPMDefRemove(virDomainDef *def, size_t idx)
+ATTRIBUTE_NONNULL(1);
+
 VIR_ENUM_DECL(virDomainTaint);
 VIR_ENUM_DECL(virDomainTaintMessage);
 VIR_ENUM_DECL(virDomainVirt);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index abdc8eaef7..b6b8606063 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -667,7 +667,9 @@ virDomainTimerTrackTypeFromString;
 virDomainTimerTrackTypeToString;
 virDomainTPMBackendTypeFromString;
 virDomainTPMBackendTypeToString;
+virDomainTPMDefFind;
 virDomainTPMDefFree;
+virDomainTPMDefRemove;
 virDomainTPMModelTypeFromString;
 virDomainTPMModelTypeToString;
 virDomainTPMPcrBankTypeFromString;
-- 
2.35.1



[PATCH v5 2/8] conf: Introduce virDomainDeviceDefOperationsCallbacks to xmlopt

2022-02-06 Thread Luke Yue
virDomainDeviceDefOperationsCallbacks would enable virDomainXMLOption to
gain driver specific callback for attaching / detaching / updating
devices, also it can store flags for attachable / detachable / updatable
devices that driver supported (currently only add flags for detachable
devices).

This would be useful when de-duplicate related functions.

Signed-off-by: Luke Yue 
---
I am not pretty sure whether these functions could be put into
virDomainXMLPrivateDataCallbacks or not, so I just create a new one to store
them.
---
 src/bhyve/bhyve_domain.c  |  2 +-
 src/ch/ch_conf.c  |  2 +-
 src/conf/domain_conf.c|  6 +-
 src/conf/domain_conf.h| 18 +-
 src/conf/virconftypes.h   |  2 ++
 src/hyperv/hyperv_driver.c|  3 ++-
 src/libxl/libxl_conf.c|  2 +-
 src/lxc/lxc_conf.c|  2 +-
 src/openvz/openvz_conf.c  |  2 +-
 src/qemu/qemu_conf.c  |  3 ++-
 src/qemu/qemu_process.c   |  2 +-
 src/security/virt-aa-helper.c |  2 +-
 src/test/test_driver.c|  3 ++-
 src/vbox/vbox_common.c|  2 +-
 src/vmware/vmware_driver.c|  2 +-
 src/vmx/vmx.c |  2 +-
 src/vz/vz_driver.c|  2 +-
 tests/bhyveargv2xmltest.c |  2 +-
 tests/testutils.c |  2 +-
 19 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c
index b526235a4e..1b7986 100644
--- a/src/bhyve/bhyve_domain.c
+++ b/src/bhyve/bhyve_domain.c
@@ -217,7 +217,7 @@ virBhyveDriverCreateXMLConf(struct _bhyveConn *driver)
 return virDomainXMLOptionNew(&virBhyveDriverDomainDefParserConfig,
  &virBhyveDriverPrivateDataCallbacks,
  &virBhyveDriverDomainXMLNamespace,
- NULL, NULL);
+ NULL, NULL, NULL);
 }
 
 
diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c
index 88a23a59cd..fc1313584b 100644
--- a/src/ch/ch_conf.c
+++ b/src/ch/ch_conf.c
@@ -111,7 +111,7 @@ chDomainXMLConfInit(virCHDriver *driver)
 virCHDriverDomainDefParserConfig.priv = driver;
 return virDomainXMLOptionNew(&virCHDriverDomainDefParserConfig,
  &virCHDriverPrivateDataCallbacks,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
 }
 
 virCHDriverConfig *
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c8c2f13f8b..e19e3deb17 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1579,7 +1579,8 @@ virDomainXMLOptionNew(virDomainDefParserConfig *config,
   virDomainXMLPrivateDataCallbacks *priv,
   virXMLNamespace *xmlns,
   virDomainABIStability *abi,
-  virSaveCookieCallbacks *saveCookie)
+  virSaveCookieCallbacks *saveCookie,
+  virDomainDeviceDefOperationsCallbacks *deviceOps)
 {
 virDomainXMLOption *xmlopt;
 
@@ -1604,6 +1605,9 @@ virDomainXMLOptionNew(virDomainDefParserConfig *config,
 if (saveCookie)
 xmlopt->saveCookie = *saveCookie;
 
+if (deviceOps)
+xmlopt->deviceOps = *deviceOps;
+
 /* Technically this forbids to use one of Xerox's MAC address prefixes in
  * our hypervisor drivers. This shouldn't ever be a problem.
  *
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c0167eee85..14fb9777de 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3208,7 +3208,8 @@ virDomainXMLOption 
*virDomainXMLOptionNew(virDomainDefParserConfig *config,
   virDomainXMLPrivateDataCallbacks 
*priv,
   virXMLNamespace *xmlns,
   virDomainABIStability *abi,
-  virSaveCookieCallbacks *saveCookie);
+  virSaveCookieCallbacks *saveCookie,
+  
virDomainDeviceDefOperationsCallbacks *deviceOps);
 
 virSaveCookieCallbacks *
 virDomainXMLOptionGetSaveCookie(virDomainXMLOption *xmlopt);
@@ -3226,6 +3227,18 @@ virXMLNamespace *
 virDomainXMLOptionGetNamespace(virDomainXMLOption *xmlopt)
 ATTRIBUTE_NONNULL(1);
 
+typedef int (*virDomainDeviceDetachFunc)(virDomainDef *vmdef,
+ virDomainDeviceDef *dev,
+ unsigned int flags);
+
+struct _virDomainDeviceDefOperationsCallbacks {
+virDomainDeviceDetachFunc   detachChr;
+virDomainDeviceDetachFunc   detachMemballoon;
+
+/* Flags for detachable devices that driver supported */
+unsigned int detachFlags;
+};
+
 /* This structure holds various callbacks and data needed
  * while parsing and creating domain XMLs */
 struct _virDomainXMLOption {
@@ -3248,6 +

[PATCH v5 0/8] Implement detach device related APIs for test driver

2022-02-06 Thread Luke Yue
diff to v4:
- Rebase to current master

diff to v3:
- Add virDomainDeviceDefOperationsCallbacks to xmlopt for de-duplicating purpose
- Add virDomainDeviceTypeFlags for de-duplicating purpose
- Remove the memballoon helper function
- Squash test_driver commits
- Move test device xmls to generichotplugdata
- Reimplement tests with internal APIs

link to v4: 
https://listman.redhat.com/archives/libvir-list/2021-December/msg00108.html
link to v3: 
https://listman.redhat.com/archives/libvir-list/2021-November/msg00288.html
link to CI: https://gitlab.com/lukedyue/libvirt/-/pipelines/464756840

Luke Yue (8):
  conf: Introduce virDomainInputDefRemove and fix memory leak
  conf: Introduce virDomainDeviceDefOperationsCallbacks to xmlopt
  conf: Add virDomainDeviceTypeFlags and use it in various drivers
  conf: Add tpm helpers for future use
  domain_driver: extract DetachXXXDeviceConfig related functions and use
them
  test_driver: Implement virDomainDetachDeviceFlags
  examples: xml: test: add xml for testing devices related APIs
  tests: Add generichotplugtest

 examples/xml/test/meson.build |   1 +
 examples/xml/test/testdomfc5.xml  |  54 ++
 examples/xml/test/testnodeinline.xml  |  54 ++
 src/bhyve/bhyve_domain.c  |   2 +-
 src/ch/ch_conf.c  |   2 +-
 src/conf/domain_conf.c| 572 +-
 src/conf/domain_conf.h| 135 -
 src/conf/virconftypes.h   |   2 +
 src/hyperv/hyperv_driver.c|   3 +-
 src/libvirt_private.syms  |  21 +
 src/libxl/libxl_conf.c|   3 +-
 src/libxl/libxl_domain.c  |   8 +
 src/libxl/libxl_domain.h  |   1 +
 src/libxl/libxl_driver.c  |  73 +--
 src/lxc/lxc_conf.c|   3 +-
 src/lxc/lxc_domain.c  |   7 +
 src/lxc/lxc_domain.h  |   1 +
 src/lxc/lxc_driver.c  |  62 +-
 src/openvz/openvz_conf.c  |   2 +-
 src/qemu/qemu_conf.c  |   3 +-
 src/qemu/qemu_domain.c|  39 ++
 src/qemu/qemu_domain.h|   6 +
 src/qemu/qemu_driver.c| 206 +--
 src/qemu/qemu_process.c   |   2 +-
 src/security/virt-aa-helper.c |   2 +-
 src/test/test_driver.c| 197 +-
 src/vbox/vbox_common.c|   2 +-
 src/vmware/vmware_driver.c|   2 +-
 src/vmx/vmx.c |   2 +-
 src/vz/vz_driver.c|   2 +-
 tests/bhyveargv2xmltest.c |   2 +-
 .../generichotplug-controller.xml |   1 +
 .../generichotplug-disk-cdrom.xml |   5 +
 .../generichotplug-filesystem.xml |   6 +
 .../generichotplug-hostdev.xml|   5 +
 .../generichotplug-input.xml  |   1 +
 .../generichotplug-interface.xml  |   6 +
 .../generichotplug-lease.xml  |   5 +
 .../generichotplug-memballoon.xml |   3 +
 .../generichotplug-memory.xml |   6 +
 .../generichotplugdata/generichotplug-rng.xml |   4 +
 .../generichotplug-shmem.xml  |   4 +
 .../generichotplug-sound.xml  |   3 +
 .../generichotplugdata/generichotplug-tpm.xml |   5 +
 .../generichotplug-vsock.xml  |   3 +
 .../generichotplug-watchdog.xml   |   1 +
 tests/generichotplugtest.c| 178 ++
 tests/meson.build |   1 +
 tests/testutils.c |   2 +-
 49 files changed, 1378 insertions(+), 332 deletions(-)
 create mode 100644 tests/generichotplugdata/generichotplug-controller.xml
 create mode 100644 tests/generichotplugdata/generichotplug-disk-cdrom.xml
 create mode 100644 tests/generichotplugdata/generichotplug-filesystem.xml
 create mode 100644 tests/generichotplugdata/generichotplug-hostdev.xml
 create mode 100644 tests/generichotplugdata/generichotplug-input.xml
 create mode 100644 tests/generichotplugdata/generichotplug-interface.xml
 create mode 100644 tests/generichotplugdata/generichotplug-lease.xml
 create mode 100644 tests/generichotplugdata/generichotplug-memballoon.xml
 create mode 100644 tests/generichotplugdata/generichotplug-memory.xml
 create mode 100644 tests/generichotplugdata/generichotplug-rng.xml
 create mode 100644 tests/generichotplugdata/generichotplug-shmem.xml
 create mode 100644 tests/generichotplugdata/generichotplug-sound.xml
 create mode 100644 tests/generichotplugdata/generichotplug-tpm.xml
 create mode 100644 tests/generichotplugdata/generichotplug-vsock.xml
 create mode 100644 tests/generichotplugdata/generichotplug-watchdog.xml
 create mode 100644 tests

[PATCH v2 4/4] tests: Add test for virDomainGetSecurityLabelList

2021-12-03 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index 012edb8601..fc7caf6bc3 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -22,7 +22,8 @@ main(void)
 
 # define DOM_FC4_UUID "ef861801-45b9-11cb-88e3-afbfe5370493"
 # define DOM_FC5_UUID "08721f99-3d1d-4aec-96eb-97803297bb36"
-# define SECURITY_LABEL "libvirt-test (enforcing)"
+# define SECLABEL_ENFORCING "libvirt-test (enforcing)"
+# define SECLABEL_PERMISSIVE "libvirt-test (permissive)"
 # define FC4_MESSAGES "tainted: network configuration using opaque shell 
scripts"
 # define FC5_MESSAGES "tainted: running with undesirable elevated privileges\n\
  tainted: network configuration using opaque shell scripts\n\
@@ -48,7 +49,7 @@ Autostart:   disable\n\
 Managed save:no\n\
 Security model:  testSecurity\n\
 Security DOI:\n\
-Security labels: " SECURITY_LABEL "\n\
+Security labels: " SECLABEL_ENFORCING "\n\
 Messages:" FC4_MESSAGES "\n\
 \n";
 static const char *domuuid_fc4 = DOM_FC4_UUID "\n\n";
@@ -69,7 +70,8 @@ Autostart:   disable\n\
 Managed save:no\n\
 Security model:  testSecurity\n\
 Security DOI:\n\
-Security labels: " SECURITY_LABEL "\n\
+Security labels: " SECLABEL_ENFORCING "\n\
+ " SECLABEL_PERMISSIVE "\n\
 Messages:" FC5_MESSAGES "\n\
 \n";
 
@@ -238,7 +240,8 @@ static int testCompareDominfoByName(const void *data 
G_GNUC_UNUSED)
 
 static int testCompareTaintedDominfoByName(const void *data G_GNUC_UNUSED)
 {
-const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "fc5", NULL };
+const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "fc5",
+ "--full-seclabels", NULL };
 const char *exp = dominfo_fc5;
 return testCompareOutputLit(exp, "\nCPU time:", argv);
 }
-- 
2.34.1



[PATCH v2 2/4] virsh: Add '--full-seclabels' option for dominfo

2021-12-03 Thread Luke Yue
There is no virsh command uses virDomainGetSecurityLabelList API, so add
an option for dominfo to call it and print full list of security labels.

Signed-off-by: Luke Yue 
---
 docs/manpages/virsh.rst  |  5 +++--
 tools/virsh-domain-monitor.c | 43 +++-
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 39636a565e..54391b7557 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -2008,9 +2008,10 @@ dominfo
 
 ::
 
-   dominfo domain
+   dominfo domain [--full-seclabels]
 
-Returns basic information about the domain.
+Returns basic information about the domain. *--full-seclabels* tells virsh
+to print full list of security labels.
 
 
 domjobabort
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index eb3e0ef11a..1bb3bed1cb 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -1203,6 +1203,10 @@ static const vshCmdInfo info_dominfo[] = {
 
 static const vshCmdOptDef opts_dominfo[] = {
 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+{.name = "full-seclabels",
+ .type = VSH_OT_BOOL,
+ .help = N_("Show full list of security labels of a domain")
+},
 {.name = NULL}
 };
 
@@ -1222,6 +1226,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd)
 int has_managed_save = 0;
 virshControl *priv = ctl->privData;
 g_auto(GStrv) messages = NULL;
+bool fullseclabels = vshCommandOptBool(cmd, "full-seclabels");
 
 if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
 return false;
@@ -1303,16 +1308,42 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd)
 vshPrint(ctl, "%-15s %s\n", _("Security model:"), secmodel.model);
 vshPrint(ctl, "%-15s %s\n", _("Security DOI:"), secmodel.doi);
 
-/* Security labels are only valid for active domains */
-seclabel = g_new0(virSecurityLabel, 1);
+if (fullseclabels) {
+int len;
+size_t i;
 
-if (virDomainGetSecurityLabel(dom, seclabel) == -1) {
-VIR_FREE(seclabel);
-return false;
+if ((len = virDomainGetSecurityLabelList(dom, &seclabel)) < 0) 
{
+g_clear_pointer(&seclabel, g_free);
+return false;
+}
+
+for (i = 0; i < len; i++)
+if (seclabel[i].label[0] != '\0')
+vshPrint(ctl, "%-16s %s (%s)\n",
+ i == 0 ? _("Security labels:") : "",
+ seclabel[i].label,
+ seclabel[i].enforcing ?
+ "enforcing" :
+ "permissive");
+
+g_clear_pointer(&seclabel, g_free);
 } else {
+/* Security labels are only valid for active domains */
+seclabel = g_new0(virSecurityLabel, 1);
+
+if (virDomainGetSecurityLabel(dom, seclabel) < 0) {
+g_clear_pointer(&seclabel, g_free);
+return false;
+}
+
 if (seclabel->label[0] != '\0')
 vshPrint(ctl, "%-15s %s (%s)\n", _("Security label:"),
- seclabel->label, seclabel->enforcing ? 
"enforcing" : "permissive");
+ seclabel->label,
+ seclabel->enforcing ?
+ "enforcing" :
+ "permissive");
+
+g_clear_pointer(&seclabel, g_free);
 }
 
 VIR_FREE(seclabel);
-- 
2.34.1



[PATCH v2 3/4] virsh: Realign some outputs

2021-12-03 Thread Luke Yue
As it's now "Security labels:" instead of "Security label:".

Signed-off-by: Luke Yue 
---
 tests/virsh-undefine |  8 ++---
 tests/virshtest.c| 70 ++--
 tools/virsh-domain-monitor.c | 42 +++---
 3 files changed, 59 insertions(+), 61 deletions(-)

diff --git a/tests/virsh-undefine b/tests/virsh-undefine
index dbbb367391..7feefdec79 100755
--- a/tests/virsh-undefine
+++ b/tests/virsh-undefine
@@ -35,11 +35,11 @@ $abs_top_builddir/tools/virsh -c test:///default \
 test $? = 0 || fail=1
 sed '/^Persistent/n; /:/d' < out1 > out
 cat <<\EOF > exp || fail=1
-Persistent: yes
+Persistent:  yes
 
 Domain 'test' has been undefined
 
-Persistent: no
+Persistent:  no
 
 EOF
 compare exp out || fail=1
@@ -50,11 +50,11 @@ $abs_top_builddir/tools/virsh -c test:///default \
 test $? = 0 || fail=1
 sed '/^Persistent/n; /:/d' < out1 > out
 cat <<\EOF > exp || fail=1
-Persistent: yes
+Persistent:  yes
 
 Domain '1' has been undefined
 
-Persistent: no
+Persistent:  no
 
 EOF
 compare exp out || fail=1
diff --git a/tests/virshtest.c b/tests/virshtest.c
index c2c892c60d..012edb8601 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -25,52 +25,52 @@ main(void)
 # define SECURITY_LABEL "libvirt-test (enforcing)"
 # define FC4_MESSAGES "tainted: network configuration using opaque shell 
scripts"
 # define FC5_MESSAGES "tainted: running with undesirable elevated privileges\n\
-tainted: network configuration using opaque shell scripts\n\
-tainted: use of host cdrom passthrough\n\
-tainted: custom device tree blob used\n\
-tainted: use of deprecated configuration settings\n\
-deprecated configuration: CPU model Deprecated-Test"
+ tainted: network configuration using opaque shell scripts\n\
+ tainted: use of host cdrom passthrough\n\
+ tainted: custom device tree blob used\n\
+ tainted: use of deprecated configuration settings\n\
+ deprecated configuration: CPU model Deprecated-Test"
 # define GET_BLKIO_PARAMETER "/dev/hda,700"
 # define SET_BLKIO_PARAMETER "/dev/hda,1000"
 # define EQUAL "="
 
 static const char *dominfo_fc4 = "\
-Id: 2\n\
-Name:   fc4\n\
-UUID:   " DOM_FC4_UUID "\n\
-OS Type:linux\n\
-State:  running\n\
-CPU(s): 1\n\
-Max memory: 261072 KiB\n\
-Used memory:131072 KiB\n\
-Persistent: yes\n\
-Autostart:  disable\n\
-Managed save:   no\n\
-Security model: testSecurity\n\
-Security DOI:   \n\
-Security label: " SECURITY_LABEL "\n\
-Messages:   " FC4_MESSAGES "\n\
+Id:  2\n\
+Name:fc4\n\
+UUID:" DOM_FC4_UUID "\n\
+OS Type: linux\n\
+State:   running\n\
+CPU(s):  1\n\
+Max memory:  261072 KiB\n\
+Used memory: 131072 KiB\n\
+Persistent:  yes\n\
+Autostart:   disable\n\
+Managed save:no\n\
+Security model:  testSecurity\n\
+Security DOI:\n\
+Security labels: " SECURITY_LABEL "\n\
+Messages:" FC4_MESSAGES "\n\
 \n";
 static const char *domuuid_fc4 = DOM_FC4_UUID "\n\n";
 static const char *domid_fc4 = "2\n\n";
 static const char *domname_fc4 = "fc4\n\n";
 static const char *domstate_fc4 = "running\n\n";
 static const char *dominfo_fc5 = "\
-Id: 3\n\
-Name:   fc5\n\
-UUID:   " DOM_FC5_UUID "\n\
-OS Type:linux\n\
-State:  running\n\
-CPU(s): 4\n\
-Max memory: 2097152 KiB\n\
-Used memory:2097152 KiB\n\
-Persistent: yes\n\
-Autostart:  disable\n\
-Managed save:   no\n\
-Security model: testSecurity\n\
-Security DOI:   \n\
-Security label: " SECURITY_LABEL "\n\
-Messages:   " FC5_MESSAGES "\n\
+Id:  3\n\
+Name:fc5\n\
+UUID:" DOM_FC5_UUID "\n\
+OS Type: linux\n\
+State:   running\n\
+CPU(s):  4\n\
+Max memory:  2097152 KiB\n\
+Used memory: 2097152 KiB\n\
+Persistent:  yes\n\
+Autostart:   disable\n\
+Managed save:no\n\
+Security model:  testSecurity\n\
+Security DOI:\n\
+Security labels: " SECURITY_LABEL "\n\
+Messages:" FC5_MESSAGES "\n\
 \n";
 
 static const char *get_blkio_parameters = "\
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index 1bb3bed1cb..5ddf48cb06 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -1233,39 +1233,39 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd)
 
 id = virDomainGetID(dom);
 if (id == ((un

[PATCH v2 1/4] test_driver: Implement virDomainGetSecurityLabelList

2021-12-03 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 43 ++
 1 file changed, 43 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index b6bca884f0..e9d009cfdb 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -137,6 +137,7 @@ VIR_ONCE_GLOBAL_INIT(testDriver);
 
 #define TEST_MODEL "i686"
 #define TEST_EMULATOR "/usr/bin/test-hv"
+#define TEST_SECURITY_LABEL_LIST_LENGTH 2
 
 static const virNodeInfo defaultNodeInfo = {
 TEST_MODEL,
@@ -5275,6 +5276,47 @@ testDomainGetSecurityLabel(virDomainPtr dom,
 return ret;
 }
 
+static int
+testDomainGetSecurityLabelList(virDomainPtr dom,
+   virSecurityLabelPtr* seclabels)
+{
+virDomainObj *vm;
+size_t i;
+int ret = -1;
+
+if (!(vm = testDomObjFromDomain(dom)))
+return -1;
+
+if (!virDomainObjIsActive(vm)) {
+/* No seclabels */
+*seclabels = NULL;
+ret = 0;
+} else {
+int len = TEST_SECURITY_LABEL_LIST_LENGTH;
+
+(*seclabels) = g_new0(virSecurityLabel, len);
+memset(*seclabels, 0, sizeof(**seclabels) * len);
+
+/* Fill the array */
+for (i = 0; i < len; i++) {
+if (virStrcpyStatic((*seclabels)[i].label, "libvirt-test") < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("security label exceeds maximum: %zu"),
+   sizeof((*seclabels)[i].label) - 1);
+g_clear_pointer(seclabels, g_free);
+goto cleanup;
+}
+if (i == 0)
+(*seclabels)[i].enforcing = 1;
+}
+ret = len;
+}
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 static int
 testNodeGetSecurityModel(virConnectPtr conn,
  virSecurityModelPtr secmodel)
@@ -10049,6 +10091,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainPinIOThread = testDomainPinIOThread, /* 7.8.0 */
 .domainSetIOThreadParams = testDomainSetIOThreadParams, /* 7.8.0 */
 .domainGetSecurityLabel = testDomainGetSecurityLabel, /* 7.5.0 */
+.domainGetSecurityLabelList = testDomainGetSecurityLabelList, /* 8.0.0 */
 .nodeGetSecurityModel = testNodeGetSecurityModel, /* 7.5.0 */
 .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
 .domainSetMemoryParameters = testDomainSetMemoryParameters, /* 5.6.0 */
-- 
2.34.1



[PATCH v2 0/4] Add an option to use virDomainGetSecurityLabelList and test it

2021-12-03 Thread Luke Yue
diff to v1:
- Add some variety when filling the test driver seclabels array
- Split 2/3 in v1 to function patch and align output patch

link to v1: 
https://listman.redhat.com/archives/libvir-list/2021-September/msg00015.html
link to CI: https://gitlab.com/lukedyue/libvirt/-/pipelines/422002148

Luke Yue (4):
  test_driver: Implement virDomainGetSecurityLabelList
  virsh: Add '--full-seclabels' option for dominfo
  virsh: Realign some outputs
  tests: Add test for virDomainGetSecurityLabelList

 docs/manpages/virsh.rst  |  5 ++-
 src/test/test_driver.c   | 43 ++
 tests/virsh-undefine |  8 ++--
 tests/virshtest.c| 77 
 tools/virsh-domain-monitor.c | 85 
 5 files changed, 147 insertions(+), 71 deletions(-)

-- 
2.34.1



[PATCH v4 0/8] Implement detach device related APIs for test driver

2021-12-03 Thread Luke Yue
diff to v3:
- Add virDomainDeviceDefOperationsCallbacks to xmlopt for de-duplicating purpose
- Add virDomainDeviceTypeFlags for de-duplicating purpose
- Remove the memballoon helper function
- Squash test_driver commits
- Move test device xmls to generichotplugdata
- Reimplement tests with internal APIs

link to v3: 
https://listman.redhat.com/archives/libvir-list/2021-November/msg00288.html
link to CI: https://gitlab.com/lukedyue/libvirt/-/pipelines/421921587

Luke Yue (8):
  conf: Introduce virDomainInputDefRemove and fix memory leak
  conf: Introduce virDomainDeviceDefOperationsCallbacks to xmlopt
  conf: Add virDomainDeviceTypeFlags and use it in various drivers
  conf: Add tpm helpers for future use
  domain_driver: extract DetachXXXDeviceConfig related functions and use
them
  test_driver: Implement virDomainDetachDeviceFlags
  examples: xml: test: add xml for testing devices related APIs
  tests: Add generichotplugtest

 examples/xml/test/meson.build |   1 +
 examples/xml/test/testdomfc5.xml  |  54 ++
 examples/xml/test/testnodeinline.xml  |  54 ++
 src/bhyve/bhyve_domain.c  |   2 +-
 src/ch/ch_conf.c  |   2 +-
 src/conf/domain_conf.c| 572 +-
 src/conf/domain_conf.h| 135 -
 src/conf/virconftypes.h   |   2 +
 src/hyperv/hyperv_driver.c|   3 +-
 src/libvirt_private.syms  |  21 +
 src/libxl/libxl_conf.c|   3 +-
 src/libxl/libxl_domain.c  |   8 +
 src/libxl/libxl_domain.h  |   1 +
 src/libxl/libxl_driver.c  |  73 +--
 src/lxc/lxc_conf.c|   3 +-
 src/lxc/lxc_domain.c  |   7 +
 src/lxc/lxc_domain.h  |   1 +
 src/lxc/lxc_driver.c  |  62 +-
 src/openvz/openvz_conf.c  |   2 +-
 src/qemu/qemu_conf.c  |   3 +-
 src/qemu/qemu_domain.c|  39 ++
 src/qemu/qemu_domain.h|   6 +
 src/qemu/qemu_driver.c| 204 +--
 src/qemu/qemu_process.c   |   2 +-
 src/security/virt-aa-helper.c |   2 +-
 src/test/test_driver.c| 197 +-
 src/vbox/vbox_common.c|   2 +-
 src/vmware/vmware_driver.c|   2 +-
 src/vmx/vmx.c |   2 +-
 src/vz/vz_driver.c|   2 +-
 tests/bhyveargv2xmltest.c |   2 +-
 .../generichotplug-controller.xml |   1 +
 .../generichotplug-disk-cdrom.xml |   5 +
 .../generichotplug-filesystem.xml |   6 +
 .../generichotplug-hostdev.xml|   5 +
 .../generichotplug-input.xml  |   1 +
 .../generichotplug-interface.xml  |   6 +
 .../generichotplug-lease.xml  |   5 +
 .../generichotplug-memballoon.xml |   3 +
 .../generichotplug-memory.xml |   6 +
 .../generichotplugdata/generichotplug-rng.xml |   4 +
 .../generichotplug-shmem.xml  |   4 +
 .../generichotplug-sound.xml  |   3 +
 .../generichotplugdata/generichotplug-tpm.xml |   5 +
 .../generichotplug-vsock.xml  |   3 +
 .../generichotplug-watchdog.xml   |   1 +
 tests/generichotplugtest.c| 178 ++
 tests/meson.build |   1 +
 tests/testutils.c |   2 +-
 49 files changed, 1377 insertions(+), 331 deletions(-)
 create mode 100644 tests/generichotplugdata/generichotplug-controller.xml
 create mode 100644 tests/generichotplugdata/generichotplug-disk-cdrom.xml
 create mode 100644 tests/generichotplugdata/generichotplug-filesystem.xml
 create mode 100644 tests/generichotplugdata/generichotplug-hostdev.xml
 create mode 100644 tests/generichotplugdata/generichotplug-input.xml
 create mode 100644 tests/generichotplugdata/generichotplug-interface.xml
 create mode 100644 tests/generichotplugdata/generichotplug-lease.xml
 create mode 100644 tests/generichotplugdata/generichotplug-memballoon.xml
 create mode 100644 tests/generichotplugdata/generichotplug-memory.xml
 create mode 100644 tests/generichotplugdata/generichotplug-rng.xml
 create mode 100644 tests/generichotplugdata/generichotplug-shmem.xml
 create mode 100644 tests/generichotplugdata/generichotplug-sound.xml
 create mode 100644 tests/generichotplugdata/generichotplug-tpm.xml
 create mode 100644 tests/generichotplugdata/generichotplug-vsock.xml
 create mode 100644 tests/generichotplugdata/generichotplug-watchdog.xml
 create mode 100644 tests/generichotplugtest.c

--
2.34.1



[PATCH v4 7/8] examples: xml: test: add xml for testing devices related APIs

2021-12-03 Thread Luke Yue
Also add some device xml to generichotplugdata for testing purpose, and
add the forgotten testdomfc5.xml to meson.build.

Signed-off-by: Luke Yue 
---
 examples/xml/test/meson.build |  1 +
 examples/xml/test/testdomfc5.xml  | 54 +++
 examples/xml/test/testnodeinline.xml  | 54 +++
 .../generichotplug-controller.xml |  1 +
 .../generichotplug-disk-cdrom.xml |  5 ++
 .../generichotplug-filesystem.xml |  6 +++
 .../generichotplug-hostdev.xml|  5 ++
 .../generichotplug-input.xml  |  1 +
 .../generichotplug-interface.xml  |  6 +++
 .../generichotplug-lease.xml  |  5 ++
 .../generichotplug-memballoon.xml |  3 ++
 .../generichotplug-memory.xml |  6 +++
 .../generichotplugdata/generichotplug-rng.xml |  4 ++
 .../generichotplug-shmem.xml  |  4 ++
 .../generichotplug-sound.xml  |  3 ++
 .../generichotplugdata/generichotplug-tpm.xml |  5 ++
 .../generichotplug-vsock.xml  |  3 ++
 .../generichotplug-watchdog.xml   |  1 +
 18 files changed, 167 insertions(+)
 create mode 100644 tests/generichotplugdata/generichotplug-controller.xml
 create mode 100644 tests/generichotplugdata/generichotplug-disk-cdrom.xml
 create mode 100644 tests/generichotplugdata/generichotplug-filesystem.xml
 create mode 100644 tests/generichotplugdata/generichotplug-hostdev.xml
 create mode 100644 tests/generichotplugdata/generichotplug-input.xml
 create mode 100644 tests/generichotplugdata/generichotplug-interface.xml
 create mode 100644 tests/generichotplugdata/generichotplug-lease.xml
 create mode 100644 tests/generichotplugdata/generichotplug-memballoon.xml
 create mode 100644 tests/generichotplugdata/generichotplug-memory.xml
 create mode 100644 tests/generichotplugdata/generichotplug-rng.xml
 create mode 100644 tests/generichotplugdata/generichotplug-shmem.xml
 create mode 100644 tests/generichotplugdata/generichotplug-sound.xml
 create mode 100644 tests/generichotplugdata/generichotplug-tpm.xml
 create mode 100644 tests/generichotplugdata/generichotplug-vsock.xml
 create mode 100644 tests/generichotplugdata/generichotplug-watchdog.xml

diff --git a/examples/xml/test/meson.build b/examples/xml/test/meson.build
index 89ebf03a7b..4a7e357d47 100644
--- a/examples/xml/test/meson.build
+++ b/examples/xml/test/meson.build
@@ -3,6 +3,7 @@ install_data(
 'testdev.xml',
 'testnodeinline.xml',
 'testdomfc4.xml',
+'testdomfc5.xml',
 'testdomfv0.xml',
 'testnode.xml',
 'testnetdef.xml',
diff --git a/examples/xml/test/testdomfc5.xml b/examples/xml/test/testdomfc5.xml
index a8afc211f6..3b9edb9da9 100644
--- a/examples/xml/test/testdomfc5.xml
+++ b/examples/xml/test/testdomfc5.xml
@@ -29,6 +29,12 @@
   
   
 
+
+  
+  
+  
+  
+
 
   
   
@@ -36,6 +42,7 @@
 
   
   
+  
   
 
 
@@ -47,5 +54,52 @@
   
 
 
+
+  
+
+
+  
+/dev/sdf1
+  
+
+
+  testarea
+  testkey
+  
+
+
+
+  
+  
+  
+  
+
+
+  
+  
+
+
+  
+524287
+0
+  
+
+
+  
+  4
+
+
+
+
+  
+
+
+  
+
+  
+
+
+  
+
   
 
diff --git a/examples/xml/test/testnodeinline.xml 
b/examples/xml/test/testnodeinline.xml
index 9165d9302d..1124146f73 100644
--- a/examples/xml/test/testnodeinline.xml
+++ b/examples/xml/test/testnodeinline.xml
@@ -117,6 +117,12 @@
 
 
   
+  
+
+
+
+
+  
   
 
 
@@ -124,6 +130,7 @@
   
 
 
+
 
   
   
@@ -135,6 +142,53 @@
 
   
   
+  
+
+  
+  
+
+  /dev/sdf1
+
+  
+  
+testarea
+testkey
+
+  
+  
+  
+
+
+
+
+  
+  
+
+
+  
+  
+
+  524287
+  0
+
+  
+  
+
+4
+  
+  
+  
+  
+
+  
+  
+
+  
+
+  
+  
+
+  
 
   
   
diff --git a/tests/generichotplugdata/generichotplug-controller.xml 
b/tests/generichotplugdata/generichotplug-controller.xml
new file mode 100644
index 00..d855bfa17f
--- /dev/null
+++ b/tests/generichotplugdata/generichotplug-controller.xml
@@ -0,0 +1 @@
+
diff --git a/tests/generichotplugdata/generichotplug-disk-cdrom.xml 
b/tests/generichotplugdata/generichotplug-disk-cdrom.xml
new file mode 100644
index 00..edc90556bb
--- /dev/null
+++ b/tests/generichotplugdata/generichotplug-disk-cdrom.xml
@@ -0

[PATCH v4 2/8] conf: Introduce virDomainDeviceDefOperationsCallbacks to xmlopt

2021-12-03 Thread Luke Yue
virDomainDeviceDefOperationsCallbacks would enable virDomainXMLOption to
gain driver specific callback for attaching / detaching / updating
devices, also it can store flags for attachable / detachable / updatable
devices that driver supported (currently only add flags for detachable
devices).

This would be useful when de-duplicate related functions.

Signed-off-by: Luke Yue 
---
I am not pretty sure whether these functions could be put into
virDomainXMLPrivateDataCallbacks or not, so I just create a new one to store
them.
---
 src/bhyve/bhyve_domain.c  |  2 +-
 src/ch/ch_conf.c  |  2 +-
 src/conf/domain_conf.c|  6 +-
 src/conf/domain_conf.h| 18 +-
 src/conf/virconftypes.h   |  2 ++
 src/hyperv/hyperv_driver.c|  3 ++-
 src/libxl/libxl_conf.c|  2 +-
 src/lxc/lxc_conf.c|  2 +-
 src/openvz/openvz_conf.c  |  2 +-
 src/qemu/qemu_conf.c  |  3 ++-
 src/qemu/qemu_process.c   |  2 +-
 src/security/virt-aa-helper.c |  2 +-
 src/test/test_driver.c|  3 ++-
 src/vbox/vbox_common.c|  2 +-
 src/vmware/vmware_driver.c|  2 +-
 src/vmx/vmx.c |  2 +-
 src/vz/vz_driver.c|  2 +-
 tests/bhyveargv2xmltest.c |  2 +-
 tests/testutils.c |  2 +-
 19 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c
index b526235a4e..1b7986 100644
--- a/src/bhyve/bhyve_domain.c
+++ b/src/bhyve/bhyve_domain.c
@@ -217,7 +217,7 @@ virBhyveDriverCreateXMLConf(struct _bhyveConn *driver)
 return virDomainXMLOptionNew(&virBhyveDriverDomainDefParserConfig,
  &virBhyveDriverPrivateDataCallbacks,
  &virBhyveDriverDomainXMLNamespace,
- NULL, NULL);
+ NULL, NULL, NULL);
 }


diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c
index ef6f4b5ba8..a2affd5c02 100644
--- a/src/ch/ch_conf.c
+++ b/src/ch/ch_conf.c
@@ -115,7 +115,7 @@ chDomainXMLConfInit(virCHDriver *driver)
 virCHDriverDomainDefParserConfig.priv = driver;
 return virDomainXMLOptionNew(&virCHDriverDomainDefParserConfig,
  &virCHDriverPrivateDataCallbacks,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
 }

 virCHDriverConfig *
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d6f69b3ace..44f1428f80 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1564,7 +1564,8 @@ virDomainXMLOptionNew(virDomainDefParserConfig *config,
   virDomainXMLPrivateDataCallbacks *priv,
   virXMLNamespace *xmlns,
   virDomainABIStability *abi,
-  virSaveCookieCallbacks *saveCookie)
+  virSaveCookieCallbacks *saveCookie,
+  virDomainDeviceDefOperationsCallbacks *deviceOps)
 {
 virDomainXMLOption *xmlopt;

@@ -1589,6 +1590,9 @@ virDomainXMLOptionNew(virDomainDefParserConfig *config,
 if (saveCookie)
 xmlopt->saveCookie = *saveCookie;

+if (deviceOps)
+xmlopt->deviceOps = *deviceOps;
+
 /* Technically this forbids to use one of Xerox's MAC address prefixes in
  * our hypervisor drivers. This shouldn't ever be a problem.
  *
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e4259bf890..1b092b2ee5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3173,7 +3173,8 @@ virDomainXMLOption 
*virDomainXMLOptionNew(virDomainDefParserConfig *config,
   virDomainXMLPrivateDataCallbacks 
*priv,
   virXMLNamespace *xmlns,
   virDomainABIStability *abi,
-  virSaveCookieCallbacks *saveCookie);
+  virSaveCookieCallbacks *saveCookie,
+  
virDomainDeviceDefOperationsCallbacks *deviceOps);

 virSaveCookieCallbacks *
 virDomainXMLOptionGetSaveCookie(virDomainXMLOption *xmlopt);
@@ -3191,6 +3192,18 @@ virXMLNamespace *
 virDomainXMLOptionGetNamespace(virDomainXMLOption *xmlopt)
 ATTRIBUTE_NONNULL(1);

+typedef int (*virDomainDeviceDetachFunc)(virDomainDef *vmdef,
+ virDomainDeviceDef *dev,
+ unsigned int flags);
+
+struct _virDomainDeviceDefOperationsCallbacks {
+virDomainDeviceDetachFunc   detachChr;
+virDomainDeviceDetachFunc   detachMemballoon;
+
+/* Flags for detachable devices that driver supported */
+unsigned int detachFlags;
+};
+
 /* This structure holds various callbacks and data needed
  * while parsing and creating domain XMLs */
 struct _virDomainXMLOption {
@@ -3213,6 +3226,9 @@ struct _vi

[PATCH v4 8/8] tests: Add generichotplugtest

2021-12-03 Thread Luke Yue
For testing hypervisor independent device detach / attach / update
functions, currently only detaching included.

Signed-off-by: Luke Yue 
---
The test would show error messages with expected to fail tests even
with VIR_TEST_DEBUG=0, really don't know what I missed to make it quiet :(
I would really appreciate it if anyone could tell me what should I do, thanks.
---
 tests/generichotplugtest.c | 178 +
 tests/meson.build  |   1 +
 2 files changed, 179 insertions(+)
 create mode 100644 tests/generichotplugtest.c

diff --git a/tests/generichotplugtest.c b/tests/generichotplugtest.c
new file mode 100644
index 00..443fc907d3
--- /dev/null
+++ b/tests/generichotplugtest.c
@@ -0,0 +1,178 @@
+#include 
+
+#include "internal.h"
+#include "testutils.h"
+
+enum {
+ATTACH,
+DETACH,
+UPDATE
+};
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+struct genericHotplugTestData {
+const char *device_filename;
+const char *device_alias;
+bool fail;
+bool alias;
+bool keep;
+int action;
+unsigned int flags;
+virDomainPtr dom;
+};
+
+static int
+testGenericHotplug(const void *data)
+{
+int ret = 0;
+g_autofree char *domain_xml = 
g_strdup_printf("test://%s/../examples/xml/test/testnode.xml",
+  abs_srcdir);
+struct genericHotplugTestData *test = (struct genericHotplugTestData *) 
data;
+g_autofree char *device_filename = NULL;
+g_autofree char *device_alias = NULL;
+g_autofree char *device_xml = NULL;
+bool fail = test->fail;
+bool alias = test->alias;
+unsigned int flags = test->flags;
+virConnectPtr conn = virConnectOpen(domain_xml);
+virDomainPtr dom = NULL;
+
+if (!test->dom) {
+dom = virDomainLookupByName(conn, "fc5");
+test->dom = dom;
+}
+
+if (alias) {
+device_alias = g_strdup_printf("%s", test->device_alias);
+} else {
+device_filename = 
g_strdup_printf("%s/generichotplugdata/generichotplug-%s.xml",
+  abs_srcdir, test->device_filename);
+
+if (virTestLoadFile(device_filename, &device_xml) < 0)
+return -1;
+}
+
+switch (test->action) {
+case ATTACH:
+ret = virDomainAttachDeviceFlags(test->dom, device_xml, flags);
+break;
+
+case DETACH:
+if (alias) {
+ret = virDomainDetachDeviceAlias(test->dom, device_alias, flags);
+} else {
+ret = virDomainDetachDeviceFlags(test->dom, device_xml, flags);
+}
+break;
+
+case UPDATE:
+ret = virDomainUpdateDeviceFlags(test->dom, device_xml, flags);
+break;
+}
+
+if (!test->keep) {
+virDomainDestroy(test->dom);
+virDomainFree(test->dom);
+test->dom = NULL;
+} else {
+test->dom = dom;
+}
+virConnectClose(conn);
+
+return ((ret < 0 && fail) || (!ret && !fail)) ? 0 : -1;
+}
+
+static int
+mymain(void)
+{
+int ret = 0;
+struct genericHotplugTestData data = {0};
+unsigned int test_flags = VIR_DOMAIN_AFFECT_LIVE | 
VIR_DOMAIN_AFFECT_CONFIG;
+
+#define DO_TEST(ACTION, dev, dev_alias, alias_, fail_, keep_, flags_) \
+do { \
+const char *name = (alias_) ? \
+   "Generic " #ACTION " alias " dev_alias : \
+   "Generic " #ACTION " " dev; \
+data.action = ACTION; \
+data.device_filename = dev; \
+data.device_alias = dev_alias; \
+data.alias = alias_; \
+data.fail = fail_; \
+data.flags = flags_; \
+data.keep = keep_; \
+if (virTestRun(name, testGenericHotplug, &data) < 0) \
+ret = -1; \
+} while (0)
+
+#define DO_TEST_DETACH(dev, dev_alias, alias, fail, keep, flags) \
+DO_TEST(DETACH, dev, dev_alias, alias, fail, keep, flags)
+
+/* Every detach test is followed by a repeated one that is expected
+to fail, cause the previous one should detach the device successfully */
+DO_TEST_DETACH("controller", "", false, false, true, test_flags);
+DO_TEST_DETACH("controller", "", false, true, false, test_flags);
+
+DO_TEST_DETACH("disk-cdrom", "", false, false, true, test_flags);
+DO_TEST_DETACH("disk-cdrom", "", false, true, false, test_flags);
+
+DO_TEST_DETACH("filesystem", "", false, false, true, test_flags);
+DO_TEST_DETACH("filesystem", "", false, true, false, test_flags);
+
+DO_TEST_DETACH("hostdev", "", false, false, true, test_flags);
+DO_TEST_DETACH("hostdev", "", false, true, false, test_flags);
+
+DO_TEST_DETACH

[PATCH v4 6/8] test_driver: Implement virDomainDetachDeviceFlags

2021-12-03 Thread Luke Yue
Introduce testDomainChgDevice for further development (just like what we
did for IOThread). And introduce testDomainDetachDeviceLiveAndConfig for
detaching devices.

Also as we implement testDomainChgDevice for both DetachDeviceFlags and
DetachDeviceAlias, we could easily implement virDomainDetachDeviceAlias
and virDomainDetachDevice.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 149 +
 1 file changed, 149 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 21caa83be7..6cd1e75771 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -10022,6 +10022,152 @@ testConnectGetAllDomainStats(virConnectPtr conn,
 return ret;
 }
 
+
+static int
+testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev,
+unsigned int flags,
+unsigned int parse_flags,
+virDomainXMLOption *xmlopt)
+{
+/* Though the function called virDomainDetachDeviceConfig, for
+test driver, it could be for both live and config */
+return virDomainDetachDeviceConfig(vmdef, dev, NULL, flags,
+   parse_flags, xmlopt);
+}
+
+static int
+testDomainDoChgDevice(testDriver *driver,
+  virDomainDeviceAction action,
+  const char *xml,
+  const char *alias,
+  virDomainDef *def,
+  unsigned int flags)
+{
+virDomainDeviceDef *dev = NULL;
+unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
+int ret = -1;
+
+if (action == VIR_DOMAIN_DEVICE_ACTION_DETACH)
+parse_flags |= VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
+
+if (xml) {
+if (!(dev = virDomainDeviceDefParse(xml, def, driver->xmlopt,
+driver->caps, parse_flags)))
+goto cleanup;
+} else if (alias) {
+dev = g_new0(virDomainDeviceDef, 1);
+if (virDomainDefFindDevice(def, alias, dev, true) < 0)
+goto cleanup;
+}
+
+if (dev == NULL)
+goto cleanup;
+
+switch (action) {
+case VIR_DOMAIN_DEVICE_ACTION_ATTACH:
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+   _("attaching devices is not supported"));
+goto cleanup;
+break;
+
+case VIR_DOMAIN_DEVICE_ACTION_DETACH:
+if (testDomainDetachDeviceLiveAndConfig(def, dev, flags, parse_flags,
+driver->xmlopt) < 0)
+goto cleanup;
+break;
+
+case VIR_DOMAIN_DEVICE_ACTION_UPDATE:
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+   _("updating devices is not supported"));
+goto cleanup;
+break;
+}
+
+ret = 0;
+
+ cleanup:
+if (xml) {
+virDomainDeviceDefFree(dev);
+} else {
+g_free(dev);
+}
+return ret;
+}
+
+static int
+testDomainChgDevice(virDomainPtr dom,
+virDomainDeviceAction action,
+const char *xml,
+const char *alias,
+unsigned int flags)
+{
+testDriver *driver = dom->conn->privateData;
+virDomainObj *vm = NULL;
+virDomainDef *def;
+virDomainDef *persistentDef;
+
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
+goto cleanup;
+
+if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+goto cleanup;
+
+if (def) {
+if (testDomainDoChgDevice(driver, action, xml,
+  alias, def, flags) < 0) {
+goto cleanup;
+}
+}
+
+if (persistentDef) {
+if (testDomainDoChgDevice(driver, action, xml,
+  alias, persistentDef, flags) < 0) {
+goto cleanup;
+}
+}
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+testDomainDetachDeviceFlags(virDomainPtr dom,
+const char *xml,
+unsigned int flags)
+{
+return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
+   xml, NULL, flags);
+}
+
+static int
+testDomainDetachDeviceAlias(virDomainPtr dom,
+const char *alias,
+unsigned int flags)
+{
+return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
+   NULL, alias, flags);
+}
+
+static int
+testDomainDetachDevice(virDomainPtr dom,
+  

[PATCH v4 5/8] domain_driver: extract DetachXXXDeviceConfig related functions and use them

2021-12-03 Thread Luke Yue
libxl / LXC / QEMU drivers share some common codes in their
DomainDetachDeviceConfig functions, so extract them to domain_conf and
use them with xmlopt etc to deduplicate the bigger function.

At the same time, this will enable test driver to test these functions
in the future.

Signed-off-by: Luke Yue 
---
Compare to the previous version, I remove the random comments, and align the
error messages, also add virDomainDetachChrDeviceConfig by using xmlopt. Then
I got a lot of choices here:

1. Just cleanup these functions and using them in drivers, just like what I did
   in the previous patch.
2. Add a bigger de-duplicated function to de-duplicate the function in libxl /
   LXC / QEMU drivers, and this is what I choose in this patch.
3. Merge all the functions into the bigger one, instead of splitting them
   This would still de-duplicate the functions in libxl / LXC / QEMU drivers.

I choose the second here as I think there would be a situation that both
these single device detach functions and the bigger function would be used
in drivers.
---
 src/conf/domain_conf.c   | 487 +++
 src/conf/domain_conf.h   |  78 +++
 src/libvirt_private.syms |  18 ++
 src/libxl/libxl_driver.c |  73 +-
 src/lxc/lxc_driver.c |  62 +
 src/qemu/qemu_driver.c   | 205 +---
 6 files changed, 609 insertions(+), 314 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 30b06c45e5..8017896fd0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31656,3 +31656,490 @@ virDomainObjGetMessages(virDomainObj *vm,

 return rv;
 }
+
+
+int
+virDomainDetachDiskDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+virDomainDiskDef *disk;
+virDomainDiskDef *det_disk;
+
+disk = dev->data.disk;
+if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
+virReportError(VIR_ERR_DEVICE_MISSING,
+   _("no matching disk device %s was found"),
+   disk->dst);
+return -1;
+}
+
+virDomainDiskDefFree(det_disk);
+
+return 0;
+}
+
+
+int
+virDomainDetachNetDeviceConfig(virDomainDef *vmdef,
+   virDomainDeviceDef *dev)
+{
+virDomainNetDef *net;
+int idx;
+
+net = dev->data.net;
+if ((idx = virDomainNetFindIdx(vmdef, net)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching net device was found"));
+return -1;
+}
+
+virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDetachSoundDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+virDomainSoundDef *sound;
+int idx;
+
+sound = dev->data.sound;
+if ((idx = virDomainSoundDefFind(vmdef, sound)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching sound device was found"));
+return -1;
+}
+
+virDomainSoundDefFree(virDomainSoundDefRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDetachHostdevDeviceConfig(virDomainDef *vmdef,
+   virDomainDeviceDef *dev)
+{
+virDomainHostdevDef *hostdev;
+virDomainHostdevDef *det_hostdev;
+int idx;
+
+hostdev = dev->data.hostdev;
+if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching hostdev device was found"));
+return -1;
+}
+
+virDomainHostdevDefFree(virDomainHostdevRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDetachLeaseDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+virDomainLeaseDef *lease;
+virDomainLeaseDef *det_lease;
+
+lease = dev->data.lease;
+if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
+virReportError(VIR_ERR_DEVICE_MISSING,
+   _("no matching lease %s in lockspace %s was found"),
+   lease->key, NULLSTR(lease->lockspace));
+return -1;
+}
+
+virDomainLeaseDefFree(det_lease);
+
+return 0;
+}
+
+
+int
+virDomainDetachControllerDeviceConfig(virDomainDef *vmdef,
+  virDomainDeviceDef *dev)
+{
+virDomainControllerDef *cont;
+int idx;
+
+cont = dev->data.controller;
+if ((idx = virDomainControllerFind(vmdef, cont->type, cont->idx)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching controller device was found"));
+return -1;
+}
+
+virDomainControllerDefFree(virDomainControllerRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDetachFSDeviceConfig(virDom

[PATCH v4 4/8] conf: Add tpm helpers for future use

2021-12-03 Thread Luke Yue
Signed-off-by: Luke Yue 
---
As persistent_state and is bool type and its default value is false, so I
guess it's fine that it's not explicitly assigned with false on default.
---
 src/conf/domain_conf.c   | 67 
 src/conf/domain_conf.h   |  6 
 src/libvirt_private.syms |  2 ++
 3 files changed, 75 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 44f1428f80..30b06c45e5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16908,6 +16908,73 @@ virDomainVsockDefEquals(const virDomainVsockDef *a,
 }


+static bool
+virDomainTPMDefEquals(const virDomainTPMDef *a,
+  const virDomainTPMDef *b)
+{
+if (a->type != b->type)
+return false;
+
+if (a->model != b->model && a->model != VIR_DOMAIN_TPM_MODEL_DEFAULT)
+return false;
+
+if (a->version != b->version && a->version != VIR_DOMAIN_TPM_MODEL_DEFAULT)
+return false;
+
+if (a->type == VIR_DOMAIN_TPM_TYPE_PASSTHROUGH) {
+if (STRNEQ_NULLABLE(a->data.passthrough.source->data.file.path,
+b->data.passthrough.source->data.file.path))
+return false;
+} else {
+if (a->data.emulator.hassecretuuid != b->data.emulator.hassecretuuid)
+return false;
+
+if (a->data.emulator.hassecretuuid == true &&
+memcmp(a->data.emulator.secretuuid,
+   b->data.emulator.secretuuid,
+   VIR_UUID_BUFLEN))
+return false;
+
+if (a->data.emulator.persistent_state !=
+b->data.emulator.persistent_state)
+return false;
+}
+
+if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+!virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
+return false;
+
+return true;
+}
+
+
+ssize_t
+virDomainTPMDefFind(const virDomainDef *def,
+const virDomainTPMDef *tpm)
+{
+size_t i;
+
+for (i = 0; i < def->ntpms; i++) {
+if (virDomainTPMDefEquals(tpm, def->tpms[i]))
+return i;
+}
+
+return -1;
+}
+
+
+virDomainTPMDef *
+virDomainTPMDefRemove(virDomainDef *def,
+  size_t idx)
+{
+virDomainTPMDef *ret = def->tpms[idx];
+
+VIR_DELETE_ELEMENT(def->tpms, idx, def->ntpms);
+
+return ret;
+}
+
+
 char *
 virDomainDefGetDefaultEmulator(virDomainDef *def,
virCaps *caps)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 070cb40509..08b6965ef5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3905,6 +3905,12 @@ bool virDomainVsockDefEquals(const virDomainVsockDef *a,
  const virDomainVsockDef *b)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;

+ssize_t virDomainTPMDefFind(const virDomainDef *def,
+const virDomainTPMDef *tpm)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+virDomainTPMDef *virDomainTPMDefRemove(virDomainDef *def, size_t idx)
+ATTRIBUTE_NONNULL(1);
+
 VIR_ENUM_DECL(virDomainTaint);
 VIR_ENUM_DECL(virDomainTaintMessage);
 VIR_ENUM_DECL(virDomainVirt);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 338207b235..9b1e6a0d2a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -666,7 +666,9 @@ virDomainTimerTrackTypeFromString;
 virDomainTimerTrackTypeToString;
 virDomainTPMBackendTypeFromString;
 virDomainTPMBackendTypeToString;
+virDomainTPMDefFind;
 virDomainTPMDefFree;
+virDomainTPMDefRemove;
 virDomainTPMModelTypeFromString;
 virDomainTPMModelTypeToString;
 virDomainTPMPcrBankTypeFromString;
--
2.34.1



[PATCH v4 1/8] conf: Introduce virDomainInputDefRemove and fix memory leak

2021-12-03 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.c   | 12 
 src/conf/domain_conf.h   |  2 ++
 src/libvirt_private.syms |  1 +
 src/qemu/qemu_driver.c   |  3 ++-
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index bdcc3dc2c1..d6f69b3ace 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16874,6 +16874,18 @@ virDomainInputDefFind(const virDomainDef *def,
 }
 
 
+virDomainInputDef *
+virDomainInputDefRemove(virDomainDef *def,
+size_t idx)
+{
+virDomainInputDef *ret = def->inputs[idx];
+
+VIR_DELETE_ELEMENT(def->inputs, idx, def->ninputs);
+
+return ret;
+}
+
+
 bool
 virDomainVsockDefEquals(const virDomainVsockDef *a,
 const virDomainVsockDef *b)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c0c07ea6ba..e4259bf890 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3852,6 +3852,8 @@ virDomainShmemDef *virDomainShmemDefRemove(virDomainDef 
*def, size_t idx)
 ssize_t virDomainInputDefFind(const virDomainDef *def,
   const virDomainInputDef *input)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+virDomainInputDef *virDomainInputDefRemove(virDomainDef *def, size_t idx)
+ATTRIBUTE_NONNULL(1);
 bool virDomainVsockDefEquals(const virDomainVsockDef *a,
  const virDomainVsockDef *b)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7be5b51100..338207b235 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -479,6 +479,7 @@ virDomainInputBusTypeToString;
 virDomainInputDefFind;
 virDomainInputDefFree;
 virDomainInputDefGetPath;
+virDomainInputDefRemove;
 virDomainInputSourceGrabToggleTypeFromString;
 virDomainInputSourceGrabToggleTypeToString;
 virDomainInputSourceGrabTypeFromString;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6333d0af36..bef2465e57 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7632,7 +7632,8 @@ qemuDomainDetachDeviceConfig(virDomainDef *vmdef,
_("matching input device not found"));
 return -1;
 }
-VIR_DELETE_ELEMENT(vmdef->inputs, idx, vmdef->ninputs);
+
+virDomainInputDefFree(virDomainInputDefRemove(vmdef, idx));
 break;
 
 case VIR_DOMAIN_DEVICE_VSOCK:
-- 
2.34.1



[PATCH v4 3/8] conf: Add virDomainDeviceTypeFlags and use it in various drivers

2021-12-03 Thread Luke Yue
Declare and use virDomainDeviceDefOperationsCallbacks in test / QEMU /
LXC / libxl drivers to store detachable devices that driver support,
this would be useful in future.

Also add test driver's memballoon device detach function and QEMU
driver's char device detach function to their xmlopt.

Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.h   | 31 ++
 src/libxl/libxl_conf.c   |  3 ++-
 src/libxl/libxl_domain.c |  8 +++
 src/libxl/libxl_domain.h |  1 +
 src/lxc/lxc_conf.c   |  3 ++-
 src/lxc/lxc_domain.c |  7 ++
 src/lxc/lxc_domain.h |  1 +
 src/qemu/qemu_conf.c |  2 +-
 src/qemu/qemu_domain.c   | 39 +
 src/qemu/qemu_domain.h   |  6 +
 src/test/test_driver.c   | 47 +++-
 11 files changed, 144 insertions(+), 4 deletions(-)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1b092b2ee5..070cb40509 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -90,6 +90,37 @@ typedef enum {
 VIR_DOMAIN_DEVICE_LAST
 } virDomainDeviceType;
 
+typedef enum {
+VIR_DOMAIN_DEVICE_FLAG_NONE = (1 << VIR_DOMAIN_DEVICE_NONE),
+VIR_DOMAIN_DEVICE_FLAG_DISK = (1 << VIR_DOMAIN_DEVICE_DISK),
+VIR_DOMAIN_DEVICE_FLAG_LEASE = (1 << VIR_DOMAIN_DEVICE_LEASE),
+VIR_DOMAIN_DEVICE_FLAG_FS = (1 << VIR_DOMAIN_DEVICE_FS),
+VIR_DOMAIN_DEVICE_FLAG_NET = (1 << VIR_DOMAIN_DEVICE_NET),
+VIR_DOMAIN_DEVICE_FLAG_INPUT = (1 << VIR_DOMAIN_DEVICE_INPUT),
+VIR_DOMAIN_DEVICE_FLAG_SOUND = (1 << VIR_DOMAIN_DEVICE_SOUND),
+VIR_DOMAIN_DEVICE_FLAG_VIDEO = (1 << VIR_DOMAIN_DEVICE_VIDEO),
+VIR_DOMAIN_DEVICE_FLAG_HOSTDEV = (1 << VIR_DOMAIN_DEVICE_HOSTDEV),
+VIR_DOMAIN_DEVICE_FLAG_WATCHDOG = (1 << VIR_DOMAIN_DEVICE_WATCHDOG),
+VIR_DOMAIN_DEVICE_FLAG_CONTROLLER = (1 << VIR_DOMAIN_DEVICE_CONTROLLER),
+VIR_DOMAIN_DEVICE_FLAG_GRAPHICS = (1 << VIR_DOMAIN_DEVICE_GRAPHICS),
+VIR_DOMAIN_DEVICE_FLAG_HUB = (1 << VIR_DOMAIN_DEVICE_HUB),
+VIR_DOMAIN_DEVICE_FLAG_REDIRDEV = (1 << VIR_DOMAIN_DEVICE_REDIRDEV),
+VIR_DOMAIN_DEVICE_FLAG_SMARTCARD = (1 << VIR_DOMAIN_DEVICE_SMARTCARD),
+VIR_DOMAIN_DEVICE_FLAG_CHR = (1 << VIR_DOMAIN_DEVICE_CHR),
+VIR_DOMAIN_DEVICE_FLAG_MEMBALLOON = (1 << VIR_DOMAIN_DEVICE_MEMBALLOON),
+VIR_DOMAIN_DEVICE_FLAG_NVRAM = (1 << VIR_DOMAIN_DEVICE_NVRAM),
+VIR_DOMAIN_DEVICE_FLAG_RNG = (1 << VIR_DOMAIN_DEVICE_RNG),
+VIR_DOMAIN_DEVICE_FLAG_SHMEM = (1 << VIR_DOMAIN_DEVICE_SHMEM),
+VIR_DOMAIN_DEVICE_FLAG_TPM = (1 << VIR_DOMAIN_DEVICE_TPM),
+VIR_DOMAIN_DEVICE_FLAG_PANIC = (1 << VIR_DOMAIN_DEVICE_PANIC),
+VIR_DOMAIN_DEVICE_FLAG_MEMORY = (1 << VIR_DOMAIN_DEVICE_MEMORY),
+VIR_DOMAIN_DEVICE_FLAG_IOMMU = (1 << VIR_DOMAIN_DEVICE_IOMMU),
+VIR_DOMAIN_DEVICE_FLAG_VSOCK = (1 << VIR_DOMAIN_DEVICE_VSOCK),
+VIR_DOMAIN_DEVICE_FLAG_AUDIO = (1 << VIR_DOMAIN_DEVICE_AUDIO),
+
+VIR_DOMAIN_DEVICE_FLAG_LAST = (1 << VIR_DOMAIN_DEVICE_LAST)
+} virDomainDeviceTypeFlags;
+
 struct _virDomainDeviceDef {
 int type; /* enum virDomainDeviceType */
 union {
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index a586454f23..4ff790ecfe 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -2505,5 +2505,6 @@ libxlCreateXMLConf(libxlDriverPrivate *driver)
 return virDomainXMLOptionNew(&libxlDomainDefParserConfig,
  &libxlDomainXMLPrivateDataCallbacks,
  &libxlDriverDomainXMLNamespace,
- NULL, NULL, NULL);
+ NULL, NULL,
+ &libxlDriverDeviceDefOpsCallbacks);
 }
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 366e3b9263..55152f9405 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -1603,3 +1603,11 @@ virXMLNamespace libxlDriverDomainXMLNamespace = {
 .prefix = "xen",
 .uri = "http://libvirt.org/schemas/domain/xen/1.0";,
 };
+
+
+virDomainDeviceDefOperationsCallbacks libxlDriverDeviceDefOpsCallbacks = {
+.detachFlags = VIR_DOMAIN_DEVICE_FLAG_DISK |
+   VIR_DOMAIN_DEVICE_FLAG_NET |
+   VIR_DOMAIN_DEVICE_FLAG_HOSTDEV |
+   VIR_DOMAIN_DEVICE_FLAG_CONTROLLER,
+};
diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h
index 981bfc2bca..1534597cd9 100644
--- a/src/libxl/libxl_domain.h
+++ b/src/libxl/libxl_domain.h
@@ -68,6 +68,7 @@ struct _libxlDomainObjPrivate {
 extern virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks;
 extern virDomainDefParserConfig libxlDomainDefParserConfig;
 extern virXMLNamespace libxlDriverDomainXMLNamespace;
+extern virDomainDeviceDefOperationsCallbacks libxlDriverDeviceDefOpsCallbacks;
 ex

Re: [PATCH 2/3] virsh: Add '--full-seclabels' option for dominfo

2021-11-30 Thread Luke Yue
On Mon, 2021-11-29 at 17:52 +0100, Martin Kletzander wrote:
> On Thu, Sep 02, 2021 at 08:29:35PM +0800, Luke Yue wrote:
> > There is no virsh command uses virDomainGetSecurityLabelList API,
> > so add
> > an option for dominfo to call it and print full list of security
> > labels.
> > 
> > Also realign some outputs as it's now "Security labels:" instead of
> > "Security label:".
> > 
> 
> This should go into separate patch as that makes it nicer to review
> and
> the separation of changes makes it more clear.
> 

Thanks for the review! I will split this in next version.

> > Signed-off-by: Luke Yue 
> > ---
> > docs/manpages/virsh.rst  |  5 +-
> > tests/virsh-undefine |  8 ++--
> > tests/virshtest.c    | 70 ++--
> > tools/virsh-domain-monitor.c | 89 -
> > ---
> > 4 files changed, 101 insertions(+), 71 deletions(-)
> > 
> > diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-
> > monitor.c
> > index f7cf82acdf..2b2746e713 100644
> > --- a/tools/virsh-domain-monitor.c
> > +++ b/tools/virsh-domain-monitor.c
> > @@ -1299,29 +1304,53 @@ cmdDominfo(vshControl *ctl, const vshCmd
> > *cmd)
> >     } else {
> >     /* Only print something if a security model is active */
> >     if (secmodel.model[0] != '\0') {
> > -    vshPrint(ctl, "%-15s %s\n", _("Security model:"),
> > secmodel.model);
> > -    vshPrint(ctl, "%-15s %s\n", _("Security DOI:"),
> > secmodel.doi);
> > -
> > -    /* Security labels are only valid for active domains
> > */
> > -    seclabel = g_new0(virSecurityLabel, 1);
> > +    vshPrint(ctl, "%-16s %s\n", _("Security model:"),
> > secmodel.model);
> > +    vshPrint(ctl, "%-16s %s\n", _("Security DOI:"),
> > secmodel.doi);
> > +
> > +    if (fullseclabels) {
> > +    int len;
> > +    size_t i;
> > +
> > +    if ((len = virDomainGetSecurityLabelList(dom,
> > &seclabel)) < 0) {
> > +    g_clear_pointer(&(seclabel), g_free);
> > +    return false;
> > +    } else {
> 
> No need for else branch when the first branch returns.
> 
> > +    for (i = 0; i < len; i++)
> > +    if (seclabel[i].label[0] != '\0')
> > +    vshPrint(ctl, "%-16s %s (%s)\n",
> > + i == 0 ? _("Security
> > labels:") : "",
> > + seclabel[i].label,
> > + seclabel[i].enforcing ?
> > + "enforcing" :
> > + "permissive");
> > +    }
> > 
> > -    if (virDomainGetSecurityLabel(dom, seclabel) == -1) {
> > -    VIR_FREE(seclabel);
> > -    return false;
> > +    g_clear_pointer(&seclabel, g_free);
> >     } else {
> > -    if (seclabel->label[0] != '\0')
> > -    vshPrint(ctl, "%-15s %s (%s)\n", _("Security
> > label:"),
> > - seclabel->label, seclabel->enforcing
> > ? "enforcing" : "permissive");
> > -    }
> > +    /* Security labels are only valid for active
> > domains */
> > +    seclabel = g_new0(virSecurityLabel, 1);
> > +
> > +    if (virDomainGetSecurityLabel(dom, seclabel) == -
> > 1) {
> 
> You properly used `< 0` before, this should do the same then.
> 
> > +    g_clear_pointer(&seclabel, g_free);
> > +    return false;
> > +    } else {
> 
> Again, no need for an else branch when if branch returns.
> 

OK, I will fix these and take the suggestion for 1/3 

> Otherwise it looks good.

Thanks,
Luke



Re: [PATCH v3 12/12] tests: Test detach-device and detach-device-alias for test driver

2021-11-29 Thread Luke Yue
On Mon, 2021-11-29 at 15:50 +0100, Martin Kletzander wrote:
> On Mon, Nov 29, 2021 at 10:41:51PM +0800, Luke Yue wrote:
> > On Fri, 2021-11-26 at 16:44 +0100, Martin Kletzander wrote:
> > > On Wed, Nov 10, 2021 at 10:24:31PM +0800, Luke Yue wrote:
> > > > Signed-off-by: Luke Yue 
> > > > ---
> > > > tests/virshtest.c | 96
> > > > +++
> > > > 1 file changed, 96 insertions(+)
> > > > 
> > > 
> > > This makes the tests very fragile.  It would be even easier to do
> > > the
> > > test using the internal APIs, similarly to how we do it with the
> > > qemuhotplugtest.
> > > 
> > 
> > Thanks for the explanation, I will look into how qemuhotplugtest is
> > implemented.
> > 
> > > > diff --git a/tests/virshtest.c b/tests/virshtest.c
> > > > index af2a70f5fb..8e5b397420 100644
> > > > --- a/tests/virshtest.c
> > > > +++ b/tests/virshtest.c
> > > > @@ -160,6 +160,8 @@ static char *custom_uri;
> > > >     "--connect", \
> > > >     custom_uri
> > > > 
> > > > +# define TEST_XML_PATH abs_top_builddir
> > > > "/../examples/xml/test"
> > > > +
> > > > static int testCompareListDefault(const void *data
> > > > G_GNUC_UNUSED)
> > > > {
> > > >     const char *const argv[] = { VIRSH_DEFAULT, "list", NULL };
> > > > @@ -437,6 +439,88 @@ static int testIOThreadPin(const void
> > > > *data
> > > > G_GNUC_UNUSED)
> > > >     return testCompareOutputLit(exp, "", NULL, argv);
> > > > }
> > > > 
> > > > +static int testCompareDetachDevice(const void *data
> > > > G_GNUC_UNUSED)
> > > > +{
> > > > +    const char *const argv[] = { VIRSH_CUSTOM, "detach-device
> > > > fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevif.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevdiskcdrom.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevsound.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevhostdev.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevlease.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevcontroller.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevfs.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevrng.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevmem.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevshmem.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevwatchdog.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevinput.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevvsock.xml;\
> > > > + detach-device fc5\
> > > > + " TEST_XML_PATH
> > > > "/testdevtpm.xml",
> > > > + NULL };
> > > > +    const char *exp =
> > > > +"Device detached su

Re: [PATCH v3 02/12] domain_driver: extract DetachXXXDeviceConfig related functions and use them

2021-11-29 Thread Luke Yue
On Mon, 2021-11-29 at 15:33 +0100, Martin Kletzander wrote:
> On Mon, Nov 29, 2021 at 09:06:57PM +0800, Luke Yue wrote:
> > On Fri, 2021-11-26 at 16:43 +0100, Martin Kletzander wrote:
> > > On Wed, Nov 10, 2021 at 10:24:21PM +0800, Luke Yue wrote:
> > > > libxl / lxc / qemu drivers share some common codes in their
> > > > DomainDetachDeviceConfig functions, so extract them to
> > > > domain_driver and
> > > > reuse them.
> > > > 
> > > 
> > > I would argue that these specific functions are actually dealing
> > > just
> > > with the domain definition which is done mostly in domain_conf.c,
> > > so
> > > I
> > > would pick that place.
> > > 
> > 
> > Thanks for the review! No problem, I would move the code to
> > domain_conf.c in next version.
> > 
> > > > At the same time, this will enable test driver to test these
> > > > functions
> > > > with virshtest in the future.
> > > > 
> > > > Signed-off-by: Luke Yue 
> > > > ---
> > > > Not pretty sure whether this is a proper way to make these
> > > > functions
> > > > reusable, maybe there is a more elegant choice.
> > > 
> > > The patch does a good job in deduplicating some of the code and
> > > except
> > > the file placement I think the overall approach is fine.
> > > 
> > > However unfortunately the functions are just copy-paste from
> > > various
> > > places and they could be cleaned up to look the same.  For
> > > example...
> > > 
> > > > ---
> > > > src/hypervisor/domain_driver.c | 266
> > > > +
> > > > src/hypervisor/domain_driver.h |  41 +
> > > > src/libvirt_private.syms   |  14 ++
> > > > src/libxl/libxl_driver.c   |  41 +
> > > > src/lxc/lxc_driver.c   |  37 +
> > > > src/qemu/qemu_driver.c | 123 +++
> > > > 6 files changed, 356 insertions(+), 166 deletions(-)
> > > > 
> > > > diff --git a/src/hypervisor/domain_driver.c
> > > > b/src/hypervisor/domain_driver.c
> > > > index 31737b0f4a..01ecb4e30e 100644
> > > > --- a/src/hypervisor/domain_driver.c
> > > > +++ b/src/hypervisor/domain_driver.c
> > > > @@ -644,3 +644,269 @@
> > > > virDomainDriverGetIOThreadsConfig(virDomainDef *targetDef,
> > > > 
> > > >     return ret;
> > > > }
> > > > +
> > > > +
> > > > +int
> > > > +virDomainDriverDetachDiskDeviceConfig(virDomainDef *vmdef,
> > > > +  virDomainDeviceDef *dev)
> > > > +{
> > > > +    virDomainDiskDef *disk;
> > > > +    virDomainDiskDef *det_disk;
> > > > +
> > > > +    disk = dev->data.disk;
> > > > +    if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk-
> > > > >dst)))
> > > > {
> > > > +    virReportError(VIR_ERR_DEVICE_MISSING, _("no target
> > > > device
> > > > %s"),
> > > > +   disk->dst);
> > > > +    return -1;
> > > > +    }
> > > > +    virDomainDiskDefFree(det_disk);
> > > > +
> > > > +    return 0;
> > > 
> > > This function uses temporary variables for everything and adds an
> > > error
> > > message (which could be moved to the virDomainDiskRemoveByName()
> > > as
> > > all
> > > callers do report the same error message when it is not found. 
> > > Other
> > > functions do essentially the same job, but have random comments,
> > > some
> > > have extra helper variables. All that could be nicely unified and
> > > it
> > > would read so much nicer.
> > > 
> > > What I really like about this change is that apart from roughly
> > > two
> > > device types, like video and chardev, this function could be
> > > de-duplicated as well.  Adding a new functionality to that de-
> > > duplicated
> > > function would then add that functionality into all the drivers
> > > using
> > > this function.  Of course the special devices would need some
> > > xmlopt
> > > callbacks or something that drivers can modify themselves for
> > > such
> > > reasons, but such change would be really, really helpful,
> > > especially
> > > in
> > > the long term.
> > 
> > So if I understand you correctly, I will unified all these
> > functions
> > into one,
> 
> Not really into one, although if you figure out a way to make that
> easily possible feel free to go on, what I meant make them look and
> read
> the same.
> 
> > just like the original ones for QEMU / lxc / libxl, but this
> > one is for all, and maybe I should create a new enum for flags of
> > detachable device that different hypervisor support, and xmlopt etc
> > for
> > special devices. I will do that in next version.
> > 
> 
> Deduplicating the bigger function would be nice to have for the
> future,
> it does not need to happen together in this one.  It will require
> some
> more work to make it "modular" enough to be used by various drivers.

OK, thanks, now I see.



Re: [PATCH v3 12/12] tests: Test detach-device and detach-device-alias for test driver

2021-11-29 Thread Luke Yue
On Fri, 2021-11-26 at 16:44 +0100, Martin Kletzander wrote:
> On Wed, Nov 10, 2021 at 10:24:31PM +0800, Luke Yue wrote:
> > Signed-off-by: Luke Yue 
> > ---
> > tests/virshtest.c | 96
> > +++
> > 1 file changed, 96 insertions(+)
> > 
> 
> This makes the tests very fragile.  It would be even easier to do the
> test using the internal APIs, similarly to how we do it with the
> qemuhotplugtest.
> 

Thanks for the explanation, I will look into how qemuhotplugtest is
implemented.

> > diff --git a/tests/virshtest.c b/tests/virshtest.c
> > index af2a70f5fb..8e5b397420 100644
> > --- a/tests/virshtest.c
> > +++ b/tests/virshtest.c
> > @@ -160,6 +160,8 @@ static char *custom_uri;
> >     "--connect", \
> >     custom_uri
> > 
> > +# define TEST_XML_PATH abs_top_builddir "/../examples/xml/test"
> > +
> > static int testCompareListDefault(const void *data G_GNUC_UNUSED)
> > {
> >     const char *const argv[] = { VIRSH_DEFAULT, "list", NULL };
> > @@ -437,6 +439,88 @@ static int testIOThreadPin(const void *data
> > G_GNUC_UNUSED)
> >     return testCompareOutputLit(exp, "", NULL, argv);
> > }
> > 
> > +static int testCompareDetachDevice(const void *data G_GNUC_UNUSED)
> > +{
> > +    const char *const argv[] = { VIRSH_CUSTOM, "detach-device fc5\
> > + " TEST_XML_PATH "/testdevif.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevdiskcdrom.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevsound.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevhostdev.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevlease.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevcontroller.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH "/testdevfs.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevrng.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevmem.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevshmem.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevwatchdog.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevinput.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevvsock.xml;\
> > + detach-device fc5\
> > + " TEST_XML_PATH
> > "/testdevtpm.xml",
> > + NULL };
> > +    const char *exp =
> > +"Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n\
> > +Device detached successfully\n\n";
> 
> If any of these fails it will be a pain to figure out which one it
> was
> if the error message does not include the name.  Splitting these is
> definitely the way to go.
> 
> > +    return testCompareOutputLit(exp, "", NULL, argv);
> > +}
> > +
> > +static int testCompareDetachDeviceError(const void *data
> > G_GNUC_UNUSED)
> > +{
> > +    const char *const argv[] = { VIRSH_CUSTOM, "detach-device fc5\
> > +

Re: [PATCH v3 08/12] conf: Add a memballoon helper for future use

2021-11-29 Thread Luke Yue
On Fri, 2021-11-26 at 16:44 +0100, Martin Kletzander wrote:
> On Wed, Nov 10, 2021 at 10:24:27PM +0800, Luke Yue wrote:
> > Currently it will only be used in test driver.
> > 
> > Signed-off-by: Luke Yue 
> > ---
> > src/conf/domain_conf.c   | 24 
> > src/conf/domain_conf.h   |  4 
> > src/libvirt_private.syms |  1 +
> > 3 files changed, 29 insertions(+)
> > 
> > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> > index 512bfab9e9..92a8bd63f3 100644
> > --- a/src/conf/domain_conf.c
> > +++ b/src/conf/domain_conf.c
> > @@ -16998,6 +16998,30 @@ virDomainTPMDefRemove(virDomainDef *def,
> > }
> > 
> > 
> > +bool
> > +virDomainMemballoonDefEquals(const virDomainMemballoonDef *a,
> > + const virDomainMemballoonDef *b)
> 
> It is really weird that you picked the membaloon as that particular
> one
> does not really make sense to be present multiple times, it is
> similar
> to the watchdog device.  It is not a problem in this case, but I feel
> like this function is a bit useless.

Oh, sorry, I didn't realize that, I forgot that the device would just
present once, so that we can just remove the device without comparison,
I will remove the comparison function.

Thanks,
Luke 



Re: [PATCH v3 06/12] conf: Add tpm helpers for future use

2021-11-29 Thread Luke Yue
On Fri, 2021-11-26 at 16:43 +0100, Martin Kletzander wrote:
> On Wed, Nov 10, 2021 at 10:24:25PM +0800, Luke Yue wrote:
> > Currently it will only be used in the test driver.
> > 
> > Signed-off-by: Luke Yue 
> > ---
> > src/conf/domain_conf.c   | 67
> > 
> > src/conf/domain_conf.h   |  6 
> > src/libvirt_private.syms |  2 ++
> > 3 files changed, 75 insertions(+)
> > 
> > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> > index 3193120b79..512bfab9e9 100644
> > --- a/src/conf/domain_conf.c
> > +++ b/src/conf/domain_conf.c
> > @@ -16931,6 +16931,73 @@ virDomainVsockDefEquals(const
> > virDomainVsockDef *a,
> > }
> > 
> > 
> > +static bool
> > +virDomainTPMDefEquals(const virDomainTPMDef *a,
> > +  const virDomainTPMDef *b)
> > +{
> > +    if (a->type != b->type)
> > +    return false;
> > +
> > +    if (a->model != b->model)
> > +    return false;
> > +
> > +    if (a->version != b->version)
> > +    return false;
> > +
> > +    if (a->type == VIR_DOMAIN_TPM_TYPE_PASSTHROUGH) {
> > +    if (STRNEQ_NULLABLE(a-
> > >data.passthrough.source.data.file.path,
> > +    b-
> > >data.passthrough.source.data.file.path))
> 
> This will not compile as `source` is a pointer here.
> 

I just noticed in commit 42b, the `source` was changed to be a
pointer, will fix in next version.

> > +    return false;
> > +    } else {
> > +    if (a->data.emulator.hassecretuuid != b-
> > >data.emulator.hassecretuuid)
> > +    return false;
> > +
> > +    if (a->data.emulator.hassecretuuid == true &&
> > +    memcmp(a->data.emulator.secretuuid,
> > +   b->data.emulator.secretuuid,
> > +   VIR_UUID_BUFLEN))
> > +    return false;
> > +
> > +    if (a->data.emulator.persistent_state !=
> > +    b->data.emulator.persistent_state)
> 
> Also it would make sense to try to detach a device without all the
> information, e.g. those that libvirt itself adds by default if they
> are
> missing, or in this case when persistent_state is set to the
> specified
> default (in formatdomain.html this is said to be "no" currently, but
> not
> filled in).  Luckily the test driver itself does not do any of this,
> so
> I guess it's fine here.

Hmm, I will look into how libvirt adds these default devices and refine
this function in next version or in the future.

Thanks,
Luke



Re: [PATCH v3 03/12] test_driver: Implement virDomainDetachDeviceFlags

2021-11-29 Thread Luke Yue
On Fri, 2021-11-26 at 16:43 +0100, Martin Kletzander wrote:
> On Wed, Nov 10, 2021 at 10:24:22PM +0800, Luke Yue wrote:
> > Introduce testDomainChgDevice for further development (just like
> > what we
> > did for IOThread). And introduce
> > testDomainDetachDeviceLiveAndConfig for
> > detaching devices.
> > 
> > Signed-off-by: Luke Yue 
> > ---
> > src/test/test_driver.c | 202
> > +
> > 1 file changed, 202 insertions(+)
> > 
> > diff --git a/src/test/test_driver.c b/src/test/test_driver.c
> > index ea474d55ac..6a7eb12f77 100644
> > --- a/src/test/test_driver.c
> > +++ b/src/test/test_driver.c
> > @@ -10051,6 +10051,207 @@
> > testConnectGetAllDomainStats(virConnectPtr conn,
> >     return ret;
> > }
> > 
> > +static int
> > +testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
> > +    virDomainDeviceDef *dev)
> 
> My comment from the previous patch would be nicely usable here as we
> could easily just make use of it.
> 
> Also I see no reason for splitting the next two patches from this
> one.
> 

OK, I will squash them in next version.

> [...]
> 
> > +
> > +static int
> > +testDomainChgDevice(virDomainPtr dom,
> > +    virDomainDeviceAction action,
> > +    const char *xml,
> > +    const char *alias,
> > +    unsigned int flags)
> > +{
> > +    testDriver *driver = dom->conn->privateData;
> > +    virDomainObj *vm = NULL;
> > +    virDomainDef *def;
> > +    virDomainDeviceDef *dev = NULL;
> > +    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
> > +    int ret = -1;
> > +
> > +    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
> > +  VIR_DOMAIN_AFFECT_CONFIG, -1);
> 
> So here you check for both live and config, saying both of them are
> supported, ...
> 
> > +
> > +    if (!(vm = testDomObjFromDomain(dom)))
> > +    goto cleanup;
> > +
> > +    if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
> > +    goto cleanup;
> > +
> > +    if (!(def = virDomainObjGetOneDef(vm, flags)))
> > +    goto cleanup;
> > +
> 
> But here it would fail with both since you are explicitly saying you
> want just one definition.
> 
> > +    if (action == VIR_DOMAIN_DEVICE_ACTION_DETACH)
> > +    parse_flags |= VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
> > +
> > +    if (xml) {
> > +    if (!(dev = virDomainDeviceDefParse(xml, def, driver-
> > >xmlopt,
> > +    driver->caps,
> > parse_flags)))
> > +    goto cleanup;
> > +    } else if (alias) {
> > +    dev = g_new0(virDomainDeviceDef, 1);
> > +    if (virDomainDefFindDevice(def, alias, dev, true) < 0)
> > +    goto cleanup;
> > +    }
> > +
> > +    if (dev == NULL)
> > +    goto cleanup;
> > +
> > +    switch (action) {
> > +    case VIR_DOMAIN_DEVICE_ACTION_ATTACH:
> > +    virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
> > +   _("attaching devices is not supported"));
> > +    goto cleanup;
> > +    break;
> > +
> > +    case VIR_DOMAIN_DEVICE_ACTION_DETACH:
> > +    if (testDomainDetachDeviceLiveAndConfig(def, dev) < 0)
> 
> And I kind of see now why you call the function "LiveAndConfig" since
> it
> can do both based on what DomainDef you call it with.  This function
> could be very easily modified to do both live and config properly.

Sorry, I missed that situation, will fix it in next version.

Thanks,
Luke



Re: [PATCH v3 02/12] domain_driver: extract DetachXXXDeviceConfig related functions and use them

2021-11-29 Thread Luke Yue
On Fri, 2021-11-26 at 16:43 +0100, Martin Kletzander wrote:
> On Wed, Nov 10, 2021 at 10:24:21PM +0800, Luke Yue wrote:
> > libxl / lxc / qemu drivers share some common codes in their
> > DomainDetachDeviceConfig functions, so extract them to
> > domain_driver and
> > reuse them.
> > 
> 
> I would argue that these specific functions are actually dealing just
> with the domain definition which is done mostly in domain_conf.c, so
> I
> would pick that place.
> 

Thanks for the review! No problem, I would move the code to
domain_conf.c in next version.

> > At the same time, this will enable test driver to test these
> > functions
> > with virshtest in the future.
> > 
> > Signed-off-by: Luke Yue 
> > ---
> > Not pretty sure whether this is a proper way to make these
> > functions
> > reusable, maybe there is a more elegant choice.
> 
> The patch does a good job in deduplicating some of the code and
> except
> the file placement I think the overall approach is fine.
> 
> However unfortunately the functions are just copy-paste from various
> places and they could be cleaned up to look the same.  For example...
> 
> > ---
> > src/hypervisor/domain_driver.c | 266
> > +
> > src/hypervisor/domain_driver.h |  41 +
> > src/libvirt_private.syms   |  14 ++
> > src/libxl/libxl_driver.c   |  41 +
> > src/lxc/lxc_driver.c   |  37 +
> > src/qemu/qemu_driver.c | 123 +++
> > 6 files changed, 356 insertions(+), 166 deletions(-)
> > 
> > diff --git a/src/hypervisor/domain_driver.c
> > b/src/hypervisor/domain_driver.c
> > index 31737b0f4a..01ecb4e30e 100644
> > --- a/src/hypervisor/domain_driver.c
> > +++ b/src/hypervisor/domain_driver.c
> > @@ -644,3 +644,269 @@
> > virDomainDriverGetIOThreadsConfig(virDomainDef *targetDef,
> > 
> >     return ret;
> > }
> > +
> > +
> > +int
> > +virDomainDriverDetachDiskDeviceConfig(virDomainDef *vmdef,
> > +  virDomainDeviceDef *dev)
> > +{
> > +    virDomainDiskDef *disk;
> > +    virDomainDiskDef *det_disk;
> > +
> > +    disk = dev->data.disk;
> > +    if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst)))
> > {
> > +    virReportError(VIR_ERR_DEVICE_MISSING, _("no target device
> > %s"),
> > +   disk->dst);
> > +    return -1;
> > +    }
> > +    virDomainDiskDefFree(det_disk);
> > +
> > +    return 0;
> 
> This function uses temporary variables for everything and adds an
> error
> message (which could be moved to the virDomainDiskRemoveByName() as
> all
> callers do report the same error message when it is not found.  Other
> functions do essentially the same job, but have random comments, some
> have extra helper variables. All that could be nicely unified and it
> would read so much nicer.
> 
> What I really like about this change is that apart from roughly two
> device types, like video and chardev, this function could be
> de-duplicated as well.  Adding a new functionality to that de-
> duplicated
> function would then add that functionality into all the drivers using
> this function.  Of course the special devices would need some xmlopt
> callbacks or something that drivers can modify themselves for such
> reasons, but such change would be really, really helpful, especially
> in
> the long term.

So if I understand you correctly, I will unified all these functions
into one, just like the original ones for QEMU / lxc / libxl, but this
one is for all, and maybe I should create a new enum for flags of
detachable device that different hypervisor support, and xmlopt etc for
special devices. I will do that in next version.

Thanks,
Luke



[PATCH v3 12/12] tests: Test detach-device and detach-device-alias for test driver

2021-11-10 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 96 +++
 1 file changed, 96 insertions(+)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index af2a70f5fb..8e5b397420 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -160,6 +160,8 @@ static char *custom_uri;
 "--connect", \
 custom_uri
 
+# define TEST_XML_PATH abs_top_builddir "/../examples/xml/test"
+
 static int testCompareListDefault(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_DEFAULT, "list", NULL };
@@ -437,6 +439,88 @@ static int testIOThreadPin(const void *data G_GNUC_UNUSED)
 return testCompareOutputLit(exp, "", NULL, argv);
 }
 
+static int testCompareDetachDevice(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "detach-device fc5\
+ " TEST_XML_PATH "/testdevif.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevdiskcdrom.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevsound.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevhostdev.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevlease.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevcontroller.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevfs.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevrng.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevmem.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevshmem.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevwatchdog.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevinput.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevvsock.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevtpm.xml",
+ NULL };
+const char *exp =
+"Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n";
+return testCompareOutputLit(exp, "", NULL, argv);
+}
+
+static int testCompareDetachDeviceError(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "detach-device fc5\
+ " TEST_XML_PATH "/testdevtpm.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevtpm.xml;\
+ detach-device fc5 --live\
+ " TEST_XML_PATH "/testdevmemballoon.xml",
+ NULL };
+const char *exp =
+"Device detached successfully\n\n\n\n";
+const char *error_msg =
+"error: Failed to detach device from " TEST_XML_PATH "/testdevtpm.xml\n\
+error: device not found: matching tpm device not found\n\
+error: Failed to detach device from " TEST_XML_PATH "/testdevmemballoon.xml\n\
+error: Operation not supported: detach of device 'memballoon' on running 
domain is not supported\n";
+return testCompareOutputLit(exp, error_msg, NULL, argv);
+}
+
+static int testCompareDetachDeviceAlias(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM,
+ "detach-device-alias fc5 ua-testCD;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevdiskcdrom.xml",
+ NULL };
+const char *exp = "Device detach request sent successfully\n\n\n";
+const char *error_msg =
+"error: Failed to detach device from " TEST_XML_PATH "/t

[PATCH v3 10/12] examples: xml: test: add xml for testing devices related APIs

2021-11-10 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 examples/xml/test/testdevcontroller.xml |  1 +
 examples/xml/test/testdevdiskcdrom.xml  |  5 +++
 examples/xml/test/testdevfs.xml |  6 +++
 examples/xml/test/testdevhostdev.xml|  5 +++
 examples/xml/test/testdevif.xml |  6 +++
 examples/xml/test/testdevinput.xml  |  1 +
 examples/xml/test/testdevlease.xml  |  5 +++
 examples/xml/test/testdevmem.xml|  6 +++
 examples/xml/test/testdevmemballoon.xml |  3 ++
 examples/xml/test/testdevrng.xml|  4 ++
 examples/xml/test/testdevshmem.xml  |  4 ++
 examples/xml/test/testdevsound.xml  |  3 ++
 examples/xml/test/testdevtpm.xml|  5 +++
 examples/xml/test/testdevvsock.xml  |  3 ++
 examples/xml/test/testdevwatchdog.xml   |  1 +
 examples/xml/test/testdomfc5.xml| 54 +
 examples/xml/test/testnodeinline.xml| 54 +
 17 files changed, 166 insertions(+)
 create mode 100644 examples/xml/test/testdevcontroller.xml
 create mode 100644 examples/xml/test/testdevdiskcdrom.xml
 create mode 100644 examples/xml/test/testdevfs.xml
 create mode 100644 examples/xml/test/testdevhostdev.xml
 create mode 100644 examples/xml/test/testdevif.xml
 create mode 100644 examples/xml/test/testdevinput.xml
 create mode 100644 examples/xml/test/testdevlease.xml
 create mode 100644 examples/xml/test/testdevmem.xml
 create mode 100644 examples/xml/test/testdevmemballoon.xml
 create mode 100644 examples/xml/test/testdevrng.xml
 create mode 100644 examples/xml/test/testdevshmem.xml
 create mode 100644 examples/xml/test/testdevsound.xml
 create mode 100644 examples/xml/test/testdevtpm.xml
 create mode 100644 examples/xml/test/testdevvsock.xml
 create mode 100644 examples/xml/test/testdevwatchdog.xml

diff --git a/examples/xml/test/testdevcontroller.xml 
b/examples/xml/test/testdevcontroller.xml
new file mode 100644
index 00..d855bfa17f
--- /dev/null
+++ b/examples/xml/test/testdevcontroller.xml
@@ -0,0 +1 @@
+
diff --git a/examples/xml/test/testdevdiskcdrom.xml 
b/examples/xml/test/testdevdiskcdrom.xml
new file mode 100644
index 00..edc90556bb
--- /dev/null
+++ b/examples/xml/test/testdevdiskcdrom.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/examples/xml/test/testdevfs.xml b/examples/xml/test/testdevfs.xml
new file mode 100644
index 00..cee5ed4ed9
--- /dev/null
+++ b/examples/xml/test/testdevfs.xml
@@ -0,0 +1,6 @@
+
+  
+  
+  
+  
+
diff --git a/examples/xml/test/testdevhostdev.xml 
b/examples/xml/test/testdevhostdev.xml
new file mode 100644
index 00..e364b50f36
--- /dev/null
+++ b/examples/xml/test/testdevhostdev.xml
@@ -0,0 +1,5 @@
+
+  
+/dev/sdf1s
+  
+
diff --git a/examples/xml/test/testdevif.xml b/examples/xml/test/testdevif.xml
new file mode 100644
index 00..7e0be80050
--- /dev/null
+++ b/examples/xml/test/testdevif.xml
@@ -0,0 +1,6 @@
+
+  
+  
+  
+  
+
diff --git a/examples/xml/test/testdevinput.xml 
b/examples/xml/test/testdevinput.xml
new file mode 100644
index 00..d958f5b931
--- /dev/null
+++ b/examples/xml/test/testdevinput.xml
@@ -0,0 +1 @@
+
diff --git a/examples/xml/test/testdevlease.xml 
b/examples/xml/test/testdevlease.xml
new file mode 100644
index 00..c53c0c7e7d
--- /dev/null
+++ b/examples/xml/test/testdevlease.xml
@@ -0,0 +1,5 @@
+
+  testarea
+  testkey
+  
+
diff --git a/examples/xml/test/testdevmem.xml b/examples/xml/test/testdevmem.xml
new file mode 100644
index 00..49efd4af55
--- /dev/null
+++ b/examples/xml/test/testdevmem.xml
@@ -0,0 +1,6 @@
+
+  
+524287
+0
+  
+
diff --git a/examples/xml/test/testdevmemballoon.xml 
b/examples/xml/test/testdevmemballoon.xml
new file mode 100644
index 00..fde18a9db6
--- /dev/null
+++ b/examples/xml/test/testdevmemballoon.xml
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/examples/xml/test/testdevrng.xml b/examples/xml/test/testdevrng.xml
new file mode 100644
index 00..369f423740
--- /dev/null
+++ b/examples/xml/test/testdevrng.xml
@@ -0,0 +1,4 @@
+
+  
+  
+
diff --git a/examples/xml/test/testdevshmem.xml 
b/examples/xml/test/testdevshmem.xml
new file mode 100644
index 00..04bf3d9a53
--- /dev/null
+++ b/examples/xml/test/testdevshmem.xml
@@ -0,0 +1,4 @@
+
+  
+  4
+
diff --git a/examples/xml/test/testdevsound.xml 
b/examples/xml/test/testdevsound.xml
new file mode 100644
index 00..cf7323077f
--- /dev/null
+++ b/examples/xml/test/testdevsound.xml
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/examples/xml/test/testdevtpm.xml b/examples/xml/test/testdevtpm.xml
new file mode 100644
index 00..cc08b7bf6d
--- /dev/null
+++ b/examples/xml/test/testdevtpm.xml
@@ -0,0 +1,5 @@
+
+  
+
+  
+
diff --git a/examples/xml/test/testdevvsock.xml 
b/examples/xml/test/testdevvsock.xml
new file mode 100644
index 00..dda45780c4
--- /dev/null
+++ b/examples/xml/test/testdevvsock.xml
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/examples/xml/test/testdevwatchdog.xml 
b/examples/xml/test/testdevwatchdog.xml

[PATCH v3 09/12] test_driver: add memballoon support for testDomainDetachDeviceLiveAndConfig

2021-11-10 Thread Luke Yue
As the memballoon device shouldn't be hot-(un)pluggable, so error if try
to remove it on a running domain, for removing from config, it's fine.

Signed-off-by: Luke Yue 
---
 src/hypervisor/domain_driver.c | 18 ++
 src/hypervisor/domain_driver.h |  3 +++
 src/libvirt_private.syms   |  1 +
 src/test/test_driver.c | 19 ---
 4 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
index 2461d977a3..0a0ff7b361 100644
--- a/src/hypervisor/domain_driver.c
+++ b/src/hypervisor/domain_driver.c
@@ -928,3 +928,21 @@ virDomainDriverDetachTPMDeviceConfig(virDomainDef *vmdef,
 
 return 0;
 }
+
+
+int
+virDomainDriverDetachMemballoonDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+if (!vmdef->memballoon ||
+!virDomainMemballoonDefEquals(dev->data.memballoon,
+  vmdef->memballoon)) {
+virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+   _("matching memballoon device not found"));
+return -1;
+}
+virDomainMemballoonDefFree(vmdef->memballoon);
+vmdef->memballoon = NULL;
+
+return 0;
+}
diff --git a/src/hypervisor/domain_driver.h b/src/hypervisor/domain_driver.h
index 51dc109c38..5920854b13 100644
--- a/src/hypervisor/domain_driver.h
+++ b/src/hypervisor/domain_driver.h
@@ -114,3 +114,6 @@ int virDomainDriverDetachVsockDeviceConfig(virDomainDef 
*vmdef,
 
 int virDomainDriverDetachTPMDeviceConfig(virDomainDef *vmdef,
  virDomainDeviceDef *dev);
+
+int virDomainDriverDetachMemballoonDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b143537bb4..19cc301a20 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1560,6 +1560,7 @@ virDomainDriverDetachFSDeviceConfig;
 virDomainDriverDetachHostdevDeviceConfig;
 virDomainDriverDetachInputDeviceConfig;
 virDomainDriverDetachLeaseDeviceConfig;
+virDomainDriverDetachMemballoonDeviceConfig;
 virDomainDriverDetachMemoryDeviceConfig;
 virDomainDriverDetachNetDeviceConfig;
 virDomainDriverDetachRedirdevDeviceConfig;
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 15b4332769..317aa0181b 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -10053,7 +10053,8 @@ testConnectGetAllDomainStats(virConnectPtr conn,
 
 static int
 testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
-virDomainDeviceDef *dev)
+virDomainDeviceDef *dev,
+unsigned int flags)
 {
 virDomainChrDef *chr;
 
@@ -10155,11 +10156,23 @@ testDomainDetachDeviceLiveAndConfig(virDomainDef 
*vmdef,
 
 break;
 
+case VIR_DOMAIN_DEVICE_MEMBALLOON:
+if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+   _("detach of device '%s' on running domain "
+ "is not supported"),
+   virDomainDeviceTypeToString(dev->type));
+return -1;
+} else {
+if (virDomainDriverDetachMemballoonDeviceConfig(vmdef, dev) < 0)
+return -1;
+}
+break;
+
 case VIR_DOMAIN_DEVICE_VIDEO:
 case VIR_DOMAIN_DEVICE_GRAPHICS:
 case VIR_DOMAIN_DEVICE_HUB:
 case VIR_DOMAIN_DEVICE_SMARTCARD:
-case VIR_DOMAIN_DEVICE_MEMBALLOON:
 case VIR_DOMAIN_DEVICE_NVRAM:
 case VIR_DOMAIN_DEVICE_NONE:
 case VIR_DOMAIN_DEVICE_PANIC:
@@ -10225,7 +10238,7 @@ testDomainChgDevice(virDomainPtr dom,
 break;
 
 case VIR_DOMAIN_DEVICE_ACTION_DETACH:
-if (testDomainDetachDeviceLiveAndConfig(def, dev) < 0)
+if (testDomainDetachDeviceLiveAndConfig(def, dev, flags) < 0)
 goto cleanup;
 break;
 
-- 
2.33.1



[PATCH v3 06/12] conf: Add tpm helpers for future use

2021-11-10 Thread Luke Yue
Currently it will only be used in the test driver.

Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.c   | 67 
 src/conf/domain_conf.h   |  6 
 src/libvirt_private.syms |  2 ++
 3 files changed, 75 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3193120b79..512bfab9e9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16931,6 +16931,73 @@ virDomainVsockDefEquals(const virDomainVsockDef *a,
 }
 
 
+static bool
+virDomainTPMDefEquals(const virDomainTPMDef *a,
+  const virDomainTPMDef *b)
+{
+if (a->type != b->type)
+return false;
+
+if (a->model != b->model)
+return false;
+
+if (a->version != b->version)
+return false;
+
+if (a->type == VIR_DOMAIN_TPM_TYPE_PASSTHROUGH) {
+if (STRNEQ_NULLABLE(a->data.passthrough.source.data.file.path,
+b->data.passthrough.source.data.file.path))
+return false;
+} else {
+if (a->data.emulator.hassecretuuid != b->data.emulator.hassecretuuid)
+return false;
+
+if (a->data.emulator.hassecretuuid == true &&
+memcmp(a->data.emulator.secretuuid,
+   b->data.emulator.secretuuid,
+   VIR_UUID_BUFLEN))
+return false;
+
+if (a->data.emulator.persistent_state !=
+b->data.emulator.persistent_state)
+return false;
+}
+
+if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+!virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
+return false;
+
+return true;
+}
+
+
+ssize_t
+virDomainTPMDefFind(const virDomainDef *def,
+const virDomainTPMDef *tpm)
+{
+size_t i;
+
+for (i = 0; i < def->ntpms; i++) {
+if (virDomainTPMDefEquals(tpm, def->tpms[i]))
+return i;
+}
+
+return -1;
+}
+
+
+virDomainTPMDef *
+virDomainTPMDefRemove(virDomainDef *def,
+  size_t idx)
+{
+virDomainTPMDef *ret = def->tpms[idx];
+
+VIR_DELETE_ELEMENT(def->tpms, idx, def->ntpms);
+
+return ret;
+}
+
+
 char *
 virDomainDefGetDefaultEmulator(virDomainDef *def,
virCaps *caps)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a089b0b3de..715c8fbd16 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3857,6 +3857,12 @@ bool virDomainVsockDefEquals(const virDomainVsockDef *a,
  const virDomainVsockDef *b)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
 
+ssize_t virDomainTPMDefFind(const virDomainDef *def,
+const virDomainTPMDef *tpm)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+virDomainTPMDef *virDomainTPMDefRemove(virDomainDef *def, size_t idx)
+ATTRIBUTE_NONNULL(1);
+
 VIR_ENUM_DECL(virDomainTaint);
 VIR_ENUM_DECL(virDomainTaintMessage);
 VIR_ENUM_DECL(virDomainVirt);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0252f7c9d6..68cc9c51cb 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -665,7 +665,9 @@ virDomainTimerTrackTypeFromString;
 virDomainTimerTrackTypeToString;
 virDomainTPMBackendTypeFromString;
 virDomainTPMBackendTypeToString;
+virDomainTPMDefFind;
 virDomainTPMDefFree;
+virDomainTPMDefRemove;
 virDomainTPMModelTypeFromString;
 virDomainTPMModelTypeToString;
 virDomainTPMPcrBankTypeFromString;
-- 
2.33.1



[PATCH v3 07/12] test_driver: add TPM support for testDomainDetachDeviceLiveAndConfig

2021-11-10 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/hypervisor/domain_driver.c | 18 ++
 src/hypervisor/domain_driver.h |  3 +++
 src/libvirt_private.syms   |  1 +
 src/test/test_driver.c |  7 ++-
 4 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
index 01ecb4e30e..2461d977a3 100644
--- a/src/hypervisor/domain_driver.c
+++ b/src/hypervisor/domain_driver.c
@@ -910,3 +910,21 @@ virDomainDriverDetachVsockDeviceConfig(virDomainDef *vmdef,
 
 return 0;
 }
+
+
+int
+virDomainDriverDetachTPMDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+int idx;
+
+if ((idx = virDomainTPMDefFind(vmdef, dev->data.tpm)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("matching tpm device not found"));
+return -1;
+}
+
+virDomainTPMDefFree(virDomainTPMDefRemove(vmdef, idx));
+
+return 0;
+}
diff --git a/src/hypervisor/domain_driver.h b/src/hypervisor/domain_driver.h
index e7fbd70d7b..51dc109c38 100644
--- a/src/hypervisor/domain_driver.h
+++ b/src/hypervisor/domain_driver.h
@@ -111,3 +111,6 @@ int virDomainDriverDetachInputDeviceConfig(virDomainDef 
*vmdef,
 
 int virDomainDriverDetachVsockDeviceConfig(virDomainDef *vmdef,
virDomainDeviceDef *dev);
+
+int virDomainDriverDetachTPMDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 68cc9c51cb..cfda58320a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1565,6 +1565,7 @@ virDomainDriverDetachRedirdevDeviceConfig;
 virDomainDriverDetachRNGDeviceConfig;
 virDomainDriverDetachShmemDeviceConfig;
 virDomainDriverDetachSoundDeviceConfig;
+virDomainDriverDetachTPMDeviceConfig;
 virDomainDriverDetachVsockDeviceConfig;
 virDomainDriverDetachWatchdogDeviceConfig;
 virDomainDriverGenerateMachineName;
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index b1ca6a7b97..15b4332769 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -10149,6 +10149,12 @@ testDomainDetachDeviceLiveAndConfig(virDomainDef 
*vmdef,
 virDomainChrDefFree(chr);
 break;
 
+case VIR_DOMAIN_DEVICE_TPM:
+if (virDomainDriverDetachTPMDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
 case VIR_DOMAIN_DEVICE_VIDEO:
 case VIR_DOMAIN_DEVICE_GRAPHICS:
 case VIR_DOMAIN_DEVICE_HUB:
@@ -10156,7 +10162,6 @@ testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
 case VIR_DOMAIN_DEVICE_MEMBALLOON:
 case VIR_DOMAIN_DEVICE_NVRAM:
 case VIR_DOMAIN_DEVICE_NONE:
-case VIR_DOMAIN_DEVICE_TPM:
 case VIR_DOMAIN_DEVICE_PANIC:
 case VIR_DOMAIN_DEVICE_IOMMU:
 case VIR_DOMAIN_DEVICE_AUDIO:
-- 
2.33.1



[PATCH v3 04/12] test_driver: Implement virDomainDetachDeviceAlias

2021-11-10 Thread Luke Yue
As we already implement testDomainChgDevice for both DetachDeviceFlags
and DetachDeviceAlias, so it's simple to implement this API by
changing the parameter.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 6a7eb12f77..9843340fec 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -10252,6 +10252,15 @@ testDomainDetachDeviceFlags(virDomainPtr dom,
xml, NULL, flags);
 }
 
+static int
+testDomainDetachDeviceAlias(virDomainPtr dom,
+const char *alias,
+unsigned int flags)
+{
+return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
+   NULL, alias, flags);
+}
+
 /*
  * Test driver
  */
@@ -10349,6 +10358,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainFSFreeze = testDomainFSFreeze, /* 5.7.0 */
 .domainFSThaw = testDomainFSThaw, /* 5.7.0 */
 .domainFSTrim = testDomainFSTrim, /* 5.7.0 */
+.domainDetachDeviceAlias = testDomainDetachDeviceAlias, /* 7.10.0 */
 .domainDetachDeviceFlags = testDomainDetachDeviceFlags, /* 7.10.0 */
 .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
 .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
-- 
2.33.1



[PATCH v3 11/12] virshtest: add expectError parameter to testCompareOutputLit

2021-11-10 Thread Luke Yue
Add expectError so that we can make some test fail on purpose and compare
the error message.

The problem is that the test would pass, but the failed test would raise
an internal error, with VIR_TEST_DEBUG=1, the error message would still
be printed.

Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 61 +--
 1 file changed, 33 insertions(+), 28 deletions(-)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index c2c892c60d..af2a70f5fb 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -110,7 +110,7 @@ static int testFilterLine(char *buffer,
 }
 
 static int
-testCompareOutputLit(const char *expectData,
+testCompareOutputLit(const char *expectData, const char *expectError,
  const char *filter, const char *const argv[])
 {
 g_autofree char *actualData = NULL;
@@ -126,14 +126,19 @@ testCompareOutputLit(const char *expectData,
 virCommandSetOutputBuffer(cmd, &actualData);
 virCommandSetErrorBuffer(cmd, &errbuf);
 
-if (virCommandRun(cmd, NULL) < 0)
+if (virCommandRun(cmd, NULL) < 0 && STREQ(expectError, ""))
 return -1;
 
-if (STRNEQ(errbuf, "")) {
+if (STREQ(expectError, "") && STRNEQ(errbuf, "")) {
 fprintf(stderr, "Command reported error: %s", errbuf);
 return -1;
 }
 
+if (STRNEQ(errbuf, expectError)) {
+virTestDifference(stderr, errbuf, expectError);
+return -1;
+}
+
 if (filter && testFilterLine(actualData, filter) < 0)
 return -1;
 
@@ -163,7 +168,7 @@ static int testCompareListDefault(const void *data 
G_GNUC_UNUSED)
 --\n\
  1test   running\n\
 \n";
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareListCustom(const void *data G_GNUC_UNUSED)
@@ -176,7 +181,7 @@ static int testCompareListCustom(const void *data 
G_GNUC_UNUSED)
  2fc4running\n\
  3fc5running\n\
 \n";
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareNodeinfoDefault(const void *data G_GNUC_UNUSED)
@@ -192,7 +197,7 @@ Thread(s) per core:  2\n\
 NUMA cell(s):2\n\
 Memory size: 3145728 KiB\n\
 \n";
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareNodeinfoCustom(const void *data G_GNUC_UNUSED)
@@ -212,112 +217,112 @@ Thread(s) per core:  2\n\
 NUMA cell(s):4\n\
 Memory size: 8192000 KiB\n\
 \n";
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareDominfoByID(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "2", NULL };
 const char *exp = dominfo_fc4;
-return testCompareOutputLit(exp, "\nCPU time:", argv);
+return testCompareOutputLit(exp, "", "\nCPU time:", argv);
 }
 
 static int testCompareDominfoByUUID(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "dominfo", DOM_FC4_UUID, NULL };
 const char *exp = dominfo_fc4;
-return testCompareOutputLit(exp, "\nCPU time:", argv);
+return testCompareOutputLit(exp, "", "\nCPU time:", argv);
 }
 
 static int testCompareDominfoByName(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "fc4", NULL };
 const char *exp = dominfo_fc4;
-return testCompareOutputLit(exp, "\nCPU time:", argv);
+return testCompareOutputLit(exp, "", "\nCPU time:", argv);
 }
 
 static int testCompareTaintedDominfoByName(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "fc5", NULL };
 const char *exp = dominfo_fc5;
-return testCompareOutputLit(exp, "\nCPU time:", argv);
+return testCompareOutputLit(exp, "", "\nCPU time:", argv);
 }
 
 static int testCompareDomuuidByID(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "domuuid", "2", NULL };
 const char *exp = domuuid_fc4;
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareDomuuidByName(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "domuuid", "fc4", NULL };
 const char *exp = domuuid_fc4;
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareDomidByName(const void *data G_G

[PATCH v3 08/12] conf: Add a memballoon helper for future use

2021-11-10 Thread Luke Yue
Currently it will only be used in test driver.

Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.c   | 24 
 src/conf/domain_conf.h   |  4 
 src/libvirt_private.syms |  1 +
 3 files changed, 29 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 512bfab9e9..92a8bd63f3 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16998,6 +16998,30 @@ virDomainTPMDefRemove(virDomainDef *def,
 }
 
 
+bool
+virDomainMemballoonDefEquals(const virDomainMemballoonDef *a,
+ const virDomainMemballoonDef *b)
+{
+if (a->model != b->model)
+return false;
+
+if (a->period != b->period)
+return false;
+
+if (a->autodeflate != b->autodeflate)
+return false;
+
+if (a->free_page_reporting != b->free_page_reporting)
+return false;
+
+if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+!virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
+return false;
+
+return true;
+}
+
+
 char *
 virDomainDefGetDefaultEmulator(virDomainDef *def,
virCaps *caps)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 715c8fbd16..f60ba37d19 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3863,6 +3863,10 @@ ssize_t virDomainTPMDefFind(const virDomainDef *def,
 virDomainTPMDef *virDomainTPMDefRemove(virDomainDef *def, size_t idx)
 ATTRIBUTE_NONNULL(1);
 
+bool virDomainMemballoonDefEquals(const virDomainMemballoonDef *a,
+  const virDomainMemballoonDef *b)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+
 VIR_ENUM_DECL(virDomainTaint);
 VIR_ENUM_DECL(virDomainTaintMessage);
 VIR_ENUM_DECL(virDomainVirt);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cfda58320a..b143537bb4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -506,6 +506,7 @@ virDomainLoaderTypeFromString;
 virDomainLoaderTypeToString;
 virDomainLockFailureTypeFromString;
 virDomainLockFailureTypeToString;
+virDomainMemballoonDefEquals;
 virDomainMemballoonModelTypeFromString;
 virDomainMemballoonModelTypeToString;
 virDomainMemoryDefFree;
-- 
2.33.1



[PATCH v3 05/12] test_driver: Implement virDomainDetachDevice

2021-11-10 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 9843340fec..b1ca6a7b97 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -10261,6 +10261,14 @@ testDomainDetachDeviceAlias(virDomainPtr dom,
NULL, alias, flags);
 }
 
+static int
+testDomainDetachDevice(virDomainPtr dom,
+   const char *xml)
+{
+return testDomainDetachDeviceFlags(dom, xml,
+   VIR_DOMAIN_AFFECT_LIVE);
+}
+
 /*
  * Test driver
  */
@@ -10358,6 +10366,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainFSFreeze = testDomainFSFreeze, /* 5.7.0 */
 .domainFSThaw = testDomainFSThaw, /* 5.7.0 */
 .domainFSTrim = testDomainFSTrim, /* 5.7.0 */
+.domainDetachDevice = testDomainDetachDevice, /* 7.10.0 */
 .domainDetachDeviceAlias = testDomainDetachDeviceAlias, /* 7.10.0 */
 .domainDetachDeviceFlags = testDomainDetachDeviceFlags, /* 7.10.0 */
 .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
-- 
2.33.1



[PATCH v3 02/12] domain_driver: extract DetachXXXDeviceConfig related functions and use them

2021-11-10 Thread Luke Yue
libxl / lxc / qemu drivers share some common codes in their
DomainDetachDeviceConfig functions, so extract them to domain_driver and
reuse them.

At the same time, this will enable test driver to test these functions
with virshtest in the future.

Signed-off-by: Luke Yue 
---
Not pretty sure whether this is a proper way to make these functions
reusable, maybe there is a more elegant choice.
---
 src/hypervisor/domain_driver.c | 266 +
 src/hypervisor/domain_driver.h |  41 +
 src/libvirt_private.syms   |  14 ++
 src/libxl/libxl_driver.c   |  41 +
 src/lxc/lxc_driver.c   |  37 +
 src/qemu/qemu_driver.c | 123 +++
 6 files changed, 356 insertions(+), 166 deletions(-)

diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
index 31737b0f4a..01ecb4e30e 100644
--- a/src/hypervisor/domain_driver.c
+++ b/src/hypervisor/domain_driver.c
@@ -644,3 +644,269 @@ virDomainDriverGetIOThreadsConfig(virDomainDef *targetDef,
 
 return ret;
 }
+
+
+int
+virDomainDriverDetachDiskDeviceConfig(virDomainDef *vmdef,
+  virDomainDeviceDef *dev)
+{
+virDomainDiskDef *disk;
+virDomainDiskDef *det_disk;
+
+disk = dev->data.disk;
+if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
+virReportError(VIR_ERR_DEVICE_MISSING, _("no target device %s"),
+   disk->dst);
+return -1;
+}
+virDomainDiskDefFree(det_disk);
+
+return 0;
+}
+
+int
+virDomainDriverDetachNetDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+virDomainNetDef *net;
+int idx;
+
+net = dev->data.net;
+if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
+return -1;
+
+/* this is guaranteed to succeed */
+virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachSoundDeviceConfig(virDomainDef *vmdef,
+   virDomainDeviceDef *dev)
+{
+virDomainSoundDef *sound;
+int idx;
+
+sound = dev->data.sound;
+if ((idx = virDomainSoundDefFind(vmdef, sound)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("device not present in domain configuration"));
+return -1;
+}
+virDomainSoundDefFree(virDomainSoundDefRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachHostdevDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+virDomainHostdevDef *hostdev;
+virDomainHostdevDef *det_hostdev;
+int idx;
+
+hostdev = dev->data.hostdev;
+if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("device not present in domain configuration"));
+return -1;
+}
+virDomainHostdevRemove(vmdef, idx);
+virDomainHostdevDefFree(det_hostdev);
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachLeaseDeviceConfig(virDomainDef *vmdef,
+   virDomainDeviceDef *dev)
+{
+virDomainLeaseDef *lease;
+virDomainLeaseDef *det_lease;
+
+lease = dev->data.lease;
+if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
+virReportError(VIR_ERR_DEVICE_MISSING,
+   _("Lease %s in lockspace %s does not exist"),
+   lease->key, NULLSTR(lease->lockspace));
+return -1;
+}
+virDomainLeaseDefFree(det_lease);
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachControllerDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+virDomainControllerDef *cont;
+virDomainControllerDef *det_cont;
+int idx;
+
+cont = dev->data.controller;
+if ((idx = virDomainControllerFind(vmdef, cont->type,
+   cont->idx)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("device not present in domain configuration"));
+return -1;
+}
+det_cont = virDomainControllerRemove(vmdef, idx);
+virDomainControllerDefFree(det_cont);
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachFSDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+virDomainFSDef *fs;
+int idx;
+
+fs = dev->data.fs;
+idx = virDomainFSIndexByName(vmdef, fs->dst);
+if (idx < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching filesystem device was found"));
+return -1;
+}
+
+fs = virDomainFSRemove(vmdef, idx);
+virDomainFSDefFree(fs);
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachRNGDeviceConfig(v

[PATCH v3 03/12] test_driver: Implement virDomainDetachDeviceFlags

2021-11-10 Thread Luke Yue
Introduce testDomainChgDevice for further development (just like what we
did for IOThread). And introduce testDomainDetachDeviceLiveAndConfig for
detaching devices.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 202 +
 1 file changed, 202 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index ea474d55ac..6a7eb12f77 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -10051,6 +10051,207 @@ testConnectGetAllDomainStats(virConnectPtr conn,
 return ret;
 }
 
+static int
+testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+virDomainChrDef *chr;
+
+switch (dev->type) {
+case VIR_DOMAIN_DEVICE_DISK:
+if (virDomainDriverDetachDiskDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_NET:
+if (virDomainDriverDetachNetDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_SOUND:
+if (virDomainDriverDetachSoundDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_HOSTDEV:
+if (virDomainDriverDetachHostdevDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_LEASE:
+if (virDomainDriverDetachLeaseDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_CONTROLLER:
+if (virDomainDriverDetachControllerDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_FS:
+if (virDomainDriverDetachFSDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_RNG:
+if (virDomainDriverDetachRNGDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_MEMORY:
+if (virDomainDriverDetachMemoryDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_REDIRDEV:
+if (virDomainDriverDetachRedirdevDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_SHMEM:
+if (virDomainDriverDetachShmemDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_WATCHDOG:
+if (virDomainDriverDetachWatchdogDeviceConfig(vmdef) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_INPUT:
+if (virDomainDriverDetachInputDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_VSOCK:
+if (virDomainDriverDetachVsockDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_CHR:
+if (!(chr = virDomainChrRemove(vmdef, dev->data.chr)))
+return -1;
+
+virDomainChrDefFree(chr);
+break;
+
+case VIR_DOMAIN_DEVICE_VIDEO:
+case VIR_DOMAIN_DEVICE_GRAPHICS:
+case VIR_DOMAIN_DEVICE_HUB:
+case VIR_DOMAIN_DEVICE_SMARTCARD:
+case VIR_DOMAIN_DEVICE_MEMBALLOON:
+case VIR_DOMAIN_DEVICE_NVRAM:
+case VIR_DOMAIN_DEVICE_NONE:
+case VIR_DOMAIN_DEVICE_TPM:
+case VIR_DOMAIN_DEVICE_PANIC:
+case VIR_DOMAIN_DEVICE_IOMMU:
+case VIR_DOMAIN_DEVICE_AUDIO:
+case VIR_DOMAIN_DEVICE_LAST:
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+   _("detach of device '%s' is not supported"),
+   virDomainDeviceTypeToString(dev->type));
+return -1;
+}
+
+return 0;
+}
+
+static int
+testDomainChgDevice(virDomainPtr dom,
+virDomainDeviceAction action,
+const char *xml,
+const char *alias,
+unsigned int flags)
+{
+testDriver *driver = dom->conn->privateData;
+virDomainObj *vm = NULL;
+virDomainDef *def;
+virDomainDeviceDef *dev = NULL;
+unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDef(vm, flags)))
+goto cleanup;
+
+if (action == VIR_DOMAIN_DEVICE_ACTION_DETACH)
+parse_flags |= VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
+
+if (xml) {
+if (!(dev = virDomainDeviceDefParse(xml, def, driver->xmlopt,
+driver->caps, parse_flags)))
+goto cleanup;
+} else if (alias) {
+dev = g_new0(virDomainDeviceDef, 1);
+if (virDomainDefFindDevice(def, alias, dev, true) < 0)
+goto clea

[PATCH v3 01/12] conf: Introduce virDomainInputDefRemove and fix memory leak

2021-11-10 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.c   | 12 
 src/conf/domain_conf.h   |  2 ++
 src/libvirt_private.syms |  1 +
 src/qemu/qemu_driver.c   |  3 ++-
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index da0c64b460..3193120b79 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16901,6 +16901,18 @@ virDomainInputDefFind(const virDomainDef *def,
 }
 
 
+virDomainInputDef *
+virDomainInputDefRemove(virDomainDef *def,
+size_t idx)
+{
+virDomainInputDef *ret = def->inputs[idx];
+
+VIR_DELETE_ELEMENT(def->inputs, idx, def->ninputs);
+
+return ret;
+}
+
+
 bool
 virDomainVsockDefEquals(const virDomainVsockDef *a,
 const virDomainVsockDef *b)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ab9a7d66f8..a089b0b3de 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3851,6 +3851,8 @@ virDomainShmemDef *virDomainShmemDefRemove(virDomainDef 
*def, size_t idx)
 ssize_t virDomainInputDefFind(const virDomainDef *def,
   const virDomainInputDef *input)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+virDomainInputDef *virDomainInputDefRemove(virDomainDef *def, size_t idx)
+ATTRIBUTE_NONNULL(1);
 bool virDomainVsockDefEquals(const virDomainVsockDef *a,
  const virDomainVsockDef *b)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9ee8fda25f..000c9893f0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -478,6 +478,7 @@ virDomainInputBusTypeToString;
 virDomainInputDefFind;
 virDomainInputDefFree;
 virDomainInputDefGetPath;
+virDomainInputDefRemove;
 virDomainInputSourceGrabToggleTypeFromString;
 virDomainInputSourceGrabToggleTypeToString;
 virDomainInputSourceGrabTypeFromString;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6a77d9f513..cf9407c358 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7678,7 +7678,8 @@ qemuDomainDetachDeviceConfig(virDomainDef *vmdef,
_("matching input device not found"));
 return -1;
 }
-VIR_DELETE_ELEMENT(vmdef->inputs, idx, vmdef->ninputs);
+
+virDomainInputDefFree(virDomainInputDefRemove(vmdef, idx));
 break;
 
 case VIR_DOMAIN_DEVICE_VSOCK:
-- 
2.33.1



[PATCH v3 00/12] Implement detach device related APIs for test driver

2021-11-10 Thread Luke Yue
v3:
- Rebase to current master branch
- Split some tests to different functions in PATCH 12/12 and add some tests

link to v2: 
https://listman.redhat.com/archives/libvir-list/2021-August/msg00637.html
link to CI: https://gitlab.com/lukedyue/libvirt/-/pipelines/405150749

Luke Yue (12):
  conf: Introduce virDomainInputDefRemove and fix memory leak
  domain_driver: extract DetachXXXDeviceConfig related functions and use
them
  test_driver: Implement virDomainDetachDeviceFlags
  test_driver: Implement virDomainDetachDeviceAlias
  test_driver: Implement virDomainDetachDevice
  conf: Add tpm helpers for future use
  test_driver: add TPM support for testDomainDetachDeviceLiveAndConfig
  conf: Add a memballoon helper for future use
  test_driver: add memballoon support for
testDomainDetachDeviceLiveAndConfig
  examples: xml: test: add xml for testing devices related APIs
  virshtest: add expectError parameter to testCompareOutputLit
  tests: Test detach-device and detach-device-alias for test driver

 examples/xml/test/testdevcontroller.xml |   1 +
 examples/xml/test/testdevdiskcdrom.xml  |   5 +
 examples/xml/test/testdevfs.xml |   6 +
 examples/xml/test/testdevhostdev.xml|   5 +
 examples/xml/test/testdevif.xml |   6 +
 examples/xml/test/testdevinput.xml  |   1 +
 examples/xml/test/testdevlease.xml  |   5 +
 examples/xml/test/testdevmem.xml|   6 +
 examples/xml/test/testdevmemballoon.xml |   3 +
 examples/xml/test/testdevrng.xml|   4 +
 examples/xml/test/testdevshmem.xml  |   4 +
 examples/xml/test/testdevsound.xml  |   3 +
 examples/xml/test/testdevtpm.xml|   5 +
 examples/xml/test/testdevvsock.xml  |   3 +
 examples/xml/test/testdevwatchdog.xml   |   1 +
 examples/xml/test/testdomfc5.xml|  54 +
 examples/xml/test/testnodeinline.xml|  54 +
 src/conf/domain_conf.c  | 103 
 src/conf/domain_conf.h  |  12 +
 src/hypervisor/domain_driver.c  | 302 
 src/hypervisor/domain_driver.h  |  47 
 src/libvirt_private.syms|  20 ++
 src/libxl/libxl_driver.c|  41 +---
 src/lxc/lxc_driver.c|  37 +--
 src/qemu/qemu_driver.c  | 124 ++
 src/test/test_driver.c  | 239 +++
 tests/virshtest.c   | 157 +---
 27 files changed, 1054 insertions(+), 194 deletions(-)
 create mode 100644 examples/xml/test/testdevcontroller.xml
 create mode 100644 examples/xml/test/testdevdiskcdrom.xml
 create mode 100644 examples/xml/test/testdevfs.xml
 create mode 100644 examples/xml/test/testdevhostdev.xml
 create mode 100644 examples/xml/test/testdevif.xml
 create mode 100644 examples/xml/test/testdevinput.xml
 create mode 100644 examples/xml/test/testdevlease.xml
 create mode 100644 examples/xml/test/testdevmem.xml
 create mode 100644 examples/xml/test/testdevmemballoon.xml
 create mode 100644 examples/xml/test/testdevrng.xml
 create mode 100644 examples/xml/test/testdevshmem.xml
 create mode 100644 examples/xml/test/testdevsound.xml
 create mode 100644 examples/xml/test/testdevtpm.xml
 create mode 100644 examples/xml/test/testdevvsock.xml
 create mode 100644 examples/xml/test/testdevwatchdog.xml

-- 
2.33.1



[PATCH v4 10/11] test_driver: Introduce testDomainGetStatsIOThread

2021-09-15 Thread Luke Yue
Introduce testDomainGetStatsIOThread to add support for
testConnectGetAllDomainStats to get IOThread infos.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 44 +-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index a6f7de2ccd..d9b0578e13 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9894,6 +9894,46 @@ testDomainGetStatsState(virDomainObj *dom,
 return 0;
 }
 
+static int
+testDomainGetStatsIOThread(virDomainObj *dom,
+   virTypedParamList *params)
+{
+testDomainObjPrivate *priv = dom->privateData;
+size_t i;
+int niothreads = 0;
+
+if (!virDomainObjIsActive(dom))
+return 0;
+
+niothreads = priv->iothreads->len;
+
+if (niothreads == 0) {
+return 0;
+}
+
+if (virTypedParamListAddUInt(params, niothreads, "iothread.count") < 0)
+return -1;
+
+for (i = 0; i < niothreads; i++) {
+testIOThreadInfo iothread = g_array_index(priv->iothreads,
+  testIOThreadInfo, i);
+if (virTypedParamListAddULLong(params, iothread.poll_max_ns,
+   "iothread.%u.poll-max-ns",
+   iothread.iothread_id) < 0)
+return -1;
+if (virTypedParamListAddUInt(params, iothread.poll_grow,
+ "iothread.%u.poll-grow",
+ iothread.iothread_id) < 0)
+return -1;
+if (virTypedParamListAddUInt(params, iothread.poll_shrink,
+ "iothread.%u.poll-shrink",
+ iothread.iothread_id) < 0)
+return -1;
+}
+
+return 0;
+}
+
 typedef int
 (*testDomainGetStatsFunc)(virDomainObj *dom,
   virTypedParamList *list);
@@ -9905,6 +9945,7 @@ struct testDomainGetStatsWorker {
 
 static struct testDomainGetStatsWorker testDomainGetStatsWorkers[] = {
 { testDomainGetStatsState, VIR_DOMAIN_STATS_STATE },
+{ testDomainGetStatsIOThread, VIR_DOMAIN_STATS_IOTHREAD },
 { NULL, 0 }
 };
 
@@ -9951,7 +9992,8 @@ testConnectGetAllDomainStats(virConnectPtr conn,
VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT 
|
VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE);
 
-unsigned int supported = VIR_DOMAIN_STATS_STATE;
+unsigned int supported = VIR_DOMAIN_STATS_STATE |
+ VIR_DOMAIN_STATS_IOTHREAD;
 virDomainObj **vms = NULL;
 size_t nvms;
 virDomainStatsRecordPtr *tmpstats = NULL;
-- 
2.33.0



[PATCH v4 11/11] tests: Test IOThread related functions for test driver

2021-09-15 Thread Luke Yue
testIOThreadAdd tests iothreadinfo and iothreadadd
testIOThreadDel tests iothreadinfo and iothreaddel
testIOThreadSet tests domstats and iothreadset
testIOThreadPin tests iothreadadd, iothreadinfo and iothreadpin

Above tests should cover the IOThreads related APIs for test driver

Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 110 ++
 1 file changed, 110 insertions(+)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index 87da1f5889..c2c892c60d 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -32,6 +32,7 @@ main(void)
 deprecated configuration: CPU model Deprecated-Test"
 # define GET_BLKIO_PARAMETER "/dev/hda,700"
 # define SET_BLKIO_PARAMETER "/dev/hda,1000"
+# define EQUAL "="
 
 static const char *dominfo_fc4 = "\
 Id: 2\n\
@@ -338,6 +339,99 @@ static int testCompareSetBlkioParameters(const void *data 
G_GNUC_UNUSED)
 return testCompareOutputLit(exp, NULL, argv);
 }
 
+static int testIOThreadAdd(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "iothreadinfo --domain fc4;\
+ iothreadadd --domain fc4 --id 6;\
+ iothreadinfo --domain fc4", NULL};
+const char *exp = "\
+ IOThread ID   CPU Affinity\n\
+-\n\
+ 2 0\n\
+ 4 0\n\
+\n\
+\n\
+ IOThread ID   CPU Affinity\n\
+-\n\
+ 2 0\n\
+ 4 0\n\
+ 6 0\n\
+\n";
+return testCompareOutputLit(exp, NULL, argv);
+}
+
+static int testIOThreadDel(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "iothreadinfo --domain fc4;\
+ iothreaddel --domain fc4 --id 2;\
+ iothreadinfo --domain fc4", NULL};
+const char *exp = "\
+ IOThread ID   CPU Affinity\n\
+-\n\
+ 2 0\n\
+ 4 0\n\
+\n\
+\n\
+ IOThread ID   CPU Affinity\n\
+-\n\
+ 4 0\n\
+\n";
+return testCompareOutputLit(exp, NULL, argv);
+}
+
+static int testIOThreadSet(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "domstats --domain fc4;\
+ iothreadset --domain fc4\
+ --id 2 --poll-max-ns 100\
+ --poll-shrink 10 --poll-grow 10;\
+ domstats --domain fc4", NULL};
+const char *exp = "\
+Domain: 'fc4'\n\
+  state.state" EQUAL "1\n\
+  state.reason" EQUAL "0\n\
+  iothread.count" EQUAL "2\n\
+  iothread.2.poll-max-ns" EQUAL "32768\n\
+  iothread.2.poll-grow" EQUAL "0\n\
+  iothread.2.poll-shrink" EQUAL "0\n\
+  iothread.4.poll-max-ns" EQUAL "32768\n\
+  iothread.4.poll-grow" EQUAL "0\n\
+  iothread.4.poll-shrink" EQUAL "0\n\n\
+\n\
+Domain: 'fc4'\n\
+  state.state" EQUAL "1\n\
+  state.reason" EQUAL "0\n\
+  iothread.count" EQUAL "2\n\
+  iothread.2.poll-max-ns" EQUAL "100\n\
+  iothread.2.poll-grow" EQUAL "10\n\
+  iothread.2.poll-shrink" EQUAL "10\n\
+  iothread.4.poll-max-ns" EQUAL "32768\n\
+  iothread.4.poll-grow" EQUAL "0\n\
+  iothread.4.poll-shrink" EQUAL "0\n\n";
+return testCompareOutputLit(exp, NULL, argv);
+}
+
+static int testIOThreadPin(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM,
+ "iothreadadd --domain fc5 --id 2;\
+ iothreadinfo --domain fc5;\
+ iothreadpin --domain fc5 --iothread 2\
+ --cpulist 0;\
+ iothreadinfo --domain fc5", NULL};
+const char *exp = "\n\
+ IOThread ID   CPU Affinity\n\
+-\n\
+ 2 0-3\n\
+\n\
+\n\
+ IOThread ID   CPU Affinity\n\
+-\n\
+ 2 0\n\
+\n";
+return testCompareOutputLit(exp, NULL, argv);
+}
+
 struct testInfo {
 const char *const *argv;
 const char *result;
@@ -438,6 +532,22 @@ mymain(void)
testCompareSetBlkioParameters, NULL) != 0)
 ret = -1;
 
+if (virTestRun("virsh iothreadadd",
+   testIOThreadAdd, NULL) != 0)
+ret = -1;
+
+if (virTestRun("virsh iothreaddel",
+   testIOThreadDel, NULL) != 0)
+ret = -1;
+
+if (virTestRun("virsh iothreadset",
+   testIOThreadSet, NULL) != 0)
+ret = -1;
+
+if (virTestRun("virsh iothreadpin",
+   testIOThreadPin, NULL) != 0)
+ret = -1;
+
 /* It's a bit awkward listing result before argument, but that's a
  * limitation of C99 vararg macros.  */
 # define DO_TEST(i, result, ...) \
-- 
2.33.0



[PATCH v4 05/11] domain_driver.c: Introduce and use virDomainDriverGetIOThreadsConfig()

2021-09-15 Thread Luke Yue
The test driver can share the same code with qemu driver when implement
testDomainGetIOThreadsConfig, so extract it for test driver to use.

Also add a new parameter `bitmap_size` to the function, it's used for
specifying the bitmap size of the bitmap to generate, it would be helpful
for test driver or some special situation.

Signed-off-by: Luke Yue 
---
 src/hypervisor/domain_driver.c | 68 ++
 src/hypervisor/domain_driver.h |  4 ++
 src/libvirt_private.syms   |  1 +
 src/qemu/qemu_driver.c | 53 +-
 4 files changed, 74 insertions(+), 52 deletions(-)

diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
index 3eb2401053..31737b0f4a 100644
--- a/src/hypervisor/domain_driver.c
+++ b/src/hypervisor/domain_driver.c
@@ -576,3 +576,71 @@ virDomainDriverDelIOThreadCheck(virDomainDef *def,
 
 return 0;
 }
+
+/**
+ * virDomainDriverGetIOThreadsConfig:
+ * @targetDef: domain definition
+ * @info: information about the IOThread in a domain
+ * @bitmap_size: generate bitmap with bitmap_size, 0 for getting the size
+ * from host
+ *
+ * Returns the number of IOThreads in the given domain or -1 in case of error
+ */
+int
+virDomainDriverGetIOThreadsConfig(virDomainDef *targetDef,
+  virDomainIOThreadInfoPtr **info,
+  unsigned int bitmap_size)
+{
+virDomainIOThreadInfoPtr *info_ret = NULL;
+virBitmap *bitmap = NULL;
+virBitmap *cpumask = NULL;
+size_t i;
+int ret = -1;
+
+if (targetDef->niothreadids == 0)
+return 0;
+
+info_ret = g_new0(virDomainIOThreadInfoPtr, targetDef->niothreadids);
+
+for (i = 0; i < targetDef->niothreadids; i++) {
+info_ret[i] = g_new0(virDomainIOThreadInfo, 1);
+
+/* IOThread ID's are taken from the iothreadids list */
+info_ret[i]->iothread_id = targetDef->iothreadids[i]->iothread_id;
+
+cpumask = targetDef->iothreadids[i]->cpumask;
+if (!cpumask) {
+if (targetDef->cpumask) {
+cpumask = targetDef->cpumask;
+} else {
+if (bitmap_size) {
+if (!(bitmap = virBitmapNew(bitmap_size)))
+goto cleanup;
+virBitmapSetAll(bitmap);
+} else {
+if (!(bitmap = virHostCPUGetAvailableCPUsBitmap()))
+goto cleanup;
+}
+cpumask = bitmap;
+}
+}
+if (virBitmapToData(cpumask, &info_ret[i]->cpumap,
+&info_ret[i]->cpumaplen) < 0)
+goto cleanup;
+virBitmapFree(bitmap);
+bitmap = NULL;
+}
+
+*info = g_steal_pointer(&info_ret);
+ret = targetDef->niothreadids;
+
+ cleanup:
+if (info_ret) {
+for (i = 0; i < targetDef->niothreadids; i++)
+virDomainIOThreadInfoFree(info_ret[i]);
+VIR_FREE(info_ret);
+}
+virBitmapFree(bitmap);
+
+return ret;
+}
diff --git a/src/hypervisor/domain_driver.h b/src/hypervisor/domain_driver.h
index d91d21bc91..7b0fbae2fd 100644
--- a/src/hypervisor/domain_driver.h
+++ b/src/hypervisor/domain_driver.h
@@ -66,3 +66,7 @@ int virDomainDriverAddIOThreadCheck(virDomainDef *def,
 
 int virDomainDriverDelIOThreadCheck(virDomainDef *def,
 unsigned int iothread_id);
+
+int virDomainDriverGetIOThreadsConfig(virDomainDef *targetDef,
+  virDomainIOThreadInfoPtr **info,
+  unsigned int bitmap_size);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d45b644caf..bcc413be02 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1541,6 +1541,7 @@ virDomainDriverAddIOThreadCheck;
 virDomainDriverDelIOThreadCheck;
 virDomainDriverGenerateMachineName;
 virDomainDriverGenerateRootHash;
+virDomainDriverGetIOThreadsConfig;
 virDomainDriverMergeBlkioDevice;
 virDomainDriverNodeDeviceDetachFlags;
 virDomainDriverNodeDeviceGetPCIInfo;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f2acb37c76..54b8529d88 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5032,57 +5032,6 @@ qemuDomainGetIOThreadsLive(virQEMUDriver *driver,
 return ret;
 }
 
-static int
-qemuDomainGetIOThreadsConfig(virDomainDef *targetDef,
- virDomainIOThreadInfoPtr **info)
-{
-virDomainIOThreadInfoPtr *info_ret = NULL;
-virBitmap *bitmap = NULL;
-virBitmap *cpumask = NULL;
-size_t i;
-int ret = -1;
-
-if (targetDef->niothreadids == 0)
-return 0;
-
-info_ret = g_new0(virDomainIOThreadInfoPtr, targetDef->niothreadids);
-
-for (i = 0; i < targetDef->niothreadids; i++) {
-info_ret[i] = g_new0(virDomainIOThreadInfo, 1);
-
-/* I

[PATCH v4 00/11] Implement IOThreads related APIs for test driver

2021-09-15 Thread Luke Yue
v4:
- Rebase to current master branch
- Add the forgotten virObjectUnlock(vm) in PATCH 09/11
- Refine tests

CI link: https://gitlab.com/lukedyue/libvirt/-/pipelines/371315349

Luke Yue (11):
  domain_driver.c: Introduce and use virDomainDriverAddIOThreadCheck()
  test_driver: Introduce testIOThreadInfo and generate IOThread infos
  test_driver: Implement virDomainAddIOThread
  test_driver: Implement virDomainDelIOThread
  domain_driver.c: Introduce and use virDomainDriverGetIOThreadsConfig()
  test_driver: Implement virDomainGetIOThreadInfo
  test_driver: Implement virDomainPinIOThread
  test_driver: Implement testDomainSetIOThreadParams
  test_driver: Implement virConnectGetAllDomainStats
  test_driver: Introduce testDomainGetStatsIOThread
  tests: Test IOThread related functions for test driver

 examples/xml/test/testdomfc4.xml |   5 +
 src/hypervisor/domain_driver.c   | 132 
 src/hypervisor/domain_driver.h   |  10 +
 src/libvirt_private.syms |   3 +
 src/qemu/qemu_driver.c   | 113 +--
 src/test/test_driver.c   | 516 +++
 tests/virshtest.c| 110 +++
 7 files changed, 781 insertions(+), 108 deletions(-)

-- 
2.33.0



[PATCH v4 09/11] test_driver: Implement virConnectGetAllDomainStats

2021-09-15 Thread Luke Yue
Implement virConnectGetAllDomainStats in a modular way just like QEMU
driver, though remove some params in GetStatsWorker that we don't need
in test driver currently.

Only add the worker to get state so far, more worker will be added
in the future.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 137 +
 1 file changed, 137 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 7cff26776a..a6f7de2ccd 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9881,6 +9881,142 @@ testDomainSetIOThreadParams(virDomainPtr dom,
 return ret;
 }
 
+static int
+testDomainGetStatsState(virDomainObj *dom,
+virTypedParamList *params)
+{
+if (virTypedParamListAddInt(params, dom->state.state, "state.state") < 0)
+return -1;
+
+if (virTypedParamListAddInt(params, dom->state.reason, "state.reason") < 0)
+return -1;
+
+return 0;
+}
+
+typedef int
+(*testDomainGetStatsFunc)(virDomainObj *dom,
+  virTypedParamList *list);
+
+struct testDomainGetStatsWorker {
+testDomainGetStatsFunc func;
+unsigned int stats;
+};
+
+static struct testDomainGetStatsWorker testDomainGetStatsWorkers[] = {
+{ testDomainGetStatsState, VIR_DOMAIN_STATS_STATE },
+{ NULL, 0 }
+};
+
+static int
+testDomainGetStats(virConnectPtr conn,
+   virDomainObj *dom,
+   unsigned int stats,
+   virDomainStatsRecordPtr *record)
+{
+g_autofree virDomainStatsRecordPtr tmp = NULL;
+g_autoptr(virTypedParamList) params = NULL;
+size_t i;
+
+params = g_new0(virTypedParamList, 1);
+
+for (i = 0; testDomainGetStatsWorkers[i].func; i++) {
+if (stats & testDomainGetStatsWorkers[i].stats) {
+if (testDomainGetStatsWorkers[i].func(dom, params) < 0)
+return -1;
+}
+}
+
+tmp = g_new0(virDomainStatsRecord, 1);
+
+if (!(tmp->dom = virGetDomain(conn, dom->def->name,
+  dom->def->uuid, dom->def->id)))
+return -1;
+
+tmp->nparams = virTypedParamListStealParams(params, &tmp->params);
+*record = g_steal_pointer(&tmp);
+return 0;
+}
+
+static int
+testConnectGetAllDomainStats(virConnectPtr conn,
+ virDomainPtr *doms,
+ unsigned int ndoms,
+ unsigned int stats,
+ virDomainStatsRecordPtr **retStats,
+ unsigned int flags)
+{
+testDriver *driver = conn->privateData;
+unsigned int lflags = flags & (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
+   VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT 
|
+   VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE);
+
+unsigned int supported = VIR_DOMAIN_STATS_STATE;
+virDomainObj **vms = NULL;
+size_t nvms;
+virDomainStatsRecordPtr *tmpstats = NULL;
+int nstats = 0;
+int ret = -1;
+size_t i;
+
+virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
+  VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
+  VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE |
+  VIR_CONNECT_GET_ALL_DOMAINS_STATS_NOWAIT |
+  VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING |
+  VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS, -1);
+
+if (!stats) {
+stats = supported;
+} else if ((flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS) &&
+   (stats & ~supported)) {
+virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
+   _("Stats types bits 0x%x are not supported by this 
daemon"),
+   stats & ~supported);
+return -1;
+}
+
+if (ndoms) {
+if (virDomainObjListConvert(driver->domains, conn, doms, ndoms, &vms,
+&nvms, NULL, lflags, true) < 0)
+return -1;
+} else {
+if (virDomainObjListCollect(driver->domains, conn, &vms, &nvms,
+NULL, lflags) < 0)
+return -1;
+}
+
+tmpstats = g_new0(virDomainStatsRecordPtr, nvms + 1);
+
+for (i = 0; i < nvms; i++) {
+virDomainStatsRecordPtr tmp = NULL;
+virDomainObj *vm = vms[i];
+
+virObjectLock(vm);
+
+if ((testDomainGetStats(conn, vm, stats, &tmp)) < 0) {
+virObjectUnlock(vm);
+goto cleanup;
+}
+
+virObjectUnlock(vm);
+
+if (!tmp)
+goto cleanup;
+
+tmpstats[nstats++] = tmp;
+}
+
+*retStats = g_steal_pointer(&tmpstats);
+ret = nstats;
+
+ cleanup:
+virDomainStatsRecordListFree(tmpstats);
+virObjectListFreeCount(vms, nvms);
+
+re

[PATCH v4 07/11] test_driver: Implement virDomainPinIOThread

2021-09-15 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 50 ++
 1 file changed, 50 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 0971661c89..43c0822c87 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9743,6 +9743,55 @@ testDomainDelIOThread(virDomainPtr dom,
 return ret;
 }
 
+static int
+testDomainPinIOThread(virDomainPtr dom,
+  unsigned int iothread_id,
+  unsigned char *cpumap,
+  int maplen,
+  unsigned int flags)
+{
+int ret = -1;
+virDomainObj *vm;
+virDomainDef *def;
+virDomainIOThreadIDDef *iothrid;
+virBitmap *cpumask = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDef(vm, flags)))
+goto cleanup;
+
+if (!(cpumask = virBitmapNewData(cpumap, maplen)))
+goto cleanup;
+
+if (virBitmapIsAllClear(cpumask)) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("Empty iothread cpumap list for pinning"));
+goto cleanup;
+}
+
+if (!(iothrid = virDomainIOThreadIDFind(def, iothread_id))) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("iothreadid %d not found"), iothread_id);
+goto cleanup;
+}
+
+virBitmapFree(iothrid->cpumask);
+iothrid->cpumask = g_steal_pointer(&cpumask);
+iothrid->autofill = false;
+
+ret = 0;
+
+ cleanup:
+virBitmapFree(cpumask);
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 /*
  * Test driver
  */
@@ -9812,6 +9861,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainGetIOThreadInfo = testDomainGetIOThreadInfo, /* 7.8.0 */
 .domainAddIOThread = testDomainAddIOThread, /* 7.8.0 */
 .domainDelIOThread = testDomainDelIOThread, /* 7.8.0 */
+.domainPinIOThread = testDomainPinIOThread, /* 7.8.0 */
 .domainGetSecurityLabel = testDomainGetSecurityLabel, /* 7.5.0 */
 .nodeGetSecurityModel = testNodeGetSecurityModel, /* 7.5.0 */
 .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
-- 
2.33.0



[PATCH v4 08/11] test_driver: Implement testDomainSetIOThreadParams

2021-09-15 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 90 ++
 1 file changed, 90 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 43c0822c87..7cff26776a 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9617,6 +9617,7 @@ testDomainGetIOThreadInfo(virDomainPtr dom,
 typedef enum {
 VIR_DOMAIN_IOTHREAD_ACTION_ADD,
 VIR_DOMAIN_IOTHREAD_ACTION_DEL,
+VIR_DOMAIN_IOTHREAD_ACTION_MOD,
 } virDomainIOThreadAction;
 
 static int
@@ -9648,6 +9649,16 @@ testDomainChgIOThread(virDomainObj *vm,
 
 virDomainIOThreadIDDel(def, iothread_id);
 
+break;
+
+case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
+if (!(virDomainIOThreadIDFind(def, iothread_id))) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("cannot find IOThread '%u' in iothreadids"),
+   iothread_id);
+return ret;
+}
+
 break;
 }
 }
@@ -9792,6 +9803,84 @@ testDomainPinIOThread(virDomainPtr dom,
 return ret;
 }
 
+static int
+testDomainIOThreadParseParams(virTypedParameterPtr params,
+  int nparams,
+  testIOThreadInfo *iothread)
+{
+if (virTypedParamsValidate(params, nparams,
+   VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
+   VIR_TYPED_PARAM_ULLONG,
+   VIR_DOMAIN_IOTHREAD_POLL_GROW,
+   VIR_TYPED_PARAM_UINT,
+   VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
+   VIR_TYPED_PARAM_UINT,
+   NULL) < 0)
+return -1;
+
+if (virTypedParamsGetULLong(params, nparams,
+VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
+&iothread->poll_max_ns) < 0)
+return -1;
+
+if (virTypedParamsGetUInt(params, nparams,
+  VIR_DOMAIN_IOTHREAD_POLL_GROW,
+  &iothread->poll_grow) < 0)
+return -1;
+
+if (virTypedParamsGetUInt(params, nparams,
+  VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
+  &iothread->poll_shrink) < 0)
+return -1;
+
+return 0;
+}
+
+static int
+testDomainSetIOThreadParams(virDomainPtr dom,
+unsigned int iothread_id,
+virTypedParameterPtr params,
+int nparams,
+unsigned int flags)
+{
+virDomainObj *vm = NULL;
+testDomainObjPrivate *priv;
+size_t i;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE, -1);
+
+if (iothread_id == 0) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("invalid value of 0 for iothread_id"));
+goto cleanup;
+}
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (testDomainChgIOThread(vm, iothread_id,
+  VIR_DOMAIN_IOTHREAD_ACTION_MOD, flags) < 0)
+goto cleanup;
+
+priv = vm->privateData;
+
+for (i = 0; i < priv->iothreads->len; i++) {
+testIOThreadInfo *iothread = &g_array_index(priv->iothreads,
+testIOThreadInfo, i);
+if (iothread->iothread_id == iothread_id) {
+if (testDomainIOThreadParseParams(params, nparams, iothread) < 0)
+goto cleanup;
+ret = 0;
+break;
+}
+}
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 /*
  * Test driver
  */
@@ -9862,6 +9951,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainAddIOThread = testDomainAddIOThread, /* 7.8.0 */
 .domainDelIOThread = testDomainDelIOThread, /* 7.8.0 */
 .domainPinIOThread = testDomainPinIOThread, /* 7.8.0 */
+.domainSetIOThreadParams = testDomainSetIOThreadParams, /* 7.8.0 */
 .domainGetSecurityLabel = testDomainGetSecurityLabel, /* 7.5.0 */
 .nodeGetSecurityModel = testNodeGetSecurityModel, /* 7.5.0 */
 .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
-- 
2.33.0



[PATCH v4 06/11] test_driver: Implement virDomainGetIOThreadInfo

2021-09-15 Thread Luke Yue
If we use test driver on different machines, and use 0 as bitmap_size
for virDomainDriverGetIOThreadsConfig(), we would get different results for
the `CPU Affinity`, because it's depending on the host CPU's bitmap. In
order to get a stable result for testing, use result of
virDomainDefGetVcpus() as bitmap_size instead.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index b588bbc32e..0971661c89 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9586,6 +9586,34 @@ testDomainGetMessages(virDomainPtr dom,
 return rv;
 }
 
+static int
+testDomainGetIOThreadInfo(virDomainPtr dom,
+  virDomainIOThreadInfoPtr **info,
+  unsigned int flags)
+{
+virDomainObj *vm;
+virDomainDef *targetDef = NULL;
+unsigned int bitmap_size = 0;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (!(targetDef = virDomainObjGetOneDef(vm, flags)))
+goto cleanup;
+
+bitmap_size = virDomainDefGetVcpus(targetDef);
+
+ret = virDomainDriverGetIOThreadsConfig(targetDef, info, bitmap_size);
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 typedef enum {
 VIR_DOMAIN_IOTHREAD_ACTION_ADD,
 VIR_DOMAIN_IOTHREAD_ACTION_DEL,
@@ -9781,6 +9809,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
 .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
 .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
+.domainGetIOThreadInfo = testDomainGetIOThreadInfo, /* 7.8.0 */
 .domainAddIOThread = testDomainAddIOThread, /* 7.8.0 */
 .domainDelIOThread = testDomainDelIOThread, /* 7.8.0 */
 .domainGetSecurityLabel = testDomainGetSecurityLabel, /* 7.5.0 */
-- 
2.33.0



[PATCH v4 04/11] test_driver: Implement virDomainDelIOThread

2021-09-15 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 55 ++
 1 file changed, 55 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index e0b7ace4ed..b588bbc32e 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9588,6 +9588,7 @@ testDomainGetMessages(virDomainPtr dom,
 
 typedef enum {
 VIR_DOMAIN_IOTHREAD_ACTION_ADD,
+VIR_DOMAIN_IOTHREAD_ACTION_DEL,
 } virDomainIOThreadAction;
 
 static int
@@ -9612,6 +9613,14 @@ testDomainChgIOThread(virDomainObj *vm,
 return ret;
 
 break;
+
+case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
+if (virDomainDriverDelIOThreadCheck(def, iothread_id) < 0)
+return ret;
+
+virDomainIOThreadIDDel(def, iothread_id);
+
+break;
 }
 }
 
@@ -9661,6 +9670,51 @@ testDomainAddIOThread(virDomainPtr dom,
 virDomainObjEndAPI(&vm);
 return ret;
 }
+
+static int
+testDomainDelIOThread(virDomainPtr dom,
+  unsigned int iothread_id,
+  unsigned int flags)
+{
+virDomainObj *vm = NULL;
+testDomainObjPrivate *priv;
+size_t i;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (iothread_id == 0) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("invalid value of 0 for iothread_id"));
+return -1;
+}
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (testDomainChgIOThread(vm, iothread_id,
+  VIR_DOMAIN_IOTHREAD_ACTION_DEL, flags) < 0)
+goto cleanup;
+
+priv = vm->privateData;
+
+for (i = 0; i < priv->iothreads->len; i++) {
+testIOThreadInfo iothread = g_array_index(priv->iothreads,
+  testIOThreadInfo, i);
+if (iothread.iothread_id == iothread_id) {
+g_array_remove_index(priv->iothreads, i);
+break;
+}
+}
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 /*
  * Test driver
  */
@@ -9728,6 +9782,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
 .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
 .domainAddIOThread = testDomainAddIOThread, /* 7.8.0 */
+.domainDelIOThread = testDomainDelIOThread, /* 7.8.0 */
 .domainGetSecurityLabel = testDomainGetSecurityLabel, /* 7.5.0 */
 .nodeGetSecurityModel = testNodeGetSecurityModel, /* 7.5.0 */
 .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
-- 
2.33.0



[PATCH v4 03/11] test_driver: Implement virDomainAddIOThread

2021-09-15 Thread Luke Yue
Introduce testDomainChgIOThread at the same time, could be used for
virDomainDelIOThread etc.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 76 ++
 1 file changed, 76 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 8de8779c7f..e0b7ace4ed 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9586,6 +9586,81 @@ testDomainGetMessages(virDomainPtr dom,
 return rv;
 }
 
+typedef enum {
+VIR_DOMAIN_IOTHREAD_ACTION_ADD,
+} virDomainIOThreadAction;
+
+static int
+testDomainChgIOThread(virDomainObj *vm,
+  unsigned int iothread_id,
+  virDomainIOThreadAction action,
+  unsigned int flags)
+{
+virDomainDef *def;
+int ret = -1;
+
+if (!(def = virDomainObjGetOneDef(vm, flags)))
+return ret;
+
+if (def) {
+switch (action) {
+case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
+if (virDomainDriverAddIOThreadCheck(def, iothread_id) < 0)
+return ret;
+
+if (!virDomainIOThreadIDAdd(def, iothread_id))
+return ret;
+
+break;
+}
+}
+
+ret = 0;
+
+return ret;
+}
+
+static int
+testDomainAddIOThread(virDomainPtr dom,
+  unsigned int iothread_id,
+  unsigned int flags)
+{
+virDomainObj *vm = NULL;
+testDomainObjPrivate *priv;
+testIOThreadInfo iothread;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (iothread_id == 0) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("invalid value of 0 for iothread_id"));
+return -1;
+}
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (testDomainChgIOThread(vm, iothread_id,
+  VIR_DOMAIN_IOTHREAD_ACTION_ADD, flags) < 0)
+goto cleanup;
+
+priv = vm->privateData;
+
+iothread.iothread_id = iothread_id;
+iothread.poll_max_ns = 32768;
+iothread.poll_grow = 0;
+iothread.poll_shrink = 0;
+
+g_array_append_val(priv->iothreads, iothread);
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
 /*
  * Test driver
  */
@@ -9652,6 +9727,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
 .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
 .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
+.domainAddIOThread = testDomainAddIOThread, /* 7.8.0 */
 .domainGetSecurityLabel = testDomainGetSecurityLabel, /* 7.5.0 */
 .nodeGetSecurityModel = testNodeGetSecurityModel, /* 7.5.0 */
 .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
-- 
2.33.0



[PATCH v4 01/11] domain_driver.c: Introduce and use virDomainDriverAddIOThreadCheck()

2021-09-15 Thread Luke Yue
The test driver can share the same code with qemu driver when implement
testDomainAddIOThreadCheck and testDomainDelIOThreadCheck, so extract
them for test driver to use.

Signed-off-by: Luke Yue 
---
 src/hypervisor/domain_driver.c | 64 ++
 src/hypervisor/domain_driver.h |  6 
 src/libvirt_private.syms   |  2 ++
 src/qemu/qemu_driver.c | 60 +++
 4 files changed, 76 insertions(+), 56 deletions(-)

diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
index 2969d55173..3eb2401053 100644
--- a/src/hypervisor/domain_driver.c
+++ b/src/hypervisor/domain_driver.c
@@ -512,3 +512,67 @@ virDomainDriverNodeDeviceDetachFlags(virNodeDevicePtr dev,
 
 return virHostdevPCINodeDeviceDetach(hostdevMgr, pci);
 }
+
+/**
+ * virDomainDriverAddIOThreadCheck:
+ * @def: domain definition
+ * @iothread_id: iothread id
+ *
+ * Returns -1 if an IOThread is already using the given iothread id
+ */
+int
+virDomainDriverAddIOThreadCheck(virDomainDef *def,
+unsigned int iothread_id)
+{
+if (virDomainIOThreadIDFind(def, iothread_id)) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("an IOThread is already using iothread_id '%u'"),
+   iothread_id);
+return -1;
+}
+
+return 0;
+}
+
+/**
+ * virDomainDriverDelIOThreadCheck:
+ * @def: domain definition
+ * @iothread_id: iothread id
+ *
+ * Returns -1 if there is no IOThread using the given iothread id
+ */
+int
+virDomainDriverDelIOThreadCheck(virDomainDef *def,
+unsigned int iothread_id)
+{
+size_t i;
+
+if (!virDomainIOThreadIDFind(def, iothread_id)) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("cannot find IOThread '%u' in iothreadids list"),
+   iothread_id);
+return -1;
+}
+
+for (i = 0; i < def->ndisks; i++) {
+if (def->disks[i]->iothread == iothread_id) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("cannot remove IOThread %u since it "
+ "is being used by disk '%s'"),
+   iothread_id, def->disks[i]->dst);
+return -1;
+}
+}
+
+for (i = 0; i < def->ncontrollers; i++) {
+if (def->controllers[i]->iothread == iothread_id) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("cannot remove IOThread '%u' since it "
+ "is being used by controller"),
+   iothread_id);
+return -1;
+}
+}
+
+return 0;
+}
diff --git a/src/hypervisor/domain_driver.h b/src/hypervisor/domain_driver.h
index 5970eef082..d91d21bc91 100644
--- a/src/hypervisor/domain_driver.h
+++ b/src/hypervisor/domain_driver.h
@@ -60,3 +60,9 @@ int virDomainDriverNodeDeviceReAttach(virNodeDevicePtr dev,
 int virDomainDriverNodeDeviceDetachFlags(virNodeDevicePtr dev,
  virHostdevManager *hostdevMgr,
  const char *driverName);
+
+int virDomainDriverAddIOThreadCheck(virDomainDef *def,
+unsigned int iothread_id);
+
+int virDomainDriverDelIOThreadCheck(virDomainDef *def,
+unsigned int iothread_id);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ace35d709f..d45b644caf 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1537,6 +1537,8 @@ virDomainCgroupSetupMemtune;
 
 
 # hypervisor/domain_driver.h
+virDomainDriverAddIOThreadCheck;
+virDomainDriverDelIOThreadCheck;
 virDomainDriverGenerateMachineName;
 virDomainDriverGenerateRootHash;
 virDomainDriverMergeBlkioDevice;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6ae678b165..f2acb37c76 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5445,58 +5445,6 @@ qemuDomainHotplugDelIOThread(virQEMUDriver *driver,
 }
 
 
-static int
-qemuDomainAddIOThreadCheck(virDomainDef *def,
-   unsigned int iothread_id)
-{
-if (virDomainIOThreadIDFind(def, iothread_id)) {
-virReportError(VIR_ERR_INVALID_ARG,
-   _("an IOThread is already using iothread_id '%u'"),
-   iothread_id);
-return -1;
-}
-
-return 0;
-}
-
-
-static int
-qemuDomainDelIOThreadCheck(virDomainDef *def,
-   unsigned int iothread_id)
-{
-size_t i;
-
-if (!virDomainIOThreadIDFind(def, iothread_id)) {
-virReportError(VIR_ERR_INVALID_ARG,
-   _("cannot find IOThread '%u' in iothreadids list"),
-   iothread_id);
- 

[PATCH v4 02/11] test_driver: Introduce testIOThreadInfo and generate IOThread infos

2021-09-15 Thread Luke Yue
Introduce testIOThreadInfo to store IOThread infos: iothread_id,
poll_max_ns, poll_grow and poll_shrink for future usage.

Add an example of IOThread configuration to testdomfc4.xml, we also want
to generate default testIOThreadInfo for the IOThread configured in the
xml, so introduce testDomainGenerateIOThreadInfos, the values are taken
from QEMU.

Signed-off-by: Luke Yue 
---
 examples/xml/test/testdomfc4.xml |  5 +
 src/test/test_driver.c   | 37 
 2 files changed, 42 insertions(+)

diff --git a/examples/xml/test/testdomfc4.xml b/examples/xml/test/testdomfc4.xml
index 26b7f25a06..cb4dd0cf70 100644
--- a/examples/xml/test/testdomfc4.xml
+++ b/examples/xml/test/testdomfc4.xml
@@ -11,6 +11,11 @@
   261072
   131072
   1
+  2
+  
+
+
+  
   
 
   
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 2c2c6f52d1..8de8779c7f 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -183,6 +183,14 @@ struct _testDomainNamespaceDef {
 xmlNodePtr *snap_nodes;
 };
 
+typedef struct _testIOThreadInfo testIOThreadInfo;
+struct _testIOThreadInfo {
+unsigned int iothread_id;
+unsigned long long poll_max_ns;
+unsigned int poll_grow;
+unsigned int poll_shrink;
+};
+
 static void
 testDomainDefNamespaceFree(void *data)
 {
@@ -381,6 +389,9 @@ struct _testDomainObjPrivate {
 /* used by get/set time APIs */
 long long seconds;
 unsigned int nseconds;
+
+/* used by IOThread APIs */
+GArray *iothreads;
 };
 
 
@@ -397,6 +408,8 @@ testDomainObjPrivateAlloc(void *opaque)
 priv->seconds = 627319920;
 priv->nseconds = 0;
 
+priv->iothreads = g_array_new(FALSE, FALSE, sizeof(testIOThreadInfo));
+
 return priv;
 }
 
@@ -427,6 +440,8 @@ static void
 testDomainObjPrivateFree(void *data)
 {
 testDomainObjPrivate *priv = data;
+
+g_array_free(priv->iothreads, TRUE);
 g_free(priv);
 }
 
@@ -696,6 +711,26 @@ testDomainGenerateIfnames(virDomainDef *domdef)
 return 0;
 }
 
+static void
+testDomainGenerateIOThreadInfos(virDomainObj *obj)
+{
+size_t i;
+testDomainObjPrivate *priv;
+
+if (!obj->def->iothreadids || !obj->def->niothreadids)
+return;
+
+priv = obj->privateData;
+
+for (i = 0; i < obj->def->niothreadids; i++) {
+testIOThreadInfo iothread;
+iothread.iothread_id = obj->def->iothreadids[i]->iothread_id;
+iothread.poll_max_ns = 32768;
+iothread.poll_grow = 0;
+iothread.poll_shrink = 0;
+g_array_append_val(priv->iothreads, iothread);
+}
+}
 
 static void
 testDomainShutdownState(virDomainPtr domain,
@@ -1045,6 +1080,8 @@ testParseDomains(testDriver *privconn,
 
 testDomainObjCheckTaint(obj);
 
+testDomainGenerateIOThreadInfos(obj);
+
 virDomainObjEndAPI(&obj);
 }
 
-- 
2.33.0



Re: [PATCH v3 0/5] Implement some job related APIs for test driver

2021-09-02 Thread Luke Yue
On Wed, 2021-08-18 at 22:17 +0800, Luke Yue wrote:
> v3:
> - Fix virDomainGetJobStats when use completed flags
> - Introduce testDomainSetDummyData
> - Add and refine some tests
> 
> Luke Yue (5):
>   test_driver: Implement virDomainGetJobInfo
>   test_driver: Implement virDomainGetJobStats
>   test_driver: Implement virDomainAbortJob
>   test_driver: Introduce testDomainSetDummyData
>   virshtest: add test for domjobinfo and domjobabort
> 
>  src/test/test_driver.c | 274
> +
>  tests/virshtest.c  |  89 +
>  2 files changed, 363 insertions(+)
> 

polite ping



[PATCH 0/3] Add an option to use virDomainGetSecurityLabelList and test it

2021-09-02 Thread Luke Yue
Luke Yue (3):
  test_driver: Implement virDomainGetSecurityLabelList
  virsh: Add '--full-seclabels' option for dominfo
  tests: Add test for virDomainGetSecurityLabelList

 docs/manpages/virsh.rst  |  5 +-
 src/test/test_driver.c   | 42 +
 tests/virsh-undefine |  8 ++--
 tests/virshtest.c| 74 +++---
 tools/virsh-domain-monitor.c | 89 
 5 files changed, 146 insertions(+), 72 deletions(-)

-- 
2.33.0



[PATCH 2/3] virsh: Add '--full-seclabels' option for dominfo

2021-09-02 Thread Luke Yue
There is no virsh command uses virDomainGetSecurityLabelList API, so add
an option for dominfo to call it and print full list of security labels.

Also realign some outputs as it's now "Security labels:" instead of
"Security label:".

Signed-off-by: Luke Yue 
---
 docs/manpages/virsh.rst  |  5 +-
 tests/virsh-undefine |  8 ++--
 tests/virshtest.c| 70 ++--
 tools/virsh-domain-monitor.c | 89 
 4 files changed, 101 insertions(+), 71 deletions(-)

diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 2204bed3bb..183033049d 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -2008,9 +2008,10 @@ dominfo
 
 ::
 
-   dominfo domain
+   dominfo domain [--full-seclabels]
 
-Returns basic information about the domain.
+Returns basic information about the domain. *--full-seclabels* tells virsh
+to print full list of security labels.
 
 
 domjobabort
diff --git a/tests/virsh-undefine b/tests/virsh-undefine
index dbbb367391..7feefdec79 100755
--- a/tests/virsh-undefine
+++ b/tests/virsh-undefine
@@ -35,11 +35,11 @@ $abs_top_builddir/tools/virsh -c test:///default \
 test $? = 0 || fail=1
 sed '/^Persistent/n; /:/d' < out1 > out
 cat <<\EOF > exp || fail=1
-Persistent: yes
+Persistent:  yes
 
 Domain 'test' has been undefined
 
-Persistent: no
+Persistent:  no
 
 EOF
 compare exp out || fail=1
@@ -50,11 +50,11 @@ $abs_top_builddir/tools/virsh -c test:///default \
 test $? = 0 || fail=1
 sed '/^Persistent/n; /:/d' < out1 > out
 cat <<\EOF > exp || fail=1
-Persistent: yes
+Persistent:  yes
 
 Domain '1' has been undefined
 
-Persistent: no
+Persistent:  no
 
 EOF
 compare exp out || fail=1
diff --git a/tests/virshtest.c b/tests/virshtest.c
index 87da1f5889..0d703f3765 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -25,51 +25,51 @@ main(void)
 # define SECURITY_LABEL "libvirt-test (enforcing)"
 # define FC4_MESSAGES "tainted: network configuration using opaque shell 
scripts"
 # define FC5_MESSAGES "tainted: running with undesirable elevated privileges\n\
-tainted: network configuration using opaque shell scripts\n\
-tainted: use of host cdrom passthrough\n\
-tainted: custom device tree blob used\n\
-tainted: use of deprecated configuration settings\n\
-deprecated configuration: CPU model Deprecated-Test"
+ tainted: network configuration using opaque shell scripts\n\
+ tainted: use of host cdrom passthrough\n\
+ tainted: custom device tree blob used\n\
+ tainted: use of deprecated configuration settings\n\
+ deprecated configuration: CPU model Deprecated-Test"
 # define GET_BLKIO_PARAMETER "/dev/hda,700"
 # define SET_BLKIO_PARAMETER "/dev/hda,1000"
 
 static const char *dominfo_fc4 = "\
-Id: 2\n\
-Name:   fc4\n\
-UUID:   " DOM_FC4_UUID "\n\
-OS Type:linux\n\
-State:  running\n\
-CPU(s): 1\n\
-Max memory: 261072 KiB\n\
-Used memory:131072 KiB\n\
-Persistent: yes\n\
-Autostart:  disable\n\
-Managed save:   no\n\
-Security model: testSecurity\n\
-Security DOI:   \n\
-Security label: " SECURITY_LABEL "\n\
-Messages:   " FC4_MESSAGES "\n\
+Id:  2\n\
+Name:fc4\n\
+UUID:" DOM_FC4_UUID "\n\
+OS Type: linux\n\
+State:   running\n\
+CPU(s):  1\n\
+Max memory:  261072 KiB\n\
+Used memory: 131072 KiB\n\
+Persistent:  yes\n\
+Autostart:   disable\n\
+Managed save:no\n\
+Security model:  testSecurity\n\
+Security DOI:\n\
+Security labels: " SECURITY_LABEL "\n\
+Messages:" FC4_MESSAGES "\n\
 \n";
 static const char *domuuid_fc4 = DOM_FC4_UUID "\n\n";
 static const char *domid_fc4 = "2\n\n";
 static const char *domname_fc4 = "fc4\n\n";
 static const char *domstate_fc4 = "running\n\n";
 static const char *dominfo_fc5 = "\
-Id: 3\n\
-Name:   fc5\n\
-UUID:   " DOM_FC5_UUID "\n\
-OS Type:linux\n\
-State:  running\n\
-CPU(s): 4\n\
-Max memory: 2097152 KiB\n\
-Used memory:2097152 KiB\n\
-Persistent: yes\n\
-Autostart:  disable\n\
-Managed save:   no\n\
-Security model: testSecurity\n\
-Security DOI:   \n\
-Security label: " SECURITY_LABEL "\n\
-Messages:   " FC5_MESSAGES "\n\
+Id:  3\n\
+Name:fc5\n\
+UUID:" DOM_FC5_UUID "\n\
+OS Type: linux\n\
+State:   running\n\
+CPU(s):  4\n\
+Max memory:  2097152 KiB\n\
+Used memory: 2097152

[PATCH 3/3] tests: Add test for virDomainGetSecurityLabelList

2021-09-02 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index 0d703f3765..4fb4799456 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -69,6 +69,7 @@ Managed save:no\n\
 Security model:  testSecurity\n\
 Security DOI:\n\
 Security labels: " SECURITY_LABEL "\n\
+ " SECURITY_LABEL "\n\
 Messages:" FC5_MESSAGES "\n\
 \n";
 
@@ -237,7 +238,8 @@ static int testCompareDominfoByName(const void *data 
G_GNUC_UNUSED)
 
 static int testCompareTaintedDominfoByName(const void *data G_GNUC_UNUSED)
 {
-const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "fc5", NULL };
+const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "fc5",
+ "--full-seclabels", NULL };
 const char *exp = dominfo_fc5;
 return testCompareOutputLit(exp, "\nCPU time:", argv);
 }
-- 
2.33.0



[PATCH 1/3] test_driver: Implement virDomainGetSecurityLabelList

2021-09-02 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 42 ++
 1 file changed, 42 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 2f19b7c520..1b5914c890 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -137,6 +137,7 @@ VIR_ONCE_GLOBAL_INIT(testDriver);
 
 #define TEST_MODEL "i686"
 #define TEST_EMULATOR "/usr/bin/test-hv"
+#define TEST_SECURITY_LABEL_LIST_LENGTH 2
 
 static const virNodeInfo defaultNodeInfo = {
 TEST_MODEL,
@@ -5261,6 +5262,46 @@ testDomainGetSecurityLabel(virDomainPtr dom,
 return ret;
 }
 
+static int
+testDomainGetSecurityLabelList(virDomainPtr dom,
+   virSecurityLabelPtr* seclabels)
+{
+virDomainObj *vm;
+size_t i;
+int ret = -1;
+
+if (!(vm = testDomObjFromDomain(dom)))
+return -1;
+
+if (!virDomainObjIsActive(vm)) {
+/* No seclabels */
+*seclabels = NULL;
+ret = 0;
+} else {
+int len = TEST_SECURITY_LABEL_LIST_LENGTH;
+
+(*seclabels) = g_new0(virSecurityLabel, len);
+memset(*seclabels, 0, sizeof(**seclabels) * len);
+
+/* Fill the array */
+for (i = 0; i < len; i++) {
+if (virStrcpyStatic((*seclabels)[i].label, "libvirt-test") < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("security label exceeds maximum: %zu"),
+   sizeof((*seclabels)[i].label) - 1);
+g_clear_pointer(seclabels, g_free);
+goto cleanup;
+}
+(*seclabels)[i].enforcing = 1;
+}
+ret = len;
+}
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 static int
 testNodeGetSecurityModel(virConnectPtr conn,
  virSecurityModelPtr secmodel)
@@ -9615,6 +9656,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
 .domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
 .domainGetSecurityLabel = testDomainGetSecurityLabel, /* 7.5.0 */
+.domainGetSecurityLabelList = testDomainGetSecurityLabelList, /* 7.8.0 */
 .nodeGetSecurityModel = testNodeGetSecurityModel, /* 7.5.0 */
 .domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
 .domainSetMemoryParameters = testDomainSetMemoryParameters, /* 5.6.0 */
-- 
2.33.0



[PATCH v2 04/12] test_driver: Implement virDomainDetachDeviceAlias

2021-08-20 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 5e4d6d37ef..6cabf78e7c 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9737,6 +9737,16 @@ testDomainDetachDeviceFlags(virDomainPtr dom,
 return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
xml, NULL, flags);
 }
+
+static int
+testDomainDetachDeviceAlias(virDomainPtr dom,
+const char *alias,
+unsigned int flags)
+{
+return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
+   NULL, alias, flags);
+}
+
 /*
  * Test driver
  */
@@ -9828,6 +9838,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainFSFreeze = testDomainFSFreeze, /* 5.7.0 */
 .domainFSThaw = testDomainFSThaw, /* 5.7.0 */
 .domainFSTrim = testDomainFSTrim, /* 5.7.0 */
+.domainDetachDeviceAlias = testDomainDetachDeviceAlias, /* 7.7.0 */
 .domainDetachDeviceFlags = testDomainDetachDeviceFlags, /* 7.7.0 */
 .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
 .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
-- 
2.33.0



[PATCH v2 01/12] conf: Introduce virDomainInputDefRemove and fix memory leak

2021-08-20 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.c   | 12 
 src/conf/domain_conf.h   |  2 ++
 src/libvirt_private.syms |  1 +
 src/qemu/qemu_driver.c   |  3 ++-
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 10effdce69..6667426b9a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16760,6 +16760,18 @@ virDomainInputDefFind(const virDomainDef *def,
 }
 
 
+virDomainInputDef *
+virDomainInputDefRemove(virDomainDef *def,
+size_t idx)
+{
+virDomainInputDef *ret = def->inputs[idx];
+
+VIR_DELETE_ELEMENT(def->inputs, idx, def->ninputs);
+
+return ret;
+}
+
+
 bool
 virDomainVsockDefEquals(const virDomainVsockDef *a,
 const virDomainVsockDef *b)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c7e6df7981..3e4701176d 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3815,6 +3815,8 @@ virDomainShmemDef *virDomainShmemDefRemove(virDomainDef 
*def, size_t idx)
 ssize_t virDomainInputDefFind(const virDomainDef *def,
   const virDomainInputDef *input)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+virDomainInputDef *virDomainInputDefRemove(virDomainDef *def, size_t idx)
+ATTRIBUTE_NONNULL(1);
 bool virDomainVsockDefEquals(const virDomainVsockDef *a,
  const virDomainVsockDef *b)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 090ac80691..f74291cb06 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -476,6 +476,7 @@ virDomainInputBusTypeToString;
 virDomainInputDefFind;
 virDomainInputDefFree;
 virDomainInputDefGetPath;
+virDomainInputDefRemove;
 virDomainInputSourceGrabToggleTypeFromString;
 virDomainInputSourceGrabToggleTypeToString;
 virDomainInputSourceGrabTypeFromString;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f31e13889e..c008921582 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7569,7 +7569,8 @@ qemuDomainDetachDeviceConfig(virDomainDef *vmdef,
_("matching input device not found"));
 return -1;
 }
-VIR_DELETE_ELEMENT(vmdef->inputs, idx, vmdef->ninputs);
+
+virDomainInputDefFree(virDomainInputDefRemove(vmdef, idx));
 break;
 
 case VIR_DOMAIN_DEVICE_VSOCK:
-- 
2.33.0



[PATCH v2 09/12] test_driver: add memballoon support for testDomainDetachDeviceLiveAndConfig

2021-08-20 Thread Luke Yue
As the memballoon device shouldn't be hot-(un)pluggable, so error if try
to remove it on a running domain, for removing from config, it's fine.

Signed-off-by: Luke Yue 
---
 src/hypervisor/domain_driver.c | 18 ++
 src/hypervisor/domain_driver.h |  3 +++
 src/libvirt_private.syms   |  1 +
 src/test/test_driver.c | 19 ---
 4 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
index 93754ae08a..34e225dd2d 100644
--- a/src/hypervisor/domain_driver.c
+++ b/src/hypervisor/domain_driver.c
@@ -797,3 +797,21 @@ virDomainDriverDetachTPMDeviceConfig(virDomainDef *vmdef,
 
 return 0;
 }
+
+
+int
+virDomainDriverDetachMemballoonDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+if (!vmdef->memballoon ||
+!virDomainMemballoonDefEquals(dev->data.memballoon,
+  vmdef->memballoon)) {
+virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+   _("matching memballoon device not found"));
+return -1;
+}
+virDomainMemballoonDefFree(vmdef->memballoon);
+vmdef->memballoon = NULL;
+
+return 0;
+}
diff --git a/src/hypervisor/domain_driver.h b/src/hypervisor/domain_driver.h
index 6cb9defb58..4d8b1f7b36 100644
--- a/src/hypervisor/domain_driver.h
+++ b/src/hypervisor/domain_driver.h
@@ -104,3 +104,6 @@ int virDomainDriverDetachVsockDeviceConfig(virDomainDef 
*vmdef,
 
 int virDomainDriverDetachTPMDeviceConfig(virDomainDef *vmdef,
  virDomainDeviceDef *dev);
+
+int virDomainDriverDetachMemballoonDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 57f0d24c36..fc4e8736b0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1543,6 +1543,7 @@ virDomainDriverDetachFSDeviceConfig;
 virDomainDriverDetachHostdevDeviceConfig;
 virDomainDriverDetachInputDeviceConfig;
 virDomainDriverDetachLeaseDeviceConfig;
+virDomainDriverDetachMemballoonDeviceConfig;
 virDomainDriverDetachMemoryDeviceConfig;
 virDomainDriverDetachNetDeviceConfig;
 virDomainDriverDetachRedirdevDeviceConfig;
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index c12a76749c..bf26df0d18 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9539,7 +9539,8 @@ testDomainGetMessages(virDomainPtr dom,
 
 static int
 testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
-virDomainDeviceDef *dev)
+virDomainDeviceDef *dev,
+unsigned int flags)
 {
 virDomainChrDef *chr;
 
@@ -9641,11 +9642,23 @@ testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
 
 break;
 
+case VIR_DOMAIN_DEVICE_MEMBALLOON:
+if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+   _("detach of device '%s' on running domain "
+ "is not supported"),
+   virDomainDeviceTypeToString(dev->type));
+return -1;
+} else {
+if (virDomainDriverDetachMemballoonDeviceConfig(vmdef, dev) < 0)
+return -1;
+}
+break;
+
 case VIR_DOMAIN_DEVICE_VIDEO:
 case VIR_DOMAIN_DEVICE_GRAPHICS:
 case VIR_DOMAIN_DEVICE_HUB:
 case VIR_DOMAIN_DEVICE_SMARTCARD:
-case VIR_DOMAIN_DEVICE_MEMBALLOON:
 case VIR_DOMAIN_DEVICE_NVRAM:
 case VIR_DOMAIN_DEVICE_NONE:
 case VIR_DOMAIN_DEVICE_PANIC:
@@ -9711,7 +9724,7 @@ testDomainChgDevice(virDomainPtr dom,
 break;
 
 case VIR_DOMAIN_DEVICE_ACTION_DETACH:
-if (testDomainDetachDeviceLiveAndConfig(def, dev) < 0)
+if (testDomainDetachDeviceLiveAndConfig(def, dev, flags) < 0)
 goto cleanup;
 break;
 
-- 
2.33.0



[PATCH v2 08/12] conf: Add a memballoon helper for future use

2021-08-20 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.c   | 24 
 src/conf/domain_conf.h   |  4 
 src/libvirt_private.syms |  1 +
 3 files changed, 29 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7f3d207a3e..62bb6669e8 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16857,6 +16857,30 @@ virDomainTPMDefRemove(virDomainDef *def,
 }
 
 
+bool
+virDomainMemballoonDefEquals(const virDomainMemballoonDef *a,
+ const virDomainMemballoonDef *b)
+{
+if (a->model != b->model)
+return false;
+
+if (a->period != b->period)
+return false;
+
+if (a->autodeflate != b->autodeflate)
+return false;
+
+if (a->free_page_reporting != b->free_page_reporting)
+return false;
+
+if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+!virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
+return false;
+
+return true;
+}
+
+
 char *
 virDomainDefGetDefaultEmulator(virDomainDef *def,
virCaps *caps)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index b8a1e1d2d2..a18992677b 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3827,6 +3827,10 @@ ssize_t virDomainTPMDefFind(const virDomainDef *def,
 virDomainTPMDef *virDomainTPMDefRemove(virDomainDef *def, size_t idx)
 ATTRIBUTE_NONNULL(1);
 
+bool virDomainMemballoonDefEquals(const virDomainMemballoonDef *a,
+  const virDomainMemballoonDef *b)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+
 VIR_ENUM_DECL(virDomainTaint);
 VIR_ENUM_DECL(virDomainTaintMessage);
 VIR_ENUM_DECL(virDomainVirt);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 349cce2f00..57f0d24c36 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -504,6 +504,7 @@ virDomainLoaderTypeFromString;
 virDomainLoaderTypeToString;
 virDomainLockFailureTypeFromString;
 virDomainLockFailureTypeToString;
+virDomainMemballoonDefEquals;
 virDomainMemballoonModelTypeFromString;
 virDomainMemballoonModelTypeToString;
 virDomainMemoryDefFree;
-- 
2.33.0



[PATCH v2 03/12] test_driver: Implement virDomainDetachDeviceFlags

2021-08-20 Thread Luke Yue
Introduce testDomainChgDevice for further development (just like what we
did for IOThread). And introduce testDomainDetachDeviceLiveAndConfig for
detaching devices.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 201 +
 1 file changed, 201 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 10a1767542..5e4d6d37ef 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9537,6 +9537,206 @@ testDomainGetMessages(virDomainPtr dom,
 return rv;
 }
 
+static int
+testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+virDomainChrDef *chr;
+
+switch (dev->type) {
+case VIR_DOMAIN_DEVICE_DISK:
+if (virDomainDriverDetachDiskDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_NET:
+if (virDomainDriverDetachNetDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_SOUND:
+if (virDomainDriverDetachSoundDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_HOSTDEV:
+if (virDomainDriverDetachHostdevDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_LEASE:
+if (virDomainDriverDetachLeaseDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_CONTROLLER:
+if (virDomainDriverDetachControllerDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_FS:
+if (virDomainDriverDetachFSDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_RNG:
+if (virDomainDriverDetachRNGDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_MEMORY:
+if (virDomainDriverDetachMemoryDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_REDIRDEV:
+if (virDomainDriverDetachRedirdevDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_SHMEM:
+if (virDomainDriverDetachShmemDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_WATCHDOG:
+if (virDomainDriverDetachWatchdogDeviceConfig(vmdef) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_INPUT:
+if (virDomainDriverDetachInputDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_VSOCK:
+if (virDomainDriverDetachVsockDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
+case VIR_DOMAIN_DEVICE_CHR:
+if (!(chr = virDomainChrRemove(vmdef, dev->data.chr)))
+return -1;
+
+virDomainChrDefFree(chr);
+break;
+
+case VIR_DOMAIN_DEVICE_VIDEO:
+case VIR_DOMAIN_DEVICE_GRAPHICS:
+case VIR_DOMAIN_DEVICE_HUB:
+case VIR_DOMAIN_DEVICE_SMARTCARD:
+case VIR_DOMAIN_DEVICE_MEMBALLOON:
+case VIR_DOMAIN_DEVICE_NVRAM:
+case VIR_DOMAIN_DEVICE_NONE:
+case VIR_DOMAIN_DEVICE_TPM:
+case VIR_DOMAIN_DEVICE_PANIC:
+case VIR_DOMAIN_DEVICE_IOMMU:
+case VIR_DOMAIN_DEVICE_AUDIO:
+case VIR_DOMAIN_DEVICE_LAST:
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+   _("detach of device '%s' is not supported"),
+   virDomainDeviceTypeToString(dev->type));
+return -1;
+}
+
+return 0;
+}
+
+static int
+testDomainChgDevice(virDomainPtr dom,
+virDomainDeviceAction action,
+const char *xml,
+const char *alias,
+unsigned int flags)
+{
+testDriver *driver = dom->conn->privateData;
+virDomainObj *vm = NULL;
+virDomainDef *def;
+virDomainDeviceDef *dev = NULL;
+unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDef(vm, flags)))
+goto cleanup;
+
+if (action == VIR_DOMAIN_DEVICE_ACTION_DETACH)
+parse_flags |= VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
+
+if (xml) {
+if (!(dev = virDomainDeviceDefParse(xml, def, driver->xmlopt,
+driver->caps, parse_flags)))
+goto cleanup;
+} else if (alias) {
+dev = g_new0(virDomainDeviceDef, 1);
+if (virDomainDefFindDevice(def, alias, dev, true) < 0)
+goto clea

[PATCH v2 00/12] Implement detach device related APIs for test driver

2021-08-20 Thread Luke Yue
v2:
- Extract DetachXXXDeviceConfig functions from drivers and use them
- Add a trial implementation of detach memballoon and TPM, if they are
fine, more device support will be added to test driver in the future
- Add expectError to testCompareOutputLit for some "fail on purpose"
tests
- Refine tests

Luke Yue (12):
  conf: Introduce virDomainInputDefRemove and fix memory leak
  domain_driver: extract DetachXXXDeviceConfig related functions and use
them
  test_driver: Implement virDomainDetachDeviceFlags
  test_driver: Implement virDomainDetachDeviceAlias
  test_driver: Implement virDomainDetachDevice
  conf: Add tpm helpers for future use
  test_driver: add TPM support for testDomainDetachDeviceLiveAndConfig
  conf: Add a memballoon helper for future use
  test_driver: add memballoon support for
testDomainDetachDeviceLiveAndConfig
  examples: xml: test: add xml for testing devices related APIs
  virshtest: add expectError parameter to testCompareOutputLit
  tests: Test detach-device and detach-device-alias for test driver

 examples/xml/test/testdevcontroller.xml |   1 +
 examples/xml/test/testdevdiskcdrom.xml  |   5 +
 examples/xml/test/testdevfs.xml |   6 +
 examples/xml/test/testdevhostdev.xml|   5 +
 examples/xml/test/testdevif.xml |   6 +
 examples/xml/test/testdevinput.xml  |   1 +
 examples/xml/test/testdevlease.xml  |   5 +
 examples/xml/test/testdevmem.xml|   6 +
 examples/xml/test/testdevmemballoon.xml |   3 +
 examples/xml/test/testdevrng.xml|   4 +
 examples/xml/test/testdevshmem.xml  |   4 +
 examples/xml/test/testdevsound.xml  |   3 +
 examples/xml/test/testdevtpm.xml|   5 +
 examples/xml/test/testdevvsock.xml  |   3 +
 examples/xml/test/testdevwatchdog.xml   |   1 +
 examples/xml/test/testdomfc5.xml|  54 +
 examples/xml/test/testnodeinline.xml|  54 +
 src/conf/domain_conf.c  | 103 
 src/conf/domain_conf.h  |  12 +
 src/hypervisor/domain_driver.c  | 303 
 src/hypervisor/domain_driver.h  |  47 
 src/libvirt_private.syms|  20 ++
 src/libxl/libxl_driver.c|  41 +---
 src/lxc/lxc_driver.c|  37 +--
 src/qemu/qemu_driver.c  | 124 ++
 src/test/test_driver.c  | 239 +++
 tests/virshtest.c   | 131 --
 27 files changed, 1033 insertions(+), 190 deletions(-)
 create mode 100644 examples/xml/test/testdevcontroller.xml
 create mode 100644 examples/xml/test/testdevdiskcdrom.xml
 create mode 100644 examples/xml/test/testdevfs.xml
 create mode 100644 examples/xml/test/testdevhostdev.xml
 create mode 100644 examples/xml/test/testdevif.xml
 create mode 100644 examples/xml/test/testdevinput.xml
 create mode 100644 examples/xml/test/testdevlease.xml
 create mode 100644 examples/xml/test/testdevmem.xml
 create mode 100644 examples/xml/test/testdevmemballoon.xml
 create mode 100644 examples/xml/test/testdevrng.xml
 create mode 100644 examples/xml/test/testdevshmem.xml
 create mode 100644 examples/xml/test/testdevsound.xml
 create mode 100644 examples/xml/test/testdevtpm.xml
 create mode 100644 examples/xml/test/testdevvsock.xml
 create mode 100644 examples/xml/test/testdevwatchdog.xml

-- 
2.33.0



[PATCH v2 11/12] virshtest: add expectError parameter to testCompareOutputLit

2021-08-20 Thread Luke Yue
Add expectError so that we can failed some test on purpose and compare
the error message.

There are some problems though, if the command raise an internal error,
the test would fail. And when testing command is failed on purpose, the
error message will be printed even the test passed.

Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 53 ++-
 1 file changed, 29 insertions(+), 24 deletions(-)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index 87da1f5889..0d2ffd960a 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -109,7 +109,7 @@ static int testFilterLine(char *buffer,
 }
 
 static int
-testCompareOutputLit(const char *expectData,
+testCompareOutputLit(const char *expectData, const char *expectError,
  const char *filter, const char *const argv[])
 {
 g_autofree char *actualData = NULL;
@@ -125,14 +125,19 @@ testCompareOutputLit(const char *expectData,
 virCommandSetOutputBuffer(cmd, &actualData);
 virCommandSetErrorBuffer(cmd, &errbuf);
 
-if (virCommandRun(cmd, NULL) < 0)
+if (virCommandRun(cmd, NULL) < 0 && STREQ(expectError, ""))
 return -1;
 
-if (STRNEQ(errbuf, "")) {
+if (STREQ(expectError, "") && STRNEQ(errbuf, "")) {
 fprintf(stderr, "Command reported error: %s", errbuf);
 return -1;
 }
 
+if (STRNEQ(errbuf, expectError)) {
+virTestDifference(stderr, errbuf, expectError);
+return -1;
+}
+
 if (filter && testFilterLine(actualData, filter) < 0)
 return -1;
 
@@ -162,7 +167,7 @@ static int testCompareListDefault(const void *data 
G_GNUC_UNUSED)
 --\n\
  1test   running\n\
 \n";
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareListCustom(const void *data G_GNUC_UNUSED)
@@ -175,7 +180,7 @@ static int testCompareListCustom(const void *data 
G_GNUC_UNUSED)
  2fc4running\n\
  3fc5running\n\
 \n";
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareNodeinfoDefault(const void *data G_GNUC_UNUSED)
@@ -191,7 +196,7 @@ Thread(s) per core:  2\n\
 NUMA cell(s):2\n\
 Memory size: 3145728 KiB\n\
 \n";
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareNodeinfoCustom(const void *data G_GNUC_UNUSED)
@@ -211,112 +216,112 @@ Thread(s) per core:  2\n\
 NUMA cell(s):4\n\
 Memory size: 8192000 KiB\n\
 \n";
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareDominfoByID(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "2", NULL };
 const char *exp = dominfo_fc4;
-return testCompareOutputLit(exp, "\nCPU time:", argv);
+return testCompareOutputLit(exp, "", "\nCPU time:", argv);
 }
 
 static int testCompareDominfoByUUID(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "dominfo", DOM_FC4_UUID, NULL };
 const char *exp = dominfo_fc4;
-return testCompareOutputLit(exp, "\nCPU time:", argv);
+return testCompareOutputLit(exp, "", "\nCPU time:", argv);
 }
 
 static int testCompareDominfoByName(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "fc4", NULL };
 const char *exp = dominfo_fc4;
-return testCompareOutputLit(exp, "\nCPU time:", argv);
+return testCompareOutputLit(exp, "", "\nCPU time:", argv);
 }
 
 static int testCompareTaintedDominfoByName(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "dominfo", "fc5", NULL };
 const char *exp = dominfo_fc5;
-return testCompareOutputLit(exp, "\nCPU time:", argv);
+return testCompareOutputLit(exp, "", "\nCPU time:", argv);
 }
 
 static int testCompareDomuuidByID(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "domuuid", "2", NULL };
 const char *exp = domuuid_fc4;
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareDomuuidByName(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_CUSTOM, "domuuid", "fc4", NULL };
 const char *exp = domuuid_fc4;
-return testCompareOutputLit(exp, NULL, argv);
+return testCompareOutputLit(exp, "", NULL, argv);
 }
 
 static int testCompareDo

[PATCH v2 12/12] tests: Test detach-device and detach-device-alias for test driver

2021-08-20 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 78 +++
 1 file changed, 78 insertions(+)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index 0d2ffd960a..c37d24e900 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -159,6 +159,8 @@ static char *custom_uri;
 "--connect", \
 custom_uri
 
+# define TEST_XML_PATH abs_top_builddir "/../examples/xml/test"
+
 static int testCompareListDefault(const void *data G_GNUC_UNUSED)
 {
 const char *const argv[] = { VIRSH_DEFAULT, "list", NULL };
@@ -343,6 +345,74 @@ static int testCompareSetBlkioParameters(const void *data 
G_GNUC_UNUSED)
 return testCompareOutputLit(exp, "", NULL, argv);
 }
 
+static int testCompareDetachDevice(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "detach-device fc5\
+ " TEST_XML_PATH "/testdevif.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevdiskcdrom.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevsound.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevhostdev.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevlease.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevcontroller.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevfs.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevrng.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevmem.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevshmem.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevwatchdog.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevinput.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevvsock.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevtpm.xml;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevtpm.xml",
+ NULL };
+const char *exp =
+"Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\
+Device detached successfully\n\n\n";
+const char *error_msg =
+"error: Failed to detach device from " TEST_XML_PATH "/testdevtpm.xml\n\
+error: device not found: matching tpm device not found\n";
+return testCompareOutputLit(exp, error_msg, NULL, argv);
+}
+
+static int testCompareDetachDeviceAlias(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM,
+ "detach-device-alias fc5 ua-testCD;\
+ detach-device fc5\
+ " TEST_XML_PATH "/testdevdiskcdrom.xml",
+ NULL };
+const char *exp = "Device detach request sent successfully\n\n\n";
+const char *error_msg =
+"error: Failed to detach device from " TEST_XML_PATH "/testdevdiskcdrom.xml\n\
+error: device not found: no target device hdb\n";
+return testCompareOutputLit(exp, error_msg, NULL, argv);
+}
+
 struct testInfo {
 const char *const *argv;
 const char *result;
@@ -443,6 +513,14 @@ mymain(void)
testCompareSetBlkioParameters, NULL) != 0)
 ret = -1;
 
+if (virTestRun("virsh detach-device",
+   testCompareDetachDevice, NULL) != 0)
+ret = -1;
+
+if (virTestRun("virsh detach-device-alias",
+   testCompareDetachDeviceAlias, NULL) != 0)
+ret = -1;
+
 /* It's a bit awkward listing result before argument, but that's a
  * limitation of C99 vararg macros.  */
 # define DO_TEST(i, result, ...) \
-- 
2.33.0



[PATCH v2 10/12] examples: xml: test: add xml for testing devices related APIs

2021-08-20 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 examples/xml/test/testdevcontroller.xml |  1 +
 examples/xml/test/testdevdiskcdrom.xml  |  5 +++
 examples/xml/test/testdevfs.xml |  6 +++
 examples/xml/test/testdevhostdev.xml|  5 +++
 examples/xml/test/testdevif.xml |  6 +++
 examples/xml/test/testdevinput.xml  |  1 +
 examples/xml/test/testdevlease.xml  |  5 +++
 examples/xml/test/testdevmem.xml|  6 +++
 examples/xml/test/testdevmemballoon.xml |  3 ++
 examples/xml/test/testdevrng.xml|  4 ++
 examples/xml/test/testdevshmem.xml  |  4 ++
 examples/xml/test/testdevsound.xml  |  3 ++
 examples/xml/test/testdevtpm.xml|  5 +++
 examples/xml/test/testdevvsock.xml  |  3 ++
 examples/xml/test/testdevwatchdog.xml   |  1 +
 examples/xml/test/testdomfc5.xml| 54 +
 examples/xml/test/testnodeinline.xml| 54 +
 17 files changed, 166 insertions(+)
 create mode 100644 examples/xml/test/testdevcontroller.xml
 create mode 100644 examples/xml/test/testdevdiskcdrom.xml
 create mode 100644 examples/xml/test/testdevfs.xml
 create mode 100644 examples/xml/test/testdevhostdev.xml
 create mode 100644 examples/xml/test/testdevif.xml
 create mode 100644 examples/xml/test/testdevinput.xml
 create mode 100644 examples/xml/test/testdevlease.xml
 create mode 100644 examples/xml/test/testdevmem.xml
 create mode 100644 examples/xml/test/testdevmemballoon.xml
 create mode 100644 examples/xml/test/testdevrng.xml
 create mode 100644 examples/xml/test/testdevshmem.xml
 create mode 100644 examples/xml/test/testdevsound.xml
 create mode 100644 examples/xml/test/testdevtpm.xml
 create mode 100644 examples/xml/test/testdevvsock.xml
 create mode 100644 examples/xml/test/testdevwatchdog.xml

diff --git a/examples/xml/test/testdevcontroller.xml 
b/examples/xml/test/testdevcontroller.xml
new file mode 100644
index 00..d855bfa17f
--- /dev/null
+++ b/examples/xml/test/testdevcontroller.xml
@@ -0,0 +1 @@
+
diff --git a/examples/xml/test/testdevdiskcdrom.xml 
b/examples/xml/test/testdevdiskcdrom.xml
new file mode 100644
index 00..edc90556bb
--- /dev/null
+++ b/examples/xml/test/testdevdiskcdrom.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/examples/xml/test/testdevfs.xml b/examples/xml/test/testdevfs.xml
new file mode 100644
index 00..cee5ed4ed9
--- /dev/null
+++ b/examples/xml/test/testdevfs.xml
@@ -0,0 +1,6 @@
+
+  
+  
+  
+  
+
diff --git a/examples/xml/test/testdevhostdev.xml 
b/examples/xml/test/testdevhostdev.xml
new file mode 100644
index 00..e364b50f36
--- /dev/null
+++ b/examples/xml/test/testdevhostdev.xml
@@ -0,0 +1,5 @@
+
+  
+/dev/sdf1s
+  
+
diff --git a/examples/xml/test/testdevif.xml b/examples/xml/test/testdevif.xml
new file mode 100644
index 00..7e0be80050
--- /dev/null
+++ b/examples/xml/test/testdevif.xml
@@ -0,0 +1,6 @@
+
+  
+  
+  
+  
+
diff --git a/examples/xml/test/testdevinput.xml 
b/examples/xml/test/testdevinput.xml
new file mode 100644
index 00..d958f5b931
--- /dev/null
+++ b/examples/xml/test/testdevinput.xml
@@ -0,0 +1 @@
+
diff --git a/examples/xml/test/testdevlease.xml 
b/examples/xml/test/testdevlease.xml
new file mode 100644
index 00..c53c0c7e7d
--- /dev/null
+++ b/examples/xml/test/testdevlease.xml
@@ -0,0 +1,5 @@
+
+  testarea
+  testkey
+  
+
diff --git a/examples/xml/test/testdevmem.xml b/examples/xml/test/testdevmem.xml
new file mode 100644
index 00..49efd4af55
--- /dev/null
+++ b/examples/xml/test/testdevmem.xml
@@ -0,0 +1,6 @@
+
+  
+524287
+0
+  
+
diff --git a/examples/xml/test/testdevmemballoon.xml 
b/examples/xml/test/testdevmemballoon.xml
new file mode 100644
index 00..fde18a9db6
--- /dev/null
+++ b/examples/xml/test/testdevmemballoon.xml
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/examples/xml/test/testdevrng.xml b/examples/xml/test/testdevrng.xml
new file mode 100644
index 00..369f423740
--- /dev/null
+++ b/examples/xml/test/testdevrng.xml
@@ -0,0 +1,4 @@
+
+  
+  
+
diff --git a/examples/xml/test/testdevshmem.xml 
b/examples/xml/test/testdevshmem.xml
new file mode 100644
index 00..04bf3d9a53
--- /dev/null
+++ b/examples/xml/test/testdevshmem.xml
@@ -0,0 +1,4 @@
+
+  
+  4
+
diff --git a/examples/xml/test/testdevsound.xml 
b/examples/xml/test/testdevsound.xml
new file mode 100644
index 00..cf7323077f
--- /dev/null
+++ b/examples/xml/test/testdevsound.xml
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/examples/xml/test/testdevtpm.xml b/examples/xml/test/testdevtpm.xml
new file mode 100644
index 00..cc08b7bf6d
--- /dev/null
+++ b/examples/xml/test/testdevtpm.xml
@@ -0,0 +1,5 @@
+
+  
+
+  
+
diff --git a/examples/xml/test/testdevvsock.xml 
b/examples/xml/test/testdevvsock.xml
new file mode 100644
index 00..dda45780c4
--- /dev/null
+++ b/examples/xml/test/testdevvsock.xml
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/examples/xml/test/testdevwatchdog.xml 
b/examples/xml/test/testdevwatchdog.xml

[PATCH v2 07/12] test_driver: add TPM support for testDomainDetachDeviceLiveAndConfig

2021-08-20 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/hypervisor/domain_driver.c | 18 ++
 src/hypervisor/domain_driver.h |  3 +++
 src/libvirt_private.syms   |  1 +
 src/test/test_driver.c |  7 ++-
 4 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
index 04c12dff5b..93754ae08a 100644
--- a/src/hypervisor/domain_driver.c
+++ b/src/hypervisor/domain_driver.c
@@ -779,3 +779,21 @@ virDomainDriverDetachVsockDeviceConfig(virDomainDef *vmdef,
 
 return 0;
 }
+
+
+int
+virDomainDriverDetachTPMDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+int idx;
+
+if ((idx = virDomainTPMDefFind(vmdef, dev->data.tpm)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("matching tpm device not found"));
+return -1;
+}
+
+virDomainTPMDefFree(virDomainTPMDefRemove(vmdef, idx));
+
+return 0;
+}
diff --git a/src/hypervisor/domain_driver.h b/src/hypervisor/domain_driver.h
index 9c089f17cc..6cb9defb58 100644
--- a/src/hypervisor/domain_driver.h
+++ b/src/hypervisor/domain_driver.h
@@ -101,3 +101,6 @@ int virDomainDriverDetachInputDeviceConfig(virDomainDef 
*vmdef,
 
 int virDomainDriverDetachVsockDeviceConfig(virDomainDef *vmdef,
virDomainDeviceDef *dev);
+
+int virDomainDriverDetachTPMDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f7f3726443..349cce2f00 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1548,6 +1548,7 @@ virDomainDriverDetachRedirdevDeviceConfig;
 virDomainDriverDetachRNGDeviceConfig;
 virDomainDriverDetachShmemDeviceConfig;
 virDomainDriverDetachSoundDeviceConfig;
+virDomainDriverDetachTPMDeviceConfig;
 virDomainDriverDetachVsockDeviceConfig;
 virDomainDriverDetachWatchdogDeviceConfig;
 virDomainDriverGenerateMachineName;
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index c6aead09c9..c12a76749c 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9635,6 +9635,12 @@ testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
 virDomainChrDefFree(chr);
 break;
 
+case VIR_DOMAIN_DEVICE_TPM:
+if (virDomainDriverDetachTPMDeviceConfig(vmdef, dev) < 0)
+return -1;
+
+break;
+
 case VIR_DOMAIN_DEVICE_VIDEO:
 case VIR_DOMAIN_DEVICE_GRAPHICS:
 case VIR_DOMAIN_DEVICE_HUB:
@@ -9642,7 +9648,6 @@ testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
 case VIR_DOMAIN_DEVICE_MEMBALLOON:
 case VIR_DOMAIN_DEVICE_NVRAM:
 case VIR_DOMAIN_DEVICE_NONE:
-case VIR_DOMAIN_DEVICE_TPM:
 case VIR_DOMAIN_DEVICE_PANIC:
 case VIR_DOMAIN_DEVICE_IOMMU:
 case VIR_DOMAIN_DEVICE_AUDIO:
-- 
2.33.0



[PATCH v2 06/12] conf: Add tpm helpers for future use

2021-08-20 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/conf/domain_conf.c   | 67 
 src/conf/domain_conf.h   |  6 
 src/libvirt_private.syms |  2 ++
 3 files changed, 75 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6667426b9a..7f3d207a3e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16790,6 +16790,73 @@ virDomainVsockDefEquals(const virDomainVsockDef *a,
 }
 
 
+static bool
+virDomainTPMDefEquals(const virDomainTPMDef *a,
+  const virDomainTPMDef *b)
+{
+if (a->type != b->type)
+return false;
+
+if (a->model != b->model)
+return false;
+
+if (a->version != b->version)
+return false;
+
+if (a->type == VIR_DOMAIN_TPM_TYPE_PASSTHROUGH) {
+if (STRNEQ_NULLABLE(a->data.passthrough.source.data.file.path,
+b->data.passthrough.source.data.file.path))
+return false;
+} else {
+if (a->data.emulator.hassecretuuid != b->data.emulator.hassecretuuid)
+return false;
+
+if (a->data.emulator.hassecretuuid == true &&
+memcmp(a->data.emulator.secretuuid,
+   b->data.emulator.secretuuid,
+   VIR_UUID_BUFLEN))
+return false;
+
+if (a->data.emulator.persistent_state !=
+b->data.emulator.persistent_state)
+return false;
+}
+
+if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+!virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
+return false;
+
+return true;
+}
+
+
+ssize_t
+virDomainTPMDefFind(const virDomainDef *def,
+const virDomainTPMDef *tpm)
+{
+size_t i;
+
+for (i = 0; i < def->ntpms; i++) {
+if (virDomainTPMDefEquals(tpm, def->tpms[i]))
+return i;
+}
+
+return -1;
+}
+
+
+virDomainTPMDef *
+virDomainTPMDefRemove(virDomainDef *def,
+  size_t idx)
+{
+virDomainTPMDef *ret = def->tpms[idx];
+
+VIR_DELETE_ELEMENT(def->tpms, idx, def->ntpms);
+
+return ret;
+}
+
+
 char *
 virDomainDefGetDefaultEmulator(virDomainDef *def,
virCaps *caps)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3e4701176d..b8a1e1d2d2 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3821,6 +3821,12 @@ bool virDomainVsockDefEquals(const virDomainVsockDef *a,
  const virDomainVsockDef *b)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
 
+ssize_t virDomainTPMDefFind(const virDomainDef *def,
+const virDomainTPMDef *tpm)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+virDomainTPMDef *virDomainTPMDefRemove(virDomainDef *def, size_t idx)
+ATTRIBUTE_NONNULL(1);
+
 VIR_ENUM_DECL(virDomainTaint);
 VIR_ENUM_DECL(virDomainTaintMessage);
 VIR_ENUM_DECL(virDomainVirt);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9cf12779bf..f7f3726443 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -661,7 +661,9 @@ virDomainTimerTrackTypeFromString;
 virDomainTimerTrackTypeToString;
 virDomainTPMBackendTypeFromString;
 virDomainTPMBackendTypeToString;
+virDomainTPMDefFind;
 virDomainTPMDefFree;
+virDomainTPMDefRemove;
 virDomainTPMModelTypeFromString;
 virDomainTPMModelTypeToString;
 virDomainUSBDeviceDefForeach;
-- 
2.33.0



[PATCH v2 05/12] test_driver: Implement virDomainDetachDevice

2021-08-20 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 6cabf78e7c..c6aead09c9 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9747,6 +9747,14 @@ testDomainDetachDeviceAlias(virDomainPtr dom,
NULL, alias, flags);
 }
 
+static int
+testDomainDetachDevice(virDomainPtr dom,
+   const char *xml)
+{
+return testDomainDetachDeviceFlags(dom, xml,
+   VIR_DOMAIN_AFFECT_LIVE);
+}
+
 /*
  * Test driver
  */
@@ -9838,6 +9846,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainFSFreeze = testDomainFSFreeze, /* 5.7.0 */
 .domainFSThaw = testDomainFSThaw, /* 5.7.0 */
 .domainFSTrim = testDomainFSTrim, /* 5.7.0 */
+.domainDetachDevice = testDomainDetachDevice, /* 7.7.0 */
 .domainDetachDeviceAlias = testDomainDetachDeviceAlias, /* 7.7.0 */
 .domainDetachDeviceFlags = testDomainDetachDeviceFlags, /* 7.7.0 */
 .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
-- 
2.33.0



[PATCH v2 02/12] domain_driver: extract DetachXXXDeviceConfig related functions and use them

2021-08-20 Thread Luke Yue
libxl / lxc / qemu drivers share some common codes in their
DomainDetachDeviceConfig functions, so extract them to domain_driver and
reuse them.

Signed-off-by: Luke Yue 
---
 src/hypervisor/domain_driver.c | 267 +
 src/hypervisor/domain_driver.h |  41 +
 src/libvirt_private.syms   |  14 ++
 src/libxl/libxl_driver.c   |  41 +
 src/lxc/lxc_driver.c   |  37 +
 src/qemu/qemu_driver.c | 123 +++
 6 files changed, 357 insertions(+), 166 deletions(-)

diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
index 2969d55173..04c12dff5b 100644
--- a/src/hypervisor/domain_driver.c
+++ b/src/hypervisor/domain_driver.c
@@ -512,3 +512,270 @@ virDomainDriverNodeDeviceDetachFlags(virNodeDevicePtr dev,
 
 return virHostdevPCINodeDeviceDetach(hostdevMgr, pci);
 }
+
+
+int
+virDomainDriverDetachDiskDeviceConfig(virDomainDef *vmdef,
+  virDomainDeviceDef *dev)
+{
+virDomainDiskDef *disk;
+virDomainDiskDef *det_disk;
+
+disk = dev->data.disk;
+if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
+virReportError(VIR_ERR_DEVICE_MISSING,
+   _("no target device %s"), disk->dst);
+return -1;
+}
+virDomainDiskDefFree(det_disk);
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachNetDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+virDomainNetDef *net;
+int idx;
+
+net = dev->data.net;
+if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
+return -1;
+
+/* this is guaranteed to succeed */
+virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachSoundDeviceConfig(virDomainDef *vmdef,
+   virDomainDeviceDef *dev)
+{
+virDomainSoundDef *sound;
+int idx;
+
+sound = dev->data.sound;
+if ((idx = virDomainSoundDefFind(vmdef, sound)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("device not present in domain configuration"));
+return -1;
+}
+virDomainSoundDefFree(virDomainSoundDefRemove(vmdef, idx));
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachHostdevDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+virDomainHostdevDef *hostdev;
+virDomainHostdevDef *det_hostdev;
+int idx;
+
+hostdev = dev->data.hostdev;
+if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("device not present in domain configuration"));
+return -1;
+}
+virDomainHostdevRemove(vmdef, idx);
+virDomainHostdevDefFree(det_hostdev);
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachLeaseDeviceConfig(virDomainDef *vmdef,
+   virDomainDeviceDef *dev)
+{
+virDomainLeaseDef *lease;
+virDomainLeaseDef *det_lease;
+
+lease = dev->data.lease;
+if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
+virReportError(VIR_ERR_DEVICE_MISSING,
+   _("Lease %s in lockspace %s does not exist"),
+   lease->key, NULLSTR(lease->lockspace));
+return -1;
+}
+virDomainLeaseDefFree(det_lease);
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachControllerDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+virDomainControllerDef *cont;
+virDomainControllerDef *det_cont;
+int idx;
+
+cont = dev->data.controller;
+if ((idx = virDomainControllerFind(vmdef, cont->type,
+   cont->idx)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("device not present in domain configuration"));
+return -1;
+}
+det_cont = virDomainControllerRemove(vmdef, idx);
+virDomainControllerDefFree(det_cont);
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachFSDeviceConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+virDomainFSDef *fs;
+int idx;
+
+fs = dev->data.fs;
+idx = virDomainFSIndexByName(vmdef, fs->dst);
+if (idx < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching filesystem device was found"));
+return -1;
+}
+
+fs = virDomainFSRemove(vmdef, idx);
+virDomainFSDefFree(fs);
+
+return 0;
+}
+
+
+int
+virDomainDriverDetachRNGDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev)
+{
+int idx;
+
+if ((idx = virDomainRNGFind(vmdef, dev->data.rng)) < 0) {
+   

[PATCH v2 1/3] test_driver: Implement virDomainGetBlkioParameters

2021-08-19 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 47 ++
 1 file changed, 47 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index b096d49ac6..23176000b6 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -3290,6 +3290,52 @@ static char *testDomainGetXMLDesc(virDomainPtr domain, 
unsigned int flags)
 return ret;
 }
 
+static int
+testDomainGetBlkioParameters(virDomainPtr dom,
+ virTypedParameterPtr params,
+ int *nparams,
+ unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def = NULL;
+int maxparams = 6;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG |
+  VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if ((*nparams) == 0) {
+*nparams = 6;
+return 0;
+} else if (*nparams < maxparams) {
+maxparams = *nparams;
+}
+
+*nparams = 0;
+
+if (!(vm = testDomObjFromDomain(dom)))
+return -1;
+
+if (!(def = virDomainObjGetOneDef(vm, flags)))
+goto cleanup;
+
+if (virTypedParameterAssign(&(params[(*nparams)++]),
+VIR_DOMAIN_BLKIO_WEIGHT,
+VIR_TYPED_PARAM_UINT,
+def->blkio.weight) < 0)
+goto cleanup;
+
+if (virDomainGetBlkioParametersAssignFromDef(def, params, nparams,
+ maxparams) < 0)
+goto cleanup;
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
 
 #define TEST_SET_PARAM(index, name, type, value) \
 if (index < *nparams && \
@@ -9522,6 +9568,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainGetInterfaceParameters = testDomainGetInterfaceParameters, /* 5.6.0 
*/
 .domainSetBlockIoTune = testDomainSetBlockIoTune, /* 5.7.0 */
 .domainGetBlockIoTune = testDomainGetBlockIoTune, /* 5.7.0 */
+.domainGetBlkioParameters = testDomainGetBlkioParameters, /* 7.7.0 */
 .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
 .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
 .domainCreate = testDomainCreate, /* 0.1.11 */
-- 
2.33.0



[PATCH v2 3/3] tests: Test BlkioParameters related functions for test driver

2021-08-19 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 examples/xml/test/testdomfv0.xml | 11 ++
 examples/xml/test/testnodeinline.xml | 11 ++
 tests/virshtest.c| 55 
 3 files changed, 77 insertions(+)

diff --git a/examples/xml/test/testdomfv0.xml b/examples/xml/test/testdomfv0.xml
index fc209cce29..e60b5d69b7 100644
--- a/examples/xml/test/testdomfv0.xml
+++ b/examples/xml/test/testdomfv0.xml
@@ -38,4 +38,15 @@
 
 
   
+  
+800
+
+  /dev/hda
+  700
+  700
+  700
+  700
+  700
+
+  
 
diff --git a/examples/xml/test/testnodeinline.xml 
b/examples/xml/test/testnodeinline.xml
index 60970145a0..9165d9302d 100644
--- a/examples/xml/test/testnodeinline.xml
+++ b/examples/xml/test/testnodeinline.xml
@@ -48,6 +48,17 @@
   
   
 
+
+  800
+  
+/dev/hda
+700
+700
+700
+700
+700
+  
+
   
   
 fc4
diff --git a/tests/virshtest.c b/tests/virshtest.c
index 751e8ffc49..87da1f5889 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -30,6 +30,8 @@ main(void)
 tainted: custom device tree blob used\n\
 tainted: use of deprecated configuration settings\n\
 deprecated configuration: CPU model Deprecated-Test"
+# define GET_BLKIO_PARAMETER "/dev/hda,700"
+# define SET_BLKIO_PARAMETER "/dev/hda,1000"
 
 static const char *dominfo_fc4 = "\
 Id: 2\n\
@@ -70,6 +72,25 @@ Security label: " SECURITY_LABEL "\n\
 Messages:   " FC5_MESSAGES "\n\
 \n";
 
+static const char *get_blkio_parameters = "\
+weight : 800\n\
+device_weight  : " GET_BLKIO_PARAMETER "\n\
+device_read_iops_sec: " GET_BLKIO_PARAMETER "\n\
+device_write_iops_sec: " GET_BLKIO_PARAMETER "\n\
+device_read_bytes_sec: " GET_BLKIO_PARAMETER "\n\
+device_write_bytes_sec: " GET_BLKIO_PARAMETER "\n\
+\n";
+
+static const char *set_blkio_parameters = "\
+\n\
+weight : 500\n\
+device_weight  : " SET_BLKIO_PARAMETER "\n\
+device_read_iops_sec: " SET_BLKIO_PARAMETER "\n\
+device_write_iops_sec: " SET_BLKIO_PARAMETER "\n\
+device_read_bytes_sec: " SET_BLKIO_PARAMETER "\n\
+device_write_bytes_sec: " SET_BLKIO_PARAMETER "\n\
+\n";
+
 static int testFilterLine(char *buffer,
   const char *toRemove)
 {
@@ -291,6 +312,32 @@ static int testCompareDomControlInfoByName(const void 
*data G_GNUC_UNUSED)
 return testCompareOutputLit(exp, NULL, argv);
 }
 
+static int testCompareGetBlkioParameters(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "blkiotune", "fv0", NULL };
+const char *exp = get_blkio_parameters;
+return testCompareOutputLit(exp, NULL, argv);
+}
+
+static int testCompareSetBlkioParameters(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "blkiotune fv0\
+ --weight 500\
+ --device-weights\
+ " SET_BLKIO_PARAMETER "\
+ --device-read-iops-sec\
+ " SET_BLKIO_PARAMETER "\
+ --device-write-iops-sec\
+ " SET_BLKIO_PARAMETER "\
+ --device-read-bytes-sec\
+ " SET_BLKIO_PARAMETER "\
+ --device-write-bytes-sec\
+ " SET_BLKIO_PARAMETER ";\
+ blkiotune fv0", NULL };
+const char *exp = set_blkio_parameters;
+return testCompareOutputLit(exp, NULL, argv);
+}
+
 struct testInfo {
 const char *const *argv;
 const char *result;
@@ -383,6 +430,14 @@ mymain(void)
testCompareDomControlInfoByName, NULL) != 0)
 ret = -1;
 
+if (virTestRun("virsh blkiotune (get parameters)",
+   testCompareGetBlkioParameters, NULL) != 0)
+ret = -1;
+
+if (virTestRun("virsh blkiotune (set parameters)",
+   testCompareSetBlkioParameters, NULL) != 0)
+ret = -1;
+
 /* It's a bit awkward listing result before argument, but that's a
  * limitation of C99 vararg macros.  */
 # define DO_TEST(i, result, ...) \
-- 
2.33.0



[PATCH v2 2/3] test_driver: Implement virDomainSetBlkioParameters

2021-08-19 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/meson.build   |  1 +
 src/test/test_driver.c | 49 ++
 2 files changed, 50 insertions(+)

diff --git a/src/test/meson.build b/src/test/meson.build
index f54585adfd..c0174ad856 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -17,6 +17,7 @@ if conf.has('WITH_TEST')
 ],
 include_directories: [
   conf_inc_dir,
+  hypervisor_inc_dir,
 ],
   )
 
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 23176000b6..3aab8377c5 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -40,6 +40,7 @@
 #include "interface_conf.h"
 #include "checkpoint_conf.h"
 #include "domain_conf.h"
+#include "domain_driver.h"
 #include "domain_event.h"
 #include "network_event.h"
 #include "snapshot_conf.h"
@@ -3290,6 +3291,53 @@ static char *testDomainGetXMLDesc(virDomainPtr domain, 
unsigned int flags)
 return ret;
 }
 
+static int
+testDomainSetBlkioParameters(virDomainPtr dom,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (virTypedParamsValidate(params, nparams,
+   VIR_DOMAIN_BLKIO_WEIGHT,
+   VIR_TYPED_PARAM_UINT,
+   VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
+   VIR_TYPED_PARAM_STRING,
+   VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS,
+   VIR_TYPED_PARAM_STRING,
+   VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS,
+   VIR_TYPED_PARAM_STRING,
+   VIR_DOMAIN_BLKIO_DEVICE_READ_BPS,
+   VIR_TYPED_PARAM_STRING,
+   VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS,
+   VIR_TYPED_PARAM_STRING,
+   NULL) < 0)
+return -1;
+
+if (!(vm = testDomObjFromDomain(dom)))
+return -1;
+
+if (!(def = virDomainObjGetOneDef(vm, flags)))
+goto cleanup;
+
+ret = 0;
+
+ret = virDomainDriverSetupPersistentDefBlkioParams(def,
+   params,
+   nparams);
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+
 static int
 testDomainGetBlkioParameters(virDomainPtr dom,
  virTypedParameterPtr params,
@@ -9568,6 +9616,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainGetInterfaceParameters = testDomainGetInterfaceParameters, /* 5.6.0 
*/
 .domainSetBlockIoTune = testDomainSetBlockIoTune, /* 5.7.0 */
 .domainGetBlockIoTune = testDomainGetBlockIoTune, /* 5.7.0 */
+.domainSetBlkioParameters = testDomainSetBlkioParameters, /* 7.7.0 */
 .domainGetBlkioParameters = testDomainGetBlkioParameters, /* 7.7.0 */
 .connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
 .connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
-- 
2.33.0



[PATCH v2 0/3] Implement some blkio related APIs for test driver

2021-08-19 Thread Luke Yue
v2:
- Rebase to current master branch
- Refine the tests

Luke Yue (3):
  test_driver: Implement virDomainGetBlkioParameters
  test_driver: Implement virDomainSetBlkioParameters
  tests: Test BlkioParameters related functions for test driver

 examples/xml/test/testdomfv0.xml | 11 
 examples/xml/test/testnodeinline.xml | 11 
 src/test/meson.build |  1 +
 src/test/test_driver.c   | 96 
 tests/virshtest.c| 55 
 5 files changed, 174 insertions(+)

-- 
2.33.0



Re: [PATCH 3/3] tests: Test BlkioParameters related functions for test driver

2021-08-18 Thread Luke Yue
On Wed, 2021-08-18 at 14:37 +0200, Martin Kletzander wrote:
> On Tue, Jul 13, 2021 at 01:42:14PM +0800, Luke Yue wrote:
> > Signed-off-by: Luke Yue 
> > ---
> > examples/xml/test/testdomfv0.xml | 11 +
> > examples/xml/test/testnodeinline.xml | 11 +
> > tests/virshtest.c    | 36
> > 
> > 3 files changed, 58 insertions(+)
> > 
> > diff --git a/examples/xml/test/testdomfv0.xml
> > b/examples/xml/test/testdomfv0.xml
> > index fc209cce29..e60b5d69b7 100644
> > --- a/examples/xml/test/testdomfv0.xml
> > +++ b/examples/xml/test/testdomfv0.xml
> > @@ -38,4 +38,15 @@
> >     
> >     
> >   
> > +  
> > +    800
> > +    
> > +  /dev/hda
> > +  700
> > +  700
> > +  700
> > +  700
> > +  700
> > +    
> > +  
> > 
> > diff --git a/examples/xml/test/testnodeinline.xml
> > b/examples/xml/test/testnodeinline.xml
> > index 0ec0f1ace6..78f3c6a671 100644
> > --- a/examples/xml/test/testnodeinline.xml
> > +++ b/examples/xml/test/testnodeinline.xml
> > @@ -48,6 +48,17 @@
> >   
> >   
> >     
> > +    
> > +  800
> > +  
> > +    /dev/hda
> > +    700
> > +    700
> > +    700
> > +    700
> > +    700
> > +  
> > +    
> >   
> >   
> >     fc4
> > diff --git a/tests/virshtest.c b/tests/virshtest.c
> > index c1974c46cb..43daf8b9c2 100644
> > --- a/tests/virshtest.c
> > +++ b/tests/virshtest.c
> > @@ -22,6 +22,7 @@ main(void)
> > 
> > # define DOM_UUID "ef861801-45b9-11cb-88e3-afbfe5370493"
> > # define SECURITY_LABEL "libvirt-test (enforcing)"
> > +# define BLKIO_PARAMETER "/dev/hda,700"
> > 
> > static const char *dominfo_fc4 = "\
> > Id: 2\n\
> > @@ -43,6 +44,14 @@ static const char *domuuid_fc4 = DOM_UUID
> > "\n\n";
> > static const char *domid_fc4 = "2\n\n";
> > static const char *domname_fc4 = "fc4\n\n";
> > static const char *domstate_fc4 = "running\n\n";
> > +static const char *blkioparameters = "\
> > +weight : 800\n\
> > +device_weight  : " BLKIO_PARAMETER "\n\
> > +device_read_iops_sec: " BLKIO_PARAMETER "\n\
> > +device_write_iops_sec: " BLKIO_PARAMETER "\n\
> > +device_read_bytes_sec: " BLKIO_PARAMETER "\n\
> > +device_write_bytes_sec: " BLKIO_PARAMETER "\n\
> > +\n";
> > 
> > static int testFilterLine(char *buffer,
> >   const char *toRemove)
> > @@ -250,6 +259,25 @@ static int testCompareDomstateByName(const
> > void *data G_GNUC_UNUSED)
> >     return testCompareOutputLit(exp, NULL, argv);
> > }
> > 
> > +static int testCompareGetBlkioParameters(const void *data
> > G_GNUC_UNUSED)
> > +{
> > +    const char *const argv[] = { VIRSH_CUSTOM, "blkiotune", "fv0",
> > NULL };
> > +    const char *exp = blkioparameters;
> > +    return testCompareOutputLit(exp, NULL, argv);
> > +}
> > +
> > +static int testCompareSetBlkioParameters(const void *data
> > G_GNUC_UNUSED)
> > +{
> > +    const char *const argv[] = { VIRSH_CUSTOM, "blkiotune", "fv0",
> > +    "--device-weights", "/dev/hda,500",
> > +    "--device-read-iops-sec", "/dev/hda,1000",
> > +    "--device-write-iops-sec", "/dev/hda,1000",
> > +    "--device-read-bytes-sec", "/dev/hda,26214400",
> > +    "--device-write-bytes-sec", "/dev/hda,26214400", NULL };
> > +    const char *exp = "\n";
> > +    return testCompareOutputLit(exp, NULL, argv);
> > +}
> > +
> > struct testInfo {
> >     const char *const *argv;
> >     const char *result;
> > @@ -334,6 +362,14 @@ mymain(void)
> >    testCompareDomstateByName, NULL) != 0)
> >     ret = -1;
> > 
> > +    if (virTestRun("virsh blkiotune (get parameters)",
> > +   testCompareGetBlkioParameters, NULL) != 0)
> > +    ret = -1;
> > +
> > +    if (virTestRun("virsh blkiotune (set parameters)",
> > +   testCompareSetBlkioParameters, NULL) != 0)
> > +    ret = -1;
> > +
> 
> Patches are fine, but please rebase them.  I would also appreciate
> testing setting some different value and then checking it was set.
> 

Thanks for the review! I will send v2 soon with improvements in tests.

> >     /* It's a bit awkward listing result before argument, but
> > that's a
> >  * limitation of C99 vararg macros.  */
> > # define DO_TEST(i, result, ...) \
> > -- 
> > 2.32.0
> > 




[PATCH v3 3/5] test_driver: Implement virDomainAbortJob

2021-08-18 Thread Luke Yue
As we are using jobState to store dummy job type, so just change it to
VIR_DOMAIN_JOB_CANCELLED when try to abort a job.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 9899976966..35350edda9 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -2889,6 +2889,34 @@ testDomainGetJobStats(virDomainPtr domain,
 return ret;
 }
 
+static int
+testDomainAbortJob(virDomainPtr dom)
+{
+virDomainObj *vm;
+int ret = -1;
+testDomainObjPrivate *priv;
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainObjCheckActive(vm) < 0)
+goto cleanup;
+
+priv = vm->privateData;
+
+if (priv->jobState == VIR_DOMAIN_JOB_NONE) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("no job is active on the domain"));
+} else {
+priv->jobState = VIR_DOMAIN_JOB_CANCELLED;
+ret = 0;
+}
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 static int
 testDomainGetLaunchSecurityInfo(virDomainPtr domain G_GNUC_UNUSED,
 virTypedParameterPtr *params G_GNUC_UNUSED,
@@ -9792,6 +9820,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainSetLifecycleAction = testDomainSetLifecycleAction, /* 5.7.0 */
 .domainGetJobInfo = testDomainGetJobInfo, /* 7.7.0 */
 .domainGetJobStats = testDomainGetJobStats, /* 7.7.0 */
+.domainAbortJob = testDomainAbortJob, /* 7.7.0 */
 
 .domainSnapshotNum = testDomainSnapshotNum, /* 1.1.4 */
 .domainSnapshotListNames = testDomainSnapshotListNames, /* 1.1.4 */
-- 
2.32.0



[PATCH v3 0/5] Implement some job related APIs for test driver

2021-08-18 Thread Luke Yue
v3:
- Fix virDomainGetJobStats when use completed flags
- Introduce testDomainSetDummyData
- Add and refine some tests

Luke Yue (5):
  test_driver: Implement virDomainGetJobInfo
  test_driver: Implement virDomainGetJobStats
  test_driver: Implement virDomainAbortJob
  test_driver: Introduce testDomainSetDummyData
  virshtest: add test for domjobinfo and domjobabort

 src/test/test_driver.c | 274 +
 tests/virshtest.c  |  89 +
 2 files changed, 363 insertions(+)

-- 
2.32.0



[PATCH v3 2/5] test_driver: Implement virDomainGetJobStats

2021-08-18 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 135 +++--
 1 file changed, 131 insertions(+), 4 deletions(-)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index ae6422c955..9899976966 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -384,6 +384,8 @@ struct _testDomainObjPrivate {
 /* used by Job Info APIs */
 unsigned int jobState;
 unsigned int jobOperation;
+bool hasCompletedJob;
+unsigned int jobCompleted;
 };
 
 
@@ -402,6 +404,8 @@ testDomainObjPrivateAlloc(void *opaque)
 
 priv->jobState = VIR_DOMAIN_JOB_NONE;
 priv->jobOperation = VIR_DOMAIN_JOB_OPERATION_UNKNOWN;
+priv->hasCompletedJob = true;
+priv->jobCompleted = VIR_DOMAIN_JOB_OPERATION_START;
 
 return priv;
 }
@@ -2683,15 +2687,24 @@ testDomainGetOSType(virDomainPtr dom G_GNUC_UNUSED)
 
 static int
 testDomainGetJobInfoImpl(virDomainObj *dom,
- virDomainJobInfoPtr info)
+ virDomainJobInfoPtr info,
+ bool completed)
 {
 testDomainObjPrivate *priv = dom->privateData;
 
 memset(info, 0, sizeof(*info));
 
-info->type = priv->jobState;
+if (completed) {
+if (priv->hasCompletedJob) {
+info->type = VIR_DOMAIN_JOB_COMPLETED;
+} else {
+info->type = VIR_DOMAIN_JOB_NONE;
+}
+} else {
+info->type = priv->jobState;
+}
 
-switch (priv->jobState) {
+switch (info->type) {
 case VIR_DOMAIN_JOB_NONE:
 break;
 
@@ -2755,13 +2768,126 @@ testDomainGetJobInfo(virDomainPtr dom,
 if (virDomainObjCheckActive(vm) < 0)
 goto cleanup;
 
-ret = testDomainGetJobInfoImpl(vm, info);
+ret = testDomainGetJobInfoImpl(vm, info, false);
 
  cleanup:
 virDomainObjEndAPI(&vm);
 return ret;
 }
 
+static int
+testDomainJobInfoToParams(testDomainObjPrivate *priv,
+  virDomainJobInfoPtr info,
+  int *type,
+  bool completed,
+  virTypedParameterPtr *params,
+  int *nparams)
+{
+virTypedParameterPtr par = NULL;
+int maxpar = 0;
+int npar = 0;
+unsigned int operation = VIR_DOMAIN_JOB_OPERATION_UNKNOWN;
+
+if (completed) {
+operation = priv->jobCompleted;
+} else {
+operation = priv->jobOperation;
+}
+
+if (virTypedParamsAddInt(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_OPERATION,
+ operation) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_DATA_TOTAL,
+info->dataTotal) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_DATA_PROCESSED,
+info->dataProcessed) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_DATA_REMAINING,
+info->dataRemaining) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_TIME_ELAPSED,
+info->timeElapsed) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_TIME_REMAINING,
+info->timeRemaining) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_MEMORY_TOTAL,
+info->memTotal) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_MEMORY_PROCESSED,
+info->memProcessed) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_MEMORY_REMAINING,
+info->memRemaining) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_DISK_TOTAL,
+info->fileTotal) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_DISK_PROCESSED,
+info->fileProcessed) < 0 ||
+virTypedParamsAddULLong(&par, &npar, &maxpar,
+VIR_DOMAIN_JOB_DISK_REMAINING,
+info->fileRemaining) < 0)
+goto error;
+
+*type = info->type;
+*params = par;
+*nparams = npar;
+return 0;
+
+ error:
+virTypedParamsFree(par, npar);
+return -1;
+}
+
+static 

[PATCH v3 5/5] virshtest: add test for domjobinfo and domjobabort

2021-08-18 Thread Luke Yue
In testCompareDomJobInfoByName, we should get different jobinfo for fc4
and fc5, as we set different jobinfo value for fc5 in
testDomainSetDummyData. And when use "--completed --keep-completed"
flags, the completed job info should be preserved, with only
"--completed" flag, the completed job info should be deleted, so should
get none next time.

In testCompareDomJobAbortByName, domjobabort should set type to
cancelled and preserve the operation.

Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 89 +++
 1 file changed, 89 insertions(+)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index 751e8ffc49..4e2efcb69a 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -291,6 +291,87 @@ static int testCompareDomControlInfoByName(const void 
*data G_GNUC_UNUSED)
 return testCompareOutputLit(exp, NULL, argv);
 }
 
+static int testCompareDomJobInfoByName(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "domjobinfo fc4;\
+ domjobinfo fc5;\
+ domjobinfo fc5 --completed --keep-completed;\
+ domjobinfo fc5 --completed;\
+ domjobinfo fc5 --completed", NULL };
+const char *exp = "\
+Job type: None\n\
+\n\
+Job type: Bounded \n\
+Operation:Backup  \n\
+Time elapsed: 4000 ms\n\
+Time remaining:   6000 ms\n\
+Data processed:   10.000 KiB\n\
+Data remaining:   20.000 KiB\n\
+Data total:   30.000 KiB\n\
+Memory processed: 1.000 MiB\n\
+Memory remaining: 2.000 MiB\n\
+Memory total: 3.000 MiB\n\
+File processed:   512.000 KiB\n\
+File remaining:   1.500 MiB\n\
+File total:   2.000 MiB\n\
+\n\
+Job type: Completed   \n\
+Operation:Start   \n\
+Time elapsed: 1ms\n\
+Data processed:   30.000 KiB\n\
+Data remaining:   0.000 B\n\
+Data total:   30.000 KiB\n\
+Memory processed: 3.000 MiB\n\
+Memory remaining: 0.000 B\n\
+Memory total: 3.000 MiB\n\
+File processed:   2.000 MiB\n\
+File remaining:   0.000 B\n\
+File total:   2.000 MiB\n\
+\n\
+Job type: Completed   \n\
+Operation:Start   \n\
+Time elapsed: 1ms\n\
+Data processed:   30.000 KiB\n\
+Data remaining:   0.000 B\n\
+Data total:   30.000 KiB\n\
+Memory processed: 3.000 MiB\n\
+Memory remaining: 0.000 B\n\
+Memory total: 3.000 MiB\n\
+File processed:   2.000 MiB\n\
+File remaining:   0.000 B\n\
+File total:   2.000 MiB\n\
+\n\
+Job type: None\n\
+\n";
+return testCompareOutputLit(exp, NULL, argv);
+}
+
+static int testCompareDomJobAbortByName(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "domjobinfo fc5;\
+ domjobabort fc5; domjobinfo fc5", NULL };
+const char *exp = "\
+Job type: Bounded \n\
+Operation:Backup  \n\
+Time elapsed: 4000 ms\n\
+Time remaining:   6000 ms\n\
+Data processed:   10.000 KiB\n\
+Data remaining:   20.000 KiB\n\
+Data total:   30.000 KiB\n\
+Memory processed: 1.000 MiB\n\
+Memory remaining: 2.000 MiB\n\
+Memory total: 3.000 MiB\n\
+File processed:   512.000 KiB\n\
+File remaining:   1.500 MiB\n\
+File total:   2.000 MiB\n\
+\n\
+\n\
+Job type: Cancelled   \n\
+Operation:Backup  \n\
+\n";
+return testCompareOutputLit(exp, NULL, argv);
+}
+
 struct testInfo {
 const char *const *argv;
 const char *result;
@@ -383,6 +464,14 @@ mymain(void)
testCompareDomControlInfoByName, NULL) != 0)
 ret = -1;
 
+if (virTestRun("virsh domjobinfo (by name)",
+   testCompareDomJobInfoByName, NULL) != 0)
+ret = -1;
+
+if (virTestRun("virsh domjobabort (by name)",
+   testCompareDomJobAbortByName, NULL) != 0)
+ret = -1;
+
 /* It's a bit awkward listing result before argument, but that's a
  * limitation of C99 vararg macros.  */
 # define DO_TEST(i, result, ...) \
-- 
2.32.0



[PATCH v3 4/5] test_driver: Introduce testDomainSetDummyData

2021-08-18 Thread Luke Yue
We can't adjust all info of a domain in XML and it's hard to adjust some
with current API coverage, so use this function to set some dummy data
to specific domains, thus we can get different results in virsh tests.

Currently, only domain fc5's priv->jobState and priv->jobOperation are
being changed, in order to test virDomainGetJobInfo and
virDomainGetJobStats (domjobinfo in virsh).

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 35350edda9..372de8ba53 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -663,6 +663,32 @@ testDomObjFromDomain(virDomainPtr domain)
 return vm;
 }
 
+/**
+ * We can't adjust all info of a domain in XML and it's hard to
+ * adjust some with current API coverage, so use this function to
+ * set some dummy data to specific domains, thus we can get different
+ * results in virshtest.
+ */
+static int
+testDomainSetDummyData(virDomainObj *obj)
+{
+virDomainDef *def;
+testDomainObjPrivate *priv;
+
+priv = obj->privateData;
+
+if (!(def = virDomainObjGetOneDef(obj, VIR_DOMAIN_AFFECT_LIVE)))
+return -1;
+
+if (STREQ(def->name, "fc5")) {
+/* For testing domjobinfo */
+priv->jobState = VIR_DOMAIN_JOB_BOUNDED;
+priv->jobOperation = VIR_DOMAIN_JOB_OPERATION_BACKUP;
+}
+
+return 0;
+}
+
 static char *
 testDomainGenerateIfname(virDomainDef *domdef)
 {
@@ -1055,6 +1081,9 @@ testParseDomains(testDriver *privconn,
 
 testDomainObjCheckTaint(obj);
 
+if (testDomainSetDummyData(obj) < 0)
+VIR_DEBUG("Failed to set dummy data");
+
 virDomainObjEndAPI(&obj);
 }
 
-- 
2.32.0



[PATCH v3 1/5] test_driver: Implement virDomainGetJobInfo

2021-08-18 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 89 ++
 1 file changed, 89 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index b096d49ac6..ae6422c955 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -380,6 +380,10 @@ struct _testDomainObjPrivate {
 /* used by get/set time APIs */
 long long seconds;
 unsigned int nseconds;
+
+/* used by Job Info APIs */
+unsigned int jobState;
+unsigned int jobOperation;
 };
 
 
@@ -396,6 +400,9 @@ testDomainObjPrivateAlloc(void *opaque)
 priv->seconds = 627319920;
 priv->nseconds = 0;
 
+priv->jobState = VIR_DOMAIN_JOB_NONE;
+priv->jobOperation = VIR_DOMAIN_JOB_OPERATION_UNKNOWN;
+
 return priv;
 }
 
@@ -2674,6 +2681,87 @@ testDomainGetOSType(virDomainPtr dom G_GNUC_UNUSED)
 return ret;
 }
 
+static int
+testDomainGetJobInfoImpl(virDomainObj *dom,
+ virDomainJobInfoPtr info)
+{
+testDomainObjPrivate *priv = dom->privateData;
+
+memset(info, 0, sizeof(*info));
+
+info->type = priv->jobState;
+
+switch (priv->jobState) {
+case VIR_DOMAIN_JOB_NONE:
+break;
+
+case VIR_DOMAIN_JOB_BOUNDED:
+info->dataTotal = 30 * 1024;
+info->dataProcessed = 10 * 1024;
+info->dataRemaining = 20 * 1024;
+info->timeRemaining = 6000;
+info->timeElapsed = 4000;
+info->memTotal = 3 * 1024 * 1024;
+info->memProcessed = 1024 * 1024;
+info->memRemaining = 2 * 1024 * 1024;
+info->fileTotal = 2 * 1024 * 1024;
+info->fileProcessed = 1024 * 1024 / 2;
+info->fileRemaining = 3 * 1024 * 1024 / 2;
+break;
+
+case VIR_DOMAIN_JOB_UNBOUNDED:
+info->dataTotal = 30 * 1024;
+info->dataProcessed = 10 * 1024;
+info->dataRemaining = 20 * 1024;
+info->timeElapsed = 4000;
+info->memTotal = 3 * 1024 * 1024;
+info->memProcessed = 1024 * 1024;
+info->memRemaining = 2 * 1024 * 1024;
+info->fileTotal = 2 * 1024 * 1024;
+info->fileProcessed = 1024 * 1024 / 2;
+info->fileRemaining = 3 * 1024 * 1024 / 2;
+break;
+
+case VIR_DOMAIN_JOB_COMPLETED:
+info->timeElapsed = 1;
+info->dataTotal = 30 * 1024;
+info->dataProcessed = 30 * 1024;
+info->memTotal = 3 * 1024 * 1024;
+info->memProcessed = 3 * 1024 * 1024;
+info->fileTotal = 2 * 1024 * 1024;
+info->fileProcessed = 2 * 1024 * 1024;
+break;
+
+case VIR_DOMAIN_JOB_FAILED:
+break;
+
+case VIR_DOMAIN_JOB_CANCELLED:
+break;
+}
+
+return 0;
+}
+
+static int
+testDomainGetJobInfo(virDomainPtr dom,
+ virDomainJobInfoPtr info)
+{
+virDomainObj *vm;
+int ret = -1;
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainObjCheckActive(vm) < 0)
+goto cleanup;
+
+ret = testDomainGetJobInfoImpl(vm, info);
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 
 static int
 testDomainGetLaunchSecurityInfo(virDomainPtr domain G_GNUC_UNUSED,
@@ -9576,6 +9664,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainMemoryPeek = testDomainMemoryPeek, /* 5.4.0 */
 .domainGetBlockInfo = testDomainGetBlockInfo, /* 5.7.0 */
 .domainSetLifecycleAction = testDomainSetLifecycleAction, /* 5.7.0 */
+.domainGetJobInfo = testDomainGetJobInfo, /* 7.7.0 */
 
 .domainSnapshotNum = testDomainSnapshotNum, /* 1.1.4 */
 .domainSnapshotListNames = testDomainSnapshotListNames, /* 1.1.4 */
-- 
2.32.0



Re: [PATCH 5/5] tests: Test detach-device and detach-device-alias for test driver

2021-08-17 Thread Luke Yue
On Tue, 2021-08-17 at 14:22 +0200, Martin Kletzander wrote:
> On Mon, Aug 16, 2021 at 07:19:49PM +0800, Luke Yue wrote:
> > Signed-off-by: Luke Yue 
> > ---
> > tests/virshtest.c | 24 
> > 1 file changed, 24 insertions(+)
> > 
> > diff --git a/tests/virshtest.c b/tests/virshtest.c
> > index 53db2aa19a..273596d636 100644
> > --- a/tests/virshtest.c
> > +++ b/tests/virshtest.c
> > @@ -291,6 +291,22 @@ static int
> > testCompareDomControlInfoByName(const void *data G_GNUC_UNUSED)
> >     return testCompareOutputLit(exp, NULL, argv);
> > }
> > 
> > +static int testCompareDetachDevice(const void *data G_GNUC_UNUSED)
> > +{
> > +    const char *const argv[] = { VIRSH_CUSTOM, "detach-device",
> > "fc5",
> > +
> > "../examples/xml/test/testdevif.xml", NULL };
> > +    const char *exp = "Device detached successfully\n\n";
> > +    return testCompareOutputLit(exp, NULL, argv);
> > +}
> > +
> > +static int testCompareDetachDeviceAlias(const void *data
> > G_GNUC_UNUSED)
> > +{
> > +    const char *const argv[] = { VIRSH_CUSTOM, "detach-device-
> > alias", "fc5",
> > + "ua-testCD", NULL };
> > +    const char *exp = "Device detach request sent
> > successfully\n\n";
> > +    return testCompareOutputLit(exp, NULL, argv);
> > +}
> > +
> 
> Not many XMLs from the previous patch are used here.  There could
> also
> be some negative tests (failing on a device that does not exist for
> example).
> 
> But if you de-duplicate the code then you can also go the other route
> and test the generic functions without running 'virsh -c test:///...'
> for every piece of functionality.
> 

No problem, will reimplement and and more tests in v2.

> > struct testInfo {
> >     const char *const *argv;
> >     const char *result;
> > @@ -383,6 +399,14 @@ mymain(void)
> >    testCompareDomControlInfoByName, NULL) != 0)
> >     ret = -1;
> > 
> > +    if (virTestRun("virsh detach-device",
> > +   testCompareDetachDevice, NULL) != 0)
> > +    ret = -1;
> > +
> > +    if (virTestRun("virsh detach-device-alias",
> > +   testCompareDetachDeviceAlias, NULL) != 0)
> > +    ret = -1;
> > +
> >     /* It's a bit awkward listing result before argument, but
> > that's a
> >  * limitation of C99 vararg macros.  */
> > # define DO_TEST(i, result, ...) \
> > -- 
> > 2.32.0
> > 




Re: [PATCH 4/5] examples: xml: test: add xml for testing devices related APIs

2021-08-17 Thread Luke Yue
On Tue, 2021-08-17 at 14:18 +0200, Martin Kletzander wrote:
> On Mon, Aug 16, 2021 at 07:19:48PM +0800, Luke Yue wrote:
> > Signed-off-by: Luke Yue 
> > ---
> > examples/xml/test/testdevcontroller.xml |  1 +
> > examples/xml/test/testdevdiskcdrom.xml  |  5 +++
> > examples/xml/test/testdevfs.xml |  6 
> > examples/xml/test/testdevhostdev.xml    |  5 +++
> > examples/xml/test/testdevif.xml |  6 
> 
> This one and ...
> 
> > examples/xml/test/testdevinput.xml  |  1 +
> > examples/xml/test/testdevlease.xml  |  5 +++
> > examples/xml/test/testdevmem.xml    |  6 
> > examples/xml/test/testdevnetif.xml  |  6 
> 
> ... this one only differ in MAC addresses, but the names suggest
> something else.  Since this commit does not use them anywhere it is
> difficult to see if they are both useful or not.
> 
> Consider adding these in a commit where they are being used.

Sorry for that, one of them is for attach APIs, and was added by
accident, will delete it in v2.




Re: [PATCH 1/5] test_driver: Implement virDomainDetachDeviceFlags

2021-08-17 Thread Luke Yue
On Tue, 2021-08-17 at 14:13 +0200, Martin Kletzander wrote:
> On Mon, Aug 16, 2021 at 07:19:45PM +0800, Luke Yue wrote:
> > Introduce testDomainChgDevice for further development (just like
> > what we
> > did for IOThread). And introduce
> > testDomainDetachDeviceLiveAndConfig for
> > detaching devices.
> > 
> > Signed-off-by: Luke Yue 
> > ---
> > src/test/test_driver.c | 270
> > +
> > 1 file changed, 270 insertions(+)
> > 
> > diff --git a/src/test/test_driver.c b/src/test/test_driver.c
> > index 00cc13511a..2ebdbaa604 100644
> > --- a/src/test/test_driver.c
> > +++ b/src/test/test_driver.c
> > @@ -9452,6 +9452,275 @@ testDomainGetMessages(virDomainPtr dom,
> >     return rv;
> > }
> > 
> > +static int
> > +testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
> > +    virDomainDeviceDef *dev)
> > +{
> > +    virDomainDiskDef *disk;
> > +    virDomainDiskDef *det_disk;
> > +    virDomainNetDef *net;
> > +    virDomainSoundDef *sound;
> > +    virDomainHostdevDef *hostdev;
> > +    virDomainHostdevDef *det_hostdev;
> > +    virDomainLeaseDef *lease;
> > +    virDomainLeaseDef *det_lease;
> > +    virDomainControllerDef *cont;
> > +    virDomainControllerDef *det_cont;
> > +    virDomainFSDef *fs;
> > +    virDomainMemoryDef *mem;
> > +    int idx;
> > +
> > +    switch (dev->type) {
> > +    case VIR_DOMAIN_DEVICE_DISK:
> > +    disk = dev->data.disk;
> > +    if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk-
> > >dst))) {
> > +    virReportError(VIR_ERR_DEVICE_MISSING,
> > +   _("no target device %s"), disk->dst);
> > +    return -1;
> > +    }
> > +    virDomainDiskDefFree(det_disk);
> > +    break;
> > +
> > +    case VIR_DOMAIN_DEVICE_NET:
> > +    net = dev->data.net;
> > +    if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
> > +    return -1;
> > +
> > +    /* this is guaranteed to succeed */
> > +    virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
> > +    break;
> > +
> > +    case VIR_DOMAIN_DEVICE_SOUND:
> > +    sound = dev->data.sound;
> > +    if ((idx = virDomainSoundDefFind(vmdef, sound)) < 0) {
> > +    virReportError(VIR_ERR_DEVICE_MISSING, "%s",
> > +   _("device not present in domain
> > configuration"));
> > +    return -1;
> > +    }
> > +    virDomainSoundDefFree(virDomainSoundDefRemove(vmdef,
> > idx));
> > +    break;
> > +
> > +    case VIR_DOMAIN_DEVICE_HOSTDEV: {
> > +    hostdev = dev->data.hostdev;
> > +    if ((idx = virDomainHostdevFind(vmdef, hostdev,
> > &det_hostdev)) < 0) {
> > +    virReportError(VIR_ERR_DEVICE_MISSING, "%s",
> > +   _("device not present in domain
> > configuration"));
> > +    return -1;
> > +    }
> > +    virDomainHostdevRemove(vmdef, idx);
> > +    virDomainHostdevDefFree(det_hostdev);
> > +    break;
> > +    }
> > +
> > +    case VIR_DOMAIN_DEVICE_LEASE:
> > +    lease = dev->data.lease;
> > +    if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
> > +    virReportError(VIR_ERR_DEVICE_MISSING,
> > +   _("Lease %s in lockspace %s does not
> > exist"),
> > +   lease->key, NULLSTR(lease->lockspace));
> > +    return -1;
> > +    }
> > +    virDomainLeaseDefFree(det_lease);
> > +    break;
> > +
> > +    case VIR_DOMAIN_DEVICE_CONTROLLER:
> > +    cont = dev->data.controller;
> > +    if ((idx = virDomainControllerFind(vmdef, cont->type,
> > +   cont->idx)) < 0) {
> > +    virReportError(VIR_ERR_DEVICE_MISSING, "%s",
> > +   _("device not present in domain
> > configuration"));
> > +    return -1;
> > +    }
> > +    det_cont = virDomainControllerRemove(vmdef, idx);
> > +    virDomainControllerDefFree(det_cont);
> > +
> > +    break;
> > +
> > +    case VIR_DOMAIN_DEVICE_FS:
> > +    fs = dev->data.fs;
> > +    idx = virDomainFSIndexByName(vmdef

Re: [PATCH v2 4/4] virshtest: add test for domjobinfo

2021-08-17 Thread Luke Yue
On Tue, 2021-08-17 at 13:52 +0200, Martin Kletzander wrote:
> On Mon, Aug 16, 2021 at 07:13:37PM +0800, Luke Yue wrote:
> > Signed-off-by: Luke Yue 
> > ---
> > tests/virshtest.c | 11 +++
> > 1 file changed, 11 insertions(+)
> > 
> > diff --git a/tests/virshtest.c b/tests/virshtest.c
> > index 53db2aa19a..0c46496c74 100644
> > --- a/tests/virshtest.c
> > +++ b/tests/virshtest.c
> > @@ -291,6 +291,13 @@ static int
> > testCompareDomControlInfoByName(const void *data G_GNUC_UNUSED)
> >     return testCompareOutputLit(exp, NULL, argv);
> > }
> > 
> > +static int testCompareDomJobInfoByName(const void *data
> > G_GNUC_UNUSED)
> > +{
> > +    const char *const argv[] = { VIRSH_CUSTOM, "domjobinfo",
> > "fc4", NULL };
> 
> You should be able to do something like:
> 
>    argv[] = { VIRSH_CUSTOM, "domjobinfo fc4; domjobabort fc4;
> domjobinfo fc4", NULL };
> 
> to test the behaviour of aborting and similarly for --completed and
> --keep-completed.
> 

Thanks for telling me that! I was wondering how I can keep the state of
the domain in virshtest, just like using interactive shell, and this
answered my question. Will do these in v3 and other unmerged patches'
tests can be improved with this, too. Thanks! 

> Maybe you can also pick one VM name that gets initialised with a
> dummy
> job.  You can base it on a name or uuid or some other random data for
> now.
> 
> > +    const char *exp = "Job type: None    \n\n";
> > +    return testCompareOutputLit(exp, NULL, argv);
> > +}
> > +
> > struct testInfo {
> >     const char *const *argv;
> >     const char *result;
> > @@ -383,6 +390,10 @@ mymain(void)
> >    testCompareDomControlInfoByName, NULL) != 0)
> >     ret = -1;
> > 
> > +    if (virTestRun("virsh domjobinfo (by name)",
> > +   testCompareDomJobInfoByName, NULL) != 0)
> > +    ret = -1;
> > +
> >     /* It's a bit awkward listing result before argument, but
> > that's a
> >  * limitation of C99 vararg macros.  */
> > # define DO_TEST(i, result, ...) \
> > -- 
> > 2.32.0
> > 




Re: [PATCH v2 2/4] test_driver: Implement virDomainGetJobStats

2021-08-17 Thread Luke Yue
On Tue, 2021-08-17 at 13:48 +0200, Martin Kletzander wrote:
> On Mon, Aug 16, 2021 at 07:13:35PM +0800, Luke Yue wrote:
> > Signed-off-by: Luke Yue 
> > ---
> > src/test/test_driver.c | 105
> > +
> > 1 file changed, 105 insertions(+)
> > 
> > diff --git a/src/test/test_driver.c b/src/test/test_driver.c
> > index 9306f0e104..93aeec7105 100644
> > --- a/src/test/test_driver.c
> > +++ b/src/test/test_driver.c
> > @@ -2769,6 +2769,110 @@ testDomainGetJobInfo(virDomainPtr dom,
> >     return ret;
> > }
> > 
> > +static int
> > +testDomainJobInfoToParams(testDomainObjPrivate *priv,
> > +  virDomainJobInfoPtr info,
> > +  int *type,
> > +  virTypedParameterPtr *params,
> > +  int *nparams)
> > +{
> > +    virTypedParameterPtr par = NULL;
> > +    int maxpar = 0;
> > +    int npar = 0;
> > +
> > +    if (virTypedParamsAddInt(&par, &npar, &maxpar,
> > + VIR_DOMAIN_JOB_OPERATION,
> > + priv->jobOperation) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_DATA_TOTAL,
> > +    info->dataTotal) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_DATA_PROCESSED,
> > +    info->dataProcessed) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_DATA_REMAINING,
> > +    info->dataRemaining) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_TIME_ELAPSED,
> > +    info->timeElapsed) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_TIME_REMAINING,
> > +    info->timeRemaining) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_MEMORY_TOTAL,
> > +    info->memTotal) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_MEMORY_PROCESSED,
> > +    info->memProcessed) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_MEMORY_REMAINING,
> > +    info->memRemaining) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_DISK_TOTAL,
> > +    info->fileTotal) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_DISK_PROCESSED,
> > +    info->fileProcessed) < 0 ||
> > +    virTypedParamsAddULLong(&par, &npar, &maxpar,
> > +    VIR_DOMAIN_JOB_DISK_REMAINING,
> > +    info->fileRemaining) < 0)
> > +    goto error;
> > +
> > +    *type = info->type;
> > +    *params = par;
> > +    *nparams = npar;
> > +    return 0;
> > +
> > + error:
> > +    virTypedParamsFree(par, npar);
> > +    return -1;
> > +}
> > +
> > +static int
> > +testDomainGetJobStats(virDomainPtr domain,
> > +  int *type,
> > +  virTypedParameterPtr *params,
> > +  int *nparams,
> > +  unsigned int flags)
> > +{
> > +    virDomainJobInfo jobInfo;
> > +    virDomainObj *dom;
> > +    testDomainObjPrivate *priv;
> > +    bool completed = !!(flags & VIR_DOMAIN_JOB_STATS_COMPLETED);
> 
> Unnecessary cast, just:
> 
> bool completed = flags & VIR_DOMAIN_JOB_STATS_COMPLETED;
> 
> would be fine.
> 
> > +    int ret = -1;
> > +
> > +    virCheckFlags(VIR_DOMAIN_JOB_STATS_COMPLETED |
> > +  VIR_DOMAIN_JOB_STATS_KEEP_COMPLETED, -1);
> > +
> > +    if (!(dom = testDomObjFromDomain(domain)))
> > +    return -1;

[PATCH 5/5] tests: Test detach-device and detach-device-alias for test driver

2021-08-16 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index 53db2aa19a..273596d636 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -291,6 +291,22 @@ static int testCompareDomControlInfoByName(const void 
*data G_GNUC_UNUSED)
 return testCompareOutputLit(exp, NULL, argv);
 }
 
+static int testCompareDetachDevice(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "detach-device", "fc5",
+ "../examples/xml/test/testdevif.xml", NULL };
+const char *exp = "Device detached successfully\n\n";
+return testCompareOutputLit(exp, NULL, argv);
+}
+
+static int testCompareDetachDeviceAlias(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "detach-device-alias", "fc5",
+ "ua-testCD", NULL };
+const char *exp = "Device detach request sent successfully\n\n";
+return testCompareOutputLit(exp, NULL, argv);
+}
+
 struct testInfo {
 const char *const *argv;
 const char *result;
@@ -383,6 +399,14 @@ mymain(void)
testCompareDomControlInfoByName, NULL) != 0)
 ret = -1;
 
+if (virTestRun("virsh detach-device",
+   testCompareDetachDevice, NULL) != 0)
+ret = -1;
+
+if (virTestRun("virsh detach-device-alias",
+   testCompareDetachDeviceAlias, NULL) != 0)
+ret = -1;
+
 /* It's a bit awkward listing result before argument, but that's a
  * limitation of C99 vararg macros.  */
 # define DO_TEST(i, result, ...) \
-- 
2.32.0



[PATCH 4/5] examples: xml: test: add xml for testing devices related APIs

2021-08-16 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 examples/xml/test/testdevcontroller.xml |  1 +
 examples/xml/test/testdevdiskcdrom.xml  |  5 +++
 examples/xml/test/testdevfs.xml |  6 
 examples/xml/test/testdevhostdev.xml|  5 +++
 examples/xml/test/testdevif.xml |  6 
 examples/xml/test/testdevinput.xml  |  1 +
 examples/xml/test/testdevlease.xml  |  5 +++
 examples/xml/test/testdevmem.xml|  6 
 examples/xml/test/testdevnetif.xml  |  6 
 examples/xml/test/testdevrng.xml|  4 +++
 examples/xml/test/testdevshmem.xml  |  4 +++
 examples/xml/test/testdevsound.xml  |  3 ++
 examples/xml/test/testdevvsock.xml  |  3 ++
 examples/xml/test/testdevwatchdog.xml   |  1 +
 examples/xml/test/testdomfc5.xml| 46 +
 examples/xml/test/testnodeinline.xml| 46 +
 16 files changed, 148 insertions(+)
 create mode 100644 examples/xml/test/testdevcontroller.xml
 create mode 100644 examples/xml/test/testdevdiskcdrom.xml
 create mode 100644 examples/xml/test/testdevfs.xml
 create mode 100644 examples/xml/test/testdevhostdev.xml
 create mode 100644 examples/xml/test/testdevif.xml
 create mode 100644 examples/xml/test/testdevinput.xml
 create mode 100644 examples/xml/test/testdevlease.xml
 create mode 100644 examples/xml/test/testdevmem.xml
 create mode 100644 examples/xml/test/testdevnetif.xml
 create mode 100644 examples/xml/test/testdevrng.xml
 create mode 100644 examples/xml/test/testdevshmem.xml
 create mode 100644 examples/xml/test/testdevsound.xml
 create mode 100644 examples/xml/test/testdevvsock.xml
 create mode 100644 examples/xml/test/testdevwatchdog.xml

diff --git a/examples/xml/test/testdevcontroller.xml 
b/examples/xml/test/testdevcontroller.xml
new file mode 100644
index 00..d855bfa17f
--- /dev/null
+++ b/examples/xml/test/testdevcontroller.xml
@@ -0,0 +1 @@
+
diff --git a/examples/xml/test/testdevdiskcdrom.xml 
b/examples/xml/test/testdevdiskcdrom.xml
new file mode 100644
index 00..edc90556bb
--- /dev/null
+++ b/examples/xml/test/testdevdiskcdrom.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/examples/xml/test/testdevfs.xml b/examples/xml/test/testdevfs.xml
new file mode 100644
index 00..cee5ed4ed9
--- /dev/null
+++ b/examples/xml/test/testdevfs.xml
@@ -0,0 +1,6 @@
+
+  
+  
+  
+  
+
diff --git a/examples/xml/test/testdevhostdev.xml 
b/examples/xml/test/testdevhostdev.xml
new file mode 100644
index 00..e364b50f36
--- /dev/null
+++ b/examples/xml/test/testdevhostdev.xml
@@ -0,0 +1,5 @@
+
+  
+/dev/sdf1s
+  
+
diff --git a/examples/xml/test/testdevif.xml b/examples/xml/test/testdevif.xml
new file mode 100644
index 00..7e0be80050
--- /dev/null
+++ b/examples/xml/test/testdevif.xml
@@ -0,0 +1,6 @@
+
+  
+  
+  
+  
+
diff --git a/examples/xml/test/testdevinput.xml 
b/examples/xml/test/testdevinput.xml
new file mode 100644
index 00..d958f5b931
--- /dev/null
+++ b/examples/xml/test/testdevinput.xml
@@ -0,0 +1 @@
+
diff --git a/examples/xml/test/testdevlease.xml 
b/examples/xml/test/testdevlease.xml
new file mode 100644
index 00..c53c0c7e7d
--- /dev/null
+++ b/examples/xml/test/testdevlease.xml
@@ -0,0 +1,5 @@
+
+  testarea
+  testkey
+  
+
diff --git a/examples/xml/test/testdevmem.xml b/examples/xml/test/testdevmem.xml
new file mode 100644
index 00..49efd4af55
--- /dev/null
+++ b/examples/xml/test/testdevmem.xml
@@ -0,0 +1,6 @@
+
+  
+524287
+0
+  
+
diff --git a/examples/xml/test/testdevnetif.xml 
b/examples/xml/test/testdevnetif.xml
new file mode 100644
index 00..89e01a611f
--- /dev/null
+++ b/examples/xml/test/testdevnetif.xml
@@ -0,0 +1,6 @@
+
+  
+  
+  
+  
+
diff --git a/examples/xml/test/testdevrng.xml b/examples/xml/test/testdevrng.xml
new file mode 100644
index 00..369f423740
--- /dev/null
+++ b/examples/xml/test/testdevrng.xml
@@ -0,0 +1,4 @@
+
+  
+  
+
diff --git a/examples/xml/test/testdevshmem.xml 
b/examples/xml/test/testdevshmem.xml
new file mode 100644
index 00..04bf3d9a53
--- /dev/null
+++ b/examples/xml/test/testdevshmem.xml
@@ -0,0 +1,4 @@
+
+  
+  4
+
diff --git a/examples/xml/test/testdevsound.xml 
b/examples/xml/test/testdevsound.xml
new file mode 100644
index 00..cf7323077f
--- /dev/null
+++ b/examples/xml/test/testdevsound.xml
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/examples/xml/test/testdevvsock.xml 
b/examples/xml/test/testdevvsock.xml
new file mode 100644
index 00..dda45780c4
--- /dev/null
+++ b/examples/xml/test/testdevvsock.xml
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/examples/xml/test/testdevwatchdog.xml 
b/examples/xml/test/testdevwatchdog.xml
new file mode 100644
index 00..a02086f296
--- /dev/null
+++ b/examples/xml/test/testdevwatchdog.xml
@@ -0,0 +1 @@
+
diff --git a/examples/xml/test/testdomfc5.xml b/examples/xml/test/testdomfc5.xml
index a8afc211f6..a529505543 100644
--- a/examples/xml/test/testdomfc5.xml
+++ b/examples/xml/test/testdomfc5.xml

[PATCH 3/5] test_driver: Implement virDomainDetachDevice

2021-08-16 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index e2463876fa..21e813db8f 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9731,6 +9731,14 @@ testDomainDetachDeviceAlias(virDomainPtr dom,
NULL, alias, flags);
 }
 
+static int
+testDomainDetachDevice(virDomainPtr dom,
+   const char *xml)
+{
+return testDomainDetachDeviceFlags(dom, xml,
+   VIR_DOMAIN_AFFECT_LIVE);
+}
+
 /*
  * Test driver
  */
@@ -9820,6 +9828,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainFSFreeze = testDomainFSFreeze, /* 5.7.0 */
 .domainFSThaw = testDomainFSThaw, /* 5.7.0 */
 .domainFSTrim = testDomainFSTrim, /* 5.7.0 */
+.domainDetachDevice = testDomainDetachDevice, /* 7.7.0 */
 .domainDetachDeviceAlias = testDomainDetachDeviceAlias, /* 7.7.0 */
 .domainDetachDeviceFlags = testDomainDetachDeviceFlags, /* 7.7.0 */
 .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
-- 
2.32.0



[PATCH 1/5] test_driver: Implement virDomainDetachDeviceFlags

2021-08-16 Thread Luke Yue
Introduce testDomainChgDevice for further development (just like what we
did for IOThread). And introduce testDomainDetachDeviceLiveAndConfig for
detaching devices.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 270 +
 1 file changed, 270 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 00cc13511a..2ebdbaa604 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9452,6 +9452,275 @@ testDomainGetMessages(virDomainPtr dom,
 return rv;
 }
 
+static int
+testDomainDetachDeviceLiveAndConfig(virDomainDef *vmdef,
+virDomainDeviceDef *dev)
+{
+virDomainDiskDef *disk;
+virDomainDiskDef *det_disk;
+virDomainNetDef *net;
+virDomainSoundDef *sound;
+virDomainHostdevDef *hostdev;
+virDomainHostdevDef *det_hostdev;
+virDomainLeaseDef *lease;
+virDomainLeaseDef *det_lease;
+virDomainControllerDef *cont;
+virDomainControllerDef *det_cont;
+virDomainFSDef *fs;
+virDomainMemoryDef *mem;
+int idx;
+
+switch (dev->type) {
+case VIR_DOMAIN_DEVICE_DISK:
+disk = dev->data.disk;
+if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
+virReportError(VIR_ERR_DEVICE_MISSING,
+   _("no target device %s"), disk->dst);
+return -1;
+}
+virDomainDiskDefFree(det_disk);
+break;
+
+case VIR_DOMAIN_DEVICE_NET:
+net = dev->data.net;
+if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
+return -1;
+
+/* this is guaranteed to succeed */
+virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
+break;
+
+case VIR_DOMAIN_DEVICE_SOUND:
+sound = dev->data.sound;
+if ((idx = virDomainSoundDefFind(vmdef, sound)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("device not present in domain configuration"));
+return -1;
+}
+virDomainSoundDefFree(virDomainSoundDefRemove(vmdef, idx));
+break;
+
+case VIR_DOMAIN_DEVICE_HOSTDEV: {
+hostdev = dev->data.hostdev;
+if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("device not present in domain configuration"));
+return -1;
+}
+virDomainHostdevRemove(vmdef, idx);
+virDomainHostdevDefFree(det_hostdev);
+break;
+}
+
+case VIR_DOMAIN_DEVICE_LEASE:
+lease = dev->data.lease;
+if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
+virReportError(VIR_ERR_DEVICE_MISSING,
+   _("Lease %s in lockspace %s does not exist"),
+   lease->key, NULLSTR(lease->lockspace));
+return -1;
+}
+virDomainLeaseDefFree(det_lease);
+break;
+
+case VIR_DOMAIN_DEVICE_CONTROLLER:
+cont = dev->data.controller;
+if ((idx = virDomainControllerFind(vmdef, cont->type,
+   cont->idx)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("device not present in domain configuration"));
+return -1;
+}
+det_cont = virDomainControllerRemove(vmdef, idx);
+virDomainControllerDefFree(det_cont);
+
+break;
+
+case VIR_DOMAIN_DEVICE_FS:
+fs = dev->data.fs;
+idx = virDomainFSIndexByName(vmdef, fs->dst);
+if (idx < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching filesystem device was found"));
+return -1;
+}
+
+fs = virDomainFSRemove(vmdef, idx);
+virDomainFSDefFree(fs);
+break;
+
+case VIR_DOMAIN_DEVICE_RNG:
+if ((idx = virDomainRNGFind(vmdef, dev->data.rng)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("no matching RNG device was found"));
+return -1;
+}
+
+virDomainRNGDefFree(virDomainRNGRemove(vmdef, idx));
+break;
+
+case VIR_DOMAIN_DEVICE_MEMORY:
+if ((idx = virDomainMemoryFindInactiveByDef(vmdef,
+dev->data.memory)) < 0) {
+virReportError(VIR_ERR_DEVICE_MISSING, "%s",
+   _("matching memory device was not found"));
+return -1;
+}
+mem = virDomainMemoryRemove(vmdef, idx);
+vmdef->mem.cur_balloon -= mem->size;
+virDomainMemoryDefFree(mem);
+break;
+
+case VIR_DOMAIN_DEVICE_REDIRDEV:
+  

[PATCH 0/5] Implement detach device related APIs for test driver

2021-08-16 Thread Luke Yue
Luke Yue (5):
  test_driver: Implement virDomainDetachDeviceFlags
  test_driver: Implement virDomainDetachDeviceAlias
  test_driver: Implement virDomainDetachDevice
  examples: xml: test: add xml for testing devices related APIs
  tests: Test detach-device and detach-device-alias for test driver

 examples/xml/test/testdevcontroller.xml |   1 +
 examples/xml/test/testdevdiskcdrom.xml  |   5 +
 examples/xml/test/testdevfs.xml |   6 +
 examples/xml/test/testdevhostdev.xml|   5 +
 examples/xml/test/testdevif.xml |   6 +
 examples/xml/test/testdevinput.xml  |   1 +
 examples/xml/test/testdevlease.xml  |   5 +
 examples/xml/test/testdevmem.xml|   6 +
 examples/xml/test/testdevnetif.xml  |   6 +
 examples/xml/test/testdevrng.xml|   4 +
 examples/xml/test/testdevshmem.xml  |   4 +
 examples/xml/test/testdevsound.xml  |   3 +
 examples/xml/test/testdevvsock.xml  |   3 +
 examples/xml/test/testdevwatchdog.xml   |   1 +
 examples/xml/test/testdomfc5.xml|  46 
 examples/xml/test/testnodeinline.xml|  46 
 src/test/test_driver.c  | 290 
 tests/virshtest.c   |  24 ++
 18 files changed, 462 insertions(+)
 create mode 100644 examples/xml/test/testdevcontroller.xml
 create mode 100644 examples/xml/test/testdevdiskcdrom.xml
 create mode 100644 examples/xml/test/testdevfs.xml
 create mode 100644 examples/xml/test/testdevhostdev.xml
 create mode 100644 examples/xml/test/testdevif.xml
 create mode 100644 examples/xml/test/testdevinput.xml
 create mode 100644 examples/xml/test/testdevlease.xml
 create mode 100644 examples/xml/test/testdevmem.xml
 create mode 100644 examples/xml/test/testdevnetif.xml
 create mode 100644 examples/xml/test/testdevrng.xml
 create mode 100644 examples/xml/test/testdevshmem.xml
 create mode 100644 examples/xml/test/testdevsound.xml
 create mode 100644 examples/xml/test/testdevvsock.xml
 create mode 100644 examples/xml/test/testdevwatchdog.xml

-- 
2.32.0



[PATCH 2/5] test_driver: Implement virDomainDetachDeviceAlias

2021-08-16 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 2ebdbaa604..e2463876fa 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9721,6 +9721,16 @@ testDomainDetachDeviceFlags(virDomainPtr dom,
 return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
xml, NULL, flags);
 }
+
+static int
+testDomainDetachDeviceAlias(virDomainPtr dom,
+const char *alias,
+unsigned int flags)
+{
+return testDomainChgDevice(dom, VIR_DOMAIN_DEVICE_ACTION_DETACH,
+   NULL, alias, flags);
+}
+
 /*
  * Test driver
  */
@@ -9810,6 +9820,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainFSFreeze = testDomainFSFreeze, /* 5.7.0 */
 .domainFSThaw = testDomainFSThaw, /* 5.7.0 */
 .domainFSTrim = testDomainFSTrim, /* 5.7.0 */
+.domainDetachDeviceAlias = testDomainDetachDeviceAlias, /* 7.7.0 */
 .domainDetachDeviceFlags = testDomainDetachDeviceFlags, /* 7.7.0 */
 .domainGetAutostart = testDomainGetAutostart, /* 0.3.2 */
 .domainSetAutostart = testDomainSetAutostart, /* 0.3.2 */
-- 
2.32.0



[PATCH v2 3/4] test_driver: Implement virDomainAbortJob

2021-08-16 Thread Luke Yue
As we are using jobState to store dummy job type, so just change it to
VIR_DOMAIN_JOB_CANCELLED when try to abort a job.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 93aeec7105..5043c57fe2 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -2874,6 +2874,34 @@ testDomainGetJobStats(virDomainPtr domain,
 return ret;
 }
 
+static int
+testDomainAbortJob(virDomainPtr dom)
+{
+virDomainObj *vm;
+int ret = -1;
+testDomainObjPrivate *priv;
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainObjCheckActive(vm) < 0)
+goto cleanup;
+
+priv = vm->privateData;
+
+if (priv->jobState == VIR_DOMAIN_JOB_NONE) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("no job is active on the domain"));
+} else {
+priv->jobState = VIR_DOMAIN_JOB_CANCELLED;
+ret = 0;
+}
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 static int
 testDomainGetLaunchSecurityInfo(virDomainPtr domain G_GNUC_UNUSED,
 virTypedParameterPtr *params G_GNUC_UNUSED,
@@ -9777,6 +9805,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainSetLifecycleAction = testDomainSetLifecycleAction, /* 5.7.0 */
 .domainGetJobInfo = testDomainGetJobInfo, /* 7.7.0 */
 .domainGetJobStats = testDomainGetJobStats, /* 7.7.0 */
+.domainAbortJob = testDomainAbortJob, /* 7.7.0 */
 
 .domainSnapshotNum = testDomainSnapshotNum, /* 1.1.4 */
 .domainSnapshotListNames = testDomainSnapshotListNames, /* 1.1.4 */
-- 
2.32.0



[PATCH v2 4/4] virshtest: add test for domjobinfo

2021-08-16 Thread Luke Yue
Signed-off-by: Luke Yue 
---
 tests/virshtest.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/tests/virshtest.c b/tests/virshtest.c
index 53db2aa19a..0c46496c74 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -291,6 +291,13 @@ static int testCompareDomControlInfoByName(const void 
*data G_GNUC_UNUSED)
 return testCompareOutputLit(exp, NULL, argv);
 }
 
+static int testCompareDomJobInfoByName(const void *data G_GNUC_UNUSED)
+{
+const char *const argv[] = { VIRSH_CUSTOM, "domjobinfo", "fc4", NULL };
+const char *exp = "Job type: None\n\n";
+return testCompareOutputLit(exp, NULL, argv);
+}
+
 struct testInfo {
 const char *const *argv;
 const char *result;
@@ -383,6 +390,10 @@ mymain(void)
testCompareDomControlInfoByName, NULL) != 0)
 ret = -1;
 
+if (virTestRun("virsh domjobinfo (by name)",
+   testCompareDomJobInfoByName, NULL) != 0)
+ret = -1;
+
 /* It's a bit awkward listing result before argument, but that's a
  * limitation of C99 vararg macros.  */
 # define DO_TEST(i, result, ...) \
-- 
2.32.0



[PATCH v2 1/4] test_driver: Implement virDomainGetJobInfo

2021-08-16 Thread Luke Yue
priv-jobState is used to store dummy job type, and priv->jobOperation is
used to store dummy job operation, they are initialized to
VIR_DOMAIN_JOB_NONE and VIR_DOMAIN_JOB_OPERATION_UNKNOWN, we can
just change them in other job related APIs as there is no real job in test
driver.

Signed-off-by: Luke Yue 
---
 src/test/test_driver.c | 89 ++
 1 file changed, 89 insertions(+)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 00cc13511a..9306f0e104 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -380,6 +380,10 @@ struct _testDomainObjPrivate {
 /* used by get/set time APIs */
 long long seconds;
 unsigned int nseconds;
+
+/* used by Job Info APIs */
+unsigned int jobState;
+unsigned int jobOperation;
 };
 
 
@@ -396,6 +400,9 @@ testDomainObjPrivateAlloc(void *opaque)
 priv->seconds = 627319920;
 priv->nseconds = 0;
 
+priv->jobState = VIR_DOMAIN_JOB_NONE;
+priv->jobOperation = VIR_DOMAIN_JOB_OPERATION_UNKNOWN;
+
 return priv;
 }
 
@@ -2681,6 +2688,87 @@ testDomainGetOSType(virDomainPtr dom G_GNUC_UNUSED)
 return ret;
 }
 
+static int
+testDomainGetJobInfoImpl(virDomainObj *dom,
+ virDomainJobInfoPtr info)
+{
+testDomainObjPrivate *priv = dom->privateData;
+
+memset(info, 0, sizeof(*info));
+
+info->type = priv->jobState;
+
+switch (priv->jobState) {
+case VIR_DOMAIN_JOB_NONE:
+break;
+
+case VIR_DOMAIN_JOB_BOUNDED:
+info->dataTotal = 30 * 1024;
+info->dataProcessed = 10 * 1024;
+info->dataRemaining = 20 * 1024;
+info->timeRemaining = 6000;
+info->timeElapsed = 4000;
+info->memTotal = 3 * 1024 * 1024;
+info->memProcessed = 1024 * 1024;
+info->memRemaining = 2 * 1024 * 1024;
+info->fileTotal = 2 * 1024 * 1024;
+info->fileProcessed = 1024 * 1024 / 2;
+info->fileRemaining = 3 * 1024 * 1024 / 2;
+break;
+
+case VIR_DOMAIN_JOB_UNBOUNDED:
+info->dataTotal = 30 * 1024;
+info->dataProcessed = 10 * 1024;
+info->dataRemaining = 20 * 1024;
+info->timeElapsed = 4000;
+info->memTotal = 3 * 1024 * 1024;
+info->memProcessed = 1024 * 1024;
+info->memRemaining = 2 * 1024 * 1024;
+info->fileTotal = 2 * 1024 * 1024;
+info->fileProcessed = 1024 * 1024 / 2;
+info->fileRemaining = 3 * 1024 * 1024 / 2;
+break;
+
+case VIR_DOMAIN_JOB_COMPLETED:
+info->timeElapsed = 1;
+info->dataTotal = 30 * 1024;
+info->dataProcessed = 30 * 1024;
+info->memTotal = 3 * 1024 * 1024;
+info->memProcessed = 3 * 1024 * 1024;
+info->fileTotal = 2 * 1024 * 1024;
+info->fileProcessed = 2 * 1024 * 1024;
+break;
+
+case VIR_DOMAIN_JOB_FAILED:
+break;
+
+case VIR_DOMAIN_JOB_CANCELLED:
+break;
+}
+
+return 0;
+}
+
+static int
+testDomainGetJobInfo(virDomainPtr dom,
+ virDomainJobInfoPtr info)
+{
+virDomainObj *vm;
+int ret = -1;
+
+if (!(vm = testDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainObjCheckActive(vm) < 0)
+goto cleanup;
+
+ret = testDomainGetJobInfoImpl(vm, info);
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 
 static int
 testDomainGetLaunchSecurityInfo(virDomainPtr domain G_GNUC_UNUSED,
@@ -9583,6 +9671,7 @@ static virHypervisorDriver testHypervisorDriver = {
 .domainMemoryPeek = testDomainMemoryPeek, /* 5.4.0 */
 .domainGetBlockInfo = testDomainGetBlockInfo, /* 5.7.0 */
 .domainSetLifecycleAction = testDomainSetLifecycleAction, /* 5.7.0 */
+.domainGetJobInfo = testDomainGetJobInfo, /* 7.7.0 */
 
 .domainSnapshotNum = testDomainSnapshotNum, /* 1.1.4 */
 .domainSnapshotListNames = testDomainSnapshotListNames, /* 1.1.4 */
-- 
2.32.0



  1   2   3   >