mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
Add support for qemu's curl driver (ie. FTP, FTPS, HTTP, HTTPS, TFTP).
This commit is contained in:
@@ -1117,6 +1117,22 @@ The possible I<-a URI> formats are described below.
|
||||
|
||||
Add the local disk image (or device) called C<disk.img>.
|
||||
|
||||
=head2 B<-a ftp://[user@]example.com[:port]/disk.img>
|
||||
|
||||
=head2 B<-a ftps://[user@]example.com[:port]/disk.img>
|
||||
|
||||
=head2 B<-a http://[user@]example.com[:port]/disk.img>
|
||||
|
||||
=head2 B<-a https://[user@]example.com[:port]/disk.img>
|
||||
|
||||
=head2 B<-a tftp://[user@]example.com[:port]/disk.img>
|
||||
|
||||
Add a disk located on a remote FTP, HTTP or TFTP server.
|
||||
|
||||
The equivalent API command would be:
|
||||
|
||||
><fs> add /disk.img protocol:(ftp|...) server:tcp:example.com
|
||||
|
||||
=head2 B<-a gluster://example.com[:port]/disk>
|
||||
|
||||
Add a disk image located on GlusterFS storage.
|
||||
|
||||
@@ -1334,6 +1334,13 @@ C<filename> is interpreted as a local file or device.
|
||||
This is the default if the optional protocol parameter
|
||||
is omitted.
|
||||
|
||||
=item C<protocol = \"ftp\"|\"ftps\"|\"http\"|\"https\"|\"tftp\">
|
||||
|
||||
Connect to a remote FTP, HTTP or TFTP server.
|
||||
The C<server> parameter must also be supplied - see below.
|
||||
|
||||
See also: L<guestfs(3)/FTP, HTTP AND TFTP>
|
||||
|
||||
=item C<protocol = \"gluster\">
|
||||
|
||||
Connect to the GlusterFS server.
|
||||
@@ -1390,6 +1397,7 @@ is a list of server(s).
|
||||
Protocol Number of servers required
|
||||
-------- --------------------------
|
||||
file List must be empty or param not used at all
|
||||
ftp|ftps|http|https|tftp Exactly one
|
||||
gluster Exactly one
|
||||
iscsi Exactly one
|
||||
nbd Exactly one
|
||||
@@ -1411,8 +1419,8 @@ for the protocol is used (see C</etc/services>).
|
||||
|
||||
=item C<username>
|
||||
|
||||
For the C<iscsi>, C<rbd>, C<ssh> protocols only, this specifies the
|
||||
remote username.
|
||||
For the C<ftp>, C<ftps>, C<http>, C<https>, C<iscsi>, C<rbd>, C<ssh>
|
||||
and C<tftp> protocols, this specifies the remote username.
|
||||
|
||||
If not given, then the local username is used for C<ssh>, and no authentication
|
||||
is attempted for ceph. But note this sometimes may give unexpected results, for
|
||||
|
||||
99
src/drives.c
99
src/drives.c
@@ -137,6 +137,50 @@ create_drive_non_file (guestfs_h *g,
|
||||
return drv;
|
||||
}
|
||||
|
||||
static struct drive *
|
||||
create_drive_curl (guestfs_h *g,
|
||||
enum drive_protocol protocol,
|
||||
struct drive_server *servers, size_t nr_servers,
|
||||
const char *exportname,
|
||||
const char *username, const char *secret,
|
||||
bool readonly, const char *format,
|
||||
const char *iface, const char *name,
|
||||
const char *disk_label,
|
||||
bool use_cache_none)
|
||||
{
|
||||
if (secret != NULL) {
|
||||
error (g, _("curl: you cannot specify a secret with this protocol"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nr_servers != 1) {
|
||||
error (g, _("curl: you must specify exactly one server"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (servers[0].transport != drive_transport_none &&
|
||||
servers[0].transport != drive_transport_tcp) {
|
||||
error (g, _("curl: only tcp transport is supported"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (STREQ (exportname, "")) {
|
||||
error (g, _("curl: pathname should not be an empty string"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (exportname[0] != '/') {
|
||||
error (g, _("curl: pathname must begin with a '/'"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return create_drive_non_file (g, protocol,
|
||||
servers, nr_servers, exportname,
|
||||
username, secret,
|
||||
readonly, format, iface, name, disk_label,
|
||||
use_cache_none);
|
||||
}
|
||||
|
||||
static struct drive *
|
||||
create_drive_gluster (guestfs_h *g,
|
||||
struct drive_server *servers, size_t nr_servers,
|
||||
@@ -871,12 +915,40 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
|
||||
disk_label, use_cache_none);
|
||||
}
|
||||
}
|
||||
else if (STREQ (protocol, "ftp")) {
|
||||
drv = create_drive_curl (g, drive_protocol_ftp,
|
||||
servers, nr_servers, filename,
|
||||
username, secret,
|
||||
readonly, format, iface, name,
|
||||
disk_label, false);
|
||||
}
|
||||
else if (STREQ (protocol, "ftps")) {
|
||||
drv = create_drive_curl (g, drive_protocol_ftps,
|
||||
servers, nr_servers, filename,
|
||||
username, secret,
|
||||
readonly, format, iface, name,
|
||||
disk_label, false);
|
||||
}
|
||||
else if (STREQ (protocol, "gluster")) {
|
||||
drv = create_drive_gluster (g, servers, nr_servers, filename,
|
||||
username, secret,
|
||||
readonly, format, iface, name,
|
||||
disk_label, false);
|
||||
}
|
||||
else if (STREQ (protocol, "http")) {
|
||||
drv = create_drive_curl (g, drive_protocol_http,
|
||||
servers, nr_servers, filename,
|
||||
username, secret,
|
||||
readonly, format, iface, name,
|
||||
disk_label, false);
|
||||
}
|
||||
else if (STREQ (protocol, "https")) {
|
||||
drv = create_drive_curl (g, drive_protocol_https,
|
||||
servers, nr_servers, filename,
|
||||
username, secret,
|
||||
readonly, format, iface, name,
|
||||
disk_label, false);
|
||||
}
|
||||
else if (STREQ (protocol, "iscsi")) {
|
||||
drv = create_drive_iscsi (g, servers, nr_servers, filename,
|
||||
username, secret,
|
||||
@@ -907,6 +979,13 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
|
||||
readonly, format, iface, name,
|
||||
disk_label, false);
|
||||
}
|
||||
else if (STREQ (protocol, "tftp")) {
|
||||
drv = create_drive_curl (g, drive_protocol_tftp,
|
||||
servers, nr_servers, filename,
|
||||
username, secret,
|
||||
readonly, format, iface, name,
|
||||
disk_label, false);
|
||||
}
|
||||
else {
|
||||
error (g, _("unknown protocol '%s'"), protocol);
|
||||
drv = NULL; /*FALLTHROUGH*/
|
||||
@@ -1175,6 +1254,14 @@ guestfs___drive_source_qemu_param (guestfs_h *g, const struct drive_source *src)
|
||||
else
|
||||
return safe_asprintf (g, "./%s", src->u.path);
|
||||
|
||||
case drive_protocol_ftp:
|
||||
return make_uri (g, "ftp", src->username,
|
||||
&src->servers[0], src->u.exportname);
|
||||
|
||||
case drive_protocol_ftps:
|
||||
return make_uri (g, "ftps", src->username,
|
||||
&src->servers[0], src->u.exportname);
|
||||
|
||||
case drive_protocol_gluster:
|
||||
switch (src->servers[0].transport) {
|
||||
case drive_transport_none:
|
||||
@@ -1186,6 +1273,14 @@ guestfs___drive_source_qemu_param (guestfs_h *g, const struct drive_source *src)
|
||||
return make_uri (g, "gluster+unix", NULL, &src->servers[0], NULL);
|
||||
}
|
||||
|
||||
case drive_protocol_http:
|
||||
return make_uri (g, "http", src->username,
|
||||
&src->servers[0], src->u.exportname);
|
||||
|
||||
case drive_protocol_https:
|
||||
return make_uri (g, "https", src->username,
|
||||
&src->servers[0], src->u.exportname);
|
||||
|
||||
case drive_protocol_iscsi:
|
||||
return make_uri (g, "iscsi", NULL, &src->servers[0], src->u.exportname);
|
||||
|
||||
@@ -1277,6 +1372,10 @@ guestfs___drive_source_qemu_param (guestfs_h *g, const struct drive_source *src)
|
||||
case drive_protocol_ssh:
|
||||
return make_uri (g, "ssh", src->username,
|
||||
&src->servers[0], src->u.exportname);
|
||||
|
||||
case drive_protocol_tftp:
|
||||
return make_uri (g, "tftp", src->username,
|
||||
&src->servers[0], src->u.exportname);
|
||||
}
|
||||
|
||||
abort ();
|
||||
|
||||
@@ -115,12 +115,17 @@ struct event {
|
||||
/* Drives added to the handle. */
|
||||
enum drive_protocol {
|
||||
drive_protocol_file,
|
||||
drive_protocol_ftp,
|
||||
drive_protocol_ftps,
|
||||
drive_protocol_gluster,
|
||||
drive_protocol_http,
|
||||
drive_protocol_https,
|
||||
drive_protocol_iscsi,
|
||||
drive_protocol_nbd,
|
||||
drive_protocol_rbd,
|
||||
drive_protocol_sheepdog,
|
||||
drive_protocol_ssh,
|
||||
drive_protocol_tftp,
|
||||
};
|
||||
|
||||
enum drive_transport {
|
||||
|
||||
@@ -661,6 +661,29 @@ servers. The server string is documented in
|
||||
L</guestfs_add_drive_opts>. The C<username> and C<secret> parameters are
|
||||
also optional, and if not given, then no authentication will be used.
|
||||
|
||||
=head3 FTP, HTTP AND TFTP
|
||||
|
||||
Libguestfs can access remote disks over FTP, FTPS, HTTP, HTTPS
|
||||
or TFTP protocols.
|
||||
|
||||
To do this, set the optional C<protocol> and C<server> parameters of
|
||||
L</guestfs_add_drive_opts> like this:
|
||||
|
||||
char **servers = { "www.example.org", NULL };
|
||||
guestfs_add_drive_opts (g, "/disk.img",
|
||||
GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
|
||||
GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "http",
|
||||
GUESTFS_ADD_DRIVE_OPTS_SERVER, servers,
|
||||
-1);
|
||||
|
||||
The C<protocol> can be one of C<"ftp">, C<"ftps">, C<"http">,
|
||||
C<"https"> or C<"tftp">.
|
||||
|
||||
C<servers> (the C<server> parameter) is a list which must have a
|
||||
single element. The single element is a string defining the Gluster
|
||||
server. The format of this string is documented in
|
||||
L</guestfs_add_drive_opts>.
|
||||
|
||||
=head3 GLUSTER
|
||||
|
||||
Libguestfs can access Gluster disks.
|
||||
|
||||
@@ -1151,6 +1151,18 @@ construct_libvirt_xml_disk (guestfs_h *g,
|
||||
*/
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
}
|
||||
break;
|
||||
|
||||
/* libvirt doesn't support the qemu curl driver yet. Give a
|
||||
* reasonable error message instead of trying and failing.
|
||||
*/
|
||||
case drive_protocol_ftp:
|
||||
case drive_protocol_ftps:
|
||||
case drive_protocol_http:
|
||||
case drive_protocol_https:
|
||||
case drive_protocol_tftp:
|
||||
error (g, _("libvirt does not support the qemu curl driver protocols (ftp, http, etc.); try setting LIBGUESTFS_BACKEND=direct"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "target"));
|
||||
@@ -1599,12 +1611,17 @@ make_drive_priv (guestfs_h *g, struct drive *drv,
|
||||
}
|
||||
break;
|
||||
|
||||
case drive_protocol_ftp:
|
||||
case drive_protocol_ftps:
|
||||
case drive_protocol_gluster:
|
||||
case drive_protocol_http:
|
||||
case drive_protocol_https:
|
||||
case drive_protocol_iscsi:
|
||||
case drive_protocol_nbd:
|
||||
case drive_protocol_rbd:
|
||||
case drive_protocol_sheepdog:
|
||||
case drive_protocol_ssh:
|
||||
case drive_protocol_tftp:
|
||||
if (!drv->readonly) {
|
||||
guestfs___copy_drive_source (g, &drv->src, &drv_priv->real_src);
|
||||
drv_priv->format = drv->format ? safe_strdup (g, drv->format) : NULL;
|
||||
@@ -1621,6 +1638,7 @@ make_drive_priv (guestfs_h *g, struct drive *drv,
|
||||
return -1;
|
||||
drv_priv->format = safe_strdup (g, "qcow2");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user