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