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