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