4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
36 static int be_do_create(int argc
, char **argv
);
37 static int be_do_destroy(int argc
, char **argv
);
38 static int be_do_list(int argc
, char **argv
);
39 static int be_do_mount(int argc
, char **argv
);
40 static int be_do_unmount(int argc
, char **argv
);
41 static int be_do_rename(int argc
, char **argv
);
42 static int be_do_activate(int argc
, char **argv
);
43 static int be_do_create_snapshot(int argc
, char **argv
);
44 static int be_do_destroy_snapshot(int argc
, char **argv
);
45 static int be_do_rollback(int argc
, char **argv
);
46 static void usage(void);
48 typedef struct be_command
{
50 int (*func
)(int argc
, char **argv
);
53 static be_command_t command_table
[] = {
54 { "create", be_do_create
},
55 { "destroy", be_do_destroy
},
56 { "list", be_do_list
},
57 { "mount", be_do_mount
},
58 { "unmount", be_do_unmount
},
59 { "rename", be_do_rename
},
60 { "activate", be_do_activate
},
61 { "create_snap", be_do_create_snapshot
},
62 { "destroy_snap", be_do_destroy_snapshot
},
65 static int fs_num
= 2;
66 static int shared_fs_num
= 2;
67 static char *fs_names
[2] = {"/", "/opt"};
68 static char *shared_fs_names
[4] = {"/export", "/export/home"};
73 (void) printf("usage:\n"
75 "\ttbeadm create [-d BE_desc] [-e nonActiveBe | -i] \n"
76 "\t\t[-o property=value] ... [-p zpool] [beName]\n"
77 "\ttbeadm destroy [-fs] beName\n"
78 "\ttbeadm create_snap [-p policy] beName [snapshot]\n"
79 "\ttbeadm destroy_snap beName snapshot\n"
80 "\ttbeadm list [-s] [beName]\n"
81 "\ttbeadm mount [-s ro|rw] beName mountpoint\n"
82 "\ttbeadm unmount [-f] beName\n"
83 "\ttbeadm rename origBeName newBeName\n"
84 "\ttbeadm activate beName\n"
85 "\ttbeadm rollback beName snapshot\n");
89 main(int argc
, char **argv
) {
96 /* Turn error printing on */
97 libbe_print_errors(B_TRUE
);
99 if (strcmp(argv
[1], "create") == 0) {
100 return (be_do_create(argc
- 1, argv
+ 1));
101 } else if (strcmp(argv
[1], "destroy") == 0) {
102 return (be_do_destroy(argc
- 1, argv
+ 1));
103 } else if (strcmp(argv
[1], "list") == 0) {
104 return (be_do_list(argc
- 1, argv
+ 1));
105 } else if (strcmp(argv
[1], "mount") == 0) {
106 return (be_do_mount(argc
- 1, argv
+ 1));
107 } else if (strcmp(argv
[1], "unmount") == 0) {
108 return (be_do_unmount(argc
- 1, argv
+ 1));
109 } else if (strcmp(argv
[1], "rename") == 0) {
110 return (be_do_rename(argc
- 2, argv
+ 2));
111 } else if (strcmp(argv
[1], "activate") == 0) {
112 return (be_do_activate(argc
- 2, argv
+ 2));
113 } else if (strcmp(argv
[1], "create_snap") == 0) {
114 return (be_do_create_snapshot(argc
- 1, argv
+ 1));
115 } else if (strcmp(argv
[1], "destroy_snap") == 0) {
116 return (be_do_destroy_snapshot(argc
- 2, argv
+ 2));
117 } else if (strcmp(argv
[1], "rollback") == 0) {
118 return (be_do_rollback(argc
- 2, argv
+ 2));
128 be_do_create(int argc
, char **argv
)
131 char *obe_name
= NULL
;
132 char *snap_name
= NULL
;
133 char *nbe_zpool
= NULL
;
134 char *nbe_name
= NULL
;
135 char *nbe_desc
= NULL
;
136 nvlist_t
*zfs_props
= NULL
;
137 char *propname
= NULL
;
138 char *propval
= NULL
;
140 boolean_t init
= B_FALSE
;
142 int ret
= BE_SUCCESS
;
144 if (nvlist_alloc(&zfs_props
, NV_UNIQUE_NAME
, 0) != 0) {
145 printf("nvlist_alloc failed.\n");
149 while ((c
= getopt(argc
, argv
, "d:e:io:p:")) != -1) {
158 /* Special option to test be_init() function */
162 if (zfs_props
== NULL
) {
163 if (nvlist_alloc(&zfs_props
, NV_UNIQUE_NAME
,
165 printf("nvlist_alloc failed.\n");
171 if ((propval
= strchr(propname
, '=')) == NULL
) {
172 (void) fprintf(stderr
, "missing "
173 "'=' for -o option\n");
178 if (nvlist_lookup_string(zfs_props
, propname
,
180 (void) fprintf(stderr
, "property '%s' "
181 "specified multiple times\n", propname
);
184 if (nvlist_add_string(zfs_props
, propname
, propval
)
186 (void) fprintf(stderr
, "internal "
187 "error: out of memory\n");
200 if (init
&& obe_name
) {
201 printf("ERROR: -e and -i are exclusive options\n");
211 } else if (argc
> 1) {
218 * Check if obe_name is really a snapshot name.
219 * If so, split it out.
223 cp
= strrchr(obe_name
, '@');
226 if (cp
[1] != NULL
&& cp
[1] != '\0') {
232 if (nvlist_alloc(&be_attrs
, NV_UNIQUE_NAME
, 0) != 0) {
233 printf("nvlist_alloc failed.\n");
238 if (nvlist_add_nvlist(be_attrs
, BE_ATTR_ZFS_PROPERTIES
,
240 printf("nvlist_add_string failed for "
241 "BE_ATTR_ZFS_PROPERTES (%s).\n", zfs_props
);
246 if (obe_name
!= NULL
) {
247 if (nvlist_add_string(be_attrs
, BE_ATTR_ORIG_BE_NAME
, obe_name
)
249 printf("nvlist_add_string failed for "
250 "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name
);
255 if (snap_name
!= NULL
) {
256 if (nvlist_add_string(be_attrs
, BE_ATTR_SNAP_NAME
, snap_name
)
258 printf("nvlist_add_string failed for "
259 "BE_ATTR_SNAP_NANE (%s).\n", snap_name
);
264 if (nbe_zpool
!= NULL
) {
265 if (nvlist_add_string(be_attrs
, BE_ATTR_NEW_BE_POOL
, nbe_zpool
)
267 printf("nvlist_add_string failed for "
268 "BE_ATTR_NEW_BE_POOL (%s).\n", nbe_zpool
);
274 if (nvlist_add_string(be_attrs
, BE_ATTR_NEW_BE_NAME
, nbe_name
)
276 printf("nvlist_add_string failed for "
277 "BE_ATTR_NEW_BE_NAME (%s).\n", nbe_name
);
283 if (nvlist_add_string(be_attrs
, BE_ATTR_NEW_BE_DESC
, nbe_desc
)
285 printf("nvlist_add_string failed for "
286 "BE_ATTR_NEW_BE_DESC (%s)\n", nbe_desc
);
293 * Add the default file system test values to test
294 * creating an initial BE.
296 if (nvlist_add_uint16(be_attrs
, BE_ATTR_FS_NUM
, fs_num
) != 0) {
297 printf("nvlist_add_uint16 failed for BE_ATTR_FS_NUM "
302 if (nvlist_add_string_array(be_attrs
, BE_ATTR_FS_NAMES
,
303 fs_names
, fs_num
) != 0) {
304 printf("nvlist_add_string_array failed for "
305 "BE_ATTR_FS_NAMES\n");
309 if (nvlist_add_uint16(be_attrs
, BE_ATTR_SHARED_FS_NUM
,
310 shared_fs_num
) != 0) {
311 printf("nvlist_add_uint16 failed for "
312 "BE_ATTR_SHARED_FS_NUM (%d).\n", shared_fs_num
);
316 if (nvlist_add_string_array(be_attrs
, BE_ATTR_SHARED_FS_NAMES
,
317 shared_fs_names
, shared_fs_num
) != 0) {
318 printf("nvlist_add_string_array failed for "
319 "BE_ATTR_SHARED_FS_NAMES\n");
323 return (be_init(be_attrs
));
326 ret
= be_copy(be_attrs
);
328 if (!nbe_name
& ret
== BE_SUCCESS
) {
330 * We requested an auto named BE; find out the
331 * name of the BE that was created for us and
332 * the auto snapshot created from the original BE.
334 if (nvlist_lookup_string(be_attrs
, BE_ATTR_NEW_BE_NAME
,
336 printf("failed to get BE_ATTR_NEW_BE_NAME attribute\n");
339 printf("Auto named BE: %s\n", nbe_name
);
342 if (nvlist_lookup_string(be_attrs
, BE_ATTR_SNAP_NAME
,
344 printf("failed to get BE_ATTR_SNAP_NAME attribute\n");
347 printf("Auto named snapshot: %s\n", snap_name
);
355 be_do_destroy(int argc
, char **argv
)
359 int destroy_flags
= 0;
362 while ((c
= getopt(argc
, argv
, "fs")) != -1) {
365 destroy_flags
|= BE_DESTROY_FLAG_FORCE_UNMOUNT
;
368 destroy_flags
|= BE_DESTROY_FLAG_SNAPSHOTS
;
384 if (nvlist_alloc(&be_attrs
, NV_UNIQUE_NAME
, 0) != 0) {
385 printf("nvlist_alloc failed.\n");
389 if (nvlist_add_string(be_attrs
, BE_ATTR_ORIG_BE_NAME
, argv
[0]) != 0) {
390 printf("nvlist_add_string failed for BE_ATTR_NEW_BE_NAME "
395 if (nvlist_add_uint16(be_attrs
, BE_ATTR_DESTROY_FLAGS
, destroy_flags
)
397 printf("nvlist_add_uint16 failed for "
398 "BE_ATTR_DESTROY_FLAGS.\n");
402 return (be_destroy(be_attrs
));
406 be_do_list(int argc
, char **argv
)
408 int err
= BE_SUCCESS
;
409 be_node_list_t
*be_nodes
;
410 be_node_list_t
*cur_be
;
411 boolean_t snaps
= B_FALSE
;
414 while ((c
= getopt(argc
, argv
, "s")) != -1) {
430 err
= be_list(argv
[0], &be_nodes
);
432 err
= be_list(NULL
, &be_nodes
);
435 if (err
== BE_SUCCESS
) {
438 "BE name\t\tActive\tActive \tDataset\t\t\tPolicy\tUUID\n");
440 " \t\t \ton boot\t \t\t\t \t \n");
442 "-------\t\t------\t-------\t-------\t\t\t------\t----\n");
444 for (cur_be
= be_nodes
; cur_be
!= NULL
;
445 cur_be
= cur_be
->be_next_node
) {
447 int name_len
= strlen(cur_be
->be_node_name
);
448 int ds_len
= strlen(cur_be
->be_root_ds
);
450 printf("%s%s%s\t%s\t%s%s%s\t%s\n",
451 cur_be
->be_node_name
,
452 name_len
< 8 ? "\t\t" : "\t",
453 cur_be
->be_active
? "yes" : "no",
454 cur_be
->be_active_on_boot
? "yes" : "no",
456 ds_len
< 8 ? "\t\t\t" :
457 (ds_len
< 16 ? "\t\t" : "\t"),
458 cur_be
->be_policy_type
,
459 cur_be
->be_uuid_str
? cur_be
->be_uuid_str
: "-");
461 be_snapshot_list_t
*snapshots
= NULL
;
462 printf("Snapshot Name\n");
463 printf("--------------\n");
464 for (snapshots
= cur_be
->be_node_snapshots
;
465 snapshots
!= NULL
; snapshots
=
466 snapshots
->be_next_snapshot
) {
468 snapshots
->be_snapshot_name
);
474 be_free_list(be_nodes
);
479 be_do_rename(int argc
, char **argv
)
485 if (argc
< 1 || argc
> 2) {
493 if (nvlist_alloc(&be_attrs
, NV_UNIQUE_NAME
, 0) != 0) {
494 printf("nvlist_alloc failed.\n");
498 if (nvlist_add_string(be_attrs
, BE_ATTR_ORIG_BE_NAME
, obe_name
)
500 printf("nvlist_add_string failed for "
501 "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name
);
505 if (nvlist_add_string(be_attrs
, BE_ATTR_NEW_BE_NAME
, nbe_name
)
507 printf("nvlist_add_string failed for "
508 "BE_ATTR_NEW_BE_NAME (%s).\n", nbe_name
);
512 return (be_rename(be_attrs
));
517 be_do_create_snapshot(int argc
, char **argv
)
520 char *obe_name
= NULL
;
521 char *snap_name
= NULL
;
524 int ret
= BE_SUCCESS
;
526 while ((c
= getopt(argc
, argv
, "p:")) != -1) {
540 if (argc
< 1 || argc
> 2) {
548 /* Snapshot name provided */
552 if (nvlist_alloc(&be_attrs
, NV_UNIQUE_NAME
, 0) != 0) {
553 printf("nvlist_alloc failed.\n");
557 if (nvlist_add_string(be_attrs
, BE_ATTR_ORIG_BE_NAME
, obe_name
)
559 printf("nvlist_add_string failed for "
560 "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name
);
565 if (nvlist_add_string(be_attrs
, BE_ATTR_POLICY
, policy
) != 0) {
566 printf("nvlist_add_string failed for "
567 "BE_ATTR_POLICY (%s).\n", policy
);
573 if (nvlist_add_string(be_attrs
, BE_ATTR_SNAP_NAME
, snap_name
)
575 printf("nvlist_add_string failed for "
576 "BE_ATTR_SNAP_NAME (%s).\n", snap_name
);
581 ret
= be_create_snapshot(be_attrs
);
583 if (!snap_name
&& ret
== BE_SUCCESS
) {
585 * We requested an auto named snapshot; find out
586 * the snapshot name that was created for us.
588 if (nvlist_lookup_string(be_attrs
, BE_ATTR_SNAP_NAME
,
590 printf("failed to get BE_ATTR_SNAP_NAME attribute\n");
593 printf("Auto named snapshot: %s\n", snap_name
);
601 be_do_destroy_snapshot(int argc
, char **argv
)
615 if (nvlist_alloc(&be_attrs
, NV_UNIQUE_NAME
, 0) != 0) {
616 printf("nvlist_alloc failed.\n");
620 if (nvlist_add_string(be_attrs
, BE_ATTR_ORIG_BE_NAME
, obe_name
)
622 printf("nvlist_add_string failed for "
623 "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name
);
627 if (nvlist_add_string(be_attrs
, BE_ATTR_SNAP_NAME
, snap_name
)
629 printf("nvlist_add_string failed for "
630 "BE_ATTR_SNAP_NAME (%s).\n", snap_name
);
634 return (be_destroy_snapshot(be_attrs
));
638 be_do_rollback(int argc
, char **argv
)
644 if (argc
< 1 || argc
> 2) {
652 if (nvlist_alloc(&be_attrs
, NV_UNIQUE_NAME
, 0) != 0) {
653 printf("nvlist_alloc failed.\n");
657 if (nvlist_add_string(be_attrs
, BE_ATTR_ORIG_BE_NAME
, obe_name
)
659 printf("nvlist_add_string failed for "
660 "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name
);
664 if (nvlist_add_string(be_attrs
, BE_ATTR_SNAP_NAME
, snap_name
)
666 printf("nvlist_add_string failed for "
667 "BE_ATTR_SNAP_NAME (%s).\n", snap_name
);
671 return (be_rollback(be_attrs
));
675 be_do_activate(int argc
, char **argv
)
680 if (argc
< 1 || argc
> 2) {
687 if (nvlist_alloc(&be_attrs
, NV_UNIQUE_NAME
, 0) != 0) {
688 printf("nvlist_alloc failed.\n");
692 if (nvlist_add_string(be_attrs
, BE_ATTR_ORIG_BE_NAME
, obe_name
)
694 printf("nvlist_add_string failed for "
695 "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name
);
699 return (be_activate(be_attrs
));
703 be_do_mount(int argc
, char **argv
)
707 boolean_t shared_fs
= B_FALSE
;
712 while ((c
= getopt(argc
, argv
, "s:")) != -1) {
717 mount_flags
|= BE_MOUNT_FLAG_SHARED_FS
;
719 if (strcmp(optarg
, "rw") == 0) {
720 mount_flags
|= BE_MOUNT_FLAG_SHARED_RW
;
721 } else if (strcmp(optarg
, "ro") != 0) {
722 printf("The -s flag requires an argument "
738 if (argc
< 1 || argc
> 2) {
746 mountpoint
= argv
[1];
749 * XXX - Need to generate a random mountpoint here;
750 * right now we're just exitting if one isn't supplied.
756 if (nvlist_alloc(&be_attrs
, NV_UNIQUE_NAME
, 0) != 0) {
757 printf("nvlist_alloc failed.\n");
761 if (nvlist_add_string(be_attrs
, BE_ATTR_ORIG_BE_NAME
, obe_name
)
763 printf("nvlist_add_string failed for "
764 "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name
);
768 if (nvlist_add_string(be_attrs
, BE_ATTR_MOUNTPOINT
, mountpoint
)
770 printf("nvlist_add_string failed for "
771 "BE_ATTR_MOUNTPOINT (%s).\n", mountpoint
);
776 if (nvlist_add_uint16(be_attrs
, BE_ATTR_MOUNT_FLAGS
,
778 printf("nvlist_add_uint16 failed for "
779 "BE_ATTR_MOUNT_FLAGS (%d).\n", mount_flags
);
784 return (be_mount(be_attrs
));
789 be_do_unmount(int argc
, char **argv
)
793 int unmount_flags
= 0;
796 while ((c
= getopt(argc
, argv
, "f")) != -1) {
799 unmount_flags
|= BE_UNMOUNT_FLAG_FORCE
;
817 if (nvlist_alloc(&be_attrs
, NV_UNIQUE_NAME
, 0) != 0) {
818 printf("nvlist_alloc failed.\n");
822 if (nvlist_add_string(be_attrs
, BE_ATTR_ORIG_BE_NAME
, obe_name
)
824 printf("nvlist_add_string failed for "
825 "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name
);
829 if (nvlist_add_uint16(be_attrs
, BE_ATTR_UNMOUNT_FLAGS
, unmount_flags
)
831 printf("nvlist_add_uint16 failed for "
832 "BE_ATTR_UNMOUNT_FLAGS\n");
836 return (be_unmount(be_attrs
));