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 *
beCreateSnapshot(PyObject * self,PyObject * args)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 *
beCopy(PyObject * self,PyObject * args)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 *
beList(PyObject * self,PyObject * args)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 *
beActivate(PyObject * self,PyObject * args)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 *
beDestroy(PyObject * self,PyObject * args)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 *
beDestroySnapshot(PyObject * self,PyObject * args)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 *
beRename(PyObject * self,PyObject * args)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 *
beMount(PyObject * self,PyObject * args)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 *
beUnmount(PyObject * self,PyObject * args)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 *
beRollback(PyObject * self,PyObject * args)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 *
bePrintErrors(PyObject * self,PyObject * args)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 *
beGetErrDesc(PyObject * self,PyObject * args)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 *
beVerifyBEName(PyObject * self,PyObject * args)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
convertBEInfoToDictionary(be_node_list_t * be,PyObject ** listDict)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
convertDatasetInfoToDictionary(be_dataset_list_t * ds,PyObject ** listDict)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
convertSnapshotInfoToDictionary(be_snapshot_list_t * ss,PyObject ** listDict)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
convertPyArgsToNvlist(nvlist_t ** nvList,int numArgs,...)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 *
beMapLibbePyErrorToString(int errCode)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
initlibbe_py()1090 initlibbe_py()
1091 {
1092 /* PyMODINIT_FUNC; */
1093 (void) Py_InitModule("libbe_py", libbeMethods);
1094 }
1095