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