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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <libgen.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <sys/nvpair.h> 30 #include <door.h> 31 #include <fcntl.h> 32 33 #include "mms_mgmt.h" 34 #include "mgmt_acsls.h" 35 #include "mmp_defs.h" 36 #include "mgmt_media.h" 37 #include "mgmt_sym.h" 38 #include "mgmt_util.h" 39 40 static char *_SrcFile = __FILE__; 41 #define HERE _SrcFile, __LINE__ 42 43 static char *mmsmntdoor = "/var/run/mmsmnt_door"; 44 45 static int voltype_in_use(void *session, char *voltype); 46 static int 47 mgmt_show_mmvols(void *session, char *pcl, char *library, nvlist_t **vols); 48 static int 49 mgmt_show_partition(void *session, char *pcl, char *library, nvlist_t **parts); 50 static int call_mmsmnt(door_arg_t *arg); 51 52 static char *label_fname = " "; 53 static mms_mgmt_setopt_t cartridgegrpopts[] = { 54 {O_NAME, "CartridgeGroupName", NULL, B_TRUE, NULL}, 55 {NULL, NULL, NULL, B_FALSE, NULL} 56 }; 57 #define CGOPT_COUNT sizeof (cartridgegrpopts) / sizeof (mms_mgmt_setopt_t) 58 59 /* 60 * Note that O_APPS (string array) is required for CartridgeGroupApplication. 61 * Add a CGA for each application specified in the array. 62 */ 63 static mms_mgmt_setopt_t cgappopts[] = { 64 {O_NAME, "CartridgeGroupName", NULL, B_TRUE, NULL}, 65 {O_APPS, "ApplicationName", NULL, B_TRUE, NULL}, 66 {NULL, NULL, NULL, B_FALSE, NULL} 67 }; 68 #define CGAOPT_COUNT sizeof (cgappopts) / sizeof (mms_mgmt_setopt_t) 69 70 /* 71 * mms_mgmt_discover_media() 72 * 73 * Finds ACSLS media, optionally filtered by library acs & lsm. 74 * Those already configured for use with MMS are filtered out unless 75 * 'showall' is TRUE. 76 * 77 * Required opts are: 78 * acshost 79 * acsport (if not the default) 80 * -- or -- 81 * library 82 * If library specified, get ACS information from LIBRARY object. 83 */ 84 int 85 mms_mgmt_discover_media( 86 void *session, boolean_t showall, nvlist_t *opts, mms_list_t *vol_list, 87 nvlist_t *errs) 88 { 89 int st; 90 mms_acslib_t *lsm = NULL; 91 mms_acslib_t *nlsm = NULL; 92 mms_acscart_t *vol = NULL; 93 mms_acscart_t *nvol = NULL; 94 mms_list_t lib_list; 95 char *acshost = NULL; 96 char *val = NULL; 97 char **in_libs = NULL; 98 int count = 0; 99 void *sess = NULL; 100 void *sessp = session; 101 boolean_t found; 102 int i; 103 char tid[64]; 104 char cmd[8192]; 105 void *response; 106 nvlist_t *volattrs = NULL; 107 nvlist_t *avl = NULL; 108 int ost; 109 110 if (!opts || !vol_list) { 111 return (MMS_MGMT_NOARG); 112 } 113 114 (void) memset(vol_list, 0, sizeof (mms_list_t)); 115 116 /* 117 * we need either the ACSLS host or one or more libraries to 118 * proceed. 119 */ 120 (void) nvlist_lookup_string(opts, O_ACSHOST, &acshost); 121 in_libs = mgmt_var_to_array(opts, O_MMSLIB, &count); 122 123 if (!acshost && !in_libs) { 124 st = ENOENT; 125 MGMT_ADD_OPTERR(errs, O_ACSHOST, st); 126 MGMT_ADD_OPTERR(errs, O_MMSLIB, st); 127 128 return (st); 129 } 130 131 if (session == NULL) { 132 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 133 if (st == 0) { 134 sessp = sess; 135 } else { 136 return (st); 137 } 138 } 139 140 /* get list of libs MMS knows about */ 141 st = mms_get_library(sessp, B_FALSE, &lib_list); 142 if (st != 0) { 143 goto done; 144 } 145 146 if (!acshost) { 147 /* only supporting a single ACSLS server for V1 */ 148 lsm = mms_list_head(&lib_list); 149 if (lsm == NULL) { 150 st = ENOENT; 151 MGMT_ADD_OPTERR(errs, O_ACSHOST, st); 152 goto done; 153 } 154 acshost = lsm->acshost; 155 } 156 157 if (count > 0) { 158 /* remove libraries not in our list */ 159 lsm = mms_list_head(&lib_list); 160 while (lsm != NULL) { 161 nlsm = mms_list_next(&lib_list, lsm); 162 found = B_FALSE; 163 164 for (i = 0; i < count; i++) { 165 if (strcmp(in_libs[i], lsm->name) == 0) { 166 found = B_TRUE; 167 break; 168 } 169 } 170 if (!found) { 171 /* remove */ 172 mms_list_remove(&lib_list, lsm); 173 free(lsm); 174 } 175 lsm = nlsm; 176 } 177 } 178 179 /* all of the volumes from the ACSLS server */ 180 st = get_acs_volumes(acshost, NULL, vol_list); 181 if (st != 0) { 182 goto done; 183 } 184 185 /* weed out volumes for libraries we're not interested in */ 186 vol = mms_list_head(vol_list); 187 while (vol != NULL) { 188 nvol = mms_list_next(vol_list, vol); 189 found = B_FALSE; 190 191 mms_list_foreach(&lib_list, lsm) { 192 if (strcmp(lsm->type, "DISK") == 0) { 193 continue; 194 } 195 if ((lsm->acs == vol->libacs) && 196 (lsm->lsm == vol->liblsm)) { 197 found = B_TRUE; 198 break; 199 } 200 } 201 if (!found) { 202 mms_list_remove(vol_list, vol); 203 free(vol); 204 } else { 205 if (lsm->name[0] != '\0') { 206 (void) strlcpy(vol->libname, lsm->name, 207 sizeof (vol->libname)); 208 } 209 } 210 vol = nvol; 211 } 212 213 /* fetch the list of cartridges MMS knows about */ 214 (void) mms_gen_taskid(tid); 215 216 (void) snprintf(cmd, sizeof (cmd), 217 "show task['%s'] reportmode[namevalue] " 218 "report[CARTRIDGE.'CartridgePCL' CARTRIDGE.'CartridgeTypeName' " 219 "CARTRIDGE.'LibraryName' CARTRIDGE.'CartridgeGroupName'] ", tid); 220 221 if (count > 0) { 222 (void) strlcat(cmd, "match [or ", sizeof (cmd)); 223 for (i = 0; i < count; i++) { 224 if (in_libs[i] == NULL) { 225 continue; 226 } 227 (void) strlcat(cmd, "streq(LIBRARY.'LibraryName' ", 228 sizeof (cmd)); 229 (void) strlcat(cmd, "'", sizeof (cmd)); 230 (void) strlcat(cmd, in_libs[i], sizeof (cmd)); 231 (void) strlcat(cmd, "') ", sizeof (cmd)); 232 } 233 (void) strlcat(cmd, "]", sizeof (cmd)); 234 } 235 (void) strlcat(cmd, ";", sizeof (cmd)); 236 237 st = mms_mgmt_send_cmd(sessp, tid, cmd, "list volumes", &response); 238 if (st == 0) { 239 st = mmp_get_nvattrs("volid", B_TRUE, response, &volattrs); 240 mms_free_rsp(response); 241 } 242 243 if (st != 0) { 244 goto done; 245 } 246 247 /* 248 * TODO: this will break horribly if barcodes are not unique for 249 * all libs. Fix this to be more library-aware. 250 */ 251 vol = mms_list_head(vol_list); 252 while (vol != NULL) { 253 nvol = mms_list_next(vol_list, vol); 254 255 ost = nvlist_lookup_nvlist(volattrs, vol->label, &avl); 256 if (ost == 0) { 257 if (!showall) { 258 mms_list_remove(vol_list, vol); 259 } else { 260 ost = nvlist_lookup_string(avl, 261 O_MPOOL, &val); 262 if (ost == 0) { 263 (void) strlcpy(vol->groupname, val, 264 sizeof (vol->groupname)); 265 } 266 } 267 } 268 vol = nvol; 269 } 270 271 done: 272 mgmt_free_str_arr(in_libs, count); 273 274 if (volattrs) { 275 nvlist_free(volattrs); 276 } 277 278 free_acslib_list(&lib_list); 279 280 if (st != 0) { 281 mms_list_free_and_destroy(vol_list, free); 282 vol_list = NULL; 283 } 284 285 return (st); 286 } 287 288 int 289 mms_mgmt_add_mpool(void *session, nvlist_t *nvl, nvlist_t *errs) 290 { 291 int st; 292 char **varray = NULL; 293 int count = 0; 294 int i; 295 296 if (!nvl) { 297 return (MMS_MGMT_NOARG); 298 } 299 300 if (!mgmt_chk_auth("solaris.mms.create")) { 301 return (EACCES); 302 } 303 304 st = mms_add_object(session, "CARTRIDGEGROUP", cartridgegrpopts, 305 nvl, errs); 306 307 if (st == 0) { 308 /* save original values */ 309 varray = mgmt_var_to_array(nvl, O_APPS, &count); 310 311 for (i = 0; i < count; i++) { 312 if (!varray[i] || (strlen(varray[i]) == 0) || 313 (strcasecmp(varray[i], "none") == 0) || 314 (strcasecmp(varray[i], "all") == 0)) { 315 continue; 316 } 317 318 /* put back a single value */ 319 (void) nvlist_add_string(nvl, O_APPS, varray[i]); 320 st = mms_add_object(session, 321 "CARTRIDGEGROUPAPPLICATION", cgappopts, nvl, errs); 322 if (st != 0) { 323 break; 324 } 325 } 326 327 /* put back original values */ 328 if (varray) { 329 (void) nvlist_add_string_array(nvl, O_APPS, varray, 330 count); 331 mgmt_free_str_arr(varray, count); 332 } 333 } 334 335 return (st); 336 } 337 338 int 339 mms_mgmt_modify_mpool(void *session, nvlist_t *nvl, nvlist_t *errs) 340 { 341 int st; 342 char **varray = NULL; 343 int count = 0; 344 int i; 345 char cmd[8192]; 346 char tid[64]; 347 void *sess = NULL; 348 void *sessp = session; 349 void *response; 350 char *mpool; 351 nvlist_t *cgattrs = NULL; 352 nvlist_t *new = NULL; 353 nvpair_t *nvp; 354 char *val; 355 boolean_t found; 356 357 /* get list of apps, if new list != old list, update */ 358 359 if (!mgmt_chk_auth("solaris.mms.modify")) { 360 return (EACCES); 361 } 362 363 if (!nvl) { 364 return (MMS_MGMT_NOARG); 365 } 366 367 st = nvlist_lookup_string(nvl, O_NAME, &mpool); 368 if (st != 0) { 369 MGMT_ADD_OPTERR(errs, O_NAME, st); 370 return (st); 371 } 372 373 varray = mgmt_var_to_array(nvl, O_APPS, &count); 374 if (varray == NULL) { 375 /* error or nothing to do? */ 376 return (0); 377 } 378 379 /* get list of already-established apps */ 380 (void) mms_gen_taskid(tid); 381 382 (void) snprintf(cmd, sizeof (cmd), 383 "show task['%s'] reportmode[namevalue] " 384 "match[streq(CARTRIDGEGROUPAPPLICATION.'CartridgeGroupName' '%s')] " 385 "report[CARTRIDGEGROUPAPPLICATION.'ApplicationName'];", 386 tid, mpool); 387 388 if (session == NULL) { 389 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 390 if (st != 0) { 391 goto done; 392 } 393 sessp = sess; 394 } 395 396 st = mms_mgmt_send_cmd(sessp, tid, cmd, "modify cartridgegroup", 397 &response); 398 if (st == 0) { 399 st = mmp_get_nvattrs("ApplicationName", B_FALSE, response, 400 &cgattrs); 401 mms_free_rsp(response); 402 } 403 if (st != 0) { 404 goto done; 405 } 406 407 /* see if we need to add any apps */ 408 for (i = 0; i < count; i++) { 409 if (!varray[i] || (strlen(varray[i]) == 0) || 410 (strcasecmp(varray[i], "none") == 0) || 411 (strcasecmp(varray[i], "all") == 0)) { 412 continue; 413 } 414 415 if (!nvlist_exists(cgattrs, varray[i])) { 416 if (!new) { 417 (void) nvlist_alloc(&new, NV_UNIQUE_NAME, 0); 418 (void) nvlist_add_string(new, O_NAME, mpool); 419 } 420 421 (void) nvlist_add_string(new, O_APPS, varray[i]); 422 st = mms_add_object(sessp, "CARTRIDGEGROUPAPPLICATION", 423 cgappopts, new, errs); 424 if (st != 0) { 425 break; 426 } 427 } 428 } 429 430 /* and if we need to remove any */ 431 nvp = NULL; 432 while ((nvp = nvlist_next_nvpair(cgattrs, nvp)) != NULL) { 433 val = nvpair_name(nvp); 434 if (!val) { 435 /* can't happen? */ 436 continue; 437 } 438 439 found = B_FALSE; 440 441 for (i = 0; i < count; i++) { 442 if (strcmp(val, varray[i]) == 0) { 443 found = B_TRUE; 444 break; 445 } 446 } 447 448 if (found) { 449 continue; 450 } 451 452 (void) mms_gen_taskid(tid); 453 (void) snprintf(cmd, sizeof (cmd), 454 "delete task['%s'] type[CARTRIDGEGROUPAPPLICATION] " 455 "match[and " 456 "(streq(CARTRIDGEGROUPAPPLICATION.'CartridgeGroupName' " 457 "'%s') " 458 "streq(CARTRIDGEGROUPAPPLICATION.'ApplicationName' " 459 "'%s'))];", 460 tid, mpool, val); 461 462 st = mms_mgmt_send_cmd(sessp, tid, cmd, "modify cartridgegroup", 463 &response); 464 if (st != 0) { 465 break; 466 } 467 } 468 469 done: 470 471 if (new) { 472 nvlist_free(new); 473 } 474 475 if (cgattrs) { 476 nvlist_free(cgattrs); 477 } 478 479 mgmt_free_str_arr(varray, count); 480 481 if (sess) { 482 (void) mms_goodbye(sess, 0); 483 } 484 485 return (st); 486 } 487 488 /* 489 * verify no cartridges 'allocated' 490 * force? remove cart anyway 491 * remove all carts 492 * remove cartridgegroupapplications 493 * remove cartridgegroup 494 */ 495 int 496 mms_mgmt_remove_mpool(void *session, char *mpool, boolean_t force, 497 nvlist_t *errs) 498 { 499 int st; 500 nvlist_t *nvl = NULL; 501 void *sess = NULL; 502 void *sessp = session; 503 void *response; 504 char tid[64]; 505 char cmd[8192]; 506 507 if (!mpool) { 508 return (MMS_MGMT_NOARG); 509 } 510 511 if (!mgmt_chk_auth("solaris.mms.delete")) { 512 return (EACCES); 513 } 514 515 st = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 516 if (st != 0) { 517 return (st); 518 } 519 520 (void) nvlist_add_string(nvl, O_NAME, mpool); 521 (void) nvlist_add_boolean_value(nvl, O_FORCE, force); 522 (void) nvlist_add_string(nvl, O_VOLUMES, "*"); 523 524 if (!session) { 525 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 526 if (st != 0) { 527 nvlist_free(nvl); 528 return (st); 529 } 530 sessp = sess; 531 } 532 533 st = mms_mgmt_remove_cartridges(sessp, nvl, errs); 534 535 if (st != 0) { 536 goto done; 537 } 538 539 (void) mms_gen_taskid(tid); 540 (void) snprintf(cmd, sizeof (cmd), 541 "delete task['%s'] type[CARTRIDGEGROUPAPPLICATION] " 542 "match[streq" 543 "(CARTRIDGEGROUPAPPLICATION.'CartridgeGroupName' '%s')];", 544 tid, mpool); 545 546 st = mms_mgmt_send_cmd(sessp, tid, cmd, "remove cartridgegroup", 547 &response); 548 if (st != 0) { 549 goto done; 550 } 551 552 (void) mms_gen_taskid(tid); 553 (void) snprintf(cmd, sizeof (cmd), 554 "delete task['%s'] type[CARTRIDGEGROUP] " 555 "match[streq(CARTRIDGEGROUP.'CartridgeGroupName' '%s')];", 556 tid, mpool); 557 558 st = mms_mgmt_send_cmd(sessp, tid, cmd, "remove cartridgegroup", 559 &response); 560 if (st != 0) { 561 goto done; 562 } 563 564 done: 565 if (nvl) { 566 nvlist_free(nvl); 567 } 568 569 return (st); 570 } 571 572 /* ARGSUSED */ 573 int 574 mms_mgmt_remove_dpool(void *session, char *dpool, boolean_t force, 575 nvlist_t *errs) 576 { 577 int st; 578 nvlist_t *nvl = NULL; 579 void *sess = NULL; 580 void *sessp = session; 581 void *response; 582 char tid[64]; 583 char cmd[8192]; 584 585 if (!dpool) { 586 return (MMS_MGMT_NOARG); 587 } 588 589 if (!mgmt_chk_auth("solaris.mms.delete")) { 590 return (EACCES); 591 } 592 593 st = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 594 if (st != 0) { 595 return (st); 596 } 597 598 (void) nvlist_add_string(nvl, O_NAME, dpool); 599 (void) nvlist_add_boolean_value(nvl, O_FORCE, force); 600 601 if (!session) { 602 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 603 if (st != 0) { 604 nvlist_free(nvl); 605 return (st); 606 } 607 sessp = sess; 608 } 609 610 (void) mms_gen_taskid(tid); 611 (void) snprintf(cmd, sizeof (cmd), 612 "delete task['%s'] type[DRIVEGROUPAPPLICATION] " 613 "match[streq" 614 "(DRIVEGROUPAPPLICATION.'DriveGroupName' '%s')];", 615 tid, dpool); 616 617 st = mms_mgmt_send_cmd(sessp, tid, cmd, "remove drivegroup", 618 &response); 619 if (st != 0) { 620 goto done; 621 } 622 623 (void) mms_gen_taskid(tid); 624 (void) snprintf(cmd, sizeof (cmd), 625 "delete task['%s'] type[DRIVEGROUP] " 626 "match[streq(DRIVEGROUP.'DriveGroupName' '%s')];", 627 tid, dpool); 628 629 st = mms_mgmt_send_cmd(sessp, tid, cmd, "remove drivegroup", 630 &response); 631 if (st != 0) { 632 goto done; 633 } 634 635 done: 636 if (nvl) { 637 nvlist_free(nvl); 638 } 639 640 return (st); 641 } 642 643 int 644 mms_mgmt_add_cartridges(void *session, nvlist_t *nvl, nvlist_t *errs) 645 { 646 int st; 647 char *mpool; 648 char **volarr = NULL; 649 char *libname; 650 char *mtype = NULL; 651 int count; 652 int i; 653 char tid[64]; 654 char cmd[8192]; 655 void *sess = NULL; 656 void *sessp = session; 657 mms_list_t lib_list; 658 mms_acslib_t *lsm; 659 char *volstr; 660 mms_list_t vol_list; 661 mms_acscart_t *vol; 662 size_t len = 0; 663 void *response; 664 nvlist_t *cart = NULL; 665 char *volxml = "</token><token>volume</token><token>"; 666 int st_save = 0; 667 char *rwmode = "readwrite"; 668 669 if (!nvl) { 670 return (MMS_MGMT_NOARG); 671 } 672 673 if (!mgmt_chk_auth("solaris.mms.media")) { 674 return (EACCES); 675 } 676 677 (void) memset(&vol_list, 0, sizeof (mms_list_t)); 678 679 st = nvlist_lookup_string(nvl, O_NAME, &mpool); 680 if (st != 0) { 681 MGMT_ADD_OPTERR(errs, O_NAME, st); 682 return (st); 683 } 684 685 st = nvlist_lookup_string(nvl, O_MMSLIB, &libname); 686 if (st != 0) { 687 MGMT_ADD_OPTERR(errs, O_MMSLIB, st); 688 return (st); 689 } 690 691 st = nvlist_lookup_string(nvl, O_VOLTYPE, &mtype); 692 if (st != 0) { 693 MGMT_ADD_OPTERR(errs, O_MTYPE, st); 694 return (st); 695 } 696 697 st = nvlist_lookup_string(nvl, "readonly", &rwmode); 698 if (st == 0) { 699 if (strcmp(rwmode, "true") == 0) { 700 rwmode = "readonly"; 701 } else if (strcmp(rwmode, "false") == 0) { 702 rwmode = "readwrite"; 703 } else { 704 st = MMS_MGMT_INVALID_READONLY; 705 MGMT_ADD_OPTERR(errs, "readonly", st); 706 return (st); 707 } 708 } 709 710 volarr = mgmt_var_to_array(nvl, O_VOLUMES, &count); 711 if (volarr == NULL) { 712 st = ENOENT; 713 MGMT_ADD_OPTERR(errs, O_VOLUMES, st); 714 return (st); 715 } 716 717 if (session == NULL) { 718 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 719 if (st != 0) { 720 mgmt_free_str_arr(volarr, count); 721 return (st); 722 } 723 sessp = sess; 724 } 725 726 /* get the library information */ 727 st = mms_get_library(sessp, B_FALSE, &lib_list); 728 if (st != 0) { 729 goto done; 730 } 731 732 mms_list_foreach(&lib_list, lsm) { 733 if (strcmp(lsm->name, libname) == 0) { 734 break; 735 } 736 } 737 if (lsm == NULL) { 738 st = EINVAL; 739 MGMT_ADD_ERR(errs, O_MMSLIB, st); 740 goto done; 741 } 742 743 /* get the volume info from the ACSLS server */ 744 for (i = 0; i < count; i++) { 745 len += strlen(volarr[i]) + strlen(volxml); 746 747 } 748 len++; /* include trailing nul */ 749 volstr = malloc(len); 750 if (volstr == NULL) { 751 st = ENOMEM; 752 goto done; 753 } 754 volstr[0] = '\0'; 755 for (i = 0; i < count; i++) { 756 if (i > 0) { 757 (void) strlcat(volstr, volxml, len); 758 } 759 (void) strlcat(volstr, volarr[i], len); 760 } 761 762 st = get_acs_volumes(lsm->acshost, volstr, &vol_list); 763 free(volstr); 764 765 if (st != 0) { 766 goto done; 767 } 768 769 /* requested volumes don't appear in the returned list */ 770 if (vol_list.list_size == 0) { 771 st = ENOENT; 772 for (i = 0; i < count; i++) { 773 if (volarr[i]) { 774 MGMT_ADD_ERR(errs, volarr[i], st); 775 } 776 } 777 goto done; 778 } 779 780 /* list to be used when creating PARTITIONs */ 781 st = nvlist_alloc(&cart, NV_UNIQUE_NAME, 0); 782 if (st != 0) { 783 goto done; 784 } 785 /* pre-populate with constant values */ 786 (void) nvlist_add_string(cart, O_MMSLIB, libname); 787 788 for (i = 0; i < count; i++) { 789 mms_list_foreach(&vol_list, vol) { 790 if (strcmp(vol->label, volarr[i]) == 0) { 791 break; 792 } 793 } 794 if (vol == NULL) { 795 /* should never happen */ 796 continue; 797 } 798 799 (void) mms_gen_taskid(tid); 800 (void) snprintf(cmd, sizeof (cmd), 801 "create task['%s'] type[CARTRIDGE] " 802 "set[CARTRIDGE.'CartridgePCL' '%s'] " 803 "set[CARTRIDGE.'CartridgeTypeName' '%s'] " 804 "set[CARTRIDGE.'CartridgeGroupName' '%s'] " 805 "set[CARTRIDGE.'LibraryName' '%s']; ", 806 tid, vol->label, mtype, mpool, libname); 807 808 st = mms_mgmt_send_cmd(sessp, tid, cmd, "add volume", 809 &response); 810 if (st != 0) { 811 MGMT_ADD_ERR(errs, vol->label, st); 812 st_save = MMS_MGMT_CREATE_CART_ERR; 813 continue; 814 } 815 /* create the PARTITION */ 816 (void) nvlist_add_string(cart, O_NAME, vol->label); 817 st = mms_mgmt_create_partition(sessp, 818 vol->label, -1, libname, rwmode, errs); 819 if (st != 0) { 820 MGMT_ADD_ERR(errs, vol->label, st); 821 st_save = MMS_MGMT_CREATE_PART_ERR; 822 mms_mgmt_add_vol_cleanup(sessp, vol->label, libname); 823 break; 824 } 825 } 826 827 done: 828 if (sess) { 829 (void) mms_goodbye(sess, 0); 830 } 831 832 free_acslib_list(&lib_list); 833 mms_list_free_and_destroy(&vol_list, free); 834 mgmt_free_str_arr(volarr, count); 835 836 if (cart) { 837 nvlist_free(cart); 838 } 839 840 return (st_save == 0 ? st : st_save); 841 } 842 843 int 844 mms_mgmt_add_voltype(void *session, nvlist_t *nvl, nvlist_t *errs) 845 { 846 int st; 847 void *sessp = session; 848 void *sess = NULL; 849 void *response = NULL; 850 char tid[64]; 851 char cmd[8192]; 852 nvlist_t *stypes = NULL; 853 nvlist_t *ctypes = NULL; 854 nvlist_t *mnvl = NULL; 855 char *in_ty = NULL; 856 char *in_sz = NULL; 857 char *in_media = NULL; 858 char *val; 859 860 if (!nvl) { 861 return (MMS_MGMT_NOARG); 862 } 863 864 if (!mgmt_chk_auth("solaris.mms.media")) { 865 return (EACCES); 866 } 867 868 st = nvlist_lookup_string(nvl, O_NAME, &in_ty); 869 if (st != 0) { 870 MGMT_ADD_OPTERR(errs, O_NAME, st); 871 return (st); 872 } 873 874 st = nvlist_lookup_string(nvl, O_SIZE, &in_sz); 875 if (st != 0) { 876 MGMT_ADD_OPTERR(errs, O_SIZE, st); 877 return (st); 878 } 879 880 st = nvlist_lookup_string(nvl, O_MTYPE, &in_media); 881 if (st != 0) { 882 MGMT_ADD_OPTERR(errs, O_MTYPE, st); 883 return (st); 884 } 885 886 if (!sessp) { 887 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 888 if (st != 0) { 889 return (st); 890 } 891 sessp = sess; 892 } 893 894 /* see if we've already got this type */ 895 st = mms_mgmt_show_cartridge_type(sessp, in_ty, &stypes); 896 if (st != 0) { 897 goto done; 898 } 899 900 /* we'll get an empty list if it isn't already defined */ 901 st = nvlist_lookup_nvlist(stypes, in_ty, &mnvl); 902 if (st == 0) { 903 /* make sure all attributes match */ 904 val = NULL; 905 (void) nvlist_lookup_string(mnvl, "CartridgeTypeMediaLength", 906 &val); 907 if ((!val) || (strcmp(val, in_sz) != 0)) { 908 st = EINVAL; 909 MGMT_ADD_OPTERR(errs, O_SIZE, st); 910 goto done; 911 } 912 913 val = NULL; 914 (void) nvlist_lookup_string(mnvl, "CartridgeShapeName", &val); 915 if ((!val) || (strcmp(val, in_media) != 0)) { 916 st = EINVAL; 917 MGMT_ADD_OPTERR(errs, O_MTYPE, st); 918 goto done; 919 } 920 921 /* all matched, nothing to do */ 922 goto done; 923 } 924 925 nvlist_free(stypes); 926 stypes = NULL; 927 928 st = mms_mgmt_list_supported_types(sessp, &stypes); 929 if (st != 0) { 930 MGMT_ADD_ERR(errs, "internal error", st); 931 goto done; 932 } 933 934 st = nvlist_lookup_nvlist(stypes, "CARTRIDGE", &ctypes); 935 if (st != 0) { 936 MGMT_ADD_ERR(errs, "internal error", st); 937 goto done; 938 } 939 940 /* make sure requested media type is supported */ 941 st = nvlist_lookup_nvlist(ctypes, in_media, &mnvl); 942 if (st != 0) { 943 if (st == ENOENT) { 944 st = EOPNOTSUPP; 945 } 946 MGMT_ADD_ERR(errs, in_media, st); 947 goto done; 948 } 949 950 /* DISK type may be any size, so set in_sz = 0 */ 951 if (strcmp(in_media, "DISK") == 0) { 952 in_sz = "0"; 953 } 954 955 /* create the new type */ 956 (void) mms_gen_taskid(tid); 957 (void) snprintf(cmd, sizeof (cmd), 958 "create task['%s'] type[CARTRIDGETYPE] " 959 "set[CARTRIDGETYPE.'CartridgeTypeName' '%s'] " 960 "set[CARTRIDGETYPE.'CartridgeTypeNumberSides' '1'] " 961 "set[CARTRIDGETYPE.'CartridgeTypeMediaType' 'data'] " 962 "set[CARTRIDGETYPE.'CartridgeTypeMediaLength' '%s'] " 963 "set[CARTRIDGETYPE.'CartridgeShapeName' '%s'];", 964 tid, in_ty, in_sz, in_media); 965 966 st = mms_mgmt_send_cmd(sessp, tid, cmd, "create cartridge type", 967 &response); 968 969 done: 970 if (sess) { 971 (void) mms_goodbye(sess, 0); 972 } 973 974 if (stypes) { 975 nvlist_free(stypes); 976 } 977 978 return (st); 979 } 980 981 static int 982 voltype_in_use(void *session, char *voltype) 983 { 984 int st; 985 void *sessp = session; 986 void *sess = NULL; 987 void *response = NULL; 988 char tid[64]; 989 char cmd[8192]; 990 nvlist_t *clist = NULL; 991 992 if (!voltype) { 993 return (MMS_MGMT_NOARG); 994 } 995 996 /* first, check to see if any cartridges are using this type */ 997 (void) mms_gen_taskid(tid); 998 (void) snprintf(cmd, sizeof (cmd), 999 "show task['%s'] reportmode[namevalue unique] " 1000 "report[CARTRIDGE.'CartridgeTypeName'] " 1001 "match[streq(CARTRIDGETYPE.'CartridgeTypeName' '%s')];", 1002 tid, voltype); 1003 1004 if (!sessp) { 1005 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1006 if (st != 0) { 1007 return (st); 1008 } 1009 sessp = sess; 1010 } 1011 1012 st = mms_mgmt_send_cmd(sessp, tid, cmd, "check voltype", &response); 1013 if (st == 0) { 1014 st = mmp_get_nvattrs("CartridgeTypeName", B_FALSE, 1015 response, &clist); 1016 mms_free_rsp(response); 1017 } 1018 1019 if (st == 0) { 1020 if (nvlist_exists(clist, voltype)) { 1021 st = EBUSY; 1022 } 1023 } 1024 1025 if (sess) { 1026 (void) mms_goodbye(sess, 0); 1027 } 1028 1029 if (clist) { 1030 nvlist_free(clist); 1031 } 1032 1033 return (st); 1034 } 1035 1036 int 1037 mms_mgmt_remove_voltype(void *session, char *voltype) 1038 { 1039 int st; 1040 void *sessp = session; 1041 void *sess = NULL; 1042 void *response = NULL; 1043 char tid[64]; 1044 char cmd[8192]; 1045 1046 if (!voltype) { 1047 return (MMS_MGMT_NOARG); 1048 } 1049 1050 if (!mgmt_chk_auth("solaris.mms.media")) { 1051 return (EACCES); 1052 } 1053 1054 if (!sessp) { 1055 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1056 if (st != 0) { 1057 return (st); 1058 } 1059 sessp = sess; 1060 } 1061 1062 /* first, check to see if any cartridges are using this type */ 1063 st = voltype_in_use(sessp, voltype); 1064 1065 if (st == 0) { 1066 (void) mms_gen_taskid(tid); 1067 (void) snprintf(cmd, sizeof (cmd), 1068 "delete task['%s'] type[CARTRIDGETYPE] " 1069 "match[streq(CARTRIDGETYPE.'CartridgeTypeName' '%s')];", 1070 tid, voltype); 1071 1072 st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete voltype", 1073 &response); 1074 } 1075 1076 if (sess) { 1077 (void) mms_goodbye(sess, 0); 1078 } 1079 1080 return (st); 1081 } 1082 1083 int 1084 mms_mgmt_modify_voltype(void *session, nvlist_t *nvl, nvlist_t *errs) 1085 { 1086 int st; 1087 void *sessp = session; 1088 void *sess = NULL; 1089 void *response = NULL; 1090 char tid[64]; 1091 char cmd[8192]; 1092 char buf[1024]; 1093 char *vtype = NULL; 1094 char *sz = NULL; 1095 char *mtype = NULL; 1096 1097 if (!nvl) { 1098 return (MMS_MGMT_NOARG); 1099 } 1100 1101 if (!mgmt_chk_auth("solaris.mms.media")) { 1102 return (EACCES); 1103 } 1104 1105 st = nvlist_lookup_string(nvl, O_NAME, &vtype); 1106 if (st != 0) { 1107 MGMT_ADD_OPTERR(errs, O_NAME, st); 1108 return (st); 1109 } 1110 1111 if (!sessp) { 1112 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1113 if (st != 0) { 1114 return (st); 1115 } 1116 sessp = sess; 1117 } 1118 1119 /* first, check to see if any cartridges are using this type */ 1120 st = voltype_in_use(sessp, vtype); 1121 if (st != 0) { 1122 goto done; 1123 } 1124 1125 (void) nvlist_lookup_string(nvl, O_MTYPE, &mtype); 1126 (void) nvlist_lookup_string(nvl, O_SIZE, &sz); 1127 1128 if (!sz && !mtype) { 1129 goto done; 1130 } 1131 1132 (void) mms_gen_taskid(tid); 1133 (void) snprintf(cmd, sizeof (cmd), 1134 "attribute task['%s'] type[CARTRIDGETYPE] " 1135 "match[streq(CARTRIDGETYPE.'CartridgeTypeName' '%s')]", 1136 tid); 1137 1138 if (sz) { 1139 (void) snprintf(buf, sizeof (buf), 1140 " set[CARTRIDGETYPE.'CartridgeTypeMediaLength' '%s']", 1141 sz); 1142 (void) strlcat(cmd, buf, sizeof (cmd)); 1143 } 1144 1145 if (mtype) { 1146 (void) snprintf(buf, sizeof (buf), 1147 "set[CARTRIDGETYPE.'CartridgeShapeName' '%s'];", 1148 mtype); 1149 (void) strlcat(cmd, buf, sizeof (cmd)); 1150 } 1151 1152 (void) strlcat(cmd, ";", sizeof (cmd)); 1153 1154 st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete voltype", &response); 1155 1156 done: 1157 if (sess) { 1158 (void) mms_goodbye(sess, 0); 1159 } 1160 1161 return (st); 1162 } 1163 1164 int 1165 mms_mgmt_show_cartridge_type(void *session, char *voltype, nvlist_t **nvl) 1166 { 1167 int st; 1168 void *sessp = session; 1169 void *sess = NULL; 1170 void *response = NULL; 1171 char tid[64]; 1172 char cmd[8192]; 1173 char buf[1024]; 1174 1175 if (!nvl) { 1176 return (MMS_MGMT_NOARG); 1177 } 1178 1179 /* if voltype is NULL, return a list of all found */ 1180 (void) mms_gen_taskid(tid); 1181 (void) snprintf(cmd, sizeof (cmd), 1182 "show task['%s'] reportmode[namevalue] " 1183 "report[CARTRIDGETYPE]", tid); 1184 1185 if (voltype != NULL) { 1186 (void) snprintf(buf, sizeof (buf), 1187 " match[streq (CARTRIDGETYPE.'CartridgeTypeName' '%s')]", 1188 voltype); 1189 (void) strlcat(cmd, buf, sizeof (cmd)); 1190 } 1191 1192 (void) strlcat(cmd, ";", sizeof (cmd)); 1193 1194 if (!sessp) { 1195 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1196 if (st != 0) { 1197 return (st); 1198 } 1199 sessp = sess; 1200 } 1201 1202 st = mms_mgmt_send_cmd(sessp, tid, cmd, "list cartridgetype", 1203 &response); 1204 if (st == 0) { 1205 st = mmp_get_nvattrs("voltype", B_TRUE, response, nvl); 1206 mms_free_rsp(response); 1207 } 1208 1209 if (sess) { 1210 (void) mms_goodbye(sess, 0); 1211 } 1212 1213 return (st); 1214 } 1215 1216 1217 int 1218 mms_mgmt_remove_cartridges(void *session, nvlist_t *nvl, nvlist_t *errs) 1219 { 1220 int st; 1221 char *mpool; 1222 boolean_t force = B_FALSE; 1223 nvlist_t *vols = NULL; 1224 void *sess = NULL; 1225 void *sessp = session; 1226 void *response; 1227 nvpair_t *nvp; 1228 nvlist_t *vlist; 1229 char *val; 1230 char *vname; 1231 boolean_t skip = B_FALSE; 1232 char tid[64]; 1233 char cmd[8192]; 1234 int skipped = 0; 1235 nvlist_t *pclnv = NULL; 1236 char *lib = NULL; 1237 1238 if (!mgmt_chk_auth("solaris.mms.media")) { 1239 return (EACCES); 1240 } 1241 1242 st = nvlist_lookup_string(nvl, O_NAME, &mpool); 1243 if (st != 0) { 1244 MGMT_ADD_OPTERR(errs, O_NAME, st); 1245 return (st); 1246 } 1247 1248 if (!nvlist_exists(nvl, O_VOLUMES)) { 1249 /* nothing to remove */ 1250 return (0); 1251 } 1252 1253 (void) nvlist_lookup_string(nvl, O_MMSLIB, &lib); 1254 1255 (void) nvlist_lookup_boolean_value(nvl, O_FORCE, &force); 1256 1257 if (!session) { 1258 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1259 if (st != 0) { 1260 return (st); 1261 } 1262 sessp = sess; 1263 } 1264 1265 /* tell the list function not to translate the var names */ 1266 (void) nvlist_add_boolean_value(nvl, "cvt_mmp", B_FALSE); 1267 1268 st = mms_mgmt_list_vols(sessp, nvl, &vols); 1269 if (st != 0) { 1270 goto done; 1271 } 1272 1273 /* Create a temporary nvlist to store PCL & Library */ 1274 st = nvlist_alloc(&pclnv, NV_UNIQUE_NAME, 0); 1275 if (st != 0) { 1276 goto done; 1277 } 1278 (void) nvlist_add_string(pclnv, O_MMSLIB, lib); 1279 1280 /* vols is now a list of the volumes we're supposed to remove */ 1281 nvp = NULL; 1282 1283 while ((nvp = nvlist_next_nvpair(vols, nvp)) != NULL) { 1284 st = nvpair_value_nvlist(nvp, &vlist); 1285 if (st != 0) { 1286 continue; 1287 } 1288 st = nvlist_lookup_string(vlist, "CartridgePCL", &vname); 1289 if (st != 0) { 1290 continue; 1291 } 1292 1293 skip = B_FALSE; 1294 1295 if (!force) { 1296 st = nvlist_lookup_string(vlist, "CartridgeState", 1297 &val); 1298 if (st != 0) { 1299 /* don't remove it if we can't tell state */ 1300 continue; 1301 } 1302 if (strcmp(val, "allocated") == 0) { 1303 /* fail */ 1304 MGMT_ADD_ERR(errs, vname, EBUSY); 1305 skipped++; 1306 skip = B_TRUE; 1307 } 1308 } 1309 1310 if (skip) { 1311 continue; 1312 } 1313 1314 (void) nvlist_add_string(pclnv, O_NAME, vname); 1315 1316 /* remove partitions and vols if necessary */ 1317 st = mms_mgmt_remove_partition(sessp, pclnv, errs); 1318 if (st != 0) { 1319 MGMT_ADD_ERR(errs, vname, st); 1320 continue; 1321 } 1322 1323 (void) mms_gen_taskid(tid); 1324 (void) snprintf(cmd, sizeof (cmd), 1325 "delete task['%s'] type[CARTRIDGE] " 1326 "match[and (streq(CARTRIDGE.'CartridgeGroupName' '%s') " 1327 "streq(CARTRIDGE.'CartridgePCL' '%s'))];", 1328 tid, mpool, vname); 1329 1330 st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete cartridge", 1331 &response); 1332 if (st != 0) { 1333 MGMT_ADD_ERR(errs, vname, st); 1334 continue; 1335 } 1336 1337 /* check for disk cartridges, remove the on-disk files if yes */ 1338 st = nvlist_lookup_string(vlist, "CartridgeTypeName", &val); 1339 if (st == 0) { 1340 if (strcmp(val, "DISK") == 0) { 1341 char *mntp = NULL; 1342 char *rpath = NULL; 1343 1344 (void) nvlist_lookup_string(vlist, 1345 "CartridgeMountPoint", &mntp); 1346 (void) nvlist_lookup_string(vlist, 1347 "CartridgePath", &rpath); 1348 if (!mntp || !rpath) { 1349 MGMT_ADD_ERR(errs, "bad cartridge path", 1350 ENOENT); 1351 continue; 1352 } 1353 (void) snprintf(cmd, sizeof (cmd), "%s/%s", 1354 mntp, rpath); 1355 st = mgmt_delete_dkvol(cmd, errs); 1356 if (st != 0) { 1357 MGMT_ADD_ERR(errs, cmd, st); 1358 } 1359 } 1360 } 1361 } 1362 1363 if (pclnv) { 1364 nvlist_free(pclnv); 1365 } 1366 1367 1368 done: 1369 if (sess) { 1370 (void) mms_goodbye(sess, 0); 1371 } 1372 1373 if (vols) { 1374 nvlist_free(vols); 1375 } 1376 1377 if ((st == 0) && skipped) { 1378 st = MMS_MGMT_CARTRIDGE_INUSE; 1379 } 1380 1381 return (st); 1382 } 1383 1384 /* 1385 * list by mpool, by mpool&cartridge id or all 1386 */ 1387 int 1388 mms_mgmt_list_vols(void *session, nvlist_t *nvl, nvlist_t **vol_list) 1389 { 1390 int st; 1391 char *mpool = NULL; 1392 char **volarr = NULL; 1393 int count; 1394 char tid[64]; 1395 char cmd[8192]; 1396 void *sess = NULL; 1397 void *sessp = session; 1398 void *response; 1399 boolean_t all = B_TRUE; 1400 int i; 1401 boolean_t cvt_mmp = B_TRUE; 1402 char *key = "volid"; 1403 1404 if (!nvl) { 1405 return (MMS_MGMT_NOARG); 1406 } 1407 1408 (void) nvlist_lookup_string(nvl, O_NAME, &mpool); 1409 1410 st = nvlist_lookup_boolean_value(nvl, "cvt_mmp", &cvt_mmp); 1411 if (st == ENOENT) { 1412 cvt_mmp = B_TRUE; 1413 } else if (cvt_mmp == B_FALSE) { 1414 key = "CartridgePCL"; 1415 } 1416 st = 0; 1417 1418 volarr = mgmt_var_to_array(nvl, O_VOLUMES, &count); 1419 if (volarr != NULL) { 1420 /* special case for all volumes */ 1421 if (strcmp(volarr[0], "*") != 0) { 1422 all = B_FALSE; 1423 } 1424 } 1425 1426 if (*vol_list == NULL) { 1427 st = nvlist_alloc(vol_list, NV_UNIQUE_NAME, 0); 1428 if (st != 0) { 1429 goto done; 1430 } 1431 1432 } 1433 1434 if (!session) { 1435 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1436 if (st != 0) { 1437 return (st); 1438 } 1439 sessp = sess; 1440 } 1441 1442 /* 1443 * get the cartridges from MMS. 1444 */ 1445 if (all) { 1446 (void) mms_gen_taskid(tid); 1447 (void) snprintf(cmd, sizeof (cmd), 1448 "show task['%s'] reportmode[namevalue] " 1449 "report[CARTRIDGE] ", tid); 1450 1451 if (!mpool) { 1452 (void) strlcat(cmd, ";", sizeof (cmd)); 1453 } else { 1454 (void) strlcat(cmd, 1455 "match[streq(CARTRIDGE.'CartridgeGroupName' '", 1456 sizeof (cmd)); 1457 (void) strlcat(cmd, mpool, sizeof (cmd)); 1458 (void) strlcat(cmd, "')];", sizeof (cmd)); 1459 } 1460 st = mms_mgmt_send_cmd(sessp, tid, cmd, "show cartridges", 1461 &response); 1462 if (st == 0) { 1463 st = mmp_get_nvattrs(key, cvt_mmp, response, 1464 vol_list); 1465 mms_free_rsp(response); 1466 } 1467 } else { 1468 for (i = 0; i < count; i++) { 1469 (void) mms_gen_taskid(tid); 1470 (void) snprintf(cmd, sizeof (cmd), 1471 "show task['%s'] reportmode[namevalue] " 1472 "report[CARTRIDGE] ", tid); 1473 1474 if (mpool) { 1475 (void) strlcat(cmd, "match[and (streq(", 1476 sizeof (cmd)); 1477 (void) strlcat(cmd, 1478 "CARTRIDGE.'CartridgeGroupName' '", 1479 sizeof (cmd)); 1480 (void) strlcat(cmd, mpool, sizeof (cmd)); 1481 (void) strlcat(cmd, "') ", sizeof (cmd)); 1482 } 1483 (void) strlcat(cmd, "streq(CARTRIDGE.'CartridgePCL' '", 1484 sizeof (cmd)); 1485 (void) strlcat(cmd, volarr[i], sizeof (cmd)); 1486 (void) strlcat(cmd, "')", sizeof (cmd)); 1487 if (mpool) { 1488 (void) strlcat(cmd, ")", sizeof (cmd)); 1489 } 1490 (void) strlcat(cmd, "];", sizeof (cmd)); 1491 1492 st = mms_mgmt_send_cmd(sessp, tid, cmd, 1493 "show cartridges", &response); 1494 if (st == 0) { 1495 st = mmp_get_nvattrs(key, cvt_mmp, 1496 response, vol_list); 1497 mms_free_rsp(response); 1498 } else { 1499 break; 1500 } 1501 } 1502 } 1503 1504 if (st == 0) { 1505 mgmt_filter_results(nvl, *vol_list); 1506 } 1507 1508 done: 1509 if (sess) { 1510 (void) mms_goodbye(sess, 0); 1511 } 1512 1513 mgmt_free_str_arr(volarr, count); 1514 1515 return (st); 1516 } 1517 1518 int 1519 mms_mgmt_show_dpool(void *session, nvlist_t *nvl, nvlist_t **pools) 1520 { 1521 int st; 1522 char **names = NULL; 1523 int count; 1524 char tid[64]; 1525 char cmd[8192]; 1526 char buf[1024]; 1527 void *sess = NULL; 1528 void *sessp = session; 1529 void *response; 1530 int i; 1531 char *key = O_DPOOL; 1532 nvlist_t *nva = NULL; 1533 nvpair_t *nvp = NULL; 1534 char *dpname = NULL; 1535 1536 if (!nvl || !pools) { 1537 return (MMS_MGMT_NOARG); 1538 } 1539 1540 if (!session) { 1541 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1542 if (st != 0) { 1543 return (st); 1544 } 1545 sessp = sess; 1546 } 1547 1548 names = mgmt_var_to_array(nvl, O_NAME, &count); 1549 1550 (void) mms_gen_taskid(tid); 1551 (void) snprintf(cmd, sizeof (cmd), 1552 "show task['%s'] reportmode[namevalue] " 1553 "report[DRIVEGROUP]", 1554 tid); 1555 1556 if (count > 1) { 1557 (void) strlcat(cmd, "match[or(", sizeof (cmd)); 1558 } else if (count == 1) { 1559 (void) strlcat(cmd, "match[", sizeof (cmd)); 1560 } 1561 for (i = 0; i < count; i++) { 1562 (void) snprintf(buf, sizeof (buf), 1563 " streq (DRIVEGROUP.'DriveGroupName' '%s')", 1564 names[i]); 1565 (void) strlcat(cmd, buf, sizeof (cmd)); 1566 } 1567 if (count > 1) { 1568 (void) strlcat(cmd, ")];", sizeof (cmd)); 1569 } else if (count == 1) { 1570 (void) strlcat(cmd, "];", sizeof (cmd)); 1571 } else { 1572 (void) strlcat(cmd, ";", sizeof (cmd)); 1573 } 1574 1575 *pools = NULL; 1576 st = mms_mgmt_send_cmd(sessp, tid, cmd, "show dpool", &response); 1577 if (st == 0) { 1578 st = mmp_get_nvattrs(key, B_TRUE, response, pools); 1579 mms_free_rsp(response); 1580 } 1581 1582 if (st != 0) { 1583 goto done; 1584 } 1585 1586 while ((nvp = nvlist_next_nvpair(*pools, nvp)) != NULL) { 1587 st = nvpair_value_nvlist(nvp, &nva); 1588 if (st != 0) { 1589 continue; 1590 } 1591 dpname = nvpair_name(nvp); 1592 1593 (void) mms_gen_taskid(tid); 1594 (void) snprintf(cmd, sizeof (cmd), 1595 "show task['%s'] reportmode[namevalue] " 1596 "report[DRIVEGROUPAPPLICATION.'ApplicationName' ] " 1597 "match[streq(DRIVEGROUP.'DriveGroupName' '%s')];", 1598 tid, dpname); 1599 1600 st = mms_mgmt_send_cmd(sessp, tid, cmd, "dpool apps", 1601 &response); 1602 if (st == 0) { 1603 st = mmp_get_nvattrs_array("application", B_TRUE, 1604 response, nva); 1605 mms_free_rsp(response); 1606 } 1607 if (st != 0) { 1608 continue; 1609 } 1610 1611 /* 1612 * Get drives in this dpool 1613 */ 1614 (void) mms_gen_taskid(tid); 1615 (void) snprintf(cmd, sizeof (cmd), 1616 "show task['%s'] reportmode[namevalue] " 1617 "report[DRIVE.'DriveName' ] " 1618 "match[streq(DRIVEGROUP.'DriveGroupName' '%s')];", 1619 tid, dpname); 1620 1621 st = mms_mgmt_send_cmd(sessp, tid, cmd, "dpool apps", 1622 &response); 1623 if (st == 0) { 1624 st = mmp_get_nvattrs_array("drive", B_TRUE, 1625 response, nva); 1626 mms_free_rsp(response); 1627 } 1628 if (st != 0) { 1629 continue; 1630 } 1631 } 1632 1633 mgmt_filter_results(nvl, *pools); 1634 1635 done: 1636 if (sess) { 1637 (void) mms_goodbye(sess, 0); 1638 } 1639 1640 if (names) { 1641 mgmt_free_str_arr(names, count); 1642 } 1643 1644 return (st); 1645 } 1646 1647 int 1648 mms_mgmt_show_mpool(void *session, nvlist_t *nvl, nvlist_t **pools) 1649 { 1650 int st; 1651 char **names = NULL; 1652 int count; 1653 char tid[64]; 1654 char cmd[8192]; 1655 char buf[1024]; 1656 void *sess = NULL; 1657 void *sessp = session; 1658 void *response; 1659 int i; 1660 char *key = O_MPOOL; 1661 int vcount = 0; 1662 uint64_t poolsz = 0; 1663 uint64_t vsz = 0; 1664 nvlist_t *vols = NULL; 1665 nvlist_t *nva = NULL; 1666 nvpair_t *nvp = NULL; 1667 nvlist_t *nvav = NULL; 1668 nvpair_t *nvpv = NULL; 1669 char *val; 1670 1671 if (!nvl || !pools) { 1672 return (MMS_MGMT_NOARG); 1673 } 1674 1675 if (!session) { 1676 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1677 if (st != 0) { 1678 return (st); 1679 } 1680 sessp = sess; 1681 } 1682 1683 names = mgmt_var_to_array(nvl, O_NAME, &count); 1684 1685 (void) mms_gen_taskid(tid); 1686 (void) snprintf(cmd, sizeof (cmd), 1687 "show task['%s'] reportmode[namevalue] " 1688 "report[CARTRIDGEGROUP]", 1689 tid); 1690 1691 if (count > 1) { 1692 (void) strlcat(cmd, "match[or(", sizeof (cmd)); 1693 } else if (count == 1) { 1694 (void) strlcat(cmd, "match[", sizeof (cmd)); 1695 } 1696 for (i = 0; i < count; i++) { 1697 (void) snprintf(buf, sizeof (buf), 1698 " streq (CARTRIDGEGROUP.'CartridgeGroupName' '%s')", 1699 names[i]); 1700 (void) strlcat(cmd, buf, sizeof (cmd)); 1701 } 1702 if (count > 1) { 1703 (void) strlcat(cmd, ")];", sizeof (cmd)); 1704 } else if (count == 1) { 1705 (void) strlcat(cmd, "];", sizeof (cmd)); 1706 } else { 1707 (void) strlcat(cmd, ";", sizeof (cmd)); 1708 } 1709 1710 *pools = NULL; 1711 st = mms_mgmt_send_cmd(sessp, tid, cmd, "show mpool", &response); 1712 if (st == 0) { 1713 st = mmp_get_nvattrs(key, B_TRUE, response, pools); 1714 mms_free_rsp(response); 1715 } 1716 1717 if (st != 0) { 1718 goto done; 1719 } 1720 1721 while ((nvp = nvlist_next_nvpair(*pools, nvp)) != NULL) { 1722 st = nvpair_value_nvlist(nvp, &nva); 1723 if (st != 0) { 1724 continue; 1725 } 1726 val = nvpair_name(nvp); 1727 1728 (void) mms_gen_taskid(tid); 1729 (void) snprintf(cmd, sizeof (cmd), 1730 "show task['%s'] reportmode[namevalue] " 1731 "report[CARTRIDGE.'CartridgePCL' " 1732 "CARTRIDGETYPE.'CartridgeShapeName' " 1733 "CARTRIDGETYPE.'CartridgeTypeMediaLength' " 1734 "PARTITION.'PartitionSize'] " 1735 "match[streq(CARTRIDGEGROUP.'CartridgeGroupName' '%s')];", 1736 tid, val); 1737 1738 st = mms_mgmt_send_cmd(sessp, tid, cmd, "mpool vols", 1739 &response); 1740 if (st == 0) { 1741 st = mmp_get_nvattrs("CartridgePCL", B_FALSE, 1742 response, &vols); 1743 mms_free_rsp(response); 1744 } 1745 if (st != 0) { 1746 continue; 1747 } 1748 1749 nvpv = NULL; 1750 cmd[0] = '\0'; 1751 poolsz = 0; 1752 vcount = 0; 1753 1754 while ((nvpv = nvlist_next_nvpair(vols, nvpv)) != NULL) { 1755 st = nvpair_value_nvlist(nvpv, &nvav); 1756 if (st != 0) { 1757 continue; 1758 } 1759 vcount++; 1760 1761 st = nvlist_lookup_string(nvav, "CartridgeShapeName", 1762 &val); 1763 if (st == 0) { 1764 (void) snprintf(buf, sizeof (buf), "%s,", val); 1765 if (strstr(cmd, buf) == NULL) { 1766 (void) strlcat(cmd, buf, sizeof (cmd)); 1767 } 1768 } 1769 st = nvlist_lookup_string(nvav, "PartitionSize", 1770 &val); 1771 if (st == 0) { 1772 (void) do_val_mms_size(val, &vsz); 1773 poolsz += vsz; 1774 } else { 1775 st = nvlist_lookup_string(nvav, 1776 "CartridgeTypeMediaLength", &val); 1777 if (st == 0) { 1778 (void) do_val_mms_size(val, &vsz); 1779 poolsz += vsz; 1780 } 1781 } 1782 1783 } 1784 nvlist_free(vols); 1785 vols = NULL; 1786 (void) snprintf(buf, sizeof (buf), "%lu", poolsz); 1787 (void) nvlist_add_string(nva, "total size", buf); 1788 (void) snprintf(buf, sizeof (buf), "%d", vcount); 1789 (void) nvlist_add_string(nva, "total volumes", buf); 1790 val = strrchr(cmd, ','); 1791 if (val != NULL) { 1792 *val = NULL; 1793 } 1794 (void) nvlist_add_string(nva, "voltype", cmd); 1795 } 1796 1797 mgmt_filter_results(nvl, *pools); 1798 1799 /* TODO: list of cartridges + sum space used/free/avail */ 1800 1801 done: 1802 if (sess) { 1803 (void) mms_goodbye(sess, 0); 1804 } 1805 1806 if (names) { 1807 mgmt_free_str_arr(names, count); 1808 } 1809 1810 return (st); 1811 } 1812 1813 /* ARGSUSED */ 1814 int 1815 mms_mgmt_create_partition(void *session, char *pcl, int64_t size, char *lib, 1816 char *rwmode, nvlist_t *errs) 1817 { 1818 int st; 1819 void *sess = NULL; 1820 void *sessp = session; 1821 void *response; 1822 char tid[64]; 1823 char cmd[8192]; 1824 nvlist_t *carts = NULL; 1825 1826 if (!mgmt_chk_auth("solaris.mms.media")) { 1827 return (EACCES); 1828 } 1829 1830 if (!session) { 1831 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1832 if (st != 0) { 1833 return (st); 1834 } 1835 sessp = sess; 1836 } 1837 1838 if (size > 0) { 1839 size /= (1024 * 1024); /* convert to mega bytes */ 1840 } 1841 1842 (void) mms_gen_taskid(tid); 1843 (void) snprintf(cmd, sizeof (cmd), 1844 "create task['%s'] type[PARTITION] " 1845 "set[PARTITION.'PartitionName' 'part1'] " 1846 "set[PARTITION.'SideName' 'side 1'] " 1847 "set[PARTITION.'CartridgePCL' '%s'] " 1848 "set[PARTITION.'PartitionAvailable' '%lld'] " 1849 "set[PARTITION.'PartitionSize' '%lld'] " 1850 "set[PARTITION.'PartitionPercentAvailable' '%d'] " 1851 "set[PARTITION.'PartitionRWMode' '%s'] " 1852 "set[PARTITION.'LibraryName' '%s'];", 1853 tid, pcl, size, size, size == -1 ? -1 : 100, rwmode, lib); 1854 1855 st = mms_mgmt_send_cmd(sessp, tid, cmd, "create partition", &response); 1856 1857 done: 1858 if (sess) { 1859 (void) mms_goodbye(sess, 0); 1860 } 1861 1862 if (carts) { 1863 nvlist_free(carts); 1864 } 1865 1866 return (st); 1867 } 1868 1869 int 1870 mms_mgmt_remove_partition(void *session, nvlist_t *nvl, nvlist_t *errs) 1871 { 1872 int st; 1873 void *sess = NULL; 1874 void *sessp = session; 1875 void *response; 1876 char tid[64]; 1877 char cmd[8192]; 1878 char *pcl = NULL; 1879 char *lib = NULL; 1880 nvlist_t *carts = NULL; 1881 nvlist_t *vols = NULL; 1882 1883 if (!mgmt_chk_auth("solaris.mms.media")) { 1884 return (EACCES); 1885 } 1886 1887 if (!nvl) { 1888 return (MMS_MGMT_NOARG); 1889 } 1890 1891 st = nvlist_lookup_string(nvl, O_NAME, &pcl); 1892 if (st != 0) { 1893 MGMT_ADD_OPTERR(errs, O_NAME, st); 1894 return (st); 1895 } 1896 1897 st = nvlist_lookup_string(nvl, O_MMSLIB, &lib); 1898 if (st != 0) { 1899 MGMT_ADD_OPTERR(errs, O_MMSLIB, st); 1900 } 1901 1902 if (!session) { 1903 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 1904 if (st != 0) { 1905 return (st); 1906 } 1907 sessp = sess; 1908 } 1909 1910 /* check for existing volumes */ 1911 st = mgmt_show_mmvols(sessp, pcl, lib, &vols); 1912 if (st != 0) { 1913 goto done; 1914 } 1915 1916 if (vols) { 1917 (void) mms_gen_taskid(tid); 1918 (void) snprintf(cmd, sizeof (cmd), 1919 "delete task['%s'] type[VOLUME] " 1920 "match[and (streq(PARTITION.'CartridgePCL' '%s') " 1921 "streq(PARTITION.'LibraryName' '%s'))];", 1922 tid, pcl, lib); 1923 1924 st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete volume", 1925 &response); 1926 if (st != 0) { 1927 goto done; 1928 } 1929 } 1930 1931 /* now the partitions */ 1932 (void) mms_gen_taskid(tid); 1933 (void) snprintf(cmd, sizeof (cmd), 1934 "delete task['%s'] type[PARTITION] " 1935 "match[and (streq (PARTITION.'LibraryName' '%s') " 1936 "streq(PARTITION.'CartridgePCL' '%s'))];", 1937 tid, lib, pcl); 1938 1939 st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete partition", 1940 &response); 1941 1942 done: 1943 if (sess) { 1944 (void) mms_goodbye(sess, 0); 1945 } 1946 1947 if (carts) { 1948 nvlist_free(carts); 1949 } 1950 1951 if (vols) { 1952 nvlist_free(vols); 1953 } 1954 1955 return (st); 1956 } 1957 1958 int 1959 mms_mgmt_label_multi(void *session, nvlist_t *nvl, nvlist_t *errs) 1960 { 1961 int st; 1962 int rst = 0; 1963 void *sess = NULL; 1964 void *sessp = session; 1965 char *pass = NULL; 1966 char *app = NULL; 1967 char *inst = NULL; 1968 char **varr = NULL; 1969 int count = 0; 1970 int i; 1971 1972 if (!mgmt_chk_auth("solaris.mms.media")) { 1973 return (EACCES); 1974 } 1975 1976 if (!nvl) { 1977 return (MMS_MGMT_NOARG); 1978 } 1979 1980 varr = mgmt_var_to_array(nvl, O_NAME, &count); 1981 if (!varr) { 1982 st = ENOENT; 1983 MGMT_ADD_OPTERR(errs, O_NAME, st); 1984 return (st); 1985 } 1986 1987 if (!session) { 1988 (void) nvlist_lookup_string(nvl, O_APPS, &app); 1989 (void) nvlist_lookup_string(nvl, "instance", &inst); 1990 (void) nvlist_lookup_string(nvl, O_MMPASS, &pass); 1991 1992 st = create_mm_clnt(app, inst, pass, NULL, &sess); 1993 if (st != 0) { 1994 return (st); 1995 } 1996 sessp = sess; 1997 } 1998 1999 for (i = 0; i < count; i++) { 2000 (void) nvlist_add_string(nvl, O_NAME, varr[i]); 2001 2002 st = mms_mgmt_label_vol(sessp, nvl, errs); 2003 if (st != 0) { 2004 /* save return status */ 2005 if (rst == 0) { 2006 rst = st; 2007 } 2008 } 2009 } 2010 2011 /* set 'name' back to the way it started */ 2012 (void) nvlist_add_string_array(nvl, O_NAME, varr, count); 2013 2014 mgmt_free_str_arr(varr, count); 2015 2016 if (sess) { 2017 (void) mms_goodbye(sess, 0); 2018 } 2019 2020 return (rst); 2021 } 2022 2023 int 2024 mms_mgmt_label_vol(void *session, nvlist_t *nvl, nvlist_t *errs) 2025 { 2026 int st; 2027 void *sess = NULL; 2028 void *sessp = session; 2029 void *response; 2030 char tid[64]; 2031 char cmd[8192]; 2032 char buf[1024]; 2033 char *pcl; 2034 char *lib; 2035 char *app; 2036 char *inst = NULL; 2037 char *pass = NULL; 2038 nvlist_t *attrs = NULL; 2039 nvlist_t *carts = NULL; 2040 nvpair_t *nva; 2041 boolean_t force = B_FALSE; 2042 boolean_t nomount = B_FALSE; 2043 2044 if (!mgmt_chk_auth("solaris.mms.media")) { 2045 return (EACCES); 2046 } 2047 2048 if (!nvl) { 2049 return (MMS_MGMT_NOARG); 2050 } 2051 2052 st = nvlist_lookup_string(nvl, O_NAME, &pcl); 2053 if (st != 0) { 2054 MGMT_ADD_OPTERR(errs, O_NAME, st); 2055 return (st); 2056 } 2057 2058 st = nvlist_lookup_string(nvl, O_MMSLIB, &lib); 2059 if (st != 0) { 2060 MGMT_ADD_OPTERR(errs, O_MMSLIB, st); 2061 return (st); 2062 } 2063 2064 st = nvlist_lookup_string(nvl, O_APPS, &app); 2065 if (st != 0) { 2066 MGMT_ADD_OPTERR(errs, O_APPS, st); 2067 return (st); 2068 } 2069 2070 (void) nvlist_lookup_boolean_value(nvl, O_FORCE, &force); 2071 2072 if (!session) { 2073 (void) nvlist_lookup_string(nvl, "instance", &inst); 2074 (void) nvlist_lookup_string(nvl, O_MMPASS, &pass); 2075 2076 st = create_mm_clnt(app, inst, pass, NULL, &sess); 2077 if (st != 0) { 2078 return (st); 2079 } 2080 sessp = sess; 2081 } 2082 2083 /* 2084 * Check if cartridge exists. 2085 */ 2086 (void) mms_gen_taskid(tid); 2087 (void) snprintf(cmd, sizeof (cmd), 2088 "show task['%s'] reportmode[namevalue] report[CARTRIDGE] " 2089 "match[and (streq(CARTRIDGE.'LibraryName' '%s') " 2090 "streq(CARTRIDGE.'CartridgePCL' '%s'))];", 2091 tid, lib, pcl); 2092 2093 st = mms_mgmt_send_cmd(sessp, tid, cmd, "show cartridge", &response); 2094 if (st == 0) { 2095 st = mmp_get_nvattrs("CartridgePCL", B_FALSE, response, &carts); 2096 mms_free_rsp(response); 2097 } 2098 2099 if (!nvlist_exists(carts, pcl)) { 2100 MGMT_ADD_OPTERR(errs, pcl, st); 2101 goto done; 2102 } 2103 2104 /* check if partition for cartridge exists. if no, create */ 2105 st = mgmt_show_partition(sessp, pcl, lib, &attrs); 2106 2107 if (st != 0) { 2108 goto done; 2109 } 2110 2111 if (attrs == NULL) { 2112 st = mms_mgmt_create_partition(sessp, pcl, -1, lib, 2113 "readwrite", errs); 2114 } else { 2115 nva = nvlist_next_nvpair(attrs, NULL); 2116 if (nva) { 2117 if (nvlist_next_nvpair(attrs, nva)) { 2118 /* got more than 1, not supported */ 2119 st = MMS_MGMT_ERR_PARTITION_NOT_UNIQUE; 2120 MGMT_ADD_ERR(errs, pcl, st); 2121 goto done; 2122 } 2123 } 2124 } 2125 2126 nvlist_free(attrs); 2127 attrs = NULL; 2128 2129 /* check for existing volumes */ 2130 st = mgmt_show_mmvols(sessp, pcl, lib, &attrs); 2131 if (st != 0) { 2132 goto done; 2133 } 2134 2135 if (!attrs) { 2136 /* create a volume */ 2137 (void) snprintf(buf, sizeof (buf), "%s_%s", lib, pcl); 2138 (void) mms_gen_taskid(tid); 2139 (void) snprintf(cmd, sizeof (cmd), 2140 "allocate task['%s'] newvolname['%s'] " 2141 "who['%s'] " 2142 "match[and (streq(CARTRIDGE.'CartridgePCL' '%s') " 2143 "streq(CARTRIDGE.'LibraryName' '%s'))];", 2144 tid, buf, app, pcl, lib); 2145 2146 st = mms_mgmt_send_cmd(sessp, tid, cmd, "create volume", 2147 &response); 2148 if (st != 0) { 2149 MGMT_ADD_ERR(errs, pcl, st); 2150 goto done; 2151 } 2152 } else if (!force) { 2153 st = MMS_MGMT_CARTRIDGE_INUSE; 2154 MGMT_ADD_ERR(errs, pcl, st); 2155 goto done; 2156 } 2157 2158 /* filename is 17 spaces - tells MM to re-init volume */ 2159 (void) nvlist_add_string(nvl, "filename", label_fname); 2160 2161 /* 2162 * If '-n' is not specified, them mount and label the cartridge 2163 */ 2164 st = nvlist_lookup_boolean_value(nvl, O_NOMOUNT, &nomount); 2165 if (st != 0 || nomount != B_TRUE) { 2166 /* ok, mount with appropriate options */ 2167 st = mms_mgmt_mount_vol(sessp, nvl, errs); 2168 2169 if (st == 0) { 2170 /* label is a quick mount/unmount */ 2171 st = mms_mgmt_unmount_vol(nvl, errs); 2172 } 2173 } 2174 2175 done: 2176 if (sess) { 2177 (void) mms_goodbye(sess, 0); 2178 } 2179 2180 if (attrs) { 2181 nvlist_free(attrs); 2182 } 2183 if (carts) { 2184 nvlist_free(carts); 2185 } 2186 2187 return (st); 2188 } 2189 2190 static int 2191 mgmt_show_partition(void *session, char *pcl, char *library, nvlist_t **parts) 2192 { 2193 int st; 2194 void *sess = NULL; 2195 void *sessp = session; 2196 void *response; 2197 char tid[64]; 2198 char cmd[8192]; 2199 nvlist_t *plist = NULL; 2200 nvpair_t *nvp = NULL; 2201 2202 if (!pcl || !library || !parts) { 2203 return (MMS_MGMT_NOARG); 2204 } 2205 2206 st = nvlist_alloc(&plist, NV_UNIQUE_NAME, 0); 2207 if (st != 0) { 2208 return (st); 2209 } 2210 2211 if (!session) { 2212 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 2213 if (st != 0) { 2214 return (st); 2215 } 2216 sessp = sess; 2217 } 2218 2219 *parts = NULL; 2220 2221 (void) mms_gen_taskid(tid); 2222 (void) snprintf(cmd, sizeof (cmd), 2223 "show task['%s'] report[PARTITION] reportmode[namevalue] " 2224 "match[and (streq(PARTITION.'CartridgePCL' '%s') " 2225 "streq(PARTITION.'LibraryName' '%s'))];", 2226 tid, pcl, library); 2227 2228 st = mms_mgmt_send_cmd(sessp, tid, cmd, "show partition", &response); 2229 if (st == 0) { 2230 st = mmp_get_nvattrs("PartitionName", B_FALSE, response, 2231 &plist); 2232 mms_free_rsp(response); 2233 } 2234 2235 if (st == 0) { 2236 nvp = nvlist_next_nvpair(plist, NULL); 2237 if (nvp) { 2238 *parts = plist; 2239 } else { 2240 nvlist_free(plist); 2241 } 2242 } 2243 2244 return (st); 2245 } 2246 2247 static int 2248 mgmt_show_mmvols(void *session, char *pcl, char *library, nvlist_t **vols) 2249 { 2250 int st; 2251 void *sess = NULL; 2252 void *sessp = session; 2253 void *response; 2254 char tid[64]; 2255 char cmd[8192]; 2256 nvlist_t *vlist = NULL; 2257 nvpair_t *nvp = NULL; 2258 2259 if (!pcl || !library || !vols) { 2260 return (MMS_MGMT_NOARG); 2261 } 2262 2263 st = nvlist_alloc(&vlist, NV_UNIQUE_NAME, 0); 2264 if (st != 0) { 2265 return (st); 2266 } 2267 2268 if (!session) { 2269 st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess); 2270 if (st != 0) { 2271 return (st); 2272 } 2273 sessp = sess; 2274 } 2275 2276 (void) mms_gen_taskid(tid); 2277 (void) snprintf(cmd, sizeof (cmd), 2278 "show task['%s'] report[VOLUME] reportmode[namevalue] " 2279 "match[and (streq(PARTITION.'CartridgePCL' '%s') " 2280 "streq(PARTITION.'LibraryName' '%s'))];", 2281 tid, pcl, library); 2282 2283 st = mms_mgmt_send_cmd(sessp, tid, cmd, "show volume", &response); 2284 if (st == 0) { 2285 st = mmp_get_nvattrs("VolumeName", B_FALSE, response, &vlist); 2286 mms_free_rsp(response); 2287 } 2288 2289 if (st == 0) { 2290 nvp = nvlist_next_nvpair(vlist, NULL); 2291 if (!nvp) { 2292 /* nothing there */ 2293 nvlist_free(vlist); 2294 *vols = NULL; 2295 } else { 2296 *vols = vlist; 2297 } 2298 } 2299 2300 return (st); 2301 } 2302 2303 static int 2304 call_mmsmnt(door_arg_t *arg) 2305 { 2306 int st; 2307 int doorfd = -1; 2308 int count; 2309 /* LINTED [warning: pointer cast may result in improper alignment] */ 2310 mmsmnt_arg_t *mntarg = (mmsmnt_arg_t *)arg->rbuf; 2311 int saverr; 2312 timespec_t sleepfor = {5, 0}; /* 5 seconds */ 2313 char *cmd[2]; 2314 2315 if (arg == NULL) { 2316 return (MMS_MGMT_NOARG); 2317 } 2318 2319 cmd[0] = MMSSBINDIR"/mmsmnt"; 2320 cmd[1] = NULL; 2321 2322 /* will get overwritten with correct status as appropriate */ 2323 st = ENOTCONN; 2324 2325 /* try 5 times to get connected, then give up */ 2326 for (count = 0; count < 5; count++) { 2327 doorfd = open(mmsmntdoor, O_RDWR); 2328 if (doorfd == -1) { 2329 if (errno == ENOENT) { 2330 /* server is not running. Try to start it */ 2331 (void) exec_mgmt_cmd(NULL, NULL, 0, 0, B_TRUE, 2332 cmd); 2333 mms_trace(MMS_DEBUG, 2334 "exec_mgmt_cmd: %s", cmd[0]); 2335 } else { 2336 st = errno; 2337 return (st); 2338 } 2339 } 2340 2341 /* 2342 * try to contact the server - if door_call successful, 2343 * status will be set by the server 2344 */ 2345 st = door_call(doorfd, arg); 2346 saverr = errno; 2347 2348 if (st == 0) { 2349 /* connected ok, return error from daemon */ 2350 st = mntarg->st; 2351 break; 2352 } 2353 2354 (void) close(doorfd); 2355 doorfd = -1; 2356 2357 if (saverr == EBADF) { 2358 /* 2359 * server was not running when we opened 2360 * the door file 2361 */ 2362 (void) exec_mgmt_cmd(NULL, NULL, 0, 0, B_TRUE, cmd); 2363 mms_trace(MMS_DEBUG, "exec_mgmt_cmd: %s", cmd[0]); 2364 /* give the server a chance to start */ 2365 (void) nanosleep(&sleepfor, NULL); 2366 } else if ((saverr != EAGAIN) && (saverr != EINTR)) { 2367 /* A non-recoverable error occurred */ 2368 st = saverr; 2369 mms_trace(MMS_ERR, 2370 "Could not contact the mmsmnt process, %d", st); 2371 return (st); 2372 } 2373 } 2374 2375 if (doorfd != -1) { 2376 (void) close(doorfd); 2377 } 2378 2379 return (st); 2380 } 2381 2382 int 2383 mms_mgmt_mount_vol(void *session, nvlist_t *nvl, nvlist_t *errs) 2384 { 2385 int st; 2386 void *sess = NULL; 2387 void *sessp = session; 2388 void *response = NULL; 2389 char tid[64]; 2390 char cmd[8192]; 2391 char mbuf[7168]; 2392 char buf[1024]; 2393 char *pcl; 2394 char *lib; 2395 char *mfile = NULL; 2396 char *val; 2397 char *app = NULL; 2398 char *vname; 2399 nvlist_t *attrs = NULL; 2400 nvpair_t *nvp; 2401 nvlist_t *nva; 2402 nvlist_t *mntattrs = NULL; 2403 mmsmnt_arg_t arg; 2404 door_arg_t d_arg; 2405 int others = 0; 2406 struct passwd *pwd = NULL; 2407 char *usernm = NULL; 2408 nvlist_t *cattrs = NULL; 2409 boolean_t isdsk = B_FALSE; 2410 char **varray = NULL; 2411 int count = 0; 2412 boolean_t vbool = B_FALSE; 2413 int i; 2414 char *inst = NULL; 2415 char *pass = NULL; 2416 2417 if (!mgmt_chk_auth("solaris.mms.io.read")) { 2418 return (EACCES); 2419 } 2420 2421 /* this function is unique, in that it returns the session */ 2422 if (!nvl) { 2423 return (MMS_MGMT_NOARG); 2424 } 2425 2426 st = nvlist_lookup_string(nvl, O_NAME, &pcl); 2427 if (st != 0) { 2428 MGMT_ADD_OPTERR(errs, O_NAME, st); 2429 return (st); 2430 } 2431 2432 st = nvlist_lookup_string(nvl, O_MMSLIB, &lib); 2433 if (st != 0) { 2434 MGMT_ADD_OPTERR(errs, O_MMSLIB, st); 2435 return (st); 2436 } 2437 2438 st = nvlist_lookup_string(nvl, O_APPS, &app); 2439 if (st != 0) { 2440 /* if not specified, see if we can mount as admin */ 2441 if (st == ENOENT) { 2442 st = 0; 2443 app = "MMS"; 2444 (void) nvlist_add_string(nvl, O_APPS, app); 2445 } else { 2446 MGMT_ADD_OPTERR(errs, O_APPS, st); 2447 return (st); 2448 } 2449 } 2450 2451 (void) nvlist_lookup_string(nvl, "filename", &mfile); 2452 (void) nvlist_lookup_string(nvl, "instance", &inst); 2453 (void) nvlist_lookup_string(nvl, O_MMPASS, &pass); 2454 2455 if (!sessp) { 2456 st = create_mm_clnt(app, inst, pass, NULL, &sess); 2457 if (st != 0) { 2458 return (st); 2459 } 2460 sessp = sess; 2461 } 2462 2463 /* check for volumes. If one doesn't exist, fail */ 2464 st = mgmt_show_mmvols(sessp, pcl, lib, &attrs); 2465 if (st == 0) { 2466 if (!attrs) { 2467 st = MMS_MGMT_VOL_NOT_INIT; 2468 } 2469 } 2470 if (st != 0) { 2471 MGMT_ADD_ERR(errs, pcl, st); 2472 goto done; 2473 } 2474 2475 nvp = NULL; 2476 while ((nvp = nvlist_next_nvpair(attrs, nvp)) != NULL) { 2477 st = nvpair_value_nvlist(nvp, &nva); 2478 if (st != 0) { 2479 goto done; 2480 } 2481 st = nvlist_lookup_string(nva, "ApplicationName", &val); 2482 if (st != 0) { 2483 continue; 2484 } 2485 2486 if (strcasecmp(val, app) != 0) { 2487 continue; 2488 } 2489 2490 /* found a valid volume */ 2491 break; 2492 } 2493 2494 if ((st != 0) || (nvp == NULL)) { 2495 st = MMS_MGMT_NO_USABLE_VOL; 2496 MGMT_ADD_ERR(errs, pcl, st); 2497 goto done; 2498 } 2499 2500 st = nvlist_lookup_string(nva, "VolumeName", &vname); 2501 if (st != 0) { 2502 goto done; 2503 } 2504 2505 /* see what type of cartridge this is */ 2506 (void) mms_gen_taskid(tid); 2507 (void) snprintf(cmd, sizeof (cmd), 2508 "show task['%s'] report[CARTRIDGETYPE.'CartridgeShapeName'] " 2509 "reportmode[namevalue] " 2510 "match[and (streq(CARTRIDGE.'CartridgePCL' '%s') " 2511 "streq(LIBRARY.'LibraryName' '%s'))];", 2512 tid, pcl, lib); 2513 2514 st = mms_mgmt_send_cmd(sessp, tid, cmd, "get cartridge type", 2515 &response); 2516 if (st == 0) { 2517 st = mmp_get_nvattrs("CartridgeShapeName", B_FALSE, response, 2518 &cattrs); 2519 mms_free_rsp(response); 2520 } 2521 if (st == 0) { 2522 if (nvlist_exists(cattrs, "DISK")) { 2523 isdsk = B_TRUE; 2524 } 2525 } 2526 /* reset */ 2527 if (cattrs) { 2528 nvlist_free(cattrs); 2529 } 2530 st = 0; 2531 2532 st = nvlist_lookup_string(nvl, "user", &usernm); 2533 if ((st != 0) || (usernm == NULL)) { 2534 pwd = getpwuid(getuid()); 2535 if (pwd != NULL) { 2536 usernm = pwd->pw_name; 2537 } 2538 if (usernm == NULL) { 2539 usernm = "root"; 2540 } 2541 } 2542 2543 /* at last, create the mount command */ 2544 (void) mms_gen_taskid(tid); 2545 (void) snprintf(cmd, sizeof (cmd), 2546 "mount task['%s'] user['%s'] type[VOLUME] " 2547 "match[and (streq(LIBRARY.'LibraryName' '%s') " 2548 "streq(CARTRIDGE.'CartridgePCL' '%s'))] " 2549 "report[MOUNTLOGICAL] reportmode[namevalue] ", 2550 tid, usernm, lib, pcl); 2551 2552 if (mfile) { 2553 (void) snprintf(buf, sizeof (buf), "filename['%s'] ", 2554 mfile); 2555 (void) strlcat(cmd, buf, sizeof (cmd)); 2556 } 2557 2558 st = nvlist_lookup_string(nvl, "blocksize", &val); 2559 if (st == 0) { 2560 (void) snprintf(buf, sizeof (buf), "blocksize['%s'] ", val); 2561 (void) strlcat(cmd, buf, sizeof (cmd)); 2562 } 2563 2564 st = nvlist_lookup_boolean_value(nvl, O_NOWAIT, &vbool); 2565 if ((st == 0) && (vbool)) { 2566 (void) strlcat(cmd, "when[immediate] ", sizeof (cmd)); 2567 } else { 2568 (void) strlcat(cmd, "when[blocking] ", sizeof (cmd)); 2569 } 2570 st = 0; 2571 2572 /* get the firstmount and accessmodes */ 2573 mbuf[0] = '\0'; 2574 2575 if (mfile && (strcmp(mfile, label_fname) == 0)) { 2576 /* The 17-space filename indicates we're labeling */ 2577 (void) strlcat(cmd, "accessmode['creat'] ", sizeof (cmd)); 2578 (void) strlcat(mbuf, "firstmount[", sizeof (mbuf)); 2579 } else { 2580 /* all options go into accessmode otherwise */ 2581 (void) strlcat(mbuf, "accessmode[", sizeof (mbuf)); 2582 } 2583 2584 /* get the rest of the options */ 2585 if (isdsk) { 2586 others++; 2587 (void) strlcat(mbuf, "'st_bsd' ", sizeof (mbuf)); 2588 } 2589 2590 st = nvlist_lookup_string(nvl, O_MMSDRV, &val); 2591 if (st == 0) { 2592 others++; 2593 (void) snprintf(buf, sizeof (buf), "'%s' ", val); 2594 (void) strlcat(mbuf, buf, sizeof (mbuf)); 2595 } 2596 2597 st = nvlist_lookup_boolean_value(nvl, O_NOREWIND, &vbool); 2598 if ((st == 0) && (vbool)) { 2599 others++; 2600 (void) strlcat(mbuf, "'norewind' ", sizeof (mbuf)); 2601 } 2602 2603 st = nvlist_lookup_string(nvl, O_DENSITY, &val); 2604 if (st == 0) { 2605 others++; 2606 (void) snprintf(buf, sizeof (buf), "'%s' ", val); 2607 (void) strlcat(mbuf, buf, sizeof (mbuf)); 2608 } 2609 2610 varray = mgmt_var_to_array(nvl, "mode", &count); 2611 for (i = 0; i < count; i++) { 2612 if (!varray[i]) { 2613 continue; 2614 } 2615 others++; 2616 (void) snprintf(buf, sizeof (buf), "'%s' ", varray[i]); 2617 (void) strlcat(mbuf, buf, sizeof (mbuf)); 2618 } 2619 mgmt_free_str_arr(varray, count); 2620 varray = NULL; 2621 count = 0; 2622 2623 st = nvlist_lookup_string(nvl, "readonly", &val); 2624 if (st == 0) { 2625 if (strcasecmp(val, "true") == 0) { 2626 (void) snprintf(buf, sizeof (buf), "'readonly' "); 2627 } else { 2628 (void) snprintf(buf, sizeof (buf), "'readwrite' "); 2629 } 2630 others++; 2631 (void) strlcat(mbuf, buf, sizeof (mbuf)); 2632 } 2633 2634 if (others > 0) { 2635 (void) strlcat(mbuf, "]", sizeof (mbuf)); 2636 (void) strlcat(cmd, mbuf, sizeof (cmd)); 2637 } 2638 2639 (void) strlcat(cmd, ";", sizeof (cmd)); 2640 2641 /* 2642 * Call the mount daemon. If successful, the handle will be 2643 * returned. 2644 */ 2645 2646 (void) memset(&arg, 0, sizeof (mmsmnt_arg_t)); 2647 (void) memset(&d_arg, 0, sizeof (door_arg_t)); 2648 2649 arg.op = 1; 2650 (void) strlcpy(arg.cartridge, pcl, sizeof (arg.cartridge)); 2651 (void) strlcpy(arg.library, lib, sizeof (arg.library)); 2652 (void) strlcpy(arg.volname, vname, sizeof (arg.volname)); 2653 (void) strlcpy(arg.cmd, cmd, sizeof (arg.cmd)); 2654 if (pass) { 2655 (void) strlcpy(arg.pass, pass, sizeof (arg.pass)); 2656 } 2657 if (inst) { 2658 (void) strlcpy(arg.inst, inst, sizeof (arg.inst)); 2659 } 2660 if (app) { 2661 (void) strlcpy(arg.app, app, sizeof (arg.app)); 2662 } 2663 d_arg.data_ptr = (char *)&arg; 2664 d_arg.data_size = sizeof (mmsmnt_arg_t); 2665 d_arg.desc_ptr = NULL; 2666 d_arg.desc_num = 0; 2667 d_arg.rbuf = (char *)&arg; 2668 d_arg.rsize = d_arg.data_size; 2669 2670 st = call_mmsmnt(&d_arg); 2671 2672 if (st == 0) { 2673 (void) nvlist_add_string(nvl, "mountdev", arg.devname); 2674 } 2675 2676 done: 2677 if (sess) { 2678 (void) mms_goodbye(sess, 0); 2679 } 2680 2681 if (attrs) { 2682 nvlist_free(attrs); 2683 } 2684 2685 if (mntattrs) { 2686 nvlist_free(mntattrs); 2687 } 2688 2689 return (st); 2690 } 2691 2692 int 2693 mms_mgmt_unmount_vol(nvlist_t *nvl, nvlist_t *errs) 2694 { 2695 int st; 2696 char *lib = NULL; 2697 char *pcl = NULL; 2698 char *dev = NULL; 2699 char *app = NULL; 2700 char *inst = NULL; 2701 char *pass = NULL; 2702 void *sess = NULL; 2703 void *resp = NULL; 2704 char tid[64]; 2705 char cmd[8192]; 2706 nvlist_t *attrs = NULL; 2707 boolean_t phys = B_FALSE; 2708 mmsmnt_arg_t arg; 2709 door_arg_t d_arg; 2710 2711 if (!mgmt_chk_auth("solaris.mms.io.read")) { 2712 return (EACCES); 2713 } 2714 2715 (void) memset(&arg, 0, sizeof (mmsmnt_arg_t)); 2716 (void) memset(&d_arg, 0, sizeof (d_arg)); 2717 2718 /* requires either the pseudodevice name, *or* library/volume */ 2719 st = nvlist_lookup_string(nvl, O_NAME, &pcl); 2720 if (st != 0) { 2721 MGMT_ADD_OPTERR(errs, O_NAME, st); 2722 return (st); 2723 } 2724 2725 if (pcl[0] == '/') { 2726 (void) strlcpy(arg.devname, pcl, sizeof (arg.devname)); 2727 } else { 2728 (void) strlcpy(arg.cartridge, pcl, sizeof (arg.cartridge)); 2729 } 2730 2731 st = nvlist_lookup_string(nvl, O_MMSLIB, &lib); 2732 if ((st != 0) && (arg.cartridge[0] != '\0')) { 2733 MGMT_ADD_OPTERR(errs, O_MMSLIB, st); 2734 return (st); 2735 } 2736 2737 if (lib) { 2738 (void) strlcpy(arg.library, lib, sizeof (arg.library)); 2739 } 2740 2741 /* could specify all the options, but unlikely */ 2742 st = nvlist_lookup_string(nvl, "mountdev", &dev); 2743 if (st == 0) { 2744 (void) strlcpy(arg.devname, dev, sizeof (arg.devname)); 2745 } 2746 2747 (void) nvlist_lookup_string(nvl, O_APPS, &app); 2748 if (!app) { 2749 app = "MMS"; 2750 } 2751 (void) nvlist_lookup_string(nvl, "instance", &inst); 2752 (void) nvlist_lookup_string(nvl, O_MMPASS, &pass); 2753 2754 /* make sure user is permitted to unmount this volume */ 2755 if (strcasecmp(app, "MMS") != 0) { 2756 st = create_mm_clnt(app, inst, pass, NULL, &sess); 2757 if (st != 0) { 2758 return (st); 2759 } 2760 2761 (void) mms_gen_taskid(tid); 2762 2763 if (pcl[0] == '/') { 2764 (void) snprintf(cmd, sizeof (cmd), 2765 "show task['%s'] report[MOUNTPHYSICAL] " 2766 "reportmode[namevalue] " 2767 "match[and " 2768 "(streq(MOUNTPHYSICAL.'ApplicationName' '%s') " 2769 "streq(MOUNTLOGICAL.'MountLogicalHandle' '%s'))];", 2770 tid, app, pcl); 2771 } else { 2772 (void) snprintf(cmd, sizeof (cmd), 2773 "show task['%s'] report[MOUNTPHYSICAL] " 2774 "reportmode[namevalue] " 2775 "match[and " 2776 "(streq(MOUNTPHYSICAL.'ApplicationName' '%s') " 2777 "streq(MOUNTPHYSICAL.'CartridgePCL' '%s'))];", 2778 tid, app, pcl); 2779 } 2780 2781 st = mms_mgmt_send_cmd(sess, tid, cmd, "check mounted vol", 2782 &resp); 2783 if (st == 0) { 2784 st = mmp_get_nvattrs("ApplicationName", B_FALSE, 2785 resp, &attrs); 2786 mms_free_rsp(resp); 2787 } 2788 if (st == 0) { 2789 if (!nvlist_exists(attrs, app)) { 2790 st = MMS_MGMT_VOL_NOT_MOUNTED; 2791 } 2792 nvlist_free(attrs); 2793 } 2794 2795 (void) mms_goodbye(sess, 0); 2796 2797 if (st != 0) { 2798 return (st); 2799 } 2800 } 2801 2802 arg.op = 2; 2803 2804 /* see if they want the cartridge physically unloaded */ 2805 st = nvlist_lookup_boolean_value(nvl, "unload", &phys); 2806 if (phys) { 2807 (void) strlcpy(arg.cmd, "physicalunmount", sizeof (arg.cmd)); 2808 } 2809 2810 d_arg.data_ptr = (char *)&arg; 2811 d_arg.data_size = sizeof (mmsmnt_arg_t); 2812 d_arg.desc_ptr = NULL; 2813 d_arg.desc_num = 0; 2814 d_arg.rbuf = (char *)&arg; 2815 d_arg.rsize = d_arg.data_size; 2816 2817 st = call_mmsmnt(&d_arg); 2818 2819 return (st); 2820 } 2821