4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <readline/readline.h>
26 static int lvm_split(char *str
, int *argc
, char **argv
, int max
)
32 while (*b
&& isspace(*b
))
35 if ((!*b
) || ((*argc
== 0)&&(*b
== '#')))
39 while (*e
&& !isspace(*e
))
54 static void _show_help(void)
56 printf("'lv_activate vgname lvname: "
58 printf("'lv_deactivate vgname lvname: "
59 "Deactivate an LV\n");
60 printf("'vg_remove_lv vgname lvname': "
62 printf("'vg_create_lv_linear vgname lvname size_in_bytes': "
63 "Create a linear LV\n");
65 "Scan the system for LVM metadata\n");
66 printf("'list_vg_names': "
67 "List the names of the VGs that exist in the system\n");
68 printf("'list_vg_ids': "
69 "List the uuids of the VGs that exist in the system\n");
70 printf("'vg_list_pvs vgname': "
71 "List the PVs that exist in VG vgname\n");
72 printf("'vg_list_lvs vgname': "
73 "List the LVs that exist in VG vgname\n");
75 "List the VGs that are currently open\n");
77 "List all VGs known to the system\n");
78 printf("'vg_extend vgname device: "
79 "Issue a lvm_vg_extend() API call on VG 'vgname'\n");
80 printf("'vg_reduce vgname device: "
81 "Issue a lvm_vg_reduce() API call on VG 'vgname'\n");
82 printf("'vg_open vgname ['r' | 'w']': "
83 "Issue a lvm_vg_open() API call on VG 'vgname'\n");
84 printf("'vg_close vgname': "
85 "Issue a lvm_vg_close() API call on VG 'vgname'\n");
86 printf("'vg_create vgname: "
87 "Issue a lvm_vg_create() to create VG 'vgname'\n");
88 printf("'vg_remove vgname: "
89 "Issue a lvm_vg_remove() to remove VG 'vgname'\n");
90 printf("'config_reload': "
91 "Issue a lvm_config_reload() API to reload LVM config\n");
92 printf("'config_override' device: "
93 "Issue a lvm_config_override() with accept device filter\n");
94 printf("'quit': exit the program\n");
97 static struct dm_hash_table
*_vgid_hash
= NULL
;
98 static struct dm_hash_table
*_vgname_hash
= NULL
;
99 static struct dm_hash_table
*_pvname_hash
= NULL
;
100 static struct dm_hash_table
*_lvname_hash
= NULL
;
102 static void _hash_destroy_single(struct dm_hash_table
**htable
)
104 if (htable
&& *htable
) {
105 dm_hash_destroy(*htable
);
110 static void _hash_destroy(void)
112 _hash_destroy_single(&_vgname_hash
);
113 _hash_destroy_single(&_vgid_hash
);
114 _hash_destroy_single(&_pvname_hash
);
115 _hash_destroy_single(&_lvname_hash
);
118 static int _hash_create(void)
120 if (!(_vgname_hash
= dm_hash_create(128)))
122 if (!(_pvname_hash
= dm_hash_create(128))) {
123 _hash_destroy_single(&_vgname_hash
);
126 if (!(_lvname_hash
= dm_hash_create(128))) {
127 _hash_destroy_single(&_vgname_hash
);
128 _hash_destroy_single(&_pvname_hash
);
131 if (!(_vgid_hash
= dm_hash_create(128))) {
132 _hash_destroy_single(&_vgname_hash
);
133 _hash_destroy_single(&_pvname_hash
);
134 _hash_destroy_single(&_lvname_hash
);
140 /* FIXME: this should be per vg */
141 static lv_t
_lookup_lv_by_name(const char *name
)
146 printf ("Invalid LV name\n");
149 if (!(lv
= dm_hash_lookup(_lvname_hash
, name
))) {
150 printf ("Can't find %s in LVs - run vg_create_lv first\n",
157 static vg_t
_lookup_vg_by_name(char **argv
, int argc
)
162 printf ("Please enter vg_name\n");
165 if (!(vg
= dm_hash_lookup(_vgid_hash
, argv
[1])) &&
166 !(vg
= dm_hash_lookup(_vgname_hash
, argv
[1]))) {
167 printf ("Can't find %s in open VGs - run vg_open first\n",
173 static void _add_lvs_to_lvname_hash(struct dm_list
*lvs
)
175 struct lvm_lv_list
*lvl
;
176 dm_list_iterate_items(lvl
, lvs
) {
177 /* Concatenate VG name with LV name */
178 dm_hash_insert(_lvname_hash
, lvm_lv_get_name(lvl
->lv
), lvl
->lv
);
182 static void _add_pvs_to_pvname_hash(struct dm_list
*pvs
)
184 struct lvm_pv_list
*pvl
;
185 dm_list_iterate_items(pvl
, pvs
) {
186 dm_hash_insert(_pvname_hash
, lvm_pv_get_name(pvl
->pv
), pvl
->pv
);
190 static void _remove_device_from_pvname_hash(struct dm_list
*pvs
, const char *name
)
192 struct lvm_pv_list
*pvl
;
193 dm_list_iterate_items(pvl
, pvs
) {
194 if (!strncmp(lvm_pv_get_name(pvl
->pv
), name
, strlen(name
)))
195 dm_hash_remove(_pvname_hash
, name
);
198 static void _add_device_to_pvname_hash(struct dm_list
*pvs
, const char *name
)
200 struct lvm_pv_list
*pvl
;
201 dm_list_iterate_items(pvl
, pvs
) {
202 if (!strncmp(lvm_pv_get_name(pvl
->pv
), name
, strlen(name
)))
203 dm_hash_insert(_pvname_hash
, name
, pvl
->pv
);
206 static void _vg_reduce(char **argv
, int argc
, lvm_t libh
)
212 printf ("Please enter vg_name\n");
215 if (!(vg
= dm_hash_lookup(_vgid_hash
, argv
[1])) &&
216 !(vg
= dm_hash_lookup(_vgname_hash
, argv
[1]))) {
217 printf ("VG not open\n");
220 if (lvm_vg_reduce(vg
, argv
[2])) {
221 printf("Error reducing %s by %s\n", argv
[1], argv
[2]);
225 printf("Success reducing vg %s by %s\n", argv
[1], argv
[2]);
228 * Add the device into the hashes for lookups
230 pvs
= lvm_vg_list_pvs(vg
);
231 if (pvs
&& !dm_list_empty(pvs
))
232 _remove_device_from_pvname_hash(pvs
, argv
[2]);
235 /* Print "Error" or "Success" depending on lvm status */
236 static int _lvm_status_to_pass_fail(int rc
)
244 static void _config_override(char **argv
, int argc
, lvm_t libh
)
250 printf ("Please enter device\n");
253 snprintf(tmp
, 63, "devices{filter=[\"a|%s|\", \"r|.*|\"]}", argv
[1]);
254 rc
= lvm_config_override(libh
, tmp
);
255 _lvm_status_to_pass_fail(rc
);
256 printf("overriding LVM configuration\n");
259 static void _config_reload(char **argv
, int argc
, lvm_t libh
)
262 rc
= lvm_config_reload(libh
);
263 _lvm_status_to_pass_fail(rc
);
264 printf("reloading LVM configuration\n");
267 static void _vg_extend(char **argv
, int argc
, lvm_t libh
)
273 printf ("Please enter vg_name\n");
276 if (!(vg
= dm_hash_lookup(_vgid_hash
, argv
[1])) &&
277 !(vg
= dm_hash_lookup(_vgname_hash
, argv
[1]))) {
278 printf ("VG not open\n");
281 if (lvm_vg_extend(vg
, argv
[2])) {
282 printf("Error extending %s with %s\n", argv
[1], argv
[2]);
286 printf("Success extending vg %s with %s\n", argv
[1], argv
[2]);
289 * Add the device into the hashes for lookups
291 pvs
= lvm_vg_list_pvs(vg
);
292 if (pvs
&& !dm_list_empty(pvs
))
293 _add_device_to_pvname_hash(pvs
, argv
[2]);
296 static void _vg_open(char **argv
, int argc
, lvm_t libh
)
303 printf ("Please enter vg_name\n");
306 if ((vg
= dm_hash_lookup(_vgid_hash
, argv
[1])) ||
307 (vg
= dm_hash_lookup(_vgname_hash
, argv
[1]))) {
308 printf ("VG already open\n");
312 vg
= lvm_vg_open(libh
, argv
[1], "r", 0);
314 vg
= lvm_vg_open(libh
, argv
[1], argv
[2], 0);
315 if (!vg
|| !lvm_vg_get_name(vg
)) {
316 printf("Error opening %s\n", argv
[1]);
320 printf("Success opening vg %s\n", argv
[1]);
321 dm_hash_insert(_vgname_hash
, lvm_vg_get_name(vg
), vg
);
322 dm_hash_insert(_vgid_hash
, lvm_vg_get_uuid(vg
), vg
);
325 * Add the LVs and PVs into the hashes for lookups
327 lvs
= lvm_vg_list_lvs(vg
);
328 if (lvs
&& !dm_list_empty(lvs
))
329 _add_lvs_to_lvname_hash(lvs
);
330 pvs
= lvm_vg_list_pvs(vg
);
331 if (pvs
&& !dm_list_empty(pvs
))
332 _add_pvs_to_pvname_hash(pvs
);
334 /* Lookup the vg and remove it from the vgname and vgid hashes */
335 static vg_t
_lookup_and_remove_vg(const char *vgname
)
339 if ((vg
= dm_hash_lookup(_vgname_hash
, vgname
))) {
340 dm_hash_remove(_vgid_hash
, lvm_vg_get_uuid(vg
));
341 dm_hash_remove(_vgname_hash
, lvm_vg_get_name(vg
));
343 if (!vg
&& (vg
= dm_hash_lookup(_vgid_hash
, vgname
))) {
344 dm_hash_remove(_vgid_hash
, lvm_vg_get_uuid(vg
));
345 dm_hash_remove(_vgname_hash
, lvm_vg_get_name(vg
));
350 static void _vg_write(char **argv
, int argc
)
356 printf ("Please enter vg_name\n");
359 vg
= _lookup_vg_by_name(argv
, argc
);
361 printf("Can't find vg_name %s\n", argv
[1]);
364 rc
= lvm_vg_write(vg
);
365 _lvm_status_to_pass_fail(rc
);
366 printf("writing VG %s\n", lvm_vg_get_name(vg
));
369 static void _vg_create(char **argv
, int argc
, lvm_t libh
)
374 printf ("Please enter vg_name\n");
377 vg
= lvm_vg_create(libh
, argv
[1]);
378 if (!vg
|| !lvm_vg_get_name(vg
)) {
379 printf("Error creating %s\n", argv
[1]);
383 printf("Success creating vg %s\n", argv
[1]);
384 dm_hash_insert(_vgname_hash
, lvm_vg_get_name(vg
), vg
);
385 dm_hash_insert(_vgid_hash
, lvm_vg_get_uuid(vg
), vg
);
388 static void _vg_remove(char **argv
, int argc
)
394 printf ("Please enter vg_name\n");
397 vg
= _lookup_vg_by_name(argv
, argc
);
399 printf("Can't find vg_name %s\n", argv
[1]);
402 rc
= lvm_vg_remove(vg
);
403 _lvm_status_to_pass_fail(rc
);
404 printf("removing VG\n");
407 static void _vg_close(char **argv
, int argc
)
413 printf ("Please enter vg_name\n");
416 vg
= _lookup_and_remove_vg(argv
[1]);
418 printf("Can't find vg_name %s\n", argv
[1]);
421 rc
= lvm_vg_close(vg
);
422 _lvm_status_to_pass_fail(rc
);
423 printf("closing VG\n");
426 static void _show_one_vg(vg_t vg
)
428 printf("%s (%s): sz=%"PRIu64
", free=%"PRIu64
", #pv=%"PRIu64
429 ", seq#=%"PRIu64
"\n",
430 lvm_vg_get_name(vg
), lvm_vg_get_uuid(vg
),
431 lvm_vg_get_size(vg
), lvm_vg_get_free_size(vg
),
432 lvm_vg_get_pv_count(vg
), lvm_vg_get_seqno(vg
));
435 static void _list_open_vgs(void)
437 dm_hash_iter(_vgid_hash
, (dm_hash_iterate_fn
) _show_one_vg
);
440 static void _pvs_in_vg(char **argv
, int argc
)
443 struct lvm_pv_list
*pvl
;
446 if (!(vg
= _lookup_vg_by_name(argv
, argc
)))
448 pvs
= lvm_vg_list_pvs(vg
);
449 if (!pvs
|| dm_list_empty(pvs
)) {
450 printf("No PVs in VG %s\n", lvm_vg_get_name(vg
));
453 printf("PVs in VG %s:\n", lvm_vg_get_name(vg
));
454 dm_list_iterate_items(pvl
, pvs
) {
455 printf("%s (%s): mda_count=%"PRIu64
"\n",
456 lvm_pv_get_name(pvl
->pv
), lvm_pv_get_uuid(pvl
->pv
),
457 lvm_pv_get_mda_count(pvl
->pv
));
461 static void _scan_vgs(lvm_t libh
)
466 static void _list_vg_names(lvm_t libh
)
468 struct dm_list
*list
;
469 struct lvm_str_list
*strl
;
472 list
= lvm_list_vg_names(libh
);
473 printf("VG names:\n");
474 dm_list_iterate_items(strl
, list
) {
480 static void _list_vg_ids(lvm_t libh
)
482 struct dm_list
*list
;
483 struct lvm_str_list
*strl
;
486 list
= lvm_list_vg_uuids(libh
);
487 printf("VG uuids:\n");
488 dm_list_iterate_items(strl
, list
) {
495 static void _lvs_in_vg(char **argv
, int argc
)
498 struct lvm_lv_list
*lvl
;
501 if (!(vg
= _lookup_vg_by_name(argv
, argc
)))
503 lvs
= lvm_vg_list_lvs(vg
);
504 if (!lvs
|| dm_list_empty(lvs
)) {
505 printf("No LVs in VG %s\n", lvm_vg_get_name(vg
));
508 printf("LVs in VG %s:\n", lvm_vg_get_name(vg
));
509 dm_list_iterate_items(lvl
, lvs
) {
510 printf("%s/%s (%s): size=%"PRIu64
", %sACTIVE / %sSUSPENDED\n",
512 lvm_lv_get_name(lvl
->lv
), lvm_lv_get_uuid(lvl
->lv
),
513 lvm_lv_get_size(lvl
->lv
),
514 lvm_lv_is_active(lvl
->lv
) ? "" : "IN",
515 lvm_lv_is_suspended(lvl
->lv
) ? "" : "NOT ");
519 static void _lv_deactivate(char **argv
, int argc
)
525 printf("Please enter vgname, lvname\n");
528 if (!(lv
= _lookup_lv_by_name(argv
[2])))
530 rc
= lvm_lv_deactivate(lv
);
531 _lvm_status_to_pass_fail(rc
);
532 printf("De-activating LV %s in VG %s\n",
535 static void _lv_activate(char **argv
, int argc
)
541 printf("Please enter vgname, lvname\n");
544 if (!(lv
= _lookup_lv_by_name(argv
[2])))
546 rc
= lvm_lv_activate(lv
);
547 _lvm_status_to_pass_fail(rc
);
548 printf("activating LV %s in VG %s\n",
551 static void _vg_remove_lv(char **argv
, int argc
)
556 printf("Please enter vgname, lvname\n");
559 if (!(lv
= _lookup_lv_by_name(argv
[2])))
561 if (lvm_vg_remove_lv(lv
))
565 dm_hash_remove(_lvname_hash
, argv
[2]);
567 printf("removing LV %s in VG %s\n",
571 static void _vg_create_lv_linear(char **argv
, int argc
)
577 printf("Please enter vgname, lvname, and size\n");
580 if (!(vg
= _lookup_vg_by_name(argv
, argc
)))
582 lv
= lvm_vg_create_lv_linear(vg
, argv
[2], atol(argv
[3]));
587 dm_hash_insert(_lvname_hash
, argv
[2], lv
);
589 printf("creating LV %s in VG %s\n",
593 static int lvmapi_test_shell(lvm_t libh
)
596 char *input
= NULL
, *args
[MAX_ARGS
], **argv
;
602 input
= readline("liblvm> ");
616 if (lvm_split(input
, &argc
, argv
, MAX_ARGS
) == MAX_ARGS
) {
617 printf("Too many arguments, sorry.");
621 if (!strcmp(argv
[0], "lvm")) {
629 if (!strcmp(argv
[0], "quit") || !strcmp(argv
[0], "exit")) {
630 printf("Exiting.\n");
632 } else if (!strcmp(argv
[0], "?") || !strcmp(argv
[0], "help")) {
634 } else if (!strcmp(argv
[0], "config_reload")) {
635 _config_reload(argv
, argc
, libh
);
636 } else if (!strcmp(argv
[0], "config_override")) {
637 _config_override(argv
, argc
, libh
);
638 } else if (!strcmp(argv
[0], "vg_extend")) {
639 _vg_extend(argv
, argc
, libh
);
640 } else if (!strcmp(argv
[0], "vg_reduce")) {
641 _vg_reduce(argv
, argc
, libh
);
642 } else if (!strcmp(argv
[0], "vg_write")) {
643 _vg_write(argv
, argc
);
644 } else if (!strcmp(argv
[0], "vg_open")) {
645 _vg_open(argv
, argc
, libh
);
646 } else if (!strcmp(argv
[0], "vg_close")) {
647 _vg_close(argv
, argc
);
648 } else if (!strcmp(argv
[0], "vg_create")) {
649 _vg_create(argv
, argc
, libh
);
650 } else if (!strcmp(argv
[0], "vg_remove")) {
651 _vg_remove(argv
, argc
);
652 } else if (!strcmp(argv
[0], "lv_activate")) {
653 _lv_activate(argv
, argc
);
654 } else if (!strcmp(argv
[0], "lv_deactivate")) {
655 _lv_deactivate(argv
, argc
);
656 } else if (!strcmp(argv
[0], "vg_remove_lv")) {
657 _vg_remove_lv(argv
, argc
);
658 } else if (!strcmp(argv
[0], "vgs_open")) {
660 } else if (!strcmp(argv
[0], "vg_list_pvs")) {
661 _pvs_in_vg(argv
, argc
);
662 } else if (!strcmp(argv
[0], "vg_list_lvs")) {
663 _lvs_in_vg(argv
, argc
);
664 } else if (!strcmp(argv
[0], "list_vg_names")) {
665 _list_vg_names(libh
);
666 } else if (!strcmp(argv
[0], "list_vg_ids")) {
668 } else if (!strcmp(argv
[0], "scan_vgs")) {
670 } else if (!strcmp(argv
[0], "vg_create_lv_linear")) {
671 _vg_create_lv_linear(argv
, argc
);
673 printf ("Unrecognized command %s\n", argv
[0]);
677 dm_hash_iter(_vgname_hash
, (dm_hash_iterate_fn
) lvm_vg_close
);
683 int main (int argc
, char *argv
[])
687 libh
= lvm_init(NULL
);
689 printf("Unable to open lvm library instance\n");
693 printf("Library version: %s\n", lvm_library_get_version());
694 lvmapi_test_shell(libh
);