1 /* libguestfs - the guestfsd daemon
2 * Copyright (C) 2009 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 #include "optgroups.h"
34 optgroup_lvm2_available (void)
36 return prog_exists ("lvm");
39 /* LVM actions. Keep an eye on liblvm, although at the time
40 * of writing it hasn't progressed very far.
44 convert_lvm_output (char *out, const char *prefix)
48 int size = 0, alloc = 0;
55 pend = strchr (p, '\n'); /* Get the next line of output. */
61 while (*p && c_isspace (*p)) /* Skip any leading whitespace. */
64 /* Sigh, skip trailing whitespace too. "pvs", I'm looking at you. */
66 while (*p && c_isspace (p[len]))
69 if (!*p) { /* Empty line? Skip it. */
76 snprintf (buf, sizeof buf, "%s%s", prefix, p);
81 if (add_string (&r, &size, &alloc, str) == -1) {
91 if (add_string (&r, &size, &alloc, NULL) == -1)
94 sort_strings (r, size-1);
104 r = command (&out, &err,
105 "lvm", "pvs", "-o", "pv_name", "--noheadings", NULL);
107 reply_with_error ("%s", err);
115 return convert_lvm_output (out, NULL);
124 r = command (&out, &err,
125 "lvm", "vgs", "-o", "vg_name", "--noheadings", NULL);
127 reply_with_error ("%s", err);
135 return convert_lvm_output (out, NULL);
144 r = command (&out, &err,
146 "-o", "vg_name,lv_name", "--noheadings",
147 "--separator", "/", NULL);
149 reply_with_error ("%s", err);
157 return convert_lvm_output (out, "/dev/");
160 /* These were so complex to implement that I ended up auto-generating
161 * the code. That code is in stubs.c, and it is generated as usual
164 guestfs_int_lvm_pv_list *
167 return parse_command_line_pvs ();
170 guestfs_int_lvm_vg_list *
173 return parse_command_line_vgs ();
176 guestfs_int_lvm_lv_list *
179 return parse_command_line_lvs ();
183 do_pvcreate (const char *device)
188 r = command (NULL, &err,
189 "lvm", "pvcreate", device, NULL);
191 reply_with_error ("%s", err);
204 do_vgcreate (const char *volgroup, char *const *physvols)
210 argc = count_strings (physvols) + 3;
211 argv = malloc (sizeof (char *) * (argc + 1));
213 reply_with_perror ("malloc");
217 argv[1] = "vgcreate";
219 for (i = 3; i <= argc; ++i)
220 argv[i] = physvols[i-3];
222 r = commandv (NULL, &err, (const char * const*) argv);
224 reply_with_error ("%s", err);
239 do_lvcreate (const char *logvol, const char *volgroup, int mbytes)
245 snprintf (size, sizeof size, "%d", mbytes);
247 r = command (NULL, &err,
249 "-L", size, "-n", logvol, volgroup, NULL);
251 reply_with_error ("%s", err);
264 do_lvresize (const char *logvol, int mbytes)
270 snprintf (size, sizeof size, "%d", mbytes);
272 r = command (NULL, &err,
274 "--force", "-L", size, logvol, NULL);
276 reply_with_error ("%s", err);
286 do_lvresize_free (const char *logvol, int percent)
291 if (percent < 0 || percent > 100) {
292 reply_with_error ("percentage must be [0..100] (was %d)", percent);
297 snprintf (size, sizeof size, "+%d%%FREE", percent);
299 r = command (NULL, &err,
300 "lvm", "lvresize", "-l", size, logvol, NULL);
302 reply_with_error ("%s", err);
311 /* Super-dangerous command used for testing. It removes all
312 * LVs, VGs and PVs permanently.
315 do_lvm_remove_all (void)
326 for (i = 0; xs[i] != NULL; ++i) {
327 /* Deactivate the LV first. On Ubuntu, lvremove '-f' option
328 * does not remove active LVs reliably.
330 (void) command (NULL, NULL, "lvm", "lvchange", "-an", xs[i], NULL);
333 r = command (NULL, &err, "lvm", "lvremove", "-f", xs[i], NULL);
335 reply_with_error ("lvremove: %s: %s", xs[i], err);
349 for (i = 0; xs[i] != NULL; ++i) {
350 /* Deactivate the VG first, see note above. */
351 (void) command (NULL, NULL, "lvm", "vgchange", "-an", xs[i], NULL);
354 r = command (NULL, &err, "lvm", "vgremove", "-f", xs[i], NULL);
356 reply_with_error ("vgremove: %s: %s", xs[i], err);
370 for (i = 0; xs[i] != NULL; ++i) {
371 r = command (NULL, &err, "lvm", "pvremove", "-f", xs[i], NULL);
373 reply_with_error ("pvremove: %s: %s", xs[i], err);
384 /* There, that was easy, sorry about your data. */
389 do_lvremove (const char *device)
394 r = command (NULL, &err,
395 "lvm", "lvremove", "-f", device, NULL);
397 reply_with_error ("%s", err);
410 do_vgremove (const char *device)
415 r = command (NULL, &err,
416 "lvm", "vgremove", "-f", device, NULL);
418 reply_with_error ("%s", err);
431 do_pvremove (const char *device)
436 r = command (NULL, &err,
437 "lvm", "pvremove", "-ff", device, NULL);
439 reply_with_error ("%s", err);
452 do_pvresize (const char *device)
457 r = command (NULL, &err,
458 "lvm", "pvresize", device, NULL);
460 reply_with_error ("%s: %s", device, err);
470 do_pvresize_size (const char *device, int64_t size)
476 snprintf (buf, sizeof buf, "%" PRIi64 "b", size);
478 r = command (NULL, &err,
480 "--setphysicalvolumesize", buf,
483 reply_with_error ("%s: %s", device, err);
493 do_vg_activate (int activate, char *const *volgroups)
499 argc = count_strings (volgroups) + 4;
500 argv = malloc (sizeof (char *) * (argc+1));
502 reply_with_perror ("malloc");
507 argv[1] = "vgchange";
509 argv[3] = activate ? "y" : "n";
510 for (i = 4; i <= argc; ++i)
511 argv[i] = volgroups[i-4];
513 r = commandv (NULL, &err, (const char * const*) argv);
515 reply_with_error ("vgchange: %s", err);
530 do_vg_activate_all (int activate)
532 char *empty[] = { NULL };
533 return do_vg_activate (activate, empty);
537 do_lvrename (const char *logvol, const char *newlogvol)
542 r = command (NULL, &err,
544 logvol, newlogvol, NULL);
546 reply_with_error ("%s -> %s: %s", logvol, newlogvol, err);
559 do_vgrename (const char *volgroup, const char *newvolgroup)
564 r = command (NULL, &err,
566 volgroup, newvolgroup, NULL);
568 reply_with_error ("%s -> %s: %s", volgroup, newvolgroup, err);
581 get_lvm_field (const char *cmd, const char *field, const char *device)
585 int r = command (&out, &err,
587 "--unbuffered", "--noheadings", "-o", field,
590 reply_with_error ("%s: %s", device, err);
599 return out; /* Caller frees. */
603 do_pvuuid (const char *device)
605 return get_lvm_field ("pvs", "pv_uuid", device);
609 do_vguuid (const char *vgname)
611 return get_lvm_field ("vgs", "vg_uuid", vgname);
615 do_lvuuid (const char *device)
617 return get_lvm_field ("lvs", "lv_uuid", device);
621 get_lvm_fields (const char *cmd, const char *field, const char *device)
625 int r = command (&out, &err,
627 "--unbuffered", "--noheadings", "-o", field,
630 reply_with_error ("%s: %s", device, err);
638 char **ret = split_lines (out);
645 for (i = 0; ret[i] != NULL; ++i)
652 do_vgpvuuids (const char *vgname)
654 return get_lvm_fields ("vgs", "pv_uuid", vgname);
658 do_vglvuuids (const char *vgname)
660 return get_lvm_fields ("vgs", "lv_uuid", vgname);
669 r = command (NULL, &err,
670 "lvm", "vgscan", NULL);
672 reply_with_error ("%s", err);
681 /* Convert a non-canonical LV path like /dev/mapper/vg-lv or /dev/dm-0
682 * to a canonical one.
684 * This is harder than it should be. A LV device like /dev/VG/LV is
685 * really a symlink to a device-mapper device like /dev/dm-0. However
686 * at the device-mapper (kernel) level, nothing is really known about
687 * LVM (a userspace concept). Therefore we use a convoluted method to
688 * determine this, by listing out known LVs and checking whether the
689 * rdev (major/minor) of the device we are passed matches any of them.
691 * Note use of 'stat' instead of 'lstat' so that symlinks are fully
695 * 1 = conversion was successful, path is an LV
696 * '*ret' is set to the updated path if 'ret' is non-NULL.
697 * 0 = path is not an LV
698 * -1 = error, reply_with_* has been called
702 lv_canonical (const char *device, char **ret)
704 struct stat stat1, stat2;
706 int r = stat (device, &stat1);
708 reply_with_perror ("stat: %s", device);
712 char **lvs = do_lvs ();
717 for (i = 0; lvs[i] != NULL; ++i) {
718 r = stat (lvs[i], &stat2);
720 reply_with_perror ("stat: %s", lvs[i]);
724 if (stat1.st_rdev == stat2.st_rdev) { /* found it */
726 *ret = strdup (lvs[i]);
728 reply_with_perror ("strdup");
743 /* Test if a device is a logical volume (RHBZ#619793). */
745 do_is_lv (const char *device)
747 return lv_canonical (device, NULL);
750 /* Return canonical name of LV to caller (RHBZ#638899). */
752 do_lvm_canonical_lv_name (const char *device)
755 int r = lv_canonical (device, &canonical);
760 reply_with_error ("%s: not a logical volume", device);
764 return canonical; /* caller frees */