Permalink
Browse files

Add support for qemu's curl driver (ie. FTP, FTPS, HTTP, HTTPS, TFTP).

  • Loading branch information...
1 parent e3c2397 commit 83f74f5c564c51a1324b12e5edc4b50356d49dc6 @rwmjones rwmjones committed May 11, 2013
Showing with 171 additions and 2 deletions.
  1. +16 −0 fish/guestfish.pod
  2. +10 −2 generator/actions.ml
  3. +99 −0 src/drives.c
  4. +5 −0 src/guestfs-internal.h
  5. +23 −0 src/guestfs.pod
  6. +18 −0 src/launch-libvirt.c
View
@@ -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.
View
@@ -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
View
@@ -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 ();
View
@@ -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 {
View
@@ -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.
View
@@ -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;

0 comments on commit 83f74f5

Please sign in to comment.