Skip to content

Commit

Permalink
2594 implement graceful shutdown for local zones in zoneadm
Browse files Browse the repository at this point in the history
Reviewed by: Saso Kiselkov <skiselkov.ml@gmail.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Dan McDonald <danmcd@omniti.com>
  • Loading branch information
alhazred authored and Dan McDonald committed Feb 24, 2014
1 parent 97f7c47 commit 3c7284b
Show file tree
Hide file tree
Showing 16 changed files with 328 additions and 43 deletions.
3 changes: 2 additions & 1 deletion usr/src/cmd/zoneadm/svc-zones
Expand Up @@ -21,6 +21,7 @@
#
#
# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2014 Nexenta Systems, Inc. All rights reserved.

. /lib/svc/share/smf_include.sh

Expand Down Expand Up @@ -109,7 +110,7 @@ case "$1" in

for zone in $zonelist; do
echo " $zone\c"
zlogin -S $zone /sbin/init 0 < /dev/null >&0 2>&0 &
zoneadm -z $zone shutdown &
SHUTDOWN=1
done

Expand Down
82 changes: 82 additions & 0 deletions usr/src/cmd/zoneadm/zoneadm.c
Expand Up @@ -21,6 +21,7 @@

/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/

/*
Expand Down Expand Up @@ -130,6 +131,7 @@ struct cmd {
#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"
Expand All @@ -152,6 +154,7 @@ static int cleanup_zonepath(char *, boolean_t);
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[]);
Expand Down Expand Up @@ -179,6 +182,7 @@ static struct cmd cmdtab[] = {
{ 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 },
Expand Down Expand Up @@ -232,6 +236,10 @@ long_help(int cmd_num)
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. "
Expand Down Expand Up @@ -1534,6 +1542,7 @@ auth_check(char *user, char *zone, int cmd_num)
case CMD_BOOT:
case CMD_HALT:
case CMD_READY:
case CMD_SHUTDOWN:
case CMD_REBOOT:
case CMD_SYSBOOT:
case CMD_VERIFY:
Expand Down Expand Up @@ -1596,6 +1605,10 @@ sanity_check(char *zone, int cmd_num, boolean_t running,
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));
Expand Down Expand Up @@ -1825,6 +1838,75 @@ halt_func(int argc, char *argv[])
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[])
{
Expand Down
30 changes: 16 additions & 14 deletions usr/src/cmd/zoneadm/zoneadm.h
Expand Up @@ -22,6 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/

#ifndef _ZONEADM_H
Expand All @@ -33,20 +34,21 @@
#define CMD_BOOT 1
#define CMD_HALT 2
#define CMD_READY 3
#define CMD_REBOOT 4
#define CMD_LIST 5
#define CMD_VERIFY 6
#define CMD_INSTALL 7
#define CMD_UNINSTALL 8
#define CMD_MOUNT 9
#define CMD_UNMOUNT 10
#define CMD_CLONE 11
#define CMD_MOVE 12
#define CMD_DETACH 13
#define CMD_ATTACH 14
#define CMD_MARK 15
#define CMD_APPLY 16
#define CMD_SYSBOOT 17
#define CMD_SHUTDOWN 4
#define CMD_REBOOT 5
#define CMD_LIST 6
#define CMD_VERIFY 7
#define CMD_INSTALL 8
#define CMD_UNINSTALL 9
#define CMD_MOUNT 10
#define CMD_UNMOUNT 11
#define CMD_CLONE 12
#define CMD_MOVE 13
#define CMD_DETACH 14
#define CMD_ATTACH 15
#define CMD_MARK 16
#define CMD_APPLY 17
#define CMD_SYSBOOT 18

#define CMD_MIN CMD_HELP
#define CMD_MAX CMD_SYSBOOT
Expand Down
11 changes: 5 additions & 6 deletions usr/src/cmd/zoneadm/zones.xml
Expand Up @@ -23,12 +23,12 @@
CDDL HEADER END
ident "%Z%%M% %I% %E% SMI"
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
operating system upgrade. Make customizations in a different
file.
Copyright 2014 Nexenta Systems, Inc. All rights reserved.
-->

<service_bundle type='manifest' name='SUNWzoner:zones'>
Expand Down Expand Up @@ -64,10 +64,9 @@
<!--
The stop method reads the timeout_seconds property and
spends 3/4 of the allotted time waiting for zones to
cleanly shut down (by running 'init 0' in each one). If
some zones don't shutdown after the 3/4 time has elapsed,
the method spends the remaining 1/4 trying to more forcibly
halt the zones
cleanly shut down. If some zones don't shutdown after
the 3/4 time has elapsed, the method spends the remaining
1/4 trying to more forcibly halt the zones
-->
<exec_method
type='method'
Expand Down
3 changes: 2 additions & 1 deletion usr/src/cmd/zoneadmd/Makefile
Expand Up @@ -23,6 +23,7 @@

#
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
#

PROG= zoneadmd
Expand All @@ -43,7 +44,7 @@ CERRWARN += -_gcc=-Wno-uninitialized

LDLIBS += -lsocket -lzonecfg -lnsl -ldevinfo -ldevice -lnvpair \
-lgen -lbsm -lcontract -lzfs -luuid -lbrand -ldladm -ltsnet -ltsol \
-linetutil
-linetutil -lscf
XGETFLAGS += -a -x zoneadmd.xcl

.KEEP_STATE:
Expand Down

0 comments on commit 3c7284b

Please sign in to comment.