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