diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2eec9177da..c23dda673e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7219,10 +7219,18 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node,
return -1;
}
}
- if (src->protocol == VIR_STORAGE_NET_PROTOCOL_SSH &&
- (tmpnode = virXPathNode("./knownHosts", ctxt))) {
- if (!(src->ssh_known_hosts_file = virXMLPropStringRequired(tmpnode, "path")))
- return -1;
+ if (src->protocol == VIR_STORAGE_NET_PROTOCOL_SSH) {
+ if ((tmpnode = virXPathNode("./knownHosts", ctxt))) {
+ if (!(src->ssh_known_hosts_file = virXMLPropStringRequired(tmpnode, "path")))
+ return -1;
+ }
+ if ((tmpnode = virXPathNode("./identity", ctxt))) {
+ if (!(src->ssh_user = virXMLPropStringRequired(tmpnode, "username")))
+ return -1;
+
+ if (!(src->ssh_keyfile = virXMLPropStringRequired(tmpnode, "keyfile")))
+ return -1;
+ }
}
return 0;
@@ -22211,8 +22219,18 @@ virDomainDiskSourceFormatNetwork(virBuffer *attrBuf,
if (src->timeout)
virBufferAsprintf(childBuf, "\n", src->timeout);
- if (src->protocol == VIR_STORAGE_NET_PROTOCOL_SSH && src->ssh_known_hosts_file)
- virBufferEscapeString(childBuf, "\n", src->ssh_known_hosts_file);
+ if (src->protocol == VIR_STORAGE_NET_PROTOCOL_SSH) {
+ if (src->ssh_known_hosts_file)
+ virBufferEscapeString(childBuf, "\n", src->ssh_known_hosts_file);
+ if (src->ssh_keyfile) {
+ virBufferAddLit(childBuf, "ssh_user);
+ virBufferEscapeString(childBuf, " keyfile='%s'", src->ssh_keyfile);
+
+ virBufferAddLit(childBuf, "/>\n");
+ }
+ }
}
diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c
index 0a39779d52..67d50af074 100644
--- a/src/conf/storage_source_conf.c
+++ b/src/conf/storage_source_conf.c
@@ -898,6 +898,7 @@ virStorageSourceCopy(const virStorageSource *src,
def->ssh_host_key_check_disabled = src->ssh_host_key_check_disabled;
def->ssh_user = g_strdup(src->ssh_user);
def->ssh_known_hosts_file = g_strdup(src->ssh_known_hosts_file);
+ def->ssh_keyfile = g_strdup(src->ssh_keyfile);
def->nfs_user = g_strdup(src->nfs_user);
def->nfs_group = g_strdup(src->nfs_group);
@@ -1177,6 +1178,7 @@ virStorageSourceClear(virStorageSource *def)
VIR_FREE(def->ssh_user);
VIR_FREE(def->ssh_known_hosts_file);
+ VIR_FREE(def->ssh_keyfile);
VIR_FREE(def->nfs_user);
VIR_FREE(def->nfs_group);
diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index a2b2244844..3b6e628e21 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -408,12 +408,11 @@ struct _virStorageSource {
bool hostcdrom; /* backing device is a cdrom */
- /* passthrough variables for the ssh driver which we don't handle properly */
- /* these must not be used apart from formatting the output JSON in the qemu driver */
+ /* ssh variables */
char *ssh_user;
bool ssh_host_key_check_disabled;
- /* additional ssh variables */
char *ssh_known_hosts_file;
+ char *ssh_keyfile;
/* nfs_user and nfs_group store the strings passed in by the user for NFS params.
* nfs_uid and nfs_gid represent the converted/looked up ID numbers which are used
diff --git a/src/qemu/qemu_nbdkit.c b/src/qemu/qemu_nbdkit.c
index afac71e21a..0a6c7962b0 100644
--- a/src/qemu/qemu_nbdkit.c
+++ b/src/qemu/qemu_nbdkit.c
@@ -1049,8 +1049,12 @@ qemuNbdkitProcessBuildCommandSSH(qemuNbdkitProcess *proc,
if (proc->source->auth) {
if (qemuNbdkitProcessBuildCommandAuth(proc->source->auth, cmd) < 0)
return -1;
- } else if (proc->source->ssh_user) {
- virCommandAddArgPair(cmd, "user", proc->source->ssh_user);
+ } else {
+ if (proc->source->ssh_keyfile)
+ virCommandAddArgPair(cmd, "identity", proc->source->ssh_keyfile);
+
+ if (proc->source->ssh_user)
+ virCommandAddArgPair(cmd, "user", proc->source->ssh_user);
}
if (proc->source->ssh_host_key_check_disabled)
@@ -1171,6 +1175,10 @@ qemuNbdkitProcessStart(qemuNbdkitProcess *proc,
if (qemuExtDeviceLogCommand(driver, vm, cmd, "nbdkit") < 0)
goto error;
+ if (proc->source->ssh_keyfile &&
+ qemuSecurityDomainSetPathLabel(driver, vm, proc->source->ssh_keyfile, false) < 0)
+ goto error;
+
if (proc->source->ssh_known_hosts_file &&
qemuSecurityDomainSetPathLabel(driver, vm, proc->source->ssh_known_hosts_file, false) < 0)
goto error;
@@ -1256,6 +1264,9 @@ qemuNbdkitProcessStop(qemuNbdkitProcess *proc,
if (proc->source->ssh_known_hosts_file)
qemuSecurityDomainRestorePathLabel(driver, vm, proc->source->ssh_known_hosts_file);
+ if (proc->source->ssh_keyfile)
+ qemuSecurityDomainRestorePathLabel(driver, vm, proc->source->ssh_keyfile);
+
if (proc->pid < 0)
return 0;
diff --git a/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0 b/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0
new file mode 100644
index 0000000000..0b52bfe0fb
--- /dev/null
+++ b/tests/qemunbdkitdata/disk-network-ssh-key.args.disk0
@@ -0,0 +1,9 @@
+nbdkit \
+--unix /tmp/statedir-0/nbdkit-test-disk-0.socket \
+--foreground ssh \
+host=example.org \
+port=2222 \
+path=test.img \
+identity=/path/to/id_rsa \
+user=myuser \
+known-hosts=/path/to/ssh_known_hosts
diff --git a/tests/qemunbdkitdata/disk-network-ssh.args.disk2 b/tests/qemunbdkitdata/disk-network-ssh.args.disk2
new file mode 100644
index 0000000000..e269a34351
--- /dev/null
+++ b/tests/qemunbdkitdata/disk-network-ssh.args.disk2
@@ -0,0 +1,9 @@
+nbdkit \
+--unix /tmp/statedir-2/nbdkit-test-disk-2.socket \
+--foreground ssh \
+host=example.org \
+port=2222 \
+path=test2.img \
+identity=/path/to/id_rsa \
+user=myuser \
+known-hosts=/path/to/ssh_known_hosts
diff --git a/tests/qemunbdkittest.c b/tests/qemunbdkittest.c
index a51b287f34..559196a1cd 100644
--- a/tests/qemunbdkittest.c
+++ b/tests/qemunbdkittest.c
@@ -299,6 +299,7 @@ mymain(void)
DO_TEST("disk-network-source-curl", QEMU_NBDKIT_CAPS_PLUGIN_CURL);
DO_TEST("disk-network-ssh", QEMU_NBDKIT_CAPS_PLUGIN_SSH);
DO_TEST("disk-network-ssh-password", QEMU_NBDKIT_CAPS_PLUGIN_SSH);
+ DO_TEST("disk-network-ssh-key", QEMU_NBDKIT_CAPS_PLUGIN_SSH);
cleanup:
qemuTestDriverFree(&driver);
diff --git a/tests/qemuxml2argvdata/disk-network-ssh-key.xml b/tests/qemuxml2argvdata/disk-network-ssh-key.xml
new file mode 100644
index 0000000000..81b92231fa
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-ssh-key.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+