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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 * Module: zones_states.c
31 * Description: Provide "zones" state interfaces for install consolidation code
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"
49 #include <sys/types.h>
50 #include <sys/param.h>
66 #include "instzones_lib.h"
67 #include "zones_strings.h"
74 * Library Function Prototypes
78 * Local Function Prototypes
82 * global internal (private) declarations
86 * *****************************************************************************
87 * global external (public) functions
88 * *****************************************************************************
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
99 * B_TRUE - non-global zone state changed successfully
100 * B_FALSE - failed to make the non-global zone run
104 _z_make_zone_running(zoneListElement_t
*a_zlem
)
108 char zonename
[ZONENAME_MAX
];
109 char *results
= (char *)NULL
;
113 /* entry assertions */
115 assert(a_zlem
!= NULL
);
117 /* act based on the zone's current kernel state */
119 switch (a_zlem
->_zlCurrKernelStatus
) {
120 case ZONE_STATE_RUNNING
:
121 case ZONE_STATE_MOUNTED
:
122 /* already running */
125 case ZONE_STATE_READY
:
126 /* This should never happen */
127 if (zonecfg_in_alt_root())
131 * We're going to upset the zone anyway, so might as well just
132 * halt it now and fall through to normal mounting.
135 _z_echoDebug(DBG_TO_ZONEHALT
, a_zlem
->_zlName
);
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");
143 ret
= z_ExecCmdArray(&status
, &results
, (char *)NULL
,
144 ZONEADM_CMD
, _z_get_argv(args
));
146 /* free generated argument list */
151 _z_program_error(ERR_ZONEHALT_EXEC
, ZONEADM_CMD
,
158 _z_program_error(ERR_ZONEBOOT_CMD_SIGNAL
,
159 ZONEADM_CMD
, a_zlem
->_zlName
);
161 _z_program_error(ERR_ZONEBOOT_CMD_ERROR
,
162 ZONEADM_CMD
, a_zlem
->_zlName
, status
,
163 results
== NULL
? "" : "\n",
164 results
== NULL
? "" : results
);
172 a_zlem
->_zlCurrKernelStatus
= ZONE_STATE_INSTALLED
;
175 case ZONE_STATE_INSTALLED
:
176 case ZONE_STATE_DOWN
:
177 /* return false if the zone cannot be booted */
179 if (a_zlem
->_zlStatus
& ZST_NOT_BOOTABLE
) {
183 _z_echoDebug(DBG_TO_ZONERUNNING
, a_zlem
->_zlName
);
185 /* these states can be booted - do so */
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());
195 (void) _z_add_arg(args
, "-z");
196 (void) _z_add_arg(args
, "%s", a_zlem
->_zlName
);
197 (void) _z_add_arg(args
, "mount");
199 ret
= z_ExecCmdArray(&status
, &results
, (char *)NULL
,
200 ZONEADM_CMD
, _z_get_argv(args
));
202 /* free generated argument list */
207 _z_program_error(ERR_ZONEBOOT_EXEC
, ZONEADM_CMD
,
215 _z_program_error(ERR_ZONEBOOT_CMD_SIGNAL
,
216 ZONEADM_CMD
, a_zlem
->_zlName
);
218 _z_program_error(ERR_ZONEBOOT_CMD_ERROR
,
219 ZONEADM_CMD
, a_zlem
->_zlName
, status
,
220 results
== NULL
? "" : "\n",
221 results
== NULL
? "" : results
);
225 /* remember this zone cannot be booted */
227 a_zlem
->_zlStatus
|= ZST_NOT_BOOTABLE
;
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
,
241 zonecfg_close_scratch(fp
);
244 zonecfg_close_scratch(fp
);
245 free(a_zlem
->_zlScratchName
);
246 a_zlem
->_zlScratchName
= _z_strdup(zonename
);
248 a_zlem
->_zlCurrKernelStatus
= ZONE_STATE_MOUNTED
;
251 case ZONE_STATE_CONFIGURED
:
252 case ZONE_STATE_INCOMPLETE
:
253 case ZONE_STATE_SHUTTING_DOWN
:
255 /* cannot transition (boot) these states */
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
269 * B_TRUE - non-global zone state changed successfully
270 * B_FALSE - failed to make the non-global zone ready
274 _z_make_zone_ready(zoneListElement_t
*a_zlem
)
277 char *results
= (char *)NULL
;
283 /* entry assertions */
285 assert(a_zlem
!= (zoneListElement_t
*)NULL
);
287 /* act based on the zone's current kernel state */
289 switch (a_zlem
->_zlCurrKernelStatus
) {
290 case ZONE_STATE_DOWN
:
291 case ZONE_STATE_READY
:
295 case ZONE_STATE_MOUNTED
:
296 _z_echoDebug(DBG_TO_ZONEUNMOUNT
, a_zlem
->_zlName
);
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
));
306 _z_program_error(ERR_ZONEUNMOUNT_EXEC
,
307 ZONEADM_CMD
, strerror(errno
));
314 _z_program_error(ERR_ZONEUNMOUNT_CMD_SIGNAL
,
315 ZONEADM_CMD
, a_zlem
->_zlName
);
317 _z_program_error(ERR_ZONEUNMOUNT_CMD_ERROR
,
318 ZONEADM_CMD
, a_zlem
->_zlName
, status
,
319 results
== NULL
? "" : "\n",
320 results
== NULL
? "" : results
);
322 if (results
!= NULL
) {
328 if (results
!= NULL
) {
332 a_zlem
->_zlCurrKernelStatus
= ZONE_STATE_INSTALLED
;
333 _z_echoDebug(DBG_TO_ZONEREADY
, a_zlem
->_zlName
);
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");
341 ret
= z_ExecCmdArray(&status
, &results
, NULL
,
342 ZONEADM_CMD
, _z_get_argv(args
));
344 _z_program_error(ERR_ZONEREADY_EXEC
, ZONEADM_CMD
,
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
) {
361 if (results
!= NULL
) {
364 /* success - zone is now in the ready state */
365 a_zlem
->_zlCurrKernelStatus
= ZONE_STATE_READY
;
368 case ZONE_STATE_RUNNING
:
370 _z_echoDebug(DBG_TO_ZONEREADY
, a_zlem
->_zlName
);
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");
378 ret
= z_ExecCmdArray(&status
, &results
, (char *)NULL
,
379 ZONEADM_CMD
, _z_get_argv(args
));
381 /* free generated argument list */
386 _z_program_error(ERR_ZONEREADY_EXEC
, ZONEADM_CMD
,
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
);
403 if (results
!= (char *)NULL
) {
404 (void) free(results
);
407 for (i
= 0; i
< MAX_RETRIES
; i
++) {
408 if (zone_get_state(a_zlem
->_zlName
, &st
) != Z_OK
) {
411 if ((st
== ZONE_STATE_DOWN
) ||
412 (st
== ZONE_STATE_INSTALLED
)||
413 (st
== ZONE_STATE_READY
)) {
416 (void) sleep(RETRY_DELAY_SECS
);
419 /* failure if maximum retries reached */
421 if (i
>= MAX_RETRIES
) {
422 _z_program_error(ERR_ZONEREADY_DIDNT_READY
,
424 a_zlem
->_zlCurrKernelStatus
= st
;
428 /* success - zone is now in the ready state */
430 a_zlem
->_zlCurrKernelStatus
= ZONE_STATE_READY
;
434 case ZONE_STATE_INSTALLED
:
435 case ZONE_STATE_CONFIGURED
:
436 case ZONE_STATE_INCOMPLETE
:
437 case ZONE_STATE_SHUTTING_DOWN
:
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
451 * B_TRUE - non-global zone state changed successfully
452 * B_FALSE - failed to make the non-global zone down
456 _z_make_zone_down(zoneListElement_t
*a_zlem
)
459 char *results
= (char *)NULL
;
463 /* entry assertions */
465 assert(a_zlem
!= NULL
);
467 /* act based on the zone's current kernel state */
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 */
476 case ZONE_STATE_MOUNTED
:
478 _z_echoDebug(DBG_TO_ZONEHALT
, a_zlem
->_zlName
);
480 /* these states can be halted - do so */
482 args
= _z_new_args(10); /* generate new arg list */
483 (void) _z_add_arg(args
, ZONEADM_CMD
);
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());
491 (void) _z_add_arg(args
, "-z");
492 (void) _z_add_arg(args
, "%s", a_zlem
->_zlName
);
493 (void) _z_add_arg(args
, "unmount");
495 ret
= z_ExecCmdArray(&status
, &results
, (char *)NULL
,
496 ZONEADM_CMD
, _z_get_argv(args
));
498 /* free generated argument list */
503 _z_program_error(ERR_ZONEHALT_EXEC
, ZONEADM_CMD
,
510 _z_program_error(ERR_ZONEBOOT_CMD_SIGNAL
,
511 ZONEADM_CMD
, a_zlem
->_zlName
);
513 _z_program_error(ERR_ZONEBOOT_CMD_ERROR
,
514 ZONEADM_CMD
, a_zlem
->_zlName
, status
,
515 results
== NULL
? "" : "\n",
516 results
== NULL
? "" : results
);
524 a_zlem
->_zlCurrKernelStatus
= ZONE_STATE_INSTALLED
;
526 * Leave the scratch name in place because the upper level
527 * software may have used it to construct file names and the
532 case ZONE_STATE_INSTALLED
:
533 case ZONE_STATE_CONFIGURED
:
534 case ZONE_STATE_INCOMPLETE
:
535 case ZONE_STATE_SHUTTING_DOWN
:
542 * Function: UmountAllZones
543 * Description: Unmount all mounted zones under a specified directory.
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
552 UmountAllZones(char *mntpnt
) {
558 if (z_zones_are_implemented()) {
560 z_set_zone_root(mntpnt
);
562 zlst
= z_get_nonglobal_zone_list();
563 if (zlst
== (zoneList_t
)NULL
) {
567 for (k
= 0; z_zlist_get_zonename(zlst
, k
) != (char *)NULL
;
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
)) {
580 z_free_zone_list(zlst
);