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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 /* 29 * Module: zones_states.c 30 * Group: libinstzones 31 * Description: Provide "zones" state interfaces for install consolidation code 32 * 33 * Public Methods: 34 * 35 * z_make_zone_running - change state of non-global zone to "running" 36 * _z_make_zone_ready - change state of non-global zone to "ready" 37 * _z_make_zone_down - change state of non-global zone to "down" 38 */ 39 40 /* 41 * System includes 42 */ 43 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <unistd.h> 47 #include <fcntl.h> 48 #include <ctype.h> 49 #include <sys/types.h> 50 #include <sys/param.h> 51 #include <string.h> 52 #include <strings.h> 53 #include <sys/stat.h> 54 #include <stdarg.h> 55 #include <limits.h> 56 #include <errno.h> 57 #include <stropts.h> 58 #include <libintl.h> 59 #include <locale.h> 60 #include <assert.h> 61 62 /* 63 * local includes 64 */ 65 66 #include "instzones_lib.h" 67 #include "zones_strings.h" 68 69 /* 70 * Private structures 71 */ 72 73 /* 74 * Library Function Prototypes 75 */ 76 77 /* 78 * Local Function Prototypes 79 */ 80 81 /* 82 * global internal (private) declarations 83 */ 84 85 /* 86 * ***************************************************************************** 87 * global external (public) functions 88 * ***************************************************************************** 89 */ 90 91 /* 92 * Name: _z_make_zone_running 93 * Description: Given a zone element entry for the non-global zone to affect, 94 * change the state of that non-global zone to "running" 95 * Arguments: a_zlem - [RO, *RW] - (zoneListElement_t) 96 * Zone list element describing the non-global zone to 97 * make running 98 * Returns: boolean_t 99 * B_TRUE - non-global zone state changed successfully 100 * B_FALSE - failed to make the non-global zone run 101 */ 102 103 boolean_t 104 _z_make_zone_running(zoneListElement_t *a_zlem) 105 { 106 FILE *fp; 107 argArray_t *args; 108 char zonename[ZONENAME_MAX]; 109 char *results = (char *)NULL; 110 int ret; 111 int status = 0; 112 113 /* entry assertions */ 114 115 assert(a_zlem != NULL); 116 117 /* act based on the zone's current kernel state */ 118 119 switch (a_zlem->_zlCurrKernelStatus) { 120 case ZONE_STATE_RUNNING: 121 case ZONE_STATE_MOUNTED: 122 /* already running */ 123 return (B_TRUE); 124 125 case ZONE_STATE_READY: 126 /* This should never happen */ 127 if (zonecfg_in_alt_root()) 128 return (B_FALSE); 129 130 /* 131 * We're going to upset the zone anyway, so might as well just 132 * halt it now and fall through to normal mounting. 133 */ 134 135 _z_echoDebug(DBG_TO_ZONEHALT, a_zlem->_zlName); 136 137 args = _z_new_args(5); /* generate new arg list */ 138 (void) _z_add_arg(args, ZONEADM_CMD); 139 (void) _z_add_arg(args, "-z"); 140 (void) _z_add_arg(args, a_zlem->_zlName); 141 (void) _z_add_arg(args, "halt"); 142 143 ret = z_ExecCmdArray(&status, &results, (char *)NULL, 144 ZONEADM_CMD, _z_get_argv(args)); 145 146 /* free generated argument list */ 147 148 _z_free_args(args); 149 150 if (ret != 0) { 151 _z_program_error(ERR_ZONEHALT_EXEC, ZONEADM_CMD, 152 strerror(errno)); 153 free(results); 154 return (B_FALSE); 155 } 156 if (status != 0) { 157 if (status == -1) { 158 _z_program_error(ERR_ZONEBOOT_CMD_SIGNAL, 159 ZONEADM_CMD, a_zlem->_zlName); 160 } else { 161 _z_program_error(ERR_ZONEBOOT_CMD_ERROR, 162 ZONEADM_CMD, a_zlem->_zlName, status, 163 results == NULL ? "" : "\n", 164 results == NULL ? "" : results); 165 } 166 free(results); 167 return (B_FALSE); 168 } 169 170 free(results); 171 172 a_zlem->_zlCurrKernelStatus = ZONE_STATE_INSTALLED; 173 /* FALLTHROUGH */ 174 175 case ZONE_STATE_INSTALLED: 176 case ZONE_STATE_DOWN: 177 /* return false if the zone cannot be booted */ 178 179 if (a_zlem->_zlStatus & ZST_NOT_BOOTABLE) { 180 return (B_FALSE); 181 } 182 183 _z_echoDebug(DBG_TO_ZONERUNNING, a_zlem->_zlName); 184 185 /* these states can be booted - do so */ 186 187 args = _z_new_args(10); /* generate new arg list */ 188 (void) _z_add_arg(args, ZONEADM_CMD); 189 if (zonecfg_in_alt_root()) { 190 (void) _z_add_arg(args, "-R"); 191 (void) _z_add_arg(args, "%s", 192 (char *)zonecfg_get_root()); 193 } 194 195 (void) _z_add_arg(args, "-z"); 196 (void) _z_add_arg(args, "%s", a_zlem->_zlName); 197 (void) _z_add_arg(args, "mount"); 198 199 ret = z_ExecCmdArray(&status, &results, (char *)NULL, 200 ZONEADM_CMD, _z_get_argv(args)); 201 202 /* free generated argument list */ 203 204 _z_free_args(args); 205 206 if (ret != 0) { 207 _z_program_error(ERR_ZONEBOOT_EXEC, ZONEADM_CMD, 208 strerror(errno)); 209 free(results); 210 return (B_FALSE); 211 } 212 213 if (status != 0) { 214 if (status == -1) { 215 _z_program_error(ERR_ZONEBOOT_CMD_SIGNAL, 216 ZONEADM_CMD, a_zlem->_zlName); 217 } else { 218 _z_program_error(ERR_ZONEBOOT_CMD_ERROR, 219 ZONEADM_CMD, a_zlem->_zlName, status, 220 results == NULL ? "" : "\n", 221 results == NULL ? "" : results); 222 } 223 free(results); 224 225 /* remember this zone cannot be booted */ 226 227 a_zlem->_zlStatus |= ZST_NOT_BOOTABLE; 228 229 return (B_FALSE); 230 } 231 free(results); 232 233 if (zonecfg_in_alt_root()) { 234 if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL || 235 zonecfg_find_scratch(fp, a_zlem->_zlName, 236 zonecfg_get_root(), zonename, 237 sizeof (zonename)) == -1) { 238 _z_program_error(ERR_ZONEBOOT_DIDNT_BOOT, 239 a_zlem->_zlName); 240 if (fp != NULL) 241 zonecfg_close_scratch(fp); 242 return (B_FALSE); 243 } 244 zonecfg_close_scratch(fp); 245 free(a_zlem->_zlScratchName); 246 a_zlem->_zlScratchName = _z_strdup(zonename); 247 } 248 a_zlem->_zlCurrKernelStatus = ZONE_STATE_MOUNTED; 249 return (B_TRUE); 250 251 case ZONE_STATE_CONFIGURED: 252 case ZONE_STATE_INCOMPLETE: 253 case ZONE_STATE_SHUTTING_DOWN: 254 default: 255 /* cannot transition (boot) these states */ 256 return (B_FALSE); 257 } 258 } 259 260 /* 261 * Name: _z_make_zone_ready 262 * Description: Given a zone element entry for the non-global zone to affect, 263 * restore the ready state of the zone when the zone is currently 264 * in the running state. 265 * Arguments: a_zlem - [RO, *RW] - (zoneListElement_t) 266 * Zone list element describing the non-global zone to 267 * make ready 268 * Returns: boolean_t 269 * B_TRUE - non-global zone state changed successfully 270 * B_FALSE - failed to make the non-global zone ready 271 */ 272 273 boolean_t 274 _z_make_zone_ready(zoneListElement_t *a_zlem) 275 { 276 argArray_t *args; 277 char *results = (char *)NULL; 278 int status = 0; 279 int i; 280 int ret; 281 zone_state_t st; 282 283 /* entry assertions */ 284 285 assert(a_zlem != (zoneListElement_t *)NULL); 286 287 /* act based on the zone's current kernel state */ 288 289 switch (a_zlem->_zlCurrKernelStatus) { 290 case ZONE_STATE_DOWN: 291 case ZONE_STATE_READY: 292 /* already down */ 293 return (B_TRUE); 294 295 case ZONE_STATE_MOUNTED: 296 _z_echoDebug(DBG_TO_ZONEUNMOUNT, a_zlem->_zlName); 297 298 args = _z_new_args(10); /* generate new arg list */ 299 (void) _z_add_arg(args, ZONEADM_CMD); 300 (void) _z_add_arg(args, "-z"); 301 (void) _z_add_arg(args, "%s", a_zlem->_zlName); 302 (void) _z_add_arg(args, "unmount"); 303 ret = z_ExecCmdArray(&status, &results, NULL, 304 ZONEADM_CMD, _z_get_argv(args)); 305 if (ret != 0) { 306 _z_program_error(ERR_ZONEUNMOUNT_EXEC, 307 ZONEADM_CMD, strerror(errno)); 308 free(results); 309 _z_free_args(args); 310 return (B_FALSE); 311 } 312 if (status != 0) { 313 if (status == -1) { 314 _z_program_error(ERR_ZONEUNMOUNT_CMD_SIGNAL, 315 ZONEADM_CMD, a_zlem->_zlName); 316 } else { 317 _z_program_error(ERR_ZONEUNMOUNT_CMD_ERROR, 318 ZONEADM_CMD, a_zlem->_zlName, status, 319 results == NULL ? "" : "\n", 320 results == NULL ? "" : results); 321 } 322 if (results != NULL) { 323 free(results); 324 } 325 _z_free_args(args); 326 return (B_FALSE); 327 } 328 if (results != NULL) { 329 free(results); 330 } 331 _z_free_args(args); 332 a_zlem->_zlCurrKernelStatus = ZONE_STATE_INSTALLED; 333 _z_echoDebug(DBG_TO_ZONEREADY, a_zlem->_zlName); 334 335 args = _z_new_args(10); /* generate new arg list */ 336 (void) _z_add_arg(args, ZONEADM_CMD); 337 (void) _z_add_arg(args, "-z"); 338 (void) _z_add_arg(args, "%s", a_zlem->_zlName); 339 (void) _z_add_arg(args, "ready"); 340 341 ret = z_ExecCmdArray(&status, &results, NULL, 342 ZONEADM_CMD, _z_get_argv(args)); 343 if (ret != 0) { 344 _z_program_error(ERR_ZONEREADY_EXEC, ZONEADM_CMD, 345 strerror(errno)); 346 free(results); 347 _z_free_args(args); 348 return (B_FALSE); 349 } 350 if (status != 0) { 351 _z_program_error(ERR_ZONEREADY_CMDFAIL, ZONEADM_CMD, 352 a_zlem->_zlName, strerror(errno), 353 results == NULL ? "" : "\n", 354 results == NULL ? "" : results); 355 if (results != NULL) { 356 free(results); 357 } 358 _z_free_args(args); 359 return (B_FALSE); 360 } 361 if (results != NULL) { 362 free(results); 363 } 364 /* success - zone is now in the ready state */ 365 a_zlem->_zlCurrKernelStatus = ZONE_STATE_READY; 366 return (B_TRUE); 367 368 case ZONE_STATE_RUNNING: 369 370 _z_echoDebug(DBG_TO_ZONEREADY, a_zlem->_zlName); 371 372 args = _z_new_args(10); /* generate new arg list */ 373 (void) _z_add_arg(args, ZONEADM_CMD); 374 (void) _z_add_arg(args, "-z"); 375 (void) _z_add_arg(args, "%s", a_zlem->_zlName); 376 (void) _z_add_arg(args, "ready"); 377 378 ret = z_ExecCmdArray(&status, &results, (char *)NULL, 379 ZONEADM_CMD, _z_get_argv(args)); 380 381 /* free generated argument list */ 382 383 _z_free_args(args); 384 385 if (ret != 0) { 386 _z_program_error(ERR_ZONEREADY_EXEC, ZONEADM_CMD, 387 strerror(errno)); 388 free(results); 389 _z_free_args(args); 390 return (B_FALSE); 391 } 392 if (status != 0) { 393 _z_program_error(ERR_ZONEREADY_CMDFAIL, ZONEADM_CMD, 394 a_zlem->_zlName, strerror(errno), 395 results == (char *)NULL ? "" : "\n", 396 results == (char *)NULL ? "" : results); 397 if (results != (char *)NULL) { 398 (void) free(results); 399 } 400 return (B_FALSE); 401 } 402 403 if (results != (char *)NULL) { 404 (void) free(results); 405 } 406 407 for (i = 0; i < MAX_RETRIES; i++) { 408 if (zone_get_state(a_zlem->_zlName, &st) != Z_OK) { 409 break; 410 } 411 if ((st == ZONE_STATE_DOWN) || 412 (st == ZONE_STATE_INSTALLED)|| 413 (st == ZONE_STATE_READY)) { 414 break; 415 } 416 (void) sleep(RETRY_DELAY_SECS); 417 } 418 419 /* failure if maximum retries reached */ 420 421 if (i >= MAX_RETRIES) { 422 _z_program_error(ERR_ZONEREADY_DIDNT_READY, 423 a_zlem->_zlName); 424 a_zlem->_zlCurrKernelStatus = st; 425 return (B_FALSE); 426 } 427 428 /* success - zone is now in the ready state */ 429 430 a_zlem->_zlCurrKernelStatus = ZONE_STATE_READY; 431 432 return (B_TRUE); 433 434 case ZONE_STATE_INSTALLED: 435 case ZONE_STATE_CONFIGURED: 436 case ZONE_STATE_INCOMPLETE: 437 case ZONE_STATE_SHUTTING_DOWN: 438 default: 439 return (B_FALSE); 440 } 441 } 442 443 /* 444 * Name: _z_make_zone_down 445 * Description: Given a zone element entry for the non-global zone to affect, 446 * change the state of that non-global zone to "down" 447 * Arguments: a_zlem - [RO, *RW] - (zoneListElement_t) 448 * Zone list element describing the non-global zone to 449 * make down 450 * Returns: boolean_t 451 * B_TRUE - non-global zone state changed successfully 452 * B_FALSE - failed to make the non-global zone down 453 */ 454 455 boolean_t 456 _z_make_zone_down(zoneListElement_t *a_zlem) 457 { 458 argArray_t *args; 459 char *results = (char *)NULL; 460 int status = 0; 461 int ret; 462 463 /* entry assertions */ 464 465 assert(a_zlem != NULL); 466 467 /* act based on the zone's current kernel state */ 468 469 switch (a_zlem->_zlCurrKernelStatus) { 470 case ZONE_STATE_DOWN: 471 case ZONE_STATE_READY: 472 case ZONE_STATE_RUNNING: 473 /* shouldn't be touched */ 474 return (B_TRUE); 475 476 case ZONE_STATE_MOUNTED: 477 478 _z_echoDebug(DBG_TO_ZONEHALT, a_zlem->_zlName); 479 480 /* these states can be halted - do so */ 481 482 args = _z_new_args(10); /* generate new arg list */ 483 (void) _z_add_arg(args, ZONEADM_CMD); 484 485 if (zonecfg_in_alt_root()) { 486 (void) _z_add_arg(args, "-R"); 487 (void) _z_add_arg(args, "%s", 488 (char *)zonecfg_get_root()); 489 } 490 491 (void) _z_add_arg(args, "-z"); 492 (void) _z_add_arg(args, "%s", a_zlem->_zlName); 493 (void) _z_add_arg(args, "unmount"); 494 495 ret = z_ExecCmdArray(&status, &results, (char *)NULL, 496 ZONEADM_CMD, _z_get_argv(args)); 497 498 /* free generated argument list */ 499 500 _z_free_args(args); 501 502 if (ret != 0) { 503 _z_program_error(ERR_ZONEHALT_EXEC, ZONEADM_CMD, 504 strerror(errno)); 505 free(results); 506 return (B_FALSE); 507 } 508 if (status != 0) { 509 if (status == -1) { 510 _z_program_error(ERR_ZONEBOOT_CMD_SIGNAL, 511 ZONEADM_CMD, a_zlem->_zlName); 512 } else { 513 _z_program_error(ERR_ZONEBOOT_CMD_ERROR, 514 ZONEADM_CMD, a_zlem->_zlName, status, 515 results == NULL ? "" : "\n", 516 results == NULL ? "" : results); 517 } 518 free(results); 519 return (B_FALSE); 520 } 521 522 free(results); 523 524 a_zlem->_zlCurrKernelStatus = ZONE_STATE_INSTALLED; 525 /* 526 * Leave the scratch name in place because the upper level 527 * software may have used it to construct file names and the 528 * like. 529 */ 530 return (B_TRUE); 531 532 case ZONE_STATE_INSTALLED: 533 case ZONE_STATE_CONFIGURED: 534 case ZONE_STATE_INCOMPLETE: 535 case ZONE_STATE_SHUTTING_DOWN: 536 default: 537 return (B_FALSE); 538 } 539 } 540 541 /* 542 * Function: UmountAllZones 543 * Description: Unmount all mounted zones under a specified directory. 544 * 545 * Scope: public 546 * Parameters: mntpnt [RO, *RO] 547 * Non-NULL pointer to name of directory to be unmounted. 548 * Return: 0 - successfull 549 * -1 - unmount failed; see errno for reason 550 */ 551 int 552 UmountAllZones(char *mntpnt) { 553 554 zoneList_t zlst; 555 int k; 556 int ret = 0; 557 558 if (z_zones_are_implemented()) { 559 560 z_set_zone_root(mntpnt); 561 562 zlst = z_get_nonglobal_zone_list(); 563 if (zlst == (zoneList_t)NULL) { 564 return (0); 565 } 566 567 for (k = 0; z_zlist_get_zonename(zlst, k) != (char *)NULL; 568 k++) { 569 if (z_zlist_get_current_state(zlst, k) > 570 ZONE_STATE_INSTALLED) { 571 if (!z_zlist_change_zone_state(zlst, k, 572 ZONE_STATE_INSTALLED)) { 573 ret = -1; 574 break; 575 } 576 } 577 } 578 579 /* Free zlst */ 580 z_free_zone_list(zlst); 581 } 582 583 return (ret); 584 585 } 586