Related issue:
https://gitlab.com/libvirt/libvirt/-/issues/16
Added in support for the following parameters in attach-disk:
--source-protocol
--source-host-name
--source-host-socket
--source-host-transport
Added documentation to virsh.rst specifying usage.
Signed-off-by: Ryan Gahagan <rgahagan(a)cs.utexas.edu>
---
docs/manpages/virsh.rst | 31 ++++++---
tools/virsh-domain.c | 135 +++++++++++++++++++++++++++++++++++-----
2 files changed, 145 insertions(+), 21 deletions(-)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 1ae6d1a0d4..36c868a3e6 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -4538,14 +4538,18 @@ attach-disk
[--current]] | [--persistent]] [--targetbus bus]
[--driver driver] [--subdriver subdriver] [--iothread iothread]
[--cache cache] [--io io] [--type type] [--alias alias]
- [--mode mode] [--sourcetype sourcetype] [--serial serial]
- [--wwn wwn] [--rawio] [--address address] [--multifunction]
- [--print-xml]
+ [--mode mode] [--sourcetype sourcetype]
+ [--source-protocol protocol] [--source-host-name hostname:port]
+ [--source-host-transport transport] [--source-host-socket socket]
+ [--serial serial] [--wwn wwn] [--rawio] [--address address]
+ [--multifunction] [--print-xml]
Attach a new disk device to the domain.
-*source* is path for the files and devices. *target* controls the bus or
-device under which the disk is exposed to the guest OS. It indicates the
-"logical" device name; the optional *targetbus* attribute specifies the type
+*source* is path for the files and devices unless *--source-protocol*
+is specified, in which case *source* is the name of a network disk.
+*target* controls the bus or device under which the disk is exposed
+to the guest OS. It indicates the "logical" device name;
+the optional *targetbus* attribute specifies the type
of disk device to emulate; possible values are driver specific, with typical
values being *ide*, *scsi*, *virtio*, *xen*, *usb*, *sata*, or *sd*, if
omitted, the bus type is inferred from the style of the device name (e.g. a
@@ -4563,7 +4567,7 @@ within the existing virtual cdrom or floppy device; consider using
``update-device`` for this usage instead.
*alias* can set user supplied alias.
*mode* can specify the two specific mode *readonly* or *shareable*.
-*sourcetype* can indicate the type of source (block|file)
+*sourcetype* can indicate the type of source (block|file|network)
*cache* can be one of "default", "none", "writethrough",
"writeback",
"directsync" or "unsafe".
*io* controls specific policies on I/O; QEMU guests support "threads",
@@ -4579,6 +4583,19 @@ ccw:cssid.ssid.devno. Virtio-ccw devices must have their cssid set
to 0xfe.
*multifunction* indicates specified pci address is a multifunction pci device
address.
+There is also support for using a network disk. As specified, the user can
+provide a *--source-protocol* in which case the *source* parameter will
+be interpreted as the source name. *--source-protocol* must be provided
+if the user intends to provide a network disk or host information.
+Host information can be provided using the tags
+*--source-host-name*, *--source-host-transport*, and *--source-host-socket*,
+which respectively denote the name of the host, the host's transport method,
+and the socket that the host uses. *--source-host-socket* and
+*--source-host-name* cannot both be provided, and the user must provide a
+*--source-host-transport* if they want to provide a *--source-host-socket*.
+The *--source-host-name* parameter supports host:port syntax
+if the user wants to provide a port as well.
+
If *--print-xml* is specified, then the XML of the disk that would be attached
is printed instead.
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index c999458d72..1303676c33 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -222,7 +222,7 @@ static const vshCmdOptDef opts_attach_disk[] = {
{.name = "source",
.type = VSH_OT_DATA,
.flags = VSH_OFLAG_REQ | VSH_OFLAG_EMPTY_OK,
- .help = N_("source of disk device")
+ .help = N_("source of disk device or name of network disk")
},
{.name = "target",
.type = VSH_OT_DATA,
@@ -268,7 +268,7 @@ static const vshCmdOptDef opts_attach_disk[] = {
},
{.name = "sourcetype",
.type = VSH_OT_STRING,
- .help = N_("type of source (block|file)")
+ .help = N_("type of source (block|file|network)")
},
{.name = "serial",
.type = VSH_OT_STRING,
@@ -298,6 +298,22 @@ static const vshCmdOptDef opts_attach_disk[] = {
.type = VSH_OT_BOOL,
.help = N_("print XML document rather than attach the disk")
},
+ {.name = "source-protocol",
+ .type = VSH_OT_STRING,
+ .help = N_("protocol used by disk device source")
+ },
+ {.name = "source-host-name",
+ .type = VSH_OT_STRING,
+ .help = N_("host name for source of disk device")
+ },
+ {.name = "source-host-transport",
+ .type = VSH_OT_STRING,
+ .help = N_("host transport for source of disk device")
+ },
+ {.name = "source-host-socket",
+ .type = VSH_OT_STRING,
+ .help = N_("host socket for source of disk device")
+ },
VIRSH_COMMON_OPT_DOMAIN_PERSISTENT,
VIRSH_COMMON_OPT_DOMAIN_CONFIG,
VIRSH_COMMON_OPT_DOMAIN_LIVE,
@@ -558,6 +574,13 @@ static int str2DiskAddress(const char *str, struct DiskAddress
*diskAddr)
return -1;
}
+typedef enum {
+ VIRSH_SOURCE_TYPE_FILE,
+ VIRSH_SOURCE_TYPE_BLOCK,
+ VIRSH_SOURCE_TYPE_NETWORK,
+ VIRSH_SOURCE_TYPE_UNKNOWN,
+} virshAttachDiskSourceType;
+
static bool
cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
{
@@ -567,8 +590,14 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
*iothread = NULL, *cache = NULL, *io = NULL,
*serial = NULL, *straddr = NULL, *wwn = NULL,
*targetbus = NULL, *alias = NULL;
+ const char *source_protocol = NULL;
+ const char *host_name = NULL;
+ const char *host_transport = NULL;
+ const char *host_socket = NULL;
+ char *host_port = NULL;
struct DiskAddress diskAddr;
- bool isFile = false, functionReturn = false;
+ virshAttachDiskSourceType disk_type = VIRSH_SOURCE_TYPE_UNKNOWN;
+ bool functionReturn = false;
int ret;
unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
const char *stype = NULL;
@@ -585,6 +614,13 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+ VSH_REQUIRE_OPTION("source-host-name", "source-protocol");
+ VSH_REQUIRE_OPTION("source-host-transport", "source-protocol");
+ VSH_REQUIRE_OPTION("source-host-socket", "source-protocol");
+ VSH_REQUIRE_OPTION("source-host-socket",
"source-host-transport");
+
+ VSH_EXCLUSIVE_OPTIONS("source-host-name", "source-host-socket");
+
if (config || persistent)
flags |= VIR_DOMAIN_AFFECT_CONFIG;
if (live)
@@ -604,23 +640,45 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
vshCommandOptStringReq(ctl, cmd, "address", &straddr) < 0 ||
vshCommandOptStringReq(ctl, cmd, "targetbus", &targetbus) < 0
||
vshCommandOptStringReq(ctl, cmd, "alias", &alias) < 0 ||
- vshCommandOptStringReq(ctl, cmd, "sourcetype", &stype) < 0)
+ vshCommandOptStringReq(ctl, cmd, "sourcetype", &stype) < 0 ||
+ vshCommandOptStringReq(ctl, cmd, "source-protocol",
&source_protocol) < 0 ||
+ vshCommandOptStringReq(ctl, cmd, "source-host-name", &host_name)
< 0 ||
+ vshCommandOptStringReq(ctl, cmd, "source-host-transport",
&host_transport) < 0 ||
+ vshCommandOptStringReq(ctl, cmd, "source-host-socket",
&host_socket) < 0)
goto cleanup;
if (!stype) {
if (driver && (STREQ(driver, "file") || STREQ(driver,
"tap"))) {
- isFile = true;
+ disk_type = VIRSH_SOURCE_TYPE_FILE;
} else {
- if (source && !stat(source, &st))
- isFile = S_ISREG(st.st_mode) ? true : false;
+ if (source && !stat(source, &st)) {
+ if (S_ISREG(st.st_mode))
+ disk_type = VIRSH_SOURCE_TYPE_FILE;
+ else
+ disk_type = VIRSH_SOURCE_TYPE_BLOCK;
+ }
}
} else if (STREQ(stype, "file")) {
- isFile = true;
- } else if (STRNEQ(stype, "block")) {
+ disk_type = VIRSH_SOURCE_TYPE_FILE;
+ } else if (STREQ(stype, "block")) {
+ disk_type = VIRSH_SOURCE_TYPE_BLOCK;
+ } else if (STREQ(stype, "network")) {
+ /* The user must provide a protocol for a network disk */
+ if (!source_protocol) {
+ vshError(ctl, _("A source-protocol must be provided for a network
disk"));
+ goto cleanup;
+ }
+ } else {
vshError(ctl, _("Unknown source type: '%s'"), stype);
goto cleanup;
}
+ /* If a protocol is provided, the disk is assumed to be a network disk.
+ * This overwrites other disk types, such as an explicit
+ * 'sourcetype=file' or comparable parameter. */
+ if (source_protocol)
+ disk_type = VIRSH_SOURCE_TYPE_NETWORK;
+
if (mode) {
if (STRNEQ(mode, "readonly") && STRNEQ(mode,
"shareable")) {
vshError(ctl, _("No support for %s in command
'attach-disk'"),
@@ -633,8 +691,13 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
goto cleanup;
/* Make XML of disk */
- virBufferAsprintf(&buf, "<disk type='%s'",
- isFile ? "file" : "block");
+ if (disk_type == VIRSH_SOURCE_TYPE_FILE)
+ virBufferAddLit(&buf, "<disk type='file'");
+ else if (disk_type == VIRSH_SOURCE_TYPE_BLOCK)
+ virBufferAddLit(&buf, "<disk type='block'");
+ else if (disk_type == VIRSH_SOURCE_TYPE_NETWORK)
+ virBufferAddLit(&buf, "<disk type='network'");
+
if (type)
virBufferAsprintf(&buf, " device='%s'", type);
if (vshCommandOptBool(cmd, "rawio"))
@@ -659,9 +722,53 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
virBufferAddLit(&buf, "/>\n");
}
- if (source)
- virBufferAsprintf(&buf, "<source %s='%s'/>\n",
- isFile ? "file" : "dev", source);
+ if (source || source_protocol) {
+ virBufferAddLit(&buf, "<source");
+ if (source_protocol) {
+ /* Using a network disk; source is --source-name */
+ virBufferAsprintf(&buf, " protocol='%s'",
source_protocol);
+ if (source)
+ virBufferAsprintf(&buf, " name='%s'", source);
+
+ if (host_name || host_socket || host_transport) {
+ /* Host information provided, add a <host> tag */
+ virBufferAddLit(&buf, ">\n");
+ virBufferAdjustIndent(&buf, 2);
+ virBufferAddLit(&buf, "<host");
+
+ if (host_name) {
+ /* Logic for host:port syntax */
+ g_autofree char *host_name_copy = g_strdup(host_name);
+ host_port = strchr(host_name_copy, ':');
+
+ if (host_port) {
+ *host_port = '\0';
+ virBufferAsprintf(&buf,
+ " name='%s'
port='%s'",
+ host_name_copy, host_port + 1);
+ } else {
+ virBufferAsprintf(&buf, " name='%s'",
host_name);
+ }
+ }
+
+ if (host_transport)
+ virBufferAsprintf(&buf, " transport='%s'",
host_transport);
+ if (host_socket)
+ virBufferAsprintf(&buf, " socket='%s'",
host_socket);
+ virBufferAddLit(&buf, "/>\n");
+ virBufferAdjustIndent(&buf, -2);
+ virBufferAddLit(&buf, "</source>\n");
+ }
+ } else {
+ /* Using a local disk; source is file or dev */
+ if (disk_type == VIRSH_SOURCE_TYPE_FILE)
+ virBufferAsprintf(&buf, " file='%s'", source);
+ else
+ virBufferAsprintf(&buf, " dev='%s'", source);
+ virBufferAddLit(&buf, "/>\n");
+ }
+ }
+
virBufferAsprintf(&buf, "<target dev='%s'", target);
if (targetbus)
virBufferAsprintf(&buf, " bus='%s'", targetbus);
--
2.29.0