Re: [PATCH] virsh: Added attach-disk support for network disk

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Nov 13, 2020 at 12:52:32 -0600, Ryan Gahagan wrote:
> 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@xxxxxxxxxxxxx>
> ---
>  docs/manpages/virsh.rst | 26 ++++++++++---
>  tools/virsh-domain.c    | 85 ++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 100 insertions(+), 11 deletions(-)
> 
> diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
> index bfd26e3120..a4d70e9211 100644
> --- a/docs/manpages/virsh.rst
> +++ b/docs/manpages/virsh.rst
> @@ -4500,14 +4500,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
> @@ -4541,6 +4545,16 @@ 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 also wishes to provide host information.
> +Host information can be provided using any of 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. 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 12b35c037d..4c43da7a2c 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,
> @@ -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,
> @@ -567,6 +583,12 @@ 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_name_copy = NULL;
> +    char *host_port = NULL;
>      struct DiskAddress diskAddr;
>      bool isFile = false, functionReturn = false;
>      int ret;
> @@ -604,7 +626,11 @@ 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) {
> @@ -632,6 +658,13 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
>      if (wwn && !virValidateWWN(wwn))
>          goto cleanup;
>  
> +    if (!source_protocol && (host_name || host_socket || host_transport)) {
> +        /* Error: cannot use network host without a source protocol */
> +        vshError(ctl, "%s",
> +                 _("Cannot use --source-host-* parameters without a --source-protocol"));
> +        goto cleanup;
> +    }

This can be replaced by:

VSH_REQUIRE_OPTION("source-host-name", "source-protocol");
VSH_REQUIRE_OPTION("source-host-transport", "source-protocol");
VSH_REQUIRE_OPTION("source-host-socket", "source-protocol");

You probably also want:

VSH_EXCLUSIVE_OPTIONS("source-host-name", "source-host-socket")

and also 

VSH_REQUIRE_OPTION("source-host-socket", "source-host-transport")

as TCP is assumed by default and it wouldn't work with unix socket path.



> +
>      /* Make XML of disk */
>      virBufferAsprintf(&buf, "<disk type='%s'",
>                        isFile ? "file" : "block");

I didn't notice this previously. You obviously need "<disk type='network'"
if defining a network disk.

> @@ -659,9 +692,51 @@ 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 */
> +                    host_name_copy = g_strdup(host_name);

host_name_copy variable is not freed, so the string is leaked. Since you
use the variable only in this scope, you can declare it here and also
use 'g_autofree' to free it on scope exit.

> +                    host_port = strchr(host_name_copy, ':');
> +
> +                    if (host_port) {
> +                        host_name_copy[(int)(host_port - host_name_copy)] = '\0';

So this pointer arithmetic expression is a bit pointless:

'ptr[X]' can be written as:

*(ptr + X)

Since strchr() returns 'ptr2 = ptr + n' and you calculate X as 'X = ptr2
- ptr'

Your calculation thus does:

*(ptr + (ptr2 - ptr)) -> *ptr2

You can thus clear the ':' char by:

    *host_port = '\0';

Additionally you forgot to move the 'host_port' pointer one after the
colon symbol which is now a NUL byte. That means that host_port actually
looks like an empty string ...

> +                        virBufferAsprintf(&buf,
> +                                          " name='%s' port='%s'",
> +                                          host_name_copy, host_port);

And thus this prints just:

$ ./build/libvirt/gcc/tools/virsh attach-disk upstream-bj /tmp/ble vda --source-host-name test:1234 --source-protocol test --print-xml
<disk type='file'>
  <source protocol='test' name='/tmp/ble'>
    <host name='test' port=''/>
  </source>
  <target dev='vda'/>
</disk>

In the above you can actually also see that <disk type='file'> is wrong
as mentioned above.

> +                    } 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 */
> +            virBufferAsprintf(&buf, " %s='%s'",
> +                        isFile ? "file" : "dev", source);

This is still misaligned.

> +            virBufferAddLit(&buf, "/>\n");
> +        }
> +    }
> +
>      virBufferAsprintf(&buf, "<target dev='%s'", target);
>      if (targetbus)
>          virBufferAsprintf(&buf, " bus='%s'", targetbus);

Unfortunately this function is very old and would need to be refactored,
the XML formatting is definitely not to our modern standards.




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux