xref: /illumos-gate/usr/src/lib/libbe/common/be_zones.c (revision ec8422d0)
1f169c0eaSGlenn Lagasse /*
2f169c0eaSGlenn Lagasse  * CDDL HEADER START
3f169c0eaSGlenn Lagasse  *
4f169c0eaSGlenn Lagasse  * The contents of this file are subject to the terms of the
5f169c0eaSGlenn Lagasse  * Common Development and Distribution License (the "License").
6f169c0eaSGlenn Lagasse  * You may not use this file except in compliance with the License.
7f169c0eaSGlenn Lagasse  *
8f169c0eaSGlenn Lagasse  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9f169c0eaSGlenn Lagasse  * or http://www.opensolaris.org/os/licensing.
10f169c0eaSGlenn Lagasse  * See the License for the specific language governing permissions
11f169c0eaSGlenn Lagasse  * and limitations under the License.
12f169c0eaSGlenn Lagasse  *
13f169c0eaSGlenn Lagasse  * When distributing Covered Code, include this CDDL HEADER in each
14f169c0eaSGlenn Lagasse  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15f169c0eaSGlenn Lagasse  * If applicable, add the following below this CDDL HEADER, with the
16f169c0eaSGlenn Lagasse  * fields enclosed by brackets "[]" replaced with your own identifying
17f169c0eaSGlenn Lagasse  * information: Portions Copyright [yyyy] [name of copyright owner]
18f169c0eaSGlenn Lagasse  *
19f169c0eaSGlenn Lagasse  * CDDL HEADER END
20f169c0eaSGlenn Lagasse  */
21f169c0eaSGlenn Lagasse 
22f169c0eaSGlenn Lagasse /*
23f169c0eaSGlenn Lagasse  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24f169c0eaSGlenn Lagasse  */
25f169c0eaSGlenn Lagasse 
267e0e2549SAlexander Eremin /*
277e0e2549SAlexander Eremin  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
28*ec8422d0SAndy Fiddaman  * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
297e0e2549SAlexander Eremin  */
307e0e2549SAlexander Eremin 
31f169c0eaSGlenn Lagasse /*
32f169c0eaSGlenn Lagasse  * System includes
33f169c0eaSGlenn Lagasse  */
34f169c0eaSGlenn Lagasse #include <assert.h>
35f169c0eaSGlenn Lagasse #include <errno.h>
36f169c0eaSGlenn Lagasse #include <libintl.h>
37f169c0eaSGlenn Lagasse #include <libnvpair.h>
38f169c0eaSGlenn Lagasse #include <libzfs.h>
39f169c0eaSGlenn Lagasse #include <stdio.h>
40f169c0eaSGlenn Lagasse #include <stdlib.h>
41f169c0eaSGlenn Lagasse #include <string.h>
42f169c0eaSGlenn Lagasse #include <sys/mntent.h>
43f169c0eaSGlenn Lagasse #include <sys/mnttab.h>
44f169c0eaSGlenn Lagasse #include <sys/mount.h>
45f169c0eaSGlenn Lagasse #include <sys/stat.h>
46f169c0eaSGlenn Lagasse #include <sys/types.h>
47f169c0eaSGlenn Lagasse #include <sys/vfstab.h>
48f169c0eaSGlenn Lagasse #include <unistd.h>
49f169c0eaSGlenn Lagasse 
50f169c0eaSGlenn Lagasse #include <libbe.h>
51f169c0eaSGlenn Lagasse #include <libbe_priv.h>
52f169c0eaSGlenn Lagasse 
53f169c0eaSGlenn Lagasse typedef struct active_zone_root_data {
54f169c0eaSGlenn Lagasse 	uuid_t	parent_uuid;
55f169c0eaSGlenn Lagasse 	char	*zoneroot_ds;
56f169c0eaSGlenn Lagasse } active_zone_root_data_t;
57f169c0eaSGlenn Lagasse 
58f169c0eaSGlenn Lagasse typedef struct mounted_zone_root_data {
59f169c0eaSGlenn Lagasse 	char	*zone_altroot;
60f169c0eaSGlenn Lagasse 	char	*zoneroot_ds;
61f169c0eaSGlenn Lagasse } mounted_zone_root_data_t;
62f169c0eaSGlenn Lagasse 
63f169c0eaSGlenn Lagasse /* Private function prototypes */
64f169c0eaSGlenn Lagasse static int be_find_active_zone_root_callback(zfs_handle_t *, void *);
65f169c0eaSGlenn Lagasse static int be_find_mounted_zone_root_callback(zfs_handle_t *, void *);
66f169c0eaSGlenn Lagasse static boolean_t be_zone_get_active(zfs_handle_t *);
67f169c0eaSGlenn Lagasse 
68f169c0eaSGlenn Lagasse 
69f169c0eaSGlenn Lagasse /* ******************************************************************** */
70f169c0eaSGlenn Lagasse /*			Semi-Private Functions				*/
71f169c0eaSGlenn Lagasse /* ******************************************************************** */
72f169c0eaSGlenn Lagasse 
73f169c0eaSGlenn Lagasse /*
74f169c0eaSGlenn Lagasse  * Function:	be_make_zoneroot
75f169c0eaSGlenn Lagasse  * Description:	Generate a string for a zone's zoneroot given the
76f169c0eaSGlenn Lagasse  *		zone's zonepath.
77f169c0eaSGlenn Lagasse  * Parameters:
78f169c0eaSGlenn Lagasse  *		zonepath - pointer to zonepath
79f169c0eaSGlenn Lagasse  *		zoneroot - pointer to buffer to retrn zoneroot in.
80f169c0eaSGlenn Lagasse  *		zoneroot_size - size of zoneroot
81f169c0eaSGlenn Lagasse  * Returns:
82f169c0eaSGlenn Lagasse  *		None
83f169c0eaSGlenn Lagasse  * Scope:
84f169c0eaSGlenn Lagasse  *		Semi-private (library wise use only)
85f169c0eaSGlenn Lagasse  */
86f169c0eaSGlenn Lagasse void
be_make_zoneroot(char * zonepath,char * zoneroot,int zoneroot_size)87f169c0eaSGlenn Lagasse be_make_zoneroot(char *zonepath, char *zoneroot, int zoneroot_size)
88f169c0eaSGlenn Lagasse {
89f169c0eaSGlenn Lagasse 	(void) snprintf(zoneroot, zoneroot_size, "%s/root", zonepath);
90f169c0eaSGlenn Lagasse }
91f169c0eaSGlenn Lagasse 
92f169c0eaSGlenn Lagasse /*
93f169c0eaSGlenn Lagasse  * Function:	be_find_active_zone_root
94f169c0eaSGlenn Lagasse  * Description:	This function will find the active zone root of a zone for
95f169c0eaSGlenn Lagasse  *		a given global BE.  It will iterate all of the zone roots
96f169c0eaSGlenn Lagasse  *		under a zonepath, find the zone roots that belong to the
97f169c0eaSGlenn Lagasse  *		specified global BE, and return the one that is active.
98f169c0eaSGlenn Lagasse  * Parameters:
99f169c0eaSGlenn Lagasse  *		be_zhp - zfs handle to global BE root dataset.
100f169c0eaSGlenn Lagasse  *		zonepath_ds - pointer to zone's zonepath dataset.
101f169c0eaSGlenn Lagasse  *		zoneroot_ds - pointer to a buffer to store the dataset name of
102f169c0eaSGlenn Lagasse  *			the zone's zoneroot that's currently active for this
103f169c0eaSGlenn Lagasse  *			given global BE..
104f169c0eaSGlenn Lagasse  *		zoneroot-ds_size - size of zoneroot_ds.
105f169c0eaSGlenn Lagasse  * Returns:
106f169c0eaSGlenn Lagasse  *		BE_SUCCESS - Success
107f169c0eaSGlenn Lagasse  *		be_errno_t - Failure
108f169c0eaSGlenn Lagasse  * Scope:
109f169c0eaSGlenn Lagasse  *		Semi-private (library wide use only)
110f169c0eaSGlenn Lagasse  */
111f169c0eaSGlenn Lagasse int
be_find_active_zone_root(zfs_handle_t * be_zhp,char * zonepath_ds,char * zoneroot_ds,int zoneroot_ds_size)112f169c0eaSGlenn Lagasse be_find_active_zone_root(zfs_handle_t *be_zhp, char *zonepath_ds,
113f169c0eaSGlenn Lagasse     char *zoneroot_ds, int zoneroot_ds_size)
114f169c0eaSGlenn Lagasse {
115fafb665dSToomas Soome 	active_zone_root_data_t		azr_data = { { 0 }, NULL };
116f169c0eaSGlenn Lagasse 	zfs_handle_t			*zhp;
117f169c0eaSGlenn Lagasse 	char				zone_container_ds[MAXPATHLEN];
118f169c0eaSGlenn Lagasse 	int				ret = BE_SUCCESS;
119f169c0eaSGlenn Lagasse 
120f169c0eaSGlenn Lagasse 	/* Get the uuid of the parent global BE */
1217e0e2549SAlexander Eremin 	if (getzoneid() == GLOBAL_ZONEID) {
1227e0e2549SAlexander Eremin 		if ((ret = be_get_uuid(zfs_get_name(be_zhp),
1237e0e2549SAlexander Eremin 		    &azr_data.parent_uuid)) != BE_SUCCESS) {
1247e0e2549SAlexander Eremin 			be_print_err(gettext("be_find_active_zone_root: failed "
1257e0e2549SAlexander Eremin 			    "to get uuid for BE root dataset %s\n"),
1267e0e2549SAlexander Eremin 			    zfs_get_name(be_zhp));
1277e0e2549SAlexander Eremin 			return (ret);
1287e0e2549SAlexander Eremin 		}
1297e0e2549SAlexander Eremin 	} else {
1307e0e2549SAlexander Eremin 		if ((ret = be_zone_get_parent_uuid(zfs_get_name(be_zhp),
1317e0e2549SAlexander Eremin 		    &azr_data.parent_uuid)) != BE_SUCCESS) {
1327e0e2549SAlexander Eremin 			be_print_err(gettext("be_find_active_zone_root: failed "
1337e0e2549SAlexander Eremin 			    "to get parentbe uuid for zone root dataset %s\n"),
1347e0e2549SAlexander Eremin 			    zfs_get_name(be_zhp));
1357e0e2549SAlexander Eremin 			return (ret);
1367e0e2549SAlexander Eremin 		}
137f169c0eaSGlenn Lagasse 	}
138f169c0eaSGlenn Lagasse 
139*ec8422d0SAndy Fiddaman 	/* Generate string for the root container dataset for this zone. */
140*ec8422d0SAndy Fiddaman 	if ((ret = be_make_container_ds(zonepath_ds, zone_container_ds,
141*ec8422d0SAndy Fiddaman 	    sizeof (zone_container_ds))) != BE_SUCCESS) {
142*ec8422d0SAndy Fiddaman 		be_print_err(gettext("%s: failed to get BE container dataset "
143*ec8422d0SAndy Fiddaman 		    "for %s\n"), __func__, zonepath_ds);
144*ec8422d0SAndy Fiddaman 		return (ret);
145*ec8422d0SAndy Fiddaman 	}
146f169c0eaSGlenn Lagasse 
147f169c0eaSGlenn Lagasse 	/* Get handle to this zone's root container dataset */
148f169c0eaSGlenn Lagasse 	if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM))
149f169c0eaSGlenn Lagasse 	    == NULL) {
150f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_find_active_zone_root: failed to "
151f169c0eaSGlenn Lagasse 		    "open zone root container dataset (%s): %s\n"),
152f169c0eaSGlenn Lagasse 		    zone_container_ds, libzfs_error_description(g_zfs));
153f169c0eaSGlenn Lagasse 		return (zfs_err_to_be_err(g_zfs));
154f169c0eaSGlenn Lagasse 	}
155f169c0eaSGlenn Lagasse 
156f169c0eaSGlenn Lagasse 	/*
157f169c0eaSGlenn Lagasse 	 * Iterate through all of this zone's BEs, looking for ones
158f169c0eaSGlenn Lagasse 	 * that belong to the parent global BE, and finding the one
159f169c0eaSGlenn Lagasse 	 * that is marked active.
160f169c0eaSGlenn Lagasse 	 */
161f169c0eaSGlenn Lagasse 	if ((ret = zfs_iter_filesystems(zhp, be_find_active_zone_root_callback,
162f169c0eaSGlenn Lagasse 	    &azr_data)) != 0) {
163f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_find_active_zone_root: failed to "
164f169c0eaSGlenn Lagasse 		    "find active zone root in zonepath dataset %s: %s\n"),
165f169c0eaSGlenn Lagasse 		    zonepath_ds, be_err_to_str(ret));
166f169c0eaSGlenn Lagasse 		goto done;
167f169c0eaSGlenn Lagasse 	}
168f169c0eaSGlenn Lagasse 
169f169c0eaSGlenn Lagasse 	if (azr_data.zoneroot_ds != NULL) {
170f169c0eaSGlenn Lagasse 		(void) strlcpy(zoneroot_ds, azr_data.zoneroot_ds,
171f169c0eaSGlenn Lagasse 		    zoneroot_ds_size);
172f169c0eaSGlenn Lagasse 		free(azr_data.zoneroot_ds);
173f169c0eaSGlenn Lagasse 	} else {
174f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_find_active_zone_root: failed to "
175f169c0eaSGlenn Lagasse 		    "find active zone root in zonepath dataset %s\n"),
176f169c0eaSGlenn Lagasse 		    zonepath_ds);
177f169c0eaSGlenn Lagasse 		ret = BE_ERR_ZONE_NO_ACTIVE_ROOT;
178f169c0eaSGlenn Lagasse 	}
179f169c0eaSGlenn Lagasse 
180f169c0eaSGlenn Lagasse done:
181f169c0eaSGlenn Lagasse 	ZFS_CLOSE(zhp);
182f169c0eaSGlenn Lagasse 	return (ret);
183f169c0eaSGlenn Lagasse }
184f169c0eaSGlenn Lagasse 
185f169c0eaSGlenn Lagasse /*
186f169c0eaSGlenn Lagasse  * Function:	be_find_mounted_zone_root
187f169c0eaSGlenn Lagasse  * Description:	This function will find the dataset mounted as the zoneroot
188f169c0eaSGlenn Lagasse  *		of a zone for a given mounted global BE.
189f169c0eaSGlenn Lagasse  * Parameters:
190f169c0eaSGlenn Lagasse  *		zone_altroot - path of zoneroot wrt the mounted global BE.
191f169c0eaSGlenn Lagasse  *		zonepath_ds - dataset of the zone's zonepath.
192f169c0eaSGlenn Lagasse  *		zoneroot_ds - pointer to a buffer to store the dataset of
193f169c0eaSGlenn Lagasse  *			the zoneroot that currently mounted for this zone
194f169c0eaSGlenn Lagasse  *			in the mounted global BE.
195f169c0eaSGlenn Lagasse  *		zoneroot_ds_size - size of zoneroot_ds
196f169c0eaSGlenn Lagasse  * Returns:
197f169c0eaSGlenn Lagasse  *		BE_SUCCESS - Success
198f169c0eaSGlenn Lagasse  *		be_errno_t - Failure
199f169c0eaSGlenn Lagasse  * Scope:
200f169c0eaSGlenn Lagasse  *		Semi-private (library wide use only)
201f169c0eaSGlenn Lagasse  */
202f169c0eaSGlenn Lagasse int
be_find_mounted_zone_root(char * zone_altroot,char * zonepath_ds,char * zoneroot_ds,int zoneroot_ds_size)203f169c0eaSGlenn Lagasse be_find_mounted_zone_root(char *zone_altroot, char *zonepath_ds,
204f169c0eaSGlenn Lagasse     char *zoneroot_ds, int zoneroot_ds_size)
205f169c0eaSGlenn Lagasse {
206f169c0eaSGlenn Lagasse 	mounted_zone_root_data_t	mzr_data = { 0 };
207f169c0eaSGlenn Lagasse 	zfs_handle_t	*zhp = NULL;
208f169c0eaSGlenn Lagasse 	char		zone_container_ds[MAXPATHLEN];
209f169c0eaSGlenn Lagasse 	int		ret = BE_SUCCESS;
210f169c0eaSGlenn Lagasse 	int		zret = 0;
211f169c0eaSGlenn Lagasse 
212f169c0eaSGlenn Lagasse 	/* Generate string for the root container dataset for this zone. */
213*ec8422d0SAndy Fiddaman 	if ((ret = be_make_container_ds(zonepath_ds, zone_container_ds,
214*ec8422d0SAndy Fiddaman 	    sizeof (zone_container_ds))) != BE_SUCCESS) {
215*ec8422d0SAndy Fiddaman 		be_print_err(gettext("%s: failed to get BE container dataset "
216*ec8422d0SAndy Fiddaman 		    "for %s\n"), __func__, zonepath_ds);
217*ec8422d0SAndy Fiddaman 		return (ret);
218*ec8422d0SAndy Fiddaman 	}
219f169c0eaSGlenn Lagasse 
220f169c0eaSGlenn Lagasse 	/* Get handle to this zone's root container dataset. */
221f169c0eaSGlenn Lagasse 	if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM))
222f169c0eaSGlenn Lagasse 	    == NULL) {
223f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_find_mounted_zone_root: failed to "
224f169c0eaSGlenn Lagasse 		    "open zone root container dataset (%s): %s\n"),
225f169c0eaSGlenn Lagasse 		    zone_container_ds, libzfs_error_description(g_zfs));
226f169c0eaSGlenn Lagasse 		return (zfs_err_to_be_err(g_zfs));
227f169c0eaSGlenn Lagasse 	}
228f169c0eaSGlenn Lagasse 
229f169c0eaSGlenn Lagasse 	mzr_data.zone_altroot = zone_altroot;
230f169c0eaSGlenn Lagasse 
231f169c0eaSGlenn Lagasse 	/*
232f169c0eaSGlenn Lagasse 	 * Iterate through all of the zone's BEs, looking for the one
233f169c0eaSGlenn Lagasse 	 * that is currently mounted at the zone altroot in the mounted
234f169c0eaSGlenn Lagasse 	 * global BE.
235f169c0eaSGlenn Lagasse 	 */
236f169c0eaSGlenn Lagasse 	if ((zret = zfs_iter_filesystems(zhp,
237f169c0eaSGlenn Lagasse 	    be_find_mounted_zone_root_callback, &mzr_data)) == 0) {
238f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_find_mounted_zone_root: did not "
239f169c0eaSGlenn Lagasse 		    "find mounted zone under altroot zonepath %s\n"),
240f169c0eaSGlenn Lagasse 		    zonepath_ds);
241f169c0eaSGlenn Lagasse 		ret = BE_ERR_NO_MOUNTED_ZONE;
242f169c0eaSGlenn Lagasse 		goto done;
243f169c0eaSGlenn Lagasse 	} else if (zret < 0) {
244f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_find_mounted_zone_root: "
245f169c0eaSGlenn Lagasse 		    "zfs_iter_filesystems failed: %s\n"),
246f169c0eaSGlenn Lagasse 		    libzfs_error_description(g_zfs));
247f169c0eaSGlenn Lagasse 		ret = zfs_err_to_be_err(g_zfs);
248f169c0eaSGlenn Lagasse 		goto done;
249f169c0eaSGlenn Lagasse 	}
250f169c0eaSGlenn Lagasse 
251f169c0eaSGlenn Lagasse 	if (mzr_data.zoneroot_ds != NULL) {
252f169c0eaSGlenn Lagasse 		(void) strlcpy(zoneroot_ds, mzr_data.zoneroot_ds,
253f169c0eaSGlenn Lagasse 		    zoneroot_ds_size);
254f169c0eaSGlenn Lagasse 		free(mzr_data.zoneroot_ds);
255f169c0eaSGlenn Lagasse 	}
256f169c0eaSGlenn Lagasse 
257f169c0eaSGlenn Lagasse done:
258f169c0eaSGlenn Lagasse 	ZFS_CLOSE(zhp);
259f169c0eaSGlenn Lagasse 	return (ret);
260f169c0eaSGlenn Lagasse }
261f169c0eaSGlenn Lagasse 
262f169c0eaSGlenn Lagasse /*
263f169c0eaSGlenn Lagasse  * Function:	be_zone_supported
264f169c0eaSGlenn Lagasse  * Description:	This function will determine if a zone is supported
265f169c0eaSGlenn Lagasse  *		based on its zonepath dataset.  The zonepath dataset
266f169c0eaSGlenn Lagasse  *		must:
267f169c0eaSGlenn Lagasse  *		   - not be under any global BE root dataset.
268f169c0eaSGlenn Lagasse  *		   - have a root container dataset underneath it.
269f169c0eaSGlenn Lagasse  *
270f169c0eaSGlenn Lagasse  * Parameters:
271f169c0eaSGlenn Lagasse  *		zonepath_ds - name of dataset of the zonepath of the
272f169c0eaSGlenn Lagasse  *		zone to check.
273f169c0eaSGlenn Lagasse  * Returns:
274f169c0eaSGlenn Lagasse  *		B_TRUE - zone is supported
275f169c0eaSGlenn Lagasse  *		B_FALSE - zone is not supported
276f169c0eaSGlenn Lagasse  * Scope:
277f169c0eaSGlenn Lagasse  *		Semi-private (library wide use only)
278f169c0eaSGlenn Lagasse  */
279f169c0eaSGlenn Lagasse boolean_t
be_zone_supported(char * zonepath_ds)280f169c0eaSGlenn Lagasse be_zone_supported(char *zonepath_ds)
281f169c0eaSGlenn Lagasse {
282f169c0eaSGlenn Lagasse 	char	zone_container_ds[MAXPATHLEN];
283f169c0eaSGlenn Lagasse 	int	ret = 0;
284f169c0eaSGlenn Lagasse 
285f169c0eaSGlenn Lagasse 	/*
286f169c0eaSGlenn Lagasse 	 * Make sure the dataset for the zonepath is not hierarchically
287f169c0eaSGlenn Lagasse 	 * under any reserved BE root container dataset of any pool.
288f169c0eaSGlenn Lagasse 	 */
289f169c0eaSGlenn Lagasse 	if ((ret = zpool_iter(g_zfs, be_check_be_roots_callback,
290f169c0eaSGlenn Lagasse 	    zonepath_ds)) > 0) {
291f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_zone_supported: "
292f169c0eaSGlenn Lagasse 		    "zonepath dataset %s not supported\n"), zonepath_ds);
293f169c0eaSGlenn Lagasse 		return (B_FALSE);
294f169c0eaSGlenn Lagasse 	} else if (ret < 0) {
295f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_zone_supported: "
296f169c0eaSGlenn Lagasse 		"zpool_iter failed: %s\n"),
297f169c0eaSGlenn Lagasse 		    libzfs_error_description(g_zfs));
298f169c0eaSGlenn Lagasse 		return (B_FALSE);
299f169c0eaSGlenn Lagasse 	}
300f169c0eaSGlenn Lagasse 
301f169c0eaSGlenn Lagasse 	/*
302f169c0eaSGlenn Lagasse 	 * Make sure the zonepath has a zone root container dataset
303f169c0eaSGlenn Lagasse 	 * underneath it.
304f169c0eaSGlenn Lagasse 	 */
305*ec8422d0SAndy Fiddaman 	if ((ret = be_make_container_ds(zonepath_ds, zone_container_ds,
306*ec8422d0SAndy Fiddaman 	    sizeof (zone_container_ds))) != BE_SUCCESS) {
307*ec8422d0SAndy Fiddaman 		be_print_err(gettext("%s: failed to get BE container dataset "
308*ec8422d0SAndy Fiddaman 		    "for %s\n"), __func__, zonepath_ds);
309*ec8422d0SAndy Fiddaman 		return (B_FALSE);
310*ec8422d0SAndy Fiddaman 	}
311f169c0eaSGlenn Lagasse 
312f169c0eaSGlenn Lagasse 	if (!zfs_dataset_exists(g_zfs, zone_container_ds,
313f169c0eaSGlenn Lagasse 	    ZFS_TYPE_FILESYSTEM)) {
314f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_zone_supported: "
315f169c0eaSGlenn Lagasse 		    "zonepath dataset (%s) does not have a zone root container "
316f169c0eaSGlenn Lagasse 		    "dataset, zone is not supported, skipping ...\n"),
317f169c0eaSGlenn Lagasse 		    zonepath_ds);
318f169c0eaSGlenn Lagasse 		return (B_FALSE);
319f169c0eaSGlenn Lagasse 	}
320f169c0eaSGlenn Lagasse 
321f169c0eaSGlenn Lagasse 	return (B_TRUE);
322f169c0eaSGlenn Lagasse }
323f169c0eaSGlenn Lagasse 
324f169c0eaSGlenn Lagasse /*
325f169c0eaSGlenn Lagasse  * Function:	be_get_supported_brandlist
326f169c0eaSGlenn Lagasse  * Desciption:	This functions retuns a list of supported brands in
327f169c0eaSGlenn Lagasse  *		a zoneBrandList_t object.
328f169c0eaSGlenn Lagasse  * Parameters:
329f169c0eaSGlenn Lagasse  *		None
330f169c0eaSGlenn Lagasse  * Returns:
331f169c0eaSGlenn Lagasse  *		Failure - NULL if no supported brands found.
332f169c0eaSGlenn Lagasse  *		Success - pointer to zoneBrandList structure.
333f169c0eaSGlenn Lagasse  * Scope:
334f169c0eaSGlenn Lagasse  *		Semi-private (library wide use only)
335f169c0eaSGlenn Lagasse  */
336f169c0eaSGlenn Lagasse zoneBrandList_t *
be_get_supported_brandlist(void)337f169c0eaSGlenn Lagasse be_get_supported_brandlist(void)
338f169c0eaSGlenn Lagasse {
339f169c0eaSGlenn Lagasse 	return (z_make_brand_list(BE_ZONE_SUPPORTED_BRANDS,
340f169c0eaSGlenn Lagasse 	    BE_ZONE_SUPPORTED_BRANDS_DELIM));
341f169c0eaSGlenn Lagasse }
342f169c0eaSGlenn Lagasse 
343f169c0eaSGlenn Lagasse /*
344f169c0eaSGlenn Lagasse  * Function:	be_zone_get_parent_uuid
345f169c0eaSGlenn Lagasse  * Description:	This function gets the parentbe property of a zone root
346f169c0eaSGlenn Lagasse  *		dataset, parsed it into internal uuid format, and returns
347f169c0eaSGlenn Lagasse  *		it in the uuid_t reference pointer passed in.
348f169c0eaSGlenn Lagasse  * Parameters:
349f169c0eaSGlenn Lagasse  *		root_ds - dataset name of a zone root dataset
350f169c0eaSGlenn Lagasse  *		uu - pointer to a uuid_t to return the parentbe uuid in
351f169c0eaSGlenn Lagasse  * Returns:
352f169c0eaSGlenn Lagasse  *		BE_SUCCESS - Success
353f169c0eaSGlenn Lagasse  *		be_errno_t - Failure
354f169c0eaSGlenn Lagasse  * Scope:
355f169c0eaSGlenn Lagasse  *		Private
356f169c0eaSGlenn Lagasse  */
357f169c0eaSGlenn Lagasse int
be_zone_get_parent_uuid(const char * root_ds,uuid_t * uu)358f169c0eaSGlenn Lagasse be_zone_get_parent_uuid(const char *root_ds, uuid_t *uu)
359f169c0eaSGlenn Lagasse {
360f169c0eaSGlenn Lagasse 	zfs_handle_t	*zhp = NULL;
361f169c0eaSGlenn Lagasse 	nvlist_t	*userprops = NULL;
362f169c0eaSGlenn Lagasse 	nvlist_t	*propname = NULL;
363f169c0eaSGlenn Lagasse 	char		*uu_string = NULL;
364f169c0eaSGlenn Lagasse 	int		ret = BE_SUCCESS;
365f169c0eaSGlenn Lagasse 
366f169c0eaSGlenn Lagasse 	/* Get handle to zone root dataset */
367f169c0eaSGlenn Lagasse 	if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) {
368f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_zone_get_parent_uuid: failed to "
369f169c0eaSGlenn Lagasse 		    "open zone root dataset (%s): %s\n"), root_ds,
370f169c0eaSGlenn Lagasse 		    libzfs_error_description(g_zfs));
371f169c0eaSGlenn Lagasse 		return (zfs_err_to_be_err(g_zfs));
372f169c0eaSGlenn Lagasse 	}
373f169c0eaSGlenn Lagasse 
374f169c0eaSGlenn Lagasse 	/* Get user properties for zone root dataset */
375f169c0eaSGlenn Lagasse 	if ((userprops = zfs_get_user_props(zhp)) == NULL) {
376f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_zone_get_parent_uuid: "
377f169c0eaSGlenn Lagasse 		    "failed to get user properties for zone root "
378f169c0eaSGlenn Lagasse 		    "dataset (%s): %s\n"), root_ds,
379f169c0eaSGlenn Lagasse 		    libzfs_error_description(g_zfs));
380f169c0eaSGlenn Lagasse 		ret = zfs_err_to_be_err(g_zfs);
381f169c0eaSGlenn Lagasse 		goto done;
382f169c0eaSGlenn Lagasse 	}
383f169c0eaSGlenn Lagasse 
384f169c0eaSGlenn Lagasse 	/* Get UUID string from zone's root dataset user properties */
385f169c0eaSGlenn Lagasse 	if (nvlist_lookup_nvlist(userprops, BE_ZONE_PARENTBE_PROPERTY,
386f169c0eaSGlenn Lagasse 	    &propname) != 0 || nvlist_lookup_string(propname, ZPROP_VALUE,
387f169c0eaSGlenn Lagasse 	    &uu_string) != 0) {
388f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_zone_get_parent_uuid: failed to "
389f169c0eaSGlenn Lagasse 		    "get parent uuid property from zone root dataset user "
390f169c0eaSGlenn Lagasse 		    "properties.\n"));
391f169c0eaSGlenn Lagasse 		ret = BE_ERR_ZONE_NO_PARENTBE;
392f169c0eaSGlenn Lagasse 		goto done;
393f169c0eaSGlenn Lagasse 	}
394f169c0eaSGlenn Lagasse 
395f169c0eaSGlenn Lagasse 	/* Parse the uuid string into internal format */
396f169c0eaSGlenn Lagasse 	if (uuid_parse(uu_string, *uu) != 0 || uuid_is_null(*uu)) {
397f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_zone_get_parent_uuid: failed to "
398f169c0eaSGlenn Lagasse 		    "parse parentuuid\n"));
399f169c0eaSGlenn Lagasse 		ret = BE_ERR_PARSE_UUID;
400f169c0eaSGlenn Lagasse 	}
401f169c0eaSGlenn Lagasse 
402f169c0eaSGlenn Lagasse done:
403f169c0eaSGlenn Lagasse 	ZFS_CLOSE(zhp);
404f169c0eaSGlenn Lagasse 	return (ret);
405f169c0eaSGlenn Lagasse }
406f169c0eaSGlenn Lagasse 
4077e0e2549SAlexander Eremin /*
4087e0e2549SAlexander Eremin  * Function:	be_zone_set_parent_uuid
4097e0e2549SAlexander Eremin  * Description:	This function sets parentbe uuid into
4107e0e2549SAlexander Eremin  *		a zfs user property for a root zone dataset.
4117e0e2549SAlexander Eremin  * Parameters:
4127e0e2549SAlexander Eremin  *		root_ds - Root zone dataset of the BE to set a uuid on.
4137e0e2549SAlexander Eremin  * Return:
4147e0e2549SAlexander Eremin  *		be_errno_t - Failure
4157e0e2549SAlexander Eremin  *		BE_SUCCESS - Success
4167e0e2549SAlexander Eremin  * Scope:
4177e0e2549SAlexander Eremin  *		Semi-private (library wide uses only)
4187e0e2549SAlexander Eremin  */
4197e0e2549SAlexander Eremin int
be_zone_set_parent_uuid(char * root_ds,uuid_t uu)4207e0e2549SAlexander Eremin be_zone_set_parent_uuid(char *root_ds, uuid_t uu)
4217e0e2549SAlexander Eremin {
4227e0e2549SAlexander Eremin 	zfs_handle_t	*zhp = NULL;
4237e0e2549SAlexander Eremin 	char		uu_string[UUID_PRINTABLE_STRING_LENGTH];
4247e0e2549SAlexander Eremin 	int		ret = BE_SUCCESS;
4257e0e2549SAlexander Eremin 
4267e0e2549SAlexander Eremin 	uuid_unparse(uu, uu_string);
4277e0e2549SAlexander Eremin 
4287e0e2549SAlexander Eremin 	/* Get handle to the root zone dataset. */
4297e0e2549SAlexander Eremin 	if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) {
4307e0e2549SAlexander Eremin 		be_print_err(gettext("be_zone_set_parent_uuid: failed to "
4317e0e2549SAlexander Eremin 		    "open root zone dataset (%s): %s\n"), root_ds,
4327e0e2549SAlexander Eremin 		    libzfs_error_description(g_zfs));
4337e0e2549SAlexander Eremin 		return (zfs_err_to_be_err(g_zfs));
4347e0e2549SAlexander Eremin 	}
4357e0e2549SAlexander Eremin 
4367e0e2549SAlexander Eremin 	/* Set parentbe uuid property for the root zone dataset */
4377e0e2549SAlexander Eremin 	if (zfs_prop_set(zhp, BE_ZONE_PARENTBE_PROPERTY, uu_string) != 0) {
4387e0e2549SAlexander Eremin 		be_print_err(gettext("be_zone_set_parent_uuid: failed to "
4397e0e2549SAlexander Eremin 		    "set parentbe uuid property for root zone dataset: %s\n"),
4407e0e2549SAlexander Eremin 		    libzfs_error_description(g_zfs));
4417e0e2549SAlexander Eremin 		ret = zfs_err_to_be_err(g_zfs);
4427e0e2549SAlexander Eremin 	}
4437e0e2549SAlexander Eremin 
4447e0e2549SAlexander Eremin 	ZFS_CLOSE(zhp);
4457e0e2549SAlexander Eremin 	return (ret);
4467e0e2549SAlexander Eremin }
4477e0e2549SAlexander Eremin 
4487e0e2549SAlexander Eremin /*
4497e0e2549SAlexander Eremin  * Function:	be_zone_compare_uuids
4507e0e2549SAlexander Eremin  * Description:	This function compare the parentbe uuid of the
4517e0e2549SAlexander Eremin  *		current running root zone dataset with the parentbe
4527e0e2549SAlexander Eremin  *		uuid of the given root zone dataset.
4537e0e2549SAlexander Eremin  * Parameters:
4547e0e2549SAlexander Eremin  *		root_ds - Root zone dataset of the BE to compare.
4557e0e2549SAlexander Eremin  * Return:
4567e0e2549SAlexander Eremin  *		B_TRUE - root dataset has right parentbe uuid
4577e0e2549SAlexander Eremin  *		B_FALSE - root dataset has wrong parentbe uuid
4587e0e2549SAlexander Eremin  * Scope:
4597e0e2549SAlexander Eremin  *		Semi-private (library wide uses only)
4607e0e2549SAlexander Eremin  */
4617e0e2549SAlexander Eremin boolean_t
be_zone_compare_uuids(char * root_ds)4627e0e2549SAlexander Eremin be_zone_compare_uuids(char *root_ds)
4637e0e2549SAlexander Eremin {
4647e0e2549SAlexander Eremin 	char		*active_ds;
4657e0e2549SAlexander Eremin 	uuid_t		parent_uuid = {0};
4667e0e2549SAlexander Eremin 	uuid_t		cur_parent_uuid = {0};
4677e0e2549SAlexander Eremin 
4687e0e2549SAlexander Eremin 	/* Get parentbe uuid from given zone root dataset */
4697e0e2549SAlexander Eremin 	if ((be_zone_get_parent_uuid(root_ds,
4707e0e2549SAlexander Eremin 	    &parent_uuid)) != BE_SUCCESS) {
4717e0e2549SAlexander Eremin 		be_print_err(gettext("be_zone_compare_uuids: failed to get "
4727e0e2549SAlexander Eremin 		    "parentbe uuid from the given BE\n"));
4737e0e2549SAlexander Eremin 		return (B_FALSE);
4747e0e2549SAlexander Eremin 	}
4757e0e2549SAlexander Eremin 
4767e0e2549SAlexander Eremin 	/*
4777e0e2549SAlexander Eremin 	 * Find current running zone root dataset and get it's parentbe
4787e0e2549SAlexander Eremin 	 * uuid property.
4797e0e2549SAlexander Eremin 	 */
4807e0e2549SAlexander Eremin 	if ((active_ds = be_get_ds_from_dir("/")) != NULL) {
4817e0e2549SAlexander Eremin 		if ((be_zone_get_parent_uuid(active_ds,
4827e0e2549SAlexander Eremin 		    &cur_parent_uuid)) != BE_SUCCESS) {
4837e0e2549SAlexander Eremin 			be_print_err(gettext("be_zone_compare_uuids: failed "
4847e0e2549SAlexander Eremin 			"to get parentbe uuid from the current running zone "
4857e0e2549SAlexander Eremin 			"root dataset\n"));
4867e0e2549SAlexander Eremin 			return (B_FALSE);
4877e0e2549SAlexander Eremin 		}
4887e0e2549SAlexander Eremin 	} else {
4897e0e2549SAlexander Eremin 		be_print_err(gettext("be_zone_compare_uuids: zone root dataset "
4907e0e2549SAlexander Eremin 		    "is not mounted\n"));
4917e0e2549SAlexander Eremin 		return (B_FALSE);
4927e0e2549SAlexander Eremin 	}
4937e0e2549SAlexander Eremin 
4947e0e2549SAlexander Eremin 	if (uuid_compare(parent_uuid, cur_parent_uuid) != 0) {
4957e0e2549SAlexander Eremin 		return (B_FALSE);
4967e0e2549SAlexander Eremin 	}
4977e0e2549SAlexander Eremin 
4987e0e2549SAlexander Eremin 	return (B_TRUE);
4997e0e2549SAlexander Eremin }
5007e0e2549SAlexander Eremin 
501f169c0eaSGlenn Lagasse /* ******************************************************************** */
502f169c0eaSGlenn Lagasse /*			Private Functions				*/
503f169c0eaSGlenn Lagasse /* ******************************************************************** */
504f169c0eaSGlenn Lagasse 
505f169c0eaSGlenn Lagasse /*
506f169c0eaSGlenn Lagasse  * Function:	be_find_active_zone_root_callback
507f169c0eaSGlenn Lagasse  * Description: This function is used as a callback to iterate over all of
508f169c0eaSGlenn Lagasse  *		a zone's root datasets, finding the one that is marked active
509f169c0eaSGlenn Lagasse  *		for the parent BE specified in the data passed in.  The name
510f169c0eaSGlenn Lagasse  *		of the zone's active root dataset is returned in heap storage
511f169c0eaSGlenn Lagasse  *		in the active_zone_root_data_t structure passed in, so the
512f169c0eaSGlenn Lagasse  *		caller is responsible for freeing it.
513f169c0eaSGlenn Lagasse  * Parameters:
514f169c0eaSGlenn Lagasse  *		zhp - zfs_handle_t pointer to current dataset being processed
515f169c0eaSGlenn Lagasse  *		data - active_zone_root_data_t pointer
516f169c0eaSGlenn Lagasse  * Returns:
517f169c0eaSGlenn Lagasse  *		0 - Success
518f169c0eaSGlenn Lagasse  *		>0 - Failure
519f169c0eaSGlenn Lagasse  * Scope:
520f169c0eaSGlenn Lagasse  *		Private
521f169c0eaSGlenn Lagasse  */
522f169c0eaSGlenn Lagasse static int
be_find_active_zone_root_callback(zfs_handle_t * zhp,void * data)523f169c0eaSGlenn Lagasse be_find_active_zone_root_callback(zfs_handle_t *zhp, void *data)
524f169c0eaSGlenn Lagasse {
525f169c0eaSGlenn Lagasse 	active_zone_root_data_t	*azr_data = data;
526f169c0eaSGlenn Lagasse 	uuid_t			parent_uuid = { 0 };
527f169c0eaSGlenn Lagasse 	int			iret = 0;
528f169c0eaSGlenn Lagasse 	int			ret = 0;
529f169c0eaSGlenn Lagasse 
530f169c0eaSGlenn Lagasse 	if ((iret = be_zone_get_parent_uuid(zfs_get_name(zhp), &parent_uuid))
531f169c0eaSGlenn Lagasse 	    != BE_SUCCESS) {
532f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_find_active_zone_root_callback: "
533f169c0eaSGlenn Lagasse 		    "skipping zone root dataset (%s): %s\n"),
534f169c0eaSGlenn Lagasse 		    zfs_get_name(zhp), be_err_to_str(iret));
535f169c0eaSGlenn Lagasse 		goto done;
536f169c0eaSGlenn Lagasse 	}
537f169c0eaSGlenn Lagasse 
538f169c0eaSGlenn Lagasse 	if (uuid_compare(azr_data->parent_uuid, parent_uuid) == 0) {
539f169c0eaSGlenn Lagasse 		/*
540f169c0eaSGlenn Lagasse 		 * Found a zone root dataset belonging to the right parent,
541f169c0eaSGlenn Lagasse 		 * check if its active.
542f169c0eaSGlenn Lagasse 		 */
543f169c0eaSGlenn Lagasse 		if (be_zone_get_active(zhp)) {
544f169c0eaSGlenn Lagasse 			/*
545f169c0eaSGlenn Lagasse 			 * Found active zone root dataset, if its already
546f169c0eaSGlenn Lagasse 			 * set in the callback data, that means this
547f169c0eaSGlenn Lagasse 			 * is the second one we've found.  Return error.
548f169c0eaSGlenn Lagasse 			 */
549f169c0eaSGlenn Lagasse 			if (azr_data->zoneroot_ds != NULL) {
550f169c0eaSGlenn Lagasse 				ret = BE_ERR_ZONE_MULTIPLE_ACTIVE;
551f169c0eaSGlenn Lagasse 				goto done;
552f169c0eaSGlenn Lagasse 			}
553f169c0eaSGlenn Lagasse 
554f169c0eaSGlenn Lagasse 			azr_data->zoneroot_ds = strdup(zfs_get_name(zhp));
555f169c0eaSGlenn Lagasse 			if (azr_data->zoneroot_ds == NULL) {
556f169c0eaSGlenn Lagasse 				ret = BE_ERR_NOMEM;
557f169c0eaSGlenn Lagasse 			}
558f169c0eaSGlenn Lagasse 		}
559f169c0eaSGlenn Lagasse 	}
560f169c0eaSGlenn Lagasse 
561f169c0eaSGlenn Lagasse done:
562f169c0eaSGlenn Lagasse 	ZFS_CLOSE(zhp);
563f169c0eaSGlenn Lagasse 	return (ret);
564f169c0eaSGlenn Lagasse }
565f169c0eaSGlenn Lagasse 
566f169c0eaSGlenn Lagasse /*
567f169c0eaSGlenn Lagasse  * Function:	be_find_mounted_zone_root_callback
568f169c0eaSGlenn Lagasse  * Description:	This function is used as a callback to iterate over all of
569f169c0eaSGlenn Lagasse  *		a zone's root datasets, find the one that is currently
570f169c0eaSGlenn Lagasse  *		mounted for the parent BE specified in the data passed in.
571f169c0eaSGlenn Lagasse  *		The name of the zone's mounted root dataset is returned in
572f169c0eaSGlenn Lagasse  *		heap storage the mounted_zone_data_t structure passed in,
573f169c0eaSGlenn Lagasse  *		so the caller is responsible for freeing it.
574f169c0eaSGlenn Lagasse  * Parameters:
575f169c0eaSGlenn Lagasse  *		zhp - zfs_handle_t pointer to the current dataset being
576f169c0eaSGlenn Lagasse  *			processed
577f169c0eaSGlenn Lagasse  *		data - mounted_zone_data_t pointer
578f169c0eaSGlenn Lagasse  * Returns:
579f169c0eaSGlenn Lagasse  *		0 - not mounted as zone's root
580f169c0eaSGlenn Lagasse  *		1 - this dataset is mounted as zone's root
581f169c0eaSGlenn Lagasse  * Scope:
582f169c0eaSGlenn Lagasse  *		Private
583f169c0eaSGlenn Lagasse  */
584f169c0eaSGlenn Lagasse static int
be_find_mounted_zone_root_callback(zfs_handle_t * zhp,void * data)585f169c0eaSGlenn Lagasse be_find_mounted_zone_root_callback(zfs_handle_t *zhp, void *data)
586f169c0eaSGlenn Lagasse {
587f169c0eaSGlenn Lagasse 	mounted_zone_root_data_t	*mzr_data = data;
588f169c0eaSGlenn Lagasse 	char				*mp = NULL;
589f169c0eaSGlenn Lagasse 
590f169c0eaSGlenn Lagasse 	if (zfs_is_mounted(zhp, &mp) && mp != NULL &&
591f169c0eaSGlenn Lagasse 	    strcmp(mp, mzr_data->zone_altroot) == 0) {
592f169c0eaSGlenn Lagasse 		mzr_data->zoneroot_ds = strdup(zfs_get_name(zhp));
593f169c0eaSGlenn Lagasse 		free(mp);
594f169c0eaSGlenn Lagasse 		return (1);
595f169c0eaSGlenn Lagasse 	}
596f169c0eaSGlenn Lagasse 
597f169c0eaSGlenn Lagasse 	free(mp);
598f169c0eaSGlenn Lagasse 	return (0);
599f169c0eaSGlenn Lagasse }
600f169c0eaSGlenn Lagasse 
601f169c0eaSGlenn Lagasse /*
602f169c0eaSGlenn Lagasse  * Function:	be_zone_get_active
603f169c0eaSGlenn Lagasse  * Description: This function gets the active property of a zone root
604f169c0eaSGlenn Lagasse  *		dataset, and returns true if active property is on.
605f169c0eaSGlenn Lagasse  * Parameters:
606f169c0eaSGlenn Lagasse  *		zfs - zfs_handle_t pointer to zone root dataset to check
607f169c0eaSGlenn Lagasse  * Returns:
608f169c0eaSGlenn Lagasse  *		B_TRUE - zone root dataset is active
609f169c0eaSGlenn Lagasse  *		B_FALSE - zone root dataset is not active
610f169c0eaSGlenn Lagasse  * Scope:
611f169c0eaSGlenn Lagasse  *		Private
612f169c0eaSGlenn Lagasse  */
613f169c0eaSGlenn Lagasse static boolean_t
be_zone_get_active(zfs_handle_t * zhp)614f169c0eaSGlenn Lagasse be_zone_get_active(zfs_handle_t *zhp)
615f169c0eaSGlenn Lagasse {
616f169c0eaSGlenn Lagasse 	nvlist_t	*userprops = NULL;
617f169c0eaSGlenn Lagasse 	nvlist_t	*propname = NULL;
618f169c0eaSGlenn Lagasse 	char		*active_str = NULL;
619f169c0eaSGlenn Lagasse 
620f169c0eaSGlenn Lagasse 	/* Get user properties for the zone root dataset */
621f169c0eaSGlenn Lagasse 	if ((userprops = zfs_get_user_props(zhp)) == NULL) {
622f169c0eaSGlenn Lagasse 		be_print_err(gettext("be_zone_get_active: "
623f169c0eaSGlenn Lagasse 		    "failed to get user properties for zone root "
624f169c0eaSGlenn Lagasse 		    "dataset (%s): %s\n"), zfs_get_name(zhp),
625f169c0eaSGlenn Lagasse 		    libzfs_error_description(g_zfs));
626f169c0eaSGlenn Lagasse 		return (B_FALSE);
627f169c0eaSGlenn Lagasse 	}
628f169c0eaSGlenn Lagasse 
629f169c0eaSGlenn Lagasse 	/* Get active property from the zone root dataset user properties */
630f169c0eaSGlenn Lagasse 	if (nvlist_lookup_nvlist(userprops, BE_ZONE_ACTIVE_PROPERTY, &propname)
631f169c0eaSGlenn Lagasse 	    != 0 || nvlist_lookup_string(propname, ZPROP_VALUE, &active_str)
632f169c0eaSGlenn Lagasse 	    != 0) {
633f169c0eaSGlenn Lagasse 		return (B_FALSE);
634f169c0eaSGlenn Lagasse 	}
635f169c0eaSGlenn Lagasse 
636f169c0eaSGlenn Lagasse 	if (strcmp(active_str, "on") == 0)
637f169c0eaSGlenn Lagasse 		return (B_TRUE);
638f169c0eaSGlenn Lagasse 
639f169c0eaSGlenn Lagasse 	return (B_FALSE);
640f169c0eaSGlenn Lagasse }
641