8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libinstzones / common / zones_states.c
blob914af2075c983ec8b166aed3170242d677c6e506
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 * Module: zones_states.c
30 * Group: libinstzones
31 * Description: Provide "zones" state interfaces for install consolidation code
33 * Public Methods:
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"
41 * System includes
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>
63 * local includes
66 #include "instzones_lib.h"
67 #include "zones_strings.h"
70 * Private structures
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
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
103 boolean_t
104 _z_make_zone_running(zoneListElement_t *a_zlem)
106 FILE *fp;
107 argArray_t *args;
108 char zonename[ZONENAME_MAX];
109 char *results = (char *)NULL;
110 int ret;
111 int status = 0;
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 */
123 return (B_TRUE);
125 case ZONE_STATE_READY:
126 /* This should never happen */
127 if (zonecfg_in_alt_root())
128 return (B_FALSE);
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 */
148 _z_free_args(args);
150 if (ret != 0) {
151 _z_program_error(ERR_ZONEHALT_EXEC, ZONEADM_CMD,
152 strerror(errno));
153 free(results);
154 return (B_FALSE);
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);
166 free(results);
167 return (B_FALSE);
170 free(results);
172 a_zlem->_zlCurrKernelStatus = ZONE_STATE_INSTALLED;
173 /* FALLTHROUGH */
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) {
180 return (B_FALSE);
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 */
204 _z_free_args(args);
206 if (ret != 0) {
207 _z_program_error(ERR_ZONEBOOT_EXEC, ZONEADM_CMD,
208 strerror(errno));
209 free(results);
210 return (B_FALSE);
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);
223 free(results);
225 /* remember this zone cannot be booted */
227 a_zlem->_zlStatus |= ZST_NOT_BOOTABLE;
229 return (B_FALSE);
231 free(results);
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);
244 zonecfg_close_scratch(fp);
245 free(a_zlem->_zlScratchName);
246 a_zlem->_zlScratchName = _z_strdup(zonename);
248 a_zlem->_zlCurrKernelStatus = ZONE_STATE_MOUNTED;
249 return (B_TRUE);
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);
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
273 boolean_t
274 _z_make_zone_ready(zoneListElement_t *a_zlem)
276 argArray_t *args;
277 char *results = (char *)NULL;
278 int status = 0;
279 int i;
280 int ret;
281 zone_state_t st;
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:
292 /* already down */
293 return (B_TRUE);
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));
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);
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);
322 if (results != NULL) {
323 free(results);
325 _z_free_args(args);
326 return (B_FALSE);
328 if (results != NULL) {
329 free(results);
331 _z_free_args(args);
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));
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);
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);
358 _z_free_args(args);
359 return (B_FALSE);
361 if (results != NULL) {
362 free(results);
364 /* success - zone is now in the ready state */
365 a_zlem->_zlCurrKernelStatus = ZONE_STATE_READY;
366 return (B_TRUE);
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 */
383 _z_free_args(args);
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);
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);
400 return (B_FALSE);
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) {
409 break;
411 if ((st == ZONE_STATE_DOWN) ||
412 (st == ZONE_STATE_INSTALLED)||
413 (st == ZONE_STATE_READY)) {
414 break;
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,
423 a_zlem->_zlName);
424 a_zlem->_zlCurrKernelStatus = st;
425 return (B_FALSE);
428 /* success - zone is now in the ready state */
430 a_zlem->_zlCurrKernelStatus = ZONE_STATE_READY;
432 return (B_TRUE);
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);
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
455 boolean_t
456 _z_make_zone_down(zoneListElement_t *a_zlem)
458 argArray_t *args;
459 char *results = (char *)NULL;
460 int status = 0;
461 int ret;
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 */
474 return (B_TRUE);
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 */
500 _z_free_args(args);
502 if (ret != 0) {
503 _z_program_error(ERR_ZONEHALT_EXEC, ZONEADM_CMD,
504 strerror(errno));
505 free(results);
506 return (B_FALSE);
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);
518 free(results);
519 return (B_FALSE);
522 free(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
528 * like.
530 return (B_TRUE);
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);
542 * Function: UmountAllZones
543 * Description: Unmount all mounted zones under a specified directory.
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
552 UmountAllZones(char *mntpnt) {
554 zoneList_t zlst;
555 int k;
556 int ret = 0;
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) {
564 return (0);
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;
579 /* Free zlst */
580 z_free_zone_list(zlst);
583 return (ret);