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