xref: /titanic_44/usr/src/lib/pylibbe/common/libbe_py.c (revision c3e9074d863038c38dc15c3af85b017f42133816)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #include <Python.h>
27 #include <sys/varargs.h>
28 #include <stdio.h>
29 #include <libnvpair.h>
30 
31 #include <libbe.h>
32 #include <libbe_priv.h>
33 
34 enum {
35 	BE_PY_SUCCESS = 0,
36 	BE_PY_ERR_APPEND = 6000,
37 	BE_PY_ERR_DICT,
38 	BE_PY_ERR_LIST,
39 	BE_PY_ERR_NVLIST,
40 	BE_PY_ERR_PARSETUPLE,
41 	BE_PY_ERR_PRINT_ERR,
42 	BE_PY_ERR_VAR_CONV,
43 } bePyErr;
44 
45 /*
46  * public libbe functions
47  */
48 
49 PyObject *beCreateSnapshot(PyObject *, PyObject *);
50 PyObject *beCopy(PyObject *, PyObject *);
51 PyObject *beList(PyObject *, PyObject *);
52 PyObject *beActivate(PyObject *, PyObject *);
53 PyObject *beDestroy(PyObject *, PyObject *);
54 PyObject *beDestroySnapshot(PyObject *, PyObject *);
55 PyObject *beRename(PyObject *, PyObject *);
56 PyObject *beMount(PyObject *, PyObject *);
57 PyObject *beUnmount(PyObject *, PyObject *);
58 PyObject *bePrintErrors(PyObject *, PyObject *);
59 PyObject *beGetErrDesc(PyObject *, PyObject *);
60 char *beMapLibbePyErrorToString(int);
61 void initlibbe_py();
62 
63 static boolean_t convertBEInfoToDictionary(be_node_list_t *be,
64     PyObject **listDict);
65 static boolean_t convertDatasetInfoToDictionary(be_dataset_list_t *ds,
66     PyObject **listDict);
67 static boolean_t convertSnapshotInfoToDictionary(be_snapshot_list_t *ss,
68     PyObject **listDict);
69 static boolean_t convertPyArgsToNvlist(nvlist_t **nvList, int numArgs, ...);
70 
71 
72 /* ~~~~~~~~~~~~~~~ */
73 /* Public Funtions */
74 /* ~~~~~~~~~~~~~~~ */
75 
76 /*
77  * Function:    beCreateSnapshot
78  * Description: Convert Python args to nvlist pairs and
79  *              call libbe:be_create_snapshot to create a
80  *              snapshot of all the datasets within a BE
81  * Parameters:
82  *   args -          pointer to a python object containing:
83  *        beName -   The name of the BE to create a snapshot of
84  *        snapName - The name of the snapshot to create (optional)
85  *
86  *        The following public attribute values. defined by libbe.h,
87  *        are used by this function:
88  *
89  * Returns a pointer to a python object and an optional snapshot name:
90  *      0, [snapName] - Success
91  *      1, [snapName] - Failure
92  * Scope:
93  *      Public
94  */
95 /* ARGSUSED */
96 PyObject *
97 beCreateSnapshot(PyObject *self, PyObject *args)
98 {
99 	char	*beName = NULL;
100 	char	*snapName = NULL;
101 	int	ret = BE_PY_SUCCESS;
102 	nvlist_t	*beAttrs = NULL;
103 	PyObject	*retVals = NULL;
104 
105 	if (!PyArg_ParseTuple(args, "z|z", &beName, &snapName)) {
106 		return (Py_BuildValue("[is]", BE_PY_ERR_PARSETUPLE, NULL));
107 	}
108 
109 	if (!convertPyArgsToNvlist(&beAttrs, 4,
110 	    BE_ATTR_ORIG_BE_NAME, beName,
111 	    BE_ATTR_SNAP_NAME, snapName)) {
112 		nvlist_free(beAttrs);
113 		return (Py_BuildValue("[is]", BE_PY_ERR_NVLIST, NULL));
114 	}
115 
116 	if (beAttrs == NULL) {
117 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
118 	}
119 
120 	if ((ret = be_create_snapshot(beAttrs)) != 0) {
121 		nvlist_free(beAttrs);
122 		return (Py_BuildValue("[is]", ret, NULL));
123 	}
124 	if (snapName == NULL) {
125 		if (nvlist_lookup_pairs(beAttrs, NV_FLAG_NOENTOK,
126 		    BE_ATTR_SNAP_NAME, DATA_TYPE_STRING, &snapName,
127 		    NULL) != 0) {
128 			nvlist_free(beAttrs);
129 			return (Py_BuildValue("[is]",
130 			    BE_PY_ERR_NVLIST, NULL));
131 		}
132 		retVals = Py_BuildValue("[is]", ret, snapName);
133 		nvlist_free(beAttrs);
134 		return (retVals);
135 	}
136 	nvlist_free(beAttrs);
137 
138 	return (Py_BuildValue("[is]", ret, NULL));
139 }
140 
141 /*
142  * Function:    beCopy
143  * Description: Convert Python args to nvlist pairs and call libbe:be_copy
144  *              to create a Boot Environment
145  * Parameters:
146  *   args -     pointer to a python object containing:
147  *     trgtBeName - The name of the BE to create
148  *     srcBeName - The name of the BE used to create trgtBeName (optional)
149  *     rpool - The pool to create the new BE in (optional)
150  *     srcSnapName - The snapshot name (optional)
151  *     beNameProperties - The properties to use when creating
152  *                        the BE (optional)
153  *
154  * Returns a pointer to a python object. That Python object will consist of
155  * the return code and optional attributes, trgtBeName and snapshotName
156  *      BE_SUCCESS, [trgtBeName], [trgtSnapName] - Success
157  *      1, [trgtBeName], [trgtSnapName] - Failure
158  * Scope:
159  *      Public
160  */
161 /* ARGSUSED */
162 PyObject *
163 beCopy(PyObject *self, PyObject *args)
164 {
165 	char	*trgtBeName = NULL;
166 	char	*srcBeName = NULL;
167 	char	*srcSnapName = NULL;
168 	char	*trgtSnapName = NULL;
169 	char	*rpool = NULL;
170 	char	*beDescription = NULL;
171 	int		pos = 0;
172 	int		ret = BE_PY_SUCCESS;
173 	nvlist_t	*beAttrs = NULL;
174 	nvlist_t	*beProps = NULL;
175 	PyObject	*beNameProperties = NULL;
176 	PyObject	*pkey = NULL;
177 	PyObject	*pvalue = NULL;
178 	PyObject	*retVals = NULL;
179 
180 	if (!PyArg_ParseTuple(args, "|zzzzOz", &trgtBeName, &srcBeName,
181 	    &srcSnapName, &rpool, &beNameProperties, &beDescription)) {
182 		return (Py_BuildValue("[iss]", BE_PY_ERR_PARSETUPLE,
183 		    NULL, NULL));
184 	}
185 
186 	if (!convertPyArgsToNvlist(&beAttrs, 10,
187 	    BE_ATTR_NEW_BE_NAME, trgtBeName,
188 	    BE_ATTR_ORIG_BE_NAME, srcBeName,
189 	    BE_ATTR_SNAP_NAME, srcSnapName,
190 	    BE_ATTR_NEW_BE_POOL, rpool,
191 	    BE_ATTR_NEW_BE_DESC, beDescription)) {
192 		nvlist_free(beAttrs);
193 		return (Py_BuildValue("[iss]", BE_PY_ERR_NVLIST, NULL, NULL));
194 	}
195 
196 	if (beNameProperties != NULL) {
197 		if (nvlist_alloc(&beProps, NV_UNIQUE_NAME, 0) != 0) {
198 			(void) printf("nvlist_alloc failed.\n");
199 			nvlist_free(beAttrs);
200 			return (Py_BuildValue("[iss]", BE_PY_ERR_NVLIST,
201 			    NULL, NULL));
202 		}
203 		while (PyDict_Next(beNameProperties, &pos, &pkey, &pvalue)) {
204 			if (!convertPyArgsToNvlist(&beProps, 2,
205 			    PyString_AsString(pkey),
206 			    PyString_AsString(pvalue))) {
207 				nvlist_free(beProps);
208 				nvlist_free(beAttrs);
209 				return (Py_BuildValue("[iss]", BE_PY_ERR_NVLIST,
210 				    NULL, NULL));
211 			}
212 		}
213 	}
214 
215 	if (beProps != NULL && beAttrs != NULL &&
216 	    nvlist_add_nvlist(beAttrs, BE_ATTR_ZFS_PROPERTIES,
217 	    beProps) != 0) {
218 		nvlist_free(beProps);
219 		nvlist_free(beAttrs);
220 		return (Py_BuildValue("[iss]", BE_PY_ERR_NVLIST,
221 		    NULL, NULL));
222 	}
223 
224 	if (beProps != NULL) nvlist_free(beProps);
225 
226 	if (trgtBeName == NULL) {
227 		/*
228 		 * Caller wants to get back the BE_ATTR_NEW_BE_NAME and
229 		 * BE_ATTR_SNAP_NAME
230 		 */
231 		if ((ret = be_copy(beAttrs)) != BE_SUCCESS) {
232 			nvlist_free(beAttrs);
233 			return (Py_BuildValue("[iss]", ret, NULL, NULL));
234 		}
235 
236 		/*
237 		 * When no trgtBeName is passed to be_copy, be_copy
238 		 * returns an auto generated beName and snapshot name.
239 		 */
240 		if (nvlist_lookup_string(beAttrs, BE_ATTR_NEW_BE_NAME,
241 		    &trgtBeName) != 0) {
242 			nvlist_free(beAttrs);
243 			return (Py_BuildValue("[iss]", BE_PY_ERR_NVLIST,
244 			    NULL, NULL));
245 		}
246 		if (nvlist_lookup_string(beAttrs, BE_ATTR_SNAP_NAME,
247 		    &trgtSnapName) != 0) {
248 			nvlist_free(beAttrs);
249 			return (Py_BuildValue("[iss]", BE_PY_ERR_NVLIST,
250 			    NULL, NULL));
251 		}
252 
253 		retVals = Py_BuildValue("[iss]", BE_PY_SUCCESS,
254 		    trgtBeName, trgtSnapName);
255 		nvlist_free(beAttrs);
256 		return (retVals);
257 
258 	} else {
259 		ret = be_copy(beAttrs);
260 		nvlist_free(beAttrs);
261 		return (Py_BuildValue("[iss]", ret, NULL, NULL));
262 	}
263 }
264 
265 /*
266  * Function:    beList
267  * Description: Convert Python args to nvlist pairs and call libbe:be_list
268  *              to gather information about Boot Environments
269  * Parameters:
270  *   args -     pointer to a python object containing:
271  *     beName - The name of the BE to list (optional)
272  *
273  * Returns a pointer to a python object. That Python object will consist of
274  * the return code and a list of Dicts or NULL.
275  *      BE_PY_SUCCESS, listOfDicts - Success
276  *      bePyErr or be_errno_t, NULL - Failure
277  * Scope:
278  *      Public
279  */
280 /* ARGSUSED */
281 PyObject *
282 beList(PyObject *self, PyObject *args)
283 {
284 	char	*beName = NULL;
285 	int	ret = BE_PY_SUCCESS;
286 	be_node_list_t *list = NULL;
287 	be_node_list_t *be = NULL;
288 	PyObject *dict = NULL;
289 	PyObject *listOfDicts = NULL;
290 
291 	if ((listOfDicts = PyList_New(0)) == NULL) {
292 		ret = BE_PY_ERR_DICT;
293 		listOfDicts = Py_None;
294 		goto done;
295 	}
296 
297 	if (!PyArg_ParseTuple(args, "|z", &beName)) {
298 		ret = BE_PY_ERR_PARSETUPLE;
299 		goto done;
300 	}
301 
302 	if ((ret = be_list(beName, &list)) != BE_SUCCESS) {
303 		goto done;
304 	}
305 
306 	for (be = list; be != NULL; be = be->be_next_node) {
307 		be_dataset_list_t *ds = be->be_node_datasets;
308 		be_snapshot_list_t *ss = be->be_node_snapshots;
309 
310 		if ((dict = PyDict_New()) == NULL) {
311 			ret = BE_PY_ERR_DICT;
312 			goto done;
313 		}
314 
315 		if (!convertBEInfoToDictionary(be, &dict)) {
316 			/* LINTED */
317 			Py_DECREF(dict);
318 			ret = BE_PY_ERR_VAR_CONV;
319 			goto done;
320 		}
321 
322 		if (PyList_Append(listOfDicts, dict) != 0) {
323 			/* LINTED */
324 			Py_DECREF(dict);
325 			ret = BE_PY_ERR_APPEND;
326 			goto done;
327 		}
328 
329 		/* LINTED */
330 		Py_DECREF(dict);
331 
332 		while (ds != NULL) {
333 			if ((dict = PyDict_New()) == NULL) {
334 				ret = BE_PY_ERR_DICT;
335 				goto done;
336 			}
337 
338 			if (!convertDatasetInfoToDictionary(ds, &dict)) {
339 				/* LINTED */
340 				Py_DECREF(dict);
341 				ret = BE_PY_ERR_VAR_CONV;
342 				goto done;
343 			}
344 
345 			if (PyList_Append(listOfDicts, dict) != 0) {
346 				/* LINTED */
347 				Py_DECREF(dict);
348 				ret = BE_PY_ERR_APPEND;
349 				goto done;
350 			}
351 
352 			ds = ds->be_next_dataset;
353 
354 			/* LINTED */
355 			Py_DECREF(dict);
356 		}
357 
358 
359 		while (ss != NULL) {
360 			if ((dict = PyDict_New()) == NULL) {
361 				/* LINTED */
362 				Py_DECREF(dict);
363 				ret = BE_PY_ERR_DICT;
364 				goto done;
365 			}
366 
367 			if (!convertSnapshotInfoToDictionary(ss, &dict)) {
368 				/* LINTED */
369 				Py_DECREF(dict);
370 				ret = BE_PY_ERR_VAR_CONV;
371 				goto done;
372 			}
373 
374 			if (PyList_Append(listOfDicts, dict) != 0) {
375 				/* LINTED */
376 				Py_DECREF(dict);
377 				ret = BE_PY_ERR_APPEND;
378 				goto done;
379 			}
380 
381 			ss = ss->be_next_snapshot;
382 
383 			/* LINTED */
384 			Py_DECREF(dict);
385 		}
386 	}
387 
388 done:
389 	if (list != NULL)
390 		be_free_list(list);
391 	return (Py_BuildValue("[iO]", ret, listOfDicts));
392 }
393 
394 /*
395  * Function:    beActivate
396  * Description: Convert Python args to nvlist pairs and call libbe:be_activate
397  *              to activate a Boot Environment
398  * Parameters:
399  *   args -     pointer to a python object containing:
400  *     beName - The name of the BE to activate
401  *
402  * Returns a pointer to a python object:
403  *      BE_SUCCESS - Success
404  *      bePyErr or be_errno_t - Failure
405  * Scope:
406  *      Public
407  */
408 /* ARGSUSED */
409 PyObject *
410 beActivate(PyObject *self, PyObject *args)
411 {
412 	char		*beName = NULL;
413 	int		ret = BE_PY_SUCCESS;
414 	nvlist_t	*beAttrs = NULL;
415 
416 	if (!PyArg_ParseTuple(args, "z", &beName)) {
417 		return (Py_BuildValue("i", BE_PY_ERR_PARSETUPLE));
418 	}
419 
420 	if (!convertPyArgsToNvlist(&beAttrs, 2, BE_ATTR_ORIG_BE_NAME, beName)) {
421 		nvlist_free(beAttrs);
422 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
423 	}
424 
425 	if (beAttrs == NULL) {
426 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
427 	}
428 
429 	ret = be_activate(beAttrs);
430 	nvlist_free(beAttrs);
431 	return (Py_BuildValue("i", ret));
432 }
433 
434 /*
435  * Function:    beDestroy
436  * Description: Convert Python args to nvlist pairs and call libbe:be_destroy
437  *              to destroy a Boot Environment
438  * Parameters:
439  *   args -     pointer to a python object containing:
440  *     beName - The name of the BE to destroy
441  *
442  * Returns a pointer to a python object:
443  *      BE_SUCCESS - Success
444  *      bePyErr or be_errno_t - Failure
445  * Scope:
446  *      Public
447  */
448 /* ARGSUSED */
449 PyObject *
450 beDestroy(PyObject *self, PyObject *args)
451 {
452 	char		*beName = NULL;
453 	int		destroy_snaps = 0;
454 	int		force_unmount = 0;
455 	int		destroy_flags = 0;
456 	int		ret = BE_PY_SUCCESS;
457 	nvlist_t	*beAttrs = NULL;
458 
459 	if (!PyArg_ParseTuple(args, "z|ii", &beName, &destroy_snaps,
460 	    &force_unmount)) {
461 		return (Py_BuildValue("i", BE_PY_ERR_PARSETUPLE));
462 	}
463 
464 	if (destroy_snaps == 1)
465 		destroy_flags |= BE_DESTROY_FLAG_SNAPSHOTS;
466 
467 	if (force_unmount == 1)
468 		destroy_flags |= BE_DESTROY_FLAG_FORCE_UNMOUNT;
469 
470 	if (!convertPyArgsToNvlist(&beAttrs, 2, BE_ATTR_ORIG_BE_NAME, beName)) {
471 		nvlist_free(beAttrs);
472 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
473 	}
474 
475 	if (nvlist_add_uint16(beAttrs, BE_ATTR_DESTROY_FLAGS, destroy_flags)
476 	    != 0) {
477 		(void) printf("nvlist_add_uint16 failed for "
478 		    "BE_ATTR_DESTROY_FLAGS (%d).\n", destroy_flags);
479 		nvlist_free(beAttrs);
480 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
481 	}
482 
483 	if (beAttrs == NULL) {
484 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
485 	}
486 
487 	ret = be_destroy(beAttrs);
488 	nvlist_free(beAttrs);
489 	return (Py_BuildValue("i", ret));
490 }
491 
492 /*
493  * Function:    beDestroySnapshot
494  * Description: Convert Python args to nvlist pairs and call libbe:be_destroy
495  *              to destroy a snapshot of a Boot Environment
496  * Parameters:
497  *   args -     pointer to a python object containing:
498  *     beName - The name of the BE to destroy
499  *     snapName - The name of the snapshot to destroy
500  *
501  * Returns a pointer to a python object:
502  *      BE_SUCCESS - Success
503  *      bePyErr or be_errno_t - Failure
504  * Scope:
505  *      Public
506  */
507 /* ARGSUSED */
508 PyObject *
509 beDestroySnapshot(PyObject *self, PyObject *args)
510 {
511 	char		*beName = NULL;
512 	char		*snapName = NULL;
513 	int		ret = BE_PY_SUCCESS;
514 	nvlist_t	*beAttrs = NULL;
515 
516 	if (!PyArg_ParseTuple(args, "zz", &beName, &snapName)) {
517 		return (Py_BuildValue("i", BE_PY_ERR_PARSETUPLE));
518 	}
519 
520 	if (!convertPyArgsToNvlist(&beAttrs, 4,
521 	    BE_ATTR_ORIG_BE_NAME, beName,
522 	    BE_ATTR_SNAP_NAME, snapName)) {
523 		nvlist_free(beAttrs);
524 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
525 	}
526 
527 	if (beAttrs == NULL) {
528 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
529 	}
530 
531 	ret = be_destroy_snapshot(beAttrs);
532 	nvlist_free(beAttrs);
533 	return (Py_BuildValue("i", ret));
534 }
535 
536 /*
537  * Function:    beRename
538  * Description: Convert Python args to nvlist pairs and call libbe:be_rename
539  *              to rename a Boot Environment
540  * Parameters:
541  *   args -     pointer to a python object containing:
542  *     oldBeName - The name of the old Boot Environment
543  *     newBeName - The name of the new Boot Environment
544  *
545  * Returns a pointer to a python object:
546  *      BE_SUCCESS - Success
547  *      bePyErr or be_errno_t - Failure
548  * Scope:
549  *      Public
550  */
551 /* ARGSUSED */
552 PyObject *
553 beRename(PyObject *self, PyObject *args)
554 {
555 	char		*oldBeName = NULL;
556 	char		*newBeName = NULL;
557 	int		ret = BE_PY_SUCCESS;
558 	nvlist_t	*beAttrs = NULL;
559 
560 	if (!PyArg_ParseTuple(args, "zz", &oldBeName, &newBeName)) {
561 		return (Py_BuildValue("i", BE_PY_ERR_PARSETUPLE));
562 	}
563 
564 	if (!convertPyArgsToNvlist(&beAttrs, 4,
565 	    BE_ATTR_ORIG_BE_NAME, oldBeName,
566 	    BE_ATTR_NEW_BE_NAME, newBeName)) {
567 		nvlist_free(beAttrs);
568 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
569 	}
570 
571 	if (beAttrs == NULL) {
572 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
573 	}
574 
575 	ret = be_rename(beAttrs);
576 	nvlist_free(beAttrs);
577 	return (Py_BuildValue("i", ret));
578 }
579 
580 /*
581  * Function:    beMount
582  * Description: Convert Python args to nvlist pairs and call libbe:be_mount
583  *              to mount a Boot Environment
584  * Parameters:
585  *   args -     pointer to a python object containing:
586  *     beName - The name of the Boot Environment to mount
587  *     mountpoint - The path of the mountpoint to mount the
588  *                  Boot Environment on (optional)
589  *
590  * Returns a pointer to a python object:
591  *      BE_SUCCESS - Success
592  *      bePyErr or be_errno_t - Failure
593  * Scope:
594  *      Public
595  */
596 /* ARGSUSED */
597 PyObject *
598 beMount(PyObject *self, PyObject *args)
599 {
600 	char		*beName = NULL;
601 	char		*mountpoint = NULL;
602 	int		ret = BE_PY_SUCCESS;
603 	nvlist_t	*beAttrs = NULL;
604 
605 	if (!PyArg_ParseTuple(args, "zz", &beName, &mountpoint)) {
606 		return (Py_BuildValue("i", BE_PY_ERR_PARSETUPLE));
607 	}
608 
609 	if (!convertPyArgsToNvlist(&beAttrs, 4,
610 	    BE_ATTR_ORIG_BE_NAME, beName,
611 	    BE_ATTR_MOUNTPOINT, mountpoint)) {
612 		nvlist_free(beAttrs);
613 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
614 	}
615 
616 	if (beAttrs == NULL) {
617 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
618 	}
619 
620 	ret = be_mount(beAttrs);
621 	nvlist_free(beAttrs);
622 	return (Py_BuildValue("i", ret));
623 }
624 
625 /*
626  * Function:    beUnmount
627  * Description: Convert Python args to nvlist pairs and call libbe:be_unmount
628  *              to unmount a Boot Environment
629  * Parameters:
630  *   args -     pointer to a python object containing:
631  *     beName - The name of the Boot Environment to unmount
632  *
633  * Returns a pointer to a python object:
634  *      BE_SUCCESS - Success
635  *      bePyErr or be_errno_t - Failure
636  * Scope:
637  *      Public
638  */
639 /* ARGSUSED */
640 PyObject *
641 beUnmount(PyObject *self, PyObject *args)
642 {
643 	char 		*beName = NULL;
644 	int		force_unmount = 0;
645 	int		unmount_flags = 0;
646 	int		ret = BE_PY_SUCCESS;
647 	nvlist_t	*beAttrs = NULL;
648 
649 	if (!PyArg_ParseTuple(args, "z|i", &beName, &force_unmount)) {
650 		return (Py_BuildValue("i", BE_PY_ERR_PARSETUPLE));
651 	}
652 
653 	if (force_unmount == 1)
654 		unmount_flags |= BE_UNMOUNT_FLAG_FORCE;
655 
656 	if (!convertPyArgsToNvlist(&beAttrs, 2,
657 	    BE_ATTR_ORIG_BE_NAME, beName)) {
658 		nvlist_free(beAttrs);
659 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
660 	}
661 
662 	if (nvlist_add_uint16(beAttrs, BE_ATTR_UNMOUNT_FLAGS, unmount_flags)
663 	    != 0) {
664 		(void) printf("nvlist_add_uint16 failed for "
665 		    "BE_ATTR_UNMOUNT_FLAGS (%d).\n", unmount_flags);
666 		nvlist_free(beAttrs);
667 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
668 	}
669 
670 	if (beAttrs == NULL) {
671 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
672 	}
673 
674 	ret = be_unmount(beAttrs);
675 	nvlist_free(beAttrs);
676 	return (Py_BuildValue("i", ret));
677 }
678 
679 /*
680  * Function:    beRollback
681  * Description: Convert Python args to nvlist pairs and call libbe:be_rollback
682  *              to rollback a Boot Environment to a previously taken
683  *               snapshot.
684  * Parameters:
685  *   args -     pointer to a python object containing:
686  *     beName - The name of the Boot Environment to unmount
687  *
688  * Returns a pointer to a python object:
689  *      BE_SUCCESS - Success
690  *      bePyErr or be_errno_t - Failure
691  * Scope:
692  *      Public
693  */
694 /* ARGSUSED */
695 PyObject *
696 beRollback(PyObject *self, PyObject *args)
697 {
698 	char		*beName = NULL;
699 	char		*snapName = NULL;
700 	int		ret = BE_PY_SUCCESS;
701 	nvlist_t	*beAttrs = NULL;
702 
703 	if (!PyArg_ParseTuple(args, "zz", &beName, &snapName)) {
704 		return (Py_BuildValue("i", BE_PY_ERR_PARSETUPLE));
705 	}
706 
707 	if (!convertPyArgsToNvlist(&beAttrs, 4,
708 	    BE_ATTR_ORIG_BE_NAME, beName,
709 	    BE_ATTR_SNAP_NAME, snapName)) {
710 		nvlist_free(beAttrs);
711 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
712 	}
713 
714 	if (beAttrs == NULL) {
715 		return (Py_BuildValue("i", BE_PY_ERR_NVLIST));
716 	}
717 
718 	ret = be_rollback(beAttrs);
719 	nvlist_free(beAttrs);
720 	return (Py_BuildValue("i", ret));
721 }
722 
723 /*
724  * Function:    bePrintErrors
725  * Description: Convert Python args to boolean and call libbe_print_errors to
726  *			turn on/off error output for the library.
727  * Parameter:
728  *   args -     pointer to a python object containing:
729  *		print_errors - Boolean that turns library error
730  *			       printing on or off.
731  * Parameters:
732  *   args -     pointer to a python object containing:
733  *     0 - do not print errors - Python boolean "False"
734  *     1 - print errors - Python boolean "True"
735  *
736  * Returns 1 on missing or invalid argument, 0 otherwise
737  * Scope:
738  *      Public
739  */
740 /* ARGSUSED */
741 PyObject *
742 bePrintErrors(PyObject *self, PyObject *args)
743 {
744 	int		print_errors;
745 
746 	if (!PyArg_ParseTuple(args, "i", &print_errors) ||
747 	    (print_errors != 1 && print_errors != 0))
748 		return (Py_BuildValue("i", BE_PY_ERR_PRINT_ERR));
749 	libbe_print_errors(print_errors == 1);
750 	return (Py_BuildValue("i", BE_PY_SUCCESS));
751 }
752 
753 /*
754  * Function:    beGetErrDesc
755  * Description: Convert Python args to an int and call be_err_to_str to
756  *			map an error code to an error string.
757  * Parameter:
758  *   args -     pointer to a python object containing:
759  *		errCode - value to map to an error string.
760  *
761  * Returns: error string or NULL
762  * Scope:
763  *      Public
764  */
765 /* ARGSUSED */
766 PyObject *
767 beGetErrDesc(PyObject *self, PyObject *args)
768 {
769 	int	errCode = 0;
770 	char	*beErrStr = NULL;
771 
772 	if (!PyArg_ParseTuple(args, "i", &errCode)) {
773 		return (Py_BuildValue("s", NULL));
774 	}
775 
776 	/*
777 	 * First check libbe_py errors. If NULL is returned check error codes
778 	 * in libbe.
779 	 */
780 
781 	if ((beErrStr = beMapLibbePyErrorToString(errCode)) == NULL) {
782 		beErrStr = be_err_to_str(errCode);
783 	}
784 
785 	return (Py_BuildValue("s", beErrStr));
786 }
787 
788 /*
789  * Function:    beVerifyBEName
790  * Description: Call be_valid_be_name() to verify the BE name.
791  * Parameter:
792  *   args -     pointer to a python object containing:
793  *		string - value to map to a string.
794  *
795  * Returns:  0 for success or 1 for failure
796  * Scope:
797  *      Public
798  */
799 /* ARGSUSED */
800 PyObject *
801 beVerifyBEName(PyObject *self, PyObject *args)
802 {
803 	char	*string = NULL;
804 
805 	if (!PyArg_ParseTuple(args, "s", &string)) {
806 		return (Py_BuildValue("i", 1));
807 	}
808 
809 	if (be_valid_be_name(string)) {
810 		return (Py_BuildValue("i", 0));
811 	} else {
812 		return (Py_BuildValue("i", 1));
813 	}
814 }
815 
816 /* ~~~~~~~~~~~~~~~~~ */
817 /* Private Functions */
818 /* ~~~~~~~~~~~~~~~~~ */
819 
820 static boolean_t
821 convertBEInfoToDictionary(be_node_list_t *be, PyObject **listDict)
822 {
823 	if (be->be_node_name != NULL) {
824 		if (PyDict_SetItemString(*listDict, BE_ATTR_ORIG_BE_NAME,
825 		    PyString_FromString(be->be_node_name)) != 0) {
826 			return (B_FALSE);
827 		}
828 	}
829 
830 	if (be->be_rpool != NULL) {
831 		if (PyDict_SetItemString(*listDict, BE_ATTR_ORIG_BE_POOL,
832 		    PyString_FromString(be->be_rpool)) != 0) {
833 			return (B_FALSE);
834 		}
835 	}
836 
837 	if (be->be_mntpt != NULL) {
838 		if (PyDict_SetItemString(*listDict, BE_ATTR_MOUNTPOINT,
839 		    PyString_FromString(be->be_mntpt)) != 0) {
840 			return (B_FALSE);
841 		}
842 	}
843 
844 	if (PyDict_SetItemString(*listDict, BE_ATTR_MOUNTED,
845 	    (be->be_mounted ? Py_True : Py_False)) != 0) {
846 		return (B_FALSE);
847 	}
848 
849 	if (PyDict_SetItemString(*listDict, BE_ATTR_ACTIVE,
850 	    (be->be_active ? Py_True : Py_False)) != 0) {
851 		return (B_FALSE);
852 	}
853 
854 	if (PyDict_SetItemString(*listDict, BE_ATTR_ACTIVE_ON_BOOT,
855 	    (be->be_active_on_boot ? Py_True : Py_False)) != 0) {
856 		return (B_FALSE);
857 	}
858 
859 	if (be->be_space_used != 0) {
860 		if (PyDict_SetItemString(*listDict, BE_ATTR_SPACE,
861 		    PyLong_FromUnsignedLongLong(be->be_space_used)) != 0) {
862 			return (B_FALSE);
863 		}
864 	}
865 
866 	if (be->be_root_ds != NULL) {
867 		if (PyDict_SetItemString(*listDict, BE_ATTR_ROOT_DS,
868 		    PyString_FromString(be->be_root_ds)) != 0) {
869 			return (B_FALSE);
870 		}
871 	}
872 
873 	if (be->be_node_creation != NULL) {
874 		if (PyDict_SetItemString(*listDict, BE_ATTR_DATE,
875 		    PyLong_FromLong(be->be_node_creation)) != 0) {
876 			return (B_FALSE);
877 		}
878 	}
879 
880 	if (be->be_policy_type != NULL) {
881 		if (PyDict_SetItemString(*listDict, BE_ATTR_POLICY,
882 		    PyString_FromString(be->be_policy_type)) != 0) {
883 			return (B_FALSE);
884 		}
885 	}
886 
887 	if (be->be_uuid_str != NULL) {
888 		if (PyDict_SetItemString(*listDict, BE_ATTR_UUID_STR,
889 		    PyString_FromString(be->be_uuid_str)) != 0) {
890 			return (B_FALSE);
891 		}
892 	}
893 
894 	return (B_TRUE);
895 }
896 
897 static boolean_t
898 convertDatasetInfoToDictionary(be_dataset_list_t *ds, PyObject **listDict)
899 {
900 	if (ds->be_dataset_name != NULL) {
901 		if (PyDict_SetItemString(*listDict, BE_ATTR_DATASET,
902 		    PyString_FromString(ds->be_dataset_name)) != 0) {
903 			return (B_FALSE);
904 		}
905 	}
906 
907 	if (PyDict_SetItemString(*listDict, BE_ATTR_STATUS,
908 	    (ds->be_ds_mounted ? Py_True : Py_False)) != 0) {
909 			return (B_FALSE);
910 	}
911 
912 	if (ds->be_ds_mntpt != NULL) {
913 		if (PyDict_SetItemString(*listDict, BE_ATTR_MOUNTPOINT,
914 		    PyString_FromString(ds->be_ds_mntpt)) != 0) {
915 			return (B_FALSE);
916 		}
917 	}
918 
919 	if (PyDict_SetItemString(*listDict, BE_ATTR_MOUNTED,
920 	    (ds->be_ds_mounted ? Py_True : Py_False)) != 0) {
921 		return (B_FALSE);
922 	}
923 
924 	if (ds->be_ds_space_used != 0) {
925 		if (PyDict_SetItemString(*listDict, BE_ATTR_SPACE,
926 		    PyLong_FromUnsignedLongLong(ds->be_ds_space_used))
927 		    != 0) {
928 			return (B_FALSE);
929 		}
930 	}
931 
932 	if (ds->be_dataset_name != 0) {
933 		if (PyDict_SetItemString(*listDict, BE_ATTR_DATASET,
934 		    PyString_FromString(ds->be_dataset_name)) != 0) {
935 			return (B_FALSE);
936 		}
937 	}
938 
939 	if (ds->be_ds_plcy_type != NULL) {
940 		if (PyDict_SetItemString(*listDict, BE_ATTR_POLICY,
941 		    PyString_FromString(ds->be_ds_plcy_type)) != 0) {
942 			return (B_FALSE);
943 		}
944 	}
945 
946 	if (ds->be_ds_creation != NULL) {
947 		if (PyDict_SetItemString(*listDict, BE_ATTR_DATE,
948 		    PyLong_FromLong(ds->be_ds_creation)) != 0) {
949 			return (B_FALSE);
950 		}
951 	}
952 
953 	return (B_TRUE);
954 }
955 
956 static boolean_t
957 convertSnapshotInfoToDictionary(be_snapshot_list_t *ss, PyObject **listDict)
958 {
959 	if (ss->be_snapshot_name != NULL) {
960 		if (PyDict_SetItemString(*listDict, BE_ATTR_SNAP_NAME,
961 		    PyString_FromString(ss->be_snapshot_name)) != 0) {
962 			return (B_FALSE);
963 		}
964 	}
965 
966 	if (ss->be_snapshot_creation != NULL) {
967 		if (PyDict_SetItemString(*listDict, BE_ATTR_DATE,
968 		    PyLong_FromLong(ss->be_snapshot_creation)) != 0) {
969 			return (B_FALSE);
970 		}
971 	}
972 
973 	if (ss->be_snapshot_type != NULL) {
974 		if (PyDict_SetItemString(*listDict, BE_ATTR_POLICY,
975 		    PyString_FromString(ss->be_snapshot_type)) != 0) {
976 			return (B_FALSE);
977 		}
978 	}
979 
980 	if (ss->be_snapshot_space_used != 0) {
981 		if (PyDict_SetItemString(*listDict, BE_ATTR_SPACE,
982 		    PyLong_FromUnsignedLongLong(ss->be_snapshot_space_used))
983 		    != 0) {
984 			return (B_FALSE);
985 		}
986 	}
987 
988 	return (B_TRUE);
989 }
990 
991 /*
992  * Convert string arguments to nvlist attributes
993  */
994 
995 static boolean_t
996 convertPyArgsToNvlist(nvlist_t **nvList, int numArgs, ...)
997 {
998 	char *pt, *pt2;
999 	va_list ap;
1000 	int i;
1001 
1002 	if (*nvList == NULL) {
1003 		if (nvlist_alloc(nvList, NV_UNIQUE_NAME, 0) != 0) {
1004 			(void) printf("nvlist_alloc failed.\n");
1005 			return (B_FALSE);
1006 		}
1007 	}
1008 
1009 	va_start(ap, numArgs);
1010 
1011 	for (i = 0; i < numArgs; i += 2) {
1012 		if ((pt = va_arg(ap, char *)) == NULL ||
1013 		    (pt2 = va_arg(ap, char *)) == NULL) {
1014 			continue;
1015 		}
1016 		if (nvlist_add_string(*nvList, pt, pt2) != 0) {
1017 			(void) printf("nvlist_add_string failed for %s (%s).\n",
1018 			    pt, pt2);
1019 			nvlist_free(*nvList);
1020 			return (B_FALSE);
1021 		}
1022 	}
1023 
1024 	va_end(ap);
1025 
1026 	return (B_TRUE);
1027 }
1028 
1029 /*
1030  * Function:    beMapLibbePyErrorToString
1031  * Description: Convert Python args to an int and map an error code to an
1032  *			error string.
1033  * Parameter:
1034  *		errCode - value to map to an error string.
1035  *
1036  * Returns error string or NULL
1037  * Scope:
1038  *      Public
1039  */
1040 
1041 char *
1042 beMapLibbePyErrorToString(int errCode)
1043 {
1044 	switch (errCode) {
1045 	case BE_PY_ERR_APPEND:
1046 		return ("Unable to append a dictionary to a list "
1047 		    "of dictinaries.");
1048 	case BE_PY_ERR_DICT:
1049 		return ("Creation of a Python dictionary failed.");
1050 	case BE_PY_ERR_LIST:
1051 		return ("beList() failed.");
1052 	case BE_PY_ERR_NVLIST:
1053 		return ("An nvlist operation failed.");
1054 	case BE_PY_ERR_PARSETUPLE:
1055 		return ("PyArg_ParseTuple() failed to convert variable to C.");
1056 	case BE_PY_ERR_PRINT_ERR:
1057 		return ("bePrintErrors() failed.");
1058 	case BE_PY_ERR_VAR_CONV:
1059 		return ("Unable to add variables to a Python dictionary.");
1060 	default:
1061 		return (NULL);
1062 	}
1063 }
1064 
1065 /* Private python initialization structure */
1066 
1067 static struct PyMethodDef libbeMethods[] = {
1068 	{"beCopy", (PyCFunction)beCopy, METH_VARARGS, "Create/Copy a BE."},
1069 	{"beCreateSnapshot", (PyCFunction)beCreateSnapshot, METH_VARARGS,
1070 	    "Create a snapshot."},
1071 	{"beDestroy", (PyCFunction)beDestroy, METH_VARARGS, "Destroy a BE."},
1072 	{"beDestroySnapshot", (PyCFunction)beDestroySnapshot, METH_VARARGS,
1073 	    "Destroy a snapshot."},
1074 	{"beMount", (PyCFunction)beMount, METH_VARARGS, "Mount a BE."},
1075 	{"beUnmount", (PyCFunction)beUnmount, METH_VARARGS, "Unmount a BE."},
1076 	{"beList", (PyCFunction)beList, METH_VARARGS, "List BE info."},
1077 	{"beRename", (PyCFunction)beRename, METH_VARARGS, "Rename a BE."},
1078 	{"beActivate", (PyCFunction)beActivate, METH_VARARGS, "Activate a BE."},
1079 	{"beRollback", (PyCFunction)beRollback, METH_VARARGS, "Rollback a BE."},
1080 	{"bePrintErrors", (PyCFunction)bePrintErrors, METH_VARARGS,
1081 	    "Enable/disable error printing."},
1082 	{"beGetErrDesc", (PyCFunction)beGetErrDesc, METH_VARARGS,
1083 	    "Map Error codes to strings."},
1084 	{"beVerifyBEName", (PyCFunction)beVerifyBEName, METH_VARARGS,
1085 	    "Verify BE name."},
1086 	{NULL, NULL, 0, NULL}
1087 };
1088 
1089 void
1090 initlibbe_py()
1091 {
1092 	/* PyMODINIT_FUNC; */
1093 	(void) Py_InitModule("libbe_py", libbeMethods);
1094 }
1095