As one wise man once said about those furry things with
no practical purpose:
a cat is like a self-aware moving bonsai tree with an attitude.
Inspired by this profound quote, introduce a <watchcat> device.
A counterpart to <watchdog> that does nothing. If the domain
crashes, it just watches. Or purrs. Or wanders around.
XML format:
<devices>
<watchcat breed='persian'/>
</devices>
Available breeds also include chihuahua, because dogs under 50 lbs
are as pointless as cats. Just ask Ron Swanson.
Signed-off-by: Ján Tomko <jtomko(a)redhat.com>
---
docs/formatdomain.html.in | 26 ++++++++
docs/schemas/domaincommon.rng | 19 ++++++
src/conf/domain_conf.c | 106 +++++++++++++++++++++++++++++++-
src/conf/domain_conf.h | 22 +++++++
src/qemu/qemu_domain.c | 1 +
src/qemu/qemu_domain_address.c | 1 +
src/qemu/qemu_driver.c | 6 ++
src/qemu/qemu_hotplug.c | 1 +
src/qemu/qemu_process.c | 5 ++
tests/genericxml2xmlindata/watchcat.xml | 18 ++++++
tests/genericxml2xmltest.c | 2 +
11 files changed, 206 insertions(+), 1 deletion(-)
create mode 100644 tests/genericxml2xmlindata/watchcat.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 08dc74b6b..bc47b85f1 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8032,6 +8032,32 @@ qemu-kvm -net nic,model=? /dev/null
</dd>
</dl>
+ <h4><a id="elementsWatchcat">Watchcat</a></h4>
+
+ <p>
+ The <code>watchcat</code> element can be used to add a watchcat.
+ <span class="since">Since 2.4.0</span>
+ </p>
+
+ <p>
+ Example:
+ </p>
+<pre>
+...
+<devices>
+ <watchcat breed='siamese'/>
+</devices>
+...
+</pre>
+ <dl>
+ <dt><code>breed</code></dt>
+ <dd>
+ <p>
+ This attribute is intentionally left undocumented
+ </p>
+ </dd>
+ </dl>
+
<h3><a id="seclabel">Security label</a></h3>
<p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 8165e699d..58630f68a 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4179,6 +4179,22 @@
</element>
</define>
+ <define name="watchcat">
+ <element name="watchcat">
+ <attribute name="breed">
+ <choice>
+ <value>persian</value>
+ <value>blue-swedish</value>
+ <value>abyssinian</value>
+ <value>british-shorthair</value>
+ <value>turkish-angora</value>
+ <value>chihuahua</value>
+ <value>siamese</value>
+ </choice>
+ </attribute>
+ </element>
+ </define>
+
<define name="input">
<element name="input">
<optional>
@@ -4691,6 +4707,9 @@
<optional>
<ref name="iommu"/>
</optional>
+ <optional>
+ <ref name="watchcat"/>
+ </optional>
</interleave>
</element>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index ae7c0d9b7..d45d40ee8 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -59,6 +59,7 @@
#include "virnetdevmacvlan.h"
#include "virhostdev.h"
#include "virmdev.h"
+#include "virrandom.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
@@ -256,7 +257,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
"tpm",
"panic",
"memory",
- "iommu")
+ "iommu",
+ "watchcat")
VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
"none",
@@ -929,6 +931,15 @@ VIR_ENUM_IMPL(virDomainShmemModel, VIR_DOMAIN_SHMEM_MODEL_LAST,
"ivshmem-plain",
"ivshmem-doorbell")
+VIR_ENUM_IMPL(virDomainWatchcatBreed, VIR_DOMAIN_WATCHCAT_BREED_LAST,
+ "persian",
+ "blue-swedish",
+ "abyssinian",
+ "british-shorthair",
+ "turkish-angora",
+ "chihuahua",
+ "siamese")
+
static virClassPtr virDomainObjClass;
static virClassPtr virDomainXMLOptionClass;
static void virDomainObjDispose(void *obj);
@@ -2739,6 +2750,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
case VIR_DOMAIN_DEVICE_IOMMU:
VIR_FREE(def->data.iommu);
break;
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
+ VIR_FREE(def->data.watchcat);
+ break;
case VIR_DOMAIN_DEVICE_LAST:
case VIR_DOMAIN_DEVICE_NONE:
break;
@@ -3608,6 +3622,7 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
case VIR_DOMAIN_DEVICE_LEASE:
case VIR_DOMAIN_DEVICE_GRAPHICS:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
case VIR_DOMAIN_DEVICE_NONE:
break;
@@ -3834,6 +3849,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
case VIR_DOMAIN_DEVICE_RNG:
case VIR_DOMAIN_DEVICE_MEMORY:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
break;
}
#endif
@@ -5010,6 +5026,12 @@ virDomainDefPostParseCommon(virDomainDefPtr def,
}
}
+ if (def->watchcat &&
+ def->watchcat->breed == VIR_DOMAIN_WATCHCAT_BREED_CHIHUAHUA) {
+ virDomainWatchdogDefPtr dawg = def->watchdog;
+ VIR_FREE(dawg);
+ }
+
/* clean up possibly duplicated metadata entries */
virXMLNodeSanitizeNamespaces(def->metadata);
@@ -5550,6 +5572,7 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_MEMORY:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_LAST:
break;
@@ -15685,6 +15708,39 @@ virDomainIOMMUDefParseXML(xmlNodePtr node,
}
+static virDomainWatchcatDefPtr
+virDomainWatchcatDefParseXML(xmlNodePtr node)
+{
+ virDomainWatchcatDefPtr watchcat = NULL, ret = NULL;
+ char *tmp = NULL;
+ int val;
+
+ if (VIR_ALLOC(watchcat) < 0)
+ goto cleanup;
+
+ if (!(tmp = virXMLPropString(node, "breed"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing breed for Watchcat device"));
+ goto cleanup;
+ }
+
+ if ((val = virDomainWatchcatBreedTypeFromString(tmp)) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, _("unknown Watchcat breed: %s"),
tmp);
+ goto cleanup;
+ }
+
+ watchcat->breed = val;
+
+ ret = watchcat;
+ watchcat = NULL;
+
+ cleanup:
+ VIR_FREE(watchcat);
+ VIR_FREE(tmp);
+ return ret;
+}
+
+
virDomainDeviceDefPtr
virDomainDeviceDefParse(const char *xmlStr,
const virDomainDef *def,
@@ -15840,6 +15896,10 @@ virDomainDeviceDefParse(const char *xmlStr,
if (!(dev->data.iommu = virDomainIOMMUDefParseXML(node, ctxt)))
goto error;
break;
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
+ if (!(dev->data.watchcat = virDomainWatchcatDefParseXML(node)))
+ goto error;
+ break;
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_LAST:
break;
@@ -20243,6 +20303,21 @@ virDomainDefParseXML(xmlDocPtr xml,
}
VIR_FREE(nodes);
+ if ((n = virXPathNodeSet("./devices/watchcat", ctxt, &nodes)) < 0)
+ goto error;
+
+ if (n > 1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("only a single Watchcat is supported"));
+ goto error;
+ }
+
+ if (n > 0) {
+ if (!(def->watchcat = virDomainWatchcatDefParseXML(nodes[0])))
+ goto error;
+ }
+ VIR_FREE(nodes);
+
/* analysis of the user namespace mapping */
if ((n = virXPathNodeSet("./idmap/uid", ctxt, &nodes)) < 0)
goto error;
@@ -22287,6 +22362,7 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src,
case VIR_DOMAIN_DEVICE_SHMEM:
case VIR_DOMAIN_DEVICE_MEMORY:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
break;
}
#endif
@@ -26463,6 +26539,27 @@ virDomainIOMMUDefFormat(virBufferPtr buf,
}
+static int
+virDomainWatchcatDefFormat(virBufferPtr buf,
+ const virDomainWatchcatDef *watchcat)
+{
+ virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
+ int ret = -1;
+
+ virBufferAsprintf(&attrBuf, " breed='%s'",
+ virDomainWatchcatBreedTypeToString(watchcat->breed));
+
+ if (virXMLFormatElement(buf, "watchcat", &attrBuf, NULL) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virBufferFreeAndReset(&attrBuf);
+ return ret;
+}
+
+
/* This internal version appends to an existing buffer
* (possibly with auto-indent), rather than flattening
* to string.
@@ -27244,6 +27341,12 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virDomainIOMMUDefFormat(buf, def->iommu) < 0)
goto error;
+ if (def->watchcat) {
+ if (virDomainWatchcatDefFormat(buf, def->watchcat) < 0)
+ goto error;
+ if (virRandomInt(100) < 2)
+ VIR_FREE(def->watchcat);
+ }
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</devices>\n");
@@ -28370,6 +28473,7 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
case VIR_DOMAIN_DEVICE_MEMBALLOON:
case VIR_DOMAIN_DEVICE_NVRAM:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Copying definition of '%d' type "
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 61379e50f..6fd4ee6eb 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -157,6 +157,9 @@ typedef virDomainTPMDef *virDomainTPMDefPtr;
typedef struct _virDomainIOMMUDef virDomainIOMMUDef;
typedef virDomainIOMMUDef *virDomainIOMMUDefPtr;
+typedef struct _virDomainWatchcatDef virDomainWatchcatDef;
+typedef virDomainWatchcatDef *virDomainWatchcatDefPtr;
+
typedef struct _virDomainVirtioOptions virDomainVirtioOptions;
typedef virDomainVirtioOptions *virDomainVirtioOptionsPtr;
@@ -186,6 +189,7 @@ typedef enum {
VIR_DOMAIN_DEVICE_PANIC,
VIR_DOMAIN_DEVICE_MEMORY,
VIR_DOMAIN_DEVICE_IOMMU,
+ VIR_DOMAIN_DEVICE_WATCHCAT,
VIR_DOMAIN_DEVICE_LAST
} virDomainDeviceType;
@@ -218,6 +222,7 @@ struct _virDomainDeviceDef {
virDomainPanicDefPtr panic;
virDomainMemoryDefPtr memory;
virDomainIOMMUDefPtr iommu;
+ virDomainWatchcatDefPtr watchcat;
} data;
};
@@ -2303,6 +2308,21 @@ struct _virDomainIOMMUDef {
virTristateSwitch iotlb;
};
+typedef enum {
+ VIR_DOMAIN_WATCHCAT_BREED_PERSIAN,
+ VIR_DOMAIN_WATCHCAT_BREED_BLUE_SWEDISH,
+ VIR_DOMAIN_WATCHCAT_BREED_ABYSSINIAN,
+ VIR_DOMAIN_WATCHCAT_BREED_BRITISH_SHORTHAIR,
+ VIR_DOMAIN_WATCHCAT_BREED_TURKISH_ANGORA,
+ VIR_DOMAIN_WATCHCAT_BREED_CHIHUAHUA,
+ VIR_DOMAIN_WATCHCAT_BREED_SIAMESE,
+ VIR_DOMAIN_WATCHCAT_BREED_LAST
+} virDomainWatchcatBreed;
+
+struct _virDomainWatchcatDef {
+ virDomainWatchcatBreed breed;
+};
+
struct _virDomainVirtioOptions {
virTristateSwitch iommu;
virTristateSwitch ats;
@@ -2448,6 +2468,7 @@ struct _virDomainDef {
virSysinfoDefPtr sysinfo;
virDomainRedirFilterDefPtr redirfilter;
virDomainIOMMUDefPtr iommu;
+ virDomainWatchcatDefPtr watchcat;
void *namespaceData;
virDomainXMLNamespace ns;
@@ -3345,6 +3366,7 @@ VIR_ENUM_DECL(virDomainMemorySource)
VIR_ENUM_DECL(virDomainMemoryAllocation)
VIR_ENUM_DECL(virDomainIOMMUModel)
VIR_ENUM_DECL(virDomainShmemModel)
+VIR_ENUM_DECL(virDomainWatchcatBreed)
/* from libvirt.h */
VIR_ENUM_DECL(virDomainState)
VIR_ENUM_DECL(virDomainNostateReason)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 580e0f830..c75ce26eb 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -4978,6 +4978,7 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_LAST:
break;
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 37473ebf1..f789cbe92 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -851,6 +851,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
case VIR_DOMAIN_DEVICE_LEASE:
case VIR_DOMAIN_DEVICE_GRAPHICS:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
case VIR_DOMAIN_DEVICE_NONE:
return 0;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 7bcc4936d..5ede1edb7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7734,6 +7734,7 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("live attach of device '%s' is not
supported"),
@@ -7833,6 +7834,7 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("live detach of device '%s' is not
supported"),
@@ -7969,6 +7971,7 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm,
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("live update of device '%s' is not
supported"),
@@ -8155,6 +8158,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("persistent attach of device '%s' is not
supported"),
@@ -8338,6 +8342,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("persistent detach of device '%s' is not
supported"),
@@ -8436,6 +8441,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("persistent update of device '%s' is not
supported"),
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 49af4d4ff..e8ba3e967 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4507,6 +4507,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_WATCHCAT:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("don't know how to remove a %s device"),
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1afb71f11..3bd08720b 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2849,6 +2849,9 @@ qemuProcessStartCPUs(virQEMUDriverPtr driver, virDomainObjPtr vm,
qemuDomainObjPrivatePtr priv = vm->privateData;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ if (vm->def->watchcat)
+ VIR_WARN("Meow!");
+
/* Bring up netdevs before starting CPUs */
if (qemuInterfaceStartDevices(vm->def) < 0)
goto cleanup;
@@ -4190,6 +4193,8 @@ qemuProcessBeginJob(virQEMUDriverPtr driver,
return -1;
qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_NONE);
+ if (vm->def->watchcat)
+ VIR_WARN("purrr");
return 0;
}
diff --git a/tests/genericxml2xmlindata/watchcat.xml
b/tests/genericxml2xmlindata/watchcat.xml
new file mode 100644
index 000000000..daeebfa43
--- /dev/null
+++ b/tests/genericxml2xmlindata/watchcat.xml
@@ -0,0 +1,18 @@
+<domain type='qemu'>
+ <name>foo-fighters</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <watchcat breed='blue-swedish'/>
+ </devices>
+</domain>
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
index d8270a6ca..6438ab2a3 100644
--- a/tests/genericxml2xmltest.c
+++ b/tests/genericxml2xmltest.c
@@ -141,6 +141,8 @@ mymain(void)
DO_TEST_FULL("cachetune-colliding-types", false, true,
TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
+ DO_TEST("watchcat");
+
virObjectUnref(caps);
virObjectUnref(xmlopt);
--
2.13.6