|
|
ffd6ed |
From a72b602cfabd360335a63e70b6cb1abf7e82f69a Mon Sep 17 00:00:00 2001
|
|
|
ffd6ed |
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
|
ffd6ed |
Date: Fri, 31 Oct 2014 11:02:33 +0000
|
|
|
ffd6ed |
Subject: [PATCH] launch: libvirt: Implement drive secrets (RHBZ#1159016).
|
|
|
ffd6ed |
|
|
|
ffd6ed |
Implement the GUESTFS_ADD_DRIVE_OPTS_SECRET argument of
|
|
|
ffd6ed |
guestfs_add_drive_opts. For libvirt we have to save the secret in
|
|
|
ffd6ed |
libvirtd first, get a UUID, and then pass the UUID back through the
|
|
|
ffd6ed |
domain XML.
|
|
|
ffd6ed |
|
|
|
ffd6ed |
(cherry picked from commit 6d6644d52d8092dd4f4add859ebda06bea4b5b56)
|
|
|
ffd6ed |
---
|
|
|
ffd6ed |
bootstrap | 1 +
|
|
|
ffd6ed |
generator/actions.ml | 2 +-
|
|
|
ffd6ed |
m4/.gitignore | 4 +
|
|
|
ffd6ed |
src/launch-libvirt.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
|
ffd6ed |
4 files changed, 275 insertions(+), 4 deletions(-)
|
|
|
ffd6ed |
|
|
|
ffd6ed |
diff --git a/bootstrap b/bootstrap
|
|
|
ffd6ed |
index b4afcdb..70789e3 100755
|
|
|
ffd6ed |
--- a/bootstrap
|
|
|
ffd6ed |
+++ b/bootstrap
|
|
|
ffd6ed |
@@ -41,6 +41,7 @@ accept4
|
|
|
ffd6ed |
areadlink
|
|
|
ffd6ed |
areadlinkat
|
|
|
ffd6ed |
arpa_inet
|
|
|
ffd6ed |
+base64
|
|
|
ffd6ed |
byteswap
|
|
|
ffd6ed |
c-ctype
|
|
|
ffd6ed |
cloexec
|
|
|
ffd6ed |
diff --git a/generator/actions.ml b/generator/actions.ml
|
|
|
ffd6ed |
index ea715d0..4bc043b 100644
|
|
|
ffd6ed |
--- a/generator/actions.ml
|
|
|
ffd6ed |
+++ b/generator/actions.ml
|
|
|
ffd6ed |
@@ -1452,7 +1452,7 @@ specify the remote username you want.
|
|
|
ffd6ed |
=item C<secret>
|
|
|
ffd6ed |
|
|
|
ffd6ed |
For the C<rbd> protocol only, this specifies the 'secret' to use when
|
|
|
ffd6ed |
-connecting to the remote device.
|
|
|
ffd6ed |
+connecting to the remote device. It must be base64 encoded.
|
|
|
ffd6ed |
|
|
|
ffd6ed |
If not given, then a secret matching the given username will be looked up in the
|
|
|
ffd6ed |
default keychain locations, or if no username is given, then no authentication
|
|
|
ffd6ed |
diff --git a/m4/.gitignore b/m4/.gitignore
|
|
|
ffd6ed |
index ed73ab3..b0f8d4b 100644
|
|
|
ffd6ed |
--- a/m4/.gitignore
|
|
|
ffd6ed |
+++ b/m4/.gitignore
|
|
|
ffd6ed |
@@ -5,6 +5,7 @@
|
|
|
ffd6ed |
/argmatch.m4
|
|
|
ffd6ed |
/arpa_inet_h.m4
|
|
|
ffd6ed |
/asm-underscore.m4
|
|
|
ffd6ed |
+/base64.m4
|
|
|
ffd6ed |
/btowc.m4
|
|
|
ffd6ed |
/byteswap.m4
|
|
|
ffd6ed |
/canonicalize-lgpl.m4
|
|
|
ffd6ed |
@@ -104,6 +105,7 @@
|
|
|
ffd6ed |
/inttypes-pri.m4
|
|
|
ffd6ed |
/ioctl.m4
|
|
|
ffd6ed |
/i-ring.m4
|
|
|
ffd6ed |
+/isatty.m4
|
|
|
ffd6ed |
/isc-posix.m4
|
|
|
ffd6ed |
/largefile.m4
|
|
|
ffd6ed |
/lchown.m4
|
|
|
ffd6ed |
@@ -166,6 +168,7 @@
|
|
|
ffd6ed |
/printf-posix.m4
|
|
|
ffd6ed |
/priv-set.m4
|
|
|
ffd6ed |
/progtest.m4
|
|
|
ffd6ed |
+/ptsname_r.m4
|
|
|
ffd6ed |
/putenv.m4
|
|
|
ffd6ed |
/quotearg.m4
|
|
|
ffd6ed |
/quote.m4
|
|
|
ffd6ed |
@@ -236,6 +239,7 @@
|
|
|
ffd6ed |
/thread.m4
|
|
|
ffd6ed |
/time_h.m4
|
|
|
ffd6ed |
/timespec.m4
|
|
|
ffd6ed |
+/ttyname_r.m4
|
|
|
ffd6ed |
/uintmax_t.m4
|
|
|
ffd6ed |
/ulonglong.m4
|
|
|
ffd6ed |
/ungetc.m4
|
|
|
ffd6ed |
diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c
|
|
|
ffd6ed |
index 026fd5a..5daa396 100644
|
|
|
ffd6ed |
--- a/src/launch-libvirt.c
|
|
|
ffd6ed |
+++ b/src/launch-libvirt.c
|
|
|
ffd6ed |
@@ -49,6 +49,7 @@
|
|
|
ffd6ed |
#endif
|
|
|
ffd6ed |
|
|
|
ffd6ed |
#include "glthread/lock.h"
|
|
|
ffd6ed |
+#include "base64.h"
|
|
|
ffd6ed |
|
|
|
ffd6ed |
#include "guestfs.h"
|
|
|
ffd6ed |
#include "guestfs-internal.h"
|
|
|
ffd6ed |
@@ -96,6 +97,27 @@ xmlBufferDetach (xmlBufferPtr buf)
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
#endif
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+#ifdef HAVE_ATTRIBUTE_CLEANUP
|
|
|
ffd6ed |
+#define CLEANUP_VIRSECRETFREE __attribute__((cleanup(cleanup_virSecretFree)))
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+static void
|
|
|
ffd6ed |
+cleanup_virSecretFree (void *ptr)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ virSecretPtr secret_obj = * (virSecretPtr *) ptr;
|
|
|
ffd6ed |
+ if (secret_obj)
|
|
|
ffd6ed |
+ virSecretFree (secret_obj);
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+#else /* !HAVE_ATTRIBUTE_CLEANUP */
|
|
|
ffd6ed |
+#define CLEANUP_VIRSECRETFREE
|
|
|
ffd6ed |
+#endif
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+/* List used to store a mapping of secret to libvirt secret UUID. */
|
|
|
ffd6ed |
+struct secret {
|
|
|
ffd6ed |
+ char *secret;
|
|
|
ffd6ed |
+ char uuid[VIR_UUID_STRING_BUFLEN];
|
|
|
ffd6ed |
+};
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
#define DOMAIN_NAME_LEN (8+16+1) /* "guestfs-" + random + \0 */
|
|
|
ffd6ed |
|
|
|
ffd6ed |
/* Per-handle data. */
|
|
|
ffd6ed |
@@ -108,6 +130,8 @@ struct backend_libvirt_data {
|
|
|
ffd6ed |
char name[DOMAIN_NAME_LEN]; /* random name */
|
|
|
ffd6ed |
bool is_kvm; /* false = qemu, true = kvm (from capabilities)*/
|
|
|
ffd6ed |
unsigned long qemu_version; /* qemu version (from libvirt) */
|
|
|
ffd6ed |
+ struct secret *secrets; /* list of secrets */
|
|
|
ffd6ed |
+ size_t nr_secrets;
|
|
|
ffd6ed |
char *uefi_code; /* UEFI (firmware) code and variables. */
|
|
|
ffd6ed |
char *uefi_vars;
|
|
|
ffd6ed |
};
|
|
|
ffd6ed |
@@ -130,6 +154,9 @@ struct libvirt_xml_params {
|
|
|
ffd6ed |
};
|
|
|
ffd6ed |
|
|
|
ffd6ed |
static int parse_capabilities (guestfs_h *g, const char *capabilities_xml, struct backend_libvirt_data *data);
|
|
|
ffd6ed |
+static int add_secret (guestfs_h *g, virConnectPtr conn, struct backend_libvirt_data *data, const struct drive *drv);
|
|
|
ffd6ed |
+static int find_secret (guestfs_h *g, const struct backend_libvirt_data *data, const struct drive *drv, const char **type, const char **uuid);
|
|
|
ffd6ed |
+static int have_secret (guestfs_h *g, const struct backend_libvirt_data *data, const struct drive *drv);
|
|
|
ffd6ed |
static xmlChar *construct_libvirt_xml (guestfs_h *g, const struct libvirt_xml_params *params);
|
|
|
ffd6ed |
static void debug_appliance_permissions (guestfs_h *g);
|
|
|
ffd6ed |
static void debug_socket_permissions (guestfs_h *g);
|
|
|
ffd6ed |
@@ -224,6 +251,8 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
|
|
|
ffd6ed |
CLEANUP_FREE xmlChar *xml = NULL;
|
|
|
ffd6ed |
CLEANUP_FREE char *appliance = NULL;
|
|
|
ffd6ed |
struct sockaddr_un addr;
|
|
|
ffd6ed |
+ struct drive *drv;
|
|
|
ffd6ed |
+ size_t i;
|
|
|
ffd6ed |
int r;
|
|
|
ffd6ed |
uint32_t size;
|
|
|
ffd6ed |
CLEANUP_FREE void *buf = NULL;
|
|
|
ffd6ed |
@@ -456,6 +485,14 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
|
|
|
ffd6ed |
debug (g, "cannot find group 'qemu'");
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ /* Store any secrets in libvirtd, keeping a mapping from the secret
|
|
|
ffd6ed |
+ * to its UUID.
|
|
|
ffd6ed |
+ */
|
|
|
ffd6ed |
+ ITER_DRIVES (g, i, drv) {
|
|
|
ffd6ed |
+ if (add_secret (g, conn, data, drv) == -1)
|
|
|
ffd6ed |
+ goto cleanup;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
/* Construct the libvirt XML. */
|
|
|
ffd6ed |
if (g->verbose)
|
|
|
ffd6ed |
guestfs___print_timestamped_message (g, "create libvirt XML");
|
|
|
ffd6ed |
@@ -1275,6 +1312,8 @@ construct_libvirt_xml_disk (guestfs_h *g,
|
|
|
ffd6ed |
CLEANUP_FREE char *path = NULL;
|
|
|
ffd6ed |
int is_host_device;
|
|
|
ffd6ed |
CLEANUP_FREE char *format = NULL;
|
|
|
ffd6ed |
+ const char *type, *uuid;
|
|
|
ffd6ed |
+ int r;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
/* XXX We probably could support this if we thought about it some more. */
|
|
|
ffd6ed |
if (drv->iface) {
|
|
|
ffd6ed |
@@ -1386,9 +1425,15 @@ construct_libvirt_xml_disk (guestfs_h *g,
|
|
|
ffd6ed |
if (drv->src.username != NULL) {
|
|
|
ffd6ed |
start_element ("auth") {
|
|
|
ffd6ed |
attribute ("username", drv->src.username);
|
|
|
ffd6ed |
- /* TODO: write the drive secret, after first storing it separately
|
|
|
ffd6ed |
- * in libvirt
|
|
|
ffd6ed |
- */
|
|
|
ffd6ed |
+ r = find_secret (g, data, drv, &type, &uuid);
|
|
|
ffd6ed |
+ if (r == -1)
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ if (r == 1) {
|
|
|
ffd6ed |
+ start_element ("secret") {
|
|
|
ffd6ed |
+ attribute ("type", type);
|
|
|
ffd6ed |
+ attribute ("uuid", uuid);
|
|
|
ffd6ed |
+ } end_element ();
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
} end_element ();
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
break;
|
|
|
ffd6ed |
@@ -1696,6 +1741,216 @@ construct_libvirt_xml_qemu_cmdline (guestfs_h *g,
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
static int
|
|
|
ffd6ed |
+construct_libvirt_xml_secret (guestfs_h *g,
|
|
|
ffd6ed |
+ const struct backend_libvirt_data *data,
|
|
|
ffd6ed |
+ const struct drive *drv,
|
|
|
ffd6ed |
+ xmlTextWriterPtr xo)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ start_element ("secret") {
|
|
|
ffd6ed |
+ attribute ("ephemeral", "yes");
|
|
|
ffd6ed |
+ attribute ("private", "yes");
|
|
|
ffd6ed |
+ start_element ("description") {
|
|
|
ffd6ed |
+ string_format ("guestfs secret associated with %s %s",
|
|
|
ffd6ed |
+ data->name, drv->src.u.path);
|
|
|
ffd6ed |
+ } end_element ();
|
|
|
ffd6ed |
+ } end_element ();
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ return 0;
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+/* If drv->src.secret != NULL, store the secret in libvirt, and save
|
|
|
ffd6ed |
+ * the UUID so we can retrieve it later. Also there is some slight
|
|
|
ffd6ed |
+ * variation depending on the protocol. See
|
|
|
ffd6ed |
+ * http://libvirt.org/formatsecret.html
|
|
|
ffd6ed |
+ */
|
|
|
ffd6ed |
+static int
|
|
|
ffd6ed |
+add_secret (guestfs_h *g, virConnectPtr conn,
|
|
|
ffd6ed |
+ struct backend_libvirt_data *data, const struct drive *drv)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ CLEANUP_XMLBUFFERFREE xmlBufferPtr xb = NULL;
|
|
|
ffd6ed |
+ xmlOutputBufferPtr ob;
|
|
|
ffd6ed |
+ CLEANUP_XMLFREETEXTWRITER xmlTextWriterPtr xo = NULL;
|
|
|
ffd6ed |
+ CLEANUP_FREE xmlChar *xml = NULL;
|
|
|
ffd6ed |
+ CLEANUP_VIRSECRETFREE virSecretPtr secret_obj = NULL;
|
|
|
ffd6ed |
+ const char *secret = drv->src.secret;
|
|
|
ffd6ed |
+ CLEANUP_FREE unsigned char *secret_raw = NULL;
|
|
|
ffd6ed |
+ size_t secret_raw_len = 0;
|
|
|
ffd6ed |
+ size_t i;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ if (secret == NULL)
|
|
|
ffd6ed |
+ return 0;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ /* If it was already stored, don't create another secret. */
|
|
|
ffd6ed |
+ if (have_secret (g, data, drv))
|
|
|
ffd6ed |
+ return 0;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ /* Create the XML for the secret. */
|
|
|
ffd6ed |
+ xb = xmlBufferCreate ();
|
|
|
ffd6ed |
+ if (xb == NULL) {
|
|
|
ffd6ed |
+ perrorf (g, "xmlBufferCreate");
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ ob = xmlOutputBufferCreateBuffer (xb, NULL);
|
|
|
ffd6ed |
+ if (ob == NULL) {
|
|
|
ffd6ed |
+ perrorf (g, "xmlOutputBufferCreateBuffer");
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ xo = xmlNewTextWriter (ob);
|
|
|
ffd6ed |
+ if (xo == NULL) {
|
|
|
ffd6ed |
+ perrorf (g, "xmlNewTextWriter");
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ if (xmlTextWriterSetIndent (xo, 1) == -1 ||
|
|
|
ffd6ed |
+ xmlTextWriterSetIndentString (xo, BAD_CAST " ") == -1) {
|
|
|
ffd6ed |
+ perrorf (g, "could not set XML indent");
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ if (xmlTextWriterStartDocument (xo, NULL, NULL, NULL) == -1) {
|
|
|
ffd6ed |
+ perrorf (g, "xmlTextWriterStartDocument");
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ if (construct_libvirt_xml_secret (g, data, drv, xo) == -1)
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ if (xmlTextWriterEndDocument (xo) == -1) {
|
|
|
ffd6ed |
+ perrorf (g, "xmlTextWriterEndDocument");
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ xml = xmlBufferDetach (xb);
|
|
|
ffd6ed |
+ if (xml == NULL) {
|
|
|
ffd6ed |
+ perrorf (g, "xmlBufferDetach");
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ debug (g, "libvirt secret XML:\n%s", xml);
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ /* Pass the XML to libvirt. */
|
|
|
ffd6ed |
+ secret_obj = virSecretDefineXML (conn, (const char *) xml, 0);
|
|
|
ffd6ed |
+ if (secret_obj == NULL) {
|
|
|
ffd6ed |
+ libvirt_error (g, _("could not define libvirt secret"));
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ /* For Ceph, we have to base64 decode the secret. For others, we
|
|
|
ffd6ed |
+ * currently just pass the secret straight through.
|
|
|
ffd6ed |
+ */
|
|
|
ffd6ed |
+ switch (drv->src.protocol) {
|
|
|
ffd6ed |
+ case drive_protocol_rbd:
|
|
|
ffd6ed |
+ if (!base64_decode_alloc (secret, strlen (secret),
|
|
|
ffd6ed |
+ (char **) &secret_raw, &secret_raw_len)) {
|
|
|
ffd6ed |
+ error (g, _("rbd protocol secret must be base64 encoded"));
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ if (secret_raw == NULL) {
|
|
|
ffd6ed |
+ error (g, _("base64_decode_alloc: %m"));
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+ case drive_protocol_file:
|
|
|
ffd6ed |
+ case drive_protocol_ftp:
|
|
|
ffd6ed |
+ case drive_protocol_ftps:
|
|
|
ffd6ed |
+ case drive_protocol_gluster:
|
|
|
ffd6ed |
+ case drive_protocol_http:
|
|
|
ffd6ed |
+ case drive_protocol_https:
|
|
|
ffd6ed |
+ case drive_protocol_iscsi:
|
|
|
ffd6ed |
+ case drive_protocol_nbd:
|
|
|
ffd6ed |
+ case drive_protocol_sheepdog:
|
|
|
ffd6ed |
+ case drive_protocol_ssh:
|
|
|
ffd6ed |
+ case drive_protocol_tftp:
|
|
|
ffd6ed |
+ secret_raw = (unsigned char *) safe_strdup (g, secret);
|
|
|
ffd6ed |
+ secret_raw_len = strlen (secret);
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ /* Set the secret. */
|
|
|
ffd6ed |
+ if (virSecretSetValue (secret_obj, secret_raw, secret_raw_len, 0) == -1) {
|
|
|
ffd6ed |
+ libvirt_error (g, _("could not set libvirt secret value"));
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ /* Get back the UUID and save it in the private data. */
|
|
|
ffd6ed |
+ i = data->nr_secrets;
|
|
|
ffd6ed |
+ data->nr_secrets++;
|
|
|
ffd6ed |
+ data->secrets =
|
|
|
ffd6ed |
+ safe_realloc (g, data->secrets, sizeof (struct secret) * data->nr_secrets);
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ data->secrets[i].secret = safe_strdup (g, secret);
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ if (virSecretGetUUIDString (secret_obj, data->secrets[i].uuid) == -1) {
|
|
|
ffd6ed |
+ libvirt_error (g, _("could not get UUID from libvirt secret"));
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ return 0;
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+static int
|
|
|
ffd6ed |
+have_secret (guestfs_h *g,
|
|
|
ffd6ed |
+ const struct backend_libvirt_data *data, const struct drive *drv)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ size_t i;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ if (drv->src.secret == NULL)
|
|
|
ffd6ed |
+ return 0;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ for (i = 0; i < data->nr_secrets; ++i) {
|
|
|
ffd6ed |
+ if (STREQ (data->secrets[i].secret, drv->src.secret))
|
|
|
ffd6ed |
+ return 1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ return 0;
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+/* Find a secret previously stored in libvirt. Returns the
|
|
|
ffd6ed |
+ * <secret type=... uuid=...> attributes. This function returns -1
|
|
|
ffd6ed |
+ * if there was an error, 0 if there is no secret, and 1 if the
|
|
|
ffd6ed |
+ * secret was found and returned.
|
|
|
ffd6ed |
+ */
|
|
|
ffd6ed |
+static int
|
|
|
ffd6ed |
+find_secret (guestfs_h *g,
|
|
|
ffd6ed |
+ const struct backend_libvirt_data *data, const struct drive *drv,
|
|
|
ffd6ed |
+ const char **type, const char **uuid)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ size_t i;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ if (drv->src.secret == NULL)
|
|
|
ffd6ed |
+ return 0;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ for (i = 0; i < data->nr_secrets; ++i) {
|
|
|
ffd6ed |
+ if (STREQ (data->secrets[i].secret, drv->src.secret)) {
|
|
|
ffd6ed |
+ *uuid = data->secrets[i].uuid;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ *type = "volume";
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ switch (drv->src.protocol) {
|
|
|
ffd6ed |
+ case drive_protocol_rbd:
|
|
|
ffd6ed |
+ *type = "ceph";
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+ case drive_protocol_iscsi:
|
|
|
ffd6ed |
+ *type = "iscsi";
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+ case drive_protocol_file:
|
|
|
ffd6ed |
+ case drive_protocol_ftp:
|
|
|
ffd6ed |
+ case drive_protocol_ftps:
|
|
|
ffd6ed |
+ case drive_protocol_gluster:
|
|
|
ffd6ed |
+ case drive_protocol_http:
|
|
|
ffd6ed |
+ case drive_protocol_https:
|
|
|
ffd6ed |
+ case drive_protocol_nbd:
|
|
|
ffd6ed |
+ case drive_protocol_sheepdog:
|
|
|
ffd6ed |
+ case drive_protocol_ssh:
|
|
|
ffd6ed |
+ case drive_protocol_tftp:
|
|
|
ffd6ed |
+ /* set to a default value above */ ;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ return 1;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ return 0;
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+static int
|
|
|
ffd6ed |
is_blk (const char *path)
|
|
|
ffd6ed |
{
|
|
|
ffd6ed |
struct stat statbuf;
|
|
|
ffd6ed |
@@ -1717,6 +1972,7 @@ shutdown_libvirt (guestfs_h *g, void *datav, int check_for_errors)
|
|
|
ffd6ed |
struct backend_libvirt_data *data = datav;
|
|
|
ffd6ed |
virConnectPtr conn = data->conn;
|
|
|
ffd6ed |
virDomainPtr dom = data->dom;
|
|
|
ffd6ed |
+ size_t i;
|
|
|
ffd6ed |
int ret = 0;
|
|
|
ffd6ed |
int flags;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
@@ -1751,6 +2007,12 @@ shutdown_libvirt (guestfs_h *g, void *datav, int check_for_errors)
|
|
|
ffd6ed |
free (data->uefi_vars);
|
|
|
ffd6ed |
data->uefi_vars = NULL;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ for (i = 0; i < data->nr_secrets; ++i)
|
|
|
ffd6ed |
+ free (data->secrets[i].secret);
|
|
|
ffd6ed |
+ free (data->secrets);
|
|
|
ffd6ed |
+ data->secrets = NULL;
|
|
|
ffd6ed |
+ data->nr_secrets = 0;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
return ret;
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
@@ -1855,6 +2117,10 @@ hot_add_drive_libvirt (guestfs_h *g, void *datav,
|
|
|
ffd6ed |
return -1;
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ /* If the drive has an associated secret, store it in libvirt. */
|
|
|
ffd6ed |
+ if (add_secret (g, conn, data, drv) == -1)
|
|
|
ffd6ed |
+ return -1;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
/* Create the XML for the new disk. */
|
|
|
ffd6ed |
xml = construct_libvirt_xml_hot_add_disk (g, data, drv, drv_index);
|
|
|
ffd6ed |
if (xml == NULL)
|
|
|
ffd6ed |
--
|
|
|
ffd6ed |
1.8.3.1
|
|
|
ffd6ed |
|