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 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 (PyDict_SetItemString(*listDict, BE_ATTR_GLOBAL_ACTIVE, 861 (be->be_global_active ? Py_True : Py_False)) != 0) { 862 return (B_FALSE); 863 } 864 865 if (be->be_space_used != 0) { 866 if (PyDict_SetItemString(*listDict, BE_ATTR_SPACE, 867 PyLong_FromUnsignedLongLong(be->be_space_used)) != 0) { 868 return (B_FALSE); 869 } 870 } 871 872 if (be->be_root_ds != NULL) { 873 if (PyDict_SetItemString(*listDict, BE_ATTR_ROOT_DS, 874 PyString_FromString(be->be_root_ds)) != 0) { 875 return (B_FALSE); 876 } 877 } 878 879 if (be->be_node_creation != NULL) { 880 if (PyDict_SetItemString(*listDict, BE_ATTR_DATE, 881 PyLong_FromLong(be->be_node_creation)) != 0) { 882 return (B_FALSE); 883 } 884 } 885 886 if (be->be_policy_type != NULL) { 887 if (PyDict_SetItemString(*listDict, BE_ATTR_POLICY, 888 PyString_FromString(be->be_policy_type)) != 0) { 889 return (B_FALSE); 890 } 891 } 892 893 if (be->be_uuid_str != NULL) { 894 if (PyDict_SetItemString(*listDict, BE_ATTR_UUID_STR, 895 PyString_FromString(be->be_uuid_str)) != 0) { 896 return (B_FALSE); 897 } 898 } 899 900 return (B_TRUE); 901 } 902 903 static boolean_t 904 convertDatasetInfoToDictionary(be_dataset_list_t *ds, PyObject **listDict) 905 { 906 if (ds->be_dataset_name != NULL) { 907 if (PyDict_SetItemString(*listDict, BE_ATTR_DATASET, 908 PyString_FromString(ds->be_dataset_name)) != 0) { 909 return (B_FALSE); 910 } 911 } 912 913 if (PyDict_SetItemString(*listDict, BE_ATTR_STATUS, 914 (ds->be_ds_mounted ? Py_True : Py_False)) != 0) { 915 return (B_FALSE); 916 } 917 918 if (ds->be_ds_mntpt != NULL) { 919 if (PyDict_SetItemString(*listDict, BE_ATTR_MOUNTPOINT, 920 PyString_FromString(ds->be_ds_mntpt)) != 0) { 921 return (B_FALSE); 922 } 923 } 924 925 if (PyDict_SetItemString(*listDict, BE_ATTR_MOUNTED, 926 (ds->be_ds_mounted ? Py_True : Py_False)) != 0) { 927 return (B_FALSE); 928 } 929 930 if (ds->be_ds_space_used != 0) { 931 if (PyDict_SetItemString(*listDict, BE_ATTR_SPACE, 932 PyLong_FromUnsignedLongLong(ds->be_ds_space_used)) 933 != 0) { 934 return (B_FALSE); 935 } 936 } 937 938 if (ds->be_dataset_name != 0) { 939 if (PyDict_SetItemString(*listDict, BE_ATTR_DATASET, 940 PyString_FromString(ds->be_dataset_name)) != 0) { 941 return (B_FALSE); 942 } 943 } 944 945 if (ds->be_ds_plcy_type != NULL) { 946 if (PyDict_SetItemString(*listDict, BE_ATTR_POLICY, 947 PyString_FromString(ds->be_ds_plcy_type)) != 0) { 948 return (B_FALSE); 949 } 950 } 951 952 if (ds->be_ds_creation != NULL) { 953 if (PyDict_SetItemString(*listDict, BE_ATTR_DATE, 954 PyLong_FromLong(ds->be_ds_creation)) != 0) { 955 return (B_FALSE); 956 } 957 } 958 959 return (B_TRUE); 960 } 961 962 static boolean_t 963 convertSnapshotInfoToDictionary(be_snapshot_list_t *ss, PyObject **listDict) 964 { 965 if (ss->be_snapshot_name != NULL) { 966 if (PyDict_SetItemString(*listDict, BE_ATTR_SNAP_NAME, 967 PyString_FromString(ss->be_snapshot_name)) != 0) { 968 return (B_FALSE); 969 } 970 } 971 972 if (ss->be_snapshot_creation != NULL) { 973 if (PyDict_SetItemString(*listDict, BE_ATTR_DATE, 974 PyLong_FromLong(ss->be_snapshot_creation)) != 0) { 975 return (B_FALSE); 976 } 977 } 978 979 if (ss->be_snapshot_type != NULL) { 980 if (PyDict_SetItemString(*listDict, BE_ATTR_POLICY, 981 PyString_FromString(ss->be_snapshot_type)) != 0) { 982 return (B_FALSE); 983 } 984 } 985 986 if (ss->be_snapshot_space_used != 0) { 987 if (PyDict_SetItemString(*listDict, BE_ATTR_SPACE, 988 PyLong_FromUnsignedLongLong(ss->be_snapshot_space_used)) 989 != 0) { 990 return (B_FALSE); 991 } 992 } 993 994 return (B_TRUE); 995 } 996 997 /* 998 * Convert string arguments to nvlist attributes 999 */ 1000 1001 static boolean_t 1002 convertPyArgsToNvlist(nvlist_t **nvList, int numArgs, ...) 1003 { 1004 char *pt, *pt2; 1005 va_list ap; 1006 int i; 1007 1008 if (*nvList == NULL) { 1009 if (nvlist_alloc(nvList, NV_UNIQUE_NAME, 0) != 0) { 1010 (void) printf("nvlist_alloc failed.\n"); 1011 return (B_FALSE); 1012 } 1013 } 1014 1015 va_start(ap, numArgs); 1016 1017 for (i = 0; i < numArgs; i += 2) { 1018 if ((pt = va_arg(ap, char *)) == NULL || 1019 (pt2 = va_arg(ap, char *)) == NULL) { 1020 continue; 1021 } 1022 if (nvlist_add_string(*nvList, pt, pt2) != 0) { 1023 (void) printf("nvlist_add_string failed for %s (%s).\n", 1024 pt, pt2); 1025 nvlist_free(*nvList); 1026 return (B_FALSE); 1027 } 1028 } 1029 1030 va_end(ap); 1031 1032 return (B_TRUE); 1033 } 1034 1035 /* 1036 * Function: beMapLibbePyErrorToString 1037 * Description: Convert Python args to an int and map an error code to an 1038 * error string. 1039 * Parameter: 1040 * errCode - value to map to an error string. 1041 * 1042 * Returns error string or NULL 1043 * Scope: 1044 * Public 1045 */ 1046 1047 char * 1048 beMapLibbePyErrorToString(int errCode) 1049 { 1050 switch (errCode) { 1051 case BE_PY_ERR_APPEND: 1052 return ("Unable to append a dictionary to a list " 1053 "of dictinaries."); 1054 case BE_PY_ERR_DICT: 1055 return ("Creation of a Python dictionary failed."); 1056 case BE_PY_ERR_LIST: 1057 return ("beList() failed."); 1058 case BE_PY_ERR_NVLIST: 1059 return ("An nvlist operation failed."); 1060 case BE_PY_ERR_PARSETUPLE: 1061 return ("PyArg_ParseTuple() failed to convert variable to C."); 1062 case BE_PY_ERR_PRINT_ERR: 1063 return ("bePrintErrors() failed."); 1064 case BE_PY_ERR_VAR_CONV: 1065 return ("Unable to add variables to a Python dictionary."); 1066 default: 1067 return (NULL); 1068 } 1069 } 1070 1071 /* Private python initialization structure */ 1072 1073 static struct PyMethodDef libbeMethods[] = { 1074 {"beCopy", (PyCFunction)beCopy, METH_VARARGS, "Create/Copy a BE."}, 1075 {"beCreateSnapshot", (PyCFunction)beCreateSnapshot, METH_VARARGS, 1076 "Create a snapshot."}, 1077 {"beDestroy", (PyCFunction)beDestroy, METH_VARARGS, "Destroy a BE."}, 1078 {"beDestroySnapshot", (PyCFunction)beDestroySnapshot, METH_VARARGS, 1079 "Destroy a snapshot."}, 1080 {"beMount", (PyCFunction)beMount, METH_VARARGS, "Mount a BE."}, 1081 {"beUnmount", (PyCFunction)beUnmount, METH_VARARGS, "Unmount a BE."}, 1082 {"beList", (PyCFunction)beList, METH_VARARGS, "List BE info."}, 1083 {"beRename", (PyCFunction)beRename, METH_VARARGS, "Rename a BE."}, 1084 {"beActivate", (PyCFunction)beActivate, METH_VARARGS, "Activate a BE."}, 1085 {"beRollback", (PyCFunction)beRollback, METH_VARARGS, "Rollback a BE."}, 1086 {"bePrintErrors", (PyCFunction)bePrintErrors, METH_VARARGS, 1087 "Enable/disable error printing."}, 1088 {"beGetErrDesc", (PyCFunction)beGetErrDesc, METH_VARARGS, 1089 "Map Error codes to strings."}, 1090 {"beVerifyBEName", (PyCFunction)beVerifyBEName, METH_VARARGS, 1091 "Verify BE name."}, 1092 {NULL, NULL, 0, NULL} 1093 }; 1094 1095 void 1096 initlibbe_py() 1097 { 1098 /* PyMODINIT_FUNC; */ 1099 (void) Py_InitModule("libbe_py", libbeMethods); 1100 } 1101