[libvirt] [PATCH v5 00/16] Use secret objects to pass iSCSI passwords

v4: https://www.redhat.com/archives/libvir-list/2017-September/msg00944.html Changes since v4 are minor - mostly to change from 3.8.0 to 3.9.0... Update the news.xml once <auth> is allowed for <source>. Add a news.xml to describe the bug fix. Beyond that - merge changes up to git commit '5d7659027'. I ran the changes through my Coverity checker too. Repeated from the cover of v4: v3: https://www.redhat.com/archives/libvir-list/2017-September/msg00881.html Difference with v3: Add patch 3 to perform virStorageSourceCopy for qemu and storage source private data. Adjust the move encinfo from private disk to private disk src to handle the Copy for the @encinfo too Repeated from cover of v3 (although perhaps just too much information for the eyes to consume): v2: https://www.redhat.com/archives/libvir-list/2017-September/msg00466.html Changes since v2: * Former Patch 1 & 2 were pushed * New Patch 1 is former Patches 3 and parts of 4 combined appropriately -> Allow <auth> under <disk> or <source> - keep track of where it was found so that format prints in the right place -> Cleaned up the tests and new xml/args files * Patch 2 is part of the former patch 6 - just the new _virStorageSource * Patch 3 is new - to introduced an allocator for domain_conf to create a _virStorageSource * Patch 4 is new - as stated found that the @diskPriv->encinfo wasn't cleaned up properly * Patch 5 is the rest of the former patch 6 * Patch 6 is the former patch 7 with some minor adjustments to allow <encryption> to follow <auth> and be both child of <disk> and <source> * Patch 7 is the former patch 10 with minor change to perform free of encinfo properly (e.g. from patch 4) * Patch 8 is former patch 5 and 9 combined * Patch 9 is new - to use the virStorageSource for iscsisrc instead of just three fields we wanted * Patch 10 is new to alter the existing hostdevPriv to use diskSrcPriv * Patch 11 is new to remove the hostdevPriv as it's no longer necesary * Patch 12 is new to split up a change in qemuBuildSCSIiSCSIHostdevDrvStr from the last patch * Patch 13 is the former patch 13 * Patch 14 is altered to accomodate the hostdev usage if virStorageSource for iscsisrc->src instead of that hack that was there before. John Ferlan (16): conf: Add/Allow parsing the auth in the disk source qemu: Introduce privateData for _virStorageSource qemu: Introduce qemuDomainStorageSourceCopy conf: Introduce virDomainDiskStorageSourceNew qemu: Add missing encinfo cleanup qemu: Relocate qemuDomainSecretInfoPtr from disk private conf: Add/Allow parsing the encryption in the disk source qemu: Move encinfo from private disk to private disk src docs: Add news article regarding auth/encryption placement conf,qemu: Replace iscsisrc fields with virStorageSourcePtr qemu: Use private disksrc for iscsi instead of private hostdev qemu: Remove private hostdev qemu: Refactor qemuBuildSCSIiSCSIHostdevDrvStr slightly qemu: Get capabilities to use iscsi password-secret argument qemu: Use secret objects to pass iSCSI passwords docs: Add news article to describe iSCSI usage of secret object docs/formatdomain.html.in | 82 ++++--- docs/news.xml | 23 ++ docs/schemas/domaincommon.rng | 48 +++- src/conf/domain_conf.c | 255 ++++++++++++++++----- src/conf/domain_conf.h | 10 +- src/lxc/lxc_native.c | 2 +- src/qemu/qemu_block.c | 64 +++++- src/qemu/qemu_blockjob.c | 2 +- src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 84 +++++-- src/qemu/qemu_command.h | 3 +- src/qemu/qemu_domain.c | 162 +++++++++---- src/qemu/qemu_domain.h | 37 ++- src/qemu/qemu_driver.c | 8 +- src/qemu/qemu_hotplug.c | 71 +++++- src/qemu/qemu_parse_command.c | 4 +- src/util/virstoragefile.c | 2 + src/util/virstoragefile.h | 5 + src/vbox/vbox_common.c | 2 +- src/xenconfig/xen_common.c | 2 +- src/xenconfig/xen_sxpr.c | 2 +- src/xenconfig/xen_xl.c | 2 +- .../qemuargv2xml-disk-drive-network-rbd-auth.xml | 6 +- tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 + ...xml2argv-disk-drive-network-iscsi-auth-AES.args | 41 ++++ ...uxml2argv-disk-drive-network-iscsi-auth-AES.xml | 43 ++++ ...ml2argv-disk-drive-network-source-auth-both.xml | 51 +++++ ...emuxml2argv-disk-drive-network-source-auth.args | 32 +++ ...qemuxml2argv-disk-drive-network-source-auth.xml | 45 ++++ ...ml2argv-hostdev-scsi-virtio-iscsi-auth-AES.args | 45 ++++ ...xml2argv-hostdev-scsi-virtio-iscsi-auth-AES.xml | 48 ++++ .../qemuxml2argv-luks-disks-source-both.xml | 40 ++++ .../qemuxml2argv-luks-disks-source.args | 62 +++++ .../qemuxml2argv-luks-disks-source.xml | 81 +++++++ tests/qemuxml2argvtest.c | 14 ++ ...muxml2xmlout-disk-drive-network-source-auth.xml | 49 ++++ .../qemuxml2xmlout-luks-disks-source.xml | 84 +++++++ .../qemuxml2xmlout-luks-disks.xml | 46 +++- tests/qemuxml2xmltest.c | 2 + tests/virhostdevtest.c | 2 +- tests/virstoragetest.c | 6 + 46 files changed, 1356 insertions(+), 219 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth-both.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source-both.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-network-source-auth.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks-source.xml mode change 120000 => 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml -- 2.13.6

Since the virStorageAuthDefPtr auth; is a member of _virStorageSource it really should be allowed to be a subelement of the disk <source> for the RBD and iSCSI prototcols. That way we can set up to allow the <auth> element to be formatted within the disk source. Since we've allowed the <auth> to be a child of <disk>, we'll need to keep track of how it was read so that when writing out we'll know whether to format as child of <disk> or <source>. For the argv2xml parsing, let's format under <source> as a preference. Do not allow <auth> to be both a child of <disk> and <source>. Modify the qemuxml2argvtest to add a parse failure when there is an <auth> as a child of <disk> *and* an <auth> as a child of <source>. Add tests to validate that if the <auth> was found in <source>, then the resulting xml2xml and xml2arg works just fine. The two new .args file are exact copies of the non "-source" version of the file. The virschematest will read the new test files and validate from a RNG viewpoint things are fine Update the virstoragefile, virstoragetest, and args2xml file to show the "preference" to place <auth> as a child of <source>. Signed-off-by: John Ferlan <jferlan@redhat.com> --- docs/formatdomain.html.in | 67 +++++++++++++--------- docs/schemas/domaincommon.rng | 18 +++++- src/conf/domain_conf.c | 67 +++++++++++++++++++++- src/util/virstoragefile.c | 1 + src/util/virstoragefile.h | 1 + .../qemuargv2xml-disk-drive-network-rbd-auth.xml | 6 +- ...ml2argv-disk-drive-network-source-auth-both.xml | 51 ++++++++++++++++ ...emuxml2argv-disk-drive-network-source-auth.args | 32 +++++++++++ ...qemuxml2argv-disk-drive-network-source-auth.xml | 45 +++++++++++++++ tests/qemuxml2argvtest.c | 2 + ...muxml2xmlout-disk-drive-network-source-auth.xml | 49 ++++++++++++++++ tests/qemuxml2xmltest.c | 1 + tests/virstoragetest.c | 6 ++ 13 files changed, 311 insertions(+), 35 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth-both.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-network-source-auth.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c0e3c22213..74f2090d06 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2297,11 +2297,11 @@ <host name="hostname" port="7000"/> <snapshot name="snapname"/> <config file="/path/to/file"/> + <auth username='myuser'> + <secret type='ceph' usage='mypassid'/> + </auth> </source> <target dev="hdc" bus="ide"/> - <auth username='myuser'> - <secret type='ceph' usage='mypassid'/> - </auth> </disk> <disk type='block' device='cdrom'> <driver name='qemu' type='raw'/> @@ -2370,20 +2370,20 @@ <driver name='qemu' type='raw'/> <source protocol='iscsi' name='iqn.2013-07.com.example:iscsi-nopool/2'> <host name='example.com' port='3260'/> + <auth username='myuser'> + <secret type='iscsi' usage='libvirtiscsi'/> + </auth> </source> - <auth username='myuser'> - <secret type='iscsi' usage='libvirtiscsi'/> - </auth> <target dev='vda' bus='virtio'/> </disk> <disk type='network' device='lun'> <driver name='qemu' type='raw'/> <source protocol='iscsi' name='iqn.2013-07.com.example:iscsi-nopool/1'> <host name='example.com' port='3260'/> + <auth username='myuser'> + <secret type='iscsi' usage='libvirtiscsi'/> + </auth> </source> - <auth username='myuser'> - <secret type='iscsi' usage='libvirtiscsi'/> - </auth> <target dev='sdb' bus='scsi'/> </disk> <disk type='volume' device='disk'> @@ -2683,6 +2683,28 @@ protocol. Supported for 'rbd' <span class="since">since 1.2.11 (QEMU only).</span> </dd> + <dt><code>auth</code></dt> + <dd><span class="since">Since libvirt 3.9.0</span>, the + <code>auth</code> element is supported for a disk + <code>type</code> "network" that is using a <code>source</code> + element with the <code>protocol</code> attributes "rbd" or "iscsi". + If present, the <code>auth</code> element provides the + authentication credentials needed to access the source. It + includes a mandatory attribute <code>username</code>, which + identifies the username to use during authentication, as well + as a sub-element <code>secret</code> with mandatory + attribute <code>type</code>, to tie back to + a <a href="formatsecret.html">libvirt secret object</a> that + holds the actual password or other credentials (the domain XML + intentionally does not expose the password, only the reference + to the object that does manage the password). + Known secret types are "ceph" for Ceph RBD network sources and + "iscsi" for CHAP authentication of iSCSI targets. + Both will require either a <code>uuid</code> attribute + with the UUID of the secret object or a <code>usage</code> + attribute matching the key that was specified in the + secret object. + </dd> </dl> <p> @@ -3156,25 +3178,14 @@ are available, each defaulting to 0. </dd> <dt><code>auth</code></dt> - <dd>The <code>auth</code> element is supported for a disk - <code>type</code> "network" that is using a <code>source</code> - element with the <code>protocol</code> attributes "rbd" or "iscsi". - If present, the <code>auth</code> element provides the - authentication credentials needed to access the source. It - includes a mandatory attribute <code>username</code>, which - identifies the username to use during authentication, as well - as a sub-element <code>secret</code> with mandatory - attribute <code>type</code>, to tie back to - a <a href="formatsecret.html">libvirt secret object</a> that - holds the actual password or other credentials (the domain XML - intentionally does not expose the password, only the reference - to the object that does manage the password). - Known secret types are "ceph" for Ceph RBD network sources and - "iscsi" for CHAP authentication of iSCSI targets. - Both will require either a <code>uuid</code> attribute - with the UUID of the secret object or a <code>usage</code> - attribute matching the key that was specified in the - secret object. <span class="since">libvirt 0.9.7</span> + <dd>Starting with <span class="since">libvirt 3.9.0</span> the + <code>auth</code> element is preferred to be a sub-element of + the <code>source</code> element. The element is still read and + managed as a <code>disk</code> sub-element. It is invalid to use + <code>auth</code> as both a sub-element of <code>disk</code> + and <code>source</code>. The <code>auth</code> element was + introduced as a <code>disk</code> sub-element in + <span class="since">libvirt 0.9.7.</span> </dd> <dt><code>geometry</code></dt> <dd>The optional <code>geometry</code> element provides the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 4dbda6932d..895af55da1 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1578,11 +1578,27 @@ <empty/> </element> </optional> + <optional> + <ref name="diskAuth"/> + </optional> <empty/> </interleave> </element> </define> + <define name="diskSourceNetworkProtocolISCSI"> + <element name="source"> + <attribute name="protocol"> + <value>iscsi</value> + </attribute> + <attribute name="name"/> + <ref name="diskSourceNetworkHost"/> + <optional> + <ref name="diskAuth"/> + </optional> + </element> + </define> + <define name="diskSourceNetworkProtocolHTTP"> <element name="source"> <attribute name="protocol"> @@ -1601,7 +1617,6 @@ <attribute name="protocol"> <choice> <value>sheepdog</value> - <value>iscsi</value> <value>ftp</value> <value>ftps</value> <value>tftp</value> @@ -1661,6 +1676,7 @@ <ref name="diskSourceNetworkProtocolNBD"/> <ref name="diskSourceNetworkProtocolGluster"/> <ref name="diskSourceNetworkProtocolRBD"/> + <ref name="diskSourceNetworkProtocolISCSI"/> <ref name="diskSourceNetworkProtocolHTTP"/> <ref name="diskSourceNetworkProtocolSimple"/> <ref name="diskSourceNetworkProtocolVxHS"/> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 54be9028d7..91d554c3ee 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8208,6 +8208,29 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node, } +static int +virDomainDiskSourceAuthParse(xmlNodePtr node, + virStorageAuthDefPtr *authdefsrc) +{ + xmlNodePtr child; + virStorageAuthDefPtr authdef; + + for (child = node->children; child; child = child->next) { + if (child->type == XML_ELEMENT_NODE && + virXMLNodeNameEqual(child, "auth")) { + + if (!(authdef = virStorageAuthDefParse(node->doc, child))) + return -1; + + *authdefsrc = authdef; + return 0; + } + } + + return 0; +} + + int virDomainDiskSourceParse(xmlNodePtr node, xmlXPathContextPtr ctxt, @@ -8245,6 +8268,9 @@ virDomainDiskSourceParse(xmlNodePtr node, goto cleanup; } + if (virDomainDiskSourceAuthParse(node, &src->auth) < 0) + goto cleanup; + /* People sometimes pass a bogus '' source path when they mean to omit the * source element completely (e.g. CDROM without media). This is just a * little compatibility check to help those broken apps */ @@ -8881,6 +8907,19 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, if (virDomainDiskSourceParse(cur, ctxt, def->src, flags) < 0) goto error; + /* If we've already found an <auth> as a child of <disk> and + * we find one as a child of <source>, then force an error to + * avoid ambiguity */ + if (authdef && def->src->auth) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("an <auth> definition already found for " + "the <disk> definition")); + goto error; + } + + if (def->src->auth) + def->src->authDefined = true; + source = true; startupPolicy = virXMLPropString(cur, "startupPolicy"); @@ -8938,6 +8977,15 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, goto error; } else if (!authdef && virXMLNodeNameEqual(cur, "auth")) { + /* If we've already parsed <source> and found an <auth> child, + * then generate an error to avoid ambiguity */ + if (def->src->authDefined) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("an <auth> definition already found for " + "disk source")); + goto error; + } + if (!(authdef = virStorageAuthDefParse(node->doc, cur))) goto error; } else if (virXMLNodeNameEqual(cur, "iotune")) { @@ -9173,8 +9221,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, def->dst = target; target = NULL; - def->src->auth = authdef; - authdef = NULL; + if (authdef) + VIR_STEAL_PTR(def->src->auth, authdef); def->src->encryption = encryption; encryption = NULL; def->domain_name = domain_name; @@ -21873,6 +21921,17 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf, goto error; } + /* Storage Source formatting will not carry through the blunder + * that disk source formatting had at one time to format the + * <auth> for a volume source type. The <auth> information is + * kept in the storage pool and would be overwritten anyway. + * So avoid formatting it for volumes. */ + if (src->auth && src->authDefined && + src->type != VIR_STORAGE_TYPE_VOLUME) { + if (virStorageAuthDefFormat(&childBuf, src->auth) < 0) + goto error; + } + if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) < 0) goto error; } @@ -22060,7 +22119,9 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferAddLit(buf, "/>\n"); } - if (def->src->auth) { + /* Format as child of <disk> if defined there; otherwise, + * if defined as child of <source>, then format later */ + if (def->src->auth && !def->src->authDefined) { if (virStorageAuthDefFormat(buf, def->src->auth) < 0) return -1; } diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index dd44949403..727ec52856 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -2558,6 +2558,7 @@ virStorageSourceParseRBDColonString(const char *rbdstr, virSecretUsageTypeToString(VIR_SECRET_USAGE_TYPE_CEPH)) < 0) goto error; src->auth = authdef; + src->authDefined = true; authdef = NULL; /* Cannot formulate a secretType (eg, usage or uuid) given diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 74dee10f2f..c8bb1066fe 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -238,6 +238,7 @@ struct _virStorageSource { virStorageNetHostDefPtr hosts; virStorageSourcePoolDefPtr srcpool; virStorageAuthDefPtr auth; + bool authDefined; virStorageEncryptionPtr encryption; char *driverName; diff --git a/tests/qemuargv2xmldata/qemuargv2xml-disk-drive-network-rbd-auth.xml b/tests/qemuargv2xmldata/qemuargv2xml-disk-drive-network-rbd-auth.xml index 3f30296c0b..e1326b925c 100644 --- a/tests/qemuargv2xmldata/qemuargv2xml-disk-drive-network-rbd-auth.xml +++ b/tests/qemuargv2xmldata/qemuargv2xml-disk-drive-network-rbd-auth.xml @@ -22,13 +22,13 @@ </disk> <disk type='network' device='disk'> <driver name='qemu' type='raw'/> - <auth username='myname'> - <secret type='ceph' usage='qemuargv2xml_usage'/> - </auth> <source protocol='rbd' name='pool/image'> <host name='mon1.example.org' port='6321'/> <host name='mon2.example.org' port='6322'/> <host name='mon3.example.org' port='6322'/> + <auth username='myname'> + <secret type='ceph' usage='qemuargv2xml_usage'/> + </auth> </source> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth-both.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth-both.xml new file mode 100644 index 0000000000..fed75ad70e --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth-both.xml @@ -0,0 +1,51 @@ +<domain type='qemu'> + <name>QEMUGuest1</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='i686' 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> + <emulator>/usr/bin/qemu-system-i686</emulator> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <auth username='myname'> + <secret type='iscsi' usage='mycluster_myname'/> + </auth> + <source protocol='iscsi' name='iqn.1992-01.com.example:storage/1'> + <host name='example.org' port='6000'/> + <auth username='myname'> + <secret type='iscsi' usage='mycluster_myname'/> + </auth> + </source> + <target dev='vda' bus='virtio'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <auth username='myname'> + <secret type='ceph' usage='mycluster_myname'/> + </auth> + <source protocol='rbd' name='pool/image'> + <host name='mon1.example.org' port='6321'/> + <host name='mon2.example.org' port='6322'/> + <host name='mon3.example.org' port='6322'/> + <auth username='myname'> + <secret type='ceph' usage='mycluster_myname'/> + </auth> + </source> + <target dev='vdb' bus='virtio'/> + </disk> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.args new file mode 100644 index 0000000000..23b1490eec --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.args @@ -0,0 +1,32 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-i686 \ +-name QEMUGuest1 \ +-S \ +-M pc \ +-m 214 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-no-acpi \ +-boot c \ +-usb \ +-drive file=iscsi://myname:AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A@example.org:\ +6000/iqn.1992-01.com.example%3Astorage/1,format=raw,if=none,\ +id=drive-virtio-disk0 \ +-device virtio-blk-pci,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,\ +id=virtio-disk0 \ +-drive 'file=rbd:pool/image:id=myname:\ +key=QVFDVm41aE82SHpGQWhBQXEwTkN2OGp0SmNJY0UrSE9CbE1RMUE=:\ +auth_supported=cephx\;none:mon_host=mon1.example.org\:6321\;mon2.example.org\:\ +6322\;mon3.example.org\:6322,format=raw,if=none,id=drive-virtio-disk1' \ +-device virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk1,\ +id=virtio-disk1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.xml new file mode 100644 index 0000000000..bd84cc42f6 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.xml @@ -0,0 +1,45 @@ +<domain type='qemu'> + <name>QEMUGuest1</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='i686' 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> + <emulator>/usr/bin/qemu-system-i686</emulator> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='iscsi' name='iqn.1992-01.com.example:storage/1'> + <host name='example.org' port='6000'/> + <auth username='myname'> + <secret type='iscsi' usage='mycluster_myname'/> + </auth> + </source> + <target dev='vda' bus='virtio'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='rbd' name='pool/image'> + <host name='mon1.example.org' port='6321'/> + <host name='mon2.example.org' port='6322'/> + <host name='mon3.example.org' port='6322'/> + <auth username='myname'> + <secret type='ceph' usage='mycluster_myname'/> + </auth> + </source> + <target dev='vdb' bus='virtio'/> + </disk> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index a505864b87..a4ff7b80c1 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -932,6 +932,7 @@ mymain(void) DO_TEST("disk-drive-network-iscsi-auth", NONE); DO_TEST_PARSE_ERROR("disk-drive-network-iscsi-auth-secrettype-invalid", NONE); DO_TEST_PARSE_ERROR("disk-drive-network-iscsi-auth-wrong-secrettype", NONE); + DO_TEST_PARSE_ERROR("disk-drive-network-source-auth-both", NONE); DO_TEST("disk-drive-network-iscsi-lun", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_BLOCK); @@ -940,6 +941,7 @@ mymain(void) DO_TEST("disk-drive-network-rbd", NONE); DO_TEST("disk-drive-network-sheepdog", NONE); DO_TEST("disk-drive-network-rbd-auth", NONE); + DO_TEST("disk-drive-network-source-auth", NONE); # ifdef HAVE_GNUTLS_CIPHER_ENCRYPT DO_TEST("disk-drive-network-rbd-auth-AES", QEMU_CAPS_OBJECT_SECRET, QEMU_CAPS_VIRTIO_SCSI); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-network-source-auth.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-network-source-auth.xml new file mode 100644 index 0000000000..9dc063dea9 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-network-source-auth.xml @@ -0,0 +1,49 @@ +<domain type='qemu'> + <name>QEMUGuest1</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='i686' 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> + <emulator>/usr/bin/qemu-system-i686</emulator> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='iscsi' name='iqn.1992-01.com.example:storage/1'> + <host name='example.org' port='6000'/> + <auth username='myname'> + <secret type='iscsi' usage='mycluster_myname'/> + </auth> + </source> + <target dev='vda' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='rbd' name='pool/image'> + <host name='mon1.example.org' port='6321'/> + <host name='mon2.example.org' port='6322'/> + <host name='mon3.example.org' port='6322'/> + <auth username='myname'> + <secret type='ceph' usage='mycluster_myname'/> + </auth> + </source> + <target dev='vdb' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 7d7a5f1e4b..c484d8d17c 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -475,6 +475,7 @@ mymain(void) DO_TEST("disk-drive-network-rbd-auth", NONE); DO_TEST("disk-drive-network-rbd-ipv6", NONE); DO_TEST("disk-drive-network-rbd-ceph-env", NONE); + DO_TEST("disk-drive-network-source-auth", NONE); DO_TEST("disk-drive-network-sheepdog", NONE); DO_TEST("disk-drive-network-vxhs", NONE); DO_TEST("disk-drive-network-tlsx509-vxhs", NONE); diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index ffebd4dc1d..fe1521d9c0 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -1361,6 +1361,9 @@ mymain(void) TEST_BACKING_PARSE("rbd:testshare:id=asdf:mon_host=example.com", "<source protocol='rbd' name='testshare'>\n" " <host name='example.com'/>\n" + " <auth username='asdf'>\n" + " <secret type='ceph'/>\n" + " </auth>\n" "</source>\n"); TEST_BACKING_PARSE("nbd:example.org:6000:exportname=blah", "<source protocol='nbd' name='blah'>\n" @@ -1526,6 +1529,9 @@ mymain(void) "}", "<source protocol='rbd' name='testshare'>\n" " <host name='example.com'/>\n" + " <auth username='asdf'>\n" + " <secret type='ceph'/>\n" + " </auth>\n" "</source>\n"); TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"rbd\"," "\"image\":\"test\"," -- 2.13.6

On Thu, Oct 05, 2017 at 09:22:08 -0400, John Ferlan wrote:
Since the virStorageAuthDefPtr auth; is a member of _virStorageSource it really should be allowed to be a subelement of the disk <source> for the RBD and iSCSI prototcols. That way we can set up to allow the <auth> element to be formatted within the disk source.
Since we've allowed the <auth> to be a child of <disk>, we'll need to keep track of how it was read so that when writing out we'll know whether to format as child of <disk> or <source>. For the argv2xml parsing, let's format under <source> as a preference. Do not allow <auth> to be both a child of <disk> and <source>.
Modify the qemuxml2argvtest to add a parse failure when there is an <auth> as a child of <disk> *and* an <auth> as a child of <source>.
Add tests to validate that if the <auth> was found in <source>, then the resulting xml2xml and xml2arg works just fine. The two new .args file are exact copies of the non "-source" version of the file.
The virschematest will read the new test files and validate from a RNG viewpoint things are fine
Update the virstoragefile, virstoragetest, and args2xml file to show the "preference" to place <auth> as a child of <source>.
Signed-off-by: John Ferlan <jferlan@redhat.com> --- docs/formatdomain.html.in | 67 +++++++++++++--------- docs/schemas/domaincommon.rng | 18 +++++- src/conf/domain_conf.c | 67 +++++++++++++++++++++- src/util/virstoragefile.c | 1 + src/util/virstoragefile.h | 1 + .../qemuargv2xml-disk-drive-network-rbd-auth.xml | 6 +- ...ml2argv-disk-drive-network-source-auth-both.xml | 51 ++++++++++++++++ ...emuxml2argv-disk-drive-network-source-auth.args | 32 +++++++++++ ...qemuxml2argv-disk-drive-network-source-auth.xml | 45 +++++++++++++++ tests/qemuxml2argvtest.c | 2 + ...muxml2xmlout-disk-drive-network-source-auth.xml | 49 ++++++++++++++++ tests/qemuxml2xmltest.c | 1 + tests/virstoragetest.c | 6 ++ 13 files changed, 311 insertions(+), 35 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth-both.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-network-source-auth.xml
[...]
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c0e3c22213..74f2090d06 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 74dee10f2f..c8bb1066fe 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -238,6 +238,7 @@ struct _virStorageSource { virStorageNetHostDefPtr hosts; virStorageSourcePoolDefPtr srcpool; virStorageAuthDefPtr auth; + bool authDefined;
I find this name slightly misleading. How about authInherited? At any rate, this patch should be applicable without conflicts and it will help in doing security related stuff for the backing chain. ACK You can push this right now. I'll pick out a few other things form this series which will be helpful for the blockdev-add saga and pass back the rest for the iSCSI work (mainly with pre-blockdev qemus).

Introduce the bare necessities to add privateData to _virStorageSource. Subsequent patches will fill in more details. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/conf/domain_conf.h | 1 + src/qemu/qemu_domain.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domain.h | 13 +++++++++++++ src/util/virstoragefile.c | 1 + src/util/virstoragefile.h | 3 +++ 5 files changed, 61 insertions(+) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a42efcfa68..ca334e0147 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2621,6 +2621,7 @@ struct _virDomainXMLPrivateDataCallbacks { /* note that private data for devices are not copied when using * virDomainDefCopy and similar functions */ virDomainXMLPrivateDataNewFunc diskNew; + virDomainXMLPrivateDataNewFunc diskSrcNew; virDomainXMLPrivateDataNewFunc hostdevNew; virDomainXMLPrivateDataNewFunc vcpuNew; virDomainXMLPrivateDataNewFunc chrSourceNew; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 2bcc9839d1..e8e7b31ff0 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -926,6 +926,48 @@ qemuDomainDiskPrivateDispose(void *obj) } +static virClassPtr qemuDomainDiskSrcPrivateClass; +static void qemuDomainDiskSrcPrivateDispose(void *obj); + +static int +qemuDomainDiskSrcPrivateOnceInit(void) +{ + qemuDomainDiskSrcPrivateClass = virClassNew(virClassForObject(), + "qemuDomainDiskSrcPrivate", + sizeof(qemuDomainDiskSrcPrivate), + qemuDomainDiskSrcPrivateDispose); + if (!qemuDomainDiskSrcPrivateClass) + return -1; + else + return 0; +} + +VIR_ONCE_GLOBAL_INIT(qemuDomainDiskSrcPrivate) + +static virObjectPtr +qemuDomainDiskSrcPrivateNew(void) +{ + qemuDomainDiskSrcPrivatePtr priv; + + if (qemuDomainDiskSrcPrivateInitialize() < 0) + return NULL; + + if (!(priv = virObjectNew(qemuDomainDiskSrcPrivateClass))) + return NULL; + + return (virObjectPtr) priv; +} + + +static void +qemuDomainDiskSrcPrivateDispose(void *obj) +{ + qemuDomainDiskSrcPrivatePtr priv = obj; + + qemuDomainSecretInfoFree(&priv->secinfo); +} + + static virClassPtr qemuDomainHostdevPrivateClass; static void qemuDomainHostdevPrivateDispose(void *obj); @@ -2302,6 +2344,7 @@ virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = { .alloc = qemuDomainObjPrivateAlloc, .free = qemuDomainObjPrivateFree, .diskNew = qemuDomainDiskPrivateNew, + .diskSrcNew = qemuDomainDiskSrcPrivateNew, .vcpuNew = qemuDomainVcpuPrivateNew, .hostdevNew = qemuDomainHostdevPrivateNew, .chrSourceNew = qemuDomainChrSourcePrivateNew, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index f92841ceb9..aba70f4030 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -359,6 +359,19 @@ struct _qemuDomainDiskPrivate { bool removable; /* device media can be removed/changed */ }; +# define QEMU_DOMAIN_DISK_SRC_PRIVATE(src) \ + ((qemuDomainDiskSrcPrivatePtr) (src)->privateData) + +typedef struct _qemuDomainDiskSrcPrivate qemuDomainDiskSrcPrivate; +typedef qemuDomainDiskSrcPrivate *qemuDomainDiskSrcPrivatePtr; +struct _qemuDomainDiskSrcPrivate { + virObject parent; + + /* for each storage source using auth/secret + * NB: *not* to be written to qemu domain object XML */ + qemuDomainSecretInfoPtr secinfo; +}; + # define QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev) \ ((qemuDomainHostdevPrivatePtr) (hostdev)->privateData) diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 727ec52856..5e45cb3a27 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -2276,6 +2276,7 @@ virStorageSourceClear(virStorageSourcePtr def) virStorageNetHostDefFree(def->nhosts, def->hosts); virStorageAuthDefFree(def->auth); + virObjectUnref(def->privateData); VIR_FREE(def->nodestorage); VIR_FREE(def->nodeformat); diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index c8bb1066fe..5673a3f77d 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -27,6 +27,7 @@ # include <sys/stat.h> # include "virbitmap.h" +# include "virobject.h" # include "virseclabel.h" # include "virstorageencryption.h" # include "virutil.h" @@ -241,6 +242,8 @@ struct _virStorageSource { bool authDefined; virStorageEncryptionPtr encryption; + virObjectPtr privateData; /* Usable to store hypervisor specific data */ + char *driverName; int format; /* virStorageFileFormat in domain backing chains, but * pool-specific enum for storage volumes */ -- 2.13.6

Create a qemu* specific StorageSourceCopy helper because we need to be able to copy the PrivateData too if it exists without adding any knowledge to the virStorageSourceCopy function. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_blockjob.c | 2 +- src/qemu/qemu_domain.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domain.h | 4 ++++ src/qemu/qemu_driver.c | 8 +++---- 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index c1b46f7d0a..15893a6048 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -124,7 +124,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver, if ((persistDisk = virDomainDiskByName(vm->newDef, disk->dst, false))) { - copy = virStorageSourceCopy(disk->mirror, false); + copy = qemuDomainStorageSourceCopy(disk->mirror, false); if (!copy || virStorageSourceInitChainElement(copy, persistDisk->src, diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e8e7b31ff0..e040614fe4 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -883,6 +883,39 @@ qemuDomainSecretInfoFree(qemuDomainSecretInfoPtr *secinfo) } +static qemuDomainSecretInfoPtr +qemuDomainSecretInfoCopy(qemuDomainSecretInfoPtr src) +{ + qemuDomainSecretInfoPtr dst = NULL; + if (VIR_ALLOC(dst) < 0) + return NULL; + + dst->type = src->type; + if (src->type == VIR_DOMAIN_SECRET_INFO_TYPE_PLAIN) { + if (VIR_STRDUP(dst->s.plain.username, src->s.plain.username) < 0) + goto error; + + if (VIR_ALLOC_N(dst->s.plain.secret, src->s.plain.secretlen) < 0) + goto error; + + memcpy(dst->s.plain.secret, src->s.plain.secret, src->s.plain.secretlen); + dst->s.plain.secretlen = src->s.plain.secretlen; + } else { + if (VIR_STRDUP(dst->s.aes.username, src->s.aes.username) < 0 || + VIR_STRDUP(dst->s.aes.alias, src->s.aes.alias) < 0 || + VIR_STRDUP(dst->s.aes.iv, src->s.aes.alias) < 0 || + VIR_STRDUP(dst->s.aes.ciphertext, src->s.aes.ciphertext) < 0) + goto error; + } + + return dst; + + error: + qemuDomainSecretInfoFree(&dst); + return NULL; +} + + static virClassPtr qemuDomainDiskPrivateClass; static void qemuDomainDiskPrivateDispose(void *obj); @@ -959,6 +992,35 @@ qemuDomainDiskSrcPrivateNew(void) } +virStorageSourcePtr +qemuDomainStorageSourceCopy(const virStorageSource *src, + bool backingChain) +{ + qemuDomainDiskSrcPrivatePtr srcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(src); + virStorageSourcePtr dst; + qemuDomainDiskSrcPrivatePtr dstPriv; + + if (!(dst = virStorageSourceCopy(src, backingChain))) + return NULL; + + if (!srcPriv->secinfo) + return dst; + + if (!(dst->privateData = qemuDomainDiskSrcPrivateNew())) + goto error; + + dstPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(dst); + if (!(dstPriv->secinfo = qemuDomainSecretInfoCopy(srcPriv->secinfo))) + goto error; + + return dst; + + error: + virStorageSourceFree(dst); + return NULL; +} + + static void qemuDomainDiskSrcPrivateDispose(void *obj) { diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index aba70f4030..a7a590c950 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -818,6 +818,10 @@ void qemuDomainMasterKeyRemove(qemuDomainObjPrivatePtr priv); void qemuDomainSecretInfoFree(qemuDomainSecretInfoPtr *secinfo) ATTRIBUTE_NONNULL(1); +virStorageSourcePtr +qemuDomainStorageSourceCopy(const virStorageSource *src, + bool backingChain); + void qemuDomainSecretDiskDestroy(virDomainDiskDefPtr disk) ATTRIBUTE_NONNULL(1); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7c6f1674a9..b1da17651a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -345,7 +345,7 @@ qemuSecurityChownCallback(const virStorageSource *src, if (chown(src->path, uid, gid) < 0) goto cleanup; } else { - if (!(cpy = virStorageSourceCopy(src, false))) + if (!(cpy = qemuDomainStorageSourceCopy(src, false))) goto cleanup; /* src file init reports errors, return -2 on failure */ @@ -14396,7 +14396,7 @@ qemuDomainSnapshotDiskDataCollect(virQEMUDriverPtr driver, dd->disk = vm->def->disks[i]; - if (!(dd->src = virStorageSourceCopy(snap->def->disks[i].src, false))) + if (!(dd->src = qemuDomainStorageSourceCopy(snap->def->disks[i].src, false))) goto error; if (virStorageSourceInitChainElement(dd->src, dd->disk->src, false) < 0) @@ -14425,7 +14425,7 @@ qemuDomainSnapshotDiskDataCollect(virQEMUDriverPtr driver, (dd->persistdisk = virDomainDiskByName(vm->newDef, dd->disk->dst, false))) { - if (!(dd->persistsrc = virStorageSourceCopy(dd->src, false))) + if (!(dd->persistsrc = qemuDomainStorageSourceCopy(dd->src, false))) goto error; if (virStorageSourceInitChainElement(dd->persistsrc, @@ -17450,7 +17450,7 @@ qemuDomainBlockCommit(virDomainPtr dom, /* For an active commit, clone enough of the base to act as the mirror */ if (topSource == disk->src) { - if (!(mirror = virStorageSourceCopy(baseSource, false))) + if (!(mirror = qemuDomainStorageSourceCopy(baseSource, false))) goto endjob; if (virStorageSourceInitChainElement(mirror, disk->src, -- 2.13.6

Add helper to manage the virStorageSourcePtr allocation for disk->src, disk->mirror, and disk->src->backingStore. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/conf/domain_conf.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 91d554c3ee..65223fe85a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1703,6 +1703,27 @@ virDomainDefGetVcpusTopology(const virDomainDef *def, } +static virStorageSourcePtr +virDomainDiskStorageSourceNew(virDomainXMLOptionPtr xmlopt) +{ + virStorageSourcePtr src; + + if (VIR_ALLOC(src) < 0) + return NULL; + + if (xmlopt && + xmlopt->privateData.diskSrcNew && + !(src->privateData = xmlopt->privateData.diskSrcNew())) + goto error; + + return src; + + error: + virStorageSourceFree(src); + return NULL; +} + + virDomainDiskDefPtr virDomainDiskDefNew(virDomainXMLOptionPtr xmlopt) { @@ -1711,7 +1732,7 @@ virDomainDiskDefNew(virDomainXMLOptionPtr xmlopt) if (VIR_ALLOC(ret) < 0) return NULL; - if (VIR_ALLOC(ret->src) < 0) + if (!(ret->src = virDomainDiskStorageSourceNew(xmlopt))) goto error; if (xmlopt && @@ -8286,7 +8307,8 @@ virDomainDiskSourceParse(xmlNodePtr node, static int -virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt, +virDomainDiskBackingStoreParse(virDomainXMLOptionPtr xmlopt, + xmlXPathContextPtr ctxt, virStorageSourcePtr src, unsigned int flags) { @@ -8302,7 +8324,7 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt, goto cleanup; } - if (VIR_ALLOC(backingStore) < 0) + if (!(backingStore = virDomainDiskStorageSourceNew(xmlopt))) goto cleanup; if (!(type = virXMLPropString(ctxt->node, "type"))) { @@ -8338,7 +8360,7 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt, } if (virDomainDiskSourceParse(source, ctxt, backingStore, flags) < 0 || - virDomainDiskBackingStoreParse(ctxt, backingStore, flags) < 0) + virDomainDiskBackingStoreParse(xmlopt, ctxt, backingStore, flags) < 0) goto cleanup; src->backingStore = backingStore; @@ -8439,6 +8461,7 @@ virDomainDiskDefIotuneParse(virDomainDiskDefPtr def, static int virDomainDiskDefMirrorParse(virDomainDiskDefPtr def, xmlNodePtr cur, + virDomainXMLOptionPtr xmlopt, xmlXPathContextPtr ctxt, unsigned int flags) { @@ -8449,7 +8472,7 @@ virDomainDiskDefMirrorParse(virDomainDiskDefPtr def, char *blockJob = NULL; int ret = -1; - if (VIR_ALLOC(def->mirror) < 0) + if (!(def->mirror = virDomainDiskStorageSourceNew(xmlopt))) goto cleanup; if ((blockJob = virXMLPropString(cur, "job"))) { @@ -8973,7 +8996,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, } else if (!def->mirror && virXMLNodeNameEqual(cur, "mirror") && !(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) { - if (virDomainDiskDefMirrorParse(def, cur, ctxt, flags) < 0) + if (virDomainDiskDefMirrorParse(def, cur, xmlopt, ctxt, flags) < 0) goto error; } else if (!authdef && virXMLNodeNameEqual(cur, "auth")) { @@ -9237,7 +9260,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, product = NULL; if (!(flags & VIR_DOMAIN_DEF_PARSE_DISK_SOURCE)) { - if (virDomainDiskBackingStoreParse(ctxt, def->src, flags) < 0) + if (virDomainDiskBackingStoreParse(xmlopt, ctxt, def->src, flags) < 0) goto error; } -- 2.13.6

When commit id 'da86c6c22' added support for diskPriv->encinfo in qemuDomainSecretDiskPrepare a change to qemuDomainSecretDiskDestroy to was missed. Although qemuDomainDiskPrivateDispose probably would do the trick. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_domain.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e040614fe4..4b5929b251 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1400,10 +1400,11 @@ qemuDomainSecretDiskDestroy(virDomainDiskDefPtr disk) { qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - if (!diskPriv || !diskPriv->secinfo) - return; + if (diskPriv && diskPriv->secinfo) + qemuDomainSecretInfoFree(&diskPriv->secinfo); - qemuDomainSecretInfoFree(&diskPriv->secinfo); + if (diskPriv && diskPriv->encinfo) + qemuDomainSecretInfoFree(&diskPriv->encinfo); } -- 2.13.6

Relocate into disk source private (qemuDomainDiskSrcPrivatePtr) Since the secret information is really _virStorageSource specific piece of data, let's manage the privateData from there instead of at the Disk level. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 6 ++++-- src/qemu/qemu_domain.c | 9 +++++---- src/qemu/qemu_domain.h | 4 ---- src/qemu/qemu_hotplug.c | 11 ++++++++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9c8bde49a8..76725e2d4e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1378,7 +1378,8 @@ qemuBuildDriveSourceStr(virDomainDiskDefPtr disk, { int actualType = virStorageSourceGetActualType(disk->src); qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - qemuDomainSecretInfoPtr secinfo = diskPriv->secinfo; + qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); + qemuDomainSecretInfoPtr secinfo = diskSrcPriv->secinfo; qemuDomainSecretInfoPtr encinfo = diskPriv->encinfo; virJSONValuePtr srcprops = NULL; char *source = NULL; @@ -2255,7 +2256,8 @@ qemuBuildDiskDriveCommandLine(virCommandPtr cmd, bool driveBoot = false; virDomainDiskDefPtr disk = def->disks[i]; qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - qemuDomainSecretInfoPtr secinfo = diskPriv->secinfo; + qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); + qemuDomainSecretInfoPtr secinfo = diskSrcPriv->secinfo; qemuDomainSecretInfoPtr encinfo = diskPriv->encinfo; if (disk->info.bootIndex) { diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 4b5929b251..72433ed36a 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -954,7 +954,6 @@ qemuDomainDiskPrivateDispose(void *obj) { qemuDomainDiskPrivatePtr priv = obj; - qemuDomainSecretInfoFree(&priv->secinfo); qemuDomainSecretInfoFree(&priv->encinfo); } @@ -1399,9 +1398,10 @@ void qemuDomainSecretDiskDestroy(virDomainDiskDefPtr disk) { qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); + qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); - if (diskPriv && diskPriv->secinfo) - qemuDomainSecretInfoFree(&diskPriv->secinfo); + if (diskSrcPriv && diskSrcPriv->secinfo) + qemuDomainSecretInfoFree(&diskSrcPriv->secinfo); if (diskPriv && diskPriv->encinfo) qemuDomainSecretInfoFree(&diskPriv->encinfo); @@ -1450,6 +1450,7 @@ qemuDomainSecretDiskPrepare(virConnectPtr conn, { virStorageSourcePtr src = disk->src; qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); + qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); if (qemuDomainSecretDiskCapable(src)) { virSecretUsageType usageType = VIR_SECRET_USAGE_TYPE_ISCSI; @@ -1457,7 +1458,7 @@ qemuDomainSecretDiskPrepare(virConnectPtr conn, if (src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD) usageType = VIR_SECRET_USAGE_TYPE_CEPH; - if (!(diskPriv->secinfo = + if (!(diskSrcPriv->secinfo = qemuDomainSecretInfoNew(conn, priv, disk->info.alias, usageType, src->auth->username, &src->auth->seclookupdef, false))) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index a7a590c950..fc4f5bc6d8 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -345,10 +345,6 @@ struct _qemuDomainDiskPrivate { bool migrating; /* the disk is being migrated */ - /* for storage devices using auth/secret - * NB: *not* to be written to qemu domain object XML */ - qemuDomainSecretInfoPtr secinfo; - /* for storage devices using encryption/secret * Can have both <auth> and <encryption> for some disks * NB:*not* to be written to qemu domain object XML */ diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 0288986d83..544a592fb7 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -258,6 +258,7 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver, char *driveAlias = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); + qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); const char *format = NULL; char *sourcestr = NULL; @@ -299,7 +300,7 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver, } if (!virStorageSourceIsEmpty(newsrc)) { - if (qemuGetDriveSourceString(newsrc, diskPriv->secinfo, &sourcestr) < 0) + if (qemuGetDriveSourceString(newsrc, diskSrcPriv->secinfo, &sourcestr) < 0) goto error; if (virStorageSourceGetActualType(newsrc) != VIR_STORAGE_TYPE_DIR) { @@ -369,6 +370,7 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, virJSONValuePtr secobjProps = NULL; virJSONValuePtr encobjProps = NULL; qemuDomainDiskPrivatePtr diskPriv; + qemuDomainDiskSrcPrivatePtr diskSrcPriv; qemuDomainSecretInfoPtr secinfo; qemuDomainSecretInfoPtr encinfo; @@ -406,7 +408,8 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, goto error; diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - secinfo = diskPriv->secinfo; + diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); + secinfo = diskSrcPriv->secinfo; if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES) { if (qemuBuildSecretInfoProps(secinfo, &secobjProps) < 0) goto error; @@ -671,6 +674,7 @@ qemuDomainAttachSCSIDisk(virConnectPtr conn, virJSONValuePtr encobjProps = NULL; virJSONValuePtr secobjProps = NULL; qemuDomainDiskPrivatePtr diskPriv; + qemuDomainDiskSrcPrivatePtr diskSrcPriv; qemuDomainSecretInfoPtr encinfo; qemuDomainSecretInfoPtr secinfo; @@ -704,7 +708,8 @@ qemuDomainAttachSCSIDisk(virConnectPtr conn, goto error; diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - secinfo = diskPriv->secinfo; + diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); + secinfo = diskSrcPriv->secinfo; if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES) { if (qemuBuildSecretInfoProps(secinfo, &secobjProps) < 0) goto error; -- 2.13.6

Since the virStorageEncryptionPtr encryption; is a member of _virStorageSource it really should be allowed to be a subelement of the disk <source> for various disk formats: Source{File|Dir|Block|Volume} SourceProtocol{RBD|ISCSI|NBD|Gluster|Simple|HTTP} NB: Simple includes sheepdog, ftp, ftps, tftp That way we can set up to allow the <encryption> element to be formatted within the disk source, but we still need to be wary from whence the element was read - see keep track and when it comes to format the data, ensure it's written in the correct place. Modify the qemuxml2argvtest to add a parse failure when there is an <encryption> as a child of <disk> *and* an <encryption> as a child of <source>. The virschematest will read the new test files and validate from a RNG viewpoint things are fine. Signed-off-by: John Ferlan <jferlan@redhat.com> --- docs/formatdomain.html.in | 15 +++- docs/schemas/domaincommon.rng | 30 ++++++++ src/conf/domain_conf.c | 68 ++++++++++++++++-- src/util/virstoragefile.h | 1 + .../qemuxml2argv-luks-disks-source-both.xml | 40 +++++++++++ .../qemuxml2argv-luks-disks-source.args | 62 ++++++++++++++++ .../qemuxml2argv-luks-disks-source.xml | 81 +++++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../qemuxml2xmlout-luks-disks-source.xml | 84 ++++++++++++++++++++++ .../qemuxml2xmlout-luks-disks.xml | 46 +++++++++++- tests/qemuxml2xmltest.c | 1 + 11 files changed, 420 insertions(+), 10 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source-both.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks-source.xml mode change 120000 => 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 74f2090d06..e594d35524 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2705,6 +2705,14 @@ attribute matching the key that was specified in the secret object. </dd> + <dd><span class="since">Since libvirt 3.9.0</span>, the + <code>encryption</code> can be a sub-element of the + <code>source</code> element for encrypted storage sources. + If present, specifies how the storage source is encrypted + See the + <a href="formatstorageencryption.html">Storage Encryption</a> + page for more information. + </dd> </dl> <p> @@ -3110,8 +3118,11 @@ <span class="since">Since 0.8.8</span> </dd> <dt><code>encryption</code></dt> - <dd>If present, specifies how the volume is encrypted. See - the <a href="formatstorageencryption.html">Storage Encryption</a> page + <dd>Starting with <span class="since">libvirt 3.9.0</span> the + <code>encryption</code> element is preferred to be a sub-element + of the <code>source</code> element. If present, specifies how the + volume is encrypted using "qcow". See the + <a href="formatstorageencryption.html">Storage Encryption</a> page for more information. </dd> <dt><code>readonly</code></dt> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 895af55da1..b3b08862c3 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1469,6 +1469,9 @@ <optional> <ref name="storageStartupPolicy"/> </optional> + <optional> + <ref name="encryption"/> + </optional> <zeroOrMore> <ref name='devSeclabel'/> </zeroOrMore> @@ -1490,6 +1493,9 @@ <optional> <ref name="storageStartupPolicy"/> </optional> + <optional> + <ref name="encryption"/> + </optional> <zeroOrMore> <ref name='devSeclabel'/> </zeroOrMore> @@ -1509,6 +1515,9 @@ <optional> <ref name="storageStartupPolicy"/> </optional> + <optional> + <ref name="encryption"/> + </optional> <empty/> </element> </optional> @@ -1581,6 +1590,9 @@ <optional> <ref name="diskAuth"/> </optional> + <optional> + <ref name="encryption"/> + </optional> <empty/> </interleave> </element> @@ -1596,6 +1608,9 @@ <optional> <ref name="diskAuth"/> </optional> + <optional> + <ref name="encryption"/> + </optional> </element> </define> @@ -1609,6 +1624,9 @@ </attribute> <attribute name="name"/> <ref name="diskSourceNetworkHost"/> + <optional> + <ref name="encryption"/> + </optional> </element> </define> @@ -1624,6 +1642,9 @@ </attribute> <attribute name="name"/> <ref name="diskSourceNetworkHost"/> + <optional> + <ref name="encryption"/> + </optional> </element> </define> @@ -1636,6 +1657,9 @@ <attribute name="name"/> </optional> <ref name="diskSourceNetworkHost"/> + <optional> + <ref name="encryption"/> + </optional> </element> </define> @@ -1648,6 +1672,9 @@ <oneOrMore> <ref name="diskSourceNetworkHost"/> </oneOrMore> + <optional> + <ref name="encryption"/> + </optional> </element> </define> @@ -1706,6 +1733,9 @@ <optional> <ref name="storageStartupPolicy"/> </optional> + <optional> + <ref name="encryption"/> + </optional> <zeroOrMore> <ref name='devSeclabel'/> </zeroOrMore> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 65223fe85a..c2be9b7155 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8252,6 +8252,29 @@ virDomainDiskSourceAuthParse(xmlNodePtr node, } +static int +virDomainDiskSourceEncryptionParse(xmlNodePtr node, + virStorageEncryptionPtr *encryptionsrc) +{ + xmlNodePtr child; + virStorageEncryptionPtr encryption = NULL; + + for (child = node->children; child; child = child->next) { + if (child->type == XML_ELEMENT_NODE && + virXMLNodeNameEqual(child, "encryption")) { + + if (!(encryption = virStorageEncryptionParseNode(node->doc, child))) + return -1; + + *encryptionsrc = encryption; + return 0; + } + } + + return 0; +} + + int virDomainDiskSourceParse(xmlNodePtr node, xmlXPathContextPtr ctxt, @@ -8292,6 +8315,9 @@ virDomainDiskSourceParse(xmlNodePtr node, if (virDomainDiskSourceAuthParse(node, &src->auth) < 0) goto cleanup; + if (virDomainDiskSourceEncryptionParse(node, &src->encryption) < 0) + goto cleanup; + /* People sometimes pass a bogus '' source path when they mean to omit the * source element completely (e.g. CDROM without media). This is just a * little compatibility check to help those broken apps */ @@ -8943,6 +8969,18 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, if (def->src->auth) def->src->authDefined = true; + /* Similarly for <encryption> - it's a child of <source> too + * and we cannot find in both places */ + if (encryption && def->src->encryption) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("an <encryption> definition already found for " + "the <disk> definition")); + goto error; + } + + if (def->src->encryption) + def->src->encryptionDefined = true; + source = true; startupPolicy = virXMLPropString(cur, "startupPolicy"); @@ -9024,11 +9062,18 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, virXMLNodeNameEqual(cur, "state")) { /* Legacy back-compat. Don't add any more attributes here */ devaddr = virXMLPropString(cur, "devaddr"); - } else if (encryption == NULL && + } else if (!encryption && virXMLNodeNameEqual(cur, "encryption")) { - encryption = virStorageEncryptionParseNode(node->doc, - cur); - if (encryption == NULL) + /* If we've already parsed <source> and found an <encryption> child, + * then generate an error to avoid ambiguity */ + if (def->src->encryptionDefined) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("an <encryption> definition already found for " + "disk source")); + goto error; + } + + if (!(encryption = virStorageEncryptionParseNode(node->doc, cur))) goto error; } else if (!serial && virXMLNodeNameEqual(cur, "serial")) { @@ -9246,8 +9291,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, target = NULL; if (authdef) VIR_STEAL_PTR(def->src->auth, authdef); - def->src->encryption = encryption; - encryption = NULL; + if (encryption) + VIR_STEAL_PTR(def->src->encryption, encryption); def->domain_name = domain_name; domain_name = NULL; def->serial = serial; @@ -21955,6 +22000,12 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf, goto error; } + /* If we found encryption as a child of <source>, then format it + * as we found it. */ + if (src->encryption && src->encryptionDefined && + virStorageEncryptionFormat(&childBuf, src->encryption) < 0) + return -1; + if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) < 0) goto error; } @@ -22283,7 +22334,10 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferEscapeString(buf, "<wwn>%s</wwn>\n", def->wwn); virBufferEscapeString(buf, "<vendor>%s</vendor>\n", def->vendor); virBufferEscapeString(buf, "<product>%s</product>\n", def->product); - if (def->src->encryption && + + /* If originally found as a child of <disk>, then format thusly; + * otherwise, will be formatted as child of <source> */ + if (def->src->encryption && !def->src->encryptionDefined && virStorageEncryptionFormat(buf, def->src->encryption) < 0) return -1; virDomainDeviceInfoFormat(buf, &def->info, diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 5673a3f77d..845a2efc71 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -241,6 +241,7 @@ struct _virStorageSource { virStorageAuthDefPtr auth; bool authDefined; virStorageEncryptionPtr encryption; + bool encryptionDefined; virObjectPtr privateData; /* Usable to store hypervisor specific data */ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source-both.xml b/tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source-both.xml new file mode 100644 index 0000000000..c4b762a1ed --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source-both.xml @@ -0,0 +1,40 @@ +<domain type='qemu'> + <name>encryptdisk</name> + <uuid>496898a6-e6ff-f7c8-5dc2-3cf410945ee9</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.1'>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> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/storage/guest_disks/encryptdisk'> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> + </encryption> + </source> + <target dev='vda' bus='virtio'/> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> + </encryption> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.args b/tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.args new file mode 100644 index 0000000000..fec46945ce --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.args @@ -0,0 +1,62 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name encryptdisk \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-encryptdisk/master-key.aes \ +-M pc-i440fx-2.1 \ +-m 1024 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 496898a6-e6ff-f7c8-5dc2-3cf410945ee9 \ +-nographic \ +-nodefaults \ +-chardev socket,id=charmonitor,\ +path=/tmp/lib/domain--1-encryptdisk/monitor.sock,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-no-acpi \ +-boot c \ +-usb \ +-object secret,id=virtio-disk0-luks-secret0,\ +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ +-drive file=/storage/guest_disks/encryptdisk,\ +key-secret=virtio-disk0-luks-secret0,format=luks,if=none,id=drive-virtio-disk0 \ +-device virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,\ +id=virtio-disk0 \ +-object secret,id=virtio-disk1-luks-secret0,\ +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ +-drive file=/storage/guest_disks/encryptdisk2,\ +key-secret=virtio-disk1-luks-secret0,format=luks,if=none,id=drive-virtio-disk1 \ +-device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk1,\ +id=virtio-disk1 \ +-object secret,id=virtio-disk2-luks-secret0,\ +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ +-drive file=iscsi://myname:AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A@example.org:\ +6000/iqn.1992-01.com.example%3Astorage/1,key-secret=virtio-disk2-luks-secret0,\ +format=luks,if=none,id=drive-virtio-disk2 \ +-device virtio-blk-pci,bus=pci.0,addr=0x6,drive=drive-virtio-disk2,\ +id=virtio-disk2 \ +-object secret,id=virtio-disk3-luks-secret0,\ +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ +-drive file=iscsi://iscsi.example.com:3260/demo-target/3,\ +key-secret=virtio-disk3-luks-secret0,format=luks,if=none,id=drive-virtio-disk3 \ +-device virtio-blk-pci,bus=pci.0,addr=0x7,drive=drive-virtio-disk3,\ +id=virtio-disk3 \ +-object secret,id=virtio-disk4-luks-secret0,\ +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ +-drive 'file=rbd:pool/image:auth_supported=none:mon_host=mon1.example.org\:\ +6321\;mon2.example.org\:6322\;mon3.example.org\:6322,\ +key-secret=virtio-disk4-luks-secret0,format=luks,if=none,\ +id=drive-virtio-disk4' \ +-device virtio-blk-pci,bus=pci.0,addr=0x8,drive=drive-virtio-disk4,\ +id=virtio-disk4 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.xml b/tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.xml new file mode 100644 index 0000000000..293877df9e --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.xml @@ -0,0 +1,81 @@ +<domain type='qemu'> + <name>encryptdisk</name> + <uuid>496898a6-e6ff-f7c8-5dc2-3cf410945ee9</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.1'>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> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/storage/guest_disks/encryptdisk'> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> + </encryption> + </source> + <target dev='vda' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/storage/guest_disks/encryptdisk2'> + <encryption format='luks'> + <secret type='passphrase' usage='/storage/guest_disks/encryptdisk2'/> + </encryption> + </source> + <target dev='vdb' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='iscsi' name='iqn.1992-01.com.example:storage/1'> + <host name='example.org' port='6000'/> + <auth username='myname'> + <secret type='iscsi' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80e80'/> + </auth> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80f77'/> + </encryption> + </source> + <target dev='vdc' bus='virtio'/> + </disk> + <disk type='volume' device='disk'> + <driver name='qemu' type='raw'/> + <source pool='pool-iscsi' volume='unit:0:0:3' mode='direct'> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80f80'/> + </encryption> + </source> + <target dev='vdd' bus='virtio'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='rbd' name='pool/image'> + <host name='mon1.example.org' port='6321'/> + <host name='mon2.example.org' port='6322'/> + <host name='mon3.example.org' port='6322'/> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> + </encryption> + </source> + <target dev='vde' bus='virtio'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index a4ff7b80c1..f326bffa16 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1666,10 +1666,12 @@ mymain(void) DO_TEST("encrypted-disk-usage", NONE); # ifdef HAVE_GNUTLS_CIPHER_ENCRYPT DO_TEST("luks-disks", QEMU_CAPS_OBJECT_SECRET); + DO_TEST("luks-disks-source", QEMU_CAPS_OBJECT_SECRET); # else DO_TEST_FAILURE("luks-disks", QEMU_CAPS_OBJECT_SECRET); # endif DO_TEST_PARSE_ERROR("luks-disk-invalid", NONE); + DO_TEST_PARSE_ERROR("luks-disks-source-both", QEMU_CAPS_OBJECT_SECRET); DO_TEST("memtune", NONE); DO_TEST("memtune-unlimited", NONE); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks-source.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks-source.xml new file mode 100644 index 0000000000..1cad3af7a6 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks-source.xml @@ -0,0 +1,84 @@ +<domain type='qemu'> + <name>encryptdisk</name> + <uuid>496898a6-e6ff-f7c8-5dc2-3cf410945ee9</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.1'>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> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/storage/guest_disks/encryptdisk'> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> + </encryption> + </source> + <target dev='vda' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/storage/guest_disks/encryptdisk2'> + <encryption format='luks'> + <secret type='passphrase' usage='/storage/guest_disks/encryptdisk2'/> + </encryption> + </source> + <target dev='vdb' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='iscsi' name='iqn.1992-01.com.example:storage/1'> + <host name='example.org' port='6000'/> + <auth username='myname'> + <secret type='iscsi' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80e80'/> + </auth> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80f77'/> + </encryption> + </source> + <target dev='vdc' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </disk> + <disk type='volume' device='disk'> + <driver name='qemu' type='raw'/> + <source pool='pool-iscsi' volume='unit:0:0:3' mode='direct'> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80f80'/> + </encryption> + </source> + <target dev='vdd' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='rbd' name='pool/image'> + <host name='mon1.example.org' port='6321'/> + <host name='mon2.example.org' port='6322'/> + <host name='mon3.example.org' port='6322'/> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80fb0'/> + </encryption> + </source> + <target dev='vde' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml deleted file mode 120000 index b59dc672fc..0000000000 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml +++ /dev/null @@ -1 +0,0 @@ -../qemuxml2argvdata/qemuxml2argv-luks-disks.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml new file mode 100644 index 0000000000..c84af442a6 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml @@ -0,0 +1,45 @@ +<domain type='qemu'> + <name>encryptdisk</name> + <uuid>496898a6-e6ff-f7c8-5dc2-3cf410945ee9</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.1'>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> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/storage/guest_disks/encryptdisk'/> + <target dev='vda' bus='virtio'/> + <encryption format='luks'> + <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/> + </encryption> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/storage/guest_disks/encryptdisk2'/> + <target dev='vdb' bus='virtio'/> + <encryption format='luks'> + <secret type='passphrase' usage='/storage/guest_disks/encryptdisk2'/> + </encryption> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index c484d8d17c..f2e4244a23 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -580,6 +580,7 @@ mymain(void) DO_TEST("encrypted-disk", NONE); DO_TEST("encrypted-disk-usage", NONE); DO_TEST("luks-disks", NONE); + DO_TEST("luks-disks-source", NONE); DO_TEST("memtune", NONE); DO_TEST("memtune-unlimited", NONE); DO_TEST("blkiotune", NONE); -- 2.13.6

On Thu, Oct 05, 2017 at 09:22:14 -0400, John Ferlan wrote:
Since the virStorageEncryptionPtr encryption; is a member of _virStorageSource it really should be allowed to be a subelement of the disk <source> for various disk formats:
Source{File|Dir|Block|Volume} SourceProtocol{RBD|ISCSI|NBD|Gluster|Simple|HTTP}
NB: Simple includes sheepdog, ftp, ftps, tftp
That way we can set up to allow the <encryption> element to be formatted within the disk source, but we still need to be wary from whence the element was read - see keep track and when it comes to format the data, ensure it's written in the correct place.
Modify the qemuxml2argvtest to add a parse failure when there is an <encryption> as a child of <disk> *and* an <encryption> as a child of <source>.
The virschematest will read the new test files and validate from a RNG viewpoint things are fine.
Signed-off-by: John Ferlan <jferlan@redhat.com> --- docs/formatdomain.html.in | 15 +++- docs/schemas/domaincommon.rng | 30 ++++++++ src/conf/domain_conf.c | 68 ++++++++++++++++-- src/util/virstoragefile.h | 1 + .../qemuxml2argv-luks-disks-source-both.xml | 40 +++++++++++ .../qemuxml2argv-luks-disks-source.args | 62 ++++++++++++++++ .../qemuxml2argv-luks-disks-source.xml | 81 +++++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../qemuxml2xmlout-luks-disks-source.xml | 84 ++++++++++++++++++++++ .../qemuxml2xmlout-luks-disks.xml | 46 +++++++++++- tests/qemuxml2xmltest.c | 1 + 11 files changed, 420 insertions(+), 10 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source-both.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks-source.xml mode change 120000 => 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml
ACK with the same comment as for 1/16

Since the encryption information can also be disk source specific move it from _qemuDomainDiskPrivate to _qemuDomainDiskSrcPrivate. Since the last allocated element from _qemuDomainDiskPrivate is removed, that means we no longer need qemuDomainDiskPrivateDispose. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 6 ++---- src/qemu/qemu_domain.c | 30 ++++++++++++------------------ src/qemu/qemu_domain.h | 10 +++++----- src/qemu/qemu_hotplug.c | 8 ++------ 4 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 76725e2d4e..97c4890935 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1377,10 +1377,9 @@ qemuBuildDriveSourceStr(virDomainDiskDefPtr disk, virQEMUCapsPtr qemuCaps) { int actualType = virStorageSourceGetActualType(disk->src); - qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); qemuDomainSecretInfoPtr secinfo = diskSrcPriv->secinfo; - qemuDomainSecretInfoPtr encinfo = diskPriv->encinfo; + qemuDomainSecretInfoPtr encinfo = diskSrcPriv->encinfo; virJSONValuePtr srcprops = NULL; char *source = NULL; int ret = -1; @@ -2255,10 +2254,9 @@ qemuBuildDiskDriveCommandLine(virCommandPtr cmd, unsigned int bootindex = 0; bool driveBoot = false; virDomainDiskDefPtr disk = def->disks[i]; - qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); qemuDomainSecretInfoPtr secinfo = diskSrcPriv->secinfo; - qemuDomainSecretInfoPtr encinfo = diskPriv->encinfo; + qemuDomainSecretInfoPtr encinfo = diskSrcPriv->encinfo; if (disk->info.bootIndex) { bootindex = disk->info.bootIndex; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 72433ed36a..ad8d484cb1 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -917,7 +917,6 @@ qemuDomainSecretInfoCopy(qemuDomainSecretInfoPtr src) static virClassPtr qemuDomainDiskPrivateClass; -static void qemuDomainDiskPrivateDispose(void *obj); static int qemuDomainDiskPrivateOnceInit(void) @@ -925,7 +924,7 @@ qemuDomainDiskPrivateOnceInit(void) qemuDomainDiskPrivateClass = virClassNew(virClassForObject(), "qemuDomainDiskPrivate", sizeof(qemuDomainDiskPrivate), - qemuDomainDiskPrivateDispose); + NULL); if (!qemuDomainDiskPrivateClass) return -1; else @@ -949,15 +948,6 @@ qemuDomainDiskPrivateNew(void) } -static void -qemuDomainDiskPrivateDispose(void *obj) -{ - qemuDomainDiskPrivatePtr priv = obj; - - qemuDomainSecretInfoFree(&priv->encinfo); -} - - static virClassPtr qemuDomainDiskSrcPrivateClass; static void qemuDomainDiskSrcPrivateDispose(void *obj); @@ -1002,14 +992,19 @@ qemuDomainStorageSourceCopy(const virStorageSource *src, if (!(dst = virStorageSourceCopy(src, backingChain))) return NULL; - if (!srcPriv->secinfo) + if (!srcPriv->secinfo && !srcPriv->encinfo) return dst; if (!(dst->privateData = qemuDomainDiskSrcPrivateNew())) goto error; dstPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(dst); - if (!(dstPriv->secinfo = qemuDomainSecretInfoCopy(srcPriv->secinfo))) + if (srcPriv->secinfo && + !(dstPriv->secinfo = qemuDomainSecretInfoCopy(srcPriv->secinfo))) + goto error; + + if (srcPriv->encinfo && + !(dstPriv->encinfo = qemuDomainSecretInfoCopy(srcPriv->encinfo))) goto error; return dst; @@ -1026,6 +1021,7 @@ qemuDomainDiskSrcPrivateDispose(void *obj) qemuDomainDiskSrcPrivatePtr priv = obj; qemuDomainSecretInfoFree(&priv->secinfo); + qemuDomainSecretInfoFree(&priv->encinfo); } @@ -1397,14 +1393,13 @@ qemuDomainSecretInfoTLSNew(virConnectPtr conn, void qemuDomainSecretDiskDestroy(virDomainDiskDefPtr disk) { - qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); if (diskSrcPriv && diskSrcPriv->secinfo) qemuDomainSecretInfoFree(&diskSrcPriv->secinfo); - if (diskPriv && diskPriv->encinfo) - qemuDomainSecretInfoFree(&diskPriv->encinfo); + if (diskSrcPriv && diskSrcPriv->encinfo) + qemuDomainSecretInfoFree(&diskSrcPriv->encinfo); } @@ -1449,7 +1444,6 @@ qemuDomainSecretDiskPrepare(virConnectPtr conn, virDomainDiskDefPtr disk) { virStorageSourcePtr src = disk->src; - qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); if (qemuDomainSecretDiskCapable(src)) { @@ -1466,7 +1460,7 @@ qemuDomainSecretDiskPrepare(virConnectPtr conn, } if (qemuDomainDiskHasEncryptionSecret(src)) { - if (!(diskPriv->encinfo = + if (!(diskSrcPriv->encinfo = qemuDomainSecretInfoNew(conn, priv, disk->info.alias, VIR_SECRET_USAGE_TYPE_VOLUME, NULL, &src->encryption->secrets[0]->seclookupdef, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index fc4f5bc6d8..97b2caefe3 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -345,11 +345,6 @@ struct _qemuDomainDiskPrivate { bool migrating; /* the disk is being migrated */ - /* for storage devices using encryption/secret - * Can have both <auth> and <encryption> for some disks - * NB:*not* to be written to qemu domain object XML */ - qemuDomainSecretInfoPtr encinfo; - /* information about the device */ bool tray; /* device has tray */ bool removable; /* device media can be removed/changed */ @@ -366,6 +361,11 @@ struct _qemuDomainDiskSrcPrivate { /* for each storage source using auth/secret * NB: *not* to be written to qemu domain object XML */ qemuDomainSecretInfoPtr secinfo; + + /* for storage devices using encryption/secret + * Can have both <auth> and <encryption> for some disks + * NB:*not* to be written to qemu domain object XML */ + qemuDomainSecretInfoPtr encinfo; }; # define QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev) \ diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 544a592fb7..7cfe8f1bc6 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -369,7 +369,6 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, const char *src = virDomainDiskGetSource(disk); virJSONValuePtr secobjProps = NULL; virJSONValuePtr encobjProps = NULL; - qemuDomainDiskPrivatePtr diskPriv; qemuDomainDiskSrcPrivatePtr diskSrcPriv; qemuDomainSecretInfoPtr secinfo; qemuDomainSecretInfoPtr encinfo; @@ -407,7 +406,6 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, if (qemuDomainSecretDiskPrepare(conn, priv, disk) < 0) goto error; - diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); secinfo = diskSrcPriv->secinfo; if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES) { @@ -415,7 +413,7 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, goto error; } - encinfo = diskPriv->encinfo; + encinfo = diskSrcPriv->encinfo; if (encinfo && qemuBuildSecretInfoProps(encinfo, &encobjProps) < 0) goto error; @@ -673,7 +671,6 @@ qemuDomainAttachSCSIDisk(virConnectPtr conn, virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virJSONValuePtr encobjProps = NULL; virJSONValuePtr secobjProps = NULL; - qemuDomainDiskPrivatePtr diskPriv; qemuDomainDiskSrcPrivatePtr diskSrcPriv; qemuDomainSecretInfoPtr encinfo; qemuDomainSecretInfoPtr secinfo; @@ -707,7 +704,6 @@ qemuDomainAttachSCSIDisk(virConnectPtr conn, if (qemuDomainSecretDiskPrepare(conn, priv, disk) < 0) goto error; - diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(disk->src); secinfo = diskSrcPriv->secinfo; if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES) { @@ -715,7 +711,7 @@ qemuDomainAttachSCSIDisk(virConnectPtr conn, goto error; } - encinfo = diskPriv->encinfo; + encinfo = diskSrcPriv->encinfo; if (encinfo && qemuBuildSecretInfoProps(encinfo, &encobjProps) < 0) goto error; -- 2.13.6

Signed-off-by: John Ferlan <jferlan@redhat.com> --- docs/news.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/news.xml b/docs/news.xml index 4e8d7c940a..09cd1cd340 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -37,6 +37,19 @@ <section title="New features"> </section> <section title="Improvements"> + <change> + <summary> + conf: Move the auth and encryption definitions to disk source + </summary> + <description> + Allow parsing and formatting of the <code>auth</code> and + <code>encryption</code> sub-elements to be a child of the + <code>source</code> element. This will allow adding an + <code>auth</code> sub-element to a <code>backingStore</code> + or <code>mirror</code> elements as a means to track specific + authentication and/or encryption needs. + </description> + </change> </section> <section title="Bug fixes"> <change> -- 2.13.6

Rather than picking apart the two pieces we need/want (path, hosts, and auth)- let's just use the new virDomainDiskStorageSourceNew API in order to allocate and use a virStorageSourcePtr. The end result is that qemuBuildSCSIiSCSIHostdevDrvStr doesn't need to "fake" one for the qemuBuildNetworkDriveStr call. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/conf/domain_conf.c | 71 ++++++++++++++++++++++++++++--------------------- src/conf/domain_conf.h | 5 +--- src/qemu/qemu_command.c | 10 +------ src/qemu/qemu_domain.c | 8 +++--- src/qemu/qemu_hotplug.c | 2 +- 5 files changed, 47 insertions(+), 49 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c2be9b7155..c9a0628001 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2497,10 +2497,9 @@ virDomainHostdevSubsysSCSIiSCSIClear(virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc { if (!iscsisrc) return; - VIR_FREE(iscsisrc->path); - virStorageNetHostDefFree(iscsisrc->nhosts, iscsisrc->hosts); - virStorageAuthDefFree(iscsisrc->auth); - iscsisrc->auth = NULL; + + virStorageSourceFree(iscsisrc->src); + iscsisrc->src = NULL; } @@ -4373,7 +4372,7 @@ virDomainHostdevDefPostParse(virDomainHostdevDefPtr dev, if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; - if (virDomainPostParseCheckISCSIPath(&iscsisrc->path) < 0) + if (virDomainPostParseCheckISCSIPath(&iscsisrc->src->path) < 0) return -1; } @@ -6915,7 +6914,8 @@ virDomainHostdevSubsysSCSIHostDefParseXML(xmlNodePtr sourcenode, } static int -virDomainHostdevSubsysSCSIiSCSIDefParseXML(xmlNodePtr sourcenode, +virDomainHostdevSubsysSCSIiSCSIDefParseXML(virDomainXMLOptionPtr xmlopt, + xmlNodePtr sourcenode, virDomainHostdevSubsysSCSIPtr def) { int ret = -1; @@ -6924,24 +6924,29 @@ virDomainHostdevSubsysSCSIiSCSIDefParseXML(xmlNodePtr sourcenode, virStorageAuthDefPtr authdef = NULL; virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &def->u.iscsi; - /* Similar to virDomainDiskSourceParse for a VIR_STORAGE_TYPE_NETWORK */ + /* For the purposes of command line creation, this needs to look + * like a disk storage source */ + if (!(iscsisrc->src = virDomainDiskStorageSourceNew(xmlopt))) + return -1; + iscsisrc->src->type = VIR_STORAGE_TYPE_NETWORK; + iscsisrc->src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI; - if (!(iscsisrc->path = virXMLPropString(sourcenode, "name"))) { + if (!(iscsisrc->src->path = virXMLPropString(sourcenode, "name"))) { virReportError(VIR_ERR_XML_ERROR, "%s", _("missing iSCSI hostdev source path name")); goto cleanup; } - if (virDomainStorageNetworkParseHosts(sourcenode, &iscsisrc->hosts, - &iscsisrc->nhosts) < 0) + if (virDomainStorageNetworkParseHosts(sourcenode, &iscsisrc->src->hosts, + &iscsisrc->src->nhosts) < 0) goto cleanup; - if (iscsisrc->nhosts < 1) { + if (iscsisrc->src->nhosts < 1) { virReportError(VIR_ERR_XML_ERROR, "%s", _("missing the host address for the iSCSI hostdev")); goto cleanup; } - if (iscsisrc->nhosts > 1) { + if (iscsisrc->src->nhosts > 1) { virReportError(VIR_ERR_XML_ERROR, "%s", _("only one source host address may be specified " "for the iSCSI hostdev")); @@ -6967,7 +6972,7 @@ virDomainHostdevSubsysSCSIiSCSIDefParseXML(xmlNodePtr sourcenode, authdef->secrettype); goto cleanup; } - iscsisrc->auth = authdef; + iscsisrc->src->auth = authdef; authdef = NULL; } cur = cur->next; @@ -6980,7 +6985,8 @@ virDomainHostdevSubsysSCSIiSCSIDefParseXML(xmlNodePtr sourcenode, } static int -virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode, +virDomainHostdevSubsysSCSIDefParseXML(virDomainXMLOptionPtr xmlopt, + xmlNodePtr sourcenode, virDomainHostdevSubsysSCSIPtr scsisrc) { char *protocol = NULL; @@ -6998,7 +7004,8 @@ virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode, } if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) - ret = virDomainHostdevSubsysSCSIiSCSIDefParseXML(sourcenode, scsisrc); + ret = virDomainHostdevSubsysSCSIiSCSIDefParseXML(xmlopt, sourcenode, + scsisrc); else ret = virDomainHostdevSubsysSCSIHostDefParseXML(sourcenode, scsisrc); @@ -7099,7 +7106,8 @@ virDomainHostdevSubsysMediatedDevDefParseXML(virDomainHostdevDefPtr def, } static int -virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, +virDomainHostdevDefParseXMLSubsys(virDomainXMLOptionPtr xmlopt, + xmlNodePtr node, xmlXPathContextPtr ctxt, const char *type, virDomainHostdevDefPtr def, @@ -7243,7 +7251,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: - if (virDomainHostdevSubsysSCSIDefParseXML(sourcenode, scsisrc) < 0) + if (virDomainHostdevSubsysSCSIDefParseXML(xmlopt, sourcenode, scsisrc) < 0) goto error; break; @@ -10164,7 +10172,8 @@ virDomainFSDefParseXML(xmlNodePtr node, } static int -virDomainActualNetDefParseXML(xmlNodePtr node, +virDomainActualNetDefParseXML(virDomainXMLOptionPtr xmlopt, + xmlNodePtr node, xmlXPathContextPtr ctxt, virDomainNetDefPtr parent, virDomainActualNetDefPtr *def, @@ -10274,7 +10283,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node, VIR_STRDUP(addrtype, "usb") < 0) goto error; hostdev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; - if (virDomainHostdevDefParseXMLSubsys(node, ctxt, addrtype, + if (virDomainHostdevDefParseXMLSubsys(xmlopt, node, ctxt, addrtype, hostdev, flags) < 0) { goto error; } @@ -10607,7 +10616,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, (flags & VIR_DOMAIN_DEF_PARSE_ACTUAL_NET) && def->type == VIR_DOMAIN_NET_TYPE_NETWORK && virXMLNodeNameEqual(cur, "actual")) { - if (virDomainActualNetDefParseXML(cur, ctxt, def, + if (virDomainActualNetDefParseXML(xmlopt, cur, ctxt, def, &actual, flags) < 0) { goto error; } @@ -10868,7 +10877,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_STRDUP(addrtype, "usb") < 0) goto error; hostdev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; - if (virDomainHostdevDefParseXMLSubsys(node, ctxt, addrtype, + if (virDomainHostdevDefParseXMLSubsys(xmlopt, node, ctxt, addrtype, hostdev, flags) < 0) { goto error; } @@ -14466,7 +14475,7 @@ virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt, switch (def->mode) { case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: /* parse managed/mode/type, and the <source> element */ - if (virDomainHostdevDefParseXMLSubsys(node, ctxt, type, def, flags) < 0) + if (virDomainHostdevDefParseXMLSubsys(xmlopt, node, ctxt, type, def, flags) < 0) goto error; break; case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: @@ -15440,9 +15449,9 @@ virDomainHostdevMatchSubsysSCSIiSCSI(virDomainHostdevDefPtr first, virDomainHostdevSubsysSCSIiSCSIPtr second_iscsisrc = &second->source.subsys.u.scsi.u.iscsi; - if (STREQ(first_iscsisrc->hosts[0].name, second_iscsisrc->hosts[0].name) && - first_iscsisrc->hosts[0].port == second_iscsisrc->hosts[0].port && - STREQ(first_iscsisrc->path, second_iscsisrc->path)) + if (STREQ(first_iscsisrc->src->hosts[0].name, second_iscsisrc->src->hosts[0].name) && + first_iscsisrc->src->hosts[0].port == second_iscsisrc->src->hosts[0].port && + STREQ(first_iscsisrc->src->path, second_iscsisrc->src->path)) return 1; return 0; } @@ -22750,7 +22759,7 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, virDomainHostdevSubsysSCSIProtocolTypeToString(scsisrc->protocol); virBufferAsprintf(buf, " protocol='%s' name='%s'", - protocol, iscsisrc->path); + protocol, iscsisrc->src->path); } if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) { @@ -22802,9 +22811,9 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { virBufferAddLit(buf, "<host"); - virBufferEscapeString(buf, " name='%s'", iscsisrc->hosts[0].name); - if (iscsisrc->hosts[0].port) - virBufferAsprintf(buf, " port='%u'", iscsisrc->hosts[0].port); + virBufferEscapeString(buf, " name='%s'", iscsisrc->src->hosts[0].name); + if (iscsisrc->src->hosts[0].port) + virBufferAsprintf(buf, " port='%u'", iscsisrc->src->hosts[0].port); virBufferAddLit(buf, "/>\n"); } else { virBufferAsprintf(buf, "<adapter name='%s'/>\n", @@ -22831,8 +22840,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI && scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI && - iscsisrc->auth) { - if (virStorageAuthDefFormat(buf, iscsisrc->auth) < 0) + iscsisrc->src->auth) { + if (virStorageAuthDefFormat(buf, iscsisrc->src->auth) < 0) return -1; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ca334e0147..dd3017e31b 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -357,10 +357,7 @@ struct _virDomainHostdevSubsysSCSIHost { typedef struct _virDomainHostdevSubsysSCSIiSCSI virDomainHostdevSubsysSCSIiSCSI; typedef virDomainHostdevSubsysSCSIiSCSI *virDomainHostdevSubsysSCSIiSCSIPtr; struct _virDomainHostdevSubsysSCSIiSCSI { - char *path; - size_t nhosts; - virStorageNetHostDefPtr hosts; - virStorageAuthDefPtr auth; + virStorageSourcePtr src; }; typedef struct _virDomainHostdevSubsysSCSI virDomainHostdevSubsysSCSI; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 97c4890935..26a98bd7e9 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4952,21 +4952,13 @@ static char * qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev) { char *source = NULL; - virStorageSource src; qemuDomainHostdevPrivatePtr hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(dev); - memset(&src, 0, sizeof(src)); - virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; - src.protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI; - src.path = iscsisrc->path; - src.hosts = iscsisrc->hosts; - src.nhosts = iscsisrc->nhosts; - /* Rather than pull what we think we want - use the network disk code */ - source = qemuBuildNetworkDriveStr(&src, hostdevPriv->secinfo); + source = qemuBuildNetworkDriveStr(iscsisrc->src, hostdevPriv->secinfo); return source; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index ad8d484cb1..ecf78b426c 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1509,7 +1509,7 @@ qemuDomainSecretHostdevPrepare(virConnectPtr conn, virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI && - iscsisrc->auth) { + iscsisrc->src->auth) { qemuDomainHostdevPrivatePtr hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev); @@ -1517,8 +1517,8 @@ qemuDomainSecretHostdevPrepare(virConnectPtr conn, if (!(hostdevPriv->secinfo = qemuDomainSecretInfoNew(conn, priv, hostdev->info->alias, VIR_SECRET_USAGE_TYPE_ISCSI, - iscsisrc->auth->username, - &iscsisrc->auth->seclookupdef, + iscsisrc->src->auth->username, + &iscsisrc->src->auth->seclookupdef, false))) return -1; } @@ -8046,7 +8046,7 @@ qemuDomainGetHostdevPath(virDomainDefPtr def, /* Follow qemuSetupDiskCgroup() and qemuSetImageCgroupInternal() * which does nothing for non local storage */ - VIR_DEBUG("Not updating /dev for hostdev iSCSI path '%s'", iscsisrc->path); + VIR_DEBUG("Not updating /dev for hostdev iSCSI path '%s'", iscsisrc->src->path); } else { virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; scsi = virSCSIDeviceNew(NULL, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 7cfe8f1bc6..1b5385d967 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -5065,7 +5065,7 @@ int qemuDomainDetachHostDevice(virQEMUDriverPtr driver, virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; virReportError(VIR_ERR_OPERATION_FAILED, _("host scsi iSCSI path %s not found"), - iscsisrc->path); + iscsisrc->src->path); } else { virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; -- 2.13.6

Rather than placing/using privateData about secinfo in the hostdev, let's use the virStorageSource (e.g. disksrc) instead. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 5 ++--- src/qemu/qemu_domain.c | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 26a98bd7e9..21f024fb88 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4952,13 +4952,12 @@ static char * qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev) { char *source = NULL; - qemuDomainHostdevPrivatePtr hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(dev); - virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; + qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(iscsisrc->src); /* Rather than pull what we think we want - use the network disk code */ - source = qemuBuildNetworkDriveStr(iscsisrc->src, hostdevPriv->secinfo); + source = qemuBuildNetworkDriveStr(iscsisrc->src, diskSrcPriv->secinfo); return source; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index ecf78b426c..916e900e9c 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1480,13 +1480,18 @@ qemuDomainSecretDiskPrepare(virConnectPtr conn, void qemuDomainSecretHostdevDestroy(virDomainHostdevDefPtr hostdev) { - qemuDomainHostdevPrivatePtr hostdevPriv = - QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev); + qemuDomainDiskSrcPrivatePtr diskSrcPriv; - if (!hostdevPriv || !hostdevPriv->secinfo) - return; + if (virHostdevIsSCSIDevice(hostdev)) { + virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; - qemuDomainSecretInfoFree(&hostdevPriv->secinfo); + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(iscsisrc->src); + if (diskSrcPriv && diskSrcPriv->secinfo) + qemuDomainSecretInfoFree(&diskSrcPriv->secinfo); + } + } } @@ -1511,10 +1516,10 @@ qemuDomainSecretHostdevPrepare(virConnectPtr conn, if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI && iscsisrc->src->auth) { - qemuDomainHostdevPrivatePtr hostdevPriv = - QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev); + qemuDomainDiskSrcPrivatePtr diskSrcPriv = + QEMU_DOMAIN_DISK_SRC_PRIVATE(iscsisrc->src); - if (!(hostdevPriv->secinfo = + if (!(diskSrcPriv->secinfo = qemuDomainSecretInfoNew(conn, priv, hostdev->info->alias, VIR_SECRET_USAGE_TYPE_ISCSI, iscsisrc->src->auth->username, -- 2.13.6

Since it's not longer used to shuttle the @secinfo, let's remove the private hostdev completely. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/conf/domain_conf.c | 12 ++--------- src/conf/domain_conf.h | 4 +--- src/lxc/lxc_native.c | 2 +- src/qemu/qemu_domain.c | 50 +++---------------------------------------- src/qemu/qemu_domain.h | 14 ------------ src/qemu/qemu_parse_command.c | 4 ++-- src/vbox/vbox_common.c | 2 +- src/xenconfig/xen_common.c | 2 +- src/xenconfig/xen_sxpr.c | 2 +- src/xenconfig/xen_xl.c | 2 +- tests/virhostdevtest.c | 2 +- 11 files changed, 14 insertions(+), 82 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c9a0628001..bd85a3b27b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2468,7 +2468,7 @@ void virDomainVideoDefFree(virDomainVideoDefPtr def) virDomainHostdevDefPtr -virDomainHostdevDefNew(virDomainXMLOptionPtr xmlopt) +virDomainHostdevDefNew(void) { virDomainHostdevDefPtr def; @@ -2478,11 +2478,6 @@ virDomainHostdevDefNew(virDomainXMLOptionPtr xmlopt) if (VIR_ALLOC(def->info) < 0) goto error; - if (xmlopt && - xmlopt->privateData.hostdevNew && - !(def->privateData = xmlopt->privateData.hostdevNew())) - goto error; - return def; error: @@ -2561,9 +2556,6 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def) } break; } - - virObjectUnref(def->privateData); - def->privateData = NULL; } void virDomainTPMDefFree(virDomainTPMDefPtr def) @@ -14459,7 +14451,7 @@ virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt, ctxt->node = node; - if (!(def = virDomainHostdevDefNew(xmlopt))) + if (!(def = virDomainHostdevDefNew())) goto error; if (mode) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index dd3017e31b..169b90c754 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -439,7 +439,6 @@ struct _virDomainHostdevCaps { /* basic device for direct passthrough */ struct _virDomainHostdevDef { virDomainDeviceDef parent; /* higher level Def containing this */ - virObjectPtr privateData; int mode; /* enum virDomainHostdevMode */ int startupPolicy; /* enum virDomainStartupPolicy */ @@ -2619,7 +2618,6 @@ struct _virDomainXMLPrivateDataCallbacks { * virDomainDefCopy and similar functions */ virDomainXMLPrivateDataNewFunc diskNew; virDomainXMLPrivateDataNewFunc diskSrcNew; - virDomainXMLPrivateDataNewFunc hostdevNew; virDomainXMLPrivateDataNewFunc vcpuNew; virDomainXMLPrivateDataNewFunc chrSourceNew; virDomainXMLPrivateDataFormatFunc format; @@ -2740,7 +2738,7 @@ void virDomainNVRAMDefFree(virDomainNVRAMDefPtr def); void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def); virDomainVideoDefPtr virDomainVideoDefNew(void); void virDomainVideoDefFree(virDomainVideoDefPtr def); -virDomainHostdevDefPtr virDomainHostdevDefNew(virDomainXMLOptionPtr xmlopt); +virDomainHostdevDefPtr virDomainHostdevDefNew(void); void virDomainHostdevDefClear(virDomainHostdevDefPtr def); void virDomainHostdevDefFree(virDomainHostdevDefPtr def); void virDomainHubDefFree(virDomainHubDefPtr def); diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c index 5fc6e7cda4..033dd427cd 100644 --- a/src/lxc/lxc_native.c +++ b/src/lxc/lxc_native.c @@ -394,7 +394,7 @@ lxcCreateNetDef(const char *type, static virDomainHostdevDefPtr lxcCreateHostdevDef(int mode, int type, const char *data) { - virDomainHostdevDefPtr hostdev = virDomainHostdevDefNew(NULL); + virDomainHostdevDefPtr hostdev = virDomainHostdevDefNew(); if (!hostdev) return NULL; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 916e900e9c..a6c1d605b3 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1025,49 +1025,6 @@ qemuDomainDiskSrcPrivateDispose(void *obj) } -static virClassPtr qemuDomainHostdevPrivateClass; -static void qemuDomainHostdevPrivateDispose(void *obj); - -static int -qemuDomainHostdevPrivateOnceInit(void) -{ - qemuDomainHostdevPrivateClass = - virClassNew(virClassForObject(), - "qemuDomainHostdevPrivate", - sizeof(qemuDomainHostdevPrivate), - qemuDomainHostdevPrivateDispose); - if (!qemuDomainHostdevPrivateClass) - return -1; - else - return 0; -} - -VIR_ONCE_GLOBAL_INIT(qemuDomainHostdevPrivate) - -static virObjectPtr -qemuDomainHostdevPrivateNew(void) -{ - qemuDomainHostdevPrivatePtr priv; - - if (qemuDomainHostdevPrivateInitialize() < 0) - return NULL; - - if (!(priv = virObjectNew(qemuDomainHostdevPrivateClass))) - return NULL; - - return (virObjectPtr) priv; -} - - -static void -qemuDomainHostdevPrivateDispose(void *obj) -{ - qemuDomainHostdevPrivatePtr priv = obj; - - qemuDomainSecretInfoFree(&priv->secinfo); -} - - static virClassPtr qemuDomainVcpuPrivateClass; static void qemuDomainVcpuPrivateDispose(void *obj); @@ -1480,14 +1437,14 @@ qemuDomainSecretDiskPrepare(virConnectPtr conn, void qemuDomainSecretHostdevDestroy(virDomainHostdevDefPtr hostdev) { - qemuDomainDiskSrcPrivatePtr diskSrcPriv; - if (virHostdevIsSCSIDevice(hostdev)) { virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi; virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { - diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(iscsisrc->src); + qemuDomainDiskSrcPrivatePtr diskSrcPriv = + QEMU_DOMAIN_DISK_SRC_PRIVATE(iscsisrc->src); + if (diskSrcPriv && diskSrcPriv->secinfo) qemuDomainSecretInfoFree(&diskSrcPriv->secinfo); } @@ -2409,7 +2366,6 @@ virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = { .diskNew = qemuDomainDiskPrivateNew, .diskSrcNew = qemuDomainDiskSrcPrivateNew, .vcpuNew = qemuDomainVcpuPrivateNew, - .hostdevNew = qemuDomainHostdevPrivateNew, .chrSourceNew = qemuDomainChrSourcePrivateNew, .parse = qemuDomainObjPrivateXMLParse, .format = qemuDomainObjPrivateXMLFormat, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 97b2caefe3..35ed7b7c78 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -368,10 +368,6 @@ struct _qemuDomainDiskSrcPrivate { qemuDomainSecretInfoPtr encinfo; }; -# define QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev) \ - ((qemuDomainHostdevPrivatePtr) (hostdev)->privateData) - - typedef struct _qemuDomainVcpuPrivate qemuDomainVcpuPrivate; typedef qemuDomainVcpuPrivate *qemuDomainVcpuPrivatePtr; struct _qemuDomainVcpuPrivate { @@ -406,16 +402,6 @@ struct qemuDomainDiskInfo { char *nodename; }; -typedef struct _qemuDomainHostdevPrivate qemuDomainHostdevPrivate; -typedef qemuDomainHostdevPrivate *qemuDomainHostdevPrivatePtr; -struct _qemuDomainHostdevPrivate { - virObject parent; - - /* for hostdev storage devices using auth/secret - * NB: *not* to be written to qemu domain object XML */ - qemuDomainSecretInfoPtr secinfo; -}; - # define QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev) \ ((qemuDomainChrSourcePrivatePtr) (dev)->privateData) diff --git a/src/qemu/qemu_parse_command.c b/src/qemu/qemu_parse_command.c index 37e1149c08..d11686c0a9 100644 --- a/src/qemu/qemu_parse_command.c +++ b/src/qemu/qemu_parse_command.c @@ -1158,7 +1158,7 @@ qemuParseCommandLinePCI(const char *val) int bus = 0, slot = 0, func = 0; const char *start; char *end; - virDomainHostdevDefPtr def = virDomainHostdevDefNew(NULL); + virDomainHostdevDefPtr def = virDomainHostdevDefNew(); if (!def) goto error; @@ -1208,7 +1208,7 @@ qemuParseCommandLinePCI(const char *val) static virDomainHostdevDefPtr qemuParseCommandLineUSB(const char *val) { - virDomainHostdevDefPtr def = virDomainHostdevDefNew(NULL); + virDomainHostdevDefPtr def = virDomainHostdevDefNew(); virDomainHostdevSubsysUSBPtr usbsrc; int first = 0, second = 0; const char *start; diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 92ee371641..3ffaab8578 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2989,7 +2989,7 @@ vboxHostDeviceGetXMLDesc(vboxDriverPtr data, virDomainDefPtr def, IMachine *mach goto release_filters; for (i = 0; i < def->nhostdevs; i++) { - def->hostdevs[i] = virDomainHostdevDefNew(NULL); + def->hostdevs[i] = virDomainHostdevDefNew(); if (!def->hostdevs[i]) goto release_hostdevs; } diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index 6d7dc2cde4..1ad9935396 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -458,7 +458,7 @@ xenParsePCI(virConfPtr conf, virDomainDefPtr def) goto skippci; if (virStrToLong_i(func, NULL, 16, &funcID) < 0) goto skippci; - if (!(hostdev = virDomainHostdevDefNew(NULL))) + if (!(hostdev = virDomainHostdevDefNew())) return -1; hostdev->managed = false; diff --git a/src/xenconfig/xen_sxpr.c b/src/xenconfig/xen_sxpr.c index fefa61ac23..5e7a386b10 100644 --- a/src/xenconfig/xen_sxpr.c +++ b/src/xenconfig/xen_sxpr.c @@ -1110,7 +1110,7 @@ xenParseSxprPCI(virDomainDefPtr def, goto error; } - if (!(dev = virDomainHostdevDefNew(NULL))) + if (!(dev = virDomainHostdevDefNew())) goto error; dev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c index 8acbfe3f69..64011d9cbe 100644 --- a/src/xenconfig/xen_xl.c +++ b/src/xenconfig/xen_xl.c @@ -733,7 +733,7 @@ xenParseXLUSB(virConfPtr conf, virDomainDefPtr def) goto skipusb; if (virStrToLong_i(device, NULL, 16, &devNum) < 0) goto skipusb; - if (!(hostdev = virDomainHostdevDefNew(NULL))) + if (!(hostdev = virDomainHostdevDefNew())) return -1; hostdev->managed = false; diff --git a/tests/virhostdevtest.c b/tests/virhostdevtest.c index 0ad58ddf3d..66a0a20e39 100644 --- a/tests/virhostdevtest.c +++ b/tests/virhostdevtest.c @@ -88,7 +88,7 @@ myInit(void) for (i = 0; i < nhostdevs; i++) { virDomainHostdevSubsys subsys; - hostdevs[i] = virDomainHostdevDefNew(NULL); + hostdevs[i] = virDomainHostdevDefNew(); if (!hostdevs[i]) goto cleanup; hostdevs[i]->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; -- 2.13.6

Rather than building the "file" string in qemuBuildSCSIHostdevDrvStr build it in the called helper. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 21f024fb88..47fa307097 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4952,13 +4952,20 @@ static char * qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev) { char *source = NULL; + char *netsource = NULL; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(iscsisrc->src); /* Rather than pull what we think we want - use the network disk code */ - source = qemuBuildNetworkDriveStr(iscsisrc->src, diskSrcPriv->secinfo); + netsource = qemuBuildNetworkDriveStr(iscsisrc->src, diskSrcPriv->secinfo); + if (!netsource) + goto cleanup; + if (virAsprintf(&source, "file=%s,if=none,format=raw", netsource) < 0) + goto cleanup; + cleanup: + VIR_FREE(netsource); return source; } @@ -5011,7 +5018,7 @@ qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev) if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { if (!(source = qemuBuildSCSIiSCSIHostdevDrvStr(dev))) goto error; - virBufferAsprintf(&buf, "file=%s,if=none,format=raw", source); + virBufferAsprintf(&buf, "%s", source); } else { if (!(source = qemuBuildSCSIHostHostdevDrvStr(dev))) goto error; -- 2.13.6

Add the capability to use the blockdev-add query-qmp-schema option to find the 'password-secret' parameter that will allow the iSCSI code to use the master secret object to encrypt the secret for an and only need to provide the object id of the secret on the command line thus obsfuscating the passphrase. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 + 7 files changed, 8 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f9028157f1..3e9cc6d112 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -443,6 +443,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, /* 270 */ "vxhs", "virtio-blk.num-queues", + "iscsi.password-secret", ); @@ -1804,6 +1805,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "blockdev-add/arg-type/options/+gluster/debug-level", QEMU_CAPS_GLUSTER_DEBUG_LEVEL}, { "blockdev-add/arg-type/+gluster/debug", QEMU_CAPS_GLUSTER_DEBUG_LEVEL}, { "blockdev-add/arg-type/+vxhs", QEMU_CAPS_VXHS}, + { "blockdev-add/arg-type/+iscsi/password-secret", QEMU_CAPS_ISCSI_PASSWORD_SECRET }, }; struct virQEMUCapsObjectTypeProps { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 2d16e5b0ef..e07891932d 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -429,6 +429,7 @@ typedef enum { /* 270 */ QEMU_CAPS_VXHS, /* -drive file.driver=vxhs via query-qmp-schema */ QEMU_CAPS_VIRTIO_BLK_NUM_QUEUES, /* virtio-blk-*.num-queues */ + QEMU_CAPS_ISCSI_PASSWORD_SECRET, /* -drive file.driver=iscsi,...,password-secret= */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml index 2546ebdd9d..00697a6c87 100644 --- a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml @@ -141,6 +141,7 @@ <flag name='virtio-gpu.max_outputs'/> <flag name='vxhs'/> <flag name='virtio-blk.num-queues'/> + <flag name='iscsi.password-secret'/> <version>2010000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml index 10a182e185..6623b820f7 100644 --- a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml @@ -224,6 +224,7 @@ <flag name='virtio-gpu.max_outputs'/> <flag name='vxhs'/> <flag name='virtio-blk.num-queues'/> + <flag name='iscsi.password-secret'/> <version>2010000</version> <kvmVersion>0</kvmVersion> <package> (v2.10.0)</package> diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml index 786cea8eab..e2bba89d40 100644 --- a/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml +++ b/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml @@ -173,6 +173,7 @@ <flag name='chardev-reconnect'/> <flag name='virtio-gpu.max_outputs'/> <flag name='virtio-blk.num-queues'/> + <flag name='iscsi.password-secret'/> <version>2009000</version> <kvmVersion>0</kvmVersion> <package> (v2.9.0)</package> diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml index 896ed503c3..4dc9ad5b56 100644 --- a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml @@ -138,6 +138,7 @@ <flag name='chardev-reconnect'/> <flag name='virtio-gpu.max_outputs'/> <flag name='virtio-blk.num-queues'/> + <flag name='iscsi.password-secret'/> <version>2009000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml index e3ff127270..5cfdc352d6 100644 --- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml @@ -221,6 +221,7 @@ <flag name='chardev-reconnect'/> <flag name='virtio-gpu.max_outputs'/> <flag name='virtio-blk.num-queues'/> + <flag name='iscsi.password-secret'/> <version>2009000</version> <kvmVersion>0</kvmVersion> <package> (v2.9.0)</package> -- 2.13.6

https://bugzilla.redhat.com/show_bug.cgi?id=1425757 The blockdev-add code provides a mechanism to sanely provide user and password-secret arguments for iscsi without placing them on the command line to be viewable by a 'ps -ef' type command or needing to create separate -iscsi devices for each disk/volume found. So modify the iSCSI command line building to check for the presence of the capability in order properly setup and use the domain master secret object to encrypt the password in a secret object and alter the parameters for the command line to utilize. Modify the xml2argvtest to exhibit the syntax for both disk and hostdev configurations. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_block.c | 64 +++++++++++++++++++++- src/qemu/qemu_command.c | 62 ++++++++++++++++----- src/qemu/qemu_command.h | 3 +- src/qemu/qemu_domain.c | 4 ++ src/qemu/qemu_hotplug.c | 50 ++++++++++++++++- ...xml2argv-disk-drive-network-iscsi-auth-AES.args | 41 ++++++++++++++ ...uxml2argv-disk-drive-network-iscsi-auth-AES.xml | 43 +++++++++++++++ ...ml2argv-hostdev-scsi-virtio-iscsi-auth-AES.args | 45 +++++++++++++++ ...xml2argv-hostdev-scsi-virtio-iscsi-auth-AES.xml | 48 ++++++++++++++++ tests/qemuxml2argvtest.c | 10 ++++ 10 files changed, 353 insertions(+), 17 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.xml diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 8d232de3e3..effbd1a207 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -560,6 +560,64 @@ qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src) } +static virJSONValuePtr +qemuBlockStorageSourceGetISCSIProps(virStorageSourcePtr src) +{ + const char *protocol = virStorageNetProtocolTypeToString(src->protocol); + char *target = NULL; + char *lunStr = NULL; + char *username = NULL; + char *objalias = NULL; + unsigned int lun = 0; + virJSONValuePtr ret = NULL; + qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(src); + + /* { driver:"iscsi", + * transport:"tcp", ("iser" also possible) + * portal:"example.com", + * target:"iqn.2017-04.com.example:iscsi-disks", + * lun:1, + * user:"username", + * password-secret:"secret-alias", + * } + */ + + if (VIR_STRDUP(target, src->path) < 0) + goto cleanup; + + /* Separate the target and lun */ + if ((lunStr = strchr(target, '/'))) { + *(lunStr++) = '\0'; + if (virStrToLong_ui(lunStr, NULL, 10, &lun) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse target for lunStr '%s'"), + target); + goto cleanup; + } + } + + if (src->auth) { + username = src->auth->username; + objalias = diskSrcPriv->secinfo->s.aes.alias; + } + + ignore_value(virJSONValueObjectCreate(&ret, + "s:driver", protocol, + "s:portal", src->hosts[0].name, + "s:target", target, + "u:lun", lun, + "s:transport", "tcp", + "S:user", username, + "S:password-secret", objalias, + NULL)); + goto cleanup; + + cleanup: + VIR_FREE(target); + return ret; +} + + /** * qemuBlockStorageSourceGetBackendProps: * @src: disk source @@ -595,10 +653,14 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src) goto cleanup; break; + case VIR_STORAGE_NET_PROTOCOL_ISCSI: + if (!(fileprops = qemuBlockStorageSourceGetISCSIProps(src))) + goto cleanup; + break; + case VIR_STORAGE_NET_PROTOCOL_NBD: case VIR_STORAGE_NET_PROTOCOL_RBD: case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG: - case VIR_STORAGE_NET_PROTOCOL_ISCSI: case VIR_STORAGE_NET_PROTOCOL_HTTP: case VIR_STORAGE_NET_PROTOCOL_HTTPS: case VIR_STORAGE_NET_PROTOCOL_FTP: diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 47fa307097..e155378dba 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1353,7 +1353,8 @@ qemuDiskBusNeedsDeviceArg(int bus) * the legacy representation. */ static bool -qemuDiskSourceNeedsProps(virStorageSourcePtr src) +qemuDiskSourceNeedsProps(virStorageSourcePtr src, + virQEMUCapsPtr qemuCaps) { int actualType = virStorageSourceGetActualType(src); @@ -1366,6 +1367,11 @@ qemuDiskSourceNeedsProps(virStorageSourcePtr src) src->protocol == VIR_STORAGE_NET_PROTOCOL_VXHS) return true; + if (actualType == VIR_STORAGE_TYPE_NETWORK && + src->protocol == VIR_STORAGE_NET_PROTOCOL_ISCSI && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_ISCSI_PASSWORD_SECRET)) + return true; + return false; } @@ -1384,7 +1390,7 @@ qemuBuildDriveSourceStr(virDomainDiskDefPtr disk, char *source = NULL; int ret = -1; - if (qemuDiskSourceNeedsProps(disk->src) && + if (qemuDiskSourceNeedsProps(disk->src, qemuCaps) && !(srcprops = qemuBlockStorageSourceGetBackendProps(disk->src))) goto cleanup; @@ -1450,7 +1456,9 @@ qemuBuildDriveSourceStr(virDomainDiskDefPtr disk, virBufferAsprintf(buf, "file.debug=%d,", cfg->glusterDebugLevel); } - if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES) { + if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES && + disk->src->type == VIR_STORAGE_TYPE_NETWORK && + disk->src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD) { /* NB: If libvirt starts using the more modern option based * syntax to build the command line (e.g., "-drive driver=rbd, * filename=%s,...") instead of the legacy model (e.g."-drive @@ -4949,20 +4957,35 @@ qemuBuildSCSIHostHostdevDrvStr(virDomainHostdevDefPtr dev) } static char * -qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev) +qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps) { char *source = NULL; char *netsource = NULL; + virJSONValuePtr srcprops = NULL; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; qemuDomainDiskSrcPrivatePtr diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(iscsisrc->src); - /* Rather than pull what we think we want - use the network disk code */ - netsource = qemuBuildNetworkDriveStr(iscsisrc->src, diskSrcPriv->secinfo); - if (!netsource) - goto cleanup; - if (virAsprintf(&source, "file=%s,if=none,format=raw", netsource) < 0) - goto cleanup; + if (qemuDiskSourceNeedsProps(iscsisrc->src, qemuCaps)) { + if (!(srcprops = qemuBlockStorageSourceGetBackendProps(iscsisrc->src))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to build the backend props")); + goto cleanup; + } + + if (!(netsource = virQEMUBuildDriveCommandlineFromJSON(srcprops))) + goto cleanup; + if (virAsprintf(&source, "%s,if=none,format=raw", netsource) < 0) + goto cleanup; + } else { + /* Rather than pull what we think we want - use the network disk code */ + if (!(netsource = qemuBuildNetworkDriveStr(iscsisrc->src, + diskSrcPriv->secinfo))) + goto cleanup; + if (virAsprintf(&source, "file=%s,if=none,format=raw", netsource) < 0) + goto cleanup; + } cleanup: VIR_FREE(netsource); @@ -5008,7 +5031,8 @@ qemuBuildSCSIVHostHostdevDevStr(const virDomainDef *def, } char * -qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev) +qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps) { virBuffer buf = VIR_BUFFER_INITIALIZER; char *source = NULL; @@ -5016,7 +5040,7 @@ qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev) virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { - if (!(source = qemuBuildSCSIiSCSIHostdevDrvStr(dev))) + if (!(source = qemuBuildSCSIiSCSIHostdevDrvStr(dev, qemuCaps))) goto error; virBufferAsprintf(&buf, "%s", source); } else { @@ -5515,10 +5539,22 @@ qemuBuildHostdevCommandLine(virCommandPtr cmd, /* SCSI */ if (virHostdevIsSCSIDevice(hostdev)) { if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) { + virDomainHostdevSubsysSCSIPtr scsisrc = + &hostdev->source.subsys.u.scsi; char *drvstr; + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) { + virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = + &scsisrc->u.iscsi; + qemuDomainDiskSrcPrivatePtr diskSrcPriv = + QEMU_DOMAIN_DISK_SRC_PRIVATE(iscsisrc->src); + + if (qemuBuildDiskSecinfoCommandLine(cmd, diskSrcPriv->secinfo) < 0) + return -1; + } + virCommandAddArg(cmd, "-drive"); - if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev))) + if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, qemuCaps))) return -1; virCommandAddArg(cmd, drvstr); VIR_FREE(drvstr); diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 94e4592ccd..ea35687abe 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -158,7 +158,8 @@ char *qemuBuildUSBHostdevDevStr(const virDomainDef *def, virDomainHostdevDefPtr dev, virQEMUCapsPtr qemuCaps); -char *qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev); +char *qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps); char *qemuBuildSCSIHostdevDevStr(const virDomainDef *def, virDomainHostdevDefPtr dev, diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index a6c1d605b3..0043c74acd 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1244,9 +1244,13 @@ qemuDomainSecretSetup(virConnectPtr conn, virSecretLookupTypeDefPtr seclookupdef, bool isLuks) { + bool iscsiHasPS = virQEMUCapsGet(priv->qemuCaps, + QEMU_CAPS_ISCSI_PASSWORD_SECRET); + if (virCryptoHaveCipher(VIR_CRYPTO_CIPHER_AES256CBC) && virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_SECRET) && (usageType == VIR_SECRET_USAGE_TYPE_CEPH || + (usageType == VIR_SECRET_USAGE_TYPE_ISCSI && iscsiHasPS) || usageType == VIR_SECRET_USAGE_TYPE_VOLUME || usageType == VIR_SECRET_USAGE_TYPE_TLS)) { if (qemuDomainSecretAESSetup(conn, priv, secinfo, srcalias, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 1b5385d967..e206d1901b 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2510,6 +2510,7 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, virDomainHostdevDefPtr hostdev) { size_t i; + int rv; int ret = -1; qemuDomainObjPrivatePtr priv = vm->privateData; virErrorPtr orig_err; @@ -2520,6 +2521,12 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, bool teardownlabel = false; bool teardowndevice = false; bool driveAdded = false; + bool secobjAdded = false; + virJSONValuePtr secobjProps = NULL; + virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; + qemuDomainDiskSrcPrivatePtr diskSrcPriv; + qemuDomainSecretInfoPtr secinfo; if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -2560,7 +2567,14 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, if (qemuDomainSecretHostdevPrepare(conn, priv, hostdev) < 0) goto cleanup; - if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev))) + diskSrcPriv = QEMU_DOMAIN_DISK_SRC_PRIVATE(iscsisrc->src); + secinfo = diskSrcPriv->secinfo; + if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES) { + if (qemuBuildSecretInfoProps(secinfo, &secobjProps) < 0) + goto cleanup; + } + + if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, priv->qemuCaps))) goto cleanup; if (!(drivealias = qemuAliasFromHostdev(hostdev))) @@ -2574,6 +2588,15 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, qemuDomainObjEnterMonitor(driver, vm); + if (secobjProps) { + rv = qemuMonitorAddObject(priv->mon, "secret", secinfo->s.aes.alias, + secobjProps); + secobjProps = NULL; /* qemuMonitorAddObject consumes */ + if (rv < 0) + goto exit_monitor; + secobjAdded = true; + } + if (qemuMonitorAddDrive(priv->mon, drvstr) < 0) goto exit_monitor; driveAdded = true; @@ -2591,7 +2614,6 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, ret = 0; cleanup: - qemuDomainSecretHostdevDestroy(hostdev); if (ret < 0) { qemuHostdevReAttachSCSIDevices(driver, vm->def->name, &hostdev, 1); if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0) @@ -2603,6 +2625,8 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, qemuDomainNamespaceTeardownHostdev(driver, vm, hostdev) < 0) VIR_WARN("Unable to remove host device from /dev"); } + qemuDomainSecretHostdevDestroy(hostdev); + virJSONValueFree(secobjProps); VIR_FREE(drivealias); VIR_FREE(drvstr); VIR_FREE(devstr); @@ -2615,6 +2639,8 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, "qemuMonitorAddDevice", drvstr, devstr); } + if (secobjAdded) + ignore_value(qemuMonitorDelObject(priv->mon, secinfo->s.aes.alias)); ignore_value(qemuDomainObjExitMonitor(driver, vm)); virErrorRestore(&orig_err); @@ -3997,6 +4023,7 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, int ret = -1; qemuDomainObjPrivatePtr priv = vm->privateData; char *drivealias = NULL; + char *objAlias = NULL; bool is_vfio = false; VIR_DEBUG("Removing host device %s from domain %p %s", @@ -4008,11 +4035,29 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, } if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { + virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; + if (!(drivealias = qemuAliasFromHostdev(hostdev))) goto cleanup; + /* Look for the markers that the iSCSI hostdev was added with a + * secret object to manage the username/password. If present, let's + * attempt to remove the object as well. */ + if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI && + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_ISCSI_PASSWORD_SECRET) && + qemuDomainSecretDiskCapable(iscsisrc->src)) { + if (!(objAlias = qemuDomainGetSecretAESAlias(hostdev->info->alias, false))) + goto cleanup; + } + qemuDomainObjEnterMonitor(driver, vm); qemuMonitorDriveDel(priv->mon, drivealias); + + /* If it fails, then so be it - it was a best shot */ + if (objAlias) + ignore_value(qemuMonitorDelObject(priv->mon, objAlias)); + if (qemuDomainObjExitMonitor(driver, vm) < 0) goto cleanup; } @@ -4084,6 +4129,7 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, cleanup: VIR_FREE(drivealias); + VIR_FREE(objAlias); virObjectUnref(cfg); return ret; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.args new file mode 100644 index 0000000000..5bc5f4f477 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.args @@ -0,0 +1,41 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-i686 \ +-name QEMUGuest1 \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-M pc \ +-m 214 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-no-acpi \ +-boot c \ +-usb \ +-object secret,id=virtio-disk0-secret0,\ +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ +-drive file.driver=iscsi,file.portal=example.org,\ +file.target=iqn.1992-01.com.example:storage,file.lun=1,file.transport=tcp,\ +file.user=myname,file.password-secret=virtio-disk0-secret0,format=raw,if=none,\ +id=drive-virtio-disk0 \ +-device virtio-blk-pci,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,\ +id=virtio-disk0 \ +-object secret,id=virtio-disk1-secret0,\ +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ +-drive file.driver=iscsi,file.portal=example.org,\ +file.target=iqn.1992-01.com.example:storage,file.lun=2,file.transport=tcp,\ +file.user=myname,file.password-secret=virtio-disk1-secret0,format=raw,if=none,\ +id=drive-virtio-disk1 \ +-device virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk1,\ +id=virtio-disk1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.xml new file mode 100644 index 0000000000..63919f1000 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.xml @@ -0,0 +1,43 @@ +<domain type='qemu'> + <name>QEMUGuest1</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='i686' 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> + <emulator>/usr/bin/qemu-system-i686</emulator> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <auth username='myname'> + <secret type='iscsi' usage='mycluster_myname'/> + </auth> + <source protocol='iscsi' name='iqn.1992-01.com.example:storage/1'> + <host name='example.org' port='6000'/> + </source> + <target dev='vda' bus='virtio'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <auth username='myname'> + <secret type='iscsi' usage='mycluster_myname'/> + </auth> + <source protocol='iscsi' name='iqn.1992-01.com.example:storage/2'> + <host name='example.org' port='6000'/> + </source> + <target dev='vdb' bus='virtio'/> + </disk> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.args new file mode 100644 index 0000000000..c6051ecb07 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.args @@ -0,0 +1,45 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-i686 \ +-name QEMUGuest2 \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-QEMUGuest2/master-key.aes \ +-M pc \ +-m 214 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9466-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest2/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-no-acpi \ +-boot c \ +-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 \ +-usb \ +-drive file=/dev/HostVG/QEMUGuest2,format=raw,if=none,id=drive-ide0-0-0 \ +-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \ +-object secret,id=hostdev0-secret0,\ +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ +-drive file.driver=iscsi,file.portal=example.org,\ +file.target=iqn.1992-01.com.example:storage,file.lun=1,file.transport=tcp,\ +file.user=myname,file.password-secret=hostdev0-secret0,if=none,format=raw,\ +id=drive-hostdev0 \ +-device scsi-generic,bus=scsi0.0,channel=0,scsi-id=2,lun=4,\ +drive=drive-hostdev0,id=hostdev0 \ +-object secret,id=hostdev1-secret0,\ +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ +-drive file.driver=iscsi,file.portal=example.org,\ +file.target=iqn.1992-01.com.example:storage,file.lun=2,file.transport=tcp,\ +file.user=myname,file.password-secret=hostdev1-secret0,if=none,format=raw,\ +id=drive-hostdev1 \ +-device scsi-generic,bus=scsi0.0,channel=0,scsi-id=2,lun=5,\ +drive=drive-hostdev1,id=hostdev1 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.xml new file mode 100644 index 0000000000..0f63f98872 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.xml @@ -0,0 +1,48 @@ +<domain type='qemu'> + <name>QEMUGuest2</name> + <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' 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> + <emulator>/usr/bin/qemu-system-i686</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='scsi' index='0' model='virtio-scsi'/> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <hostdev mode='subsystem' type='scsi' managed='yes'> + <source protocol='iscsi' name='iqn.1992-01.com.example:storage/1'> + <host name='example.org' port='3260'/> + <auth username='myname'> + <secret type='iscsi' usage='mycluster_myname'/> + </auth> + </source> + <address type='drive' controller='0' bus='0' target='2' unit='4'/> + </hostdev> + <hostdev mode='subsystem' type='scsi' managed='yes'> + <source protocol='iscsi' name='iqn.1992-01.com.example:storage/2'> + <host name='example.org' port='3260'/> + <auth username='myname'> + <secret type='iscsi' usage='mycluster_myname'/> + </auth> + </source> + <address type='drive' controller='0' bus='0' target='2' unit='5'/> + </hostdev> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index f326bffa16..bfa2e58a4e 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -933,6 +933,10 @@ mymain(void) DO_TEST_PARSE_ERROR("disk-drive-network-iscsi-auth-secrettype-invalid", NONE); DO_TEST_PARSE_ERROR("disk-drive-network-iscsi-auth-wrong-secrettype", NONE); DO_TEST_PARSE_ERROR("disk-drive-network-source-auth-both", NONE); +# ifdef HAVE_GNUTLS_CIPHER_ENCRYPT + DO_TEST("disk-drive-network-iscsi-auth-AES", + QEMU_CAPS_OBJECT_SECRET, QEMU_CAPS_ISCSI_PASSWORD_SECRET); +# endif DO_TEST("disk-drive-network-iscsi-lun", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_BLOCK); @@ -2334,6 +2338,12 @@ mymain(void) DO_TEST("hostdev-scsi-virtio-iscsi-auth", QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_SCSI_GENERIC); +# ifdef HAVE_GNUTLS_CIPHER_ENCRYPT + DO_TEST("hostdev-scsi-virtio-iscsi-auth-AES", + QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_DEVICE_SCSI_GENERIC, QEMU_CAPS_OBJECT_SECRET, + QEMU_CAPS_ISCSI_PASSWORD_SECRET); +# endif DO_TEST("hostdev-scsi-vhost-scsi-ccw", QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VHOST_SCSI, QEMU_CAPS_DEVICE_SCSI_GENERIC, QEMU_CAPS_VIRTIO_CCW); -- 2.13.6

Signed-off-by: John Ferlan <jferlan@redhat.com> --- docs/news.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/news.xml b/docs/news.xml index 09cd1cd340..b5f7e11b4f 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -63,6 +63,16 @@ way. </description> </change> + <change> + <summary> + Securely pass iSCSI authentication data + </summary> + <description> + Rather than supplying the authentication data as part of the + iSCSI URL for a disk or host device, utilize the encrypted + secret object to securely pass the authentication data. + </description> + </change> </section> </release> <release version="v3.8.0" date="2017-10-04"> -- 2.13.6

ping? Tks - John On 10/05/2017 09:22 AM, John Ferlan wrote:
v4: https://www.redhat.com/archives/libvir-list/2017-September/msg00944.html
Changes since v4 are minor - mostly to change from 3.8.0 to 3.9.0... Update the news.xml once <auth> is allowed for <source>. Add a news.xml to describe the bug fix. Beyond that - merge changes up to git commit '5d7659027'.
I ran the changes through my Coverity checker too.
Repeated from the cover of v4:
v3: https://www.redhat.com/archives/libvir-list/2017-September/msg00881.html
Difference with v3:
Add patch 3 to perform virStorageSourceCopy for qemu and storage source private data.
Adjust the move encinfo from private disk to private disk src to handle the Copy for the @encinfo too
Repeated from cover of v3 (although perhaps just too much information for the eyes to consume):
v2: https://www.redhat.com/archives/libvir-list/2017-September/msg00466.html
Changes since v2:
* Former Patch 1 & 2 were pushed
* New Patch 1 is former Patches 3 and parts of 4 combined appropriately -> Allow <auth> under <disk> or <source> - keep track of where it was found so that format prints in the right place -> Cleaned up the tests and new xml/args files
* Patch 2 is part of the former patch 6 - just the new _virStorageSource
* Patch 3 is new - to introduced an allocator for domain_conf to create a _virStorageSource
* Patch 4 is new - as stated found that the @diskPriv->encinfo wasn't cleaned up properly
* Patch 5 is the rest of the former patch 6
* Patch 6 is the former patch 7 with some minor adjustments to allow <encryption> to follow <auth> and be both child of <disk> and <source>
* Patch 7 is the former patch 10 with minor change to perform free of encinfo properly (e.g. from patch 4)
* Patch 8 is former patch 5 and 9 combined
* Patch 9 is new - to use the virStorageSource for iscsisrc instead of just three fields we wanted
* Patch 10 is new to alter the existing hostdevPriv to use diskSrcPriv
* Patch 11 is new to remove the hostdevPriv as it's no longer necesary
* Patch 12 is new to split up a change in qemuBuildSCSIiSCSIHostdevDrvStr from the last patch
* Patch 13 is the former patch 13
* Patch 14 is altered to accomodate the hostdev usage if virStorageSource for iscsisrc->src instead of that hack that was there before.
John Ferlan (16): conf: Add/Allow parsing the auth in the disk source qemu: Introduce privateData for _virStorageSource qemu: Introduce qemuDomainStorageSourceCopy conf: Introduce virDomainDiskStorageSourceNew qemu: Add missing encinfo cleanup qemu: Relocate qemuDomainSecretInfoPtr from disk private conf: Add/Allow parsing the encryption in the disk source qemu: Move encinfo from private disk to private disk src docs: Add news article regarding auth/encryption placement conf,qemu: Replace iscsisrc fields with virStorageSourcePtr qemu: Use private disksrc for iscsi instead of private hostdev qemu: Remove private hostdev qemu: Refactor qemuBuildSCSIiSCSIHostdevDrvStr slightly qemu: Get capabilities to use iscsi password-secret argument qemu: Use secret objects to pass iSCSI passwords docs: Add news article to describe iSCSI usage of secret object
docs/formatdomain.html.in | 82 ++++--- docs/news.xml | 23 ++ docs/schemas/domaincommon.rng | 48 +++- src/conf/domain_conf.c | 255 ++++++++++++++++----- src/conf/domain_conf.h | 10 +- src/lxc/lxc_native.c | 2 +- src/qemu/qemu_block.c | 64 +++++- src/qemu/qemu_blockjob.c | 2 +- src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 84 +++++-- src/qemu/qemu_command.h | 3 +- src/qemu/qemu_domain.c | 162 +++++++++---- src/qemu/qemu_domain.h | 37 ++- src/qemu/qemu_driver.c | 8 +- src/qemu/qemu_hotplug.c | 71 +++++- src/qemu/qemu_parse_command.c | 4 +- src/util/virstoragefile.c | 2 + src/util/virstoragefile.h | 5 + src/vbox/vbox_common.c | 2 +- src/xenconfig/xen_common.c | 2 +- src/xenconfig/xen_sxpr.c | 2 +- src/xenconfig/xen_xl.c | 2 +- .../qemuargv2xml-disk-drive-network-rbd-auth.xml | 6 +- tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 + ...xml2argv-disk-drive-network-iscsi-auth-AES.args | 41 ++++ ...uxml2argv-disk-drive-network-iscsi-auth-AES.xml | 43 ++++ ...ml2argv-disk-drive-network-source-auth-both.xml | 51 +++++ ...emuxml2argv-disk-drive-network-source-auth.args | 32 +++ ...qemuxml2argv-disk-drive-network-source-auth.xml | 45 ++++ ...ml2argv-hostdev-scsi-virtio-iscsi-auth-AES.args | 45 ++++ ...xml2argv-hostdev-scsi-virtio-iscsi-auth-AES.xml | 48 ++++ .../qemuxml2argv-luks-disks-source-both.xml | 40 ++++ .../qemuxml2argv-luks-disks-source.args | 62 +++++ .../qemuxml2argv-luks-disks-source.xml | 81 +++++++ tests/qemuxml2argvtest.c | 14 ++ ...muxml2xmlout-disk-drive-network-source-auth.xml | 49 ++++ .../qemuxml2xmlout-luks-disks-source.xml | 84 +++++++ .../qemuxml2xmlout-luks-disks.xml | 46 +++- tests/qemuxml2xmltest.c | 2 + tests/virhostdevtest.c | 2 +- tests/virstoragetest.c | 6 + 46 files changed, 1356 insertions(+), 219 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-iscsi-auth-AES.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth-both.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-source-auth.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-iscsi-auth-AES.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source-both.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks-source.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-drive-network-source-auth.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks-source.xml mode change 120000 => 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml
participants (2)
-
John Ferlan
-
Peter Krempa