Tizen 2.1 base
[external/device-mapper.git] / test / api / test.c
1 /*
2  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
4  *
5  * This file is part of LVM2.
6  *
7  * This copyrighted material is made available to anyone wishing to use,
8  * modify, copy, or redistribute it subject to the terms and conditions
9  * of the GNU Lesser General Public License v.2.1.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, write to the Free Software Foundation,
13  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14  */
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <readline/readline.h>
19
20 #include "lvm2app.h"
21
22 #define MAX_ARGS 64
23
24 static int lvm_split(char *str, int *argc, char **argv, int max)
25 {
26         char *b = str, *e;
27         *argc = 0;
28
29         while (*b) {
30                 while (*b && isspace(*b))
31                         b++;
32
33                 if ((!*b) || ((*argc == 0)&&(*b == '#')))
34                         break;
35
36                 e = b;
37                 while (*e && !isspace(*e))
38                         e++;
39
40                 argv[(*argc)++] = b;
41                 if (!*e)
42                         break;
43                 *e++ = '\0';
44                 b = e;
45                 if (*argc == max)
46                         break;
47         }
48
49         return *argc;
50 }
51
52 static void _show_help(void)
53 {
54         printf("'lv_activate vgname lvname: "
55                "Activate an LV\n");
56         printf("'lv_deactivate vgname lvname: "
57                "Deactivate an LV\n");
58         printf("'vg_remove_lv vgname lvname': "
59                "Remove a LV\n");
60         printf("'vg_create_lv_linear vgname lvname size_in_bytes': "
61                "Create a linear LV\n");
62         printf("'scan_vgs': "
63                "Scan the system for LVM metadata\n");
64         printf("'list_vg_names': "
65                "List the names of the VGs that exist in the system\n");
66         printf("'list_vg_ids': "
67                "List the uuids of the VGs that exist in the system\n");
68         printf("'vg_list_pvs vgname': "
69                "List the PVs that exist in VG vgname\n");
70         printf("'pv_list_pvsegs pvname': "
71                "List the PV segments that exist in PV pvname\n");
72         printf("'vg_list_lvs vgname': "
73                "List the LVs that exist in VG vgname\n");
74         printf("'lv_list_lvsegs vgname lvname': "
75                "List the LV segments that exist in LV vgname/lvname\n");
76         printf("'vgs_open': "
77                "List the VGs that are currently open\n");
78         printf("'vgs': "
79                "List all VGs known to the system\n");
80         printf("'vg_extend vgname device: "
81                "Issue a lvm_vg_extend() API call on VG 'vgname'\n");
82         printf("'vg_reduce vgname device: "
83                "Issue a lvm_vg_reduce() API call on VG 'vgname'\n");
84         printf("'vg_open vgname ['r' | 'w']': "
85                "Issue a lvm_vg_open() API call on VG 'vgname'\n");
86         printf("'vg_close vgname': "
87                "Issue a lvm_vg_close() API call on VG 'vgname'\n");
88         printf("'vg_create vgname: "
89                "Issue a lvm_vg_create() to create VG 'vgname'\n");
90         printf("'vg_remove vgname: "
91                "Issue a lvm_vg_remove() to remove VG 'vgname'\n");
92         printf("'config_reload': "
93                "Issue a lvm_config_reload() API to reload LVM config\n");
94         printf("'config_override' device: "
95                "Issue a lvm_config_override() with accept device filter\n");
96         printf("'vg_get_tags vgname': "
97                "List the tags of a VG\n");
98         printf("'lv_get_property vgname lvname property_name': "
99                "Display the value of LV property\n");
100         printf("'vg_get_property vgname property_name': "
101                "Display the value of VG property\n");
102         printf("'pv_get_property pvname property_name': "
103                "Display the value of PV property\n");
104         printf("'vg_set_property vgname property_name': "
105                "Set the value of VG property\n");
106         printf("'lv_get_tags vgname lvname': "
107                "List the tags of a LV\n");
108         printf("'vg_{add|remove}_tag vgname tag': "
109                "Add/remove a tag from a VG\n");
110         printf("'lv_{add|remove}_tag vgname lvname tag': "
111                "Add/remove a tag from a LV\n");
112         printf("'vgname_from_devname device': "
113                "Lookup a vgname from a device name\n");
114         printf("'vgname_from_pvid pvid': "
115                "Lookup a vgname from a pvid\n");
116         printf("'lv_from_uuid vgname lvuuid': "
117                "Lookup an LV from an LV uuid\n");
118         printf("'lv_from_name vgname lvname': "
119                "Lookup an LV from an LV name\n");
120         printf("'pv_from_uuid vgname pvuuid': "
121                "Lookup an LV from an LV uuid\n");
122         printf("'pv_from_name vgname pvname': "
123                "Lookup an LV from an LV name\n");
124         printf("'quit': exit the program\n");
125 }
126
127 static struct dm_hash_table *_vgid_hash = NULL;
128 static struct dm_hash_table *_vgname_hash = NULL;
129 static struct dm_hash_table *_pvname_hash = NULL;
130 static struct dm_hash_table *_lvname_hash = NULL;
131
132 static void _hash_destroy_single(struct dm_hash_table **htable)
133 {
134         if (htable && *htable) {
135                 dm_hash_destroy(*htable);
136                 *htable = NULL;
137         }
138 }
139
140 static void _hash_destroy(void)
141 {
142         _hash_destroy_single(&_vgname_hash);
143         _hash_destroy_single(&_vgid_hash);
144         _hash_destroy_single(&_pvname_hash);
145         _hash_destroy_single(&_lvname_hash);
146 }
147
148 static int _hash_create(void)
149 {
150         if (!(_vgname_hash = dm_hash_create(128)))
151                 return 0;
152         if (!(_pvname_hash = dm_hash_create(128))) {
153                 _hash_destroy_single(&_vgname_hash);
154                 return 0;
155         }
156         if (!(_lvname_hash = dm_hash_create(128))) {
157                 _hash_destroy_single(&_vgname_hash);
158                 _hash_destroy_single(&_pvname_hash);
159                 return 0;
160         }
161         if (!(_vgid_hash = dm_hash_create(128))) {
162                 _hash_destroy_single(&_vgname_hash);
163                 _hash_destroy_single(&_pvname_hash);
164                 _hash_destroy_single(&_lvname_hash);
165                 return 0;
166         }
167         return 1;
168 }
169
170 /* FIXME: this should be per vg */
171 static lv_t _lookup_lv_by_name(const char *name)
172 {
173         lv_t lv;
174
175         if (!name) {
176                 printf ("Invalid LV name\n");
177                 return NULL;
178         }
179         if (!(lv = dm_hash_lookup(_lvname_hash, name))) {
180                 printf ("Can't find %s in LVs - run vg_create_lv first\n",
181                         name);
182                 return NULL;
183         }
184         return lv;
185 }
186
187 static vg_t _lookup_vg_by_name(char **argv, int argc)
188 {
189         vg_t vg;
190
191         if (argc < 2) {
192                 printf ("Please enter vg_name\n");
193                 return NULL;
194         }
195         if (!(vg = dm_hash_lookup(_vgid_hash, argv[1])) &&
196             !(vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
197                 printf ("Can't find %s in open VGs - run vg_open first\n",
198                         argv[1]);
199                 return NULL;
200         }
201         return vg;
202 }
203
204 static pv_t _lookup_pv_by_name(const char *name)
205 {
206         pv_t pv;
207
208         if (!(pv = dm_hash_lookup(_pvname_hash, name))) {
209                 printf ("Can't find %s in open PVs - run vg_open first\n",
210                         name);
211                 return NULL;
212         }
213         return pv;
214 }
215
216 static void _add_lvs_to_lvname_hash(struct dm_list *lvs)
217 {
218         struct lvm_lv_list *lvl;
219         dm_list_iterate_items(lvl, lvs) {
220                 /* Concatenate VG name with LV name */
221                 dm_hash_insert(_lvname_hash, lvm_lv_get_name(lvl->lv), lvl->lv);
222         }
223 }
224
225 static void _add_pvs_to_pvname_hash(struct dm_list *pvs)
226 {
227         struct lvm_pv_list *pvl;
228         dm_list_iterate_items(pvl, pvs) {
229                 dm_hash_insert(_pvname_hash, lvm_pv_get_name(pvl->pv), pvl->pv);
230         }
231 }
232
233 static void _remove_device_from_pvname_hash(struct dm_list *pvs, const char *name)
234 {
235         struct lvm_pv_list *pvl;
236         dm_list_iterate_items(pvl, pvs) {
237                 if (!strncmp(lvm_pv_get_name(pvl->pv), name, strlen(name)))
238                         dm_hash_remove(_pvname_hash, name);
239         }
240 }
241 static void _add_device_to_pvname_hash(struct dm_list *pvs, const char *name)
242 {
243         struct lvm_pv_list *pvl;
244         dm_list_iterate_items(pvl, pvs) {
245                 if (!strncmp(lvm_pv_get_name(pvl->pv), name, strlen(name)))
246                         dm_hash_insert(_pvname_hash, name, pvl->pv);
247         }
248 }
249
250 static void _vg_reduce(char **argv, int argc, lvm_t libh)
251 {
252         vg_t vg;
253         struct dm_list *pvs;
254
255         if (argc < 2) {
256                 printf ("Please enter vg_name\n");
257                 return;
258         }
259         if (!(vg = dm_hash_lookup(_vgid_hash, argv[1])) &&
260             !(vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
261                 printf ("VG not open\n");
262                 return;
263         }
264         if (lvm_vg_reduce(vg, argv[2])) {
265                 printf("Error reducing %s by %s\n", argv[1], argv[2]);
266                 return;
267         }
268
269         printf("Success reducing vg %s by %s\n", argv[1], argv[2]);
270
271         /*
272          * Add the device into the hashes for lookups
273          */
274         pvs = lvm_vg_list_pvs(vg);
275         if (pvs && !dm_list_empty(pvs))
276                 _remove_device_from_pvname_hash(pvs, argv[2]);
277 }
278
279 /* Print "Error" or "Success" depending on lvm status */
280 static int _lvm_status_to_pass_fail(int rc)
281 {
282         if (rc)
283                 printf("Error ");
284         else
285                 printf("Success ");
286         return rc;
287 }
288 static void _config_override(char **argv, int argc, lvm_t libh)
289 {
290         int rc;
291         char tmp[64];
292
293         if (argc < 2) {
294                 printf ("Please enter device\n");
295                 return;
296         }
297         snprintf(tmp, 63, "devices{filter=[\"a|%s|\", \"r|.*|\"]}", argv[1]);
298         rc = lvm_config_override(libh, tmp);
299         _lvm_status_to_pass_fail(rc);
300         printf("overriding LVM configuration\n");
301 }
302
303 static void _config_reload(char **argv, int argc, lvm_t libh)
304 {
305         int rc;
306         rc = lvm_config_reload(libh);
307         _lvm_status_to_pass_fail(rc);
308         printf("reloading LVM configuration\n");
309 }
310
311 static void _vg_extend(char **argv, int argc, lvm_t libh)
312 {
313         vg_t vg;
314         struct dm_list *pvs;
315
316         if (argc < 2) {
317                 printf ("Please enter vg_name\n");
318                 return;
319         }
320         if (!(vg = dm_hash_lookup(_vgid_hash, argv[1])) &&
321             !(vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
322                 printf ("VG not open\n");
323                 return;
324         }
325         if (lvm_vg_extend(vg, argv[2])) {
326                 printf("Error extending %s with %s\n", argv[1], argv[2]);
327                 return;
328         }
329
330         printf("Success extending vg %s with %s\n", argv[1], argv[2]);
331
332         /*
333          * Add the device into the hashes for lookups
334          */
335         pvs = lvm_vg_list_pvs(vg);
336         if (pvs && !dm_list_empty(pvs))
337                 _add_device_to_pvname_hash(pvs, argv[2]);
338 }
339
340 static void _vg_open(char **argv, int argc, lvm_t libh)
341 {
342         vg_t vg;
343         struct dm_list *lvs;
344         struct dm_list *pvs;
345
346         if (argc < 2) {
347                 printf ("Please enter vg_name\n");
348                 return;
349         }
350         if ((vg = dm_hash_lookup(_vgid_hash, argv[1])) ||
351             (vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
352                 printf ("VG already open\n");
353                 return;
354         }
355         if (argc < 3)
356                 vg = lvm_vg_open(libh, argv[1], "r", 0);
357         else
358                 vg = lvm_vg_open(libh, argv[1], argv[2], 0);
359         if (!vg || !lvm_vg_get_name(vg)) {
360                 printf("Error opening %s\n", argv[1]);
361                 return;
362         }
363
364         printf("Success opening vg %s\n", argv[1]);
365         dm_hash_insert(_vgname_hash, lvm_vg_get_name(vg), vg);
366         dm_hash_insert(_vgid_hash, lvm_vg_get_uuid(vg), vg);
367
368         /*
369          * Add the LVs and PVs into the hashes for lookups
370          */
371         lvs = lvm_vg_list_lvs(vg);
372         if (lvs && !dm_list_empty(lvs))
373                 _add_lvs_to_lvname_hash(lvs);
374         pvs = lvm_vg_list_pvs(vg);
375         if (pvs && !dm_list_empty(pvs))
376                 _add_pvs_to_pvname_hash(pvs);
377 }
378 /* Lookup the vg and remove it from the vgname and vgid hashes */
379 static vg_t _lookup_and_remove_vg(const char *vgname)
380 {
381         vg_t vg=NULL;
382
383         if ((vg = dm_hash_lookup(_vgname_hash, vgname))) {
384                 dm_hash_remove(_vgid_hash, lvm_vg_get_uuid(vg));
385                 dm_hash_remove(_vgname_hash, lvm_vg_get_name(vg));
386         }
387         if (!vg && (vg = dm_hash_lookup(_vgid_hash, vgname))) {
388                 dm_hash_remove(_vgid_hash, lvm_vg_get_uuid(vg));
389                 dm_hash_remove(_vgname_hash, lvm_vg_get_name(vg));
390         }
391         return vg;
392 }
393
394 static void _vg_write(char **argv, int argc)
395 {
396         vg_t vg;
397         int rc = 0;
398
399         if (argc < 2) {
400                 printf ("Please enter vg_name\n");
401                 return;
402         }
403         vg = _lookup_vg_by_name(argv, argc);
404         if (!vg) {
405                 printf("Can't find vg_name %s\n", argv[1]);
406                 return;
407         }
408         rc = lvm_vg_write(vg);
409         _lvm_status_to_pass_fail(rc);
410         printf("writing VG %s\n", lvm_vg_get_name(vg));
411 }
412
413 static void _vg_create(char **argv, int argc, lvm_t libh)
414 {
415         vg_t vg;
416
417         if (argc < 2) {
418                 printf ("Please enter vg_name\n");
419                 return;
420         }
421         vg = lvm_vg_create(libh, argv[1]);
422         if (!vg || !lvm_vg_get_name(vg)) {
423                 printf("Error creating %s\n", argv[1]);
424                 return;
425         }
426
427         printf("Success creating vg %s\n", argv[1]);
428         dm_hash_insert(_vgname_hash, lvm_vg_get_name(vg), vg);
429         dm_hash_insert(_vgid_hash, lvm_vg_get_uuid(vg), vg);
430 }
431
432 static void _vg_remove(char **argv, int argc)
433 {
434         vg_t vg;
435         int rc = 0;
436
437         if (argc < 2) {
438                 printf ("Please enter vg_name\n");
439                 return;
440         }
441         vg = _lookup_vg_by_name(argv, argc);
442         if (!vg) {
443                 printf("Can't find vg_name %s\n", argv[1]);
444                 return;
445         }
446         rc = lvm_vg_remove(vg);
447         _lvm_status_to_pass_fail(rc);
448         printf("removing VG\n");
449 }
450
451 static void _vg_close(char **argv, int argc)
452 {
453         vg_t vg;
454         int rc = 0;
455
456         if (argc < 2) {
457                 printf ("Please enter vg_name\n");
458                 return;
459         }
460         vg = _lookup_and_remove_vg(argv[1]);
461         if (!vg) {
462                 printf("Can't find vg_name %s\n", argv[1]);
463                 return;
464         }
465         rc = lvm_vg_close(vg);
466         _lvm_status_to_pass_fail(rc);
467         printf("closing VG\n");
468 }
469
470 static void _show_one_vg(vg_t vg)
471 {
472         printf("%s (%s): sz=%"PRIu64", free=%"PRIu64", #pv=%"PRIu64
473                 ", seq#=%"PRIu64"\n",
474                 lvm_vg_get_name(vg), lvm_vg_get_uuid(vg),
475                 lvm_vg_get_size(vg), lvm_vg_get_free_size(vg),
476                 lvm_vg_get_pv_count(vg), lvm_vg_get_seqno(vg));
477 }
478
479 static void _print_pv(pv_t pv)
480 {
481         if (!pv)
482                 return;
483         printf("%s (%s): size=%"PRIu64", free=%"PRIu64
484                ", dev_size=%"PRIu64", mda_count=%"PRIu64"\n",
485                lvm_pv_get_name(pv), lvm_pv_get_uuid(pv),
486                lvm_pv_get_size(pv), lvm_pv_get_free(pv),
487                lvm_pv_get_dev_size(pv),
488                lvm_pv_get_mda_count(pv));
489 }
490
491 static void _print_lv(vg_t vg, lv_t lv)
492 {
493         if (!lv)
494                 return;
495         printf("%s/%s (%s): size=%"PRIu64", %sACTIVE / %sSUSPENDED\n",
496                lvm_vg_get_name(vg),
497                lvm_lv_get_name(lv), lvm_lv_get_uuid(lv),
498                lvm_lv_get_size(lv),
499                lvm_lv_is_active(lv) ? "" : "IN",
500                lvm_lv_is_suspended(lv) ? "" : "NOT ");
501 }
502
503 static void _list_open_vgs(void)
504 {
505         dm_hash_iter(_vgid_hash, (dm_hash_iterate_fn) _show_one_vg);
506 }
507
508 static void _pvs_in_vg(char **argv, int argc)
509 {
510         struct dm_list *pvs;
511         struct lvm_pv_list *pvl;
512         vg_t vg;
513
514         if (!(vg = _lookup_vg_by_name(argv, argc)))
515                 return;
516         pvs = lvm_vg_list_pvs(vg);
517         if (!pvs || dm_list_empty(pvs)) {
518                 printf("No PVs in VG %s\n", lvm_vg_get_name(vg));
519                 return;
520         }
521         printf("PVs in VG %s:\n", lvm_vg_get_name(vg));
522         dm_list_iterate_items(pvl, pvs) {
523                 _print_pv(pvl->pv);
524         }
525 }
526
527 static void _print_property_value(const char *name,
528                                   struct lvm_property_value v)
529 {
530         if (!v.is_valid)
531                 printf("%s = INVALID\n", name);
532         else if (v.is_string)
533                 printf("%s = %s\n", name, v.value.string);
534         else
535                 printf("%s = %"PRIu64"\n", name, v.value.integer);
536 }
537
538 static void _pvsegs_in_pv(char **argv, int argc)
539 {
540         struct dm_list *pvsegs;
541         struct lvm_pvseg_list *pvl;
542         pv_t pv;
543
544         if (!(pv = _lookup_pv_by_name(argv[1])))
545                 return;
546         pvsegs = lvm_pv_list_pvsegs(pv);
547         if (!pvsegs || dm_list_empty(pvsegs)) {
548                 printf("No PV segments in pv %s\n", argv[1]);
549                 return;
550         }
551         printf("PV segments in pv %s:\n", argv[1]);
552         dm_list_iterate_items(pvl, pvsegs) {
553                 struct lvm_property_value v;
554                 v = lvm_pvseg_get_property(pvl->pvseg, "pvseg_start");
555                 _print_property_value("pvseg_start", v);
556                 v = lvm_pvseg_get_property(pvl->pvseg, "pvseg_size");
557                 _print_property_value("pvseg_size", v);
558         }
559 }
560
561 static void _scan_vgs(lvm_t libh)
562 {
563         lvm_scan(libh);
564 }
565
566 static void _list_vg_names(lvm_t libh)
567 {
568         struct dm_list *list;
569         struct lvm_str_list *strl;
570
571         list = lvm_list_vg_names(libh);
572         printf("VG names:\n");
573         dm_list_iterate_items(strl, list) {
574                 printf("%s\n", strl->str);
575         }
576 }
577
578 static void _list_vg_ids(lvm_t libh)
579 {
580         struct dm_list *list;
581         struct lvm_str_list *strl;
582
583         list = lvm_list_vg_uuids(libh);
584         printf("VG uuids:\n");
585         dm_list_iterate_items(strl, list) {
586                 printf("%s\n", strl->str);
587         }
588 }
589
590 static void _display_tags(struct dm_list *list)
591 {
592         struct lvm_str_list *strl;
593         if (dm_list_empty(list)) {
594                 printf("No tags exist\n");
595                 return;
596         } else if (!list) {
597                 printf("Error obtaining tags\n");
598                 return;
599         }
600         dm_list_iterate_items(strl, list) {
601                 printf("%s\n", strl->str);
602         }
603 }
604
605 static void _vg_get_tags(char **argv, int argc)
606 {
607         vg_t vg;
608
609         if (!(vg = _lookup_vg_by_name(argv, argc)))
610                 return;
611         printf("VG tags:\n");
612         _display_tags(lvm_vg_get_tags(vg));
613 }
614
615 static void _vg_tag(char **argv, int argc, int add)
616 {
617         vg_t vg;
618
619         if (argc < 3) {
620                 printf("Please enter vgname, tag\n");
621                 return;
622         }
623         if (!(vg = _lookup_vg_by_name(argv, argc)))
624                 return;
625         if (add && lvm_vg_add_tag(vg, argv[2]))
626                 printf("Error ");
627         else if (!add && lvm_vg_remove_tag(vg, argv[2])){
628                 printf("Error ");
629         } else {
630                 printf("Success ");
631         }
632         printf("%s tag %s to VG %s\n",
633                add ? "adding":"removing", argv[2], argv[1]);
634 }
635
636 static void _pv_get_property(char **argv, int argc)
637 {
638         pv_t pv;
639         struct lvm_property_value v;
640
641         if (argc < 3) {
642                 printf("Please enter pvname, field_id\n");
643                 return;
644         }
645         if (!(pv = _lookup_pv_by_name(argv[1])))
646                 return;
647         v = lvm_pv_get_property(pv, argv[2]);
648         _print_property_value(argv[2], v);
649 }
650
651 static void _vg_get_property(char **argv, int argc)
652 {
653         vg_t vg;
654         struct lvm_property_value v;
655
656         if (argc < 3) {
657                 printf("Please enter vgname, field_id\n");
658                 return;
659         }
660         if (!(vg = _lookup_vg_by_name(argv, argc)))
661                 return;
662         v =  lvm_vg_get_property(vg, argv[2]);
663         _print_property_value(argv[2], v);
664 }
665
666 static void _lv_get_property(char **argv, int argc)
667 {
668         lv_t lv;
669         struct lvm_property_value v;
670
671         if (argc < 4) {
672                 printf("Please enter vgname, lvname, field_id\n");
673                 return;
674         }
675         if (!(lv = _lookup_lv_by_name(argv[2])))
676                 return;
677         v = lvm_lv_get_property(lv, argv[3]);
678         _print_property_value(argv[3], v);
679 }
680
681 static void _vg_set_property(char **argv, int argc)
682 {
683         vg_t vg;
684         struct lvm_property_value value;
685         int rc;
686
687         if (argc < 4) {
688                 printf("Please enter vgname, field_id, value\n");
689                 return;
690         }
691         if (!(vg = _lookup_vg_by_name(argv, argc)))
692                 return;
693         value = lvm_vg_get_property(vg, argv[2]);
694         if (!value.is_valid) {
695                 printf("Error obtaining property value\n");
696                 return;
697         }
698         if (value.is_string)
699                 value.value.string = argv[3];
700         else
701                 value.value.integer = atoi(argv[3]);
702         rc = lvm_vg_set_property(vg, argv[2], &value);
703         if (rc)
704                 printf("Error ");
705         else
706                 printf("Success ");
707         printf("setting value of property %s in VG %s\n",
708                argv[2], argv[1]);
709 }
710
711 static void _lv_get_tags(char **argv, int argc)
712 {
713         lv_t lv;
714
715         if (argc < 3) {
716                 printf("Please enter vgname, lvname\n");
717                 return;
718         }
719         if (!(lv = _lookup_lv_by_name(argv[2])))
720                 return;
721         printf("LV tags:\n");
722         _display_tags(lvm_lv_get_tags(lv));
723 }
724
725 static void _lv_tag(char **argv, int argc, int add)
726 {
727         lv_t lv;
728
729         if (argc < 3) {
730                 printf("Please enter vgname, lvname\n");
731                 return;
732         }
733         if (!(lv = _lookup_lv_by_name(argv[2])))
734                 return;
735         if (add && lvm_lv_add_tag(lv, argv[3]))
736                 printf("Error ");
737         else if (!add && lvm_lv_remove_tag(lv, argv[3])){
738                 printf("Error ");
739         } else {
740                 printf("Success ");
741         }
742         printf("%s tag %s to LV %s\n",
743                add ? "adding":"removing", argv[3], argv[2]);
744 }
745
746 static void _lv_from_uuid(char **argv, int argc)
747 {
748         vg_t vg;
749
750         if (argc < 3) {
751                 printf("Please enter vgname, lv_uuid\n");
752                 return;
753         }
754         if (!(vg = _lookup_vg_by_name(argv, argc)))
755                 return;
756         _print_lv(vg, lvm_lv_from_uuid(vg, argv[2]));
757 }
758
759 static void _lv_from_name(char **argv, int argc)
760 {
761         vg_t vg;
762
763         if (argc < 3) {
764                 printf("Please enter vgname, lv_uuid\n");
765                 return;
766         }
767         if (!(vg = _lookup_vg_by_name(argv, argc)))
768                 return;
769         _print_lv(vg, lvm_lv_from_name(vg, argv[2]));
770 }
771
772 static void _pv_from_uuid(char **argv, int argc)
773 {
774         vg_t vg;
775
776         if (argc < 3) {
777                 printf("Please enter vgname, pv_uuid\n");
778                 return;
779         }
780         if (!(vg = _lookup_vg_by_name(argv, argc)))
781                 return;
782         _print_pv(lvm_pv_from_uuid(vg, argv[2]));
783 }
784
785 static void _pv_from_name(char **argv, int argc)
786 {
787         vg_t vg;
788
789         if (argc < 3) {
790                 printf("Please enter vgname, pv_uuid\n");
791                 return;
792         }
793         if (!(vg = _lookup_vg_by_name(argv, argc)))
794                 return;
795         _print_pv(lvm_pv_from_name(vg, argv[2]));
796 }
797
798 static void _vgname_from_pvid(char **argv, int argc, lvm_t libh)
799 {
800         const char *vgname;
801
802         if (argc < 1) {
803                 printf("Please enter pvid\n");
804                 return;
805         }
806         if (!(vgname = lvm_vgname_from_pvid(libh, argv[1]))) {
807                 printf("Error ");
808         } else {
809                 printf("Success ");
810         }
811         printf("looking up vgname=%s from PVID=%s\n",
812                vgname, argv[1]);
813 }
814 static void _vgname_from_devname(char **argv, int argc, lvm_t libh)
815 {
816         const char *vgname;
817
818         if (argc < 1) {
819                 printf("Please enter device\n");
820                 return;
821         }
822         if (!(vgname = lvm_vgname_from_device(libh, argv[1]))) {
823                 printf("Error ");
824         } else {
825                 printf("Success ");
826         }
827         printf("looking up vgname=%s from device name=%s\n",
828                vgname, argv[1]);
829 }
830 static void _lvs_in_vg(char **argv, int argc)
831 {
832         struct dm_list *lvs;
833         struct lvm_lv_list *lvl;
834         vg_t vg;
835
836         if (!(vg = _lookup_vg_by_name(argv, argc)))
837                 return;
838         lvs = lvm_vg_list_lvs(vg);
839         if (!lvs || dm_list_empty(lvs)) {
840                 printf("No LVs in VG %s\n", lvm_vg_get_name(vg));
841                 return;
842         }
843         printf("LVs in VG %s:\n", lvm_vg_get_name(vg));
844         dm_list_iterate_items(lvl, lvs) {
845                 _print_lv(vg, lvl->lv);
846         }
847 }
848
849 static void _lvsegs_in_lv(char **argv, int argc)
850 {
851         struct dm_list *lvsegs;
852         struct lvm_lvseg_list *lvl;
853         lv_t lv;
854
855         if (!(lv = _lookup_lv_by_name(argv[2])))
856                 return;
857         lvsegs = lvm_lv_list_lvsegs(lv);
858         if (!lvsegs || dm_list_empty(lvsegs)) {
859                 printf("No LV segments in lv %s\n", lvm_lv_get_name(lv));
860                 return;
861         }
862         printf("LV segments in lv %s:\n", lvm_lv_get_name(lv));
863         dm_list_iterate_items(lvl, lvsegs) {
864                 struct lvm_property_value v;
865                 v = lvm_lvseg_get_property(lvl->lvseg, "segtype");
866                 _print_property_value("segtype", v);
867                 v = lvm_lvseg_get_property(lvl->lvseg, "seg_start_pe");
868                 _print_property_value("seg_start_pe", v);
869                 v = lvm_lvseg_get_property(lvl->lvseg, "seg_size");
870                 _print_property_value("seg_size", v);
871         }
872 }
873
874 static void _lv_deactivate(char **argv, int argc)
875 {
876         lv_t lv;
877         int rc=0;
878
879         if (argc < 3) {
880                 printf("Please enter vgname, lvname\n");
881                 return;
882         }
883         if (!(lv = _lookup_lv_by_name(argv[2])))
884                 return;
885         rc = lvm_lv_deactivate(lv);
886         _lvm_status_to_pass_fail(rc);
887         printf("De-activating LV %s in VG %s\n",
888                 argv[2], argv[1]);
889 }
890 static void _lv_activate(char **argv, int argc)
891 {
892         lv_t lv;
893         int rc=0;
894
895         if (argc < 3) {
896                 printf("Please enter vgname, lvname\n");
897                 return;
898         }
899         if (!(lv = _lookup_lv_by_name(argv[2])))
900                 return;
901         rc = lvm_lv_activate(lv);
902         _lvm_status_to_pass_fail(rc);
903         printf("activating LV %s in VG %s\n",
904                 argv[2], argv[1]);
905 }
906
907 static void _vg_remove_lv(char **argv, int argc)
908 {
909         lv_t lv;
910
911         if (argc < 3) {
912                 printf("Please enter vgname, lvname\n");
913                 return;
914         }
915         if (!(lv = _lookup_lv_by_name(argv[2])))
916                 return;
917         if (lvm_vg_remove_lv(lv))
918                 printf("Error ");
919         else {
920                 printf("Success ");
921                 dm_hash_remove(_lvname_hash, argv[2]);
922         }
923         printf("removing LV %s in VG %s\n",
924                 argv[2], argv[1]);
925 }
926
927 static void _vg_create_lv_linear(char **argv, int argc)
928 {
929         vg_t vg;
930         lv_t lv;
931
932         if (argc < 4) {
933                 printf("Please enter vgname, lvname, and size\n");
934                 return;
935         }
936         if (!(vg = _lookup_vg_by_name(argv, argc)))
937                 return;
938         lv = lvm_vg_create_lv_linear(vg, argv[2], atol(argv[3]));
939         if (!lv)
940                 printf("Error ");
941         else {
942                 printf("Success ");
943                 dm_hash_insert(_lvname_hash, argv[2], lv);
944         }
945         printf("creating LV %s in VG %s\n",
946                 argv[2], argv[1]);
947 }
948
949 static int lvmapi_test_shell(lvm_t libh)
950 {
951         int argc;
952         char *input = NULL, *args[MAX_ARGS], **argv;
953
954         _hash_create();
955         argc=0;
956         while (1) {
957                 free(input);
958                 input = readline("liblvm> ");
959
960                 /* EOF */
961                 if (!input) {
962                         printf("\n");
963                         break;
964                 }
965
966                 /* empty line */
967                 if (!*input)
968                         continue;
969
970                 argv = args;
971
972                 if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
973                         printf("Too many arguments, sorry.");
974                         continue;
975                 }
976
977                 if (!strcmp(argv[0], "lvm")) {
978                         argv++;
979                         argc--;
980                 }
981
982                 if (!argc)
983                         continue;
984
985                 if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
986                         printf("Exiting.\n");
987                         break;
988                 } else if (!strcmp(argv[0], "?") || !strcmp(argv[0], "help")) {
989                         _show_help();
990                 } else if (!strcmp(argv[0], "config_reload")) {
991                         _config_reload(argv, argc, libh);
992                 } else if (!strcmp(argv[0], "config_override")) {
993                         _config_override(argv, argc, libh);
994                 } else if (!strcmp(argv[0], "vg_extend")) {
995                         _vg_extend(argv, argc, libh);
996                 } else if (!strcmp(argv[0], "vg_reduce")) {
997                         _vg_reduce(argv, argc, libh);
998                 } else if (!strcmp(argv[0], "vg_write")) {
999                         _vg_write(argv, argc);
1000                 } else if (!strcmp(argv[0], "vg_open")) {
1001                         _vg_open(argv, argc, libh);
1002                 } else if (!strcmp(argv[0], "vg_close")) {
1003                         _vg_close(argv, argc);
1004                 } else if (!strcmp(argv[0], "vg_create")) {
1005                         _vg_create(argv, argc, libh);
1006                 } else if (!strcmp(argv[0], "vg_remove")) {
1007                         _vg_remove(argv, argc);
1008                 } else if (!strcmp(argv[0], "lv_activate")) {
1009                         _lv_activate(argv, argc);
1010                 } else if (!strcmp(argv[0], "lv_deactivate")) {
1011                         _lv_deactivate(argv, argc);
1012                 } else if (!strcmp(argv[0], "vg_remove_lv")) {
1013                         _vg_remove_lv(argv, argc);
1014                 } else if (!strcmp(argv[0], "vgs_open")) {
1015                         _list_open_vgs();
1016                 } else if (!strcmp(argv[0], "vg_list_pvs")) {
1017                         _pvs_in_vg(argv, argc);
1018                 } else if (!strcmp(argv[0], "pv_list_pvsegs")) {
1019                         _pvsegs_in_pv(argv, argc);
1020                 } else if (!strcmp(argv[0], "vg_list_lvs")) {
1021                         _lvs_in_vg(argv, argc);
1022                 } else if (!strcmp(argv[0], "lv_list_lvsegs")) {
1023                         _lvsegs_in_lv(argv, argc);
1024                 } else if (!strcmp(argv[0], "list_vg_names")) {
1025                         _list_vg_names(libh);
1026                 } else if (!strcmp(argv[0], "list_vg_ids")) {
1027                         _list_vg_ids(libh);
1028                 } else if (!strcmp(argv[0], "scan_vgs")) {
1029                         _scan_vgs(libh);
1030                 } else if (!strcmp(argv[0], "vg_create_lv_linear")) {
1031                         _vg_create_lv_linear(argv, argc);
1032                 } else if (!strcmp(argv[0], "vg_add_tag")) {
1033                         _vg_tag(argv, argc, 1);
1034                 } else if (!strcmp(argv[0], "vg_remove_tag")) {
1035                         _vg_tag(argv, argc, 0);
1036                 } else if (!strcmp(argv[0], "vg_get_tags")) {
1037                         _vg_get_tags(argv, argc);
1038                 } else if (!strcmp(argv[0], "lv_get_property")) {
1039                         _lv_get_property(argv, argc);
1040                 } else if (!strcmp(argv[0], "vg_get_property")) {
1041                         _vg_get_property(argv, argc);
1042                 } else if (!strcmp(argv[0], "pv_get_property")) {
1043                         _pv_get_property(argv, argc);
1044                 } else if (!strcmp(argv[0], "vg_set_property")) {
1045                         _vg_set_property(argv, argc);
1046                 } else if (!strcmp(argv[0], "lv_add_tag")) {
1047                         _lv_tag(argv, argc, 1);
1048                 } else if (!strcmp(argv[0], "lv_remove_tag")) {
1049                         _lv_tag(argv, argc, 0);
1050                 } else if (!strcmp(argv[0], "lv_get_tags")) {
1051                         _lv_get_tags(argv, argc);
1052                 } else if (!strcmp(argv[0], "vgname_from_devname")) {
1053                         _vgname_from_devname(argv, argc, libh);
1054                 } else if (!strcmp(argv[0], "vgname_from_pvid")) {
1055                         _vgname_from_pvid(argv, argc, libh);
1056                 } else if (!strcmp(argv[0], "lv_from_uuid")) {
1057                         _lv_from_uuid(argv, argc);
1058                 } else if (!strcmp(argv[0], "lv_from_name")) {
1059                         _lv_from_name(argv, argc);
1060                 } else if (!strcmp(argv[0], "pv_from_uuid")) {
1061                         _pv_from_uuid(argv, argc);
1062                 } else if (!strcmp(argv[0], "pv_from_name")) {
1063                         _pv_from_name(argv, argc);
1064                 } else {
1065                         printf ("Unrecognized command %s\n", argv[0]);
1066                 }
1067         }
1068
1069         dm_hash_iter(_vgname_hash, (dm_hash_iterate_fn) lvm_vg_close);
1070         _hash_destroy();
1071         free(input);
1072         return 0;
1073 }
1074
1075 int main (int argc, char *argv[])
1076 {
1077         lvm_t libh;
1078
1079         libh = lvm_init(NULL);
1080         if (!libh) {
1081                 printf("Unable to open lvm library instance\n");
1082                 return 1;
1083         }
1084
1085         printf("Library version: %s\n", lvm_library_get_version());
1086         lvmapi_test_shell(libh);
1087
1088         lvm_quit(libh);
1089         return 0;
1090 }
1091