Print this page
2594 implement graceful shutdown for local zones in zoneadm

*** 19,28 **** --- 19,29 ---- * CDDL HEADER END */ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ /* * zoneadm is a command interpreter for zone administration. It is all in * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
*** 128,137 **** --- 129,139 ---- #define SHELP_HELP "help" #define SHELP_BOOT "boot [-- boot_arguments]" #define SHELP_HALT "halt" #define SHELP_READY "ready" + #define SHELP_SHUTDOWN "shutdown [-r [-- boot_arguments]]" #define SHELP_REBOOT "reboot [-- boot_arguments]" #define SHELP_LIST "list [-cipv]" #define SHELP_VERIFY "verify" #define SHELP_INSTALL "install [brand-specific args]" #define SHELP_UNINSTALL "uninstall [-F] [brand-specific args]"
*** 150,159 **** --- 152,162 ---- static int help_func(int argc, char *argv[]); static int ready_func(int argc, char *argv[]); static int boot_func(int argc, char *argv[]); + static int shutdown_func(int argc, char *argv[]); static int halt_func(int argc, char *argv[]); static int reboot_func(int argc, char *argv[]); static int list_func(int argc, char *argv[]); static int verify_func(int argc, char *argv[]); static int install_func(int argc, char *argv[]);
*** 177,186 **** --- 180,190 ---- static struct cmd cmdtab[] = { { CMD_HELP, "help", SHELP_HELP, help_func }, { CMD_BOOT, "boot", SHELP_BOOT, boot_func }, { CMD_HALT, "halt", SHELP_HALT, halt_func }, { CMD_READY, "ready", SHELP_READY, ready_func }, + { CMD_SHUTDOWN, "shutdown", SHELP_SHUTDOWN, shutdown_func }, { CMD_REBOOT, "reboot", SHELP_REBOOT, reboot_func }, { CMD_LIST, "list", SHELP_LIST, list_func }, { CMD_VERIFY, "verify", SHELP_VERIFY, verify_func }, { CMD_INSTALL, "install", SHELP_INSTALL, install_func }, { CMD_UNINSTALL, "uninstall", SHELP_UNINSTALL,
*** 230,239 **** --- 234,247 ---- return (gettext("Halts specified zone, bypassing shutdown " "scripts and removing runtime\n\tresources of the zone.")); case CMD_READY: return (gettext("Prepares a zone for running applications but " "does not start any user\n\tprocesses in the zone.")); + case CMD_SHUTDOWN: + return (gettext("Gracefully shutdown the zone or reboot if " + "the '-r' option is specified.\n\t" + "See zoneadm(1m) for valid boot arguments.")); case CMD_REBOOT: return (gettext("Restarts the zone (equivalent to a halt / " "boot sequence).\n\tFails if the zone is not active. " "See zoneadm(1m) for valid boot\n\targuments.")); case CMD_LIST:
*** 1532,1541 **** --- 1540,1550 ---- (void) strlcpy(authname, ZONE_CLONEFROM_AUTH, MAXAUTHS); break; case CMD_BOOT: case CMD_HALT: case CMD_READY: + case CMD_SHUTDOWN: case CMD_REBOOT: case CMD_SYSBOOT: case CMD_VERIFY: case CMD_INSTALL: case CMD_UNINSTALL:
*** 1594,1603 **** --- 1603,1616 ---- switch (cmd_num) { case CMD_HALT: zerror(gettext("use %s to %s this zone."), "halt(1M)", cmd_to_str(cmd_num)); break; + case CMD_SHUTDOWN: + zerror(gettext("use %s to %s this zone."), + "shutdown(1M)", cmd_to_str(cmd_num)); + break; case CMD_REBOOT: zerror(gettext("use %s to %s this zone."), "reboot(1M)", cmd_to_str(cmd_num)); break; default:
*** 1823,1832 **** --- 1836,1914 ---- zarg.cmd = Z_HALT; return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) == 0) ? Z_OK : Z_ERR); } + static int + shutdown_func(int argc, char *argv[]) + { + zone_cmd_arg_t zarg; + int arg; + boolean_t reboot = B_FALSE; + + zarg.cmd = Z_SHUTDOWN; + + if (zonecfg_in_alt_root()) { + zerror(gettext("cannot shut down zone in alternate root")); + return (Z_ERR); + } + + optind = 0; + while ((arg = getopt(argc, argv, "?r")) != EOF) { + switch (arg) { + case '?': + sub_usage(SHELP_SHUTDOWN, CMD_SHUTDOWN); + return (optopt == '?' ? Z_OK : Z_USAGE); + case 'r': + reboot = B_TRUE; + break; + default: + sub_usage(SHELP_SHUTDOWN, CMD_SHUTDOWN); + return (Z_USAGE); + } + } + + zarg.bootbuf[0] = '\0'; + for (; optind < argc; optind++) { + if (strlcat(zarg.bootbuf, argv[optind], + sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) { + zerror(gettext("Boot argument list too long")); + return (Z_ERR); + } + if (optind < argc - 1) + if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >= + sizeof (zarg.bootbuf)) { + zerror(gettext("Boot argument list too long")); + return (Z_ERR); + } + } + + /* + * zoneadmd should be the one to decide whether or not to proceed, + * so even though it seems that the third parameter below should + * perhaps be B_TRUE, it really shouldn't be. + */ + if (sanity_check(target_zone, CMD_SHUTDOWN, B_TRUE, B_FALSE, B_FALSE) + != Z_OK) + return (Z_ERR); + + if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != Z_OK) + return (Z_ERR); + + if (reboot) { + if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE, + B_FALSE) != Z_OK) + return (Z_ERR); + + zarg.cmd = Z_BOOT; + if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, + B_TRUE) != Z_OK) + return (Z_ERR); + } + return (Z_OK); + } + static int reboot_func(int argc, char *argv[]) { zone_cmd_arg_t zarg; int arg;