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