Re-translating a disk type='volume' definition from a storage pool is not a good idea in cases when the volume might have changed or we might not have access to the storage driver. Specific cases are if a storage pool is not activated on daemon restart, then re-connecting to a VM fails, or if the virt-aa-helper program tries to setup labelling for apparmor. Add a new flag which will preserve the translated data in the definition. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- src/conf/domain_conf.c | 69 ++++++++++++++++++++++++++++++------------ src/conf/domain_conf.h | 4 +++ 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e128457b00..9b636215e9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7006,7 +7006,8 @@ virDomainLeaseDefParseXML(xmlNodePtr node, } static virStorageSourcePoolDef * -virDomainDiskSourcePoolDefParse(xmlNodePtr node) +virDomainDiskSourcePoolDefParse(xmlNodePtr node, + virDomainDefParseFlags flags) { g_autoptr(virStorageSourcePoolDef) source = g_new0(virStorageSourcePoolDef, 1); @@ -7029,6 +7030,14 @@ virDomainDiskSourcePoolDefParse(xmlNodePtr node) &source->mode) < 0) return NULL; + if (flags & VIR_DOMAIN_DEF_PARSE_VOLUME_TRANSLATED) { + if (virXMLPropEnum(node, "actualType", + virStorageTypeFromString, + VIR_XML_PROP_NONZERO, + &source->actualtype) < 0) + return NULL; + } + return g_steal_pointer(&source); } @@ -7448,12 +7457,22 @@ virDomainStorageSourceParse(xmlNodePtr node, unsigned int flags, virDomainXMLOption *xmlopt) { + virStorageType actualType = src->type; VIR_XPATH_NODE_AUTORESTORE(ctxt) xmlNodePtr tmp; ctxt->node = node; - switch (src->type) { + if (src->type == VIR_STORAGE_TYPE_VOLUME) { + if (!(src->srcpool = virDomainDiskSourcePoolDefParse(node, flags))) + return -1; + + /* If requested we need to also parse the translated volume runtime data */ + if (flags & VIR_DOMAIN_DEF_PARSE_VOLUME_TRANSLATED) + actualType = virStorageSourceGetActualType(src); + } + + switch (actualType) { case VIR_STORAGE_TYPE_FILE: src->path = virXMLPropString(node, "file"); src->fdgroup = virXMLPropString(node, "fdgroup"); @@ -7469,8 +7488,7 @@ virDomainStorageSourceParse(xmlNodePtr node, return -1; break; case VIR_STORAGE_TYPE_VOLUME: - if (!(src->srcpool = virDomainDiskSourcePoolDefParse(node))) - return -1; + /* parsed above */ break; case VIR_STORAGE_TYPE_NVME: if (virDomainDiskSourceNVMeParse(node, ctxt, src) < 0) @@ -7488,7 +7506,7 @@ virDomainStorageSourceParse(xmlNodePtr node, case VIR_STORAGE_TYPE_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected disk type %1$s"), - virStorageTypeToString(src->type)); + virStorageTypeToString(actualType)); return -1; } @@ -8647,7 +8665,7 @@ virDomainFSDefParseXML(virDomainXMLOption *xmlopt, units = virXMLPropString(source_node, "units"); } else if (def->type == VIR_DOMAIN_FS_TYPE_VOLUME) { def->src->type = VIR_STORAGE_TYPE_VOLUME; - if (!(def->src->srcpool = virDomainDiskSourcePoolDefParse(source_node))) + if (!(def->src->srcpool = virDomainDiskSourcePoolDefParse(source_node, flags))) goto error; } } @@ -22335,10 +22353,28 @@ virDomainDiskSourceFormat(virBuffer *buf, bool skipEnc, virDomainXMLOption *xmlopt) { + virStorageType actualType = src->type; g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); - switch (src->type) { + if (src->type == VIR_STORAGE_TYPE_VOLUME) { + if (src->srcpool) { + virBufferEscapeString(&attrBuf, " pool='%s'", src->srcpool->pool); + virBufferEscapeString(&attrBuf, " volume='%s'", src->srcpool->volume); + if (src->srcpool->mode) + virBufferAsprintf(&attrBuf, " mode='%s'", + virStorageSourcePoolModeTypeToString(src->srcpool->mode)); + } + + if (flags & VIR_DOMAIN_DEF_FORMAT_VOLUME_TRANSLATED && + src->srcpool->actualtype != VIR_STORAGE_TYPE_NONE) { + virBufferAsprintf(&attrBuf, " actualType='%s'", + virStorageTypeToString(src->srcpool->actualtype)); + actualType = virStorageSourceGetActualType(src); + } + } + + switch (actualType) { case VIR_STORAGE_TYPE_FILE: virBufferEscapeString(&attrBuf, " file='%s'", src->path); virBufferEscapeString(&attrBuf, " fdgroup='%s'", src->fdgroup); @@ -22357,15 +22393,7 @@ virDomainDiskSourceFormat(virBuffer *buf, break; case VIR_STORAGE_TYPE_VOLUME: - if (src->srcpool) { - virBufferEscapeString(&attrBuf, " pool='%s'", src->srcpool->pool); - virBufferEscapeString(&attrBuf, " volume='%s'", - src->srcpool->volume); - if (src->srcpool->mode) - virBufferAsprintf(&attrBuf, " mode='%s'", - virStorageSourcePoolModeTypeToString(src->srcpool->mode)); - } - + /* formatted above */ break; case VIR_STORAGE_TYPE_NVME: @@ -22383,13 +22411,13 @@ virDomainDiskSourceFormat(virBuffer *buf, case VIR_STORAGE_TYPE_NONE: case VIR_STORAGE_TYPE_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected disk type %1$d"), src->type); + _("unexpected disk type %1$d"), actualType); return -1; } virDomainDiskSourceFormatSlices(&childBuf, src); - if (src->type != VIR_STORAGE_TYPE_NETWORK) + if (actualType != VIR_STORAGE_TYPE_NETWORK) virDomainSourceDefFormatSeclabel(&childBuf, src->nseclabels, src->seclabels, flags); @@ -22408,7 +22436,7 @@ virDomainDiskSourceFormat(virBuffer *buf, if (src->pr) virStoragePRDefFormat(&childBuf, src->pr, flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE); - if (policy && src->type != VIR_STORAGE_TYPE_NETWORK) + if (policy && actualType != VIR_STORAGE_TYPE_NETWORK) virBufferEscapeString(&attrBuf, " startupPolicy='%s'", virDomainStartupPolicyTypeToString(policy)); @@ -27512,7 +27540,8 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, VIR_DOMAIN_DEF_FORMAT_STATUS | VIR_DOMAIN_DEF_FORMAT_ACTUAL_NET | VIR_DOMAIN_DEF_FORMAT_PCI_ORIG_STATES | - VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST, + VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST | + VIR_DOMAIN_DEF_FORMAT_VOLUME_TRANSLATED, -1); if (!(type = virDomainVirtTypeToString(def->virtType))) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 16289789c2..9e6dd930fa 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3734,6 +3734,8 @@ typedef enum { * post parse callbacks before starting. Failure of the post parse callback * is recorded as def->postParseFail */ VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL = 1 << 11, + /* Parse the translated disk type='volume' data if present */ + VIR_DOMAIN_DEF_PARSE_VOLUME_TRANSLATED = 1 << 12, } virDomainDefParseFlags; typedef enum { @@ -3749,6 +3751,8 @@ typedef enum { VIR_DOMAIN_DEF_FORMAT_ALLOW_ROM = 1 << 6, VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT = 1 << 7, VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST = 1 << 8, + /* format disk type='volume' translated data if present */ + VIR_DOMAIN_DEF_FORMAT_VOLUME_TRANSLATED = 1 << 9, } virDomainDefFormatFlags; /* Use these flags to skip specific domain ABI consistency checks done -- 2.41.0