On Thu, Jan 28, 2016 at 04:11:30PM +0100, Pino Toscano wrote:
lvm2 2.02.107 adds the -S/--select option used in lvs to filter out
only
public LVs (see RHBZ#1278878). To make this work again with versions
of lvm2 older than that, only on old versions filter out thin layouts
and compose the resulting device strings ourselves.
The filtering done is much simplier than what "-S lv_role=public" will
do, but should be good enough for our need.
---
daemon/lvm.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 136 insertions(+), 11 deletions(-)
diff --git a/daemon/lvm.c b/daemon/lvm.c
index 979cf63..8bef4d5 100644
--- a/daemon/lvm.c
+++ b/daemon/lvm.c
@@ -103,6 +103,85 @@ convert_lvm_output (char *out, const char *prefix)
return ret.argv;
}
+/* Filter a colon-separated output of
+ * lvs -o lv_attr,vg_name,lv_name
+ * removing thin layouts, and building the device path as we expect it.
+ *
+ * This is used only when lvm has no -S.
+ */
+static char **
+filter_convert_old_lvs_output (char *out)
+{
+ char *p, *pend;
+ DECLARE_STRINGSBUF (ret);
+
+ p = out;
+ while (p) {
+ size_t len;
+ char *saveptr;
+ char *lv_attr, *vg_name, *lv_name;
+
+ pend = strchr (p, '\n'); /* Get the next line of output. */
+ if (pend) {
+ *pend = '\0';
+ pend++;
+ }
+
+ while (*p && c_isspace (*p)) /* Skip any leading whitespace. */
+ p++;
+
+ /* Sigh, skip trailing whitespace too. "pvs", I'm looking at you. */
+ len = strlen (p)-1;
+ while (*p && c_isspace (p[len]))
+ p[len--] = '\0';
+
+ if (!*p) { /* Empty line? Skip it. */
+ skip_line:
+ p = pend;
+ continue;
+ }
+
+ lv_attr = strtok_r (p, ":", &saveptr);
+ if (!lv_attr)
+ goto skip_line;
+
+ vg_name = strtok_r (NULL, ":", &saveptr);
+ if (!vg_name)
+ goto skip_line;
+
+ lv_name = strtok_r (NULL, ":", &saveptr);
+ if (!lv_name)
+ goto skip_line;
+
+ /* Ignore thin layouts (RHBZ#1278878). */
+ if (lv_attr[0] == 't')
+ goto skip_line;
+
+ /* Ignore "unknown device" message (RHBZ#1054761). */
+ if (STRNEQ (p, "unknown device")) {
+ char buf[256];
+
+ snprintf (buf, sizeof buf, "/dev/%s/%s", vg_name, lv_name);
+ if (add_string (&ret, buf) == -1) {
+ free (out);
+ return NULL;
+ }
+ }
+
+ p = pend;
+ }
+
+ free (out);
+
+ if (ret.size > 0)
+ sort_strings (ret.argv, ret.size);
+
+ if (end_stringsbuf (&ret) == -1)
+ return NULL;
+
+ return ret.argv;
+}
+
char **
do_pvs (void)
{
@@ -139,26 +218,72 @@ do_vgs (void)
return convert_lvm_output (out, NULL);
}
+/* Check whether lvs has -S to filter its output.
+ * It is available only in lvm2 >= 2.02.107.
+ */
+static int
+test_lvs_has_S_opt (void)
+{
+ static int result = -1;
+ if (result != -1)
+ return result;
+
+ CLEANUP_FREE char *out = NULL;
+ CLEANUP_FREE char *err = NULL;
+
+ int r = command (&out, &err, str_lvm, "lvs", "--help",
NULL);
+ if (r == -1) {
+ reply_with_error ("lvm lvs --help: %s", err);
+ return -1;
+ }
+
+ if (strstr (out, "-S") == NULL)
+ result = 0;
+ else
+ result = 1;
+
+ return result;
+}
+
char **
do_lvs (void)
{
char *out;
CLEANUP_FREE char *err = NULL;
int r;
+ int has_S = test_lvs_has_S_opt ();
- r = command (&out, &err,
- str_lvm, "lvs",
- "-o", "vg_name,lv_name",
- "-S", "lv_role=public",
- "--noheadings",
- "--separator", "/", NULL);
- if (r == -1) {
- reply_with_error ("%s", err);
- free (out);
+ if (has_S < 0)
return NULL;
- }
- return convert_lvm_output (out, "/dev/");
+ if (has_S > 0) {
+ r = command (&out, &err,
+ str_lvm, "lvs",
+ "-o", "vg_name,lv_name",
+ "-S", "lv_role=public",
+ "--noheadings",
+ "--separator", "/", NULL);
+ if (r == -1) {
+ reply_with_error ("%s", err);
+ free (out);
+ return NULL;
+ }
+
+ return convert_lvm_output (out, "/dev/");
+ } else {
+ r = command (&out, &err,
+ str_lvm, "lvs",
+ "-o", "lv_attr,vg_name,lv_name",
+ "--noheadings",
+ "--separator", ":", NULL);
+ if (r == -1) {
+ reply_with_error ("%s", err);
+ free (out);
+ return NULL;
+ }
+
+ return filter_convert_old_lvs_output (out);
+ }
}
ACK.
Rich.
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v