[libvirt] [PATCH] conf: Parse virtio-crypto in the domain XML
by Longpeng(Mike)
As virtio-crypto has been supported in QEMU 2.9 and
the frontend driver has been merged in linux 4.10,
so it's necessary to support virtio-crypto in domain
XML.
This patch parse the domain XML with virtio-crypto
support, the virtio-crypto XML looks like this:
<crypto model='virtio'>
<backend type='builtin' queues='2'/>
</crypto>
Signed-off-by: Longpeng(Mike) <longpeng2(a)huawei.com>
---
src/conf/domain_conf.c | 212 +++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 32 +++++++
src/qemu/qemu_alias.c | 20 ++++
src/qemu/qemu_alias.h | 4 +
src/qemu/qemu_capabilities.c | 4 +
src/qemu/qemu_capabilities.h | 2 +
src/qemu/qemu_command.c | 129 +++++++++++++++++++++++++
src/qemu/qemu_command.h | 4 +
src/qemu/qemu_domain_address.c | 17 ++++
src/qemu/qemu_driver.c | 6 ++
src/qemu/qemu_hotplug.c | 1 +
11 files changed, 431 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9f7b906..fcfccd5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -237,6 +237,7 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
"memballoon",
"nvram",
"rng",
+ "crypto",
"shmem",
"tpm",
"panic",
@@ -797,6 +798,14 @@ VIR_ENUM_IMPL(virDomainRNGBackend,
"random",
"egd");
+VIR_ENUM_IMPL(virDomainCryptoModel,
+ VIR_DOMAIN_CRYPTO_MODEL_LAST,
+ "virtio");
+
+VIR_ENUM_IMPL(virDomainCryptoBackend,
+ VIR_DOMAIN_CRYPTO_BACKEND_LAST,
+ "builtin");
+
VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_LAST,
"tpm-tis")
@@ -2337,6 +2346,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
case VIR_DOMAIN_DEVICE_RNG:
virDomainRNGDefFree(def->data.rng);
break;
+ case VIR_DOMAIN_DEVICE_CRYPTO:
+ virDomainCryptoDefFree(def->data.crypto);
+ break;
case VIR_DOMAIN_DEVICE_CHR:
virDomainChrDefFree(def->data.chr);
break;
@@ -2600,6 +2612,10 @@ void virDomainDefFree(virDomainDefPtr def)
virDomainRNGDefFree(def->rngs[i]);
VIR_FREE(def->rngs);
+ for (i = 0; i < def->ncryptos; i++)
+ virDomainCryptoDefFree(def->cryptos[i]);
+ VIR_FREE(def->cryptos);
+
for (i = 0; i < def->nmems; i++)
virDomainMemoryDefFree(def->mems[i]);
VIR_FREE(def->mems);
@@ -3169,6 +3185,8 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
return &device->data.shmem->info;
case VIR_DOMAIN_DEVICE_RNG:
return &device->data.rng->info;
+ case VIR_DOMAIN_DEVICE_CRYPTO:
+ return &device->data.crypto->info;
case VIR_DOMAIN_DEVICE_TPM:
return &device->data.tpm->info;
case VIR_DOMAIN_DEVICE_PANIC:
@@ -3464,6 +3482,12 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
if (cb(def, &device, &def->rngs[i]->info, opaque) < 0)
return -1;
}
+ device.type = VIR_DOMAIN_DEVICE_CRYPTO;
+ for (i = 0; i < def->ncryptos; i++) {
+ device.data.crypto = def->cryptos[i];
+ if (cb(def, &device, &def->cryptos[i]->info, opaque) < 0)
+ return -1;
+ }
if (def->nvram) {
device.type = VIR_DOMAIN_DEVICE_NVRAM;
device.data.nvram = def->nvram;
@@ -3541,6 +3565,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_LAST:
case VIR_DOMAIN_DEVICE_RNG:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
case VIR_DOMAIN_DEVICE_MEMORY:
break;
}
@@ -4599,6 +4624,7 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
case VIR_DOMAIN_DEVICE_MEMBALLOON:
case VIR_DOMAIN_DEVICE_NVRAM:
case VIR_DOMAIN_DEVICE_RNG:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
case VIR_DOMAIN_DEVICE_SHMEM:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
@@ -12022,6 +12048,88 @@ virDomainRNGDefParseXML(xmlNodePtr node,
}
+static virDomainCryptoDefPtr
+virDomainCryptoDefParseXML(xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ unsigned int flags)
+{
+ char *model = NULL;
+ char *backend = NULL;
+ char *queues = NULL;
+ virDomainCryptoDefPtr def;
+ xmlNodePtr save = ctxt->node;
+ xmlNodePtr *backends = NULL;
+ int nbackends;
+
+ if (VIR_ALLOC(def) < 0)
+ return NULL;
+
+ if (!(model = virXMLPropString(node, "model"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing Crypto device model"));
+ goto error;
+ }
+
+ if ((def->model = virDomainCryptoModelTypeFromString(model)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown Crypto model '%s'"), model);
+ goto error;
+ }
+
+ ctxt->node = node;
+
+ if ((nbackends = virXPathNodeSet("./backend", ctxt, &backends)) < 0)
+ goto error;
+
+ if (nbackends != 1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("only one Crypto backend is supported"));
+ goto error;
+ }
+
+ if (!(backend = virXMLPropString(backends[0], "type"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing Crypto device backend type"));
+ goto error;
+ }
+
+ if ((def->backend = virDomainCryptoBackendTypeFromString(backend)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown Crypto backend model '%s'"), backend);
+ goto error;
+ }
+
+ switch ((virDomainCryptoBackend) def->backend) {
+ case VIR_DOMAIN_CRYPTO_BACKEND_BUILTIN:
+ queues = virXMLPropString(backends[0], "queues");
+ if (queues && virStrToLong_ui(queues, NULL, 10, &def->queues) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Malformed 'queues' value '%s'"), queues);
+ }
+ break;
+
+ case VIR_DOMAIN_CRYPTO_BACKEND_LAST:
+ break;
+ }
+
+ if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
+ goto error;
+
+cleanup:
+ VIR_FREE(model);
+ VIR_FREE(backend);
+ VIR_FREE(queues);
+ VIR_FREE(backends);
+ ctxt->node = save;
+ return def;
+
+error:
+ virDomainCryptoDefFree(def);
+ def = NULL;
+ goto cleanup;
+}
+
+
static virDomainMemballoonDefPtr
virDomainMemballoonDefParseXML(xmlNodePtr node,
xmlXPathContextPtr ctxt,
@@ -13368,6 +13476,10 @@ virDomainDeviceDefParse(const char *xmlStr,
if (!(dev->data.rng = virDomainRNGDefParseXML(node, ctxt, flags)))
goto error;
break;
+ case VIR_DOMAIN_DEVICE_CRYPTO:
+ if (!(dev->data.crypto = virDomainCryptoDefParseXML(node, ctxt, flags)))
+ goto error;
+ break;
case VIR_DOMAIN_DEVICE_CHR:
if (!(dev->data.chr = virDomainChrDefParseXML(ctxt,
node,
@@ -17073,6 +17185,22 @@ virDomainDefParseXML(xmlDocPtr xml,
}
VIR_FREE(nodes);
+ /* Parse the crypto devices */
+ if ((n = virXPathNodeSet("./devices/crypto", ctxt, &nodes)) < 0)
+ goto error;
+ if (n && VIR_ALLOC_N(def->cryptos, n) < 0)
+ goto error;
+ for (i = 0; i < n; i++) {
+ virDomainCryptoDefPtr crypto = virDomainCryptoDefParseXML(nodes[i],
+ ctxt,
+ flags);
+ if (!crypto)
+ goto error;
+
+ def->cryptos[def->ncryptos++] = crypto;
+ }
+ VIR_FREE(nodes);
+
/* Parse the TPM devices */
if ((n = virXPathNodeSet("./devices/tpm", ctxt, &nodes)) < 0)
goto error;
@@ -18199,6 +18327,25 @@ virDomainRNGDefCheckABIStability(virDomainRNGDefPtr src,
static bool
+virDomainCryptoDefCheckABIStability(virDomainCryptoDefPtr src,
+ virDomainCryptoDefPtr dst)
+{
+ if (src->model != dst->model) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target Crypto model '%s' does not match source '%s'"),
+ virDomainCryptoModelTypeToString(dst->model),
+ virDomainCryptoModelTypeToString(src->model));
+ return false;
+ }
+
+ if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
+ return false;
+
+ return true;
+}
+
+
+static bool
virDomainHubDefCheckABIStability(virDomainHubDefPtr src,
virDomainHubDefPtr dst)
{
@@ -18933,6 +19080,17 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
if (!virDomainRNGDefCheckABIStability(src->rngs[i], dst->rngs[i]))
goto error;
+ if (src->ncryptos != dst->ncryptos) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target domain crypto device count %zu "
+ "does not match source %zu"), dst->ncryptos, src->ncryptos);
+ goto error;
+ }
+
+ for (i = 0; i < src->ncryptos; i++)
+ if (!virDomainCryptoDefCheckABIStability(src->cryptos[i], dst->cryptos[i]))
+ goto error;
+
if (src->npanics != dst->npanics) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target domain panic device count %zu "
@@ -19007,6 +19165,7 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
case VIR_DOMAIN_DEVICE_NVRAM:
case VIR_DOMAIN_DEVICE_LAST:
case VIR_DOMAIN_DEVICE_RNG:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_SHMEM:
@@ -21590,6 +21749,51 @@ virDomainRNGDefFree(virDomainRNGDefPtr def)
static int
+virDomainCryptoDefFormat(virBufferPtr buf,
+ virDomainCryptoDefPtr def,
+ unsigned int flags)
+{
+ const char *model = virDomainCryptoModelTypeToString(def->model);
+ const char *backend = virDomainCryptoBackendTypeToString(def->backend);
+
+ virBufferAsprintf(buf, "<crypto model='%s'>\n", model);
+ virBufferAdjustIndent(buf, 2);
+ virBufferAsprintf(buf, "<backend type='%s'", backend);
+
+ switch ((virDomainCryptoBackend) def->backend) {
+ case VIR_DOMAIN_CRYPTO_BACKEND_BUILTIN:
+ if (def->queues)
+ virBufferAsprintf(buf, " queues='%u'", def->queues);
+
+ virBufferAddLit(buf, "/>\n");
+ break;
+
+ case VIR_DOMAIN_CRYPTO_BACKEND_LAST:
+ break;
+ }
+
+ if (virDomainDeviceInfoNeedsFormat(&def->info, flags)) {
+ if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
+ return -1;
+ }
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</crypto>\n");
+ return 0;
+}
+
+void
+virDomainCryptoDefFree(virDomainCryptoDefPtr def)
+{
+ if (!def)
+ return;
+
+ virDomainDeviceInfoClear(&def->info);
+ VIR_FREE(def);
+}
+
+
+static int
virDomainMemorySourceDefFormat(virBufferPtr buf,
virDomainMemoryDefPtr def)
{
@@ -23539,6 +23743,11 @@ virDomainDefFormatInternal(virDomainDefPtr def,
goto error;
}
+ for (n = 0; n < def->ncryptos; n++) {
+ if (virDomainCryptoDefFormat(buf, def->cryptos[n], flags))
+ goto error;
+ }
+
if (def->nvram)
virDomainNVRAMDefFormat(buf, def->nvram, flags);
@@ -24657,6 +24866,9 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
case VIR_DOMAIN_DEVICE_RNG:
rc = virDomainRNGDefFormat(&buf, src->data.rng, flags);
break;
+ case VIR_DOMAIN_DEVICE_CRYPTO:
+ rc = virDomainCryptoDefFormat(&buf, src->data.crypto, flags);
+ break;
case VIR_DOMAIN_DEVICE_CHR:
rc = virDomainChrDefFormat(&buf, src->data.chr, flags);
break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ba0ad5f..995ce8f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -127,6 +127,9 @@ typedef virDomainSnapshotObjList *virDomainSnapshotObjListPtr;
typedef struct _virDomainRNGDef virDomainRNGDef;
typedef virDomainRNGDef *virDomainRNGDefPtr;
+typedef struct _virDomainCryptoDef virDomainCryptoDef;
+typedef virDomainCryptoDef *virDomainCryptoDefPtr;
+
typedef struct _virDomainIdMapEntry virDomainIdMapEntry;
typedef virDomainIdMapEntry *virDomainIdMapEntryPtr;
@@ -172,6 +175,7 @@ typedef enum {
VIR_DOMAIN_DEVICE_MEMBALLOON,
VIR_DOMAIN_DEVICE_NVRAM,
VIR_DOMAIN_DEVICE_RNG,
+ VIR_DOMAIN_DEVICE_CRYPTO,
VIR_DOMAIN_DEVICE_SHMEM,
VIR_DOMAIN_DEVICE_TPM,
VIR_DOMAIN_DEVICE_PANIC,
@@ -203,6 +207,7 @@ struct _virDomainDeviceDef {
virDomainMemballoonDefPtr memballoon;
virDomainNVRAMDefPtr nvram;
virDomainRNGDefPtr rng;
+ virDomainCryptoDefPtr crypto;
virDomainShmemDefPtr shmem;
virDomainTPMDefPtr tpm;
virDomainPanicDefPtr panic;
@@ -1927,6 +1932,26 @@ struct _virDomainRNGDef {
};
typedef enum {
+ VIR_DOMAIN_CRYPTO_MODEL_VIRTIO,
+
+ VIR_DOMAIN_CRYPTO_MODEL_LAST
+} virDomainCryptoModel;
+
+typedef enum {
+ VIR_DOMAIN_CRYPTO_BACKEND_BUILTIN,
+
+ VIR_DOMAIN_CRYPTO_BACKEND_LAST
+} virDomainCryptoBackend;
+
+struct _virDomainCryptoDef {
+ int model;
+ int backend;
+ unsigned int queues; /* Multiqueue virtio-crypto */
+
+ virDomainDeviceInfo info;
+};
+
+typedef enum {
VIR_DOMAIN_MEMORY_MODEL_NONE,
VIR_DOMAIN_MEMORY_MODEL_DIMM, /* dimm hotpluggable memory device */
@@ -2218,6 +2243,9 @@ struct _virDomainDef {
size_t nrngs;
virDomainRNGDefPtr *rngs;
+ size_t ncryptos;
+ virDomainCryptoDefPtr *cryptos;
+
size_t nshmems;
virDomainShmemDefPtr *shmems;
@@ -2696,6 +2724,8 @@ int virDomainDefCompatibleDevice(virDomainDefPtr def,
void virDomainRNGDefFree(virDomainRNGDefPtr def);
+void virDomainCryptoDefFree(virDomainCryptoDefPtr def);
+
int virDomainDiskIndexByAddress(virDomainDefPtr def,
virPCIDeviceAddressPtr pci_controller,
unsigned int bus, unsigned int target,
@@ -2996,6 +3026,8 @@ VIR_ENUM_DECL(virDomainHyperv)
VIR_ENUM_DECL(virDomainKVM)
VIR_ENUM_DECL(virDomainRNGModel)
VIR_ENUM_DECL(virDomainRNGBackend)
+VIR_ENUM_DECL(virDomainCryptoModel)
+VIR_ENUM_DECL(virDomainCryptoBackend)
VIR_ENUM_DECL(virDomainTPMModel)
VIR_ENUM_DECL(virDomainTPMBackend)
VIR_ENUM_DECL(virDomainMemoryModel)
diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
index d624071..25b87d2 100644
--- a/src/qemu/qemu_alias.c
+++ b/src/qemu/qemu_alias.c
@@ -331,6 +331,26 @@ qemuAssignDeviceRNGAlias(virDomainDefPtr def,
int
+qemuAssignDeviceCryptoAlias(const virDomainDef *def,
+ virDomainCryptoDefPtr crypto)
+{
+ size_t i;
+ int maxidx = 0;
+ int idx;
+
+ for (i = 0; i < def->ncryptos; i++) {
+ if ((idx = qemuDomainDeviceAliasIndex(&def->cryptos[i]->info, "crypto")) >= maxidx)
+ maxidx = idx + 1;
+ }
+
+ if (virAsprintf(&crypto->info.alias, "crypto%d", maxidx) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+int
qemuAssignDeviceMemoryAlias(virDomainDefPtr def,
virDomainMemoryDefPtr mem)
{
diff --git a/src/qemu/qemu_alias.h b/src/qemu/qemu_alias.h
index e328a9b..4ae1c92 100644
--- a/src/qemu/qemu_alias.h
+++ b/src/qemu/qemu_alias.h
@@ -57,6 +57,10 @@ int qemuAssignDeviceRedirdevAlias(virDomainDefPtr def,
int qemuAssignDeviceRNGAlias(virDomainDefPtr def,
virDomainRNGDefPtr rng);
+int
+qemuAssignDeviceCryptoAlias(const virDomainDef *def,
+ virDomainCryptoDefPtr crypto);
+
int qemuAssignDeviceMemoryAlias(virDomainDefPtr def,
virDomainMemoryDefPtr mems);
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 2c0b29d..b1b718b 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -337,6 +337,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"drive-detect-zeroes",
"tls-creds-x509", /* 230 */
+ "cryptodev-backend-builtin",
+ "virtio-crypto",
);
@@ -1565,6 +1567,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
{ "pxb", QEMU_CAPS_DEVICE_PXB },
{ "pxb-pcie", QEMU_CAPS_DEVICE_PXB_PCIE },
{ "tls-creds-x509", QEMU_CAPS_OBJECT_TLS_CREDS_X509 },
+ { "cryptodev-backend-builtin", QEMU_CAPS_OBJECT_CRYPTO_BUILTIN },
+ { "virtio-crypto-device", QEMU_CAPS_DEVICE_VIRTIO_CRYPTO },
};
static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = {
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index affb639..98cb817 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -370,6 +370,8 @@ typedef enum {
/* 230 */
QEMU_CAPS_OBJECT_TLS_CREDS_X509, /* -object tls-creds-x509 */
+ QEMU_CAPS_OBJECT_CRYPTO_BUILTIN,
+ QEMU_CAPS_DEVICE_VIRTIO_CRYPTO,
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 3898ed7..8cf1258 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5451,6 +5451,132 @@ qemuBuildRNGCommandLine(virLogManagerPtr logManager,
}
+static char *
+qemuBuildCryptoBackendStr(virDomainCryptoDefPtr crypto,
+ virQEMUCapsPtr qemuCaps)
+{
+ const char *type = NULL;
+ char *alias = NULL;
+ char *queue = NULL;
+ char *ret = NULL;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ if (virAsprintf(&alias, "obj%s", crypto->info.alias) < 0)
+ goto cleanup;
+
+ if (crypto->queues > 1) {
+ if (virAsprintf(&queue, ",queues=%u", crypto->queues) < 0)
+ goto cleanup;
+ }
+
+ switch ((virDomainCryptoBackend)crypto->backend) {
+ case VIR_DOMAIN_CRYPTO_BACKEND_BUILTIN:
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_CRYPTO_BUILTIN)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this qemu doesn't support the crypto-backend"
+ "-builtin"));
+ goto cleanup;
+ }
+
+ type = "cryptodev-backend-builtin";
+ break;
+
+ case VIR_DOMAIN_CRYPTO_BACKEND_LAST:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("unknown crypto backend"));
+ goto cleanup;
+ }
+
+ virBufferAsprintf(&buf, "%s,id=%s%s", type, alias, queue);
+
+ ret = virBufferContentAndReset(&buf);
+
+cleanup:
+ VIR_FREE(alias);
+ return ret;
+}
+
+
+char *
+qemuBuildCryptoDevStr(const virDomainDef *def,
+ virDomainCryptoDefPtr dev,
+ virQEMUCapsPtr qemuCaps)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ if (dev->model != VIR_DOMAIN_CRYPTO_MODEL_VIRTIO ||
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_CRYPTO)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("this qemu doesn't support crypto device model '%s'"),
+ virDomainRNGModelTypeToString(dev->model));
+ goto error;
+ }
+
+ if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("this qemu only support crypto device PCI address type"));
+ goto error;
+ }
+
+ virBufferAsprintf(&buf, "virtio-crypto-pci,cryptodev=obj%s,id=%s",
+ dev->info.alias, dev->info.alias);
+
+ if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferCheckError(&buf) < 0)
+ goto error;
+
+ return virBufferContentAndReset(&buf);
+
+error:
+ virBufferFreeAndReset(&buf);
+ return NULL;
+}
+
+
+static int
+qemuBuildCryptoCommandLine(virCommandPtr cmd,
+ const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps)
+{
+ size_t i;
+
+ for (i = 0; i < def->ncryptos; i++) {
+ virDomainCryptoDefPtr crypto = def->cryptos[i];
+ char *tmp;
+
+ if (qemuAssignDeviceCryptoAlias(def, crypto)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("crypto device assign alias faile"));
+ return -1;
+ }
+
+ if (!crypto->info.alias) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("crypto device is missing alias"));
+ return -1;
+ }
+
+ /* add the Crypto backend */
+ if (!(tmp = qemuBuildCryptoBackendStr(crypto, qemuCaps)))
+ return -1;
+
+ virCommandAddArgList(cmd, "-object", tmp, NULL);
+ VIR_FREE(tmp);
+
+ /* add the device */
+ if (!(tmp = qemuBuildCryptoDevStr(def, crypto, qemuCaps)))
+ return -1;
+
+ virCommandAddArgList(cmd, "-device", tmp, NULL);
+ VIR_FREE(tmp);
+ }
+
+ return 0;
+}
+
+
static char *qemuBuildSmbiosBiosStr(virSysinfoBIOSDefPtr def)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -9312,6 +9438,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
if (qemuBuildRNGCommandLine(logManager, cmd, cfg, def, qemuCaps) < 0)
goto error;
+ if (qemuBuildCryptoCommandLine(cmd, def, qemuCaps) < 0)
+ goto error;
+
if (qemuBuildNVRAMCommandLine(cmd, def, qemuCaps) < 0)
goto error;
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index c4d0567..ec9b3ac 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -143,6 +143,10 @@ int qemuBuildRNGBackendProps(virDomainRNGDefPtr rng,
const char **type,
virJSONValuePtr *props);
+char *qemuBuildCryptoDevStr(const virDomainDef *def,
+ virDomainCryptoDefPtr dev,
+ virQEMUCapsPtr qemuCaps);
+
char *qemuBuildShmemDevStr(virDomainDefPtr def,
virDomainShmemDefPtr shmem,
virQEMUCapsPtr qemuCaps);
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index ee44d45..26e6caa 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -328,6 +328,12 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
def->rngs[i]->info.type = type;
}
+ for (i = 0; i < def->ncryptos; i++) {
+ if (def->cryptos[i]->model == VIR_DOMAIN_CRYPTO_MODEL_VIRTIO &&
+ def->cryptos[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ def->cryptos[i]->info.type = type;
+ }
+
if (type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
for (i = 0; i < def->nfss; i++) {
if (def->fss[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
@@ -1236,6 +1242,17 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
goto error;
}
+ /* VirtIO CRYPTO */
+ for (i = 0; i < def->ncryptos; i++) {
+ if (def->cryptos[i]->model != VIR_DOMAIN_CRYPTO_MODEL_VIRTIO ||
+ !virDeviceInfoPCIAddressWanted(&def->cryptos[i]->info))
+ continue;
+
+ if (virDomainPCIAddressReserveNextSlot(addrs,
+ &def->cryptos[i]->info, flags) < 0)
+ goto error;
+ }
+
/* A watchdog - check if it is a PCI device */
if (def->watchdog &&
def->watchdog->model == VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB &&
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2089359..a28a3c2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7431,6 +7431,7 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
case VIR_DOMAIN_DEVICE_SHMEM:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("live attach of device '%s' is not supported"),
@@ -7522,6 +7523,7 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("live detach of device '%s' is not supported"),
@@ -7637,6 +7639,7 @@ qemuDomainUpdateDeviceLive(virConnectPtr conn,
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("live update of device '%s' is not supported"),
@@ -7800,6 +7803,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("persistent attach of device '%s' is not supported"),
@@ -7954,6 +7958,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("persistent detach of device '%s' is not supported"),
@@ -8052,6 +8057,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
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 093aaf9..c1cfb76 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3301,6 +3301,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_LAST:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("don't know how to remove a %s device"),
virDomainDeviceTypeToString(dev->type));
--
1.8.3.1
8 years, 3 months
[libvirt] [PATCH] virutil: Provide non-linux impl for virGetFCHostNameByFabricWWN
by Michal Privoznik
Currently, there's only linux implementation for
virGetFCHostNameByFabricWWN(). Since the symbol is exported in
our private symbols we ought to have implementation for other
platforms too. This also triggers compilation error on FreeBSD:
../src/.libs/libvirt_driver_storage_impl.a(libvirt_driver_storage_impl_la-storage_backend_scsi.o): In function `createVport':
/usr/home/jenkins/libvirt-master/systems/libvirt-freebsd/build/src/../../src/storage/storage_backend_scsi.c:740: undefined reference to `virGetFCHostNameByFabricWWN'
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
Pushed under trivial and build-breaker rules.
src/util/virutil.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/util/virutil.c b/src/util/virutil.c
index da836b46d..aeaa7f98e 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -2480,6 +2480,14 @@ virGetFCHostNameByWWN(const char *sysfs_prefix ATTRIBUTE_UNUSED,
return NULL;
}
+char *
+virGetFCHostNameByFabricWWN(const char *sysfs_prefix ATTRIBUTE_UNUSED,
+ const char *fabric_wwn ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
+ return NULL;
+}
+
char *
virFindFCHostCapableVport(const char *sysfs_prefix ATTRIBUTE_UNUSED)
{
--
2.11.0
8 years, 3 months
Re: [libvirt] [Qemu-devel] [PATCH 0/5] Use non-blacklisted family/model/stepping for Haswell CPU model
by Eduardo Habkost
Oops, there are 3 actual mistakes I missed among the false
positives, below:
On Sun, Jan 08, 2017 at 11:47:21AM -0800, no-reply(a)patchew.org wrote:
[...]
> === OUTPUT BEGIN ===
> Checking PATCH 1/5: i386: Add explicit array size to x86_cpu_vendor_words2str()...
> ERROR: line over 90 characters
> #27: FILE: target/i386/cpu.c:172:
> +static void x86_cpu_vendor_words2str(char dst[static (CPUID_VENDOR_SZ + 1)], uint32_t vendor1,
False positive.
>
> ERROR: space prohibited between function name and open parenthesis '('
> #27: FILE: target/i386/cpu.c:172:
> +static void x86_cpu_vendor_words2str(char dst[static (CPUID_VENDOR_SZ + 1)], uint32_t vendor1,
False positive.
>
> total: 2 errors, 0 warnings, 8 lines checked
>
> Your patch has style problems, please review. If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
>
> Checking PATCH 2/5: i386: host_vendor_fms() helper function...
> ERROR: line over 90 characters
> #20: FILE: target/i386/cpu.c:685:
> +void host_vendor_fms(char vendor[static (CPUID_VENDOR_SZ + 1)], int *family, int *model, int *stepping)
Oops, will fix it.
>
> ERROR: space prohibited between function name and open parenthesis '('
> #20: FILE: target/i386/cpu.c:685:
> +void host_vendor_fms(char vendor[static (CPUID_VENDOR_SZ + 1)], int *family, int *model, int *stepping)
False positive.
>
> ERROR: storage class should be at the beginning of the declaration
> #20: FILE: target/i386/cpu.c:685:
> +void host_vendor_fms(char vendor[static (CPUID_VENDOR_SZ + 1)], int *family, int *model, int *stepping)
>
False positive.
> ERROR: line over 90 characters
> #57: FILE: target/i386/cpu.c:1599:
> + host_vendor_fms(host_cpudef.vendor, &host_cpudef.family, &host_cpudef.model, &host_cpudef.stepping);
Will fix it.
>
> ERROR: line over 90 characters
> #69: FILE: target/i386/cpu.h:1426:
> +void host_vendor_fms(char vendor[static (CPUID_VENDOR_SZ + 1)], int *family, int *model, int *stepping);
Will fix it.
>
> ERROR: space prohibited between function name and open parenthesis '('
> #69: FILE: target/i386/cpu.h:1426:
> +void host_vendor_fms(char vendor[static (CPUID_VENDOR_SZ + 1)], int *family, int *model, int *stepping);
False positive.
>
> ERROR: storage class should be at the beginning of the declaration
> #69: FILE: target/i386/cpu.h:1426:
> +void host_vendor_fms(char vendor[static (CPUID_VENDOR_SZ + 1)], int *family, int *model, int *stepping);
False positive.
>
> total: 7 errors, 0 warnings, 50 lines checked
>
> Your patch has style problems, please review. If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
>
> Checking PATCH 3/5: i386/kvm: Blacklist TSX on known broken hosts...
> Checking PATCH 4/5: pc: Add 2.9 machine-types...
> Checking PATCH 5/5: i386: Change stepping of Haswell to non-blacklisted value...
> === OUTPUT END ===
>
> Test command exited with code: 1
>
>
> ---
> Email generated automatically by Patchew [http://patchew.org/].
> Please send your feedback to patchew-devel(a)freelists.org
--
Eduardo
8 years, 3 months
Re: [libvirt] [Qemu-devel] [PATCH v2 0/2] Allow migration with invtsc if TSC frequency is explicitly set
by Eduardo Habkost
On Sun, Jan 08, 2017 at 09:19:49AM -0800, no-reply(a)patchew.org wrote:
> Hi,
>
> Your series failed automatic build test. Please find the testing commands and
> their output below. If you have docker installed, you can probably reproduce it
> locally.
>
> Type: series
> Message-id: 20170108171330.11129-1-ehabkost(a)redhat.com
> Subject: [Qemu-devel] [PATCH v2 0/2] Allow migration with invtsc if TSC frequency is explicitly set
Ouch. I simply removed patches 3/4 and 4/4 from the series, and
didn't notice there was a mistake in patch 1/2 corrected by patch
4/4 in v1. I will fix it and send v3, sorry for the noise.
--
Eduardo
8 years, 3 months
[libvirt] [PATCH v2 0/2] Allow migration with invtsc if TSC frequency is explicitly set
by Eduardo Habkost
This series makes QEMU accept migration if tsc-frequency is
explicitly set on configuration. As management software is
required to keep device configuration the same on migration
source or destination, explicit tsc-frequency will ensure that
either:
* The destination host has a matching TSC frequency; or
* The destination host has TSC scaling available.
Changes series v1 -> v2
=======================
* v1 series subject was:
* [PATCH 0/4] Allow migration with invtsc if there's no
frequency mismatch
* Removed patches 3/4 and 4/4, that allowed migration
if no explicit tsc-frequency was set. Implementing the check on
post_load or post_init is not enough to make migration abort,
so we will need a more complex solution to implement that
feature.
Plans for future work
=====================
1) Querying host TSC frequency/scaling capability
-------------------------------------------------
I plan to include TSC frequency/scaling information on
query-cpu-model-expansion model="host" in a future series. Then
management software will be able to automatically configure TSC
frequency when invtsc is enabled, instead of requiring the user
to configure it explicitly. While we don't implement that, invtsc
migration will be possible only if the user configures TSC
frequency manually.
2) invtsc migration with no explicit TSC frequency
--------------------------------------------------
A future series can implement migration when TSC frequency is not
specified explicitly. It will be a bit more complex because it
requires either letting the destination abort the migration, or
sending TSC frequency/scaling information from destination to
source.
---
Cc: Marcelo Tosatti <mtosatti(a)redhat.com>
Cc: "Daniel P. Berrange" <berrange(a)redhat.com>
Cc: Paolo Bonzini <pbonzini(a)redhat.com>
Cc: kvm(a)vger.kernel.org
Cc: Haozhong Zhang <haozhong.zhang(a)intel.com>
Cc: "Michael S. Tsirkin" <mst(a)redhat.com>
Cc: Igor Mammedov <imammedo(a)redhat.com>
Cc: libvir-list(a)redhat.com
Cc: Jiri Denemark <jdenemar(a)redhat.com>
Eduardo Habkost (2):
kvm: Simplify invtsc check
kvm: Allow invtsc migration if tsc-khz is set explicitly
target/i386/kvm.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
--
2.11.0.259.g40922b1
8 years, 3 months
[libvirt] Regarding Migration Code
by Anubhav Guleria
Greetings,
I was trying to understand the flow of Migration Code in libvirt and
have few doubts:
1) libvirt talks to QEMU/KVM guests via QEMU API. So overall, in
order to manage QEMU/KVM guests I can either use libvirt (or tools
based on libvirt like virsh) or QEMU monitor. Is it so?
2) Since libvirt is Hypervisor neutral so actual migration
algorithm(precopy or postcopy) is present in the hypervisor ,i.e. in
case of QEMU it should be present in QEMU code base . I was going
through the code starting from libvirt-domain api and not able to
follow after virDomainMigrateVersion3Full(.....) . Kindly help.
3) I want to determine the Migration
Time, Downtime and other resource usage.
What is the correct way to determine the same? Should I use libvirt
API or directly virsh or something else? Which is fast and efficient
way for the same?
Thanks in advance. And sorry if that was too basic
8 years, 3 months
[libvirt] [PATCH] virsh: fix a typo
by Chen Hanxiao
From: Chen Hanxiao <chenhanxiao(a)gmail.com>
s/rather then/rather than
Signed-off-by: Chen Hanxiao <chenhanxiao(a)gmail.com>
---
tools/virsh.pod | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod
index ef91223..e5c94e7 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1673,7 +1673,7 @@ periodically increased by I<auto-converge-increment>.
I<--rdma-pin-all> can be used with RDMA migration (i.e., when I<migrateuri>
starts with rdma://) to tell the hypervisor to pin all domain's memory at once
-before migration starts rather then letting it pin memory pages as needed.
+before migration starts rather than letting it pin memory pages as needed.
B<Note>: Individual hypervisors usually do not support all possible types of
migration. For example, QEMU does not support direct migration.
--
2.7.4
8 years, 3 months
[libvirt] [PATCH v2 0/4] Allow creation of vHBA by parent_wwnn/wwpn or fabric_name
by John Ferlan
v1: http://www.redhat.com/archives/libvir-list/2016-November/msg00866.html
Based on ACKs some of the v1 changes were pushed to make this series
appear shorter.
Changes since v1
- Patch 1 (formerly patch 4)
Rather than separate XML elements, use the existing <parent> and just
make attributes for wwnn, wwpn, and fabric_wwn. The parent element can
now be string text or empty.
Added checked for if either wwnn/wwpn provided, then the other is too.
- Patch 2 (formerly patch 5)
No changes, but no formal ACK either
- Patch 3 (formerly patch 10)
Rather than READ_WWN macro across two functions, I created a helper
function to read and compare the various wwn values (wwnn, wwpn, and
fabric_wwn).
John Ferlan (4):
nodedev: Add the ability to create vHBA by parent wwnn/wwpn or
fabric_wwn
conf: Add more fchost search fields for storage pool vHBA creation
util: Introduce virGetFCHostNameByFabricWWN
iscsi: Add parent wwnn/wwpn or fabric capability for createVport
docs/schemas/basictypes.rng | 15 ++++
docs/schemas/nodedev.rng | 24 +++++-
src/conf/node_device_conf.c | 126 +++++++++++++++++++++++++++++++
src/conf/node_device_conf.h | 14 ++++
src/conf/storage_conf.c | 21 +++++-
src/conf/storage_conf.h | 3 +
src/libvirt_private.syms | 3 +
src/node_device/node_device_driver.c | 13 ++++
src/storage/storage_backend_scsi.c | 21 +++++-
src/util/virutil.c | 141 ++++++++++++++++++++++++++---------
src/util/virutil.h | 4 +
11 files changed, 346 insertions(+), 39 deletions(-)
--
2.7.4
8 years, 3 months
[libvirt] [PATCH v2] libxl: define a per-domain logger.
by Cédric Bosdonnat
libxl doesn't provide a way to write one log for each domain. Thus
we need to demux the messages. If our logger doesn't know to which
domain to attribute a message, then it will write it to the default
log file.
Starting with Xen 4.9 (commit f9858025 and following), libxl will
write the domain ID in an easy to grab manner. The logger introduced
by this commit will use it to demux the libxl log messages.
Thanks to the default log file, this logger will also work with older
versions of Xen.
---
* v2: addressed Jim's comments
src/Makefile.am | 1 +
src/libxl/libxl_conf.c | 38 +-------
src/libxl/libxl_conf.h | 4 +-
src/libxl/libxl_domain.c | 4 +
src/libxl/libxl_driver.c | 2 +
src/libxl/libxl_logger.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++
src/libxl/libxl_logger.h | 39 +++++++++
7 files changed, 274 insertions(+), 37 deletions(-)
create mode 100644 src/libxl/libxl_logger.c
create mode 100644 src/libxl/libxl_logger.h
diff --git a/src/Makefile.am b/src/Makefile.am
index b71378728..e34d52345 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -851,6 +851,7 @@ LIBXL_DRIVER_SOURCES = \
libxl/libxl_capabilities.c libxl/libxl_capabilities.h \
libxl/libxl_domain.c libxl/libxl_domain.h \
libxl/libxl_driver.c libxl/libxl_driver.h \
+ libxl/libxl_logger.c libxl/libxl_logger.h \
libxl/libxl_migration.c libxl/libxl_migration.h
UML_DRIVER_SOURCES = \
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index b569ddad8..ac83b51c7 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -76,9 +76,7 @@ libxlDriverConfigDispose(void *obj)
virObjectUnref(cfg->caps);
libxl_ctx_free(cfg->ctx);
- xtl_logger_destroy(cfg->logger);
- if (cfg->logger_file)
- VIR_FORCE_FCLOSE(cfg->logger_file);
+ libxlLoggerFree(cfg->logger);
VIR_FREE(cfg->configDir);
VIR_FREE(cfg->autostartDir);
@@ -1356,8 +1354,6 @@ libxlDriverConfigPtr
libxlDriverConfigNew(void)
{
libxlDriverConfigPtr cfg;
- char *log_file = NULL;
- xentoollog_level log_level = XTL_DEBUG;
char ebuf[1024];
unsigned int free_mem;
@@ -1386,9 +1382,6 @@ libxlDriverConfigNew(void)
if (VIR_STRDUP(cfg->channelDir, LIBXL_CHANNEL_DIR) < 0)
goto error;
- if (virAsprintf(&log_file, "%s/libxl-driver.log", cfg->logDir) < 0)
- goto error;
-
if (virFileMakePath(cfg->logDir) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("failed to create log dir '%s': %s"),
@@ -1397,37 +1390,13 @@ libxlDriverConfigNew(void)
goto error;
}
- if ((cfg->logger_file = fopen(log_file, "a")) == NULL) {
- VIR_ERROR(_("Failed to create log file '%s': %s"),
- log_file, virStrerror(errno, ebuf, sizeof(ebuf)));
- goto error;
- }
- VIR_FREE(log_file);
-
- switch (virLogGetDefaultPriority()) {
- case VIR_LOG_DEBUG:
- log_level = XTL_DEBUG;
- break;
- case VIR_LOG_INFO:
- log_level = XTL_INFO;
- break;
- case VIR_LOG_WARN:
- log_level = XTL_WARN;
- break;
- case VIR_LOG_ERROR:
- log_level = XTL_ERROR;
- break;
- }
-
- cfg->logger =
- (xentoollog_logger *)xtl_createlogger_stdiostream(cfg->logger_file,
- log_level, XTL_STDIOSTREAM_SHOW_DATE);
+ cfg->logger = libxlLoggerNew(cfg->logDir, virLogGetDefaultPriority());
if (!cfg->logger) {
VIR_ERROR(_("cannot create logger for libxenlight, disabling driver"));
goto error;
}
- if (libxl_ctx_alloc(&cfg->ctx, LIBXL_VERSION, 0, cfg->logger)) {
+ if (libxl_ctx_alloc(&cfg->ctx, LIBXL_VERSION, 0, (xentoollog_logger *)cfg->logger)) {
VIR_ERROR(_("cannot initialize libxenlight context, probably not "
"running in a Xen Dom0, disabling driver"));
goto error;
@@ -1478,7 +1447,6 @@ libxlDriverConfigNew(void)
return cfg;
error:
- VIR_FREE(log_file);
virObjectUnref(cfg);
return NULL;
}
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index 851f3afb4..69d78851a 100644
--- a/src/libxl/libxl_conf.h
+++ b/src/libxl/libxl_conf.h
@@ -41,6 +41,7 @@
# include "locking/lock_manager.h"
# include "virfirmware.h"
# include "libxl_capabilities.h"
+# include "libxl_logger.h"
# define LIBXL_DRIVER_NAME "xenlight"
# define LIBXL_VNC_PORT_MIN 5900
@@ -74,8 +75,7 @@ struct _libxlDriverConfig {
unsigned int version;
/* log stream for driver-wide libxl ctx */
- FILE *logger_file;
- xentoollog_logger *logger;
+ libxlLoggerPtr logger;
/* libxl ctx for driver wide ops; getVersion, getNodeInfo, ... */
libxl_ctx *ctx;
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 5cde576ef..3bc468f61 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -809,6 +809,8 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
VIR_FREE(xml);
}
+ libxlLoggerCloseFile(cfg->logger, vm->def->id);
+
virDomainObjRemoveTransientDef(vm);
virObjectUnref(cfg);
}
@@ -1291,6 +1293,8 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
*/
vm->def->id = domid;
+ libxlLoggerOpenFile(cfg->logger, domid, vm->def->name);
+
/* Always enable domain death events */
if (libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, &priv->deathW))
goto destroy_dom;
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 7e5d9b69e..6a4ecddef 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -406,6 +406,8 @@ libxlReconnectDomain(virDomainObjPtr vm,
/* Update domid in case it changed (e.g. reboot) while we were gone? */
vm->def->id = d_info.domid;
+ libxlLoggerOpenFile(cfg->logger, vm->def->id, vm->def->name);
+
/* Update hostdev state */
if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
vm->def, hostdev_flags) < 0)
diff --git a/src/libxl/libxl_logger.c b/src/libxl/libxl_logger.c
new file mode 100644
index 000000000..d8ccdd852
--- /dev/null
+++ b/src/libxl/libxl_logger.c
@@ -0,0 +1,223 @@
+/*
+ * libxl_logger.c: libxl logger implementation
+ *
+ * Copyright (c) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Cédric Bosdonnat <cbosdonnat(a)suse.com>
+ */
+#include <config.h>
+
+#include <string.h>
+#include <libxl.h>
+
+#include "internal.h"
+#include "libxl_logger.h"
+#include "util/viralloc.h"
+#include "util/virerror.h"
+#include "util/virfile.h"
+#include "util/virhash.h"
+#include "util/virstring.h"
+#include "util/virtime.h"
+
+#define VIR_FROM_THIS VIR_FROM_LIBXL
+
+VIR_LOG_INIT("libxl.libxl_logger");
+
+typedef struct xentoollog_logger_libvirt xentoollog_logger_libvirt;
+
+struct xentoollog_logger_libvirt {
+ xentoollog_logger vtable;
+ xentoollog_level minLevel;
+ const char *logDir;
+
+ /* map storing the opened fds: "domid" -> FILE* */
+ virHashTablePtr files;
+ FILE *defaultLogFile;
+};
+
+static void
+libxlLoggerFileFree(void *payload, const void *key ATTRIBUTE_UNUSED)
+{
+ FILE *file = payload;
+ VIR_FORCE_FCLOSE(file);
+ file = NULL;
+}
+
+ATTRIBUTE_FMT_PRINTF(5, 0) static void
+libvirt_vmessage(xentoollog_logger *logger_in,
+ xentoollog_level level,
+ int errnoval,
+ const char *context,
+ const char *format,
+ va_list args)
+{
+ xentoollog_logger_libvirt *lg = (xentoollog_logger_libvirt *)logger_in;
+ FILE *logFile = lg->defaultLogFile;
+ char timestamp[VIR_TIME_STRING_BUFLEN];
+ char *message = NULL;
+ char *start, *end;
+ char ebuf[1024];
+
+ VIR_DEBUG("libvirt_vmessage: context='%s' format='%s'", context, format);
+
+ if (level < lg->minLevel)
+ return;
+
+ if (virVasprintf(&message, format, args) < 0)
+ return;
+
+ /* Should we print to a domain-specific log file? */
+ if ((start = strstr(message, ": Domain ")) &&
+ (end = strstr(start + 9, ":"))) {
+ FILE *domainLogFile;
+
+ VIR_DEBUG("Found domain log message");
+
+ start = start + 9;
+ *end = '\0';
+
+ domainLogFile = virHashLookup(lg->files, start);
+ if (domainLogFile)
+ logFile = domainLogFile;
+
+ *end = ':';
+ }
+
+ /* Do the actual print to the log file */
+ if (virTimeStringNowRaw(timestamp) < 0)
+ timestamp[0] = '\0';
+
+ fprintf(logFile, "%s: ", timestamp);
+ if (context)
+ fprintf(logFile, "%s: ", context);
+
+ fprintf(logFile, "%s", message);
+
+ if (errnoval >= 0)
+ fprintf(logFile, ": %s", virStrerror(errnoval, ebuf, sizeof(ebuf)));
+
+ fputc('\n', logFile);
+ fflush(logFile);
+
+ VIR_FREE(message);
+}
+
+static void
+libvirt_progress(xentoollog_logger *logger_in ATTRIBUTE_UNUSED,
+ const char *context ATTRIBUTE_UNUSED,
+ const char *doingwhat ATTRIBUTE_UNUSED,
+ int percent ATTRIBUTE_UNUSED,
+ unsigned long done ATTRIBUTE_UNUSED,
+ unsigned long total ATTRIBUTE_UNUSED)
+{
+ /* This function purposedly does nothing: it's no logging info */
+}
+
+static void
+libvirt_destroy(xentoollog_logger *logger_in)
+{
+ xentoollog_logger_libvirt *lg = (xentoollog_logger_libvirt*)logger_in;
+ VIR_FREE(lg);
+}
+
+
+libxlLoggerPtr libxlLoggerNew(const char *logDir,
+ virLogPriority minLevel)
+{
+ xentoollog_logger_libvirt logger;
+ libxlLoggerPtr logger_out = NULL;
+ char *path = NULL;
+
+ switch (minLevel) {
+ case VIR_LOG_DEBUG:
+ logger.minLevel = XTL_DEBUG;
+ break;
+ case VIR_LOG_INFO:
+ logger.minLevel = XTL_INFO;
+ break;
+ case VIR_LOG_WARN:
+ logger.minLevel = XTL_WARN;
+ break;
+ case VIR_LOG_ERROR:
+ logger.minLevel = XTL_ERROR;
+ break;
+ }
+ logger.logDir = logDir;
+
+ if ((logger.files = virHashCreate(3, libxlLoggerFileFree)) == NULL)
+ return NULL;
+
+ if (virAsprintf(&path, "%s/libxl-driver.log", logDir) < 0)
+ goto error;
+
+ if ((logger.defaultLogFile = fopen(path, "a")) == NULL)
+ goto error;
+
+ logger_out = XTL_NEW_LOGGER(libvirt, logger);
+
+ cleanup:
+ VIR_FREE(path);
+ return logger_out;
+
+ error:
+ virHashFree(logger.files);
+ goto cleanup;
+}
+
+void libxlLoggerFree(libxlLoggerPtr logger)
+{
+ xentoollog_logger *xtl_logger = (xentoollog_logger*)logger;
+ if (logger->defaultLogFile)
+ VIR_FORCE_FCLOSE(logger->defaultLogFile);
+ virHashFree(logger->files);
+ xtl_logger_destroy(xtl_logger);
+}
+
+void libxlLoggerOpenFile(libxlLoggerPtr logger, int id, const char *name)
+{
+ char *path = NULL;
+ FILE *logFile = NULL;
+ char *domidstr = NULL;
+ char ebuf[1024];
+
+ if (virAsprintf(&path, "%s/%s.log", logger->logDir, name) < 0 ||
+ virAsprintf(&domidstr, "%d", id) < 0)
+ goto cleanup;
+
+ if (!(logFile = fopen(path, "a"))) {
+ VIR_WARN("Failed to open log file %s: %s",
+ path, virStrerror(errno, ebuf, sizeof(ebuf)));
+ goto cleanup;
+ }
+ ignore_value(virHashAddEntry(logger->files, domidstr, logFile));
+
+ cleanup:
+ VIR_FREE(path);
+ VIR_FREE(domidstr);
+}
+
+void libxlLoggerCloseFile(libxlLoggerPtr logger, int id)
+{
+ char *domidstr = NULL;
+ if (virAsprintf(&domidstr, "%d", id) < 0)
+ return;
+
+ ignore_value(virHashRemoveEntry(logger->files, domidstr));
+
+ VIR_FREE(domidstr);
+}
diff --git a/src/libxl/libxl_logger.h b/src/libxl/libxl_logger.h
new file mode 100644
index 000000000..88c2868eb
--- /dev/null
+++ b/src/libxl/libxl_logger.h
@@ -0,0 +1,39 @@
+/*
+ * libxl_logger.h: libxl logger implementation
+ *
+ * Copyright (c) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Cédric Bosdonnat <cbosdonnat(a)suse.com>
+ */
+
+#ifndef __LIBXL_LOGGER_H
+# define __LIBXL_LOGGER_H
+
+# include "util/virlog.h"
+
+typedef struct xentoollog_logger_libvirt libxlLogger;
+typedef libxlLogger *libxlLoggerPtr;
+
+libxlLoggerPtr libxlLoggerNew(const char *logDir,
+ virLogPriority minLevel);
+void libxlLoggerFree(libxlLoggerPtr logger);
+
+void libxlLoggerOpenFile(libxlLoggerPtr logger, int id, const char *name);
+void libxlLoggerCloseFile(libxlLoggerPtr logger, int id);
+
+#endif /* __LIBXL_LOGGER_H */
--
2.11.0
8 years, 3 months