Example #1
0
/*
 * Function:	be_is_active_on_boot
 * Description:	Checks if the BE name passed in has the "active on boot"
 *		property set to B_TRUE.
 * Paramters:
 *		be_name - the name of the BE to check
 * Returns:
 *		B_TRUE - if active on boot.
 *		B_FALSE - if not active on boot.
 * Scope:
 *		Semi-private (library wide use only)
 */
boolean_t
be_is_active_on_boot(char *be_name)
{
	be_node_list_t *be_node = NULL;

	if (be_name == NULL) {
		be_print_err(gettext("be_is_active_on_boot: "
		    "be_name must not be NULL\n"));
		return (B_FALSE);
	}

	if (_be_list(be_name, &be_node) != BE_SUCCESS) {
		return (B_FALSE);
	}

	if (be_node == NULL) {
		return (B_FALSE);
	}

	if (be_node->be_active_on_boot) {
		be_free_list(be_node);
		return (B_TRUE);
	} else {
		be_free_list(be_node);
		return (B_FALSE);
	}
}
Example #2
0
static int
be_do_list(int argc, char **argv)
{
	be_node_list_t	*be_nodes = NULL;
	boolean_t	all = B_FALSE;
	boolean_t	dsets = B_FALSE;
	boolean_t	snaps = B_FALSE;
	boolean_t	parsable = B_FALSE;
	int		err = 1;
	int		c = 0;
	char		*be_name = NULL;
	be_sort_t	order = BE_SORT_UNSPECIFIED;

	while ((c = getopt(argc, argv, "adk:svHK:")) != -1) {
		switch (c) {
		case 'a':
			all = B_TRUE;
			break;
		case 'd':
			dsets = B_TRUE;
			break;
		case 'k':
		case 'K':
			if (order != BE_SORT_UNSPECIFIED) {
				(void) fprintf(stderr, _("Sort key can be "
				    "specified only once.\n"));
				usage();
				return (1);
			}
			if (strcmp(optarg, "date") == 0) {
				if (c == 'k')
					order = BE_SORT_DATE;
				else
					order = BE_SORT_DATE_REV;
				break;
			}
			if (strcmp(optarg, "name") == 0) {
				if (c == 'k')
					order = BE_SORT_NAME;
				else
					order = BE_SORT_NAME_REV;
				break;
			}
			if (strcmp(optarg, "space") == 0) {
				if (c == 'k')
					order = BE_SORT_SPACE;
				else
					order = BE_SORT_SPACE_REV;
				break;
			}
			(void) fprintf(stderr, _("Unknown sort key: %s\n"),
			    optarg);
			usage();
			return (1);
		case 's':
			snaps = B_TRUE;
			break;
		case 'v':
			libbe_print_errors(B_TRUE);
			break;
		case 'H':
			parsable = B_TRUE;
			break;
		default:
			usage();
			return (1);
		}
	}

	if (all) {
		if (dsets) {
			(void) fprintf(stderr, _("Invalid options: -a and %s "
			    "are mutually exclusive.\n"), "-d");
			usage();
			return (1);
		}
		if (snaps) {
			(void) fprintf(stderr, _("Invalid options: -a and %s "
			    "are mutually exclusive.\n"), "-s");
			usage();
			return (1);
		}

		dsets = B_TRUE;
		snaps = B_TRUE;
	}

	argc -= optind;
	argv += optind;


	if (argc == 1)
		be_name = argv[0];

	err = be_list(be_name, &be_nodes);

	switch (err) {
	case BE_SUCCESS:
		/* the default sort is ascending date, no need to sort twice */
		if (order == BE_SORT_UNSPECIFIED)
			order = BE_SORT_DATE;

		if (order != BE_SORT_DATE) {
			err = be_sort(&be_nodes, order);
			if (err != BE_SUCCESS) {
				(void) fprintf(stderr, _("Unable to sort Boot "
				    "Environment\n"));
				(void) fprintf(stderr, "%s\n",
				    be_err_to_str(err));
				break;
			}
		}

		print_nodes(be_name, dsets, snaps, parsable, be_nodes);
		break;
	case BE_ERR_BE_NOENT:
		if (be_name == NULL)
			(void) fprintf(stderr, _("No boot environments found "
			    "on this system.\n"));
		else {
			(void) fprintf(stderr, _("%s does not exist or appear "
			    "to be a valid BE.\nPlease check that the name of "
			    "the BE provided is correct.\n"), be_name);
		}
		break;
	default:
		(void) fprintf(stderr, _("Unable to display Boot "
		    "Environment\n"));
		(void) fprintf(stderr, "%s\n", be_err_to_str(err));
	}

	if (be_nodes != NULL)
		be_free_list(be_nodes);
	return (err);
}
Example #3
0
static int
be_do_list(int argc, char **argv)
{
	be_node_list_t	*be_nodes = NULL;
	boolean_t	all = B_FALSE;
	boolean_t	dsets = B_FALSE;
	boolean_t	snaps = B_FALSE;
	boolean_t	parsable = B_FALSE;
	int		err = 1;
	int		c = 0;
	char		*be_name = NULL;

	while ((c = getopt(argc, argv, "nadsH")) != -1) {
		switch (c) {
		case 'a':
			all = B_TRUE;
			break;
		case 'd':
			dsets = B_TRUE;
			break;
		case 's':
			snaps = B_TRUE;
			break;
		case 'H':
			parsable = B_TRUE;
			break;
		default:
			usage();
			return (1);
		}
	}

	if (all) {
		if (dsets) {
			(void) fprintf(stderr, _("Invalid options: -a and %s "
			    "are mutually exclusive.\n"), "-d");
			usage();
			return (1);
		}
		if (snaps) {
			(void) fprintf(stderr, _("Invalid options: -a and %s "
			    "are mutually exclusive.\n"), "-s");
			usage();
			return (1);
		}

		dsets = B_TRUE;
		snaps = B_TRUE;
	}

	argc -= optind;
	argv += optind;


	if (argc == 1)
		be_name = argv[0];

	err = be_list(be_name, &be_nodes);

	switch (err) {
	case BE_SUCCESS:
		print_nodes(be_name, dsets, snaps, parsable, be_nodes);
		break;
	case BE_ERR_BE_NOENT:
		if (be_name == NULL)
			(void) fprintf(stderr, _("No boot environments found "
			    "on this system.\n"));
		else {
			(void) fprintf(stderr, _("%s does not exist or appear "
			    "to be a valid BE.\nPlease check that the name of "
			    "the BE provided is correct.\n"), be_name);
		}
		break;
	default:
		(void) fprintf(stderr, _("Unable to display Boot "
		    "Environment\n"));
		(void) fprintf(stderr, "%s\n", be_err_to_str(err));
	}

	if (be_nodes != NULL)
		be_free_list(be_nodes);
	return (err);
}
Example #4
0
/*
 * Function:	_be_list
 * Description:	This does the actual work described in be_list.
 * Parameters:
 *		be_name - The name of the BE to look up.
 *			  If NULL a list of all BEs will be returned.
 *		be_nodes - A reference pointer to the list of BEs. The list
 *			   structure will be allocated here and must
 *			   be freed by a call to be_free_list. If there are no
 *			   BEs found on the system this reference will be
 *			   set to NULL.
 * Return:
 *		BE_SUCCESS - Success
 *		be_errno_t - Failure
 * Scope:
 *		Semi-private (library wide use only)
 */
int
_be_list(char *be_name, be_node_list_t **be_nodes)
{
	list_callback_data_t cb = { 0 };
	be_transaction_data_t bt = { 0 };
	int ret = BE_SUCCESS;
	zpool_handle_t *zphp;
	char *rpool = NULL;
	struct be_defaults be_defaults;

	if (be_nodes == NULL)
		return (BE_ERR_INVAL);

	be_get_defaults(&be_defaults);

	if (be_find_current_be(&bt) != BE_SUCCESS) {
		/*
		 * We were unable to find a currently booted BE which
		 * probably means that we're not booted in a BE envoronment.
		 * None of the BE's will be marked as the active BE.
		 */
		(void) strcpy(cb.current_be, "-");
	} else {
		(void) strncpy(cb.current_be, bt.obe_name,
		    sizeof (cb.current_be));
		rpool = bt.obe_zpool;
	}

	/*
	 * If be_name is NULL we'll look for all BE's on the system.
	 * If not then we will only return data for the specified BE.
	 */
	if (be_name != NULL)
		cb.be_name = strdup(be_name);

	if (be_defaults.be_deflt_rpool_container && rpool != NULL) {
		if ((zphp = zpool_open(g_zfs, rpool)) == NULL) {
			be_print_err(gettext("be_list: failed to "
			    "open rpool (%s): %s\n"), rpool,
			    libzfs_error_description(g_zfs));
			free(cb.be_name);
			return (zfs_err_to_be_err(g_zfs));
		}

		ret = be_get_list_callback(zphp, &cb);
	} else {
		if ((zpool_iter(g_zfs, be_get_list_callback, &cb)) != 0) {
			if (cb.be_nodes_head != NULL) {
				be_free_list(cb.be_nodes_head);
				cb.be_nodes_head = NULL;
				cb.be_nodes = NULL;
			}
			ret = BE_ERR_BE_NOENT;
		}
	}

	if (cb.be_nodes_head == NULL) {
		if (be_name != NULL)
			be_print_err(gettext("be_list: BE (%s) does not "
			    "exist\n"), be_name);
		else
			be_print_err(gettext("be_list: No BE's found\n"));
		ret = BE_ERR_BE_NOENT;
	}

	*be_nodes = cb.be_nodes_head;

	free(cb.be_name);

	be_sort_list(be_nodes);

	return (ret);
}
Example #5
0
/*
 * Function:	_be_activate
 * Description:	This does the actual work described in be_activate.
 * Parameters:
 *		be_name - pointer to the name of BE to activate.
 *
 * Return:
 *		BE_SUCCESS - Success
 *		be_errnot_t - Failure
 * Scope:
 *		Public
 */
int
_be_activate(char *be_name)
{
	be_transaction_data_t cb = { 0 };
	zfs_handle_t	*zhp = NULL;
	char		root_ds[MAXPATHLEN];
	char		*cur_vers = NULL, *new_vers = NULL;
	be_node_list_t	*be_nodes = NULL;
	uuid_t		uu = {0};
	int		entry, ret = BE_SUCCESS;
	int		zret = 0;

	/*
	 * TODO: The BE needs to be validated to make sure that it is actually
	 * a bootable BE.
	 */

	if (be_name == NULL)
		return (BE_ERR_INVAL);

	/* Set obe_name to be_name in the cb structure */
	cb.obe_name = be_name;

	/* find which zpool the be is in */
	if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &cb)) == 0) {
		be_print_err(gettext("be_activate: failed to "
		    "find zpool for BE (%s)\n"), cb.obe_name);
		return (BE_ERR_BE_NOENT);
	} else if (zret < 0) {
		be_print_err(gettext("be_activate: "
		    "zpool_iter failed: %s\n"),
		    libzfs_error_description(g_zfs));
		ret = zfs_err_to_be_err(g_zfs);
		return (ret);
	}

	be_make_root_ds(cb.obe_zpool, cb.obe_name, root_ds, sizeof (root_ds));
	cb.obe_root_ds = strdup(root_ds);

	if (getzoneid() == GLOBAL_ZONEID) {
		if (be_has_grub() && (ret = be_get_grub_vers(&cb, &cur_vers,
		    &new_vers)) != BE_SUCCESS) {
			be_print_err(gettext("be_activate: failed to get grub "
			    "versions from capability files.\n"));
			return (ret);
		}
		if (cur_vers != NULL) {
			/*
			 * We need to check to see if the version number from
			 * the BE being activated is greater than the current
			 * one.
			 */
			if (new_vers != NULL &&
			    atof(cur_vers) < atof(new_vers)) {
				if ((ret = be_do_installgrub(&cb))
				    != BE_SUCCESS) {
					free(new_vers);
					free(cur_vers);
					return (ret);
				}
				free(new_vers);
			}
			free(cur_vers);
		} else if (new_vers != NULL) {
			if ((ret = be_do_installgrub(&cb)) != BE_SUCCESS) {
				free(new_vers);
				return (ret);
			}
			free(new_vers);
		}
		if (!be_has_menu_entry(root_ds, cb.obe_zpool, &entry)) {
			if ((ret = be_append_menu(cb.obe_name, cb.obe_zpool,
			    NULL, NULL, NULL)) != BE_SUCCESS) {
				be_print_err(gettext("be_activate: Failed to "
				    "add BE (%s) to the GRUB menu\n"),
				    cb.obe_name);
				goto done;
			}
		}
		if (be_has_grub()) {
			if ((ret = be_change_grub_default(cb.obe_name,
			    cb.obe_zpool)) != BE_SUCCESS) {
				be_print_err(gettext("be_activate: failed to "
				    "change the default entry in menu.lst\n"));
				goto done;
			}
		}
	}

	if ((ret = _be_list(cb.obe_name, &be_nodes)) != BE_SUCCESS) {
		return (ret);
	}

	if ((ret = set_canmount(be_nodes, "noauto")) != BE_SUCCESS) {
		be_print_err(gettext("be_activate: failed to set "
		    "canmount dataset property\n"));
		goto done;
	}

	if ((ret = set_bootfs(be_nodes->be_rpool, root_ds)) != BE_SUCCESS) {
		be_print_err(gettext("be_activate: failed to set "
		    "bootfs pool property for %s\n"), root_ds);
		goto done;
	}

	if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) != NULL) {
		/*
		 * We don't need to close the zfs handle at this
		 * point because The callback funtion
		 * be_promote_ds_callback() will close it for us.
		 */
		if (be_promote_ds_callback(zhp, NULL) != 0) {
			be_print_err(gettext("be_activate: "
			    "failed to activate the "
			    "datasets for %s: %s\n"),
			    root_ds,
			    libzfs_error_description(g_zfs));
			ret = BE_ERR_PROMOTE;
			goto done;
		}
	} else {
		be_print_err(gettext("be_activate:: failed to open "
		    "dataset (%s): %s\n"), root_ds,
		    libzfs_error_description(g_zfs));
		ret = zfs_err_to_be_err(g_zfs);
		goto done;
	}

	if (getzoneid() == GLOBAL_ZONEID &&
	    be_get_uuid(cb.obe_root_ds, &uu) == BE_SUCCESS &&
	    (ret = be_promote_zone_ds(cb.obe_name, cb.obe_root_ds))
	    != BE_SUCCESS) {
		be_print_err(gettext("be_activate: failed to promote "
		    "the active zonepath datasets for zones in BE %s\n"),
		    cb.obe_name);
	}

done:
	be_free_list(be_nodes);
	return (ret);
}