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