[Libguestfs] [PATCH 5/5] rbd: Support using a custom secret

Mike Kelly pioto at pioto.org
Tue May 7 14:50:12 UTC 2013


---
 generator/actions.ml   |   20 ++++++++---
 src/drives.c           |   86 +++++++++++++++++++++++++++++++++++++-----------
 src/guestfs-internal.h |    2 ++
 src/guestfs.pod        |    5 ++-
 src/launch-libvirt.c   |    3 ++
 5 files changed, 90 insertions(+), 26 deletions(-)

diff --git a/generator/actions.ml b/generator/actions.ml
index daea6b6..b0b4be7 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -1247,7 +1247,7 @@ not all belong to a single logical operating system
 
   { defaults with
     name = "add_drive";
-    style = RErr, [String "filename"], [OBool "readonly"; OString "format"; OString "iface"; OString "name"; OString "label"; OString "protocol"; OStringList "server"; OString "username"];
+    style = RErr, [String "filename"], [OBool "readonly"; OString "format"; OString "iface"; OString "name"; OString "label"; OString "protocol"; OStringList "server"; OString "username"; OString "secret"];
     once_had_no_optargs = true;
     blocking = false;
     fish_alias = ["add"];
@@ -1353,6 +1353,7 @@ See also: L<guestfs(3)/NETWORK BLOCK DEVICE>.
 Connect to the Ceph (librbd/RBD) server.
 The C<server> parameter must also be supplied - see below.
 The C<username> parameter may be supplied.  See below.
+The C<secret> parameter may be supplied.  See below.
 
 See also: L<guestfs(3)/CEPH>.
 
@@ -1404,12 +1405,21 @@ for the protocol is used (see C</etc/services>).
 
 For the C<ssh> and C<rbd> protocols only, this specifies the remote username.
 
-If not given, then the local username is used for C<ssh>, and 'admin' is used
-for C<rbd>.  But note this sometimes may give unexpected results, for example
-if using the libvirt backend and if the libvirt backend is configured to start
-the qemu appliance as a special user such as C<qemu.qemu>.  If in doubt,
+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
+example if using the libvirt backend and if the libvirt backend is configured to
+start the qemu appliance as a special user such as C<qemu.qemu>.  If in doubt,
 specify the remote username you want.
 
+=item C<secret>
+
+For the C<rbd> protocol only, this specifies the 'secret' to use when
+connecting to the remote device.
+
+If not given, then a secret matching the given username will be looked up in the
+default keychain locations, or if no username is given, then no authentication
+will be used.
+
 =back" };
 
   { defaults with
diff --git a/src/drives.c b/src/drives.c
index a510e1e..1429050 100644
--- a/src/drives.c
+++ b/src/drives.c
@@ -107,7 +107,8 @@ static struct drive *
 create_drive_non_file (guestfs_h *g,
                        enum drive_protocol protocol,
                        struct drive_server *servers, size_t nr_servers,
-                       const char *exportname, const char *username,
+                       const char *exportname,
+                       const char *username, const char *secret,
                        bool readonly, const char *format,
                        const char *iface, const char *name,
                        const char *disk_label,
@@ -120,6 +121,7 @@ create_drive_non_file (guestfs_h *g,
   drv->src.nr_servers = nr_servers;
   drv->src.u.exportname = safe_strdup (g, exportname);
   drv->src.username = username ? safe_strdup (g, username) : NULL;
+  drv->src.secret = secret ? safe_strdup (g, secret) : NULL;
 
   drv->readonly = readonly;
   drv->format = format ? safe_strdup (g, format) : NULL;
@@ -136,7 +138,8 @@ create_drive_non_file (guestfs_h *g,
 static struct drive *
 create_drive_gluster (guestfs_h *g,
                       struct drive_server *servers, size_t nr_servers,
-                      const char *exportname, const char *username,
+                      const char *exportname,
+                      const char *username, const char *secret,
                       bool readonly, const char *format,
                       const char *iface, const char *name,
                       const char *disk_label,
@@ -146,6 +149,11 @@ create_drive_gluster (guestfs_h *g,
     error (g, _("gluster: you cannot specify a username with this protocol"));
     return NULL;
   }
+  if (secret != NULL) {
+    error (g, _("gluster: you cannot specify a secret with this protocol"));
+    return NULL;
+  }
+
 
   if (nr_servers != 1) {
     error (g, _("gluster: you must specify exactly one server"));
@@ -165,7 +173,8 @@ create_drive_gluster (guestfs_h *g,
   }
 
   return create_drive_non_file (g, drive_protocol_gluster,
-                                servers, nr_servers, exportname, username,
+                                servers, nr_servers, exportname,
+                                username, secret,
                                 readonly, format, iface, name, disk_label,
                                 use_cache_none);
 }
@@ -185,7 +194,8 @@ nbd_port (void)
 static struct drive *
 create_drive_nbd (guestfs_h *g,
                   struct drive_server *servers, size_t nr_servers,
-                  const char *exportname, const char *username,
+                  const char *exportname,
+                  const char *username, const char *secret,
                   bool readonly, const char *format,
                   const char *iface, const char *name,
                   const char *disk_label,
@@ -195,6 +205,10 @@ create_drive_nbd (guestfs_h *g,
     error (g, _("nbd: you cannot specify a username with this protocol"));
     return NULL;
   }
+  if (secret != NULL) {
+    error (g, _("nbd: you cannot specify a secret with this protocol"));
+    return NULL;
+  }
 
   if (nr_servers != 1) {
     error (g, _("nbd: you must specify exactly one server"));
@@ -205,7 +219,8 @@ create_drive_nbd (guestfs_h *g,
     servers[0].port = nbd_port ();
 
   return create_drive_non_file (g, drive_protocol_nbd,
-                                servers, nr_servers, exportname, username,
+                                servers, nr_servers, exportname,
+                                username, secret,
                                 readonly, format, iface, name, disk_label,
                                 use_cache_none);
 }
@@ -213,7 +228,8 @@ create_drive_nbd (guestfs_h *g,
 static struct drive *
 create_drive_rbd (guestfs_h *g,
                   struct drive_server *servers, size_t nr_servers,
-                  const char *exportname, const char *username,
+                  const char *exportname,
+                  const char *username, const char *secret,
                   bool readonly, const char *format,
                   const char *iface, const char *name,
                   const char *disk_label,
@@ -244,7 +260,8 @@ create_drive_rbd (guestfs_h *g,
   }
 
   return create_drive_non_file (g, drive_protocol_rbd,
-                                servers, nr_servers, exportname, username,
+                                servers, nr_servers, exportname,
+                                username, secret,
                                 readonly, format, iface, name, disk_label,
                                 use_cache_none);
 }
@@ -252,7 +269,8 @@ create_drive_rbd (guestfs_h *g,
 static struct drive *
 create_drive_sheepdog (guestfs_h *g,
                        struct drive_server *servers, size_t nr_servers,
-                       const char *exportname, const char *username,
+                       const char *exportname,
+                       const char *username, const char *secret,
                        bool readonly, const char *format,
                        const char *iface, const char *name,
                        const char *disk_label,
@@ -264,6 +282,10 @@ create_drive_sheepdog (guestfs_h *g,
     error (g, _("sheepdog: you cannot specify a username with this protocol"));
     return NULL;
   }
+  if (secret != NULL) {
+    error (g, _("sheepdog: you cannot specify a secret with this protocol"));
+    return NULL;
+  }
 
   for (i = 0; i < nr_servers; ++i) {
     if (servers[i].transport != drive_transport_none &&
@@ -283,7 +305,8 @@ create_drive_sheepdog (guestfs_h *g,
   }
 
   return create_drive_non_file (g, drive_protocol_sheepdog,
-                                servers, nr_servers, exportname, username,
+                                servers, nr_servers, exportname,
+                                username, secret,
                                 readonly, format, iface, name, disk_label,
                                 use_cache_none);
 }
@@ -291,12 +314,18 @@ create_drive_sheepdog (guestfs_h *g,
 static struct drive *
 create_drive_ssh (guestfs_h *g,
                   struct drive_server *servers, size_t nr_servers,
-                  const char *exportname, const char *username,
+                  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, _("ssh: you cannot specify a secret with this protocol"));
+    return NULL;
+  }
+
   if (nr_servers != 1) {
     error (g, _("ssh: you must specify exactly one server"));
     return NULL;
@@ -319,7 +348,8 @@ create_drive_ssh (guestfs_h *g,
   }
 
   return create_drive_non_file (g, drive_protocol_ssh,
-                                servers, nr_servers, exportname, username,
+                                servers, nr_servers, exportname,
+                                username, secret,
                                 readonly, format, iface, name, disk_label,
                                 use_cache_none);
 }
@@ -690,6 +720,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
   size_t nr_servers = 0;
   struct drive_server *servers = NULL;
   const char *username;
+  const char *secret;
   int use_cache_none;
   struct drive *drv;
   size_t i, drv_index;
@@ -720,6 +751,8 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
   }
   username = optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_USERNAME_BITMASK
     ? optargs->username : NULL;
+  secret = optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_SECRET_BITMASK
+    ? optargs->secret : NULL;
 
   if (format && !valid_format_iface (format)) {
     error (g, _("%s parameter is empty or contains disallowed characters"),
@@ -750,6 +783,11 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
       free_drive_servers (servers, nr_servers);
       return -1;
     }
+    if (secret != NULL) {
+      error (g, _("you cannot specify a secret with file-backed disks"));
+      free_drive_servers (servers, nr_servers);
+      return -1;
+    }
 
     if (STREQ (filename, "/dev/null"))
       drv = create_drive_dev_null (g, readonly, format, iface, name,
@@ -775,27 +813,32 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
     }
   }
   else if (STREQ (protocol, "gluster")) {
-    drv = create_drive_gluster (g, servers, nr_servers, filename, username,
+    drv = create_drive_gluster (g, servers, nr_servers, filename,
+                                username, secret,
                                 readonly, format, iface, name,
                                 disk_label, false);
   }
   else if (STREQ (protocol, "nbd")) {
-    drv = create_drive_nbd (g, servers, nr_servers, filename, username,
+    drv = create_drive_nbd (g, servers, nr_servers, filename,
+                            username, secret,
                             readonly, format, iface, name,
                             disk_label, false);
   }
   else if (STREQ (protocol, "rbd")) {
-    drv = create_drive_rbd (g, servers, nr_servers, filename, username,
+    drv = create_drive_rbd (g, servers, nr_servers, filename,
+                            username, secret,
                             readonly, format, iface, name,
                             disk_label, false);
   }
   else if (STREQ (protocol, "sheepdog")) {
-    drv = create_drive_sheepdog (g, servers, nr_servers, filename, username,
+    drv = create_drive_sheepdog (g, servers, nr_servers, filename,
+                                 username, secret,
                                  readonly, format, iface, name,
                                  disk_label, false);
   }
   else if (STREQ (protocol, "ssh")) {
-    drv = create_drive_ssh (g, servers, nr_servers, filename, username,
+    drv = create_drive_ssh (g, servers, nr_servers, filename,
+                            username, secret,
                             readonly, format, iface, name,
                             disk_label, false);
   }
@@ -1083,7 +1126,7 @@ guestfs___drive_source_qemu_param (guestfs_h *g, const struct drive_source *src)
 
   case drive_protocol_rbd: {
     /* build the list of all the mon hosts */
-    CLEANUP_FREE char *mon_host = NULL, *username = NULL;
+    CLEANUP_FREE char *mon_host = NULL, *username = NULL, *secret = NULL;
     char *auth;
     size_t n = 0;
     for (int i = 0; i < src->nr_servers; i++) {
@@ -1113,13 +1156,15 @@ guestfs___drive_source_qemu_param (guestfs_h *g, const struct drive_source *src)
 
     if (src->username)
         username = safe_asprintf (g, ":id=%s", src->username);
-    if (username)
+    if (src->secret)
+        secret = safe_asprintf (g, ":key=%s", src->secret);
+    if (username || secret)
         auth = ":auth_supported=cephx\\;none";
     else
         auth = ":auth_supported=none";
 
-    return safe_asprintf (g, "rbd:%s:mon_host=%s%s%s", src->u.exportname, mon_host,
-            username ? username : "", auth);
+    return safe_asprintf (g, "rbd:%s:mon_host=%s%s%s%s", src->u.exportname, mon_host,
+            username ? username : "", auth, secret ? secret : "");
   }
 
   case drive_protocol_sheepdog:
@@ -1155,6 +1200,7 @@ guestfs___free_drive_source (struct drive_source *src)
   if (src) {
     free (src->u.path);
     free (src->username);
+    free (src->secret);
     free_drive_servers (src->servers, src->nr_servers);
   }
 }
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index e13c498..6a58f2f 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -161,6 +161,8 @@ struct drive_source {
 
   /* Optional username (may be NULL if not specified). */
   char *username;
+  /* Optional secret (may be NULL if not specified). */
+  char *secret;
 };
 
 struct drive {
diff --git a/src/guestfs.pod b/src/guestfs.pod
index ee9cc2a..99374c2 100644
--- a/src/guestfs.pod
+++ b/src/guestfs.pod
@@ -652,11 +652,14 @@ L</guestfs_add_drive_opts> like this:
                          GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                          GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "rbd",
                          GUESTFS_ADD_DRIVE_OPTS_SERVER, servers,
+                         GUESTFS_ADD_DRIVE_OPTS_USERNAME, "rbduser",
+                         GUESTFS_ADD_DRIVE_OPTS_SECRET, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
                          -1);
 
 C<servers> (the C<server> parameter) is a list of one or more Ceph
 servers.  The server string is documented in
-L</guestfs_add_drive_opts>.
+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 GLUSTER
 
diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c
index c2bd81c..e33ddc6 100644
--- a/src/launch-libvirt.c
+++ b/src/launch-libvirt.c
@@ -1144,6 +1144,9 @@ construct_libvirt_xml_disk (guestfs_h *g,
       XMLERROR (-1,
                 xmlTextWriterWriteAttribute (xo, BAD_CAST "username",
                                              BAD_CAST drv_priv->real_src.username));
+      /* TODO: write the drive secret, after first storing it separately
+       * in libvirt
+       */
       XMLERROR (-1, xmlTextWriterEndElement (xo));
     }
   }
-- 
1.7.9.5




More information about the Libguestfs mailing list